From 9b45c1286eb8e01173b8d130072064bd2ea9e76f Mon Sep 17 00:00:00 2001 From: Ezerous Date: Mon, 23 Jan 2017 17:23:35 +0200 Subject: [PATCH 01/18] Small doc changes --- CONTRIBUTING.md | 1 - README.md | 11 ++++++++--- 2 files changed, 8 insertions(+), 4 deletions(-) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index e28d7593..44be1c74 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -45,4 +45,3 @@ follow the workflow below to make a merge request: [trello-board]: https://trello.com/invite/b/4MVlkrkg/44a931707bd0b84a5e0bdfc42b9ae4f1/mthmmy [discord-server]: https://discord.gg/CVt3yrn -[gitlab-contributing-guide]: https://gitlab.com/gitlab-org/gitlab-ce/blob/master/CONTRIBUTING.md diff --git a/README.md b/README.md index 69c60e28..89f8a134 100644 --- a/README.md +++ b/README.md @@ -2,9 +2,11 @@ [![build status](https://gitlab.com/ThmmyNoLife/mTHMMY/badges/develop/build.svg)](https://gitlab.com/ThmmyNoLife/mTHMMY/commits/develop) [![API](https://img.shields.io/badge/API-19%2B-blue.svg?style=flat)](https://android-arsenal.com/api?level=19) -[![Discord Channel](https://img.shields.io/badge/discord-public@mTHMMY-738bd7.svg?style=flat)](https://discord.gg/CVt3yrn) +[![Discord Channel](https://img.shields.io/badge/discord-public@mTHMMY-738bd7.svg?style=flat)][discord-server] +[![Trello Board](https://img.shields.io/badge/trello-mTHMMY-red.svg?style=flat)][trello-board] -mTHMMY is a mobile app for thmmy.gr + +mTHMMY is a mobile app for the [thmmy.gr](https://www.thmmy.gr) community. ## Requirements @@ -16,4 +18,7 @@ Please refer to [CONTRIBUTING.md](/CONTRIBUTING.md) for details. ## Contact -Do not hesitate to contact us for any matter at `thmmynolife@gmail.com`. +Do not hesitate to contact us for any matter, either by sending an email to `thmmynolife@gmail.com`, or by joining our [Discord server][discord-server]. + +[discord-server]: https://discord.gg/CVt3yrn +[trello-board]: https://trello.com/invite/b/4MVlkrkg/44a931707bd0b84a5e0bdfc42b9ae4f1/mthmmy From fd3539a1f600ca1acead1f05e9d58cbb59d1f650 Mon Sep 17 00:00:00 2001 From: Ezerous Date: Tue, 24 Jan 2017 19:44:38 +0000 Subject: [PATCH 02/18] Update forum_post.txt --- doc/forum_post.txt | 31 ++++++++++++++++--------------- 1 file changed, 16 insertions(+), 15 deletions(-) diff --git a/doc/forum_post.txt b/doc/forum_post.txt index f51905fa..1957af12 100644 --- a/doc/forum_post.txt +++ b/doc/forum_post.txt @@ -1,34 +1,35 @@ [center][size=25pt][b]Introduction[/b][/size][/center] - [url=https://www.thmmy.gr/smf/index.php?topic=67629.0][/url], project Android . +Από τη συζήτηση [url=https://www.thmmy.gr/smf/index.php?topic=67629.0]εδώ[/url], ξεκίνησε ένα project με στόχο τη δημιουργία εφαρμογής για Android κινητά που θα συγκεντρώνει και θα κάνει πιο εύκολη τη πρόσβαση σε μερικές από τις βασικές σελίδες και υπηρεσίες που αφορούν τη σχολή και χρησιμοποιούμε καθημερινά. - 2+ 9000 [size=9pt](.java, .xml )[/size], ( closed alpha phase) Google Play Store! +Μετά από 2+ μήνες δουλειάς και πάνω από 9000 γραμμές κώδικα (.java, .xml και άλλα), σήμερα (16/1/2017) ανεβάσαμε για πρώτη φορά την εφαρμογή (σε closed alpha phase) στο Google Play Store! - forum. , ethmmy , instant chat .., , . +Προς το παρόν η εφαρμογή υποστηρίζει κάποιες από τις βασικές λειτουργίες του forum. Σταδιακά θα ενσωματώνονται όλο και περισσότερες λειτουργίες, για παράδειγμα ενός συστήματος ειδοποιήσεων για νέες ανακοινώσεις του ethmmy και της σελίδας της γραμματείας, instant chat κ.ά., ανάλογα πάντα με τις ιδέες, τη διάθεση και την ενέργεια όσων θα συμμετέχουν. - project L, iason1907 [url=https://www.thmmy.gr/smf/index.php?topic=67565.msg1163192#msg1163192]nohponex[/url]. +Αυτή τη στιγμή με το project ασχολούμαστε εγώ και ο L, ενώ έχουν βοηθήσει ο iason1907 και ο [url=https://www.thmmy.gr/smf/index.php?topic=67565.msg1163192#msg1163192]nohponex[/url]. [hr] -[center][size=25pt][b] contributors[/b][/size] +[center][size=25pt][b]Κάλεσμα για contributors[/b][/size] -[img height=400]https://tctechcrunch2011.files.wordpress.com/2015/04/uncle-sam-we-want-you1-kopie_1.png[/img][/center] +[img height=200]https://tctechcrunch2011.files.wordpress.com/2015/04/uncle-sam-we-want-you1-kopie_1.png[/img][/center] - project : +Αν ενδιαφέρεσαι κι [b]ΕΣΥ[/b] να ασχοληθείς με το project μπορείς να το κάνεις με πολλούς τρόπους: [list] -[li] repository. [i][/i] developers , , javadocs documentation , white-box testing, backend server . , , forks merge requests - . -[/li] + [li] - bugs, , [url=https://discord.gg/PVRVjth]Discord server[/url], Issue Tracker . +Να αναφέρεις bugs, να προτείνεις βελτιώσεις και να συμμετέχεις σε συζητήσεις στον [url=https://discord.gg/PVRVjth]Discord server[/url] μας και στον Issue Tracker στο [url=trello.com]Trello[/url] (το link του είναι pinned στο #feedback στο Discord). [/li] [li] - alpha [url=https://play.google.com/apps/testing/gr.thmmy.mthmmy][/url] gmail . +Να κατεβάσεις και να δοκιμάσεις την alpha έκδοση της εφαρμογής από [url=https://play.google.com/apps/testing/gr.thmmy.mthmmy]εδώ[/url], [b]αφού [/b]πρώτα μας στείλεις το Gmail που έχεις στο Google Play για να αποκτήσεις πρόσβαση. [/li] [li] - Discord email thmmynolife@gmail.com. +Να έρθεις σε άμεση επικοινωνία με την ομάδα μέσω του [url=https://discord.gg/PVRVjth]Discord[/url] ή στέλνοντας email στο thmmynolife@gmail.com. +[/li] +[li]Αν ξέρεις προγραμματισμό μπορείς αρχικά να ζητήσεις πρόσβαση στο repository και να συνεισφέρεις κώδικα με fork και merge requests στους ρυθμούς σου. Χρειάζονται [i]άμεσα[/i] νέοι developers για υλοποιήση καινούργιων χαρακτηριστικών, διόρθωση εντόμων, σύνταξη των javadocs και του documentation γενικότερα, white-box testing, υλοποίηση του backend στο server που στήθηκε πρόσφατα και πολλών άλλων. [/li][/list] [hr] -[center][size=25pt][b] [/b][/size][/center] +[center][size=25pt][b]Η εφαρμογή[/b][/size][/center] -[center][url=https://s6.postimg.org/4mupem3jl/image.png][img width=200]https://s6.postimg.org/4mupem3jl/image.png[/img][/url] [url=https://s6.postimg.org/ovdhmldgx/image.png][img width=200]https://s6.postimg.org/ovdhmldgx/image.png[/img][/url] [url=https://s6.postimg.org/a9mgycgoh/image.png][img width=200]https://s6.postimg.org/a9mgycgoh/image.png[/img][/url] [url=https://s6.postimg.org/5jwj9qpo1/image.png][img width=200]https://s6.postimg.org/5jwj9qpo1/image.png[/img][/url] [url=https://s6.postimg.org/fjrfpn0xd/image.png][img width=200]https://s6.postimg.org/fjrfpn0xd/image.png[/img][/url] [url=https://s6.postimg.org/z0c5c5w1d/image.png][img width=200]https://s6.postimg.org/z0c5c5w1d/image.png[/img][/url][/center] +[center][url=https://s6.postimg.org/v9mseb7n5/image.png][img width=200]https://s6.postimg.org/v9mseb7n5/image.png[/img][/url] [url=https://s6.postimg.org/3nk0tmoa9/image2.png][img width=200]https://s6.postimg.org/3nk0tmoa9/image2.png[/img][/url] [url=https://s6.postimg.org/i813ogj8x/image3.png][img width=200]https://s6.postimg.org/i813ogj8x/image3.png[/img][/url] [url=https://s6.postimg.org/4to0sfckx/image4.png][img width=200]https://s6.postimg.org/4to0sfckx/image4.png[/img][/url] [url=https://s6.postimg.org/69zjakfht/image5.png][img width=200]https://s6.postimg.org/69zjakfht/image5.png[/img][/url] [url=https://s6.postimg.org/rkx3etxm9/image6.png][img width=200]https://s6.postimg.org/rkx3etxm9/image6.png[/img][/url][/center] - login logout, "", boards, topics user profiles post. \ No newline at end of file +Αυτή τη στιγμή στην εφαρμογή μπορείς να κάνεις login και logout, να δεις τα "Πρόσφατα", να περιηγηθείς στα boards, topics και user profiles, να κατεβάσεις αρχεία από τα downloads και από συνημμένα σε post. \ No newline at end of file From d74331b05dc94c9c259290815efc30a4247bd2f4 Mon Sep 17 00:00:00 2001 From: Apostolof Date: Wed, 22 Feb 2017 19:40:46 +0200 Subject: [PATCH 03/18] Fix for embedded videos and reversed order in user stats. --- .../activities/board/BoardActivity.java | 2 +- .../downloads/DownloadsActivity.java | 2 +- .../profile/stats/StatsFragment.java | 3 +++ .../gr/thmmy/mthmmy/base/BaseActivity.java | 1 + .../gr/thmmy/mthmmy/base/BaseApplication.java | 25 ++++++++++++++++++- .../thmmy/mthmmy/session/SessionManager.java | 2 +- .../gr/thmmy/mthmmy/utils/ParseHelpers.java | 7 ++++-- 7 files changed, 36 insertions(+), 6 deletions(-) diff --git a/app/src/main/java/gr/thmmy/mthmmy/activities/board/BoardActivity.java b/app/src/main/java/gr/thmmy/mthmmy/activities/board/BoardActivity.java index c3587b1b..77d2165d 100644 --- a/app/src/main/java/gr/thmmy/mthmmy/activities/board/BoardActivity.java +++ b/app/src/main/java/gr/thmmy/mthmmy/activities/board/BoardActivity.java @@ -201,7 +201,7 @@ public class BoardActivity extends BaseActivity implements BoardAdapter.OnLoadMo .url(boardUrl[0]) .build(); try { - Response response = BaseActivity.getClient().newCall(request).execute(); + Response response = client.newCall(request).execute(); parseBoard(Jsoup.parse(response.body().string())); } catch (SSLHandshakeException e) { Report.w(TAG, "Certificate problem (please switch to unsafe connection)."); diff --git a/app/src/main/java/gr/thmmy/mthmmy/activities/downloads/DownloadsActivity.java b/app/src/main/java/gr/thmmy/mthmmy/activities/downloads/DownloadsActivity.java index 2343f78d..ea02b7b8 100644 --- a/app/src/main/java/gr/thmmy/mthmmy/activities/downloads/DownloadsActivity.java +++ b/app/src/main/java/gr/thmmy/mthmmy/activities/downloads/DownloadsActivity.java @@ -192,7 +192,7 @@ public class DownloadsActivity extends BaseActivity implements DownloadsAdapter. .url(downloadsUrl[0]) .build(); try { - Response response = BaseActivity.getClient().newCall(request).execute(); + Response response = client.newCall(request).execute(); parseDownloads(Jsoup.parse(response.body().string())); } catch (SSLHandshakeException e) { Report.w(TAG, "Certificate problem (please switch to unsafe connection)."); diff --git a/app/src/main/java/gr/thmmy/mthmmy/activities/profile/stats/StatsFragment.java b/app/src/main/java/gr/thmmy/mthmmy/activities/profile/stats/StatsFragment.java index d99f7d65..2e102c0e 100644 --- a/app/src/main/java/gr/thmmy/mthmmy/activities/profile/stats/StatsFragment.java +++ b/app/src/main/java/gr/thmmy/mthmmy/activities/profile/stats/StatsFragment.java @@ -33,6 +33,7 @@ import org.jsoup.nodes.Element; import org.jsoup.select.Elements; import java.util.ArrayList; +import java.util.Collections; import java.util.List; import javax.net.ssl.SSLHandshakeException; @@ -206,6 +207,7 @@ public class StatsFragment extends Fragment { Integer.parseInt(dataCols.last().text()))); mostPopularBoardsByPostsLabels.add(dataCols.first().text()); } + Collections.reverse(mostPopularBoardsByPostsLabels); } { Elements mostPopularBoardsByActivityRows = statsRows.last().select(">td").last() @@ -218,6 +220,7 @@ public class StatsFragment extends Fragment { Float.parseFloat(tmp.substring(0, tmp.indexOf("%"))))); mostPopularBoardsByActivityLabels.add(dataCols.first().text()); } + Collections.reverse(mostPopularBoardsByActivityLabels); } } return true; diff --git a/app/src/main/java/gr/thmmy/mthmmy/base/BaseActivity.java b/app/src/main/java/gr/thmmy/mthmmy/base/BaseActivity.java index 501e2452..2147a1d3 100644 --- a/app/src/main/java/gr/thmmy/mthmmy/base/BaseActivity.java +++ b/app/src/main/java/gr/thmmy/mthmmy/base/BaseActivity.java @@ -79,6 +79,7 @@ public abstract class BaseActivity extends AppCompatActivity { super.onCreate(savedInstanceState); if (client == null) client = BaseApplication.getInstance().getClient(); //must check every time - e.g. + // they become null when app restarts after crash if (sessionManager == null) sessionManager = BaseApplication.getInstance().getSessionManager(); diff --git a/app/src/main/java/gr/thmmy/mthmmy/base/BaseApplication.java b/app/src/main/java/gr/thmmy/mthmmy/base/BaseApplication.java index 1e5ffdd6..b119dabe 100644 --- a/app/src/main/java/gr/thmmy/mthmmy/base/BaseApplication.java +++ b/app/src/main/java/gr/thmmy/mthmmy/base/BaseApplication.java @@ -19,11 +19,17 @@ import com.mikepenz.materialdrawer.util.AbstractDrawerImageLoader; import com.mikepenz.materialdrawer.util.DrawerImageLoader; import com.squareup.picasso.Picasso; +import java.io.IOException; +import java.util.Objects; import java.util.concurrent.TimeUnit; import gr.thmmy.mthmmy.R; import gr.thmmy.mthmmy.session.SessionManager; +import okhttp3.HttpUrl; +import okhttp3.Interceptor; import okhttp3.OkHttpClient; +import okhttp3.Request; +import okhttp3.Response; public class BaseApplication extends Application { @@ -40,7 +46,7 @@ public class BaseApplication extends Application { //Display Metrics private static float dpHeight, dpWidth; - public static BaseApplication getInstance(){ + public static BaseApplication getInstance() { return baseApplication; } @@ -54,6 +60,22 @@ public class BaseApplication extends Application { PersistentCookieJar cookieJar = new PersistentCookieJar(new SetCookieCache(), sharedPrefsCookiePersistor); client = new OkHttpClient.Builder() .cookieJar(cookieJar) + .addInterceptor(new Interceptor() { + @Override + public Response intercept(Chain chain) throws IOException { + Request request = chain.request(); + HttpUrl oldUrl = chain.request().url(); + if (Objects.equals(chain.request().url().host(), "www.thmmy.gr")) { + if (!oldUrl.toString().contains("theme=4")) { + //Probably works but needs more testing: + HttpUrl newUrl = oldUrl.newBuilder().addQueryParameter("theme", "4").build(); + request = request.newBuilder().url(newUrl).build(); + } + } + return chain.proceed(request); + + } + }) .connectTimeout(30, TimeUnit.SECONDS) .writeTimeout(30, TimeUnit.SECONDS) .readTimeout(30, TimeUnit.SECONDS) @@ -71,6 +93,7 @@ public class BaseApplication extends Application { public void set(ImageView imageView, Uri uri, Drawable placeholder) { Picasso.with(imageView.getContext()).load(uri).placeholder(placeholder).into(imageView); } + @Override public void cancel(ImageView imageView) { Picasso.with(imageView.getContext()).cancelRequest(imageView); diff --git a/app/src/main/java/gr/thmmy/mthmmy/session/SessionManager.java b/app/src/main/java/gr/thmmy/mthmmy/session/SessionManager.java index 2321b88a..c6bbd713 100644 --- a/app/src/main/java/gr/thmmy/mthmmy/session/SessionManager.java +++ b/app/src/main/java/gr/thmmy/mthmmy/session/SessionManager.java @@ -332,7 +332,7 @@ public class SessionManager { if (!avatar.isEmpty()) return avatar.first().attr("src"); - Report.e(TAG, "Extracting avatar's link failed!"); + Report.i(TAG, "Extracting avatar's link failed!"); return null; } diff --git a/app/src/main/java/gr/thmmy/mthmmy/utils/ParseHelpers.java b/app/src/main/java/gr/thmmy/mthmmy/utils/ParseHelpers.java index 2520cc89..2e8867f5 100644 --- a/app/src/main/java/gr/thmmy/mthmmy/utils/ParseHelpers.java +++ b/app/src/main/java/gr/thmmy/mthmmy/utils/ParseHelpers.java @@ -1,5 +1,7 @@ package gr.thmmy.mthmmy.utils; +import android.util.Log; + import org.jsoup.nodes.Document; import org.jsoup.nodes.Element; import org.jsoup.select.Elements; @@ -153,15 +155,16 @@ public class ParseHelpers { fixed = fixed.replace( fixed.substring(fixed.indexOf("") + 9) , "
" - + "" + "" + "" + "\"\"" + "
"); + ++tmp_counter; } return fixed; } From 85eef4f8c106bd4074ec1001151ae327470cc2ee Mon Sep 17 00:00:00 2001 From: Apostolof Date: Wed, 22 Feb 2017 22:24:17 +0200 Subject: [PATCH 04/18] Topic reply init. --- .../activities/topic/TopicActivity.java | 134 +++- .../mthmmy/activities/topic/TopicAdapter.java | 666 ++++++++++-------- .../res/layout/activity_topic_post_row.xml | 17 +- .../layout/activity_topic_quick_reply_row.xml | 53 ++ app/src/main/res/values/strings.xml | 2 + 5 files changed, 530 insertions(+), 342 deletions(-) create mode 100644 app/src/main/res/layout/activity_topic_quick_reply_row.xml diff --git a/app/src/main/java/gr/thmmy/mthmmy/activities/topic/TopicActivity.java b/app/src/main/java/gr/thmmy/mthmmy/activities/topic/TopicActivity.java index 8ca6f707..92cc5317 100644 --- a/app/src/main/java/gr/thmmy/mthmmy/activities/topic/TopicActivity.java +++ b/app/src/main/java/gr/thmmy/mthmmy/activities/topic/TopicActivity.java @@ -14,14 +14,19 @@ import android.util.SparseArray; import android.view.MotionEvent; import android.view.View; import android.widget.ImageButton; +import android.widget.LinearLayout; 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.io.UnsupportedEncodingException; +import java.net.URLEncoder; import java.util.ArrayList; import java.util.Objects; @@ -33,7 +38,9 @@ import gr.thmmy.mthmmy.model.ThmmyPage; import gr.thmmy.mthmmy.utils.ParseHelpers; import me.zhanghai.android.materialprogressbar.MaterialProgressBar; import mthmmy.utils.Report; +import okhttp3.MultipartBody; import okhttp3.Request; +import okhttp3.RequestBody; import okhttp3.Response; /** @@ -62,10 +69,11 @@ public class TopicActivity extends BaseActivity { private TopicAdapter topicAdapter; private ArrayList postsList; private static final int NO_POST_FOCUS = -1; - private static int postFocus = NO_POST_FOCUS; + private int postFocus = NO_POST_FOCUS; private static int postFocusPosition = 0; - //Quotes - public static final ArrayList toQuoteList = new ArrayList<>(); + //Reply + private FloatingActionButton replyFAB; + private String replyPageUrl = null; //Topic's pages private int thisPage = 1; private int numberOfPages = 1; @@ -85,7 +93,6 @@ public class TopicActivity extends BaseActivity { private ImageButton nextPage; private ImageButton lastPage; //Other variables - private FloatingActionButton replyFAB; private MaterialProgressBar progressBar; private static String base_url = ""; private String topicTitle; @@ -132,42 +139,27 @@ public class TopicActivity extends BaseActivity { recyclerView.setHasFixedSize(true); LinearLayoutManager layoutManager = new LinearLayoutManager(getApplicationContext()); recyclerView.setLayoutManager(layoutManager); - topicAdapter = new TopicAdapter(this, postsList, - topicTask); + topicAdapter = new TopicAdapter(this, postsList, topicTask); recyclerView.setAdapter(topicAdapter); replyFAB = (FloatingActionButton) findViewById(R.id.topic_fab); replyFAB.setEnabled(false); - replyFAB.hide(); - /*if (!sessionManager.isLoggedIn()) replyFAB.hide(); + final LinearLayout bottomNavBar = (LinearLayout) 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()) { - //TODO Reply - } else { - new AlertDialog.Builder(TopicActivity.this) - .setMessage("You need to be logged in to reply!") - .setPositiveButton("Login", new DialogInterface.OnClickListener() { - @Override - public void onClick(DialogInterface dialogInterface, int i) { - Intent intent = new Intent(TopicActivity.this, LoginActivity.class); - startActivity(intent); - finish(); - overridePendingTransition(R.anim.push_right_in, R.anim.push_right_out); - } - }) - .setNegativeButton("Cancel", new DialogInterface.OnClickListener() { - @Override - public void onClick(DialogInterface dialogInterface, int i) { - } - }) - .show(); + postsList.add(null); + topicAdapter.prepareForReply(new ReplyTask()); + replyFAB.hide(); + bottomNavBar.setVisibility(View.GONE); + topicAdapter.notifyItemInserted(postsList.size()); } } }); - }*/ + } //Sets bottom navigation bar firstPage = (ImageButton) findViewById(R.id.page_first_button); @@ -488,6 +480,7 @@ public class TopicActivity extends BaseActivity { progressBar.setVisibility(ProgressBar.INVISIBLE); topicAdapter.customNotifyDataSetChanged(new TopicTask()); + if (replyPageUrl == null) replyFAB.setVisibility(View.GONE); if (replyFAB.getVisibility() != View.GONE) replyFAB.setEnabled(true); //Set current page @@ -528,6 +521,12 @@ public class TopicActivity extends BaseActivity { private void parse(Document topic) { ParseHelpers.Language language = ParseHelpers.Language.getLanguage(topic); + //Find reply page url + { + Element replyButton = topic.select("a:has(img[alt=Reply])").first(); + if (replyButton != null) replyPageUrl = replyButton.attr("href"); + } + //Finds topic title if missing if (topicTitle == null || Objects.equals(topicTitle, "")) { parsedTitle = topic.select("td[id=top_subject]").first().text(); @@ -555,7 +554,84 @@ public class TopicActivity extends BaseActivity { postsList.clear(); postsList.addAll(TopicParser.parseTopic(topic, language)); - //postsList = TopicParser.parseTopic(topic, language); + } + } + + class ReplyTask extends AsyncTask { + + @Override + protected void onPreExecute() { + progressBar.setVisibility(ProgressBar.VISIBLE); + paginationEnabled(false); + replyFAB.setEnabled(false); + } + + @Override + protected Boolean doInBackground(String... message) { + Document document; + String numReplies, seqnum, sc, subject, topic; + + Request request = new Request.Builder() + .url(replyPageUrl + ";wap2") + .build(); + try { + Response response = client.newCall(request).execute(); + document = Jsoup.parse(response.body().string()); + + //https://www.thmmy.gr/smf/index.php?action=post;topic=67565.15;num_replies=27 + 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"); + subject = document.select("input[name=subject]").first().attr("value"); + topic = document.select("input[name=topic]").first().attr("value"); + Log.d(TAG, "numReplies " + numReplies + "\n" + + "seqnum " + seqnum + "\n" + + "sc " + sc + "\n" + + "subject " + subject + "\n" + + "topic " + topic + "\n"); + } catch (IOException e) { + Report.i(TAG, "Post failed.", e); + return false; + } catch (Selector.SelectorParseException e) { + Report.e(TAG, "Post failed.", e); + return false; + } + + Log.d(TAG, message[0]); + RequestBody postBody = null; + try { + postBody = new MultipartBody.Builder() + .setType(MultipartBody.FORM) + .addFormDataPart("message", URLEncoder.encode(message[0], "UTF-8")) + .addFormDataPart("num_replies", numReplies) + .addFormDataPart("seqnum", seqnum) + .addFormDataPart("sc", sc) + .addFormDataPart("subject", subject) + .addFormDataPart("topic", topic) + .addFormDataPart("goback", "1") + .build(); + } catch (UnsupportedEncodingException e) { + e.printStackTrace(); + } + + 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(); + return true; + } catch (IOException e) { + Report.i(TAG, "Post failed.", e); + return false; + } + } + + @Override + protected void onPostExecute(Boolean result) { + progressBar.setVisibility(ProgressBar.GONE); } } } \ No newline at end of file diff --git a/app/src/main/java/gr/thmmy/mthmmy/activities/topic/TopicAdapter.java b/app/src/main/java/gr/thmmy/mthmmy/activities/topic/TopicAdapter.java index 2ea65fb9..d989f608 100644 --- a/app/src/main/java/gr/thmmy/mthmmy/activities/topic/TopicAdapter.java +++ b/app/src/main/java/gr/thmmy/mthmmy/activities/topic/TopicAdapter.java @@ -11,9 +11,11 @@ import android.os.Build; import android.os.Bundle; import android.support.annotation.NonNull; import android.support.v4.content.res.ResourcesCompat; +import android.support.v7.widget.AppCompatImageButton; import android.support.v7.widget.CardView; import android.support.v7.widget.RecyclerView; import android.text.TextUtils; +import android.util.Log; import android.view.LayoutInflater; import android.view.MotionEvent; import android.view.View; @@ -21,6 +23,7 @@ import android.view.ViewGroup; import android.webkit.WebResourceRequest; import android.webkit.WebView; import android.webkit.WebViewClient; +import android.widget.EditText; import android.widget.FrameLayout; import android.widget.ImageButton; import android.widget.ImageView; @@ -31,6 +34,7 @@ import android.widget.TextView; import com.squareup.picasso.Picasso; import java.util.ArrayList; +import java.util.Date; import java.util.List; import java.util.Objects; @@ -50,12 +54,11 @@ 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.TopicActivity.toQuoteList; /** * Custom {@link android.support.v7.widget.RecyclerView.Adapter} used for topics. */ -class TopicAdapter extends RecyclerView.Adapter { +class TopicAdapter extends RecyclerView.Adapter { /** * Debug Tag for logging debug output to LogCat */ @@ -65,6 +68,7 @@ class TopicAdapter extends RecyclerView.Adapter { */ private static int THUMBNAIL_SIZE; private final Context context; + private ArrayList toQuoteList = new ArrayList<>(); private final List postsList; /** * Used to hold the state of visibility and other attributes for views that are animated or @@ -87,69 +91,16 @@ class TopicAdapter extends RecyclerView.Adapter { */ private static final int isQuoteButtonChecked = 2; private TopicActivity.TopicTask topicTask; - - /** - * Custom {@link RecyclerView.ViewHolder} implementation - */ - class MyViewHolder extends RecyclerView.ViewHolder { - final CardView cardView; - final LinearLayout cardChildLinear; - final FrameLayout postDateAndNumberExp; - final TextView postDate, postNum, username, subject; - final ImageView thumbnail; - final public WebView post; - final ImageButton quoteToggle; - final RelativeLayout header; - final LinearLayout userExtraInfo; - final View bodyFooterDivider; - final LinearLayout postFooter; - - final TextView specialRank, rank, gender, numberOfPosts, personalText, stars; - - MyViewHolder(View view) { - super(view); - //Initializes layout's graphic elements - //Standard stuff - cardView = (CardView) view.findViewById(R.id.card_view); - cardChildLinear = (LinearLayout) view.findViewById(R.id.card_child_linear); - postDateAndNumberExp = (FrameLayout) view.findViewById(R.id.post_date_and_number_exp); - postDate = (TextView) view.findViewById(R.id.post_date); - postNum = (TextView) view.findViewById(R.id.post_number); - thumbnail = (ImageView) view.findViewById(R.id.thumbnail); - username = (TextView) view.findViewById(R.id.username); - subject = (TextView) view.findViewById(R.id.subject); - post = (WebView) view.findViewById(R.id.post); - post.setBackgroundColor(Color.argb(1, 255, 255, 255)); - quoteToggle = (ImageButton) view.findViewById(R.id.toggle_quote_button); - bodyFooterDivider = view.findViewById(R.id.body_footer_divider); - postFooter = (LinearLayout) view.findViewById(R.id.post_footer); - - //User's extra info - header = (RelativeLayout) view.findViewById(R.id.header); - userExtraInfo = (LinearLayout) view.findViewById(R.id.user_extra_info); - specialRank = (TextView) view.findViewById(R.id.special_rank); - rank = (TextView) view.findViewById(R.id.rank); - gender = (TextView) view.findViewById(R.id.gender); - numberOfPosts = (TextView) view.findViewById(R.id.number_of_posts); - personalText = (TextView) view.findViewById(R.id.personal_text); - stars = (TextView) view.findViewById(R.id.stars); - } - - /** - * Cancels all pending Picasso requests - */ - void cleanup() { - Picasso.with(context).cancelRequest(thumbnail); - thumbnail.setImageDrawable(null); - } - } + private TopicActivity.ReplyTask replyTask; + private final int VIEW_TYPE_POST = 0; + private final int VIEW_TYPE_QUICK_REPLY = 1; + private boolean firstTime = false; /** * @param context the context of the {@link RecyclerView} * @param postsList List of {@link Post} objects to use */ - TopicAdapter(Context context, List postsList, - TopicActivity.TopicTask topicTask) { + TopicAdapter(Context context, List postsList, TopicActivity.TopicTask topicTask) { this.context = context; this.postsList = postsList; @@ -161,280 +112,322 @@ class TopicAdapter extends RecyclerView.Adapter { this.topicTask = topicTask; } + void prepareForReply(TopicActivity.ReplyTask replyTask) { + this.replyTask = replyTask; + firstTime = true; + } + @Override - public void onViewRecycled(final MyViewHolder holder) { - holder.cleanup(); + public int getItemViewType(int position) { + return postsList.get(position) == null ? VIEW_TYPE_QUICK_REPLY : VIEW_TYPE_POST; } @Override - public MyViewHolder onCreateViewHolder(ViewGroup parent, int viewType) { - View itemView = LayoutInflater.from(parent.getContext()) - .inflate(R.layout.activity_topic_post_row, parent, false); - return new MyViewHolder(itemView); + public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) { + if (viewType == VIEW_TYPE_POST) { + View itemView = LayoutInflater.from(parent.getContext()) + .inflate(R.layout.activity_topic_post_row, parent, false); + return new PostViewHolder(itemView); + } else if (viewType == VIEW_TYPE_QUICK_REPLY) { + View view = LayoutInflater.from(parent.getContext()). + inflate(R.layout.activity_topic_quick_reply_row, parent, false); + return new QuickReplyViewHolder(view); + } + return null; } @SuppressLint("SetJavaScriptEnabled") @Override - public void onBindViewHolder(final MyViewHolder holder, final int position) { - final Post currentPost = postsList.get(position); - - //Post's WebView parameters - holder.post.setClickable(true); - holder.post.setWebViewClient(new LinkLauncher()); - - //Avoids errors about layout having 0 width/height - holder.thumbnail.setMinimumWidth(1); - holder.thumbnail.setMinimumHeight(1); - //Sets thumbnail size - holder.thumbnail.setMaxWidth(THUMBNAIL_SIZE); - holder.thumbnail.setMaxHeight(THUMBNAIL_SIZE); - - //noinspection ConstantConditions - Picasso.with(context) - .load(currentPost.getThumbnailUrl()) - .resize(THUMBNAIL_SIZE, THUMBNAIL_SIZE) - .centerCrop() - .error(ResourcesCompat.getDrawable(context.getResources() - , R.drawable.ic_default_user_thumbnail, null)) - .placeholder(ResourcesCompat.getDrawable(context.getResources() - , R.drawable.ic_default_user_thumbnail, null)) - .transform(new CircleTransform()) - .into(holder.thumbnail); - - //Sets username,submit date, index number, subject, post's and attached files texts - holder.username.setText(currentPost.getAuthor()); - holder.postDate.setText(currentPost.getPostDate()); - if (currentPost.getPostNumber() != 0) - holder.postNum.setText(context.getString( - R.string.user_number_of_posts, currentPost.getPostNumber())); - else - holder.postNum.setText(""); - holder.subject.setText(currentPost.getSubject()); - holder.post.loadDataWithBaseURL("file:///android_asset/", currentPost.getContent(), "text/html", "UTF-8", null); - if (currentPost.getAttachedFiles() != null && currentPost.getAttachedFiles().size() != 0) { - holder.bodyFooterDivider.setVisibility(View.VISIBLE); - int filesTextColor; - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) { - filesTextColor = context.getResources().getColor(R.color.accent, null); - } else //noinspection deprecation - filesTextColor = context.getResources().getColor(R.color.accent); - - holder.postFooter.removeAllViews(); - for (final ThmmyFile attachedFile : currentPost.getAttachedFiles()) { - final TextView attached = new TextView(context); - attached.setTextSize(10f); - attached.setClickable(true); - attached.setTypeface(Typeface.createFromAsset(context.getAssets() + public void onBindViewHolder(final RecyclerView.ViewHolder currentHolder, final int position) { + if (currentHolder instanceof PostViewHolder) { + final Post currentPost = postsList.get(position); + final PostViewHolder holder = (PostViewHolder) currentHolder; + + //Post's WebView parameters + holder.post.setClickable(true); + holder.post.setWebViewClient(new LinkLauncher()); + + //Avoids errors about layout having 0 width/height + holder.thumbnail.setMinimumWidth(1); + holder.thumbnail.setMinimumHeight(1); + //Sets thumbnail size + holder.thumbnail.setMaxWidth(THUMBNAIL_SIZE); + holder.thumbnail.setMaxHeight(THUMBNAIL_SIZE); + + //noinspection ConstantConditions + Picasso.with(context) + .load(currentPost.getThumbnailUrl()) + .resize(THUMBNAIL_SIZE, THUMBNAIL_SIZE) + .centerCrop() + .error(ResourcesCompat.getDrawable(context.getResources() + , R.drawable.ic_default_user_thumbnail, null)) + .placeholder(ResourcesCompat.getDrawable(context.getResources() + , R.drawable.ic_default_user_thumbnail, null)) + .transform(new CircleTransform()) + .into(holder.thumbnail); + + //Sets username,submit date, index number, subject, post's and attached files texts + holder.username.setText(currentPost.getAuthor()); + holder.postDate.setText(currentPost.getPostDate()); + if (currentPost.getPostNumber() != 0) + holder.postNum.setText(context.getString( + R.string.user_number_of_posts, currentPost.getPostNumber())); + else + holder.postNum.setText(""); + holder.subject.setText(currentPost.getSubject()); + holder.post.loadDataWithBaseURL("file:///android_asset/", currentPost.getContent(), "text/html", "UTF-8", null); + if (currentPost.getAttachedFiles() != null && currentPost.getAttachedFiles().size() != 0) { + holder.bodyFooterDivider.setVisibility(View.VISIBLE); + int filesTextColor; + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) { + filesTextColor = context.getResources().getColor(R.color.accent, null); + } else //noinspection deprecation + filesTextColor = context.getResources().getColor(R.color.accent); + + holder.postFooter.removeAllViews(); + for (final ThmmyFile attachedFile : currentPost.getAttachedFiles()) { + final TextView attached = new TextView(context); + attached.setTextSize(10f); + attached.setClickable(true); + attached.setTypeface(Typeface.createFromAsset(context.getAssets() + , "fonts/fontawesome-webfont.ttf")); + attached.setText(faIconFromFilename(attachedFile.getFilename()) + " " + + attachedFile.getFilename() + attachedFile.getFileInfo()); + attached.setTextColor(filesTextColor); + attached.setPadding(0, 3, 0, 3); + + attached.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View view) { + ((BaseActivity) context).launchDownloadService(attachedFile); + } + }); + + holder.postFooter.addView(attached); + } + } else { + holder.bodyFooterDivider.setVisibility(View.GONE); + holder.postFooter.removeAllViews(); + } + + String mSpecialRank, mRank, mGender, mNumberOfPosts, mPersonalText; + int mNumberOfStars, mUserColor; + + if (!currentPost.isDeleted()) { //Sets user's extra info + mSpecialRank = currentPost.getSpecialRank(); + mRank = currentPost.getRank(); + mGender = currentPost.getGender(); + mNumberOfPosts = currentPost.getNumberOfPosts(); + mPersonalText = currentPost.getPersonalText(); + mNumberOfStars = currentPost.getNumberOfStars(); + mUserColor = currentPost.getUserColor(); + } else { + mSpecialRank = null; + mRank = null; + mGender = null; + mNumberOfPosts = null; + mPersonalText = null; + mNumberOfStars = 0; + mUserColor = 0; + } + + if (!Objects.equals(mSpecialRank, "") && mSpecialRank != null) { + holder.specialRank.setText(mSpecialRank); + holder.specialRank.setVisibility(View.VISIBLE); + } else + holder.specialRank.setVisibility(View.GONE); + if (!Objects.equals(mRank, "") && mRank != null) { + holder.rank.setText(mRank); + holder.rank.setVisibility(View.VISIBLE); + } else + holder.rank.setVisibility(View.GONE); + if (!Objects.equals(mGender, "") && mGender != null) { + holder.gender.setText(mGender); + holder.gender.setVisibility(View.VISIBLE); + } else + holder.gender.setVisibility(View.GONE); + if (!Objects.equals(mNumberOfPosts, "") && mNumberOfPosts != null) { + holder.numberOfPosts.setText(mNumberOfPosts); + holder.numberOfPosts.setVisibility(View.VISIBLE); + } else + holder.numberOfPosts.setVisibility(View.GONE); + if (!Objects.equals(mPersonalText, "") && mPersonalText != null) { + holder.personalText.setText("\"" + mPersonalText + "\""); + holder.personalText.setVisibility(View.VISIBLE); + } else + holder.personalText.setVisibility(View.GONE); + if (mNumberOfStars > 0) { + holder.stars.setTypeface(Typeface.createFromAsset(context.getAssets() , "fonts/fontawesome-webfont.ttf")); - attached.setText(faIconFromFilename(attachedFile.getFilename()) + " " - + attachedFile.getFilename() + attachedFile.getFileInfo()); - attached.setTextColor(filesTextColor); - attached.setPadding(0, 3, 0, 3); - attached.setOnClickListener(new View.OnClickListener() { + String aStar = context.getResources().getString(R.string.fa_icon_star); + String usersStars = ""; + for (int i = 0; i < mNumberOfStars; ++i) { + usersStars += aStar; + } + holder.stars.setText(usersStars); + holder.stars.setTextColor(mUserColor); + holder.stars.setVisibility(View.VISIBLE); + } else + holder.stars.setVisibility(View.GONE); + //Special card for special member of the month! + if (mUserColor == TopicParser.USER_COLOR_PINK) { + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { + holder.cardChildLinear.setBackground(context.getResources(). + getDrawable(R.drawable.member_of_the_month_card, null)); + } else //noinspection deprecation + holder.cardChildLinear.setBackground(context.getResources(). + getDrawable(R.drawable.member_of_the_month_card)); + } else holder.cardChildLinear.setBackground(null); + + //Avoid's view's visibility recycling + if (!currentPost.isDeleted() && viewProperties.get(position)[isUserExtraInfoVisibile]) { + holder.userExtraInfo.setVisibility(View.VISIBLE); + holder.userExtraInfo.setAlpha(1.0f); + } else { + holder.userExtraInfo.setVisibility(View.GONE); + holder.userExtraInfo.setAlpha(0.0f); + } + if (!currentPost.isDeleted()) { + //Sets graphics behavior + holder.header.setOnClickListener(new View.OnClickListener() { @Override - public void onClick(View view) { - ((BaseActivity) context).launchDownloadService(attachedFile); + public void onClick(View v) { + //Clicking an expanded header starts profile activity + if (viewProperties.get(holder.getAdapterPosition())[isUserExtraInfoVisibile]) { + Intent intent = new Intent(context, ProfileActivity.class); + Bundle extras = new Bundle(); + extras.putString(BUNDLE_PROFILE_URL, currentPost.getProfileURL()); + if (currentPost.getThumbnailUrl() == null) + extras.putString(BUNDLE_PROFILE_THUMBNAIL_URL, ""); + else + extras.putString(BUNDLE_PROFILE_THUMBNAIL_URL, currentPost.getThumbnailUrl()); + extras.putString(BUNDLE_PROFILE_USERNAME, currentPost.getAuthor()); + intent.putExtras(extras); + intent.setFlags(FLAG_ACTIVITY_NEW_TASK); + context.startActivity(intent); + } + + boolean[] tmp = viewProperties.get(holder.getAdapterPosition()); + tmp[isUserExtraInfoVisibile] = !tmp[isUserExtraInfoVisibile]; + viewProperties.set(holder.getAdapterPosition(), tmp); + TopicAnimations.animateUserExtraInfoVisibility(holder.userExtraInfo); } }); + //Clicking the expanded part of a header (the extra info) makes it collapse + holder.userExtraInfo.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + boolean[] tmp = viewProperties.get(holder.getAdapterPosition()); + tmp[1] = false; + viewProperties.set(holder.getAdapterPosition(), tmp); - holder.postFooter.addView(attached); + TopicAnimations.animateUserExtraInfoVisibility(v); + } + }); + } else { + holder.header.setOnClickListener(null); + holder.userExtraInfo.setOnClickListener(null); } - } else { - holder.bodyFooterDivider.setVisibility(View.GONE); - holder.postFooter.removeAllViews(); - } - - String mSpecialRank, mRank, mGender, mNumberOfPosts, mPersonalText; - int mNumberOfStars, mUserColor; - - if (!currentPost.isDeleted()) { //Sets user's extra info - mSpecialRank = currentPost.getSpecialRank(); - mRank = currentPost.getRank(); - mGender = currentPost.getGender(); - mNumberOfPosts = currentPost.getNumberOfPosts(); - mPersonalText = currentPost.getPersonalText(); - mNumberOfStars = currentPost.getNumberOfStars(); - mUserColor = currentPost.getUserColor(); - } else { - mSpecialRank = null; - mRank = null; - mGender = null; - mNumberOfPosts = null; - mPersonalText = null; - mNumberOfStars = 0; - mUserColor = 0; - } - if (!Objects.equals(mSpecialRank, "") && mSpecialRank != null) { - holder.specialRank.setText(mSpecialRank); - holder.specialRank.setVisibility(View.VISIBLE); - } else - holder.specialRank.setVisibility(View.GONE); - if (!Objects.equals(mRank, "") && mRank != null) { - holder.rank.setText(mRank); - holder.rank.setVisibility(View.VISIBLE); - } else - holder.rank.setVisibility(View.GONE); - if (!Objects.equals(mGender, "") && mGender != null) { - holder.gender.setText(mGender); - holder.gender.setVisibility(View.VISIBLE); - } else - holder.gender.setVisibility(View.GONE); - if (!Objects.equals(mNumberOfPosts, "") && mNumberOfPosts != null) { - holder.numberOfPosts.setText(mNumberOfPosts); - holder.numberOfPosts.setVisibility(View.VISIBLE); - } else - holder.numberOfPosts.setVisibility(View.GONE); - if (!Objects.equals(mPersonalText, "") && mPersonalText != null) { - holder.personalText.setText("\"" + mPersonalText + "\""); - holder.personalText.setVisibility(View.VISIBLE); - } else - holder.personalText.setVisibility(View.GONE); - if (mNumberOfStars > 0) { - holder.stars.setTypeface(Typeface.createFromAsset(context.getAssets() - , "fonts/fontawesome-webfont.ttf")); - - String aStar = context.getResources().getString(R.string.fa_icon_star); - String usersStars = ""; - for (int i = 0; i < mNumberOfStars; ++i) { - usersStars += aStar; + //Avoid's view's visibility recycling + if (viewProperties.get(position)[isPostDateAndNumberVisibile]) { //Expanded + holder.postDateAndNumberExp.setVisibility(View.VISIBLE); + holder.postDateAndNumberExp.setAlpha(1.0f); + holder.postDateAndNumberExp.setTranslationY(0); + + holder.username.setMaxLines(Integer.MAX_VALUE); + holder.username.setEllipsize(null); + + holder.subject.setTextColor(Color.parseColor("#FFFFFF")); + holder.subject.setMaxLines(Integer.MAX_VALUE); + holder.subject.setEllipsize(null); + } else { //Collapsed + holder.postDateAndNumberExp.setVisibility(View.GONE); + holder.postDateAndNumberExp.setAlpha(0.0f); + holder.postDateAndNumberExp.setTranslationY(holder.postDateAndNumberExp.getHeight()); + + holder.username.setMaxLines(1); + holder.username.setEllipsize(TextUtils.TruncateAt.END); + + holder.subject.setTextColor(Color.parseColor("#757575")); + holder.subject.setMaxLines(1); + holder.subject.setEllipsize(TextUtils.TruncateAt.END); } - holder.stars.setText(usersStars); - holder.stars.setTextColor(mUserColor); - holder.stars.setVisibility(View.VISIBLE); - } else - holder.stars.setVisibility(View.GONE); - //Special card for special member of the month! - if (mUserColor == TopicParser.USER_COLOR_PINK) { - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { - holder.cardChildLinear.setBackground(context.getResources(). - getDrawable(R.drawable.member_of_the_month_card, null)); - } else //noinspection deprecation - holder.cardChildLinear.setBackground(context.getResources(). - getDrawable(R.drawable.member_of_the_month_card)); - } else holder.cardChildLinear.setBackground(null); - - //Avoid's view's visibility recycling - if (!currentPost.isDeleted() && viewProperties.get(position)[isUserExtraInfoVisibile]) { - holder.userExtraInfo.setVisibility(View.VISIBLE); - holder.userExtraInfo.setAlpha(1.0f); - } else { - holder.userExtraInfo.setVisibility(View.GONE); - holder.userExtraInfo.setAlpha(0.0f); - } - if (!currentPost.isDeleted()) { - //Sets graphics behavior - holder.header.setOnClickListener(new View.OnClickListener() { - @Override - public void onClick(View v) { - //Clicking an expanded header starts profile activity - if (viewProperties.get(holder.getAdapterPosition())[isUserExtraInfoVisibile]) { - Intent intent = new Intent(context, ProfileActivity.class); - Bundle extras = new Bundle(); - extras.putString(BUNDLE_PROFILE_URL, currentPost.getProfileURL()); - if (currentPost.getThumbnailUrl() == null) - extras.putString(BUNDLE_PROFILE_THUMBNAIL_URL, ""); - else - extras.putString(BUNDLE_PROFILE_THUMBNAIL_URL, currentPost.getThumbnailUrl()); - extras.putString(BUNDLE_PROFILE_USERNAME, currentPost.getAuthor()); - intent.putExtras(extras); - intent.setFlags(FLAG_ACTIVITY_NEW_TASK); - context.startActivity(intent); + //noinspection PointlessBooleanExpression,ConstantConditions + if (!BaseActivity.getSessionManager().isLoggedIn() || true) //Hide it until reply is implemented + holder.quoteToggle.setVisibility(View.GONE); + else { + if (viewProperties.get(position)[isQuoteButtonChecked]) + holder.quoteToggle.setImageResource(R.drawable.ic_format_quote_checked); + else + holder.quoteToggle.setImageResource(R.drawable.ic_format_quote_unchecked); + //Sets graphics behavior + holder.quoteToggle.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View view) { + boolean[] tmp = viewProperties.get(holder.getAdapterPosition()); + if (tmp[isQuoteButtonChecked]) { + if (toQuoteList.contains(currentPost.getPostNumber())) { + toQuoteList.remove(toQuoteList.indexOf(currentPost.getPostNumber())); + } else + Report.i(TAG, "An error occurred while trying to exclude post from" + + "toQuoteList, post wasn't there!"); + holder.quoteToggle.setImageResource(R.drawable.ic_format_quote_unchecked); + } else { + toQuoteList.add(currentPost.getPostNumber()); + holder.quoteToggle.setImageResource(R.drawable.ic_format_quote_checked); + } + tmp[isQuoteButtonChecked] = !tmp[isQuoteButtonChecked]; + viewProperties.set(holder.getAdapterPosition(), tmp); } - - boolean[] tmp = viewProperties.get(holder.getAdapterPosition()); - tmp[isUserExtraInfoVisibile] = !tmp[isUserExtraInfoVisibile]; - viewProperties.set(holder.getAdapterPosition(), tmp); - TopicAnimations.animateUserExtraInfoVisibility(holder.userExtraInfo); - } - }); - //Clicking the expanded part of a header (the extra info) makes it collapse - holder.userExtraInfo.setOnClickListener(new View.OnClickListener() { + }); + } + //Card expand/collapse when card is touched + holder.cardView.setOnClickListener(new View.OnClickListener() { @Override - public void onClick(View v) { + public void onClick(View view) { + //Change post's viewProperties accordingly boolean[] tmp = viewProperties.get(holder.getAdapterPosition()); - tmp[1] = false; + tmp[isPostDateAndNumberVisibile] = !tmp[isPostDateAndNumberVisibile]; viewProperties.set(holder.getAdapterPosition(), tmp); - TopicAnimations.animateUserExtraInfoVisibility(v); + TopicAnimations.animatePostExtraInfoVisibility(holder.postDateAndNumberExp + , holder.username, holder.subject + , Color.parseColor("#FFFFFF") + , Color.parseColor("#757575")); } }); - } else { - holder.header.setOnClickListener(null); - holder.userExtraInfo.setOnClickListener(null); - } - - //Avoid's view's visibility recycling - if (viewProperties.get(position)[isPostDateAndNumberVisibile]) { //Expanded - holder.postDateAndNumberExp.setVisibility(View.VISIBLE); - holder.postDateAndNumberExp.setAlpha(1.0f); - holder.postDateAndNumberExp.setTranslationY(0); - - holder.username.setMaxLines(Integer.MAX_VALUE); - holder.username.setEllipsize(null); - - holder.subject.setTextColor(Color.parseColor("#FFFFFF")); - holder.subject.setMaxLines(Integer.MAX_VALUE); - holder.subject.setEllipsize(null); - } else { //Collapsed - holder.postDateAndNumberExp.setVisibility(View.GONE); - holder.postDateAndNumberExp.setAlpha(0.0f); - holder.postDateAndNumberExp.setTranslationY(holder.postDateAndNumberExp.getHeight()); - - holder.username.setMaxLines(1); - holder.username.setEllipsize(TextUtils.TruncateAt.END); - - holder.subject.setTextColor(Color.parseColor("#757575")); - holder.subject.setMaxLines(1); - holder.subject.setEllipsize(TextUtils.TruncateAt.END); - } - //noinspection PointlessBooleanExpression,ConstantConditions - if (!BaseActivity.getSessionManager().isLoggedIn() || true) //Hide it until reply is implemented - holder.quoteToggle.setVisibility(View.GONE); - else { - if (viewProperties.get(position)[isQuoteButtonChecked]) - holder.quoteToggle.setImageResource(R.drawable.ic_format_quote_checked); - else - holder.quoteToggle.setImageResource(R.drawable.ic_format_quote_unchecked); - //Sets graphics behavior - holder.quoteToggle.setOnClickListener(new View.OnClickListener() { + //Also when post is clicked + holder.post.setOnTouchListener(new CustomTouchListener(holder.post, holder.cardView)); + } else if (currentHolder instanceof QuickReplyViewHolder) { + final QuickReplyViewHolder holder = (QuickReplyViewHolder) currentHolder; + if (firstTime) { + //Build quotes + String quotes = ""; + for (int quotePosition : toQuoteList) { + //Date postDate = new Date(); + Log.d(TAG, postsList.get(quotePosition).getPostDate()); + if (postsList.get(quotePosition).getPostIndex() != 0) { + quotes += "[quote author=" + postsList.get(quotePosition).getAuthor() + + " link=topic=68525.msg" + postsList.get(quotePosition).getPostIndex() + + "#msg" + postsList.get(quotePosition).getPostIndex() + + " date=" + "1000" + + "\n" + postsList.get(quotePosition).getContent() + + "\n" + "[/quote]" + "\n"; + } + } + holder.quickReply.setText(quotes); + } + holder.submitButton.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { - boolean[] tmp = viewProperties.get(holder.getAdapterPosition()); - if (tmp[isQuoteButtonChecked]) { - if (toQuoteList.contains(currentPost.getPostNumber())) { - toQuoteList.remove(toQuoteList.indexOf(currentPost.getPostNumber())); - } else - Report.i(TAG, "An error occurred while trying to exclude post from" + - "toQuoteList, post wasn't there!"); - holder.quoteToggle.setImageResource(R.drawable.ic_format_quote_unchecked); - } else { - toQuoteList.add(currentPost.getPostNumber()); - holder.quoteToggle.setImageResource(R.drawable.ic_format_quote_checked); - } - tmp[isQuoteButtonChecked] = !tmp[isQuoteButtonChecked]; - viewProperties.set(holder.getAdapterPosition(), tmp); + if (holder.quickReply.getText().toString().isEmpty()) return; + holder.submitButton.setEnabled(false); + replyTask.execute(holder.quickReply.getText().toString()); } }); } - //Card expand/collapse when card is touched - holder.cardView.setOnClickListener(new View.OnClickListener() { - @Override - public void onClick(View view) { - //Change post's viewProperties accordingly - boolean[] tmp = viewProperties.get(holder.getAdapterPosition()); - tmp[isPostDateAndNumberVisibile] = !tmp[isPostDateAndNumberVisibile]; - viewProperties.set(holder.getAdapterPosition(), tmp); - - TopicAnimations.animatePostExtraInfoVisibility(holder.postDateAndNumberExp - , holder.username, holder.subject - , Color.parseColor("#FFFFFF") - , Color.parseColor("#757575")); - } - }); - //Also when post is clicked - holder.post.setOnTouchListener(new CustomTouchListener(holder.post, holder.cardView)); } void customNotifyDataSetChanged(TopicActivity.TopicTask topicTask) { @@ -452,6 +445,68 @@ class TopicAdapter extends RecyclerView.Adapter { return postsList.size(); } + /** + * Custom {@link RecyclerView.ViewHolder} implementation + */ + private class PostViewHolder extends RecyclerView.ViewHolder { + final CardView cardView; + final LinearLayout cardChildLinear; + final FrameLayout postDateAndNumberExp; + final TextView postDate, postNum, username, subject; + final ImageView thumbnail; + final public WebView post; + final ImageButton quoteToggle; + final RelativeLayout header; + final LinearLayout userExtraInfo; + final View bodyFooterDivider; + final LinearLayout postFooter; + + final TextView specialRank, rank, gender, numberOfPosts, personalText, stars; + + PostViewHolder(View view) { + super(view); + //Initializes layout's graphic elements + //Standard stuff + cardView = (CardView) view.findViewById(R.id.card_view); + cardChildLinear = (LinearLayout) view.findViewById(R.id.card_child_linear); + postDateAndNumberExp = (FrameLayout) view.findViewById(R.id.post_date_and_number_exp); + postDate = (TextView) view.findViewById(R.id.post_date); + postNum = (TextView) view.findViewById(R.id.post_number); + thumbnail = (ImageView) view.findViewById(R.id.thumbnail); + username = (TextView) view.findViewById(R.id.username); + subject = (TextView) view.findViewById(R.id.subject); + post = (WebView) view.findViewById(R.id.post); + post.setBackgroundColor(Color.argb(1, 255, 255, 255)); + quoteToggle = (ImageButton) view.findViewById(R.id.toggle_quote_button); + bodyFooterDivider = view.findViewById(R.id.body_footer_divider); + postFooter = (LinearLayout) view.findViewById(R.id.post_footer); + + //User's extra info + header = (RelativeLayout) view.findViewById(R.id.header); + userExtraInfo = (LinearLayout) view.findViewById(R.id.user_extra_info); + specialRank = (TextView) view.findViewById(R.id.special_rank); + rank = (TextView) view.findViewById(R.id.rank); + gender = (TextView) view.findViewById(R.id.gender); + numberOfPosts = (TextView) view.findViewById(R.id.number_of_posts); + personalText = (TextView) view.findViewById(R.id.personal_text); + stars = (TextView) view.findViewById(R.id.stars); + } + } + + /** + * Custom {@link RecyclerView.ViewHolder} implementation + */ + private static class QuickReplyViewHolder extends RecyclerView.ViewHolder { + final EditText quickReply; + final AppCompatImageButton submitButton; + + QuickReplyViewHolder(View quickReply) { + super(quickReply); + this.quickReply = (EditText) quickReply.findViewById(R.id.quick_reply_text); + submitButton = (AppCompatImageButton) quickReply.findViewById(R.id.quick_reply_submit); + } + } + /** * This class is a gesture detector for WebViews. It handles post's clicks, long clicks and * touch and drag. @@ -592,6 +647,7 @@ class TopicAdapter extends RecyclerView.Adapter { //Method always returns true as no url should be loaded in the WebViews return true; } + } /** diff --git a/app/src/main/res/layout/activity_topic_post_row.xml b/app/src/main/res/layout/activity_topic_post_row.xml index 6c56547e..13e53227 100644 --- a/app/src/main/res/layout/activity_topic_post_row.xml +++ b/app/src/main/res/layout/activity_topic_post_row.xml @@ -1,12 +1,13 @@ - + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index dffad4fe..b1d04389 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -44,6 +44,8 @@ Page next last + Quick reply… + Submit Username From 48583ccba361672c88d5e984edc3f92bb255ab61 Mon Sep 17 00:00:00 2001 From: Apostolof Date: Wed, 22 Feb 2017 23:43:58 +0200 Subject: [PATCH 05/18] Topic reply fixes. --- .../activities/topic/TopicActivity.java | 35 ++++-------- .../mthmmy/activities/topic/TopicAdapter.java | 50 +++++++++++++++--- app/src/main/res/drawable-hdpi/ic_send.png | Bin 0 -> 324 bytes app/src/main/res/drawable-mdpi/ic_send.png | Bin 0 -> 257 bytes app/src/main/res/drawable-xhdpi/ic_send.png | Bin 0 -> 419 bytes app/src/main/res/drawable-xxhdpi/ic_send.png | Bin 0 -> 553 bytes app/src/main/res/drawable-xxxhdpi/ic_send.png | Bin 0 -> 729 bytes 7 files changed, 53 insertions(+), 32 deletions(-) create mode 100644 app/src/main/res/drawable-hdpi/ic_send.png create mode 100644 app/src/main/res/drawable-mdpi/ic_send.png create mode 100644 app/src/main/res/drawable-xhdpi/ic_send.png create mode 100644 app/src/main/res/drawable-xxhdpi/ic_send.png create mode 100644 app/src/main/res/drawable-xxxhdpi/ic_send.png diff --git a/app/src/main/java/gr/thmmy/mthmmy/activities/topic/TopicActivity.java b/app/src/main/java/gr/thmmy/mthmmy/activities/topic/TopicActivity.java index 92cc5317..e6860ff0 100644 --- a/app/src/main/java/gr/thmmy/mthmmy/activities/topic/TopicActivity.java +++ b/app/src/main/java/gr/thmmy/mthmmy/activities/topic/TopicActivity.java @@ -9,7 +9,6 @@ import android.support.design.widget.FloatingActionButton; import android.support.v7.widget.LinearLayoutManager; import android.support.v7.widget.RecyclerView; import android.support.v7.widget.Toolbar; -import android.util.Log; import android.util.SparseArray; import android.view.MotionEvent; import android.view.View; @@ -25,8 +24,6 @@ import org.jsoup.nodes.Element; import org.jsoup.select.Selector; import java.io.IOException; -import java.io.UnsupportedEncodingException; -import java.net.URLEncoder; import java.util.ArrayList; import java.util.Objects; @@ -578,17 +575,11 @@ public class TopicActivity extends BaseActivity { Response response = client.newCall(request).execute(); document = Jsoup.parse(response.body().string()); - //https://www.thmmy.gr/smf/index.php?action=post;topic=67565.15;num_replies=27 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"); subject = document.select("input[name=subject]").first().attr("value"); topic = document.select("input[name=topic]").first().attr("value"); - Log.d(TAG, "numReplies " + numReplies + "\n" - + "seqnum " + seqnum + "\n" - + "sc " + sc + "\n" - + "subject " + subject + "\n" - + "topic " + topic + "\n"); } catch (IOException e) { Report.i(TAG, "Post failed.", e); return false; @@ -597,22 +588,17 @@ public class TopicActivity extends BaseActivity { return false; } - Log.d(TAG, message[0]); RequestBody postBody = null; - try { - postBody = new MultipartBody.Builder() - .setType(MultipartBody.FORM) - .addFormDataPart("message", URLEncoder.encode(message[0], "UTF-8")) - .addFormDataPart("num_replies", numReplies) - .addFormDataPart("seqnum", seqnum) - .addFormDataPart("sc", sc) - .addFormDataPart("subject", subject) - .addFormDataPart("topic", topic) - .addFormDataPart("goback", "1") - .build(); - } catch (UnsupportedEncodingException e) { - e.printStackTrace(); - } + + postBody = new MultipartBody.Builder() + .setType(MultipartBody.FORM) + .addFormDataPart("message", message[0]) + .addFormDataPart("num_replies", numReplies) + .addFormDataPart("seqnum", seqnum) + .addFormDataPart("sc", sc) + .addFormDataPart("subject", subject) + .addFormDataPart("topic", topic) + .build(); Request post = new Request.Builder() .url("https://www.thmmy.gr/smf/index.php?action=post2") @@ -621,6 +607,7 @@ public class TopicActivity extends BaseActivity { .build(); try { + client.newCall(post).execute(); client.newCall(post).execute(); return true; } catch (IOException e) { diff --git a/app/src/main/java/gr/thmmy/mthmmy/activities/topic/TopicAdapter.java b/app/src/main/java/gr/thmmy/mthmmy/activities/topic/TopicAdapter.java index d989f608..230388be 100644 --- a/app/src/main/java/gr/thmmy/mthmmy/activities/topic/TopicAdapter.java +++ b/app/src/main/java/gr/thmmy/mthmmy/activities/topic/TopicAdapter.java @@ -33,9 +33,14 @@ import android.widget.TextView; import com.squareup.picasso.Picasso; +import java.text.DateFormat; +import java.text.ParseException; +import java.text.SimpleDateFormat; import java.util.ArrayList; +import java.util.Calendar; import java.util.Date; import java.util.List; +import java.util.Locale; import java.util.Objects; import gr.thmmy.mthmmy.R; @@ -355,7 +360,7 @@ class TopicAdapter extends RecyclerView.Adapter { holder.subject.setEllipsize(TextUtils.TruncateAt.END); } //noinspection PointlessBooleanExpression,ConstantConditions - if (!BaseActivity.getSessionManager().isLoggedIn() || true) //Hide it until reply is implemented + if (!BaseActivity.getSessionManager().isLoggedIn()) holder.quoteToggle.setVisibility(View.GONE); else { if (viewProperties.get(position)[isQuoteButtonChecked]) @@ -368,14 +373,14 @@ class TopicAdapter extends RecyclerView.Adapter { public void onClick(View view) { boolean[] tmp = viewProperties.get(holder.getAdapterPosition()); if (tmp[isQuoteButtonChecked]) { - if (toQuoteList.contains(currentPost.getPostNumber())) { - toQuoteList.remove(toQuoteList.indexOf(currentPost.getPostNumber())); + if (toQuoteList.contains(postsList.indexOf(currentPost))) { + toQuoteList.remove(toQuoteList.indexOf(postsList.indexOf(currentPost))); } else Report.i(TAG, "An error occurred while trying to exclude post from" + "toQuoteList, post wasn't there!"); holder.quoteToggle.setImageResource(R.drawable.ic_format_quote_unchecked); } else { - toQuoteList.add(currentPost.getPostNumber()); + toQuoteList.add(postsList.indexOf(currentPost)); holder.quoteToggle.setImageResource(R.drawable.ic_format_quote_checked); } tmp[isQuoteButtonChecked] = !tmp[isQuoteButtonChecked]; @@ -406,15 +411,44 @@ class TopicAdapter extends RecyclerView.Adapter { //Build quotes String quotes = ""; for (int quotePosition : toQuoteList) { - //Date postDate = new Date(); - Log.d(TAG, postsList.get(quotePosition).getPostDate()); + Date postDate = null; + { + String date = postsList.get(quotePosition).getPostDate(); + if (date != null) { + DateFormat format = new SimpleDateFormat("MMMM d, yyyy, h:m:s a", Locale.ENGLISH); + if (date.contains("Today")) { + date = date.replace("Today at", + Calendar.getInstance().getDisplayName(Calendar.MONTH, + Calendar.LONG, Locale.ENGLISH) + + " " + Calendar.getInstance().get(Calendar.DAY_OF_MONTH) + + ", " + Calendar.getInstance().get(Calendar.YEAR) + ","); + } else if (date.contains("Σήμερα")) { + date = date.replace("Σήμερα στις", + Calendar.getInstance().getDisplayName(Calendar.MONTH, + Calendar.LONG, Locale.ENGLISH) + + " " + Calendar.getInstance().get(Calendar.DAY_OF_MONTH) + + ", " + Calendar.getInstance().get(Calendar.YEAR) + ","); + if (date.contains("πμ")) date = date.replace("πμ", "am"); + if (date.contains("μμ")) date = date.replace("μμ", "pm"); + } + + Log.d(TAG, date); + + try { + postDate = format.parse(date); + } catch (ParseException e) { + e.printStackTrace(); + } + } + } if (postsList.get(quotePosition).getPostIndex() != 0) { + assert postDate != null; quotes += "[quote author=" + postsList.get(quotePosition).getAuthor() + " link=topic=68525.msg" + postsList.get(quotePosition).getPostIndex() + "#msg" + postsList.get(quotePosition).getPostIndex() - + " date=" + "1000" + + " date=" + postDate.getTime() / 1000 + "]" + "\n" + postsList.get(quotePosition).getContent() - + "\n" + "[/quote]" + "\n"; + + "\n" + "[/quote]" + "\n\n"; } } holder.quickReply.setText(quotes); diff --git a/app/src/main/res/drawable-hdpi/ic_send.png b/app/src/main/res/drawable-hdpi/ic_send.png new file mode 100644 index 0000000000000000000000000000000000000000..a8fd035d0d23fcac869997482ed1d5395d0aba82 GIT binary patch literal 324 zcmV-K0lWT*P)S35LzoYFzo zat0lwo>Oy>N=_St0_C(hNR;#Sg)|DNp^YIH*y0pMPCtE<$e@Gvy;e@m-w^4i z`;=3AP!V->Fv1eM9|jr8pj)ym%4nj8Db_d$lFd;0mQ4CC{d}qW$hmOY8_8v_{loY+ zOBA<`k6FUJxtgeNuA(fq9?-;Dv>#zj)Q_<0S%MsctYncK6pbqfMdyyv@xLGOAiu69 Wl6gt;kN*e&00009pV literal 0 HcmV?d00001 diff --git a/app/src/main/res/drawable-mdpi/ic_send.png b/app/src/main/res/drawable-mdpi/ic_send.png new file mode 100644 index 0000000000000000000000000000000000000000..c914ae97b6e506d6abf13cd9ddf7898d7d02a255 GIT binary patch literal 257 zcmV+c0sj7pP)XltOlag`CJFo`J@BleA)r$e9?zAim0QD zF_zfjqRr>}vJ%LliZ+IrV}s+Te3F4YYUp5u1-3ZF3`|gtOH@JwJ%m_cFG$o!#^NP6 zk@WqUJ~R0K(Oxq6Ix5~~_~x*4%Ah%}MHwU)jw-|d+{q?xDVxL}pq;B600000NkvXX Hu0mjfQ|oRn literal 0 HcmV?d00001 diff --git a/app/src/main/res/drawable-xhdpi/ic_send.png b/app/src/main/res/drawable-xhdpi/ic_send.png new file mode 100644 index 0000000000000000000000000000000000000000..c104e00d0a84603d3118c9a63980483b69620d7f GIT binary patch literal 419 zcmV;U0bKrxP)uJTkr|g48teTQc+`w)9g$p6HJnO?|aw0 z;xy?_a`N)tO*TL5XP(KDKoUp-|4-l=wqU}mz$fJJ42Lk|Rba$B3}MBqK#|+n@~XP{ z^@~7W$m<}6yqXG>^IG;Q5IiqQfpT8cp#*XvO!CqcFv-hGKrJt8fnr_*iM&Dy6uE)T zrg_C6&?>L0i<7Vb>#z$aZ~+hSVVGA(<2*11v#<)=a0F*?2QMM=l3tg!p57Dms`9ej zw@5s_w{l+A0&}niJ8%r=a1XCF1WsW|GoeM;fIaBLB|Hiwv=37fFLB$uSobCF!g$?f zRO2q@O*8TGA^UNq@vxQXdfQ5jGU<5R%r(j+27y*P&X7mSfkY+Nh?BbGoBH}!-f z!Jt)X%u^K8IaNF&nIzScIMvLAH?SmiC2=lsIihiS-;&k4qWFJ3-&g*=I=*1hNx!?7 zFWZ0LYIV4-yQf`9qoWCq>WY}RInHkC`pLvu!DwsX?Rc~)$nJo^nt*_f3v|jiJ_!#E zm~`^J#*;sgkvQC`O?YQi7vF?eOy8VA=SUA+y?PFbe z-hc9fnmS{VFXeU2_kU)JO?fJo^Yg^{E`|J`k-|@G>{mC%iwpSUoKN|`dbPgvm)G;>kKcuy{_2#RBm7^JIJ|%f&al;M#uDolTJz93CwSr?RGHvH+9N3 zWcrF{uGG}1o_LRC^1gr1V*MP~_AJR0G4*j&{vT2*XKLc-IJM_iO~l%XfjUiE=^}@@ zH%CdfYG|BYar>cm_|G1vpKp|>O$>EBXS7M}M5S98OXcsXRkeRpA6P5*a))HPEfZhi zwlQT%VrOuvo89#W-;^iG6Yqq$t?N^oan|FPLHEy|C4J7UlLIHSzuKc8nq@ml^2^K( ptD4p&pX@k(ND~nw0Rfr&7y}cY`f6y(?*}FU22WQ%mvv4FO#s$F^FaUr literal 0 HcmV?d00001 diff --git a/app/src/main/res/drawable-xxxhdpi/ic_send.png b/app/src/main/res/drawable-xxxhdpi/ic_send.png new file mode 100644 index 0000000000000000000000000000000000000000..ca6a867c3e419748826014293e63d0906bb973cb GIT binary patch literal 729 zcmV;~0w(>5P)fgS;3T_`w$h7bsP1W6SGh*?qmQRP;R zeAO(ov;U8N!ONxy=5@badU|@tI^Cr)u!Ea`00aO65C8~303ZMXfB*!5GXWdoiJ0Jq z*$CJdhvKJrBd&4dYy|Y_i4}2|8)ze-$`|s~zJT620{ZNT*W}4g0C{pEpvsnbOrGon zkf$LD_|;HAHBZar$xZ-yawLE}4Itp4MFGe2bO!-80#3`*Wdzs==<`Fo5?2vmBcO;p z)w$@mv4AR@;!&nNMH7%NPf-O_^VE%;r#ct?aV#Kwo-zptnWu~bLggv5fDn1AbJ1ZU zj`H-#XGSkzKXpT1-uuxN=nd8F)N;n zCGkmY8zkt3xRUWhc+{hK&=28<;!^alp&mwY!pZDqxd43FD5BCt%+GS=bB}v zpgW*TdPT`)X0pGe=RPx8UsDZ}nQSj=hs#V;0UnMj=tj;=Q~_x+6HUNY zC)s%r5d@^pOj7}EA6b_EOdyW}ipq=^0pU+Ju@cZDGjWeDCNl Date: Fri, 24 Feb 2017 22:13:27 +0200 Subject: [PATCH 06/18] Topic reply. --- .../mthmmy/activities/topic/ReplyParser.java | 50 +++++ .../activities/topic/TopicActivity.java | 43 ++-- .../mthmmy/activities/topic/TopicAdapter.java | 184 +++++++++++++----- .../res/layout/activity_topic_post_row.xml | 3 +- .../layout/activity_topic_quick_reply_row.xml | 99 ++++++++-- app/src/main/res/values/strings.xml | 1 + 6 files changed, 294 insertions(+), 86 deletions(-) create mode 100644 app/src/main/java/gr/thmmy/mthmmy/activities/topic/ReplyParser.java diff --git a/app/src/main/java/gr/thmmy/mthmmy/activities/topic/ReplyParser.java b/app/src/main/java/gr/thmmy/mthmmy/activities/topic/ReplyParser.java new file mode 100644 index 00000000..4950478b --- /dev/null +++ b/app/src/main/java/gr/thmmy/mthmmy/activities/topic/ReplyParser.java @@ -0,0 +1,50 @@ +package gr.thmmy.mthmmy.activities.topic; + +import android.util.Log; + +import org.jsoup.Jsoup; +import org.jsoup.nodes.Document; + +import java.io.IOException; + +import okhttp3.Response; + +class ReplyParser { + /** + * Debug Tag for logging debug output to LogCat + */ + @SuppressWarnings("unused") + private static final String TAG = "ReplyParser"; + + enum REPLY_STATUS { + SUCCESSFUL, NO_SUBJECT, EMPTY_BODY, NEW_REPLY_WHILE_POSTING, NOT_FOUND, SESSION_ENDED, OTHER_ERROR + } + + static REPLY_STATUS replyStatus(Response response) throws IOException { + if (response.code() == 404) return REPLY_STATUS.NOT_FOUND; + if (response.code() < 200 || response.code() >= 400) return REPLY_STATUS.OTHER_ERROR; + String finalUrl = response.request().url().toString(); + if (finalUrl.contains("action=post")) { + Document postErrorPage = Jsoup.parse(response.body().string()); + String[] errors = postErrorPage.select("tr[id=errors] div[id=error_list]").first() + .toString().split("
"); + for (int i = 0; i < errors.length; ++i) { //TODO test + Log.d("TAG", String.valueOf(i)); + Log.d("TAG", errors[i]); + } + for (String error : errors) { + if (error.contains("Your session timed out while posting") || + error.contains("Υπερβήκατε τον μέγιστο χρόνο σύνδεσης κατά την αποστολή")) + return REPLY_STATUS.SESSION_ENDED; + if (error.contains("No subject was filled in") + || error.contains("Δεν δόθηκε τίτλος")) + return REPLY_STATUS.NO_SUBJECT; + if (error.contains("The message body was left empty") + || error.contains("Δεν δόθηκε κείμενο για το μήνυμα")) + return REPLY_STATUS.EMPTY_BODY; + } + return REPLY_STATUS.NEW_REPLY_WHILE_POSTING; + } + return REPLY_STATUS.SUCCESSFUL; + } +} diff --git a/app/src/main/java/gr/thmmy/mthmmy/activities/topic/TopicActivity.java b/app/src/main/java/gr/thmmy/mthmmy/activities/topic/TopicActivity.java index e6860ff0..7f0393a9 100644 --- a/app/src/main/java/gr/thmmy/mthmmy/activities/topic/TopicActivity.java +++ b/app/src/main/java/gr/thmmy/mthmmy/activities/topic/TopicActivity.java @@ -40,6 +40,8 @@ import okhttp3.Request; import okhttp3.RequestBody; import okhttp3.Response; +import static gr.thmmy.mthmmy.activities.topic.ReplyParser.replyStatus; + /** * Activity for topics. When creating an Intent of this activity you need to bundle a String * containing this topics's url using the key {@link #BUNDLE_TOPIC_URL} and a String containing @@ -84,6 +86,7 @@ public class TopicActivity extends BaseActivity { private static final int LARGE_STEP = 10; private Integer pageRequestValue; //Bottom navigation graphics + LinearLayout bottomNavBar; private ImageButton firstPage; private ImageButton previousPage; private TextView pageIndicator; @@ -136,12 +139,12 @@ public class TopicActivity extends BaseActivity { recyclerView.setHasFixedSize(true); LinearLayoutManager layoutManager = new LinearLayoutManager(getApplicationContext()); recyclerView.setLayoutManager(layoutManager); - topicAdapter = new TopicAdapter(this, postsList, topicTask); + topicAdapter = new TopicAdapter(this, postsList, topicTask, topicTitle); recyclerView.setAdapter(topicAdapter); replyFAB = (FloatingActionButton) findViewById(R.id.topic_fab); replyFAB.setEnabled(false); - final LinearLayout bottomNavBar = (LinearLayout) findViewById(R.id.bottom_navigation_bar); + bottomNavBar = (LinearLayout) findViewById(R.id.bottom_navigation_bar); if (!sessionManager.isLoggedIn()) replyFAB.hide(); else { replyFAB.setOnClickListener(new View.OnClickListener() { @@ -341,7 +344,7 @@ public class TopicActivity extends BaseActivity { paginationEnabled(true); changePage(pageRequestValue - 1); } else if (event.getAction() == MotionEvent.ACTION_MOVE) { - if (!rect.contains(v.getLeft() + (int) event.getX(), v.getTop() + (int) event.getY())) { + if (!rect.contains(v.getLeft() + (int) event.getX(), v.getTop() + (int) event.getY())) { //TODO fix bug autoIncrement = false; incrementPageRequestValue(thisPage - pageRequestValue); paginationEnabled(true); @@ -437,11 +440,12 @@ public class TopicActivity extends BaseActivity { return SAME_PAGE; } } - } else if (Integer.parseInt(newPageUrl.substring(base_url.length() + 1)) / 15 + 1 == thisPage) + } else if (Integer.parseInt(newPageUrl.substring(base_url.length() + 1)) / 15 + 1 == thisPage) //TODO fix bug return SAME_PAGE; } else if (!Objects.equals(loadedPageUrl, "")) topicTitle = null; loadedPageUrl = newPageUrl; + replyPageUrl = null; Request request = new Request.Builder() .url(newPageUrl) .build(); @@ -477,7 +481,7 @@ public class TopicActivity extends BaseActivity { progressBar.setVisibility(ProgressBar.INVISIBLE); topicAdapter.customNotifyDataSetChanged(new TopicTask()); - if (replyPageUrl == null) replyFAB.setVisibility(View.GONE); + if (replyPageUrl == null) replyFAB.hide(); if (replyFAB.getVisibility() != View.GONE) replyFAB.setEnabled(true); //Set current page @@ -521,6 +525,8 @@ public class TopicActivity extends BaseActivity { //Find reply page url { Element replyButton = topic.select("a:has(img[alt=Reply])").first(); + if (replyButton == null) + replyButton = topic.select("a:has(img[alt=Απάντηση])").first(); if (replyButton != null) replyPageUrl = replyButton.attr("href"); } @@ -581,16 +587,14 @@ public class TopicActivity extends BaseActivity { subject = document.select("input[name=subject]").first().attr("value"); topic = document.select("input[name=topic]").first().attr("value"); } catch (IOException e) { - Report.i(TAG, "Post failed.", e); + Report.e(TAG, "Post failed.", e); return false; } catch (Selector.SelectorParseException e) { Report.e(TAG, "Post failed.", e); return false; } - RequestBody postBody = null; - - postBody = new MultipartBody.Builder() + RequestBody postBody = new MultipartBody.Builder() .setType(MultipartBody.FORM) .addFormDataPart("message", message[0]) .addFormDataPart("num_replies", numReplies) @@ -608,10 +612,19 @@ public class TopicActivity extends BaseActivity { try { client.newCall(post).execute(); - client.newCall(post).execute(); - return true; + Response response = client.newCall(post).execute(); + switch (replyStatus(response)) { + case SUCCESSFUL: + return true; + case NEW_REPLY_WHILE_POSTING: + //TODO this... + return true; + default: + Report.e(TAG, "Malformed post. Request string:\n" + post.toString()); + return true; + } } catch (IOException e) { - Report.i(TAG, "Post failed.", e); + Report.e(TAG, "Post failed.", e); return false; } } @@ -619,6 +632,12 @@ public class TopicActivity extends BaseActivity { @Override protected void onPostExecute(Boolean result) { 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); } } } \ No newline at end of file diff --git a/app/src/main/java/gr/thmmy/mthmmy/activities/topic/TopicAdapter.java b/app/src/main/java/gr/thmmy/mthmmy/activities/topic/TopicAdapter.java index 230388be..035933cf 100644 --- a/app/src/main/java/gr/thmmy/mthmmy/activities/topic/TopicAdapter.java +++ b/app/src/main/java/gr/thmmy/mthmmy/activities/topic/TopicAdapter.java @@ -10,12 +10,14 @@ import android.net.Uri; import android.os.Build; import android.os.Bundle; import android.support.annotation.NonNull; +import android.support.annotation.Nullable; import android.support.v4.content.res.ResourcesCompat; import android.support.v7.widget.AppCompatImageButton; import android.support.v7.widget.CardView; import android.support.v7.widget.RecyclerView; +import android.text.Editable; import android.text.TextUtils; -import android.util.Log; +import android.text.TextWatcher; import android.view.LayoutInflater; import android.view.MotionEvent; import android.view.View; @@ -59,6 +61,7 @@ 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.base.BaseActivity.getSessionManager; /** * Custom {@link android.support.v7.widget.RecyclerView.Adapter} used for topics. @@ -73,6 +76,7 @@ class TopicAdapter extends RecyclerView.Adapter { */ private static int THUMBNAIL_SIZE; private final Context context; + private String topicTitle; private ArrayList toQuoteList = new ArrayList<>(); private final List postsList; /** @@ -99,13 +103,16 @@ class TopicAdapter extends RecyclerView.Adapter { private TopicActivity.ReplyTask replyTask; private final int VIEW_TYPE_POST = 0; private final int VIEW_TYPE_QUICK_REPLY = 1; - private boolean firstTime = false; + + private String[] replyDataHolder = new String[2]; + private int replySubject = 0, replyText = 1; /** * @param context the context of the {@link RecyclerView} * @param postsList List of {@link Post} objects to use */ - TopicAdapter(Context context, List postsList, TopicActivity.TopicTask topicTask) { + TopicAdapter(Context context, List postsList, TopicActivity.TopicTask topicTask + , String topicTitle) { this.context = context; this.postsList = postsList; @@ -115,11 +122,11 @@ class TopicAdapter extends RecyclerView.Adapter { viewProperties.add(new boolean[3]); } this.topicTask = topicTask; + this.topicTitle = topicTitle; } void prepareForReply(TopicActivity.ReplyTask replyTask) { this.replyTask = replyTask; - firstTime = true; } @Override @@ -136,12 +143,22 @@ class TopicAdapter extends RecyclerView.Adapter { } else if (viewType == VIEW_TYPE_QUICK_REPLY) { View view = LayoutInflater.from(parent.getContext()). inflate(R.layout.activity_topic_quick_reply_row, parent, false); - return new QuickReplyViewHolder(view); + //Default post subject + replyDataHolder[replySubject] = "Re: " + topicTitle; + //Build quotes + String quotes = ""; + for (int quotePosition : toQuoteList) { + quotes += buildQuote(quotePosition); + } + if (!Objects.equals(quotes, "")) + replyDataHolder[replyText] = quotes; + return new QuickReplyViewHolder(view, new CustomEditTextListener(replySubject), + new CustomEditTextListener(replyText)); } return null; } - @SuppressLint("SetJavaScriptEnabled") + @SuppressLint({"SetJavaScriptEnabled", "SetTextI18n"}) @Override public void onBindViewHolder(final RecyclerView.ViewHolder currentHolder, final int position) { if (currentHolder instanceof PostViewHolder) { @@ -407,52 +424,24 @@ class TopicAdapter extends RecyclerView.Adapter { holder.post.setOnTouchListener(new CustomTouchListener(holder.post, holder.cardView)); } else if (currentHolder instanceof QuickReplyViewHolder) { final QuickReplyViewHolder holder = (QuickReplyViewHolder) currentHolder; - if (firstTime) { - //Build quotes - String quotes = ""; - for (int quotePosition : toQuoteList) { - Date postDate = null; - { - String date = postsList.get(quotePosition).getPostDate(); - if (date != null) { - DateFormat format = new SimpleDateFormat("MMMM d, yyyy, h:m:s a", Locale.ENGLISH); - if (date.contains("Today")) { - date = date.replace("Today at", - Calendar.getInstance().getDisplayName(Calendar.MONTH, - Calendar.LONG, Locale.ENGLISH) - + " " + Calendar.getInstance().get(Calendar.DAY_OF_MONTH) - + ", " + Calendar.getInstance().get(Calendar.YEAR) + ","); - } else if (date.contains("Σήμερα")) { - date = date.replace("Σήμερα στις", - Calendar.getInstance().getDisplayName(Calendar.MONTH, - Calendar.LONG, Locale.ENGLISH) - + " " + Calendar.getInstance().get(Calendar.DAY_OF_MONTH) - + ", " + Calendar.getInstance().get(Calendar.YEAR) + ","); - if (date.contains("πμ")) date = date.replace("πμ", "am"); - if (date.contains("μμ")) date = date.replace("μμ", "pm"); - } - - Log.d(TAG, date); - - try { - postDate = format.parse(date); - } catch (ParseException e) { - e.printStackTrace(); - } - } - } - if (postsList.get(quotePosition).getPostIndex() != 0) { - assert postDate != null; - quotes += "[quote author=" + postsList.get(quotePosition).getAuthor() - + " link=topic=68525.msg" + postsList.get(quotePosition).getPostIndex() - + "#msg" + postsList.get(quotePosition).getPostIndex() - + " date=" + postDate.getTime() / 1000 + "]" - + "\n" + postsList.get(quotePosition).getContent() - + "\n" + "[/quote]" + "\n\n"; - } - } - holder.quickReply.setText(quotes); - } + + //noinspection ConstantConditions + Picasso.with(context) + .load(getSessionManager().getAvatarLink()) + .resize(THUMBNAIL_SIZE, THUMBNAIL_SIZE) + .centerCrop() + .error(ResourcesCompat.getDrawable(context.getResources() + , R.drawable.ic_default_user_thumbnail, null)) + .placeholder(ResourcesCompat.getDrawable(context.getResources() + , R.drawable.ic_default_user_thumbnail, null)) + .transform(new CircleTransform()) + .into(holder.thumbnail); + holder.username.setText(getSessionManager().getUsername()); + holder.quickReplySubject.setText(replyDataHolder[replySubject]); + + if (replyDataHolder[replyText] != null && !Objects.equals(replyDataHolder[replyText], "")) + holder.quickReply.setText(replyDataHolder[replyText]); + holder.submitButton.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { @@ -531,12 +520,23 @@ class TopicAdapter extends RecyclerView.Adapter { * Custom {@link RecyclerView.ViewHolder} implementation */ private static class QuickReplyViewHolder extends RecyclerView.ViewHolder { - final EditText quickReply; + final ImageView thumbnail; + final TextView username; + final EditText quickReply, quickReplySubject; final AppCompatImageButton submitButton; + final CustomEditTextListener replySubject, replyText; - QuickReplyViewHolder(View quickReply) { + QuickReplyViewHolder(View quickReply, CustomEditTextListener replySubject + , CustomEditTextListener replyText) { super(quickReply); + thumbnail = (ImageView) quickReply.findViewById(R.id.thumbnail); + username = (TextView) quickReply.findViewById(R.id.username); this.quickReply = (EditText) quickReply.findViewById(R.id.quick_reply_text); + this.replyText = replyText; + this.quickReply.addTextChangedListener(replyText); + quickReplySubject = (EditText) quickReply.findViewById(R.id.quick_reply_subject); + this.replySubject = replySubject; + quickReplySubject.addTextChangedListener(replySubject); submitButton = (AppCompatImageButton) quickReply.findViewById(R.id.quick_reply_submit); } } @@ -684,6 +684,82 @@ class TopicAdapter extends RecyclerView.Adapter { } + private class CustomEditTextListener implements TextWatcher { + private int positionInDataHolder; + + CustomEditTextListener(int positionInDataHolder) { + this.positionInDataHolder = positionInDataHolder; + } + + @Override + public void beforeTextChanged(CharSequence charSequence, int i, int i2, int i3) { + } + + @Override + public void onTextChanged(CharSequence charSequence, int i, int i2, int i3) { + replyDataHolder[positionInDataHolder] = charSequence.toString(); + } + + @Override + public void afterTextChanged(Editable editable) { + } + } + + @Nullable + private String buildQuote(int quotePosition) { + Date postDate = null; + { + String date = postsList.get(quotePosition).getPostDate(); + if (date != null) { + DateFormat format = new SimpleDateFormat("MMMM d, yyyy, h:m:s a", Locale.ENGLISH); + date = date.replace("Ιανουαρίου", "January"); + date = date.replace("Φεβρουαρίου", "February"); + date = date.replace("Μαρτίου", "March"); + date = date.replace("Απριλίου", "April"); + date = date.replace("Μαΐου", "May"); + date = date.replace("Ιουνίου", "June"); + date = date.replace("Ιουλίου", "July"); + date = date.replace("Αυγούστου", "August"); + date = date.replace("Σεπτεμβρίου", "September"); + date = date.replace("Οκτωβρίου", "October"); + date = date.replace("Νοεμβρίου", "November"); + date = date.replace("Δεκεμβρίου", "December"); + + if (date.contains("Today")) { + date = date.replace("Today at", + Calendar.getInstance().getDisplayName(Calendar.MONTH, + Calendar.LONG, Locale.ENGLISH) + + " " + Calendar.getInstance().get(Calendar.DAY_OF_MONTH) + + ", " + Calendar.getInstance().get(Calendar.YEAR) + ","); + } else if (date.contains("Σήμερα")) { + date = date.replace("Σήμερα στις", + Calendar.getInstance().getDisplayName(Calendar.MONTH, + Calendar.LONG, Locale.ENGLISH) + + " " + Calendar.getInstance().get(Calendar.DAY_OF_MONTH) + + ", " + Calendar.getInstance().get(Calendar.YEAR) + ","); + if (date.contains("πμ")) date = date.replace("πμ", "am"); + if (date.contains("μμ")) date = date.replace("μμ", "pm"); + } + try { + postDate = format.parse(date); + } catch (ParseException e) { + e.printStackTrace(); + } + } + } + if (postsList.get(quotePosition).getPostIndex() != 0) { + if (postDate != null) { + return "[quote author=" + postsList.get(quotePosition).getAuthor() + + " link=topic=68525.msg" + postsList.get(quotePosition).getPostIndex() + + "#msg" + postsList.get(quotePosition).getPostIndex() + + " date=" + postDate.getTime() / 1000 + "]" + + "\n" + postsList.get(quotePosition).getContent() + + "\n" + "[/quote]" + "\n\n"; + } + } + return null; + } + /** * Returns a String with a single FontAwesome typeface character corresponding to this file's * extension. diff --git a/app/src/main/res/layout/activity_topic_post_row.xml b/app/src/main/res/layout/activity_topic_post_row.xml index 13e53227..677a58db 100644 --- a/app/src/main/res/layout/activity_topic_post_row.xml +++ b/app/src/main/res/layout/activity_topic_post_row.xml @@ -115,8 +115,7 @@ android:layout_toEndOf="@+id/thumbnail_holder" android:ellipsize="end" android:maxLines="1" - android:text="@string/post_subject" - /> + android:text="@string/post_subject"/> @@ -22,32 +23,94 @@ + android:orientation="vertical"> - + android:clickable="true" + android:paddingLeft="16dp" + android:paddingRight="16dp" + android:paddingTop="16dp"> + + + + + + + - + android:layout_below="@+id/username" + android:layout_toEndOf="@+id/thumbnail_holder" + android:hint="@string/quick_reply_subject" + android:inputType="textMultiLine" + android:maxLength="80" + android:textSize="10sp"/> + - + android:orientation="horizontal" + android:paddingLeft="16dp" + android:paddingRight="16dp"> + + + + + + + +
\ No newline at end of file diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index b1d04389..d95e5e63 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -45,6 +45,7 @@ next last Quick reply… + Subject… Submit From 1e1721032146e63b4f9793e7c1f86344da0a7856 Mon Sep 17 00:00:00 2001 From: Apostolof Date: Sat, 25 Feb 2017 21:46:26 +0200 Subject: [PATCH 07/18] Profile fixes and additions. --- .../activities/profile/ProfileActivity.java | 10 +++++--- .../profile/summary/SummaryFragment.java | 12 +++++++++ .../mthmmy/utils/CenterVerticalSpan.java | 25 +++++++++++-------- 3 files changed, 32 insertions(+), 15 deletions(-) diff --git a/app/src/main/java/gr/thmmy/mthmmy/activities/profile/ProfileActivity.java b/app/src/main/java/gr/thmmy/mthmmy/activities/profile/ProfileActivity.java index 60fea8d3..2444bf95 100644 --- a/app/src/main/java/gr/thmmy/mthmmy/activities/profile/ProfileActivity.java +++ b/app/src/main/java/gr/thmmy/mthmmy/activities/profile/ProfileActivity.java @@ -19,6 +19,7 @@ import android.text.SpannableString; import android.text.Spanned; import android.text.style.ForegroundColorSpan; import android.text.style.RelativeSizeSpan; +import android.util.Log; import android.view.View; import android.widget.ImageView; import android.widget.ProgressBar; @@ -243,14 +244,15 @@ public class ProfileActivity extends BaseActivity implements LatestPostsFragment try { Response response = client.newCall(request).execute(); profilePage = Jsoup.parse(response.body().string()); - Elements contentsTable = profilePage.select(".bordercolor > tbody:nth-child(1) > tr:nth-child(2)"); + Elements contentsTable = profilePage. + select(".bordercolor > tbody:nth-child(1) > tr:nth-child(2) tbody"); //Finds username if missing if (username == null || Objects.equals(username, "")) { username = contentsTable.select("tr").first().select("td").last().text(); } if (thumbnailUrl == null || Objects.equals(thumbnailUrl, "")) { //Maybe there is an avatar - Element profileAvatar = contentsTable.select("img.avatar").first(); + Element profileAvatar = profilePage.select("img.avatar").first(); if (profileAvatar != null) thumbnailUrl = profileAvatar.attr("abs:src"); } { //Finds personal text @@ -291,8 +293,8 @@ public class ProfileActivity extends BaseActivity implements LatestPostsFragment protected void onPostExecute(Boolean result) { if (!result) { //Parse failed! Report.d(TAG, "Parse failed!"); - Toast.makeText(getBaseContext() - , "Fatal error!\n Aborting...", Toast.LENGTH_LONG).show(); + Toast.makeText(getBaseContext(), "Fatal error!\n Aborting..." + , Toast.LENGTH_LONG).show(); finish(); } //Parse was successful diff --git a/app/src/main/java/gr/thmmy/mthmmy/activities/profile/summary/SummaryFragment.java b/app/src/main/java/gr/thmmy/mthmmy/activities/profile/summary/SummaryFragment.java index a2a0eea9..f876b6ff 100644 --- a/app/src/main/java/gr/thmmy/mthmmy/activities/profile/summary/SummaryFragment.java +++ b/app/src/main/java/gr/thmmy/mthmmy/activities/profile/summary/SummaryFragment.java @@ -6,6 +6,8 @@ import android.os.Build; import android.os.Bundle; import android.support.v4.app.Fragment; import android.text.Html; +import android.text.method.LinkMovementMethod; +import android.util.Log; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; @@ -189,6 +191,16 @@ public class SummaryFragment extends Fragment { } TextView entry = new TextView(this.getContext()); + if (profileSummaryRow.contains("@") && + (profileSummaryRow.contains("Email") || profileSummaryRow.contains("E-mail"))) { + Log.d(TAG, "mpika"); + Log.d(TAG, profileSummaryRow); + String email = profileSummaryRow.substring(profileSummaryRow.indexOf(": ") + 6); + profileSummaryRow = profileSummaryRow.replace(email, + "" + email + ""); + entry.setMovementMethod(LinkMovementMethod.getInstance()); + } + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) entry.setTextColor(getResources().getColor(R.color.primary_text, null)); else diff --git a/app/src/main/java/gr/thmmy/mthmmy/utils/CenterVerticalSpan.java b/app/src/main/java/gr/thmmy/mthmmy/utils/CenterVerticalSpan.java index 949a9736..cc98fe90 100644 --- a/app/src/main/java/gr/thmmy/mthmmy/utils/CenterVerticalSpan.java +++ b/app/src/main/java/gr/thmmy/mthmmy/utils/CenterVerticalSpan.java @@ -1,20 +1,23 @@ package gr.thmmy.mthmmy.utils; -import android.text.TextPaint; -import android.text.style.SuperscriptSpan; -import android.util.Log; - -public class CenterVerticalSpan extends SuperscriptSpan { - public CenterVerticalSpan() { - } +import android.graphics.Canvas; +import android.graphics.Paint; +import android.graphics.Rect; +import android.support.annotation.NonNull; +import android.text.style.ReplacementSpan; +public class CenterVerticalSpan extends ReplacementSpan { @Override - public void updateDrawState(TextPaint textPaint) { - textPaint.baselineShift -= 7f; + public int getSize(@NonNull Paint paint, CharSequence text, int start, int end, Paint.FontMetricsInt fm) { + text = text.subSequence(start, end); + return (int) paint.measureText(text.toString()); } @Override - public void updateMeasureState(TextPaint tp) { - updateDrawState(tp); + public void draw(@NonNull Canvas canvas, CharSequence text, int start, int end, float x, int top, int y, int bottom, Paint paint) { + text = text.subSequence(start, end); + Rect charSize = new Rect(); + paint.getTextBounds(text.toString(), 0, 1, charSize); + canvas.drawText(text.toString(), x, (bottom + charSize.height()) / 2f, paint); } } \ No newline at end of file From 5914ab0b7ba6ed5108f0901b551e4399f56f041d Mon Sep 17 00:00:00 2001 From: Apostolof Date: Sun, 26 Feb 2017 00:26:00 +0200 Subject: [PATCH 08/18] Topic scrollable title and auto scroll, extra info. --- app/build.gradle | 10 +- .../activities/board/BoardActivity.java | 3 +- .../activities/topic/TopicActivity.java | 98 +++++++++++++++++-- .../gr/thmmy/mthmmy/base/BaseActivity.java | 50 +++++----- app/src/main/res/layout/activity_topic.xml | 20 ++-- app/src/main/res/layout/dialog_topic_info.xml | 33 +++++++ app/src/main/res/menu/topic_menu.xml | 16 +++ app/src/main/res/values/colors.xml | 1 + 8 files changed, 186 insertions(+), 45 deletions(-) create mode 100644 app/src/main/res/layout/dialog_topic_info.xml create mode 100644 app/src/main/res/menu/topic_menu.xml diff --git a/app/build.gradle b/app/build.gradle index bbf5b90d..2469aa31 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -28,11 +28,11 @@ android { dependencies { compile fileTree(dir: 'libs', include: ['*.jar']) - compile 'com.android.support:appcompat-v7:25.1.0' - compile 'com.android.support:design:25.1.0' - compile 'com.android.support:support-v4:25.1.0' - compile 'com.android.support:cardview-v7:25.1.0' - compile 'com.android.support:recyclerview-v7:25.1.0' + compile 'com.android.support:appcompat-v7:25.2.0' + compile 'com.android.support:design:25.2.0' + compile 'com.android.support:support-v4:25.2.0' + compile 'com.android.support:cardview-v7:25.2.0' + compile 'com.android.support:recyclerview-v7:25.2.0' compile 'com.google.firebase:firebase-crash:10.0.1' compile 'com.squareup.okhttp3:okhttp:3.5.0' compile 'com.squareup.picasso:picasso:2.5.2' diff --git a/app/src/main/java/gr/thmmy/mthmmy/activities/board/BoardActivity.java b/app/src/main/java/gr/thmmy/mthmmy/activities/board/BoardActivity.java index 77d2165d..c44afe1b 100644 --- a/app/src/main/java/gr/thmmy/mthmmy/activities/board/BoardActivity.java +++ b/app/src/main/java/gr/thmmy/mthmmy/activities/board/BoardActivity.java @@ -92,8 +92,7 @@ public class BoardActivity extends BaseActivity implements BoardAdapter.OnLoadMo } thisPageBookmark = new Bookmark(boardTitle, ThmmyPage.getBoardId(boardUrl)); - thisPageBookmarkButton = (ImageButton) findViewById(R.id.bookmark); - setBoardBookmark(); + setBoardBookmark((ImageButton) findViewById(R.id.bookmark)); createDrawer(); progressBar = (MaterialProgressBar) findViewById(R.id.progressBar); diff --git a/app/src/main/java/gr/thmmy/mthmmy/activities/topic/TopicActivity.java b/app/src/main/java/gr/thmmy/mthmmy/activities/topic/TopicActivity.java index 7f0393a9..82100a2d 100644 --- a/app/src/main/java/gr/thmmy/mthmmy/activities/topic/TopicActivity.java +++ b/app/src/main/java/gr/thmmy/mthmmy/activities/topic/TopicActivity.java @@ -6,10 +6,21 @@ import android.os.AsyncTask; import android.os.Bundle; import android.os.Handler; import android.support.design.widget.FloatingActionButton; +import android.support.v7.app.AlertDialog; import android.support.v7.widget.LinearLayoutManager; import android.support.v7.widget.RecyclerView; import android.support.v7.widget.Toolbar; +import android.text.Html; +import android.text.SpannableString; +import android.text.SpannableStringBuilder; +import android.text.method.LinkMovementMethod; +import android.text.method.ScrollingMovementMethod; +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; import android.view.MotionEvent; import android.view.View; import android.widget.ImageButton; @@ -92,6 +103,9 @@ public class TopicActivity extends BaseActivity { private TextView pageIndicator; private ImageButton nextPage; private ImageButton lastPage; + //Topic's info + SpannableStringBuilder topicTreeAndMods = new SpannableStringBuilder("Loading..."), + topicViewers = new SpannableStringBuilder("Loading..."); //Other variables private MaterialProgressBar progressBar; private static String base_url = ""; @@ -117,18 +131,22 @@ public class TopicActivity extends BaseActivity { finish(); } + thisPageBookmark = new Bookmark(topicTitle, ThmmyPage.getTopicId(topicPageUrl)); + //Initializes graphics toolbar = (Toolbar) findViewById(R.id.toolbar); - toolbar.setTitle(topicTitle); + TextView toolbarTitle = (TextView) toolbar.findViewById(R.id.toolbar_title); + toolbarTitle.setText(topicTitle); setSupportActionBar(toolbar); if (getSupportActionBar() != null) { getSupportActionBar().setDisplayHomeAsUpEnabled(true); getSupportActionBar().setDisplayShowHomeEnabled(true); } - thisPageBookmark = new Bookmark(topicTitle, ThmmyPage.getTopicId(topicPageUrl)); - thisPageBookmarkButton = (ImageButton) findViewById(R.id.bookmark); - setTopicBookmark(); + //Makes title scrollable + toolbarTitle.setHorizontallyScrolling(true); + toolbarTitle.setMovementMethod(new ScrollingMovementMethod()); + createDrawer(); progressBar = (MaterialProgressBar) findViewById(R.id.progressBar); @@ -179,6 +197,43 @@ public class TopicActivity extends BaseActivity { topicTask.execute(extras.getString(BUNDLE_TOPIC_URL)); //Attempt data parsing } + @Override + public boolean onCreateOptionsMenu(Menu menu) { + // Inflates the menu; this adds items to the action bar if it is present. + getMenuInflater().inflate(R.menu.topic_menu, menu); + setTopicBookmark(menu.getItem(0)); + return true; + } + + @Override + public boolean onOptionsItemSelected(MenuItem item) { + // Handle presses on the action bar items + switch (item.getItemId()) { + case R.id.menu_bookmark: + topicMenuBookmarkClick(); + return true; + case R.id.menu_info: + AlertDialog.Builder builder = new AlertDialog.Builder(this); + LayoutInflater inflater = this.getLayoutInflater(); + LinearLayout infoDialog = (LinearLayout) inflater.inflate(R.layout.dialog_topic_info + , null); + ((TextView) infoDialog.findViewById(R.id.dialog_title)).setText("Info"); + TextView treeAndMods = (TextView) infoDialog.findViewById(R.id.topic_tree_and_mods); + treeAndMods.setText(topicTreeAndMods); + treeAndMods.setMovementMethod(LinkMovementMethod.getInstance()); + TextView usersViewing = (TextView) infoDialog.findViewById(R.id.users_viewing); + usersViewing.setText(topicViewers); + usersViewing.setMovementMethod(LinkMovementMethod.getInstance()); + + builder.setView(infoDialog); + AlertDialog dialog = builder.create(); + dialog.show(); + return true; + default: + return super.onOptionsItemSelected(item); + } + } + @Override public void onBackPressed() { if (drawer.isDrawerOpen()) { @@ -476,7 +531,8 @@ public class TopicActivity extends BaseActivity { case SUCCESS: if (topicTitle == null || Objects.equals(topicTitle, "")) { thisPageBookmark = new Bookmark(parsedTitle, ThmmyPage.getTopicId(loadedPageUrl)); - setTopicBookmark(); + invalidateOptionsMenu(); + //setTopicBookmark(menu.getItem(0)); } progressBar.setVisibility(ProgressBar.INVISIBLE); @@ -522,7 +578,13 @@ public class TopicActivity extends BaseActivity { private void parse(Document topic) { ParseHelpers.Language language = ParseHelpers.Language.getLanguage(topic); - //Find reply page url + //Finds topic's tree, mods and users viewing + { + topicTreeAndMods = getSpannableFromHtml(topic.select("div.nav").first().html()); + topicViewers = getSpannableFromHtml(TopicParser.parseUsersViewingThisTopic(topic, language)); + } + + //Finds reply page url { Element replyButton = topic.select("a:has(img[alt=Reply])").first(); if (replyButton == null) @@ -558,6 +620,30 @@ public class TopicActivity extends BaseActivity { postsList.clear(); postsList.addAll(TopicParser.parseTopic(topic, language)); } + + private void makeLinkClickable(SpannableStringBuilder strBuilder, final URLSpan span) + { + int start = strBuilder.getSpanStart(span); + int end = strBuilder.getSpanEnd(span); + int flags = strBuilder.getSpanFlags(span); + ClickableSpan clickable = new ClickableSpan() { + public void onClick(View view) { + //TODO + } + }; + strBuilder.setSpan(clickable, start, end, flags); + strBuilder.removeSpan(span); + } + + private SpannableStringBuilder getSpannableFromHtml(String html) { + CharSequence sequence = Html.fromHtml(html); + SpannableStringBuilder strBuilder = new SpannableStringBuilder(sequence); + URLSpan[] urls = strBuilder.getSpans(0, sequence.length(), URLSpan.class); + for(URLSpan span : urls) { + makeLinkClickable(strBuilder, span); + } + return strBuilder; + } } class ReplyTask extends AsyncTask { diff --git a/app/src/main/java/gr/thmmy/mthmmy/base/BaseActivity.java b/app/src/main/java/gr/thmmy/mthmmy/base/BaseActivity.java index 2147a1d3..9e2a3023 100644 --- a/app/src/main/java/gr/thmmy/mthmmy/base/BaseActivity.java +++ b/app/src/main/java/gr/thmmy/mthmmy/base/BaseActivity.java @@ -14,6 +14,7 @@ import android.support.annotation.NonNull; import android.support.v4.content.ContextCompat; import android.support.v7.app.AppCompatActivity; import android.support.v7.widget.Toolbar; +import android.view.MenuItem; import android.view.View; import android.widget.ImageButton; import android.widget.Toast; @@ -63,7 +64,8 @@ public abstract class BaseActivity extends AppCompatActivity { private static final String BOOKMARKED_TOPICS_KEY = "bookmarkedTopicsKey"; private static final String BOOKMARKED_BOARDS_KEY = "bookmarkedBoardsKey"; protected Bookmark thisPageBookmark; - protected ImageButton thisPageBookmarkButton; + protected MenuItem thisPageBookmarkMenuButton; + protected ImageButton thisPageBookmarkImageButton; private SharedPreferences bookmarksFile; private ArrayList topicsBookmarked; private ArrayList boardsBookmarked; @@ -408,42 +410,42 @@ public abstract class BaseActivity extends AppCompatActivity { return topicsBookmarked; } - protected void setTopicBookmark() { + protected void setTopicBookmark(MenuItem thisPageBookmarkMenuButton) { + this.thisPageBookmarkMenuButton = thisPageBookmarkMenuButton; if (thisPageBookmark.matchExists(topicsBookmarked)) { - thisPageBookmarkButton.setImageDrawable(bookmarked); + thisPageBookmarkMenuButton.setIcon(bookmarked); } else { - thisPageBookmarkButton.setImageDrawable(notBookmarked); + thisPageBookmarkMenuButton.setIcon(notBookmarked); + } + } + + protected void topicMenuBookmarkClick(){ + if (thisPageBookmark.matchExists(topicsBookmarked)) { + thisPageBookmarkMenuButton.setIcon(notBookmarked); + toggleTopicToBookmarks(thisPageBookmark); + Toast.makeText(BaseActivity.this, "Bookmark removed", Toast.LENGTH_SHORT).show(); + } else { + thisPageBookmarkMenuButton.setIcon(bookmarked); + toggleTopicToBookmarks(thisPageBookmark); + Toast.makeText(BaseActivity.this, "Bookmark added", Toast.LENGTH_SHORT).show(); } - thisPageBookmarkButton.setOnClickListener(new View.OnClickListener() { - @Override - public void onClick(View view) { - if (thisPageBookmark.matchExists(topicsBookmarked)) { - thisPageBookmarkButton.setImageDrawable(notBookmarked); - toggleTopicToBookmarks(thisPageBookmark); - Toast.makeText(BaseActivity.this, "Bookmark removed", Toast.LENGTH_SHORT).show(); - } else { - thisPageBookmarkButton.setImageDrawable(bookmarked); - toggleTopicToBookmarks(thisPageBookmark); - Toast.makeText(BaseActivity.this, "Bookmark added", Toast.LENGTH_SHORT).show(); - } - } - }); } - protected void setBoardBookmark() { + protected void setBoardBookmark(final ImageButton thisPageBookmarkImageButton) { + this.thisPageBookmarkImageButton = thisPageBookmarkImageButton; if (thisPageBookmark.matchExists(boardsBookmarked)) { - thisPageBookmarkButton.setImageDrawable(bookmarked); + thisPageBookmarkImageButton.setImageDrawable(bookmarked); } else { - thisPageBookmarkButton.setImageDrawable(notBookmarked); + thisPageBookmarkImageButton.setImageDrawable(notBookmarked); } - thisPageBookmarkButton.setOnClickListener(new View.OnClickListener() { + thisPageBookmarkImageButton.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { if (thisPageBookmark.matchExists(boardsBookmarked)) { - thisPageBookmarkButton.setImageDrawable(notBookmarked); + thisPageBookmarkImageButton.setImageDrawable(notBookmarked); Toast.makeText(BaseActivity.this, "Bookmark removed", Toast.LENGTH_SHORT).show(); } else { - thisPageBookmarkButton.setImageDrawable(bookmarked); + thisPageBookmarkImageButton.setImageDrawable(bookmarked); Toast.makeText(BaseActivity.this, "Bookmark added", Toast.LENGTH_SHORT).show(); } toggleBoardToBookmarks(thisPageBookmark); diff --git a/app/src/main/res/layout/activity_topic.xml b/app/src/main/res/layout/activity_topic.xml index 23b12737..e4735bcc 100644 --- a/app/src/main/res/layout/activity_topic.xml +++ b/app/src/main/res/layout/activity_topic.xml @@ -23,15 +23,19 @@ android:background="?attr/colorPrimary" app:popupTheme="@style/ToolbarTheme"> - + android:ellipsize="marquee" + android:fillViewport="true" + android:focusable="true" + android:focusableInTouchMode="true" + android:marqueeRepeatLimit="marquee_forever" + android:maxLines="1" + android:scrollHorizontally="true" + android:textColor="@color/white" + /> diff --git a/app/src/main/res/layout/dialog_topic_info.xml b/app/src/main/res/layout/dialog_topic_info.xml new file mode 100644 index 00000000..47b8ec31 --- /dev/null +++ b/app/src/main/res/layout/dialog_topic_info.xml @@ -0,0 +1,33 @@ + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/menu/topic_menu.xml b/app/src/main/res/menu/topic_menu.xml new file mode 100644 index 00000000..16c60e0a --- /dev/null +++ b/app/src/main/res/menu/topic_menu.xml @@ -0,0 +1,16 @@ + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/values/colors.xml b/app/src/main/res/values/colors.xml index 45d9efda..7af0467a 100644 --- a/app/src/main/res/values/colors.xml +++ b/app/src/main/res/values/colors.xml @@ -16,6 +16,7 @@ #323232 #3C3F41 #8B8B8B + #4B0082 #FFFFFF #CCCCCC From 9aed067fe87cad9ca02005b4587c4da753687689 Mon Sep 17 00:00:00 2001 From: Apostolof Date: Sun, 26 Feb 2017 01:00:02 +0200 Subject: [PATCH 09/18] Missed files. --- app/src/main/res/drawable-hdpi/ic_info.png | Bin 0 -> 595 bytes app/src/main/res/drawable-mdpi/ic_info.png | Bin 0 -> 376 bytes app/src/main/res/drawable-xhdpi/ic_info.png | Bin 0 -> 796 bytes app/src/main/res/drawable-xxhdpi/ic_info.png | Bin 0 -> 1174 bytes app/src/main/res/drawable-xxxhdpi/ic_info.png | Bin 0 -> 1643 bytes 5 files changed, 0 insertions(+), 0 deletions(-) create mode 100644 app/src/main/res/drawable-hdpi/ic_info.png create mode 100644 app/src/main/res/drawable-mdpi/ic_info.png create mode 100644 app/src/main/res/drawable-xhdpi/ic_info.png create mode 100644 app/src/main/res/drawable-xxhdpi/ic_info.png create mode 100644 app/src/main/res/drawable-xxxhdpi/ic_info.png diff --git a/app/src/main/res/drawable-hdpi/ic_info.png b/app/src/main/res/drawable-hdpi/ic_info.png new file mode 100644 index 0000000000000000000000000000000000000000..0932c17cb0a520c5e53f4658e9119be31add6a3b GIT binary patch literal 595 zcmV-Z0<8UsP)%`C3sM%1uI7A4~W&$&k#SORf|;Z59lSGzzD-M zZYJ9V+Ty~45N6-J?9S}WCSu!m1fUGC08_vkutTizT@O$K#KRPn0W<)g zwtQ>=CLkTOpc;O??)U&yf)Eq~Ji0h|1vCM9Ko++#fzQsn7U0cgo`sxRf}DvjjL>mX z1sH;_HE?C;jAN`4r6S}jGXR`wB*7VA$hi7`1=SeAeE=!lVVo7IpbQJ(frq0D%p?<^ z57|WlBNpgsiJ%6H8Lw?JiM{Dzdk$C-`&%zT33kp@1zX`qkb`S>PQ_J%$}F`d*(BXE zn!PjP=TareB8JTnYt|j{(^UzY62p9mf(pdXL?wu3S5`>wcgq~)h@X{8(2f`;gyepM z+Ch@c+5Ra(I$NeANW5h_L9HW59MnBx*a}flo6LDo2`aI&VT2$k##)l1SLxUg<5~!U z>crlO*%PngN*&Cxp9xA(3h++sZzR<|jjh3c367t literal 0 HcmV?d00001 diff --git a/app/src/main/res/drawable-mdpi/ic_info.png b/app/src/main/res/drawable-mdpi/ic_info.png new file mode 100644 index 0000000000000000000000000000000000000000..03cf044b9196a2d9eb25dd2b0e7d450b8cd9ccc7 GIT binary patch literal 376 zcmV-;0f+vHP)Z=|Uq!V2Jb2FU~rSn*bl%WN}9FAdHsm!ngyVN8Ydm#1=A@Qk-Ep^JWBzni0T%ACj6rgu!ZSc02c5! zI=~oagqADPrU&@Lv_ZQVS~UwWhZm;}n!r|+82fgP_Uw=zc(-d>b^(KU8F8st=B)VY z*L5ARI3i4F12MYjmIcc^Im=(ywNej@%XH$;Sn_-_9W1U8CQ000009mL1_^p@j(jBg*T$)1zHmG0R7`_r37qm6)SjCguX>lylPF0 zVsEr*p-MHq*?t435DsV4nc3MLEj#dmY@FHio1Ho5%$ZymhPj)pTn3N0#&GwcYqma75W;Qw-e|&H0=YR1g+ET#%*1w1r^f*Sb)BV?weX> z)g%G((3?I6{Dd~3C8!J)pdnI`o-IS0(0QM6)Yk}H1B^oNBVPCsT7*UnCS#O9KShkW zOaJ2pARl4;FX*w!Y(iN2xy_=*dX58-qoCK@j-de^fO#Rpj)du_%45(4vt>>P zpvgLIc+B^=m@N$*fF0Ip$s<6G*|MzzaKJj1JpxpiE&DnE9oDH}`SQ4%_-`=nZD%?F z-2V@G1Q-_L!T%4ymr(JhEg@H%*ad*qCgyH**&~3J8(m?YHa!BoWn;Kf`JTNW9gL;YpJfT!4v?f-?N>!N2y@VhpDNynDFm7S1 zB@Ei8>VYfcXN8$pZOuhxE}$}BDC~)bg?HlKrYWp>)!sq3To!kCBMPyHlx~a}2C16h zDtnFBI)|IgRuHkAdL#B08CIc8a+p-2XEn-aF8YkKrZe+#E;y=G?sMHv|FvOVUNIG@ z+}Cwr_!as2aUYj_cd24_Y+?8jr3X{j<(hSlywW!L^E3KFUHW^UeydYfIgnj+X8;*M aeEk8vDd_O@^L|qR0000+h=4B{BM?J=FIPTcFvhON3%T7%W|U2L2!T^AP2|+ za)AC(7!(8bgQh^cphHj+bb(6ZXS?_v^4%6t?rjBB1nL59AplW32W^7lpvSiXP$Os& z^v6?gm!Jhuy^VmHK--= z2GofWtrQdi<)9+?Sq#533p!47jyE_~MgbLo)_gjgM5ikx=BosafKGhQxdO_|6re)T zS07IPz_1)voJ)0sj(p6&hrSvGRNw;+$#(`6gSjd4b_`<3=RwLh1t{d>XY~#A#9+o- z4%+AVv?{VEi8%9?h3J0TJ~uF5L=c z0Ch1Ao?(js{3JU>MQ`T|@dLRNQ#<=XVvBq@= zl%TAsSp-l&Ww05G3xS^~Yw8mLG({P#(_%nz%9fRu)L zlZm1!K(s`0T;)+?)?z?&lzDnZ0JTsCJGK-M>#+J<1W+y`)K^*vNcnXK(I#ck5eos) zdYIN^ZWL*o+KFXXuK8F|{hxKnUfR=IOS&xr)XS*rMPbz2No3UNuqns634fpbjKBOgj~6k<@YGex>FCRkC7qYgcB8=ONFDWo4PRCkw=O@JJd5{11Tq1UX_c^sX z*I+7X9qcXQ2D0 o{dNDq!~t@E93ThC0kT(r0kE_Sftt4CY5)KL07*qoM6N<$f)uq8Qvd(} literal 0 HcmV?d00001 diff --git a/app/src/main/res/drawable-xxxhdpi/ic_info.png b/app/src/main/res/drawable-xxxhdpi/ic_info.png new file mode 100644 index 0000000000000000000000000000000000000000..cb42f367549b9ffce0d1c1501ce7430c2bf41209 GIT binary patch literal 1643 zcmV-x29)`UP)eG%y?eHFA#G!h#vQEQ_qX}xS`U=H*~X7+b>fBW0t?!x!wXwJ;eC%^s8&R$Zb zl&Xqyrx=6?AOeVr03v{>2p|H8iU9tj1)%ky1E4<870?aP1ZW!cf;3H^;lEu5_0rGa z&(4nk7G+P$2^Nr(UJs)Irei%6^*y4S?2>?O*{EK^>qw%3T`; zwS#7d1OSJC!=PVPcG^QwH>fu60Cs|YR@rT1ptd{$SPZ(P{Aoj=MR@_R8}vl^*M6fX z)>{BIpf3y!3j;JpZvm|YHPH80lWOR*RiLe)gY+|Z4cNz&c$RMfa02y1!VbR#T?Op{ zH5u@w8MF^{tpW(&f$Dt$uq0t>iCNJxLqVSj#&H^6bQ?|#-^x0G6`=c?9eYH>OPaZO zky7Eun!b*MmSq*d63yUa4W|e6hQrC=JkTi`_H-aLWeq@s=CJb<=$#DJWY&O2G>4=5 ztN^IdeBqwYT0xA2Ltwu~KT0ODBNL8)t}*1adr+hA(ioD?xdyOX=;$9*X7**FWIO0j zVc&MS0@@4W$iWr||J?_c-`v?HBg7 zEiC{AVM+PCrGRkFhRv^pHLKb*02~tL`Gp(-C<@o8yKDm}Qt5yj_iawHTmV45D|jC~ zpp6CA0CWff&|`T_b_Jk{c2;n0uPp%8f^x&76lyyz0n`a9ske1@Tj&^HFX()C3R#Iu z0H~t^A6jex7!=g=X9oaaj^HWy(lh{kv2dHFj-`~By9R*zjPc>AG$oZ9Y!xgcHYxun zT~aL-{32{N3E(Va>}o*4FRR4F)|q07n>KPUo>0 zmn8sSGrn}BQI5VFFaYjIR*MM$^97x54iLbKv=(Gg!;GPQ0RreuYe`bFCGT2*0KRAZ z=rIXkn_yc?b3g!=3H;b-5Zz-dO<`0OkmWUs3JH1OQx!9uqjzpCbT+ z0=svTtPUo1s7=XQmrA!dWKNI$?qMLS2ID1a$C_c*jJsI<*7dBNq z=P}_hUfWet^46~$-d4_}nu8ksz!LmxSpa~lS9*VNVZ`!eEy*NnRKx#aQzaLZoxpQq z;~JfKNeex74g-(1oj#@4@T#6hQ$E;Os2JDm5N1+GX$VLw@N=oEIjQL@Za`RS(ia<@ z!zbak(r*X?PoTeTc_r&ag20!Dokr6>*?hE1DtRkWU1hnU-3y(9HC*n6Yo*L?^D&<# zEZ=hN9%UzZAP%HW0k_6 zGfC^E*C?zVWu;xLq`Z(t0DrHdj%7ITqe-ipz5pn%Ctyk9L52c9K`;HZPy0CiLvDBp z)ZT2atQk pAVdHWKvV<}0YpUr5kQm!{RPu1rx Date: Sun, 26 Feb 2017 18:33:12 +0200 Subject: [PATCH 10/18] Color change and functionality of links at topic's extra info dialog. Post's last edit date, profile action to only the thumbnail. Ability to install to external memory. --- app/src/main/AndroidManifest.xml | 3 +- .../activities/topic/TopicActivity.java | 37 ++++++- .../mthmmy/activities/topic/TopicAdapter.java | 104 +++++++++++------- .../mthmmy/activities/topic/TopicParser.java | 15 ++- .../main/java/gr/thmmy/mthmmy/model/Post.java | 20 +++- app/src/main/res/values/colors.xml | 3 +- 6 files changed, 127 insertions(+), 55 deletions(-) diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index f95392f4..8a57fcbc 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -1,6 +1,7 @@ + package="gr.thmmy.mthmmy" + android:installLocation="auto"> diff --git a/app/src/main/java/gr/thmmy/mthmmy/activities/topic/TopicActivity.java b/app/src/main/java/gr/thmmy/mthmmy/activities/topic/TopicActivity.java index 82100a2d..710170fa 100644 --- a/app/src/main/java/gr/thmmy/mthmmy/activities/topic/TopicActivity.java +++ b/app/src/main/java/gr/thmmy/mthmmy/activities/topic/TopicActivity.java @@ -1,5 +1,6 @@ package gr.thmmy.mthmmy.activities.topic; +import android.content.Intent; import android.graphics.Rect; import android.net.Uri; import android.os.AsyncTask; @@ -11,7 +12,6 @@ import android.support.v7.widget.LinearLayoutManager; import android.support.v7.widget.RecyclerView; import android.support.v7.widget.Toolbar; import android.text.Html; -import android.text.SpannableString; import android.text.SpannableStringBuilder; import android.text.method.LinkMovementMethod; import android.text.method.ScrollingMovementMethod; @@ -39,6 +39,8 @@ 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.base.BaseActivity; import gr.thmmy.mthmmy.model.Bookmark; import gr.thmmy.mthmmy.model.Post; @@ -51,6 +53,12 @@ import okhttp3.Request; import okhttp3.RequestBody; import okhttp3.Response; +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.ReplyParser.replyStatus; /** @@ -621,14 +629,33 @@ public class TopicActivity extends BaseActivity { postsList.addAll(TopicParser.parseTopic(topic, language)); } - private void makeLinkClickable(SpannableStringBuilder strBuilder, final URLSpan span) - { + private void makeLinkClickable(SpannableStringBuilder strBuilder, final URLSpan span) { int start = strBuilder.getSpanStart(span); int end = strBuilder.getSpanEnd(span); int flags = strBuilder.getSpanFlags(span); ClickableSpan clickable = new ClickableSpan() { + @Override public void onClick(View view) { - //TODO + ThmmyPage.PageCategory target = ThmmyPage.resolvePageCategory(Uri.parse(span.getURL())); + if (target.is(ThmmyPage.PageCategory.BOARD)) { + Intent intent = new Intent(getApplicationContext(), BoardActivity.class); + Bundle extras = new Bundle(); + extras.putString(BUNDLE_BOARD_URL, span.getURL()); + extras.putString(BUNDLE_BOARD_TITLE, ""); + intent.putExtras(extras); + intent.setFlags(FLAG_ACTIVITY_NEW_TASK); + getApplicationContext().startActivity(intent); + } else if (target.is(ThmmyPage.PageCategory.PROFILE)) { + Intent intent = new Intent(getApplicationContext(), ProfileActivity.class); + Bundle extras = new Bundle(); + extras.putString(BUNDLE_PROFILE_URL, span.getURL()); + extras.putString(BUNDLE_PROFILE_THUMBNAIL_URL, ""); + extras.putString(BUNDLE_PROFILE_USERNAME, ""); + intent.putExtras(extras); + intent.setFlags(FLAG_ACTIVITY_NEW_TASK); + getApplicationContext().startActivity(intent); + } else if (target.is(ThmmyPage.PageCategory.INDEX)) + finish(); } }; strBuilder.setSpan(clickable, start, end, flags); @@ -639,7 +666,7 @@ public class TopicActivity extends BaseActivity { CharSequence sequence = Html.fromHtml(html); SpannableStringBuilder strBuilder = new SpannableStringBuilder(sequence); URLSpan[] urls = strBuilder.getSpans(0, sequence.length(), URLSpan.class); - for(URLSpan span : urls) { + for (URLSpan span : urls) { makeLinkClickable(strBuilder, span); } return strBuilder; diff --git a/app/src/main/java/gr/thmmy/mthmmy/activities/topic/TopicAdapter.java b/app/src/main/java/gr/thmmy/mthmmy/activities/topic/TopicAdapter.java index 035933cf..59c529af 100644 --- a/app/src/main/java/gr/thmmy/mthmmy/activities/topic/TopicAdapter.java +++ b/app/src/main/java/gr/thmmy/mthmmy/activities/topic/TopicAdapter.java @@ -18,6 +18,7 @@ import android.support.v7.widget.RecyclerView; import android.text.Editable; import android.text.TextUtils; import android.text.TextWatcher; +import android.util.Log; import android.view.LayoutInflater; import android.view.MotionEvent; import android.view.View; @@ -198,34 +199,52 @@ class TopicAdapter extends RecyclerView.Adapter { holder.postNum.setText(""); holder.subject.setText(currentPost.getSubject()); holder.post.loadDataWithBaseURL("file:///android_asset/", currentPost.getContent(), "text/html", "UTF-8", null); - if (currentPost.getAttachedFiles() != null && currentPost.getAttachedFiles().size() != 0) { + if ((currentPost.getAttachedFiles() != null && currentPost.getAttachedFiles().size() != 0) + || (currentPost.getLastEdit() != null)) { holder.bodyFooterDivider.setVisibility(View.VISIBLE); - int filesTextColor; - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) { - filesTextColor = context.getResources().getColor(R.color.accent, null); - } else //noinspection deprecation - filesTextColor = context.getResources().getColor(R.color.accent); - holder.postFooter.removeAllViews(); - for (final ThmmyFile attachedFile : currentPost.getAttachedFiles()) { - final TextView attached = new TextView(context); - attached.setTextSize(10f); - attached.setClickable(true); - attached.setTypeface(Typeface.createFromAsset(context.getAssets() - , "fonts/fontawesome-webfont.ttf")); - attached.setText(faIconFromFilename(attachedFile.getFilename()) + " " - + attachedFile.getFilename() + attachedFile.getFileInfo()); - attached.setTextColor(filesTextColor); - attached.setPadding(0, 3, 0, 3); - - attached.setOnClickListener(new View.OnClickListener() { - @Override - public void onClick(View view) { - ((BaseActivity) context).launchDownloadService(attachedFile); - } - }); - holder.postFooter.addView(attached); + if (currentPost.getAttachedFiles() != null && currentPost.getAttachedFiles().size() != 0) { + int filesTextColor; + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) { + filesTextColor = context.getResources().getColor(R.color.accent, null); + } else //noinspection deprecation + filesTextColor = context.getResources().getColor(R.color.accent); + + for (final ThmmyFile attachedFile : currentPost.getAttachedFiles()) { + final TextView attached = new TextView(context); + attached.setTextSize(10f); + attached.setClickable(true); + attached.setTypeface(Typeface.createFromAsset(context.getAssets() + , "fonts/fontawesome-webfont.ttf")); + attached.setText(faIconFromFilename(attachedFile.getFilename()) + " " + + attachedFile.getFilename() + attachedFile.getFileInfo()); + attached.setTextColor(filesTextColor); + attached.setPadding(0, 3, 0, 3); + + attached.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View view) { + ((BaseActivity) context).launchDownloadService(attachedFile); + } + }); + + holder.postFooter.addView(attached); + } + } + if (currentPost.getLastEdit() != null && currentPost.getLastEdit().length() > 0) { + int lastEditTextColor; + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) { + lastEditTextColor = context.getResources().getColor(R.color.white, null); + } else //noinspection deprecation + lastEditTextColor = context.getResources().getColor(R.color.white); + + final TextView lastEdit = new TextView(context); + lastEdit.setTextSize(12f); + lastEdit.setText(currentPost.getLastEdit()); + lastEdit.setTextColor(lastEditTextColor); + lastEdit.setPadding(0, 3, 0, 3); + holder.postFooter.addView(lastEdit); } } else { holder.bodyFooterDivider.setVisibility(View.GONE); @@ -312,24 +331,27 @@ class TopicAdapter extends RecyclerView.Adapter { } if (!currentPost.isDeleted()) { //Sets graphics behavior + holder.thumbnail.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View view) { + //Clicking the thumbnail opens user's profile + Intent intent = new Intent(context, ProfileActivity.class); + Bundle extras = new Bundle(); + extras.putString(BUNDLE_PROFILE_URL, currentPost.getProfileURL()); + if (currentPost.getThumbnailUrl() == null) + extras.putString(BUNDLE_PROFILE_THUMBNAIL_URL, ""); + else + extras.putString(BUNDLE_PROFILE_THUMBNAIL_URL, currentPost.getThumbnailUrl()); + extras.putString(BUNDLE_PROFILE_USERNAME, currentPost.getAuthor()); + intent.putExtras(extras); + intent.setFlags(FLAG_ACTIVITY_NEW_TASK); + context.startActivity(intent); + } + }); holder.header.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { - //Clicking an expanded header starts profile activity - if (viewProperties.get(holder.getAdapterPosition())[isUserExtraInfoVisibile]) { - Intent intent = new Intent(context, ProfileActivity.class); - Bundle extras = new Bundle(); - extras.putString(BUNDLE_PROFILE_URL, currentPost.getProfileURL()); - if (currentPost.getThumbnailUrl() == null) - extras.putString(BUNDLE_PROFILE_THUMBNAIL_URL, ""); - else - extras.putString(BUNDLE_PROFILE_THUMBNAIL_URL, currentPost.getThumbnailUrl()); - extras.putString(BUNDLE_PROFILE_USERNAME, currentPost.getAuthor()); - intent.putExtras(extras); - intent.setFlags(FLAG_ACTIVITY_NEW_TASK); - context.startActivity(intent); - } - + //Clicking the header makes it expand/collapse boolean[] tmp = viewProperties.get(holder.getAdapterPosition()); tmp[isUserExtraInfoVisibile] = !tmp[isUserExtraInfoVisibile]; viewProperties.set(holder.getAdapterPosition(), tmp); @@ -341,7 +363,7 @@ class TopicAdapter extends RecyclerView.Adapter { @Override public void onClick(View v) { boolean[] tmp = viewProperties.get(holder.getAdapterPosition()); - tmp[1] = false; + tmp[isUserExtraInfoVisibile] = false; viewProperties.set(holder.getAdapterPosition(), tmp); TopicAnimations.animateUserExtraInfoVisibility(v); diff --git a/app/src/main/java/gr/thmmy/mthmmy/activities/topic/TopicParser.java b/app/src/main/java/gr/thmmy/mthmmy/activities/topic/TopicParser.java index 9cab0649..9229c6b9 100644 --- a/app/src/main/java/gr/thmmy/mthmmy/activities/topic/TopicParser.java +++ b/app/src/main/java/gr/thmmy/mthmmy/activities/topic/TopicParser.java @@ -160,7 +160,7 @@ class TopicParser { for (Element thisRow : postRows) { //Variables for Post constructor String p_userName, p_thumbnailUrl, p_subject, p_post, p_postDate, p_profileURL, p_rank, - p_specialRank, p_gender, p_personalText, p_numberOfPosts; + p_specialRank, p_gender, p_personalText, p_numberOfPosts, p_postLastEditDate; int p_postNum, p_postIndex, p_numberOfStars, p_userColor; boolean p_isDeleted = false; ArrayList p_attachedFiles; @@ -175,6 +175,7 @@ class TopicParser { p_numberOfStars = 0; p_userColor = USER_COLOR_YELLOW; p_attachedFiles = new ArrayList<>(); + p_postLastEditDate = null; //Language independent parsing //Finds thumbnail url @@ -190,11 +191,11 @@ class TopicParser { //Finds post's text p_post = ParseHelpers.youtubeEmbeddedFix(thisRow.select("div").select(".post").first()); - //Add stuff to make it work in WebView + //Adds stuff to make it work in WebView //style.css p_post = ("" + p_post); - //Find post's index + //Finds post's index //This is an int assigned by the forum used for post focusing and quotes, it is not //the same as reply index. Element postIndex = thisRow.select("a[name^=msg]").first(); @@ -205,6 +206,10 @@ class TopicParser { p_postIndex = Integer.parseInt(tmp.substring(tmp.indexOf("msg") + 3)); } + Element postLastEditDate = thisRow.select("td.smalltext[id^=modified_]").first(); + if (postLastEditDate != null && !Objects.equals(postLastEditDate.text(), "")) + p_postLastEditDate = postLastEditDate.text(); + //Language dependent parsing Element userName; if (language.is(ParseHelpers.Language.GREEK)) { @@ -406,12 +411,12 @@ class TopicParser { parsedPostsList.add(new Post(p_thumbnailUrl, p_userName, p_subject, p_post, p_postIndex , p_postNum, p_postDate, p_profileURL, p_rank, p_specialRank, p_gender , p_numberOfPosts, p_personalText, p_numberOfStars, p_userColor - , p_attachedFiles)); + , p_attachedFiles, p_postLastEditDate)); } else { //Deleted user //Add new post in postsList, only standard information needed parsedPostsList.add(new Post(p_thumbnailUrl, p_userName, p_subject, p_post, p_postIndex - , p_postNum, p_postDate, p_userColor, p_attachedFiles)); + , p_postNum, p_postDate, p_userColor, p_attachedFiles, p_postLastEditDate)); } } return parsedPostsList; diff --git a/app/src/main/java/gr/thmmy/mthmmy/model/Post.java b/app/src/main/java/gr/thmmy/mthmmy/model/Post.java index 15b6afe6..baf8cc20 100644 --- a/app/src/main/java/gr/thmmy/mthmmy/model/Post.java +++ b/app/src/main/java/gr/thmmy/mthmmy/model/Post.java @@ -27,6 +27,7 @@ public class Post { private final boolean isDeleted; private final int userColor; private final ArrayList attachedFiles; + private final String lastEdit; //Extra info private final String profileURL; @@ -57,6 +58,7 @@ public class Post { personalText = ""; numberOfStars = 0; attachedFiles = null; + lastEdit = null; } /** @@ -80,12 +82,13 @@ public class Post { * @param numberOfStars author's number of stars * @param userColor author's user color * @param attachedFiles post's attached files + * @param lastEdit post's last edit date */ public Post(@Nullable String thumbnailUrl, String author, String subject, String content , int postIndex, int postNumber, String postDate, String profileURl, @Nullable String rank , @Nullable String special_rank, @Nullable String gender, @Nullable String numberOfPosts , @Nullable String personalText, int numberOfStars, int userColor - , @Nullable ArrayList attachedFiles) { + , @Nullable ArrayList attachedFiles, @Nullable String lastEdit) { if (Objects.equals(thumbnailUrl, "")) this.thumbnailUrl = null; else this.thumbnailUrl = thumbnailUrl; this.author = author; @@ -97,6 +100,7 @@ public class Post { this.isDeleted = false; this.userColor = userColor; this.attachedFiles = attachedFiles; + this.lastEdit = lastEdit; this.profileURL = profileURl; this.rank = rank; this.specialRank = special_rank; @@ -120,10 +124,11 @@ public class Post { * @param postDate date of submission * @param userColor author's user color * @param attachedFiles post's attached files + * @param lastEdit post's last edit date */ public Post(@Nullable String thumbnailUrl, String author, String subject, String content , int postIndex, int postNumber, String postDate, int userColor - , @Nullable ArrayList attachedFiles) { + , @Nullable ArrayList attachedFiles, @Nullable String lastEdit) { if (Objects.equals(thumbnailUrl, "")) this.thumbnailUrl = null; else this.thumbnailUrl = thumbnailUrl; this.author = author; @@ -135,6 +140,7 @@ public class Post { this.isDeleted = true; this.userColor = userColor; this.attachedFiles = attachedFiles; + this.lastEdit = lastEdit; profileURL = null; rank = "Rank"; specialRank = "Special rank"; @@ -310,4 +316,14 @@ public class Post { public ArrayList getAttachedFiles() { return attachedFiles; } + + /** + * Gets this post's last edit date or null if post hasn't been edited. + * + * @return date of last edit or null + */ + @Nullable + public String getLastEdit() { + return lastEdit; + } } diff --git a/app/src/main/res/values/colors.xml b/app/src/main/res/values/colors.xml index 7af0467a..c864d4e3 100644 --- a/app/src/main/res/values/colors.xml +++ b/app/src/main/res/values/colors.xml @@ -16,7 +16,8 @@ #323232 #3C3F41 #8B8B8B - #4B0082 + + #FF9800 #FFFFFF #CCCCCC From a67adf20583055bb3ad6ff057bfeb518cd274daf Mon Sep 17 00:00:00 2001 From: Ezerous Date: Sun, 12 Mar 2017 12:20:33 +0200 Subject: [PATCH 11/18] Timber init (Report class was removed), library updates --- app/build.gradle | 11 ++- app/src/debug/java/mthmmy/utils/Report.java | 81 ---------------- app/src/main/assets/apache_libraries.html | 4 +- app/src/main/assets/mit_libraries.html | 2 +- .../mthmmy/activities/LoginActivity.java | 9 +- .../activities/board/BoardActivity.java | 20 +--- .../mthmmy/activities/board/BoardAdapter.java | 1 - .../downloads/DownloadsActivity.java | 18 +--- .../downloads/DownloadsAdapter.java | 5 - .../mthmmy/activities/main/MainActivity.java | 1 - .../activities/main/forum/ForumFragment.java | 14 +-- .../main/recent/RecentFragment.java | 14 +-- .../activities/profile/ProfileActivity.java | 29 ++---- .../latestPosts/LatestPostsAdapter.java | 5 - .../latestPosts/LatestPostsFragment.java | 25 ++--- .../profile/stats/StatsFragment.java | 27 ++---- .../profile/summary/SummaryFragment.java | 25 ++--- .../mthmmy/activities/topic/ReplyParser.java | 6 -- .../activities/topic/TopicActivity.java | 31 +++--- .../mthmmy/activities/topic/TopicAdapter.java | 11 +-- .../mthmmy/activities/topic/TopicParser.java | 13 +-- .../gr/thmmy/mthmmy/base/BaseApplication.java | 9 ++ .../gr/thmmy/mthmmy/base/BaseFragment.java | 12 +-- .../java/gr/thmmy/mthmmy/model/ThmmyPage.java | 4 +- .../gr/thmmy/mthmmy/receiver/Receiver.java | 6 +- .../mthmmy/services/DownloadService.java | 25 ++--- .../thmmy/mthmmy/session/SessionManager.java | 43 ++++----- .../mthmmy/utils/CrashReportingTree.java | 34 +++++++ app/src/release/java/mthmmy.utils/Report.java | 96 ------------------- build.gradle | 2 +- gradle/wrapper/gradle-wrapper.properties | 4 +- 31 files changed, 176 insertions(+), 411 deletions(-) delete mode 100644 app/src/debug/java/mthmmy/utils/Report.java create mode 100644 app/src/main/java/gr/thmmy/mthmmy/utils/CrashReportingTree.java delete mode 100644 app/src/release/java/mthmmy.utils/Report.java diff --git a/app/build.gradle b/app/build.gradle index 2469aa31..522c3627 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -2,7 +2,7 @@ apply plugin: 'com.android.application' android { compileSdkVersion 25 - buildToolsVersion "25.0.1" + buildToolsVersion "25.0.2" defaultConfig { vectorDrawables.useSupportLibrary = true @@ -33,20 +33,21 @@ dependencies { compile 'com.android.support:support-v4:25.2.0' compile 'com.android.support:cardview-v7:25.2.0' compile 'com.android.support:recyclerview-v7:25.2.0' - compile 'com.google.firebase:firebase-crash:10.0.1' - compile 'com.squareup.okhttp3:okhttp:3.5.0' + compile 'com.google.firebase:firebase-crash:10.2.0' + compile 'com.squareup.okhttp3:okhttp:3.6.0' compile 'com.squareup.picasso:picasso:2.5.2' compile 'com.jakewharton.picasso:picasso2-okhttp3-downloader:1.1.0' compile 'org.jsoup:jsoup:1.10.2' compile 'com.github.franmontiel:PersistentCookieJar:v1.0.0' compile 'com.github.PhilJay:MPAndroidChart:v3.0.1' - compile('com.mikepenz:materialdrawer:5.8.1@aar') { + compile('com.mikepenz:materialdrawer:5.8.2@aar') { transitive = true } compile 'com.mikepenz:fontawesome-typeface:4.7.0.0@aar' - compile 'pl.droidsonroids.gif:android-gif-drawable:1.2.3' + compile 'pl.droidsonroids.gif:android-gif-drawable:1.2.5' compile 'com.bignerdranch.android:expandablerecyclerview:3.0.0-RC1' compile 'me.zhanghai.android.materialprogressbar:library:1.3.0' + compile 'com.jakewharton.timber:timber:4.5.1' } apply plugin: 'com.google.gms.google-services' diff --git a/app/src/debug/java/mthmmy/utils/Report.java b/app/src/debug/java/mthmmy/utils/Report.java deleted file mode 100644 index 6e6a906f..00000000 --- a/app/src/debug/java/mthmmy/utils/Report.java +++ /dev/null @@ -1,81 +0,0 @@ -package mthmmy.utils; - -import android.util.Log; - -public class Report -{ - - public static void v (String TAG, String message) - { - Log.v(TAG,message); - } - - public static void v (String TAG, String message, Throwable tr) - { - Log.v(TAG,message + ": " + tr.getMessage(),tr); - } - - public static void d (String TAG, String message) - { - Log.d(TAG,message); - } - - public static void d (String TAG, String message, Throwable tr) - { - Log.d(TAG,message + ": " + tr.getMessage(),tr); - } - - public static void i (String TAG, String message) - { - Log.i(TAG,message); - } - - public static void i (String TAG, String message, Throwable tr) - { - Log.i(TAG,message + ": " + tr.getMessage(),tr); - } - - public static void w (String TAG, String message) - { - Log.w(TAG,message); - } - - public static void w (String TAG, String message, Throwable tr) - { - Log.w(TAG,message + ": " + tr.getMessage(),tr); - } - - public static void e (String TAG, String message) - { - Log.e(TAG,message); - } - - public static void e (String TAG, String message, Throwable tr) - { - Log.e(TAG,message + ": " + tr.getMessage(),tr); - } - - public static void wtf (String TAG, String message) - { - Log.wtf(TAG,message); - } - - public static void wtf (String TAG, String message, Throwable tr) - { - Log.wtf(TAG,message + ": " + tr.getMessage(),tr); - } - - /** - * Prints long messages in logcat (debug level). - */ - public static void longMessage(String TAG, String message) - { - int maxLogSize = 1000; - for(int i = 0; i <= message.length() / maxLogSize; i++) { - int start = i * maxLogSize; - int end = (i+1) * maxLogSize; - end = end > message.length() ? message.length() : end; - Report.d(TAG, message.substring(start, end)); - } - } -} \ No newline at end of file diff --git a/app/src/main/assets/apache_libraries.html b/app/src/main/assets/apache_libraries.html index 10867db3..2c0ceabc 100644 --- a/app/src/main/assets/apache_libraries.html +++ b/app/src/main/assets/apache_libraries.html @@ -39,7 +39,7 @@
  • -
    OkHttp v3.5.0 (Copyright ©2016 Square, Inc.)
    +
    OkHttp v3.6.0 (Copyright ©2016 Square, Inc.)
  • Picasso v2.5.2 (Copyright ©2013 Square, Inc.)
    @@ -51,7 +51,7 @@
    MPAndroidChart v3.0.1 (Copyright ©2016 Philipp Jahoda)
  • -
    MaterialDrawer v5.8.1 (Copyright ©2016 Mike Penz)
    +
    MaterialDrawer v5.8.2 (Copyright ©2016 Mike Penz)
  • Fontawesome Typeface Library v4.7.0.0 (Copyright ©2016 Mike Penz)
    diff --git a/app/src/main/assets/mit_libraries.html b/app/src/main/assets/mit_libraries.html index 6d72c330..2c6cf3bb 100644 --- a/app/src/main/assets/mit_libraries.html +++ b/app/src/main/assets/mit_libraries.html @@ -42,7 +42,7 @@
    jsoup v1.10.2 (Copyright ©2009-2017, Jonathan Hedley <jonathan@hedley.net>)
  • -
    android-gif-drawable v1.2.3 (Copyright ©2016 Karol Wrótniak, Droids on Roids)
    +
    android-gif-drawable v1.2.5 (Copyright ©2016 Karol Wrótniak, Droids on Roids)
  • Expandable RecyclerView v3.0.0-RC1 (Copyright ©2015, Big Nerd Ranch)
    diff --git a/app/src/main/java/gr/thmmy/mthmmy/activities/LoginActivity.java b/app/src/main/java/gr/thmmy/mthmmy/activities/LoginActivity.java index 7dacd734..39a770c2 100644 --- a/app/src/main/java/gr/thmmy/mthmmy/activities/LoginActivity.java +++ b/app/src/main/java/gr/thmmy/mthmmy/activities/LoginActivity.java @@ -14,7 +14,8 @@ import android.widget.Toast; import gr.thmmy.mthmmy.R; import gr.thmmy.mthmmy.activities.main.MainActivity; import gr.thmmy.mthmmy.base.BaseActivity; -import mthmmy.utils.Report; + +import timber.log.Timber; import static gr.thmmy.mthmmy.session.SessionManager.CONNECTION_ERROR; import static gr.thmmy.mthmmy.session.SessionManager.EXCEPTION; @@ -34,12 +35,8 @@ public class LoginActivity extends BaseActivity { private String password; /* --Graphics End-- */ - //Other variables - private static final String TAG = "LoginActivity"; - private LoginTask loginTask; - @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); @@ -55,7 +52,7 @@ public class LoginActivity extends BaseActivity { btnLogin.setOnClickListener(new View.OnClickListener() { public void onClick(View view) { - Report.d(TAG, "Login"); + Timber.d("Login"); //Get username and password strings username = inputUsername.getText().toString().trim(); diff --git a/app/src/main/java/gr/thmmy/mthmmy/activities/board/BoardActivity.java b/app/src/main/java/gr/thmmy/mthmmy/activities/board/BoardActivity.java index c44afe1b..d4cf2236 100644 --- a/app/src/main/java/gr/thmmy/mthmmy/activities/board/BoardActivity.java +++ b/app/src/main/java/gr/thmmy/mthmmy/activities/board/BoardActivity.java @@ -30,16 +30,11 @@ import gr.thmmy.mthmmy.model.Bookmark; import gr.thmmy.mthmmy.model.ThmmyPage; import gr.thmmy.mthmmy.model.Topic; import me.zhanghai.android.materialprogressbar.MaterialProgressBar; -import mthmmy.utils.Report; import okhttp3.Request; import okhttp3.Response; +import timber.log.Timber; public class BoardActivity extends BaseActivity implements BoardAdapter.OnLoadMoreListener { - /** - * Debug Tag for logging debug output to LogCat - */ - @SuppressWarnings("unused") - private static final String TAG = "BoardActivity"; /** * The key to use when putting board's url String to {@link BoardActivity}'s Bundle. */ @@ -76,7 +71,7 @@ public class BoardActivity extends BaseActivity implements BoardAdapter.OnLoadMo boardUrl = extras.getString(BUNDLE_BOARD_URL); ThmmyPage.PageCategory target = ThmmyPage.resolvePageCategory(Uri.parse(boardUrl)); if (!target.is(ThmmyPage.PageCategory.BOARD)) { - Report.e(TAG, "Bundle came with a non board url!\nUrl:\n" + boardUrl); + Timber.e("Bundle came with a non board url!\nUrl:\n%s" , boardUrl); Toast.makeText(this, "An error has occurred\nAborting.", Toast.LENGTH_SHORT).show(); finish(); } @@ -181,13 +176,6 @@ public class BoardActivity extends BaseActivity implements BoardAdapter.OnLoadMo * parameter!

    */ public class BoardTask extends AsyncTask { - //Class variables - /** - * Debug Tag for logging debug output to LogCat - */ - @SuppressWarnings("unused") - private static final String TAG = "BoardTask"; //Separate tag for AsyncTask - @Override protected void onPreExecute() { if (!isLoadingMore) progressBar.setVisibility(ProgressBar.VISIBLE); @@ -203,9 +191,9 @@ public class BoardActivity extends BaseActivity implements BoardAdapter.OnLoadMo Response response = client.newCall(request).execute(); parseBoard(Jsoup.parse(response.body().string())); } catch (SSLHandshakeException e) { - Report.w(TAG, "Certificate problem (please switch to unsafe connection)."); + Timber.w("Certificate problem (please switch to unsafe connection)."); } catch (Exception e) { - Report.e("TAG", "ERROR", e); + Timber.e("ERROR", e); } return null; } diff --git a/app/src/main/java/gr/thmmy/mthmmy/activities/board/BoardAdapter.java b/app/src/main/java/gr/thmmy/mthmmy/activities/board/BoardAdapter.java index 306302fe..b6b716be 100644 --- a/app/src/main/java/gr/thmmy/mthmmy/activities/board/BoardAdapter.java +++ b/app/src/main/java/gr/thmmy/mthmmy/activities/board/BoardAdapter.java @@ -32,7 +32,6 @@ import static gr.thmmy.mthmmy.activities.topic.TopicActivity.BUNDLE_TOPIC_URL; * {@link RecyclerView.Adapter} that can display a {@link gr.thmmy.mthmmy.model.Board}. */ class BoardAdapter extends RecyclerView.Adapter { - private static final String TAG = "BoardAdapter"; private final int VIEW_TYPE_SUB_BOARD_TITLE = 0; private final int VIEW_TYPE_SUB_BOARD = 1; private final int VIEW_TYPE_TOPIC_TITLE = 2; diff --git a/app/src/main/java/gr/thmmy/mthmmy/activities/downloads/DownloadsActivity.java b/app/src/main/java/gr/thmmy/mthmmy/activities/downloads/DownloadsActivity.java index ea02b7b8..b4339f14 100644 --- a/app/src/main/java/gr/thmmy/mthmmy/activities/downloads/DownloadsActivity.java +++ b/app/src/main/java/gr/thmmy/mthmmy/activities/downloads/DownloadsActivity.java @@ -27,16 +27,12 @@ import gr.thmmy.mthmmy.base.BaseActivity; import gr.thmmy.mthmmy.model.Download; import gr.thmmy.mthmmy.model.ThmmyPage; import me.zhanghai.android.materialprogressbar.MaterialProgressBar; -import mthmmy.utils.Report; + import okhttp3.Request; import okhttp3.Response; +import timber.log.Timber; public class DownloadsActivity extends BaseActivity implements DownloadsAdapter.OnLoadMoreListener { - /** - * Debug Tag for logging debug output to LogCat - */ - @SuppressWarnings("unused") - private static final String TAG = "DownloadsActivity"; /** * The key to use when putting download's url String to {@link DownloadsActivity}'s Bundle. */ @@ -73,7 +69,7 @@ public class DownloadsActivity extends BaseActivity implements DownloadsAdapter. if (downloadsUrl != null && !Objects.equals(downloadsUrl, "")) { ThmmyPage.PageCategory target = ThmmyPage.resolvePageCategory(Uri.parse(downloadsUrl)); if (!target.is(ThmmyPage.PageCategory.DOWNLOADS)) { - Report.e(TAG, "Bundle came with a non board url!\nUrl:\n" + downloadsUrl); + Timber.e("Bundle came with a non board url!\nUrl:\n%s" , downloadsUrl); Toast.makeText(this, "An error has occurred\nAborting.", Toast.LENGTH_SHORT).show(); finish(); } @@ -173,10 +169,6 @@ public class DownloadsActivity extends BaseActivity implements DownloadsAdapter. * as String parameter!

    */ class ParseDownloadPageTask extends AsyncTask { - /** - * Debug Tag for logging debug output to LogCat - */ - private static final String TAG = "ParseDownloadPageTask"; //Separate tag for AsyncTask private String thisPageUrl; @Override @@ -195,9 +187,9 @@ public class DownloadsActivity extends BaseActivity implements DownloadsAdapter. Response response = client.newCall(request).execute(); parseDownloads(Jsoup.parse(response.body().string())); } catch (SSLHandshakeException e) { - Report.w(TAG, "Certificate problem (please switch to unsafe connection)."); + Timber.w("Certificate problem (please switch to unsafe connection)."); } catch (Exception e) { - Report.e("TAG", "ERROR", e); + Timber.e("ERROR", e); } return null; } diff --git a/app/src/main/java/gr/thmmy/mthmmy/activities/downloads/DownloadsAdapter.java b/app/src/main/java/gr/thmmy/mthmmy/activities/downloads/DownloadsAdapter.java index a46dfeea..0253359b 100644 --- a/app/src/main/java/gr/thmmy/mthmmy/activities/downloads/DownloadsAdapter.java +++ b/app/src/main/java/gr/thmmy/mthmmy/activities/downloads/DownloadsAdapter.java @@ -29,11 +29,6 @@ import static gr.thmmy.mthmmy.activities.downloads.DownloadsActivity.BUNDLE_DOWN import static gr.thmmy.mthmmy.activities.downloads.DownloadsActivity.BUNDLE_DOWNLOADS_URL; class DownloadsAdapter extends RecyclerView.Adapter { - /** - * Debug Tag for logging debug output to LogCat - */ - @SuppressWarnings("unused") - private static final String TAG = "DownloadsAdapter"; private final int VIEW_TYPE_DOWNLOAD = 0; private final int VIEW_TYPE_LOADING = 1; diff --git a/app/src/main/java/gr/thmmy/mthmmy/activities/main/MainActivity.java b/app/src/main/java/gr/thmmy/mthmmy/activities/main/MainActivity.java index 5e701d6e..d3d38870 100644 --- a/app/src/main/java/gr/thmmy/mthmmy/activities/main/MainActivity.java +++ b/app/src/main/java/gr/thmmy/mthmmy/activities/main/MainActivity.java @@ -38,7 +38,6 @@ import static gr.thmmy.mthmmy.activities.topic.TopicActivity.BUNDLE_TOPIC_URL; public class MainActivity extends BaseActivity implements RecentFragment.RecentFragmentInteractionListener, ForumFragment.ForumFragmentInteractionListener { //----------------------------------------CLASS VARIABLES----------------------------------------- - private static final String TAG = "MainActivity"; private static final int TIME_INTERVAL = 2000; private long mBackPressed; diff --git a/app/src/main/java/gr/thmmy/mthmmy/activities/main/forum/ForumFragment.java b/app/src/main/java/gr/thmmy/mthmmy/activities/main/forum/ForumFragment.java index d9777cf7..8bcecc25 100644 --- a/app/src/main/java/gr/thmmy/mthmmy/activities/main/forum/ForumFragment.java +++ b/app/src/main/java/gr/thmmy/mthmmy/activities/main/forum/ForumFragment.java @@ -30,10 +30,11 @@ import gr.thmmy.mthmmy.model.Board; import gr.thmmy.mthmmy.model.Category; import gr.thmmy.mthmmy.session.SessionManager; import me.zhanghai.android.materialprogressbar.MaterialProgressBar; -import mthmmy.utils.Report; + import okhttp3.HttpUrl; import okhttp3.Request; import okhttp3.Response; +import timber.log.Timber; /** * A {@link BaseFragment} subclass. @@ -87,7 +88,7 @@ public class ForumFragment extends BaseFragment forumTask.execute(); } - Report.d(TAG, "onActivityCreated"); + Timber.d("onActivityCreated"); } @Override @@ -151,8 +152,7 @@ public class ForumFragment extends BaseFragment //---------------------------------------ASYNC TASK----------------------------------- - public class ForumTask extends AsyncTask { - private static final String TAG = "ForumTask"; + private class ForumTask extends AsyncTask { private HttpUrl forumUrl = SessionManager.forumUrl; //may change upon collapse/expand private Document document; @@ -179,10 +179,10 @@ public class ForumFragment extends BaseFragment fetchedCategories.clear(); return 0; } catch (IOException e) { - Report.d(TAG, "Network Error", e); + Timber.d("Network Error", e); return 1; } catch (Exception e) { - Report.d(TAG, "Exception", e); + Timber.d("Exception", e); return 2; } @@ -225,7 +225,7 @@ public class ForumFragment extends BaseFragment } } else - Report.e(TAG, "Parsing failed!"); + Timber.e("Parsing failed!"); } public void setUrl(String string) diff --git a/app/src/main/java/gr/thmmy/mthmmy/activities/main/recent/RecentFragment.java b/app/src/main/java/gr/thmmy/mthmmy/activities/main/recent/RecentFragment.java index 7cd9ef63..d9e92599 100644 --- a/app/src/main/java/gr/thmmy/mthmmy/activities/main/recent/RecentFragment.java +++ b/app/src/main/java/gr/thmmy/mthmmy/activities/main/recent/RecentFragment.java @@ -29,10 +29,11 @@ import gr.thmmy.mthmmy.session.SessionManager; import gr.thmmy.mthmmy.utils.CustomRecyclerView; import gr.thmmy.mthmmy.utils.exceptions.ParseException; import me.zhanghai.android.materialprogressbar.MaterialProgressBar; -import mthmmy.utils.Report; + import okhttp3.HttpUrl; import okhttp3.Request; import okhttp3.Response; +import timber.log.Timber; /** * A {@link BaseFragment} subclass. @@ -86,7 +87,7 @@ public class RecentFragment extends BaseFragment { recentTask.execute(); } - Report.d(TAG, "onActivityCreated"); + Timber.d("onActivityCreated"); } @@ -141,8 +142,7 @@ public class RecentFragment extends BaseFragment { //---------------------------------------ASYNC TASK----------------------------------- - public class RecentTask extends AsyncTask { - private static final String TAG = "RecentTask"; + private class RecentTask extends AsyncTask { private final HttpUrl thmmyUrl = SessionManager.indexUrl; private Document document; @@ -161,13 +161,13 @@ public class RecentFragment extends BaseFragment { parse(document); return 0; } catch (ParseException e) { - Report.e(TAG, "ParseException", e); + Timber.e("ParseException", e); return 1; } catch (IOException e) { - Report.i(TAG, "Network Error", e); + Timber.i("Network Error", e); return 2; } catch (Exception e) { - Report.e(TAG, "Exception", e); + Timber.e("Exception", e); return 3; } diff --git a/app/src/main/java/gr/thmmy/mthmmy/activities/profile/ProfileActivity.java b/app/src/main/java/gr/thmmy/mthmmy/activities/profile/ProfileActivity.java index 2444bf95..08495dd9 100644 --- a/app/src/main/java/gr/thmmy/mthmmy/activities/profile/ProfileActivity.java +++ b/app/src/main/java/gr/thmmy/mthmmy/activities/profile/ProfileActivity.java @@ -19,7 +19,7 @@ import android.text.SpannableString; import android.text.Spanned; import android.text.style.ForegroundColorSpan; import android.text.style.RelativeSizeSpan; -import android.util.Log; + import android.view.View; import android.widget.ImageView; import android.widget.ProgressBar; @@ -50,9 +50,10 @@ import gr.thmmy.mthmmy.model.ThmmyPage; import gr.thmmy.mthmmy.utils.CenterVerticalSpan; import gr.thmmy.mthmmy.utils.CircleTransform; import me.zhanghai.android.materialprogressbar.MaterialProgressBar; -import mthmmy.utils.Report; + import okhttp3.Request; import okhttp3.Response; +import timber.log.Timber; import static gr.thmmy.mthmmy.activities.topic.TopicActivity.BUNDLE_TOPIC_TITLE; import static gr.thmmy.mthmmy.activities.topic.TopicActivity.BUNDLE_TOPIC_URL; @@ -64,11 +65,6 @@ import static gr.thmmy.mthmmy.activities.topic.TopicActivity.BUNDLE_TOPIC_URL; * the username using the key {@link #BUNDLE_PROFILE_USERNAME}. */ public class ProfileActivity extends BaseActivity implements LatestPostsFragment.LatestPostsFragmentInteractionListener { - /** - * Debug Tag for logging debug output to LogCat - */ - @SuppressWarnings("unused") - private static final String TAG = "ProfileActivity"; /** * The key to use when putting profile's url String to {@link ProfileActivity}'s Bundle. */ @@ -179,7 +175,7 @@ public class ProfileActivity extends BaseActivity implements LatestPostsFragment ThmmyPage.PageCategory target = ThmmyPage.resolvePageCategory(Uri.parse(profileUrl)); if (!target.is(ThmmyPage.PageCategory.PROFILE)) { - Report.e(TAG, "Bundle came with a non profile url!\nUrl:\n" + profileUrl); + Timber.e("Bundle came with a non profile url!\nUrl:\n%s" , profileUrl); Toast.makeText(this, "An error has occurred\n Aborting.", Toast.LENGTH_SHORT).show(); finish(); } @@ -222,11 +218,6 @@ public class ProfileActivity extends BaseActivity implements LatestPostsFragment */ public class ProfileTask extends AsyncTask { //Class variables - /** - * Debug Tag for logging debug output to LogCat - */ - @SuppressWarnings("unused") - private static final String TAG = "ProfileTask"; //Separate tag for AsyncTask Document profilePage; Spannable usernameSpan; @@ -262,7 +253,7 @@ public class ProfileActivity extends BaseActivity implements LatestPostsFragment } else { //Should never get here! //Something is wrong. - Report.e(TAG, "An error occurred while trying to find profile's personal text."); + Timber.e("An error occurred while trying to find profile's personal text."); personalText = null; } } @@ -283,16 +274,16 @@ public class ProfileActivity extends BaseActivity implements LatestPostsFragment } return true; } catch (SSLHandshakeException e) { - Report.w(TAG, "Certificate problem (please switch to unsafe connection)."); + Timber.w("Certificate problem (please switch to unsafe connection)."); } catch (Exception e) { - Report.e("TAG", "ERROR", e); + Timber.e("ERROR", e); } return false; } protected void onPostExecute(Boolean result) { - if (!result) { //Parse failed! - Report.d(TAG, "Parse failed!"); + if (!result) { //Parse failed! //TODO report as ParseException? + Timber.d("Parse failed!"); Toast.makeText(getBaseContext(), "Fatal error!\n Aborting..." , Toast.LENGTH_LONG).show(); finish(); @@ -344,7 +335,7 @@ public class ProfileActivity extends BaseActivity implements LatestPostsFragment viewPager.setAdapter(adapter); } - class ViewPagerAdapter extends FragmentPagerAdapter { + private class ViewPagerAdapter extends FragmentPagerAdapter { private final List mFragmentList = new ArrayList<>(); private final List mFragmentTitleList = new ArrayList<>(); diff --git a/app/src/main/java/gr/thmmy/mthmmy/activities/profile/latestPosts/LatestPostsAdapter.java b/app/src/main/java/gr/thmmy/mthmmy/activities/profile/latestPosts/LatestPostsAdapter.java index 5f0f77d2..13319607 100644 --- a/app/src/main/java/gr/thmmy/mthmmy/activities/profile/latestPosts/LatestPostsAdapter.java +++ b/app/src/main/java/gr/thmmy/mthmmy/activities/profile/latestPosts/LatestPostsAdapter.java @@ -21,11 +21,6 @@ import me.zhanghai.android.materialprogressbar.MaterialProgressBar; * specified {@link LatestPostsFragment.LatestPostsFragmentInteractionListener}. */ class LatestPostsAdapter extends RecyclerView.Adapter { - /** - * Debug Tag for logging debug output to LogCat - */ - @SuppressWarnings("unused") - private static final String TAG = "LatestPostsAdapter"; private final int VIEW_TYPE_ITEM = 0; private final int VIEW_TYPE_LOADING = 1; final private LatestPostsFragment.LatestPostsFragmentInteractionListener interactionListener; diff --git a/app/src/main/java/gr/thmmy/mthmmy/activities/profile/latestPosts/LatestPostsFragment.java b/app/src/main/java/gr/thmmy/mthmmy/activities/profile/latestPosts/LatestPostsFragment.java index ccdb5593..5c3f8d40 100644 --- a/app/src/main/java/gr/thmmy/mthmmy/activities/profile/latestPosts/LatestPostsFragment.java +++ b/app/src/main/java/gr/thmmy/mthmmy/activities/profile/latestPosts/LatestPostsFragment.java @@ -26,19 +26,15 @@ import gr.thmmy.mthmmy.base.BaseFragment; import gr.thmmy.mthmmy.model.PostSummary; import gr.thmmy.mthmmy.utils.ParseHelpers; import me.zhanghai.android.materialprogressbar.MaterialProgressBar; -import mthmmy.utils.Report; + import okhttp3.Request; import okhttp3.Response; +import timber.log.Timber; /** * Use the {@link LatestPostsFragment#newInstance} factory method to create an instance of this fragment. */ public class LatestPostsFragment extends BaseFragment implements LatestPostsAdapter.OnLoadMoreListener{ - /** - * Debug Tag for logging debug output to LogCat - */ - @SuppressWarnings("unused") - private static final String TAG = "LatestPostsFragment"; /** * The key to use when putting profile's url String to {@link LatestPostsFragment}'s Bundle. */ @@ -136,7 +132,7 @@ public class LatestPostsFragment extends BaseFragment implements LatestPostsAdap profileLatestPostsTask.execute(profileUrl + ";sa=showPosts"); pagesLoaded = 1; } - Report.d(TAG, "onActivityCreated"); + Timber.d("onActivityCreated"); } @Override @@ -156,14 +152,7 @@ public class LatestPostsFragment extends BaseFragment implements LatestPostsAdap *

    LatestPostsTask's {@link AsyncTask#execute execute} method needs a profile's url as String * parameter!

    */ - public class LatestPostsTask extends AsyncTask { - //Class variables - /** - * Debug Tag for logging debug output to LogCat - */ - @SuppressWarnings("unused") - private static final String TAG = "LatestPostsTask"; //Separate tag for AsyncTask - + private class LatestPostsTask extends AsyncTask { protected void onPreExecute() { if (!isLoadingMore) progressBar.setVisibility(ProgressBar.VISIBLE); } @@ -176,16 +165,16 @@ public class LatestPostsFragment extends BaseFragment implements LatestPostsAdap Response response = BaseActivity.getClient().newCall(request).execute(); return parseLatestPosts(Jsoup.parse(response.body().string())); } catch (SSLHandshakeException e) { - Report.w(TAG, "Certificate problem (please switch to unsafe connection)."); + Timber.w("Certificate problem (please switch to unsafe connection)."); } catch (Exception e) { - Report.e("TAG", "ERROR", e); + Timber.e("ERROR", e); } return false; } protected void onPostExecute(Boolean result) { if (!result) { //Parse failed! - Report.d(TAG, "Parse failed!"); + Timber.d("Parse failed!"); Toast.makeText(getContext() , "Fatal error!\n Aborting...", Toast.LENGTH_LONG).show(); getActivity().finish(); diff --git a/app/src/main/java/gr/thmmy/mthmmy/activities/profile/stats/StatsFragment.java b/app/src/main/java/gr/thmmy/mthmmy/activities/profile/stats/StatsFragment.java index 2e102c0e..f573f3db 100644 --- a/app/src/main/java/gr/thmmy/mthmmy/activities/profile/stats/StatsFragment.java +++ b/app/src/main/java/gr/thmmy/mthmmy/activities/profile/stats/StatsFragment.java @@ -41,16 +41,12 @@ import javax.net.ssl.SSLHandshakeException; import gr.thmmy.mthmmy.R; import gr.thmmy.mthmmy.base.BaseActivity; import me.zhanghai.android.materialprogressbar.MaterialProgressBar; -import mthmmy.utils.Report; + import okhttp3.Request; import okhttp3.Response; +import timber.log.Timber; public class StatsFragment extends Fragment { - /** - * Debug Tag for logging debug output to LogCat - */ - @SuppressWarnings("unused") - private static final String TAG = "StatsFragment"; /** * The key to use when putting profile's url String to {@link StatsFragment}'s Bundle. */ @@ -109,7 +105,7 @@ public class StatsFragment extends Fragment { profileStatsTask = new ProfileStatsTask(); profileStatsTask.execute(profileUrl + ";sa=statPanel"); } - Report.d(TAG, "onActivityCreated"); + Timber.d("onActivityCreated"); } @Override @@ -127,14 +123,7 @@ public class StatsFragment extends Fragment { *

    Calling SummaryTask's {@link AsyncTask#execute execute} method needs to have profile's url * as String parameter!

    */ - public class ProfileStatsTask extends AsyncTask { - //Class variables - /** - * Debug Tag for logging debug output to LogCat - */ - @SuppressWarnings("unused") - private static final String TAG = "ProfileStatsTask"; //Separate tag for AsyncTask - + private class ProfileStatsTask extends AsyncTask { @Override protected void onPreExecute() { progressBar.setVisibility(ProgressBar.VISIBLE); @@ -150,9 +139,9 @@ public class StatsFragment extends Fragment { Response response = BaseActivity.getClient().newCall(request).execute(); return parseStats(Jsoup.parse(response.body().string())); } catch (SSLHandshakeException e) { - Report.w(TAG, "Certificate problem (please switch to unsafe connection)."); + Timber.w("Certificate problem (please switch to unsafe connection)."); } catch (Exception e) { - Report.e("TAG", "ERROR", e); + Timber.e("ERROR", e); } return false; } @@ -160,7 +149,7 @@ public class StatsFragment extends Fragment { @Override protected void onPostExecute(Boolean result) { if (!result) { //Parse failed! - Report.d(TAG, "Parse failed!"); + Timber.d("Parse failed!"); Toast.makeText(getContext() , "Fatal error!\n Aborting...", Toast.LENGTH_LONG).show(); getActivity().finish(); @@ -348,7 +337,7 @@ public class StatsFragment extends Fragment { mostPopularBoardsByActivityChart.invalidate(); } - class MyXAxisValueFormatter implements IAxisValueFormatter { + private class MyXAxisValueFormatter implements IAxisValueFormatter { private final ArrayList mValues; MyXAxisValueFormatter(ArrayList values) { diff --git a/app/src/main/java/gr/thmmy/mthmmy/activities/profile/summary/SummaryFragment.java b/app/src/main/java/gr/thmmy/mthmmy/activities/profile/summary/SummaryFragment.java index f876b6ff..70644bf4 100644 --- a/app/src/main/java/gr/thmmy/mthmmy/activities/profile/summary/SummaryFragment.java +++ b/app/src/main/java/gr/thmmy/mthmmy/activities/profile/summary/SummaryFragment.java @@ -7,7 +7,7 @@ import android.os.Bundle; import android.support.v4.app.Fragment; import android.text.Html; import android.text.method.LinkMovementMethod; -import android.util.Log; + import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; @@ -25,18 +25,14 @@ import java.util.Objects; import gr.thmmy.mthmmy.R; import gr.thmmy.mthmmy.utils.ParseHelpers; -import mthmmy.utils.Report; + +import timber.log.Timber; /** * Use the {@link SummaryFragment#newInstance} factory method to create an instance of this fragment. */ public class SummaryFragment extends Fragment { - /** - * Debug Tag for logging debug output to LogCat - */ - @SuppressWarnings("unused") - private static final String TAG = "SummaryFragment"; /** * The key to use when putting profile's source code String to {@link SummaryFragment}'s Bundle. */ @@ -96,7 +92,7 @@ public class SummaryFragment extends Fragment { summaryTask = new SummaryTask(); summaryTask.execute(profileSummaryDocument); } - Report.d(TAG, "onActivityCreated"); + Timber.d("onActivityCreated"); } @Override @@ -114,14 +110,7 @@ public class SummaryFragment extends Fragment { *

    Calling SummaryTask's {@link AsyncTask#execute execute} method needs to have profile's url * as String parameter!

    */ - public class SummaryTask extends AsyncTask { - //Class variables - /** - * Debug Tag for logging debug output to LogCat - */ - @SuppressWarnings("unused") - private static final String TAG = "SummaryTask"; //Separate tag for AsyncTask - + private class SummaryTask extends AsyncTask { protected Void doInBackground(Document... profileSummaryPage) { parsedProfileSummaryData = parseProfileSummary(profileSummaryPage[0]); return null; @@ -193,8 +182,8 @@ public class SummaryFragment extends Fragment { if (profileSummaryRow.contains("@") && (profileSummaryRow.contains("Email") || profileSummaryRow.contains("E-mail"))) { - Log.d(TAG, "mpika"); - Log.d(TAG, profileSummaryRow); + Timber.d("mpika"); + Timber.d(profileSummaryRow); String email = profileSummaryRow.substring(profileSummaryRow.indexOf(": ") + 6); profileSummaryRow = profileSummaryRow.replace(email, "" + email + ""); diff --git a/app/src/main/java/gr/thmmy/mthmmy/activities/topic/ReplyParser.java b/app/src/main/java/gr/thmmy/mthmmy/activities/topic/ReplyParser.java index 4950478b..ca47585a 100644 --- a/app/src/main/java/gr/thmmy/mthmmy/activities/topic/ReplyParser.java +++ b/app/src/main/java/gr/thmmy/mthmmy/activities/topic/ReplyParser.java @@ -10,12 +10,6 @@ import java.io.IOException; import okhttp3.Response; class ReplyParser { - /** - * Debug Tag for logging debug output to LogCat - */ - @SuppressWarnings("unused") - private static final String TAG = "ReplyParser"; - enum REPLY_STATUS { SUCCESSFUL, NO_SUBJECT, EMPTY_BODY, NEW_REPLY_WHILE_POSTING, NOT_FOUND, SESSION_ENDED, OTHER_ERROR } diff --git a/app/src/main/java/gr/thmmy/mthmmy/activities/topic/TopicActivity.java b/app/src/main/java/gr/thmmy/mthmmy/activities/topic/TopicActivity.java index 710170fa..942dd50c 100644 --- a/app/src/main/java/gr/thmmy/mthmmy/activities/topic/TopicActivity.java +++ b/app/src/main/java/gr/thmmy/mthmmy/activities/topic/TopicActivity.java @@ -47,11 +47,12 @@ import gr.thmmy.mthmmy.model.Post; import gr.thmmy.mthmmy.model.ThmmyPage; import gr.thmmy.mthmmy.utils.ParseHelpers; import me.zhanghai.android.materialprogressbar.MaterialProgressBar; -import mthmmy.utils.Report; + 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; @@ -69,11 +70,6 @@ import static gr.thmmy.mthmmy.activities.topic.ReplyParser.replyStatus; @SuppressWarnings("unchecked") public class TopicActivity extends BaseActivity { //Class variables - /** - * Debug Tag for logging debug output to LogCat - */ - @SuppressWarnings("unused") - private static final String TAG = "TopicActivity"; /** * The key to use when putting topic's url String to {@link TopicActivity}'s Bundle. */ @@ -134,7 +130,7 @@ public class TopicActivity extends BaseActivity { ThmmyPage.PageCategory target = ThmmyPage.resolvePageCategory( Uri.parse(topicPageUrl)); if (!target.is(ThmmyPage.PageCategory.TOPIC)) { - Report.e(TAG, "Bundle came with a non topic url!\nUrl:\n" + topicPageUrl); + Timber.e("Bundle came with a non topic url!\nUrl:\n" + topicPageUrl); Toast.makeText(this, "An error has occurred\n Aborting.", Toast.LENGTH_SHORT).show(); finish(); } @@ -455,11 +451,6 @@ public class TopicActivity extends BaseActivity { * as String parameter!

    */ class TopicTask extends AsyncTask { - //Class variables - /** - * Debug Tag for logging debug output to LogCat - */ - private static final String TAG = "TopicTask"; //Separate tag for AsyncTask private static final int SUCCESS = 0; private static final int NETWORK_ERROR = 1; private static final int OTHER_ERROR = 2; @@ -518,10 +509,10 @@ public class TopicActivity extends BaseActivity { parse(document); return SUCCESS; } catch (IOException e) { - Report.i(TAG, "IO Exception", e); + Timber.i("IO Exception", e); return NETWORK_ERROR; } catch (Exception e) { - Report.e(TAG, "Exception", e); + Timber.e("Exception", e); return OTHER_ERROR; } } @@ -570,7 +561,7 @@ public class TopicActivity extends BaseActivity { break; default: //Parse failed - should never happen - Report.d(TAG, "Parse failed!"); + Timber.d("Parse failed!"); //TODO report ParseException? Toast.makeText(getBaseContext(), "Fatal Error", Toast.LENGTH_SHORT).show(); finish(); break; @@ -609,7 +600,7 @@ public class TopicActivity extends BaseActivity { } else { parsedTitle = parsedTitle.substring(parsedTitle.indexOf("Θέμα:") + 6 , parsedTitle.indexOf("(Αναγνώστηκε") - 2); - Report.d(TAG, parsedTitle); + Timber.d(parsedTitle); } } @@ -700,10 +691,10 @@ public class TopicActivity extends BaseActivity { subject = document.select("input[name=subject]").first().attr("value"); topic = document.select("input[name=topic]").first().attr("value"); } catch (IOException e) { - Report.e(TAG, "Post failed.", e); + Timber.e("Post failed.", e); return false; } catch (Selector.SelectorParseException e) { - Report.e(TAG, "Post failed.", e); + Timber.e("Post failed.", e); return false; } @@ -733,11 +724,11 @@ public class TopicActivity extends BaseActivity { //TODO this... return true; default: - Report.e(TAG, "Malformed post. Request string:\n" + post.toString()); + Timber.e("Malformed post. Request string:\n" + post.toString()); return true; } } catch (IOException e) { - Report.e(TAG, "Post failed.", e); + Timber.e("Post failed.", e); return false; } } diff --git a/app/src/main/java/gr/thmmy/mthmmy/activities/topic/TopicAdapter.java b/app/src/main/java/gr/thmmy/mthmmy/activities/topic/TopicAdapter.java index 59c529af..3f5154fb 100644 --- a/app/src/main/java/gr/thmmy/mthmmy/activities/topic/TopicAdapter.java +++ b/app/src/main/java/gr/thmmy/mthmmy/activities/topic/TopicAdapter.java @@ -18,7 +18,7 @@ import android.support.v7.widget.RecyclerView; import android.text.Editable; import android.text.TextUtils; import android.text.TextWatcher; -import android.util.Log; + import android.view.LayoutInflater; import android.view.MotionEvent; import android.view.View; @@ -54,7 +54,8 @@ 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 mthmmy.utils.Report; + +import timber.log.Timber; import static android.content.Intent.FLAG_ACTIVITY_NEW_TASK; import static gr.thmmy.mthmmy.activities.board.BoardActivity.BUNDLE_BOARD_TITLE; @@ -68,10 +69,6 @@ import static gr.thmmy.mthmmy.base.BaseActivity.getSessionManager; * Custom {@link android.support.v7.widget.RecyclerView.Adapter} used for topics. */ class TopicAdapter extends RecyclerView.Adapter { - /** - * Debug Tag for logging debug output to LogCat - */ - private static final String TAG = "TopicAdapter"; /** * Int that holds thumbnail's size defined in R.dimen */ @@ -415,7 +412,7 @@ class TopicAdapter extends RecyclerView.Adapter { if (toQuoteList.contains(postsList.indexOf(currentPost))) { toQuoteList.remove(toQuoteList.indexOf(postsList.indexOf(currentPost))); } else - Report.i(TAG, "An error occurred while trying to exclude post from" + + Timber.i("An error occurred while trying to exclude post from" + "toQuoteList, post wasn't there!"); holder.quoteToggle.setImageResource(R.drawable.ic_format_quote_unchecked); } else { diff --git a/app/src/main/java/gr/thmmy/mthmmy/activities/topic/TopicParser.java b/app/src/main/java/gr/thmmy/mthmmy/activities/topic/TopicParser.java index 9229c6b9..7d21196a 100644 --- a/app/src/main/java/gr/thmmy/mthmmy/activities/topic/TopicParser.java +++ b/app/src/main/java/gr/thmmy/mthmmy/activities/topic/TopicParser.java @@ -17,7 +17,8 @@ import java.util.Objects; import gr.thmmy.mthmmy.model.Post; import gr.thmmy.mthmmy.model.ThmmyFile; import gr.thmmy.mthmmy.utils.ParseHelpers; -import mthmmy.utils.Report; +import timber.log.Timber; + /** * Singleton used for parsing a topic. @@ -36,12 +37,6 @@ class TopicParser { static final int USER_COLOR_PINK = Color.parseColor("#FF4081"); private static final int USER_COLOR_YELLOW = Color.parseColor("#FFEB3B"); - /** - * Debug Tag for logging debug output to LogCat - */ - @SuppressWarnings("unused") - private static final String TAG = "TopicParser"; - /** * Returns users currently viewing this topic. * @@ -257,7 +252,7 @@ class TopicParser { try { attachedUrl = new URL(tmpAttachedFileUrlAndName.attr("href")); } catch (MalformedURLException e) { - Report.e(TAG, "Attached file malformed url", e); + Timber.e("Attached file malformed url", e); break; } String attachedFileName = tmpAttachedFileUrlAndName.text().substring(1); @@ -317,7 +312,7 @@ class TopicParser { try { attachedUrl = new URL(tmpAttachedFileUrlAndName.attr("href")); } catch (MalformedURLException e) { - Report.e(TAG, "Attached file malformed url", e); + Timber.e("Attached file malformed url", e); break; } String attachedFileName = tmpAttachedFileUrlAndName.text().substring(1); diff --git a/app/src/main/java/gr/thmmy/mthmmy/base/BaseApplication.java b/app/src/main/java/gr/thmmy/mthmmy/base/BaseApplication.java index b119dabe..3030cce0 100644 --- a/app/src/main/java/gr/thmmy/mthmmy/base/BaseApplication.java +++ b/app/src/main/java/gr/thmmy/mthmmy/base/BaseApplication.java @@ -23,13 +23,16 @@ import java.io.IOException; import java.util.Objects; import java.util.concurrent.TimeUnit; +import gr.thmmy.mthmmy.BuildConfig; import gr.thmmy.mthmmy.R; import gr.thmmy.mthmmy.session.SessionManager; +import gr.thmmy.mthmmy.utils.CrashReportingTree; import okhttp3.HttpUrl; import okhttp3.Interceptor; import okhttp3.OkHttpClient; import okhttp3.Request; import okhttp3.Response; +import timber.log.Timber; public class BaseApplication extends Application { @@ -55,6 +58,12 @@ public class BaseApplication extends Application { super.onCreate(); baseApplication = this; //init singleton + if (BuildConfig.DEBUG) { + Timber.plant(new Timber.DebugTree()); + } else { + Timber.plant(new CrashReportingTree()); + } + SharedPreferences sharedPrefs = getSharedPreferences(SHARED_PREFS_NAME, MODE_PRIVATE); SharedPrefsCookiePersistor sharedPrefsCookiePersistor = new SharedPrefsCookiePersistor(getApplicationContext()); PersistentCookieJar cookieJar = new PersistentCookieJar(new SetCookieCache(), sharedPrefsCookiePersistor); diff --git a/app/src/main/java/gr/thmmy/mthmmy/base/BaseFragment.java b/app/src/main/java/gr/thmmy/mthmmy/base/BaseFragment.java index c7b3d477..c33ffdf6 100644 --- a/app/src/main/java/gr/thmmy/mthmmy/base/BaseFragment.java +++ b/app/src/main/java/gr/thmmy/mthmmy/base/BaseFragment.java @@ -5,8 +5,8 @@ import android.os.Bundle; import android.support.annotation.Nullable; import android.support.v4.app.Fragment; -import mthmmy.utils.Report; import okhttp3.OkHttpClient; +import timber.log.Timber; public abstract class BaseFragment extends Fragment { protected static final String ARG_SECTION_NUMBER = "SectionNumber"; @@ -26,31 +26,31 @@ public abstract class BaseFragment extends Fragment { if(client==null) client = BaseApplication.getInstance().getClient(); //must check every time - e.g. // becomes null when app restarts after crash - Report.d(TAG, "onCreate"); + Timber.d("onCreate"); } @Override public void onStart() { super.onStart(); - Report.d(TAG, "onStart"); + Timber.d("onStart"); } @Override public void onResume() { super.onResume(); - Report.d(TAG, "onResume"); + Timber.d("onResume"); } @Override public void onPause() { super.onPause(); - Report.d(TAG, "onPause"); + Timber.d("onPause"); } @Override public void onStop() { super.onStop(); - Report.d(TAG, "onStop"); + Timber.d("onStop"); } @Override diff --git a/app/src/main/java/gr/thmmy/mthmmy/model/ThmmyPage.java b/app/src/main/java/gr/thmmy/mthmmy/model/ThmmyPage.java index cc9a1781..38f95867 100644 --- a/app/src/main/java/gr/thmmy/mthmmy/model/ThmmyPage.java +++ b/app/src/main/java/gr/thmmy/mthmmy/model/ThmmyPage.java @@ -4,7 +4,7 @@ import android.net.Uri; import java.util.Objects; -import mthmmy.utils.Report; +import timber.log.Timber; /** * This class consists exclusively of static classes (enums) and methods (excluding methods of inner @@ -162,7 +162,7 @@ public class ThmmyPage { || Objects.equals(uriString, "https://www.thmmy.gr") || Objects.equals(uriString, "https://www.thmmy.gr/smf/index.php")) return PageCategory.INDEX; - Report.v(TAG, "Unknown thmmy link found, link: " + uriString); + Timber.v("Unknown thmmy link found, link: " + uriString); return PageCategory.UNKNOWN_THMMY; } return PageCategory.NOT_THMMY; diff --git a/app/src/main/java/gr/thmmy/mthmmy/receiver/Receiver.java b/app/src/main/java/gr/thmmy/mthmmy/receiver/Receiver.java index 3e811134..d93f4272 100644 --- a/app/src/main/java/gr/thmmy/mthmmy/receiver/Receiver.java +++ b/app/src/main/java/gr/thmmy/mthmmy/receiver/Receiver.java @@ -14,7 +14,8 @@ import android.webkit.MimeTypeMap; import java.io.File; import gr.thmmy.mthmmy.R; -import mthmmy.utils.Report; + +import timber.log.Timber; import static gr.thmmy.mthmmy.services.DownloadService.ACTION_DOWNLOAD; import static gr.thmmy.mthmmy.services.DownloadService.COMPLETED; @@ -28,7 +29,6 @@ import static gr.thmmy.mthmmy.services.DownloadService.SAVE_DIR; import static gr.thmmy.mthmmy.services.DownloadService.STARTED; public class Receiver extends BroadcastReceiver { - private static final String TAG = "BroadcastReceiver"; public Receiver() { } @@ -72,7 +72,7 @@ public class Receiver extends BroadcastReceiver { builder.setContentIntent(pendingIntent); } else - Report.w(TAG, "File doesn't exist."); + Timber.w("File doesn't exist."); } Notification notification = builder.build(); notificationManager.notify(id, notification); diff --git a/app/src/main/java/gr/thmmy/mthmmy/services/DownloadService.java b/app/src/main/java/gr/thmmy/mthmmy/services/DownloadService.java index 7339fa73..cd878b25 100644 --- a/app/src/main/java/gr/thmmy/mthmmy/services/DownloadService.java +++ b/app/src/main/java/gr/thmmy/mthmmy/services/DownloadService.java @@ -13,12 +13,13 @@ import java.io.IOException; import gr.thmmy.mthmmy.base.BaseApplication; import gr.thmmy.mthmmy.receiver.Receiver; -import mthmmy.utils.Report; + import okhttp3.OkHttpClient; import okhttp3.Request; import okhttp3.Response; import okio.BufferedSink; import okio.Okio; +import timber.log.Timber; /** * An {@link IntentService} subclass for handling asynchronous task requests in @@ -116,9 +117,9 @@ public class DownloadService extends IntentService { if(!dirPath.isDirectory()) { if(dirPath.mkdirs()) - Report.i(TAG, "mTHMMY's directory created successfully!"); + Timber.i("mTHMMY's directory created successfully!"); else - Report.e(TAG, "Couldn't create mTHMMY's directory..."); + Timber.e("Couldn't create mTHMMY's directory..."); } @@ -127,7 +128,7 @@ public class DownloadService extends IntentService { if(tokens.length!=2) { - Report.w(TAG, "Couldn't get file extension..."); + Timber.w("Couldn't get file extension..."); nameFormat = fileName + "(%d)"; } else @@ -148,26 +149,26 @@ public class DownloadService extends IntentService { fileName = file.getName(); - Report.v(TAG, "Started saving file " + fileName); + Timber.v("Started saving file " + fileName); sendNotification(downloadId, STARTED, fileName); sink = Okio.buffer(Okio.sink(file)); sink.writeAll(response.body().source()); sink.flush(); - Report.i(TAG, "Download OK!"); + Timber.i("Download OK!"); sendNotification(downloadId, COMPLETED, fileName); } else - Report.e(TAG, "Response not a binary file!"); + Timber.e("Response not a binary file!"); } catch (FileNotFoundException e){ - Report.i(TAG, "Download failed..."); - Report.e(TAG, "FileNotFound", e); + Timber.i("Download failed..."); + Timber.e("FileNotFound", e); sendNotification(downloadId, FAILED, fileName); } catch (IOException e){ - Report.i(TAG, "Download failed..."); - Report.e(TAG, "IOException", e); + Timber.i("Download failed..."); + Timber.e("IOException", e); sendNotification(downloadId, FAILED, fileName); } finally { if (sink!= null) { @@ -203,7 +204,7 @@ public class DownloadService extends IntentService { break; } default:{ - Report.wtf(TAG, "Invalid notification case!"); + Timber.e("Invalid notification case!"); return; } } diff --git a/app/src/main/java/gr/thmmy/mthmmy/session/SessionManager.java b/app/src/main/java/gr/thmmy/mthmmy/session/SessionManager.java index c6bbd713..ce0f9228 100644 --- a/app/src/main/java/gr/thmmy/mthmmy/session/SessionManager.java +++ b/app/src/main/java/gr/thmmy/mthmmy/session/SessionManager.java @@ -18,7 +18,6 @@ import java.util.regex.Matcher; import java.util.regex.Pattern; import gr.thmmy.mthmmy.utils.exceptions.ParseException; -import mthmmy.utils.Report; import okhttp3.Cookie; import okhttp3.FormBody; import okhttp3.HttpUrl; @@ -26,15 +25,13 @@ import okhttp3.OkHttpClient; import okhttp3.Request; import okhttp3.RequestBody; import okhttp3.Response; +import timber.log.Timber; /** * This class handles all session related operations (e.g. login, logout) * and stores data to SharedPreferences (session information and cookies). */ public class SessionManager { - //Class TAG - private static final String TAG = "SessionManager"; - //Generic constants public static final HttpUrl indexUrl = HttpUrl.parse("https://www.thmmy.gr/smf/index.php?theme=4"); public static final HttpUrl forumUrl = HttpUrl.parse("https://www.thmmy.gr/smf/index.php?action=forum;theme=4"); @@ -80,7 +77,7 @@ public class SessionManager { * Always call it in a separate thread. */ public int login(String... strings) { - Report.i(TAG, "Logging in..."); + Timber.i("Logging in..."); //Build the login request for each case Request request; @@ -114,7 +111,7 @@ public class SessionManager { if (unreadRepliesLinks.size()>=2) //Normally it's just == 2, but who knows what can be posted by users { - Report.i(TAG, "Login successful!"); + Timber.i("Login successful!"); setPersistentCookieSession(); //Store cookies //Edit SharedPreferences, save session's data @@ -133,18 +130,18 @@ public class SessionManager { return SUCCESS; } else { - Report.i(TAG, "Login failed."); + Timber.i("Login failed."); //Investigate login failure Elements error = document.select("b:contains(That username does not exist.)"); if (error.size() == 1) { //Wrong username - Report.i(TAG, "Wrong Username"); + Timber.i("Wrong Username"); return WRONG_USER; } error = document.select("body:contains(Password incorrect)"); if (error.size() == 1) { //Wrong password - Report.i(TAG, "Wrong Password"); + Timber.i("Wrong Password"); return WRONG_PASSWORD; } @@ -154,13 +151,13 @@ public class SessionManager { } //Handle exception } catch (InterruptedIOException e) { - Report.i(TAG, "Login InterruptedIOException"); //users cancels LoginTask + Timber.i("Login InterruptedIOException"); //users cancels LoginTask return CANCELLED; } catch (IOException e) { - Report.w(TAG, "Login IOException", e); + Timber.w("Login IOException", e); return CONNECTION_ERROR; } catch (Exception e) { - Report.w(TAG, "Login Exception (other)", e); + Timber.w("Login Exception (other)", e); return EXCEPTION; } } @@ -175,7 +172,7 @@ public class SessionManager { * fragments' data are retrieved). */ public void validateSession() { - Report.i(TAG, "Validating session..."); + Timber.i("Validating session..."); if (isLoggedIn()) { int loginResult = login(); @@ -192,7 +189,7 @@ public class SessionManager { * Call this function when user explicitly chooses to continue as a guest (UI thread). */ public void guestLogin() { - Report.i("TAG", "Continuing as a guest, as chosen by the user."); + Timber.i("Continuing as a guest, as chosen by the user."); clearSessionData(); sharedPrefs.edit().putBoolean(LOGIN_SCREEN_AS_DEFAULT, false).apply(); } @@ -202,7 +199,7 @@ public class SessionManager { * Logout function. Always call it in a separate thread. */ public int logout() { - Report.i(TAG, "Logging out..."); + Timber.i("Logging out..."); Request request = new Request.Builder() .url(sharedPrefs.getString(LOGOUT_LINK, "LogoutLink")) @@ -216,17 +213,17 @@ public class SessionManager { Elements loginButton = document.select("[value=Login]"); //Attempt to find login button if (!loginButton.isEmpty()) //If login button exists, logout was successful { - Report.i(TAG, "Logout successful!"); + Timber.i("Logout successful!"); return SUCCESS; } else { - Report.i(TAG, "Logout failed."); + Timber.i("Logout failed."); return FAILURE; } } catch (IOException e) { - Report.w(TAG, "Logout IOException", e); + Timber.w("Logout IOException", e); return CONNECTION_ERROR; } catch (Exception e) { - Report.w(TAG, "Logout Exception", e); + Timber.w("Logout Exception", e); return EXCEPTION; } finally { //All data should always be cleared from device regardless the result of logout @@ -288,7 +285,7 @@ public class SessionManager { sharedPrefs.edit().clear().apply(); //Clear session data sharedPrefs.edit().putString(USERNAME, guestName).apply(); sharedPrefs.edit().putBoolean(LOGGED_IN, false).apply(); //User logs out - Report.i(TAG, "Session data cleared."); + Timber.i("Session data cleared."); } @NonNull @@ -321,7 +318,7 @@ public class SessionManager { if(userName != null && !userName.isEmpty()) return userName; - Report.e(TAG, "ParseException", new ParseException("Parsing failed(username extraction)")); + Timber.e("ParseException", new ParseException("Parsing failed(username extraction)")); return "User"; //return a default username } @@ -332,7 +329,7 @@ public class SessionManager { if (!avatar.isEmpty()) return avatar.first().attr("src"); - Report.i(TAG, "Extracting avatar's link failed!"); + Timber.i("Extracting avatar's link failed!"); return null; } @@ -346,7 +343,7 @@ public class SessionManager { if(link != null && !link.isEmpty()) return link; } - Report.e(TAG, "ParseException", new ParseException("Parsing failed(logoutLink extraction)")); + Timber.e("ParseException", new ParseException("Parsing failed(logoutLink extraction)")); return "https://www.thmmy.gr/smf/index.php?action=logout"; //return a default link } //----------------------------------OTHER FUNCTIONS END----------------------------------------- diff --git a/app/src/main/java/gr/thmmy/mthmmy/utils/CrashReportingTree.java b/app/src/main/java/gr/thmmy/mthmmy/utils/CrashReportingTree.java new file mode 100644 index 00000000..2aeca9a2 --- /dev/null +++ b/app/src/main/java/gr/thmmy/mthmmy/utils/CrashReportingTree.java @@ -0,0 +1,34 @@ +package gr.thmmy.mthmmy.utils; + +import android.util.Log; + +import com.google.firebase.crash.FirebaseCrash; + +import gr.thmmy.mthmmy.utils.exceptions.UnknownException; +import timber.log.Timber; + +public class CrashReportingTree extends Timber.Tree { + @Override + protected void log(int priority, String tag, String message, Throwable t) { + if (priority == Log.VERBOSE || priority == Log.DEBUG) { + return; + } + + String level="A"; + + if (priority == Log.INFO) + level = "I"; + else if (priority == Log.WARN) + level = "W"; + else if(priority == Log.ERROR) + level = "E"; + + FirebaseCrash.log(level + "/" + tag + ": " + message); + + if(t==null) + t = new UnknownException("UnknownException"); + + if ((priority == Log.ERROR)) + FirebaseCrash.report(t); + } +} diff --git a/app/src/release/java/mthmmy.utils/Report.java b/app/src/release/java/mthmmy.utils/Report.java deleted file mode 100644 index 4a6a46b8..00000000 --- a/app/src/release/java/mthmmy.utils/Report.java +++ /dev/null @@ -1,96 +0,0 @@ -package mthmmy.utils; - -import com.google.firebase.crash.FirebaseCrash; - -import gr.thmmy.mthmmy.utils.exceptions.UnknownException; - -public class Report -{ - - public static void v (String TAG, String message) - { - log("V", TAG, message); - } - - public static void v (String TAG, String message, Throwable tr) - { - exception("V", TAG, message, tr); - } - - public static void d (String TAG, String message) - { - log("D", TAG, message); - } - - public static void d (String TAG, String message, Throwable tr) - { - exception("D", TAG, message, tr); - } - - public static void i (String TAG, String message) - { - log("I", TAG, message); - } - - public static void i (String TAG, String message, Throwable tr) - { - exception("I", TAG, message, tr); - } - - public static void w (String TAG, String message) - { - log("W", TAG, message); - } - - public static void w (String TAG, String message, Throwable tr) - { - exception("W", TAG, message, tr); - } - - public static void e (String TAG, String message) - { - log("E", TAG, message); - } - - public static void e (String TAG, String message, Throwable tr) - { - exception("E", TAG, message, tr); - } - - public static void wtf (String TAG, String message) - { - log("WTF", TAG, message); - } - - public static void wtf (String TAG, String message, Throwable tr) - { - exception("WTF", TAG, message, tr); - } - - private static void log(String level, String TAG, String message) - { - if(!level.equals("V")&&!level.equals("D")) //don't log V and D levels - { - FirebaseCrash.log(level + "/" + TAG + ": " + message); - if(level.equals("E")||level.equals("WTF")) //report only serious exceptions - FirebaseCrash.report(new UnknownException("UnknownException")); - } - } - - private static void exception(String level, String TAG, String message, Throwable tr) - { - if(!level.equals("V")&&!level.equals("D")) //don't log V and D levels - { - FirebaseCrash.log(level + "/" + TAG + ": " + message + ": " + tr.getMessage()); - if(level.equals("E")||level.equals("WTF")) //report only serious exceptions - FirebaseCrash.report(tr); - } - } - - /** - * Does nothing in release. - */ - public static void longMessage(String TAG, String level, String message) {return;} - - -} diff --git a/build.gradle b/build.gradle index 25e7e862..a40a0e30 100644 --- a/build.gradle +++ b/build.gradle @@ -6,7 +6,7 @@ buildscript { maven { url "https://jitpack.io" } } dependencies { - classpath 'com.android.tools.build:gradle:2.2.3' + classpath 'com.android.tools.build:gradle:2.3.0' classpath 'com.google.gms:google-services:3.0.0' // NOTE: Do not place your application dependencies here; they belong // in the individual module build.gradle files diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index 04e285f3..8b6dacea 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,6 +1,6 @@ -#Mon Dec 28 10:00:20 PST 2015 +#Wed Mar 08 11:25:21 EET 2017 distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-2.14.1-all.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-3.3-all.zip From be889af3d7a286a9cc98fbec9401e45257b461e2 Mon Sep 17 00:00:00 2001 From: Ezerous Date: Tue, 14 Mar 2017 12:32:32 +0200 Subject: [PATCH 12/18] yml file update --- .gitlab-ci.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index d02a2bf6..bf367524 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -2,8 +2,8 @@ image: openjdk:8-jdk variables: ANDROID_TARGET_SDK: "25" - ANDROID_BUILD_TOOLS: "25.0.1" - ANDROID_SDK_TOOLS: "25.2.5" + ANDROID_BUILD_TOOLS: "25.0.2" + ANDROID_SDK_TOOLS: "25.3.0" before_script: - apt-get --quiet update --yes From fd2f289aee0c484fdba54a25e3609d8dd65a7119 Mon Sep 17 00:00:00 2001 From: Ezerous Date: Tue, 14 Mar 2017 12:40:08 +0200 Subject: [PATCH 13/18] yml update 2 --- .gitlab-ci.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index bf367524..cd22f77e 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -3,7 +3,7 @@ image: openjdk:8-jdk variables: ANDROID_TARGET_SDK: "25" ANDROID_BUILD_TOOLS: "25.0.2" - ANDROID_SDK_TOOLS: "25.3.0" + ANDROID_SDK_TOOLS: "25.2.5" before_script: - apt-get --quiet update --yes From 34cd86e98c2c20fdb37eb69fe29f1c83d0641dde Mon Sep 17 00:00:00 2001 From: Apostolof Date: Sun, 19 Mar 2017 01:30:30 +0200 Subject: [PATCH 14/18] Html to BBcode init --- app/build.gradle | 13 +- .../mthmmy/activities/topic/TopicAdapter.java | 221 +++++++++++++++++- 2 files changed, 227 insertions(+), 7 deletions(-) diff --git a/app/build.gradle b/app/build.gradle index 522c3627..c7dc1920 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -20,7 +20,8 @@ android { proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' } debug { - def date = new Date().format('ddMMyy_HHmm'); + //def date = new Date().format('ddMMyy_HHmm'); + def date = 1; archivesBaseName = archivesBaseName + "-$date" } } @@ -28,11 +29,11 @@ android { dependencies { compile fileTree(dir: 'libs', include: ['*.jar']) - compile 'com.android.support:appcompat-v7:25.2.0' - compile 'com.android.support:design:25.2.0' - compile 'com.android.support:support-v4:25.2.0' - compile 'com.android.support:cardview-v7:25.2.0' - compile 'com.android.support:recyclerview-v7:25.2.0' + compile 'com.android.support:appcompat-v7:25.3.0' + compile 'com.android.support:design:25.3.0' + compile 'com.android.support:support-v4:25.3.0' + compile 'com.android.support:cardview-v7:25.3.0' + compile 'com.android.support:recyclerview-v7:25.3.0' compile 'com.google.firebase:firebase-crash:10.2.0' compile 'com.squareup.okhttp3:okhttp:3.6.0' compile 'com.squareup.picasso:picasso:2.5.2' diff --git a/app/src/main/java/gr/thmmy/mthmmy/activities/topic/TopicAdapter.java b/app/src/main/java/gr/thmmy/mthmmy/activities/topic/TopicAdapter.java index 3f5154fb..6f1d438c 100644 --- a/app/src/main/java/gr/thmmy/mthmmy/activities/topic/TopicAdapter.java +++ b/app/src/main/java/gr/thmmy/mthmmy/activities/topic/TopicAdapter.java @@ -42,9 +42,12 @@ import java.text.SimpleDateFormat; import java.util.ArrayList; import java.util.Calendar; import java.util.Date; +import java.util.HashMap; import java.util.List; import java.util.Locale; +import java.util.Map; import java.util.Objects; +import java.util.regex.Matcher; import gr.thmmy.mthmmy.R; import gr.thmmy.mthmmy.activities.board.BoardActivity; @@ -149,7 +152,7 @@ class TopicAdapter extends RecyclerView.Adapter { quotes += buildQuote(quotePosition); } if (!Objects.equals(quotes, "")) - replyDataHolder[replyText] = quotes; + replyDataHolder[replyText] = htmlToBBcode(quotes); return new QuickReplyViewHolder(view, new CustomEditTextListener(replySubject), new CustomEditTextListener(replyText)); } @@ -779,6 +782,222 @@ class TopicAdapter extends RecyclerView.Adapter { return null; } + private String htmlToBBcode(String html) { + Map bbMap = new HashMap<>(); + Map smileysMap1 = new HashMap<>(); + Map smileysMap2 = new HashMap<>(); + smileysMap1.put("Smiley", ":)"); + smileysMap1.put("Wink", ";)"); + smileysMap1.put("Cheesy", ":D"); + smileysMap1.put("Grin", ";D"); + smileysMap1.put("Angry", ">:("); + smileysMap1.put("Sad", ":("); + smileysMap1.put("Shocked", ":o"); + smileysMap1.put("Cool", "8))"); + smileysMap1.put("Huh", ":???:"); + smileysMap1.put("Roll Eyes", "::)"); + smileysMap1.put("Tongue", ":P"); + smileysMap1.put("Embarrassed", ":-["); + smileysMap1.put("Lips Sealed", ":-X"); + smileysMap1.put("Kiss", ":-*"); + smileysMap1.put("Cry", ":'("); + smileysMap1.put("heart", "<3"); + smileysMap1.put("kleidaria", "^locked^"); + smileysMap1.put("roll_over", "^rollover^"); + smileysMap1.put("redface", "^redface^"); + smileysMap1.put("confused", "^confused^"); + smileysMap1.put("innocent", "^innocent^"); + smileysMap1.put("sleep", "^sleep^"); + smileysMap1.put("lips_sealed", "^sealed^"); + smileysMap1.put("cool", "^cool^"); + smileysMap1.put("crazy", "^crazy^"); + smileysMap1.put("mad", "^mad^"); + smileysMap1.put("wav", "^wav^"); + smileysMap1.put("BinkyBaby", "^binkybaby^"); + smileysMap1.put("DontKnow", "^dontknow^"); + smileysMap1.put("angry4", ":angry4:"); + smileysMap1.put("angryAndHot", "^angryhot^"); + smileysMap1.put("angry", "^angry^"); + smileysMap1.put("bang_head", "^banghead^"); + smileysMap1.put("CryBaby", "^crybaby^"); + smileysMap1.put("Hello", "^hello^"); + smileysMap1.put("jerk", "^jerk^"); + smileysMap1.put("NoNo", "^nono^"); + smileysMap1.put("NotWorthy", "^notworthy^"); + smileysMap1.put("Off-topic", "^off-topic^"); + smileysMap1.put("Puke", "^puke^"); + smileysMap1.put("Shout", "^shout^"); + smileysMap1.put("Slurp", "^slurp^"); + smileysMap1.put("SuperConfused", "^superconfused^"); + smileysMap1.put("SuperInnocent", "^superinnocent^"); + smileysMap1.put("CellPhone", "^cellPhone^"); + smileysMap1.put("Idiot", "^idiot^"); + smileysMap1.put("Knuppel", "^knuppel^"); + smileysMap1.put("TickedOff", "^tickedOff^"); + smileysMap1.put("Peace", "^peace^"); + smileysMap1.put("Suspicious", "^suspicious^"); + smileysMap1.put("Caffine", "^caffine^"); + smileysMap1.put("argue", "^argue^"); + smileysMap1.put("banned2", "^banned2^"); + smileysMap1.put("banned", "^banned^"); + smileysMap1.put("bath", "^bath^"); + smileysMap1.put("beg", "^beg^"); + smileysMap1.put("bluescreen", "^bluescreen^"); + smileysMap1.put("boil", "^boil^"); + smileysMap1.put("bye", "^bye^"); + smileysMap1.put("callmerip", "^callmerip^"); + smileysMap1.put("carnaval", "^carnaval^"); + smileysMap1.put("clap", "^clap^"); + smileysMap1.put("coffepot", "^coffepot^"); + smileysMap1.put("crap", "^crap^"); + smileysMap1.put("curses", "^curses^"); + smileysMap1.put("funny", "^funny^"); + smileysMap1.put("guitar", "^guitar^"); + smileysMap1.put("kissy", "^kissy^"); + smileysMap1.put("band", "^band^"); + smileysMap1.put("ivres", "^ivres^"); + smileysMap1.put("kaloe", "^kaloe^"); + smileysMap1.put("kremala", "^kremala^"); + smileysMap1.put("moon", "^moon^"); + smileysMap1.put("mopping", "^mopping^"); + smileysMap1.put("mountza", "^mountza^"); + smileysMap1.put("pcsleep", "^pcsleep^"); + smileysMap1.put("pinokio", "^pinokio^"); + smileysMap1.put("poke", "^poke^"); + smileysMap1.put("seestars", "^seestars^"); + smileysMap1.put("sfyri", "^sfyri^"); + smileysMap1.put("spam", "^spam^"); + smileysMap1.put("super", "^super^"); + smileysMap1.put("tafos", "^tafos^"); + smileysMap1.put("tomato", "^tomato^"); + smileysMap1.put("ytold", "^ytold^"); + smileysMap1.put("beer", "^beer^"); + smileysMap1.put("ο fritz!!!", "^fritz^"); + smileysMap1.put("o Wade!!!", "^wade^"); + smileysMap1.put("bonjour", "^hat^"); + smileysMap1.put("bonjour2", "^miss^"); + smileysMap1.put("question", "^que^"); + smileysMap1.put("shifty", "^shifty^"); + smileysMap1.put("shy", "^shy^"); + smileysMap1.put("music_listenning", "^music_listen^"); + smileysMap1.put("bag_face", "^bagface^"); + smileysMap1.put("rotation", "^rotate^"); + smileysMap1.put("love", "^love^"); + smileysMap1.put("speech", "^speech^"); + smileysMap1.put("shocked", "^shocked^"); + smileysMap1.put("extremely_shocked", "^ex_shocked^"); + smileysMap1.put("smurf", "^smurf^"); + smileysMap1.put("monster", "^monster^"); + smileysMap1.put("pig", "^pig^"); + smileysMap1.put("lol", "^lol^"); + + smileysMap2.put("Police", "^Police^"); + smileysMap2.put("foyska", "^fouska^"); + smileysMap2.put("nista", "^nysta^"); + smileysMap2.put("10_7_3", "^sfinaki^"); + smileysMap2.put("yu", "^yue^"); + smileysMap2.put("a-eatpaper", "^eatpaper^"); + smileysMap2.put("lypi", "^lypi^"); + smileysMap2.put("megashok1wq", "^aytoxeir^"); + smileysMap2.put("victory", "^victory^"); + smileysMap2.put("filarakia", "^filarakia^"); + smileysMap2.put("rofl", "^rolfmao^"); + smileysMap2.put("locked", "^lock^"); + smileysMap2.put("facepalm", "^facepalm^"); + + //html stuff on the beginning + bbMap.put("\n ", ""); + //quotes and code headers + bbMap.put("\n\\s+?
    \n (.+?)\n
    ", ""); + bbMap.put("\n\\s+?
    \n (.+?)\n
    ", ""); + bbMap.put("\n\\s+?
    \n (.+?)\n
    ", ""); + bbMap.put("
    ", "\n"); + //bold + bbMap.put("\n\\s+?(.+?)", "\\[b\\]$1\\[/b\\]"); + //italics + bbMap.put("\n\\s+?(.+?)", "\\[i\\]$1\\[/i\\]"); + //underline + bbMap.put("\n\\s+?(.+?)", "\\[u\\]$1\\[/u\\]"); + //deleted + bbMap.put("\n\\s+?(.+?)", "\\[s\\]$1\\[/s\\]"); + //text color + bbMap.put("\n\\s+?(.+?)", "\\[color=$1\\]$2\\[/color\\]"); + //glow + bbMap.put("\n\\s+?(.+?)", "\\[glow=$1,2,300\\]$2\\[/glow\\]"); + //shadow + bbMap.put("\n\\s+?(.+?)", "\\[shadow=$1,$2\\]$3\\[/shadow\\]"); + //running text + bbMap.put("\\s+?\n (.+?)\n ", "\\[move\\]$1\\[/move\\]"); + //alignment + bbMap.put("\n\\s+?
    \n (.+?)\n
    ", "\\[center\\]$1\\[/center\\]"); + bbMap.put("\n\\s+?
    \n (.+?)\n
    ", "\\[$1\\]$2\\[/$1\\]"); + //preformated + bbMap.put("\n\\s+?
    (.+?)
    ", "\\[pre\\]$1\\[/pre\\]"); + //horizontal rule + bbMap.put("\n\\s+?
    ", "\\[hr\\]"); + //resize + bbMap.put("\n\\s+?(.+?)", "\\[size=$1\\]$3\\[/size\\]"); + //font + bbMap.put("\n\\s+?(.+?)", "\\[font=$1\\]$2\\[/font\\]"); + //lists + bbMap.put("\\s+
  • (.+?)
  • ", "\\[li\\]$1\\[/li\\]"); + bbMap.put("\n\\s+
      ([\\S\\s]+?)\n\\s+
    ", + "\\[list\\]\n$1\n\\[/list\\]"); + //latex code + bbMap.put("\n\\s+?", "\\[tex\\]$1\\[/tex\\]"); + //code + bbMap.put("\n\\s+?
    \n (.+?)\n
    ", "\\[code\\]$1\\[/code\\]"); + //teletype + bbMap.put("\n\\s+?(.+?)", "\\[tt\\]$1\\[/tt\\]"); + //superscript/subscript + bbMap.put("\n\\s+?(.+?)", "\\[sub\\]$1\\[/sub\\]"); + bbMap.put("\n\\s+?(.+?)", "\\[sup\\]$1\\[/sup\\]"); + //tables + bbMap.put("\\s+?([\\S\\s]+?)", "\\[td\\]$1\\[/td\\]"); + bbMap.put("([\\S\\s]+?)\n ", "\\[tr\\]$1\\[/tr\\]"); + bbMap.put("\n\\s+?\n \n ([\\S\\s]+?)\n \n
    " + , "\\[table\\]$2\\[/table\\]"); + //videos + bbMap.put("\n\\s+?
    \n", + "[youtube]https://www.youtube.com/watch?v=$1[/youtube]"); + //ftp + bbMap.put("([\\S\\s]+?)", "\\[fpt=ftp:$1\\]$2\\[/ftp\\]"); + //mailto + bbMap.put("\n\\s+?([\\S\\s]+?)", "\\[email\\]$2\\[/email\\]"); + //links + bbMap.put("\n\\s+?([\\S\\s]+?)", "\\[url=$1\\]$2\\[/url\\]"); + //smileys + for (Map.Entry entry : smileysMap1.entrySet()) { + bbMap.put("\n \""", entry.getValue().toString()); + } + for (Map.Entry entry : smileysMap2.entrySet()) { //Those that have empty alt tag + bbMap.put("\n ", entry.getValue().toString()); + } + + bbMap.put("\n \"Undecided\"" + , Matcher.quoteReplacement(":-\\")); + + //html stuff on the end + bbMap.put("\n
    ", ""); + + for (Map.Entry entry : bbMap.entrySet()) { + html = html.replaceAll(entry.getKey().toString(), entry.getValue().toString()); + } + + //img need to be done last or it messes up everything else + html = html.replaceAll("\\s+", + "\\[img width=$2 height=$3\\]$1\\[/img\\]"); + html = html.replaceAll("\\s+", + "\\[img height=$2 width=$3\\]$1\\[/img\\]"); + html = html.replaceAll("\\s+", "\\[img width=$2\\]$1\\[/img\\]"); + html = html.replaceAll("\\s+", "\\[img height=$2\\]$1\\[/img\\]"); + html = html.replaceAll("\\s+", "\\[img\\]$1\\[/img\\]"); + + return html; + } + /** * Returns a String with a single FontAwesome typeface character corresponding to this file's * extension. From 41fcbd1d2e9c2a8a1712f0aada2d23a855cb84fb Mon Sep 17 00:00:00 2001 From: Apostolof Date: Mon, 20 Mar 2017 20:25:13 +0200 Subject: [PATCH 15/18] Topic reply refreshes topic, bookmarks go to last topic's page --- app/build.gradle | 4 +- .../mthmmy/activities/BookmarkActivity.java | 2 +- .../mthmmy/activities/topic/Posting.java | 263 ++++++++++++++++++ .../mthmmy/activities/topic/ReplyParser.java | 44 --- .../activities/topic/TopicActivity.java | 30 +- .../mthmmy/activities/topic/TopicAdapter.java | 228 +-------------- 6 files changed, 302 insertions(+), 269 deletions(-) create mode 100644 app/src/main/java/gr/thmmy/mthmmy/activities/topic/Posting.java delete mode 100644 app/src/main/java/gr/thmmy/mthmmy/activities/topic/ReplyParser.java diff --git a/app/build.gradle b/app/build.gradle index c7dc1920..a5af6136 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -20,8 +20,8 @@ android { proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' } debug { - //def date = new Date().format('ddMMyy_HHmm'); - def date = 1; + def date = new Date().format('ddMMyy_HHmm'); + //def date = 1; archivesBaseName = archivesBaseName + "-$date" } } diff --git a/app/src/main/java/gr/thmmy/mthmmy/activities/BookmarkActivity.java b/app/src/main/java/gr/thmmy/mthmmy/activities/BookmarkActivity.java index 5d854eef..ec0c2b25 100644 --- a/app/src/main/java/gr/thmmy/mthmmy/activities/BookmarkActivity.java +++ b/app/src/main/java/gr/thmmy/mthmmy/activities/BookmarkActivity.java @@ -114,7 +114,7 @@ public class BookmarkActivity extends BaseActivity { Intent intent = new Intent(BookmarkActivity.this, TopicActivity.class); Bundle extras = new Bundle(); extras.putString(BUNDLE_TOPIC_URL, "https://www.thmmy.gr/smf/index.php?topic=" - + bookmarkedTopic.getId() + ".0"); + + bookmarkedTopic.getId() + "." + 2147483647); extras.putString(BUNDLE_TOPIC_TITLE, bookmarkedTopic.getTitle()); intent.putExtras(extras); startActivity(intent); diff --git a/app/src/main/java/gr/thmmy/mthmmy/activities/topic/Posting.java b/app/src/main/java/gr/thmmy/mthmmy/activities/topic/Posting.java new file mode 100644 index 00000000..7c42b8cd --- /dev/null +++ b/app/src/main/java/gr/thmmy/mthmmy/activities/topic/Posting.java @@ -0,0 +1,263 @@ +package gr.thmmy.mthmmy.activities.topic; + +import android.util.Log; + +import org.jsoup.Jsoup; +import org.jsoup.nodes.Document; + +import java.io.IOException; +import java.util.HashMap; +import java.util.Map; +import java.util.regex.Matcher; + +import okhttp3.Response; + +class Posting { + enum REPLY_STATUS { + SUCCESSFUL, NO_SUBJECT, EMPTY_BODY, NEW_REPLY_WHILE_POSTING, NOT_FOUND, SESSION_ENDED, OTHER_ERROR + } + + static REPLY_STATUS replyStatus(Response response) throws IOException { + if (response.code() == 404) return REPLY_STATUS.NOT_FOUND; + if (response.code() < 200 || response.code() >= 400) return REPLY_STATUS.OTHER_ERROR; + String finalUrl = response.request().url().toString(); + if (finalUrl.contains("action=post")) { + Document postErrorPage = Jsoup.parse(response.body().string()); + String[] errors = postErrorPage.select("tr[id=errors] div[id=error_list]").first() + .toString().split("
    "); + for (int i = 0; i < errors.length; ++i) { //TODO test + Log.d("TAG", String.valueOf(i)); + Log.d("TAG", errors[i]); + } + for (String error : errors) { + if (error.contains("Your session timed out while posting") || + error.contains("Υπερβήκατε τον μέγιστο χρόνο σύνδεσης κατά την αποστολή")) + return REPLY_STATUS.SESSION_ENDED; + if (error.contains("No subject was filled in") + || error.contains("Δεν δόθηκε τίτλος")) + return REPLY_STATUS.NO_SUBJECT; + if (error.contains("The message body was left empty") + || error.contains("Δεν δόθηκε κείμενο για το μήνυμα")) + return REPLY_STATUS.EMPTY_BODY; + } + return REPLY_STATUS.NEW_REPLY_WHILE_POSTING; + } + return REPLY_STATUS.SUCCESSFUL; + } + + static String htmlToBBcode(String html) { + Map bbMap = new HashMap<>(); + Map smileysMap1 = new HashMap<>(); + Map smileysMap2 = new HashMap<>(); + smileysMap1.put("Smiley", ":)"); + smileysMap1.put("Wink", ";)"); + smileysMap1.put("Cheesy", ":D"); + smileysMap1.put("Grin", ";D"); + smileysMap1.put("Angry", ">:("); + smileysMap1.put("Sad", ":("); + smileysMap1.put("Shocked", ":o"); + smileysMap1.put("Cool", "8))"); + smileysMap1.put("Huh", ":???:"); + smileysMap1.put("Roll Eyes", "::)"); + smileysMap1.put("Tongue", ":P"); + smileysMap1.put("Embarrassed", ":-["); + smileysMap1.put("Lips Sealed", ":-X"); + smileysMap1.put("Kiss", ":-*"); + smileysMap1.put("Cry", ":'("); + smileysMap1.put("heart", "<3"); + smileysMap1.put("kleidaria", "^locked^"); + smileysMap1.put("roll_over", "^rollover^"); + smileysMap1.put("redface", "^redface^"); + smileysMap1.put("confused", "^confused^"); + smileysMap1.put("innocent", "^innocent^"); + smileysMap1.put("sleep", "^sleep^"); + smileysMap1.put("lips_sealed", "^sealed^"); + smileysMap1.put("cool", "^cool^"); + smileysMap1.put("crazy", "^crazy^"); + smileysMap1.put("mad", "^mad^"); + smileysMap1.put("wav", "^wav^"); + smileysMap1.put("BinkyBaby", "^binkybaby^"); + smileysMap1.put("DontKnow", "^dontknow^"); + smileysMap1.put("angry4", ":angry4:"); + smileysMap1.put("angryAndHot", "^angryhot^"); + smileysMap1.put("angry", "^angry^"); + smileysMap1.put("bang_head", "^banghead^"); + smileysMap1.put("CryBaby", "^crybaby^"); + smileysMap1.put("Hello", "^hello^"); + smileysMap1.put("jerk", "^jerk^"); + smileysMap1.put("NoNo", "^nono^"); + smileysMap1.put("NotWorthy", "^notworthy^"); + smileysMap1.put("Off-topic", "^off-topic^"); + smileysMap1.put("Puke", "^puke^"); + smileysMap1.put("Shout", "^shout^"); + smileysMap1.put("Slurp", "^slurp^"); + smileysMap1.put("SuperConfused", "^superconfused^"); + smileysMap1.put("SuperInnocent", "^superinnocent^"); + smileysMap1.put("CellPhone", "^cellPhone^"); + smileysMap1.put("Idiot", "^idiot^"); + smileysMap1.put("Knuppel", "^knuppel^"); + smileysMap1.put("TickedOff", "^tickedOff^"); + smileysMap1.put("Peace", "^peace^"); + smileysMap1.put("Suspicious", "^suspicious^"); + smileysMap1.put("Caffine", "^caffine^"); + smileysMap1.put("argue", "^argue^"); + smileysMap1.put("banned2", "^banned2^"); + smileysMap1.put("banned", "^banned^"); + smileysMap1.put("bath", "^bath^"); + smileysMap1.put("beg", "^beg^"); + smileysMap1.put("bluescreen", "^bluescreen^"); + smileysMap1.put("boil", "^boil^"); + smileysMap1.put("bye", "^bye^"); + smileysMap1.put("callmerip", "^callmerip^"); + smileysMap1.put("carnaval", "^carnaval^"); + smileysMap1.put("clap", "^clap^"); + smileysMap1.put("coffepot", "^coffepot^"); + smileysMap1.put("crap", "^crap^"); + smileysMap1.put("curses", "^curses^"); + smileysMap1.put("funny", "^funny^"); + smileysMap1.put("guitar", "^guitar^"); + smileysMap1.put("kissy", "^kissy^"); + smileysMap1.put("band", "^band^"); + smileysMap1.put("ivres", "^ivres^"); + smileysMap1.put("kaloe", "^kaloe^"); + smileysMap1.put("kremala", "^kremala^"); + smileysMap1.put("moon", "^moon^"); + smileysMap1.put("mopping", "^mopping^"); + smileysMap1.put("mountza", "^mountza^"); + smileysMap1.put("pcsleep", "^pcsleep^"); + smileysMap1.put("pinokio", "^pinokio^"); + smileysMap1.put("poke", "^poke^"); + smileysMap1.put("seestars", "^seestars^"); + smileysMap1.put("sfyri", "^sfyri^"); + smileysMap1.put("spam", "^spam^"); + smileysMap1.put("super", "^super^"); + smileysMap1.put("tafos", "^tafos^"); + smileysMap1.put("tomato", "^tomato^"); + smileysMap1.put("ytold", "^ytold^"); + smileysMap1.put("beer", "^beer^"); + smileysMap1.put("ο fritz!!!", "^fritz^"); + smileysMap1.put("o Wade!!!", "^wade^"); + smileysMap1.put("bonjour", "^hat^"); + smileysMap1.put("bonjour2", "^miss^"); + smileysMap1.put("question", "^que^"); + smileysMap1.put("shifty", "^shifty^"); + smileysMap1.put("shy", "^shy^"); + smileysMap1.put("music_listenning", "^music_listen^"); + smileysMap1.put("bag_face", "^bagface^"); + smileysMap1.put("rotation", "^rotate^"); + smileysMap1.put("love", "^love^"); + smileysMap1.put("speech", "^speech^"); + smileysMap1.put("shocked", "^shocked^"); + smileysMap1.put("extremely_shocked", "^ex_shocked^"); + smileysMap1.put("smurf", "^smurf^"); + smileysMap1.put("monster", "^monster^"); + smileysMap1.put("pig", "^pig^"); + smileysMap1.put("lol", "^lol^"); + + smileysMap2.put("Police", "^Police^"); + smileysMap2.put("foyska", "^fouska^"); + smileysMap2.put("nista", "^nysta^"); + smileysMap2.put("10_7_3", "^sfinaki^"); + smileysMap2.put("yu", "^yue^"); + smileysMap2.put("a-eatpaper", "^eatpaper^"); + smileysMap2.put("lypi", "^lypi^"); + smileysMap2.put("megashok1wq", "^aytoxeir^"); + smileysMap2.put("victory", "^victory^"); + smileysMap2.put("filarakia", "^filarakia^"); + smileysMap2.put("rofl", "^rolfmao^"); + smileysMap2.put("locked", "^lock^"); + smileysMap2.put("facepalm", "^facepalm^"); + + //html stuff on the beginning + bbMap.put("\n ", ""); + //quotes and code headers + bbMap.put("\n\\s+?
    \n (.+?)\n
    ", ""); + bbMap.put("\n\\s+?
    \n (.+?)\n
    ", ""); + bbMap.put("\n\\s+?
    \n (.+?)\n
    ", ""); + bbMap.put("
    ", "\n"); + //bold + bbMap.put("\n\\s+?(.+?)", "\\[b\\]$1\\[/b\\]"); + //italics + bbMap.put("\n\\s+?(.+?)", "\\[i\\]$1\\[/i\\]"); + //underline + bbMap.put("\n\\s+?(.+?)", "\\[u\\]$1\\[/u\\]"); + //deleted + bbMap.put("\n\\s+?(.+?)", "\\[s\\]$1\\[/s\\]"); + //text color + bbMap.put("\n\\s+?(.+?)", "\\[color=$1\\]$2\\[/color\\]"); + //glow + bbMap.put("\n\\s+?(.+?)", "\\[glow=$1,2,300\\]$2\\[/glow\\]"); + //shadow + bbMap.put("\n\\s+?(.+?)", "\\[shadow=$1,$2\\]$3\\[/shadow\\]"); + //running text + bbMap.put("\\s+?\n (.+?)\n ", "\\[move\\]$1\\[/move\\]"); + //alignment + bbMap.put("\n\\s+?
    \n (.+?)\n
    ", "\\[center\\]$1\\[/center\\]"); + bbMap.put("\n\\s+?
    \n (.+?)\n
    ", "\\[$1\\]$2\\[/$1\\]"); + //preformated + bbMap.put("\n\\s+?
    (.+?)
    ", "\\[pre\\]$1\\[/pre\\]"); + //horizontal rule + bbMap.put("\n\\s+?
    ", "\\[hr\\]"); + //resize + bbMap.put("\n\\s+?(.+?)", "\\[size=$1\\]$3\\[/size\\]"); + //font + bbMap.put("\n\\s+?(.+?)", "\\[font=$1\\]$2\\[/font\\]"); + //lists + bbMap.put("\\s+
  • (.+?)
  • ", "\\[li\\]$1\\[/li\\]"); + bbMap.put("\n\\s+
      ([\\S\\s]+?)\n\\s+
    ", + "\\[list\\]\n$1\n\\[/list\\]"); + //latex code + bbMap.put("\n\\s+?", "\\[tex\\]$1\\[/tex\\]"); + //code + bbMap.put("\n\\s+?
    \n (.+?)\n
    ", "\\[code\\]$1\\[/code\\]"); + //teletype + bbMap.put("\n\\s+?(.+?)", "\\[tt\\]$1\\[/tt\\]"); + //superscript/subscript + bbMap.put("\n\\s+?(.+?)", "\\[sub\\]$1\\[/sub\\]"); + bbMap.put("\n\\s+?(.+?)", "\\[sup\\]$1\\[/sup\\]"); + //tables + bbMap.put("\\s+?([\\S\\s]+?)", "\\[td\\]$1\\[/td\\]"); + bbMap.put("([\\S\\s]+?)\n ", "\\[tr\\]$1\\[/tr\\]"); + bbMap.put("\n\\s+?\n \n ([\\S\\s]+?)\n \n
    " + , "\\[table\\]$2\\[/table\\]"); + //videos + bbMap.put("\n\\s+?
    \n", + "[youtube]https://www.youtube.com/watch?v=$1[/youtube]"); + //ftp + bbMap.put("([\\S\\s]+?)", "\\[fpt=ftp:$1\\]$2\\[/ftp\\]"); + //mailto + bbMap.put("\n\\s+?([\\S\\s]+?)", "\\[email\\]$2\\[/email\\]"); + //links + bbMap.put("\n\\s+?([\\S\\s]+?)", "\\[url=$1\\]$2\\[/url\\]"); + //smileys + for (Map.Entry entry : smileysMap1.entrySet()) { + bbMap.put("\n \""", entry.getValue().toString()); + } + for (Map.Entry entry : smileysMap2.entrySet()) { //Those that have empty alt tag + bbMap.put("\n ", entry.getValue().toString()); + } + + bbMap.put("\n \"Undecided\"" + , Matcher.quoteReplacement(":-\\")); + + //html stuff on the end + bbMap.put("\n
    ", ""); + + for (Map.Entry entry : bbMap.entrySet()) { + html = html.replaceAll(entry.getKey().toString(), entry.getValue().toString()); + } + + //img need to be done last or it messes up everything else + html = html.replaceAll("\\s+", + "\\[img width=$2 height=$3\\]$1\\[/img\\]"); + html = html.replaceAll("\\s+", + "\\[img height=$2 width=$3\\]$1\\[/img\\]"); + html = html.replaceAll("\\s+", "\\[img width=$2\\]$1\\[/img\\]"); + html = html.replaceAll("\\s+", "\\[img height=$2\\]$1\\[/img\\]"); + html = html.replaceAll("\\s+", "\\[img\\]$1\\[/img\\]"); + + return html; + } +} diff --git a/app/src/main/java/gr/thmmy/mthmmy/activities/topic/ReplyParser.java b/app/src/main/java/gr/thmmy/mthmmy/activities/topic/ReplyParser.java deleted file mode 100644 index ca47585a..00000000 --- a/app/src/main/java/gr/thmmy/mthmmy/activities/topic/ReplyParser.java +++ /dev/null @@ -1,44 +0,0 @@ -package gr.thmmy.mthmmy.activities.topic; - -import android.util.Log; - -import org.jsoup.Jsoup; -import org.jsoup.nodes.Document; - -import java.io.IOException; - -import okhttp3.Response; - -class ReplyParser { - enum REPLY_STATUS { - SUCCESSFUL, NO_SUBJECT, EMPTY_BODY, NEW_REPLY_WHILE_POSTING, NOT_FOUND, SESSION_ENDED, OTHER_ERROR - } - - static REPLY_STATUS replyStatus(Response response) throws IOException { - if (response.code() == 404) return REPLY_STATUS.NOT_FOUND; - if (response.code() < 200 || response.code() >= 400) return REPLY_STATUS.OTHER_ERROR; - String finalUrl = response.request().url().toString(); - if (finalUrl.contains("action=post")) { - Document postErrorPage = Jsoup.parse(response.body().string()); - String[] errors = postErrorPage.select("tr[id=errors] div[id=error_list]").first() - .toString().split("
    "); - for (int i = 0; i < errors.length; ++i) { //TODO test - Log.d("TAG", String.valueOf(i)); - Log.d("TAG", errors[i]); - } - for (String error : errors) { - if (error.contains("Your session timed out while posting") || - error.contains("Υπερβήκατε τον μέγιστο χρόνο σύνδεσης κατά την αποστολή")) - return REPLY_STATUS.SESSION_ENDED; - if (error.contains("No subject was filled in") - || error.contains("Δεν δόθηκε τίτλος")) - return REPLY_STATUS.NO_SUBJECT; - if (error.contains("The message body was left empty") - || error.contains("Δεν δόθηκε κείμενο για το μήνυμα")) - return REPLY_STATUS.EMPTY_BODY; - } - return REPLY_STATUS.NEW_REPLY_WHILE_POSTING; - } - return REPLY_STATUS.SUCCESSFUL; - } -} diff --git a/app/src/main/java/gr/thmmy/mthmmy/activities/topic/TopicActivity.java b/app/src/main/java/gr/thmmy/mthmmy/activities/topic/TopicActivity.java index 942dd50c..9e35e942 100644 --- a/app/src/main/java/gr/thmmy/mthmmy/activities/topic/TopicActivity.java +++ b/app/src/main/java/gr/thmmy/mthmmy/activities/topic/TopicActivity.java @@ -1,5 +1,6 @@ package gr.thmmy.mthmmy.activities.topic; +import android.content.Context; import android.content.Intent; import android.graphics.Rect; import android.net.Uri; @@ -17,12 +18,14 @@ import android.text.method.LinkMovementMethod; import android.text.method.ScrollingMovementMethod; import android.text.style.ClickableSpan; import android.text.style.URLSpan; +import android.util.Log; import android.util.SparseArray; import android.view.LayoutInflater; import android.view.Menu; import android.view.MenuItem; import android.view.MotionEvent; import android.view.View; +import android.view.inputmethod.InputMethodManager; import android.widget.ImageButton; import android.widget.LinearLayout; import android.widget.ProgressBar; @@ -60,7 +63,7 @@ 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.ReplyParser.replyStatus; +import static gr.thmmy.mthmmy.activities.topic.Posting.replyStatus; /** * Activity for topics. When creating an Intent of this activity you need to bundle a String @@ -117,6 +120,7 @@ public class TopicActivity extends BaseActivity { private String parsedTitle; private RecyclerView recyclerView; private String loadedPageUrl = ""; + private boolean reloadingPage = false; @Override @@ -480,7 +484,7 @@ public class TopicActivity extends BaseActivity { } } //Checks if the page to be loaded is the one already shown - if (!Objects.equals(loadedPageUrl, "") && loadedPageUrl.contains(base_url)) { + if (!reloadingPage && !Objects.equals(loadedPageUrl, "") && loadedPageUrl.contains(base_url)) { if (newPageUrl.contains("topicseen#new") || newPageUrl.contains("#new")) if (thisPage == numberOfPages) return SAME_PAGE; @@ -497,6 +501,7 @@ public class TopicActivity extends BaseActivity { } else if (Integer.parseInt(newPageUrl.substring(base_url.length() + 1)) / 15 + 1 == thisPage) //TODO fix bug return SAME_PAGE; } else if (!Objects.equals(loadedPageUrl, "")) topicTitle = null; + if (reloadingPage) reloadingPage = !reloadingPage; loadedPageUrl = newPageUrl; replyPageUrl = null; @@ -735,13 +740,34 @@ public class TopicActivity extends BaseActivity { @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(base_url + "." + 2147483647); + else { + reloadingPage = true; + topicTask.execute(loadedPageUrl); + } + Log.d("TAG", "sent"); + } } } } \ No newline at end of file diff --git a/app/src/main/java/gr/thmmy/mthmmy/activities/topic/TopicAdapter.java b/app/src/main/java/gr/thmmy/mthmmy/activities/topic/TopicAdapter.java index 6f1d438c..db548985 100644 --- a/app/src/main/java/gr/thmmy/mthmmy/activities/topic/TopicAdapter.java +++ b/app/src/main/java/gr/thmmy/mthmmy/activities/topic/TopicAdapter.java @@ -42,12 +42,9 @@ import java.text.SimpleDateFormat; import java.util.ArrayList; import java.util.Calendar; import java.util.Date; -import java.util.HashMap; import java.util.List; import java.util.Locale; -import java.util.Map; import java.util.Objects; -import java.util.regex.Matcher; import gr.thmmy.mthmmy.R; import gr.thmmy.mthmmy.activities.board.BoardActivity; @@ -66,6 +63,7 @@ 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.htmlToBBcode; import static gr.thmmy.mthmmy.base.BaseActivity.getSessionManager; /** @@ -144,6 +142,7 @@ class TopicAdapter extends RecyclerView.Adapter { } else if (viewType == VIEW_TYPE_QUICK_REPLY) { View view = LayoutInflater.from(parent.getContext()). inflate(R.layout.activity_topic_quick_reply_row, parent, false); + view.findViewById(R.id.quick_reply_submit).setEnabled(true); //Default post subject replyDataHolder[replySubject] = "Re: " + topicTitle; //Build quotes @@ -467,9 +466,14 @@ class TopicAdapter extends RecyclerView.Adapter { holder.submitButton.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { + if (holder.quickReplySubject.getText().toString().isEmpty()) return; if (holder.quickReply.getText().toString().isEmpty()) return; holder.submitButton.setEnabled(false); - replyTask.execute(holder.quickReply.getText().toString()); + replyTask.execute(holder.quickReplySubject.getText().toString(), + holder.quickReply.getText().toString()); + replyDataHolder[replySubject] = "Re: " + topicTitle; + replyDataHolder[replyText] = ""; + holder.quickReply.setText(""); } }); } @@ -782,222 +786,6 @@ class TopicAdapter extends RecyclerView.Adapter { return null; } - private String htmlToBBcode(String html) { - Map bbMap = new HashMap<>(); - Map smileysMap1 = new HashMap<>(); - Map smileysMap2 = new HashMap<>(); - smileysMap1.put("Smiley", ":)"); - smileysMap1.put("Wink", ";)"); - smileysMap1.put("Cheesy", ":D"); - smileysMap1.put("Grin", ";D"); - smileysMap1.put("Angry", ">:("); - smileysMap1.put("Sad", ":("); - smileysMap1.put("Shocked", ":o"); - smileysMap1.put("Cool", "8))"); - smileysMap1.put("Huh", ":???:"); - smileysMap1.put("Roll Eyes", "::)"); - smileysMap1.put("Tongue", ":P"); - smileysMap1.put("Embarrassed", ":-["); - smileysMap1.put("Lips Sealed", ":-X"); - smileysMap1.put("Kiss", ":-*"); - smileysMap1.put("Cry", ":'("); - smileysMap1.put("heart", "<3"); - smileysMap1.put("kleidaria", "^locked^"); - smileysMap1.put("roll_over", "^rollover^"); - smileysMap1.put("redface", "^redface^"); - smileysMap1.put("confused", "^confused^"); - smileysMap1.put("innocent", "^innocent^"); - smileysMap1.put("sleep", "^sleep^"); - smileysMap1.put("lips_sealed", "^sealed^"); - smileysMap1.put("cool", "^cool^"); - smileysMap1.put("crazy", "^crazy^"); - smileysMap1.put("mad", "^mad^"); - smileysMap1.put("wav", "^wav^"); - smileysMap1.put("BinkyBaby", "^binkybaby^"); - smileysMap1.put("DontKnow", "^dontknow^"); - smileysMap1.put("angry4", ":angry4:"); - smileysMap1.put("angryAndHot", "^angryhot^"); - smileysMap1.put("angry", "^angry^"); - smileysMap1.put("bang_head", "^banghead^"); - smileysMap1.put("CryBaby", "^crybaby^"); - smileysMap1.put("Hello", "^hello^"); - smileysMap1.put("jerk", "^jerk^"); - smileysMap1.put("NoNo", "^nono^"); - smileysMap1.put("NotWorthy", "^notworthy^"); - smileysMap1.put("Off-topic", "^off-topic^"); - smileysMap1.put("Puke", "^puke^"); - smileysMap1.put("Shout", "^shout^"); - smileysMap1.put("Slurp", "^slurp^"); - smileysMap1.put("SuperConfused", "^superconfused^"); - smileysMap1.put("SuperInnocent", "^superinnocent^"); - smileysMap1.put("CellPhone", "^cellPhone^"); - smileysMap1.put("Idiot", "^idiot^"); - smileysMap1.put("Knuppel", "^knuppel^"); - smileysMap1.put("TickedOff", "^tickedOff^"); - smileysMap1.put("Peace", "^peace^"); - smileysMap1.put("Suspicious", "^suspicious^"); - smileysMap1.put("Caffine", "^caffine^"); - smileysMap1.put("argue", "^argue^"); - smileysMap1.put("banned2", "^banned2^"); - smileysMap1.put("banned", "^banned^"); - smileysMap1.put("bath", "^bath^"); - smileysMap1.put("beg", "^beg^"); - smileysMap1.put("bluescreen", "^bluescreen^"); - smileysMap1.put("boil", "^boil^"); - smileysMap1.put("bye", "^bye^"); - smileysMap1.put("callmerip", "^callmerip^"); - smileysMap1.put("carnaval", "^carnaval^"); - smileysMap1.put("clap", "^clap^"); - smileysMap1.put("coffepot", "^coffepot^"); - smileysMap1.put("crap", "^crap^"); - smileysMap1.put("curses", "^curses^"); - smileysMap1.put("funny", "^funny^"); - smileysMap1.put("guitar", "^guitar^"); - smileysMap1.put("kissy", "^kissy^"); - smileysMap1.put("band", "^band^"); - smileysMap1.put("ivres", "^ivres^"); - smileysMap1.put("kaloe", "^kaloe^"); - smileysMap1.put("kremala", "^kremala^"); - smileysMap1.put("moon", "^moon^"); - smileysMap1.put("mopping", "^mopping^"); - smileysMap1.put("mountza", "^mountza^"); - smileysMap1.put("pcsleep", "^pcsleep^"); - smileysMap1.put("pinokio", "^pinokio^"); - smileysMap1.put("poke", "^poke^"); - smileysMap1.put("seestars", "^seestars^"); - smileysMap1.put("sfyri", "^sfyri^"); - smileysMap1.put("spam", "^spam^"); - smileysMap1.put("super", "^super^"); - smileysMap1.put("tafos", "^tafos^"); - smileysMap1.put("tomato", "^tomato^"); - smileysMap1.put("ytold", "^ytold^"); - smileysMap1.put("beer", "^beer^"); - smileysMap1.put("ο fritz!!!", "^fritz^"); - smileysMap1.put("o Wade!!!", "^wade^"); - smileysMap1.put("bonjour", "^hat^"); - smileysMap1.put("bonjour2", "^miss^"); - smileysMap1.put("question", "^que^"); - smileysMap1.put("shifty", "^shifty^"); - smileysMap1.put("shy", "^shy^"); - smileysMap1.put("music_listenning", "^music_listen^"); - smileysMap1.put("bag_face", "^bagface^"); - smileysMap1.put("rotation", "^rotate^"); - smileysMap1.put("love", "^love^"); - smileysMap1.put("speech", "^speech^"); - smileysMap1.put("shocked", "^shocked^"); - smileysMap1.put("extremely_shocked", "^ex_shocked^"); - smileysMap1.put("smurf", "^smurf^"); - smileysMap1.put("monster", "^monster^"); - smileysMap1.put("pig", "^pig^"); - smileysMap1.put("lol", "^lol^"); - - smileysMap2.put("Police", "^Police^"); - smileysMap2.put("foyska", "^fouska^"); - smileysMap2.put("nista", "^nysta^"); - smileysMap2.put("10_7_3", "^sfinaki^"); - smileysMap2.put("yu", "^yue^"); - smileysMap2.put("a-eatpaper", "^eatpaper^"); - smileysMap2.put("lypi", "^lypi^"); - smileysMap2.put("megashok1wq", "^aytoxeir^"); - smileysMap2.put("victory", "^victory^"); - smileysMap2.put("filarakia", "^filarakia^"); - smileysMap2.put("rofl", "^rolfmao^"); - smileysMap2.put("locked", "^lock^"); - smileysMap2.put("facepalm", "^facepalm^"); - - //html stuff on the beginning - bbMap.put("\n ", ""); - //quotes and code headers - bbMap.put("\n\\s+?
    \n (.+?)\n
    ", ""); - bbMap.put("\n\\s+?
    \n (.+?)\n
    ", ""); - bbMap.put("\n\\s+?
    \n (.+?)\n
    ", ""); - bbMap.put("
    ", "\n"); - //bold - bbMap.put("\n\\s+?(.+?)", "\\[b\\]$1\\[/b\\]"); - //italics - bbMap.put("\n\\s+?(.+?)", "\\[i\\]$1\\[/i\\]"); - //underline - bbMap.put("\n\\s+?(.+?)", "\\[u\\]$1\\[/u\\]"); - //deleted - bbMap.put("\n\\s+?(.+?)", "\\[s\\]$1\\[/s\\]"); - //text color - bbMap.put("\n\\s+?(.+?)", "\\[color=$1\\]$2\\[/color\\]"); - //glow - bbMap.put("\n\\s+?(.+?)", "\\[glow=$1,2,300\\]$2\\[/glow\\]"); - //shadow - bbMap.put("\n\\s+?(.+?)", "\\[shadow=$1,$2\\]$3\\[/shadow\\]"); - //running text - bbMap.put("\\s+?\n (.+?)\n ", "\\[move\\]$1\\[/move\\]"); - //alignment - bbMap.put("\n\\s+?
    \n (.+?)\n
    ", "\\[center\\]$1\\[/center\\]"); - bbMap.put("\n\\s+?
    \n (.+?)\n
    ", "\\[$1\\]$2\\[/$1\\]"); - //preformated - bbMap.put("\n\\s+?
    (.+?)
    ", "\\[pre\\]$1\\[/pre\\]"); - //horizontal rule - bbMap.put("\n\\s+?
    ", "\\[hr\\]"); - //resize - bbMap.put("\n\\s+?(.+?)", "\\[size=$1\\]$3\\[/size\\]"); - //font - bbMap.put("\n\\s+?(.+?)", "\\[font=$1\\]$2\\[/font\\]"); - //lists - bbMap.put("\\s+
  • (.+?)
  • ", "\\[li\\]$1\\[/li\\]"); - bbMap.put("\n\\s+
      ([\\S\\s]+?)\n\\s+
    ", - "\\[list\\]\n$1\n\\[/list\\]"); - //latex code - bbMap.put("\n\\s+?", "\\[tex\\]$1\\[/tex\\]"); - //code - bbMap.put("\n\\s+?
    \n (.+?)\n
    ", "\\[code\\]$1\\[/code\\]"); - //teletype - bbMap.put("\n\\s+?(.+?)", "\\[tt\\]$1\\[/tt\\]"); - //superscript/subscript - bbMap.put("\n\\s+?(.+?)", "\\[sub\\]$1\\[/sub\\]"); - bbMap.put("\n\\s+?(.+?)", "\\[sup\\]$1\\[/sup\\]"); - //tables - bbMap.put("\\s+?([\\S\\s]+?)", "\\[td\\]$1\\[/td\\]"); - bbMap.put("([\\S\\s]+?)\n ", "\\[tr\\]$1\\[/tr\\]"); - bbMap.put("\n\\s+?\n \n ([\\S\\s]+?)\n \n
    " - , "\\[table\\]$2\\[/table\\]"); - //videos - bbMap.put("\n\\s+?
    \n", - "[youtube]https://www.youtube.com/watch?v=$1[/youtube]"); - //ftp - bbMap.put("([\\S\\s]+?)", "\\[fpt=ftp:$1\\]$2\\[/ftp\\]"); - //mailto - bbMap.put("\n\\s+?([\\S\\s]+?)", "\\[email\\]$2\\[/email\\]"); - //links - bbMap.put("\n\\s+?([\\S\\s]+?)", "\\[url=$1\\]$2\\[/url\\]"); - //smileys - for (Map.Entry entry : smileysMap1.entrySet()) { - bbMap.put("\n \""", entry.getValue().toString()); - } - for (Map.Entry entry : smileysMap2.entrySet()) { //Those that have empty alt tag - bbMap.put("\n ", entry.getValue().toString()); - } - - bbMap.put("\n \"Undecided\"" - , Matcher.quoteReplacement(":-\\")); - - //html stuff on the end - bbMap.put("\n
    ", ""); - - for (Map.Entry entry : bbMap.entrySet()) { - html = html.replaceAll(entry.getKey().toString(), entry.getValue().toString()); - } - - //img need to be done last or it messes up everything else - html = html.replaceAll("\\s+", - "\\[img width=$2 height=$3\\]$1\\[/img\\]"); - html = html.replaceAll("\\s+", - "\\[img height=$2 width=$3\\]$1\\[/img\\]"); - html = html.replaceAll("\\s+", "\\[img width=$2\\]$1\\[/img\\]"); - html = html.replaceAll("\\s+", "\\[img height=$2\\]$1\\[/img\\]"); - html = html.replaceAll("\\s+", "\\[img\\]$1\\[/img\\]"); - - return html; - } - /** * Returns a String with a single FontAwesome typeface character corresponding to this file's * extension. From d84575b3aa30b68f3b3d2a93a856cd72f931f1e1 Mon Sep 17 00:00:00 2001 From: Apostolof Date: Tue, 21 Mar 2017 00:06:42 +0200 Subject: [PATCH 16/18] Bug fixes --- app/build.gradle | 5 ++-- .../main/recent/RecentFragment.java | 2 +- .../activities/topic/TopicActivity.java | 23 ++++++++++++------- .../mthmmy/activities/topic/TopicAdapter.java | 7 +++--- .../mthmmy/activities/topic/TopicParser.java | 15 +++++++++--- .../java/gr/thmmy/mthmmy/model/ThmmyPage.java | 6 ++++- 6 files changed, 40 insertions(+), 18 deletions(-) diff --git a/app/build.gradle b/app/build.gradle index a5af6136..b637c25f 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -20,9 +20,10 @@ android { proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' } debug { - def date = new Date().format('ddMMyy_HHmm'); + def date = new Date().format('ddMMyy_HH'); //def date = 1; - archivesBaseName = archivesBaseName + "-$date" + //archivesBaseName = archivesBaseName + "-$date" + archivesBaseName = archivesBaseName } } } diff --git a/app/src/main/java/gr/thmmy/mthmmy/activities/main/recent/RecentFragment.java b/app/src/main/java/gr/thmmy/mthmmy/activities/main/recent/RecentFragment.java index d9e92599..47f4678d 100644 --- a/app/src/main/java/gr/thmmy/mthmmy/activities/main/recent/RecentFragment.java +++ b/app/src/main/java/gr/thmmy/mthmmy/activities/main/recent/RecentFragment.java @@ -179,7 +179,7 @@ public class RecentFragment extends BaseFragment { if (result == 0) recentAdapter.notifyDataSetChanged(); else if (result == 2) - Toast.makeText(getActivity(), "Network error", Toast.LENGTH_SHORT).show(); + Toast.makeText(getActivity(), "Network error", Toast.LENGTH_SHORT).show(); //Fixme, sometimes activity isn't ready progressBar.setVisibility(ProgressBar.INVISIBLE); swipeRefreshLayout.setRefreshing(false); diff --git a/app/src/main/java/gr/thmmy/mthmmy/activities/topic/TopicActivity.java b/app/src/main/java/gr/thmmy/mthmmy/activities/topic/TopicActivity.java index 9e35e942..7ec81619 100644 --- a/app/src/main/java/gr/thmmy/mthmmy/activities/topic/TopicActivity.java +++ b/app/src/main/java/gr/thmmy/mthmmy/activities/topic/TopicActivity.java @@ -407,7 +407,8 @@ public class TopicActivity extends BaseActivity { paginationEnabled(true); changePage(pageRequestValue - 1); } else if (event.getAction() == MotionEvent.ACTION_MOVE) { - if (!rect.contains(v.getLeft() + (int) event.getX(), v.getTop() + (int) event.getY())) { //TODO fix bug + if (rect != null && + !rect.contains(v.getLeft() + (int) event.getX(), v.getTop() + (int) event.getY())) { autoIncrement = false; incrementPageRequestValue(thisPage - pageRequestValue); paginationEnabled(true); @@ -469,7 +470,6 @@ public class TopicActivity extends BaseActivity { protected Integer doInBackground(String... strings) { Document document; - base_url = strings[0].substring(0, strings[0].lastIndexOf(".")); //New topic's base url String newPageUrl = strings[0]; //Finds the index of message focus if present @@ -484,26 +484,33 @@ public class TopicActivity extends BaseActivity { } } //Checks if the page to be loaded is the one already shown - if (!reloadingPage && !Objects.equals(loadedPageUrl, "") && loadedPageUrl.contains(base_url)) { + if (!reloadingPage && !Objects.equals(loadedPageUrl, "") && newPageUrl.contains(base_url)) { if (newPageUrl.contains("topicseen#new") || newPageUrl.contains("#new")) if (thisPage == numberOfPages) return SAME_PAGE; if (newPageUrl.contains("msg")) { String tmpUrlSbstr = newPageUrl.substring(newPageUrl.indexOf("msg") + 3); + Log.d("TAG", tmpUrlSbstr); if (tmpUrlSbstr.contains("msg")) tmpUrlSbstr = tmpUrlSbstr.substring(0, tmpUrlSbstr.indexOf("msg") - 1); + Log.d("TAG", tmpUrlSbstr); int testAgainst = Integer.parseInt(tmpUrlSbstr); + Log.d("TAG", "testAgainst = " + testAgainst); for (Post post : postsList) { + Log.d("TAG", "post index = " + post.getPostIndex()); if (post.getPostIndex() == testAgainst) { return SAME_PAGE; } } - } else if (Integer.parseInt(newPageUrl.substring(base_url.length() + 1)) / 15 + 1 == thisPage) //TODO fix bug + } else if ((Objects.equals(newPageUrl, base_url) && thisPage == 1) || + Integer.parseInt(newPageUrl.substring(base_url.length() + 1)) / 15 + 1 == thisPage) return SAME_PAGE; } else if (!Objects.equals(loadedPageUrl, "")) topicTitle = null; if (reloadingPage) reloadingPage = !reloadingPage; loadedPageUrl = newPageUrl; + if (strings[0].substring(0, strings[0].lastIndexOf(".")).contains("topic=")) + base_url = strings[0].substring(0, strings[0].lastIndexOf(".")); //New topic's base url replyPageUrl = null; Request request = new Request.Builder() .url(newPageUrl) @@ -693,7 +700,7 @@ public class TopicActivity extends BaseActivity { 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"); - subject = document.select("input[name=subject]").first().attr("value"); + //subject = document.select("input[name=subject]").first().attr("value"); topic = document.select("input[name=topic]").first().attr("value"); } catch (IOException e) { Timber.e("Post failed.", e); @@ -705,11 +712,11 @@ public class TopicActivity extends BaseActivity { RequestBody postBody = new MultipartBody.Builder() .setType(MultipartBody.FORM) - .addFormDataPart("message", message[0]) + .addFormDataPart("message", message[1]) .addFormDataPart("num_replies", numReplies) .addFormDataPart("seqnum", seqnum) .addFormDataPart("sc", sc) - .addFormDataPart("subject", subject) + .addFormDataPart("subject", message[0]) .addFormDataPart("topic", topic) .build(); @@ -742,7 +749,7 @@ public class TopicActivity extends BaseActivity { protected void onPostExecute(Boolean result) { View view = getCurrentFocus(); if (view != null) { - InputMethodManager imm = (InputMethodManager)getSystemService(Context.INPUT_METHOD_SERVICE); + InputMethodManager imm = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE); imm.hideSoftInputFromWindow(view.getWindowToken(), 0); } diff --git a/app/src/main/java/gr/thmmy/mthmmy/activities/topic/TopicAdapter.java b/app/src/main/java/gr/thmmy/mthmmy/activities/topic/TopicAdapter.java index db548985..3667417a 100644 --- a/app/src/main/java/gr/thmmy/mthmmy/activities/topic/TopicAdapter.java +++ b/app/src/main/java/gr/thmmy/mthmmy/activities/topic/TopicAdapter.java @@ -471,9 +471,10 @@ class TopicAdapter extends RecyclerView.Adapter { holder.submitButton.setEnabled(false); replyTask.execute(holder.quickReplySubject.getText().toString(), holder.quickReply.getText().toString()); - replyDataHolder[replySubject] = "Re: " + topicTitle; - replyDataHolder[replyText] = ""; - holder.quickReply.setText(""); + + holder.quickReplySubject.getText().clear(); + holder.quickReplySubject.setText("Re: " + topicTitle); + holder.quickReply.getText().clear(); } }); } diff --git a/app/src/main/java/gr/thmmy/mthmmy/activities/topic/TopicParser.java b/app/src/main/java/gr/thmmy/mthmmy/activities/topic/TopicParser.java index 7d21196a..efff957e 100644 --- a/app/src/main/java/gr/thmmy/mthmmy/activities/topic/TopicParser.java +++ b/app/src/main/java/gr/thmmy/mthmmy/activities/topic/TopicParser.java @@ -1,6 +1,7 @@ package gr.thmmy.mthmmy.activities.topic; import android.graphics.Color; +import android.util.Log; import org.jsoup.Jsoup; import org.jsoup.nodes.Document; @@ -194,11 +195,19 @@ class TopicParser { //This is an int assigned by the forum used for post focusing and quotes, it is not //the same as reply index. Element postIndex = thisRow.select("a[name^=msg]").first(); - if (postIndex == null) - p_postIndex = NO_INDEX; - else { + if (postIndex != null) { String tmp = postIndex.attr("name"); p_postIndex = Integer.parseInt(tmp.substring(tmp.indexOf("msg") + 3)); + } else{ + postIndex = thisRow.select("div[id^=subject]").first(); + Log.d("TAG", "got"); + Log.d("TAG", postIndex.toString()); + if (postIndex == null) + p_postIndex = NO_INDEX; + else{ + String tmp = postIndex.attr("id"); + p_postIndex = Integer.parseInt(tmp.substring(tmp.indexOf("subject") + 8)); + } } Element postLastEditDate = thisRow.select("td.smalltext[id^=modified_]").first(); diff --git a/app/src/main/java/gr/thmmy/mthmmy/model/ThmmyPage.java b/app/src/main/java/gr/thmmy/mthmmy/model/ThmmyPage.java index 38f95867..12c94f95 100644 --- a/app/src/main/java/gr/thmmy/mthmmy/model/ThmmyPage.java +++ b/app/src/main/java/gr/thmmy/mthmmy/model/ThmmyPage.java @@ -1,6 +1,7 @@ package gr.thmmy.mthmmy.model; import android.net.Uri; +import android.util.Log; import java.util.Objects; @@ -170,7 +171,10 @@ public class ThmmyPage { public static String getBoardId(String boardUrl) { if (resolvePageCategory(Uri.parse(boardUrl)) == PageCategory.BOARD) { - return boardUrl.substring(boardUrl.indexOf("board=") + 6, boardUrl.lastIndexOf(".")); + String returnString = boardUrl.substring(boardUrl.indexOf("board=") + 6); + if (returnString.contains(".")) + returnString = boardUrl.substring(boardUrl.indexOf("board=") + 6, boardUrl.lastIndexOf(".")); + return returnString; } return null; } From d5b520690af4a784eea43d43900e09f8c05e25f8 Mon Sep 17 00:00:00 2001 From: Apostolof Date: Tue, 21 Mar 2017 00:56:07 +0200 Subject: [PATCH 17/18] Bug fixes --- .../mthmmy/activities/main/MainActivity.java | 1 - .../activities/main/forum/ForumAdapter.java | 6 +-- .../activities/topic/TopicActivity.java | 25 ++++++------ .../mthmmy/activities/topic/TopicAdapter.java | 14 +++++-- .../mthmmy/activities/topic/TopicParser.java | 2 - .../gr/thmmy/mthmmy/base/BaseActivity.java | 14 +++---- .../gr/thmmy/mthmmy/base/BaseFragment.java | 7 ++-- .../java/gr/thmmy/mthmmy/model/Category.java | 3 +- .../java/gr/thmmy/mthmmy/model/ThmmyPage.java | 1 - .../mthmmy/services/DownloadService.java | 39 +++++++------------ .../thmmy/mthmmy/session/SessionManager.java | 34 ++++++++-------- .../mthmmy/utils/CenterVerticalSpan.java | 2 +- .../gr/thmmy/mthmmy/utils/ParseHelpers.java | 2 - .../utils/exceptions/UnknownException.java | 6 +-- .../layout/activity_topic_quick_reply_row.xml | 4 +- 15 files changed, 74 insertions(+), 86 deletions(-) diff --git a/app/src/main/java/gr/thmmy/mthmmy/activities/main/MainActivity.java b/app/src/main/java/gr/thmmy/mthmmy/activities/main/MainActivity.java index d3d38870..ddc604b4 100644 --- a/app/src/main/java/gr/thmmy/mthmmy/activities/main/MainActivity.java +++ b/app/src/main/java/gr/thmmy/mthmmy/activities/main/MainActivity.java @@ -9,7 +9,6 @@ import android.support.v4.app.FragmentManager; import android.support.v4.app.FragmentPagerAdapter; import android.support.v4.view.ViewPager; import android.support.v7.widget.Toolbar; -import android.util.Log; import android.widget.Toast; import gr.thmmy.mthmmy.R; diff --git a/app/src/main/java/gr/thmmy/mthmmy/activities/main/forum/ForumAdapter.java b/app/src/main/java/gr/thmmy/mthmmy/activities/main/forum/ForumAdapter.java index 40f14c93..9f896b29 100644 --- a/app/src/main/java/gr/thmmy/mthmmy/activities/main/forum/ForumAdapter.java +++ b/app/src/main/java/gr/thmmy/mthmmy/activities/main/forum/ForumAdapter.java @@ -36,7 +36,7 @@ class ForumAdapter extends ExpandableRecyclerAdapter { private String[] replyDataHolder = new String[2]; private int replySubject = 0, replyText = 1; + private String loadedPageUrl = ""; /** * @param context the context of the {@link RecyclerView} * @param postsList List of {@link Post} objects to use */ TopicAdapter(Context context, List postsList, TopicActivity.TopicTask topicTask - , String topicTitle) { + , String topicTitle, String loadedPageUrl) { this.context = context; this.postsList = postsList; @@ -122,12 +123,18 @@ class TopicAdapter extends RecyclerView.Adapter { } this.topicTask = topicTask; this.topicTitle = topicTitle; + this.loadedPageUrl = loadedPageUrl; } void prepareForReply(TopicActivity.ReplyTask replyTask) { this.replyTask = replyTask; } + void setTopicInfo(String topicTitle, String loadedPageUrl) { + this.topicTitle = topicTitle; + this.loadedPageUrl = loadedPageUrl; + } + @Override public int getItemViewType(int position) { return postsList.get(position) == null ? VIEW_TYPE_QUICK_REPLY : VIEW_TYPE_POST; @@ -712,7 +719,7 @@ class TopicAdapter extends RecyclerView.Adapter { } private class CustomEditTextListener implements TextWatcher { - private int positionInDataHolder; + private final int positionInDataHolder; CustomEditTextListener(int positionInDataHolder) { this.positionInDataHolder = positionInDataHolder; @@ -777,7 +784,8 @@ class TopicAdapter extends RecyclerView.Adapter { if (postsList.get(quotePosition).getPostIndex() != 0) { if (postDate != null) { return "[quote author=" + postsList.get(quotePosition).getAuthor() - + " link=topic=68525.msg" + postsList.get(quotePosition).getPostIndex() + + " link=topic=" + ThmmyPage.getTopicId(loadedPageUrl) + ".msg" + + postsList.get(quotePosition).getPostIndex() + "#msg" + postsList.get(quotePosition).getPostIndex() + " date=" + postDate.getTime() / 1000 + "]" + "\n" + postsList.get(quotePosition).getContent() diff --git a/app/src/main/java/gr/thmmy/mthmmy/activities/topic/TopicParser.java b/app/src/main/java/gr/thmmy/mthmmy/activities/topic/TopicParser.java index efff957e..3ce9c24d 100644 --- a/app/src/main/java/gr/thmmy/mthmmy/activities/topic/TopicParser.java +++ b/app/src/main/java/gr/thmmy/mthmmy/activities/topic/TopicParser.java @@ -200,8 +200,6 @@ class TopicParser { p_postIndex = Integer.parseInt(tmp.substring(tmp.indexOf("msg") + 3)); } else{ postIndex = thisRow.select("div[id^=subject]").first(); - Log.d("TAG", "got"); - Log.d("TAG", postIndex.toString()); if (postIndex == null) p_postIndex = NO_INDEX; else{ diff --git a/app/src/main/java/gr/thmmy/mthmmy/base/BaseActivity.java b/app/src/main/java/gr/thmmy/mthmmy/base/BaseActivity.java index 9e2a3023..3be339d3 100644 --- a/app/src/main/java/gr/thmmy/mthmmy/base/BaseActivity.java +++ b/app/src/main/java/gr/thmmy/mthmmy/base/BaseActivity.java @@ -64,8 +64,8 @@ public abstract class BaseActivity extends AppCompatActivity { private static final String BOOKMARKED_TOPICS_KEY = "bookmarkedTopicsKey"; private static final String BOOKMARKED_BOARDS_KEY = "bookmarkedBoardsKey"; protected Bookmark thisPageBookmark; - protected MenuItem thisPageBookmarkMenuButton; - protected ImageButton thisPageBookmarkImageButton; + private MenuItem thisPageBookmarkMenuButton; + private ImageButton thisPageBookmarkImageButton; private SharedPreferences bookmarksFile; private ArrayList topicsBookmarked; private ArrayList boardsBookmarked; @@ -347,7 +347,7 @@ public abstract class BaseActivity extends AppCompatActivity { }); } - protected void updateDrawer() { + private void updateDrawer() { if (drawer != null) { if (!sessionManager.isLoggedIn()) //When logged out or if user is guest { @@ -376,7 +376,7 @@ public abstract class BaseActivity extends AppCompatActivity { * Result toast will always display a success, because when user chooses logout all data are * cleared regardless of the actual outcome */ - protected class LogoutTask extends AsyncTask { //Attempt logout + private class LogoutTask extends AsyncTask { //Attempt logout ProgressDialog progressDialog; protected Integer doInBackground(Void... voids) { @@ -419,7 +419,7 @@ public abstract class BaseActivity extends AppCompatActivity { } } - protected void topicMenuBookmarkClick(){ + protected void topicMenuBookmarkClick() { if (thisPageBookmark.matchExists(topicsBookmarked)) { thisPageBookmarkMenuButton.setIcon(notBookmarked); toggleTopicToBookmarks(thisPageBookmark); @@ -524,7 +524,7 @@ public abstract class BaseActivity extends AppCompatActivity { } //Display popup gor user to grant permission - public void requestPerms() { //Runtime permissions request for devices with API >= 23 + private void requestPerms() { //Runtime permissions request for devices with API >= 23 if (Build.VERSION.SDK_INT > Build.VERSION_CODES.LOLLIPOP_MR1) { String[] PERMISSIONS_STORAGE = { Manifest.permission.READ_EXTERNAL_STORAGE, @@ -559,7 +559,7 @@ public abstract class BaseActivity extends AppCompatActivity { } //Uses temp file - called after permission grant - public void launchDownloadService() { + private void launchDownloadService() { if (checkPerms()) DownloadService.startActionDownload(this, tempThmmyFile.getFileUrl().toString()); diff --git a/app/src/main/java/gr/thmmy/mthmmy/base/BaseFragment.java b/app/src/main/java/gr/thmmy/mthmmy/base/BaseFragment.java index c33ffdf6..20bd8da2 100644 --- a/app/src/main/java/gr/thmmy/mthmmy/base/BaseFragment.java +++ b/app/src/main/java/gr/thmmy/mthmmy/base/BaseFragment.java @@ -15,7 +15,7 @@ public abstract class BaseFragment extends Fragment { protected FragmentInteractionListener fragmentInteractionListener; private String TAG; - protected int sectionNumber; + private int sectionNumber; protected static OkHttpClient client; @Override @@ -23,7 +23,7 @@ public abstract class BaseFragment extends Fragment { super.onCreate(savedInstanceState); TAG = getArguments().getString(ARG_TAG); sectionNumber = getArguments().getInt(ARG_SECTION_NUMBER); - if(client==null) + if (client == null) client = BaseApplication.getInstance().getClient(); //must check every time - e.g. // becomes null when app restarts after crash Timber.d("onCreate"); @@ -76,5 +76,6 @@ public abstract class BaseFragment extends Fragment { * the activity that contains it, to allow communication upon interaction, * between the fragment and the activity/ other fragments */ - public interface FragmentInteractionListener {} + public interface FragmentInteractionListener { + } } diff --git a/app/src/main/java/gr/thmmy/mthmmy/model/Category.java b/app/src/main/java/gr/thmmy/mthmmy/model/Category.java index ce43c42d..46142bbf 100644 --- a/app/src/main/java/gr/thmmy/mthmmy/model/Category.java +++ b/app/src/main/java/gr/thmmy/mthmmy/model/Category.java @@ -7,8 +7,7 @@ import java.util.List; import static android.R.attr.id; -public class Category implements Parent -{ +public class Category implements Parent { private final String title; private final String categoryURL; private boolean expanded = false; diff --git a/app/src/main/java/gr/thmmy/mthmmy/model/ThmmyPage.java b/app/src/main/java/gr/thmmy/mthmmy/model/ThmmyPage.java index 12c94f95..9e935f69 100644 --- a/app/src/main/java/gr/thmmy/mthmmy/model/ThmmyPage.java +++ b/app/src/main/java/gr/thmmy/mthmmy/model/ThmmyPage.java @@ -1,7 +1,6 @@ package gr.thmmy.mthmmy.model; import android.net.Uri; -import android.util.Log; import java.util.Objects; diff --git a/app/src/main/java/gr/thmmy/mthmmy/services/DownloadService.java b/app/src/main/java/gr/thmmy/mthmmy/services/DownloadService.java index cd878b25..52883ef4 100644 --- a/app/src/main/java/gr/thmmy/mthmmy/services/DownloadService.java +++ b/app/src/main/java/gr/thmmy/mthmmy/services/DownloadService.java @@ -27,7 +27,7 @@ import timber.log.Timber; */ public class DownloadService extends IntentService { private static final String TAG = "DownloadService"; - private static int sDownloadId =0; + private static int sDownloadId = 0; private Receiver receiver; @@ -48,7 +48,6 @@ public class DownloadService extends IntentService { public static final String FAILED = "Failed"; - public DownloadService() { super("DownloadService"); } @@ -109,14 +108,12 @@ public class DownloadService extends IntentService { Response response = client.newCall(request).execute(); String contentType = response.headers("Content-Type").toString(); //check if link provides a binary file - if(contentType.equals("[application/octet-stream]")) - { + if (contentType.equals("[application/octet-stream]")) { fileName = response.headers("Content-Disposition").toString().split("\"")[1]; File dirPath = new File(SAVE_DIR); - if(!dirPath.isDirectory()) - { - if(dirPath.mkdirs()) + if (!dirPath.isDirectory()) { + if (dirPath.mkdirs()) Timber.i("mTHMMY's directory created successfully!"); else Timber.e("Couldn't create mTHMMY's directory..."); @@ -126,20 +123,16 @@ public class DownloadService extends IntentService { String nameFormat; String[] tokens = fileName.split("\\.(?=[^\\.]+$)"); - if(tokens.length!=2) - { + if (tokens.length != 2) { Timber.w("Couldn't get file extension..."); nameFormat = fileName + "(%d)"; - } - else + } else nameFormat = tokens[0] + "(%d)." + tokens[1]; - - File file = new File(dirPath, fileName); - for (int i = 1;;i++) { + for (int i = 1; ; i++) { if (!file.exists()) { break; } @@ -157,21 +150,18 @@ public class DownloadService extends IntentService { sink.flush(); Timber.i("Download OK!"); sendNotification(downloadId, COMPLETED, fileName); - } - else + } else Timber.e("Response not a binary file!"); - } - catch (FileNotFoundException e){ + } catch (FileNotFoundException e) { Timber.i("Download failed..."); Timber.e("FileNotFound", e); sendNotification(downloadId, FAILED, fileName); - } - catch (IOException e){ + } catch (IOException e) { Timber.i("Download failed..."); Timber.e("IOException", e); sendNotification(downloadId, FAILED, fileName); } finally { - if (sink!= null) { + if (sink != null) { try { sink.close(); } catch (IOException e) { @@ -181,9 +171,8 @@ public class DownloadService extends IntentService { } } - private void sendNotification(int downloadId, String type, @NonNull String fileName) - { - Intent intent = new Intent(ACTION_DOWNLOAD); + private void sendNotification(int downloadId, String type, @NonNull String fileName) { + Intent intent = new Intent(ACTION_DOWNLOAD); switch (type) { case STARTED: { intent.putExtra(EXTRA_NOTIFICATION_TITLE, "Download Started"); @@ -203,7 +192,7 @@ public class DownloadService extends IntentService { intent.putExtra(EXTRA_NOTIFICATION_TICKER, "Download Failed"); break; } - default:{ + default: { Timber.e("Invalid notification case!"); return; } diff --git a/app/src/main/java/gr/thmmy/mthmmy/session/SessionManager.java b/app/src/main/java/gr/thmmy/mthmmy/session/SessionManager.java index ce0f9228..1455fb27 100644 --- a/app/src/main/java/gr/thmmy/mthmmy/session/SessionManager.java +++ b/app/src/main/java/gr/thmmy/mthmmy/session/SessionManager.java @@ -48,12 +48,12 @@ public class SessionManager { public static final int EXCEPTION = 6; // Client & Cookies - private OkHttpClient client; - private PersistentCookieJar cookieJar; - private SharedPrefsCookiePersistor cookiePersistor; //Used to explicitly edit cookies in cookieJar + private final OkHttpClient client; + private final PersistentCookieJar cookieJar; + private final SharedPrefsCookiePersistor cookiePersistor; //Used to explicitly edit cookies in cookieJar //Shared Preferences & its keys - private SharedPreferences sharedPrefs; + private final SharedPreferences sharedPrefs; private static final String USERNAME = "Username"; private static final String AVATAR_LINK = "AvatarLink"; private static final String HAS_AVATAR = "HasAvatar"; @@ -109,7 +109,7 @@ public class SessionManager { Elements unreadRepliesLinks = document.select("a[href=https://www.thmmy.gr/smf/index.php?action=unreadreplies]"); - if (unreadRepliesLinks.size()>=2) //Normally it's just == 2, but who knows what can be posted by users + if (unreadRepliesLinks.size() >= 2) //Normally it's just == 2, but who knows what can be posted by users { Timber.i("Login successful!"); setPersistentCookieSession(); //Store cookies @@ -289,7 +289,7 @@ public class SessionManager { } @NonNull - private String extractUserName(@NonNull Document doc){ + private String extractUserName(@NonNull Document doc) { //Scribbles2 Theme Elements user = doc.select("div[id=myuser] > h3"); String userName = null; @@ -301,8 +301,7 @@ public class SessionManager { Matcher matcher = pattern.matcher(txt); if (matcher.find()) userName = matcher.group(1); - } - else { + } else { //Helios_Multi and SMF_oneBlue user = doc.select("td.smalltext[width=100%] b"); if (user.size() == 1) @@ -314,20 +313,20 @@ public class SessionManager { userName = user.first().ownText(); } } - - if(userName != null && !userName.isEmpty()) + + if (userName != null && !userName.isEmpty()) return userName; Timber.e("ParseException", new ParseException("Parsing failed(username extraction)")); - return "User"; //return a default username + return "User"; //return a default username } @Nullable private String extractAvatarLink(@NonNull Document doc) { - Elements avatar = doc.getElementsByClass("avatar"); - if (!avatar.isEmpty()) - return avatar.first().attr("src"); + Elements avatar = doc.getElementsByClass("avatar"); + if (!avatar.isEmpty()) + return avatar.first().attr("src"); Timber.i("Extracting avatar's link failed!"); return null; @@ -337,14 +336,13 @@ public class SessionManager { private String extractLogoutLink(@NonNull Document doc) { 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"); - if(link != null && !link.isEmpty()) + if (link != null && !link.isEmpty()) return link; } Timber.e("ParseException", new ParseException("Parsing failed(logoutLink extraction)")); - return "https://www.thmmy.gr/smf/index.php?action=logout"; //return a default link + return "https://www.thmmy.gr/smf/index.php?action=logout"; //return a default link } //----------------------------------OTHER FUNCTIONS END----------------------------------------- diff --git a/app/src/main/java/gr/thmmy/mthmmy/utils/CenterVerticalSpan.java b/app/src/main/java/gr/thmmy/mthmmy/utils/CenterVerticalSpan.java index cc98fe90..12f0a9e6 100644 --- a/app/src/main/java/gr/thmmy/mthmmy/utils/CenterVerticalSpan.java +++ b/app/src/main/java/gr/thmmy/mthmmy/utils/CenterVerticalSpan.java @@ -14,7 +14,7 @@ public class CenterVerticalSpan extends ReplacementSpan { } @Override - public void draw(@NonNull Canvas canvas, CharSequence text, int start, int end, float x, int top, int y, int bottom, Paint paint) { + public void draw(@NonNull Canvas canvas, CharSequence text, int start, int end, float x, int top, int y, int bottom,@NonNull Paint paint) { text = text.subSequence(start, end); Rect charSize = new Rect(); paint.getTextBounds(text.toString(), 0, 1, charSize); diff --git a/app/src/main/java/gr/thmmy/mthmmy/utils/ParseHelpers.java b/app/src/main/java/gr/thmmy/mthmmy/utils/ParseHelpers.java index 2e8867f5..75a9fa72 100644 --- a/app/src/main/java/gr/thmmy/mthmmy/utils/ParseHelpers.java +++ b/app/src/main/java/gr/thmmy/mthmmy/utils/ParseHelpers.java @@ -1,7 +1,5 @@ package gr.thmmy.mthmmy.utils; -import android.util.Log; - import org.jsoup.nodes.Document; import org.jsoup.nodes.Element; import org.jsoup.select.Elements; diff --git a/app/src/main/java/gr/thmmy/mthmmy/utils/exceptions/UnknownException.java b/app/src/main/java/gr/thmmy/mthmmy/utils/exceptions/UnknownException.java index fc0e7f65..81c890ad 100644 --- a/app/src/main/java/gr/thmmy/mthmmy/utils/exceptions/UnknownException.java +++ b/app/src/main/java/gr/thmmy/mthmmy/utils/exceptions/UnknownException.java @@ -5,10 +5,10 @@ package gr.thmmy.mthmmy.utils.exceptions; * exception is set, to report to FireBase. */ public class UnknownException extends Exception { - public UnknownException() {} + public UnknownException() { + } - public UnknownException(String message) - { + public UnknownException(String message) { super(message); } } diff --git a/app/src/main/res/layout/activity_topic_quick_reply_row.xml b/app/src/main/res/layout/activity_topic_quick_reply_row.xml index 602654ee..870d0a8c 100644 --- a/app/src/main/res/layout/activity_topic_quick_reply_row.xml +++ b/app/src/main/res/layout/activity_topic_quick_reply_row.xml @@ -1,6 +1,7 @@ + android:textSize="10sp" + tools:ignore="SmallSp"/> Date: Wed, 22 Mar 2017 00:14:33 +0200 Subject: [PATCH 18/18] Updated Version to 1.2.0 --- VERSION | 2 +- app/build.gradle | 12 +++++------- 2 files changed, 6 insertions(+), 8 deletions(-) diff --git a/VERSION b/VERSION index 45a1b3f4..26aaba0e 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -1.1.2 +1.2.0 diff --git a/app/build.gradle b/app/build.gradle index b637c25f..f1403f49 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -9,8 +9,8 @@ android { applicationId "gr.thmmy.mthmmy" minSdkVersion 19 targetSdkVersion 25 - versionCode 5 - versionName "1.1.2" + versionCode 6 + versionName "1.2.0" archivesBaseName = "mTHMMY-v$versionName" } @@ -19,12 +19,10 @@ android { minifyEnabled false proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' } - debug { + /*debug { def date = new Date().format('ddMMyy_HH'); - //def date = 1; - //archivesBaseName = archivesBaseName + "-$date" - archivesBaseName = archivesBaseName - } + archivesBaseName = archivesBaseName + "-$date" + }*/ } }