Browse Source

Minor fixes, cleanup and commenting.

pull/24/head
Apostolos Fanakis 8 years ago
parent
commit
05044e7e56
  1. 8
      app/src/main/java/gr/thmmy/mthmmy/activities/board/BoardAdapter.java
  2. 4
      app/src/main/java/gr/thmmy/mthmmy/activities/profile/ProfileActivity.java
  3. 2
      app/src/main/java/gr/thmmy/mthmmy/activities/profile/latestPosts/LatestPostsAdapter.java
  4. 2
      app/src/main/java/gr/thmmy/mthmmy/activities/topic/TopicActivity.java
  5. 19
      app/src/main/java/gr/thmmy/mthmmy/activities/topic/TopicAdapter.java
  6. 58
      app/src/main/java/gr/thmmy/mthmmy/model/Board.java
  7. 111
      app/src/main/java/gr/thmmy/mthmmy/model/LinkTarget.java
  8. 208
      app/src/main/java/gr/thmmy/mthmmy/model/Post.java
  9. 65
      app/src/main/java/gr/thmmy/mthmmy/model/PostSummary.java
  10. 72
      app/src/main/java/gr/thmmy/mthmmy/model/Topic.java
  11. 44
      app/src/main/java/gr/thmmy/mthmmy/model/TopicSummary.java
  12. 96
      app/src/main/java/gr/thmmy/mthmmy/utils/ParseHelpers.java

8
app/src/main/java/gr/thmmy/mthmmy/activities/board/BoardAdapter.java

@ -101,6 +101,12 @@ class BoardAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> {
, LinearLayout.LayoutParams.WRAP_CONTENT)); , LinearLayout.LayoutParams.WRAP_CONTENT));
topicTitle.setText(context.getString(R.string.topic_title)); topicTitle.setText(context.getString(R.string.topic_title));
topicTitle.setTypeface(topicTitle.getTypeface(), Typeface.BOLD); topicTitle.setTypeface(topicTitle.getTypeface(), Typeface.BOLD);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
topicTitle.setTextColor(context.getColor(R.color.primary_text));
} else {
//noinspection deprecation
topicTitle.setTextColor(context.getResources().getColor(R.color.primary_text));
}
topicTitle.setTextAlignment(View.TEXT_ALIGNMENT_CENTER); topicTitle.setTextAlignment(View.TEXT_ALIGNMENT_CENTER);
topicTitle.setTextSize(20f); topicTitle.setTextSize(20f);
@ -236,7 +242,7 @@ class BoardAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> {
topicViewHolder.topicSubject.setText(lockedSticky); topicViewHolder.topicSubject.setText(lockedSticky);
topicViewHolder.topicStartedBy.setText(context.getString(R.string.topic_started_by, topic.getStarter())); topicViewHolder.topicStartedBy.setText(context.getString(R.string.topic_started_by, topic.getStarter()));
topicViewHolder.topicStats.setText(topic.getStats()); topicViewHolder.topicStats.setText(topic.getStats());
topicViewHolder.topicLastPost.setText(context.getString(R.string.topic_last_post, topic.getLastPost())); topicViewHolder.topicLastPost.setText(context.getString(R.string.topic_last_post, topic.getLastPostDateAndTime()));
topicViewHolder.topicLastPost.setOnClickListener(new View.OnClickListener() { topicViewHolder.topicLastPost.setOnClickListener(new View.OnClickListener() {
@Override @Override
public void onClick(View view) { public void onClick(View view) {

4
app/src/main/java/gr/thmmy/mthmmy/activities/profile/ProfileActivity.java

@ -174,8 +174,8 @@ public class ProfileActivity extends BaseActivity implements LatestPostsFragment
@Override @Override
public void onLatestPostsFragmentInteraction(PostSummary postSummary) { public void onLatestPostsFragmentInteraction(PostSummary postSummary) {
Intent i = new Intent(ProfileActivity.this, TopicActivity.class); Intent i = new Intent(ProfileActivity.this, TopicActivity.class);
i.putExtra(BUNDLE_TOPIC_URL, postSummary.getTopicUrl()); i.putExtra(BUNDLE_TOPIC_URL, postSummary.getPostUrl());
i.putExtra(BUNDLE_TOPIC_TITLE, postSummary.getTitle().substring(postSummary.getTitle(). i.putExtra(BUNDLE_TOPIC_TITLE, postSummary.getSubject().substring(postSummary.getSubject().
lastIndexOf("/ ") + 2)); lastIndexOf("/ ") + 2));
startActivity(i); startActivity(i);
} }

2
app/src/main/java/gr/thmmy/mthmmy/activities/profile/latestPosts/LatestPostsAdapter.java

@ -66,7 +66,7 @@ class LatestPostsAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> {
PostSummary topic = parsedTopicSummaries.get(position); PostSummary topic = parsedTopicSummaries.get(position);
final LatestPostViewHolder latestPostViewHolder = (LatestPostViewHolder) holder; final LatestPostViewHolder latestPostViewHolder = (LatestPostViewHolder) holder;
latestPostViewHolder.postTitle.setText(topic.getTitle()); latestPostViewHolder.postTitle.setText(topic.getSubject());
latestPostViewHolder.postDate.setText(topic.getDateTime()); latestPostViewHolder.postDate.setText(topic.getDateTime());
latestPostViewHolder.post.loadDataWithBaseURL("file:///android_asset/" latestPostViewHolder.post.loadDataWithBaseURL("file:///android_asset/"
, topic.getPost(), "text/html", "UTF-8", null); , topic.getPost(), "text/html", "UTF-8", null);

2
app/src/main/java/gr/thmmy/mthmmy/activities/topic/TopicActivity.java

@ -385,7 +385,7 @@ public class TopicActivity extends BaseActivity {
switch (parseResult) { switch (parseResult) {
case SUCCESS: case SUCCESS:
progressBar.setVisibility(ProgressBar.INVISIBLE); progressBar.setVisibility(ProgressBar.INVISIBLE);
topicAdapter.customNotifyDataSetChanged(); topicAdapter.customNotifyDataSetChanged(new TopicTask());
replyFAB.setEnabled(true); replyFAB.setEnabled(true);
//Set current page //Set current page

19
app/src/main/java/gr/thmmy/mthmmy/activities/topic/TopicAdapter.java

@ -96,7 +96,7 @@ class TopicAdapter extends RecyclerView.Adapter<TopicAdapter.MyViewHolder> {
private static final int isQuoteButtonChecked = 2; private static final int isQuoteButtonChecked = 2;
private final MaterialProgressBar progressBar; private final MaterialProgressBar progressBar;
private DownloadTask downloadTask; private DownloadTask downloadTask;
private final TopicActivity.TopicTask topicTask; private TopicActivity.TopicTask topicTask;
/** /**
* Custom {@link RecyclerView.ViewHolder} implementation * Custom {@link RecyclerView.ViewHolder} implementation
@ -223,7 +223,7 @@ class TopicAdapter extends RecyclerView.Adapter<TopicAdapter.MyViewHolder> {
holder.postNum.setText(""); holder.postNum.setText("");
holder.subject.setText(currentPost.getSubject()); holder.subject.setText(currentPost.getSubject());
holder.post.loadDataWithBaseURL("file:///android_asset/", currentPost.getContent(), "text/html", "UTF-8", null); holder.post.loadDataWithBaseURL("file:///android_asset/", currentPost.getContent(), "text/html", "UTF-8", null);
if (currentPost.getAttachedFiles().size() != 0) { if (currentPost.getAttachedFiles() != null && currentPost.getAttachedFiles().size() != 0) {
holder.bodyFooterDivider.setVisibility(View.VISIBLE); holder.bodyFooterDivider.setVisibility(View.VISIBLE);
int filesTextColor; int filesTextColor;
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
@ -286,7 +286,7 @@ class TopicAdapter extends RecyclerView.Adapter<TopicAdapter.MyViewHolder> {
holder.personalText.setVisibility(View.VISIBLE); holder.personalText.setVisibility(View.VISIBLE);
} else } else
holder.personalText.setVisibility(View.GONE); holder.personalText.setVisibility(View.GONE);
if (mNumberOfStars != 0) { if (mNumberOfStars > 0) {
holder.stars.setTypeface(Typeface.createFromAsset(context.getAssets() holder.stars.setTypeface(Typeface.createFromAsset(context.getAssets()
, "fonts/fontawesome-webfont.ttf")); , "fonts/fontawesome-webfont.ttf"));
@ -300,6 +300,7 @@ class TopicAdapter extends RecyclerView.Adapter<TopicAdapter.MyViewHolder> {
holder.stars.setVisibility(View.VISIBLE); holder.stars.setVisibility(View.VISIBLE);
} else } else
holder.stars.setVisibility(View.GONE); holder.stars.setVisibility(View.GONE);
//Special card for special member of the month!
if (mUserColor == TopicParser.USER_COLOR_PINK) { if (mUserColor == TopicParser.USER_COLOR_PINK) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
holder.cardChildLinear.setBackground(context.getResources(). holder.cardChildLinear.setBackground(context.getResources().
@ -425,7 +426,8 @@ class TopicAdapter extends RecyclerView.Adapter<TopicAdapter.MyViewHolder> {
holder.post.setOnTouchListener(new CustomTouchListener(holder.post, holder.cardView)); holder.post.setOnTouchListener(new CustomTouchListener(holder.post, holder.cardView));
} }
void customNotifyDataSetChanged() { void customNotifyDataSetChanged(TopicActivity.TopicTask topicTask) {
this.topicTask = topicTask;
viewProperties.clear(); viewProperties.clear();
for (int i = 0; i < postsList.size(); ++i) { for (int i = 0; i < postsList.size(); ++i) {
//Initializes properties, array's values will be false by default //Initializes properties, array's values will be false by default
@ -529,7 +531,7 @@ class TopicAdapter extends RecyclerView.Adapter<TopicAdapter.MyViewHolder> {
final String uriString = uri.toString(); final String uriString = uri.toString();
LinkTarget.Target target = LinkTarget.resolveLinkTarget(uri); LinkTarget.Target target = LinkTarget.resolveLinkTarget(uri);
if (LinkTarget.targetEqual(target, LinkTarget.Target.TOPIC)) { if (target.is(LinkTarget.Target.TOPIC)) {
//This url points to a topic //This url points to a topic
//Checks if this is the current topic //Checks if this is the current topic
if (Objects.equals(uriString.substring(0, uriString.lastIndexOf(".")), base_url)) { if (Objects.equals(uriString.substring(0, uriString.lastIndexOf(".")), base_url)) {
@ -551,7 +553,8 @@ class TopicAdapter extends RecyclerView.Adapter<TopicAdapter.MyViewHolder> {
} }
} }
topicTask.execute(uri.toString()); topicTask.execute(uri.toString());
} else if (LinkTarget.targetEqual(target, LinkTarget.Target.BOARD)) { return true;
} else if (target.is(LinkTarget.Target.BOARD)) {
Intent intent = new Intent(context, BoardActivity.class); Intent intent = new Intent(context, BoardActivity.class);
Bundle extras = new Bundle(); Bundle extras = new Bundle();
extras.putString(BUNDLE_BOARD_URL, uriString); extras.putString(BUNDLE_BOARD_URL, uriString);
@ -559,7 +562,8 @@ class TopicAdapter extends RecyclerView.Adapter<TopicAdapter.MyViewHolder> {
intent.putExtras(extras); intent.putExtras(extras);
intent.setFlags(FLAG_ACTIVITY_NEW_TASK); intent.setFlags(FLAG_ACTIVITY_NEW_TASK);
context.startActivity(intent); context.startActivity(intent);
} else if (LinkTarget.targetEqual(target, LinkTarget.Target.PROFILE)) { return true;
} else if (target.is(LinkTarget.Target.PROFILE)) {
Intent intent = new Intent(context, ProfileActivity.class); Intent intent = new Intent(context, ProfileActivity.class);
Bundle extras = new Bundle(); Bundle extras = new Bundle();
extras.putString(BUNDLE_PROFILE_URL, uriString); extras.putString(BUNDLE_PROFILE_URL, uriString);
@ -568,6 +572,7 @@ class TopicAdapter extends RecyclerView.Adapter<TopicAdapter.MyViewHolder> {
intent.putExtras(extras); intent.putExtras(extras);
intent.setFlags(FLAG_ACTIVITY_NEW_TASK); intent.setFlags(FLAG_ACTIVITY_NEW_TASK);
context.startActivity(intent); context.startActivity(intent);
return true;
} }
Intent intent = new Intent(Intent.ACTION_VIEW, uri); Intent intent = new Intent(Intent.ACTION_VIEW, uri);

58
app/src/main/java/gr/thmmy/mthmmy/model/Board.java

@ -1,8 +1,36 @@
package gr.thmmy.mthmmy.model; package gr.thmmy.mthmmy.model;
/**
* Class that defines a board of the forum. All member variables are declared final (thus no setters
* are supplied). Class has one constructor and getter methods for all variables.
* <p>A forum board is described by the board's url, its title, the moderators assigned to it, its
* view and reply stats, its latest post's info and url.</p>
*/
public class Board { public class Board {
private final String url, title, mods, stats, lastPost, lastPostUrl; private final String url, title, mods, stats, lastPost, lastPostUrl;
// Suppresses default constructor
@SuppressWarnings("unused")
private Board() {
url = null;
title = null;
mods = null;
stats = null;
lastPost = null;
lastPostUrl = null;
}
/**
* Constructor specifying all class variables necessary to describe this board. All variables
* are declared final, once assigned they can not change.
*
* @param url this board's url
* @param title this board's title
* @param mods this board's assigned moderators
* @param stats this board's view and reply stats
* @param lastPost this board's latest post's info
* @param lastPostUrl this board's latest post's url
*/
public Board(String url, String title, String mods, String stats, String lastPost, String lastPostUrl) { public Board(String url, String title, String mods, String stats, String lastPost, String lastPostUrl) {
this.url = url; this.url = url;
this.title = title; this.title = title;
@ -12,26 +40,56 @@ public class Board {
this.lastPostUrl = lastPostUrl; this.lastPostUrl = lastPostUrl;
} }
/**
* Gets this board's url.
*
* @return this board's url
*/
public String getUrl() { public String getUrl() {
return url; return url;
} }
/**
* Gets this board's title.
*
* @return this board's title
*/
public String getTitle() { public String getTitle() {
return title; return title;
} }
/**
* Gets this board's assigned moderators.
*
* @return this board's moderators
*/
public String getMods() { public String getMods() {
return mods; return mods;
} }
/**
* Gets this board's view and reply stats.
*
* @return this board's stats
*/
public String getStats() { public String getStats() {
return stats; return stats;
} }
/**
* Gets this board's latest post's info.
*
* @return latest post's info
*/
public String getLastPost() { public String getLastPost() {
return lastPost; return lastPost;
} }
/**
* Gets this board's latest post's url.
*
* @return latest post's url
*/
public String getLastPostUrl() { public String getLastPostUrl() {
return lastPostUrl; return lastPostUrl;
} }

111
app/src/main/java/gr/thmmy/mthmmy/model/LinkTarget.java

@ -1,28 +1,125 @@
package gr.thmmy.mthmmy.model; package gr.thmmy.mthmmy.model;
import android.net.Uri; import android.net.Uri;
import android.support.annotation.NonNull;
import java.util.Objects; import java.util.Objects;
import mthmmy.utils.Report; import mthmmy.utils.Report;
/**
* This class consists exclusively of static classes (enums) and methods (excluding methods of inner
* classes). It can be used to resolve link targets as to whether they are pointing to the forum and
* where in the forum they may point.
*/
public class LinkTarget { public class LinkTarget {
/**
* Debug Tag for logging debug output to LogCat
*/
@SuppressWarnings("unused")
private static final String TAG = "LinkTarget"; private static final String TAG = "LinkTarget";
/**
* An enum describing a link's target by defining the types:<ul>
* <li>{@link #NOT_THMMY}</li>
* <li>{@link #THMMY}</li>
* <li>{@link #UNKNOWN_THMMY}</li>
* <li>{@link #TOPIC}</li>
* <li>{@link #BOARD}</li>
* <li>{@link #UNREAD_POSTS}</li>
* <li>{@link #PROFILE_SUMMARY}</li>
* <li>{@link #PROFILE_LATEST_POSTS}</li>
* <li>{@link #PROFILE_STATS}</li>
* <li>{@link #PROFILE}</li>
* </ul>
*/
public enum Target { public enum Target {
NOT_THMMY, UNKNOWN_THMMY, TOPIC, BOARD, UNREAD_POSTS, PROFILE_SUMMARY, /**
PROFILE_LATEST_POSTS, PROFILE_STATS, PROFILE * Link doesn't point to thmmy.
*/
NOT_THMMY,
/**
* Link points to thmmy.
*/
THMMY,
/**
* Link points to a thmmy page that's not (yet) supported by the app.
*/
UNKNOWN_THMMY,
/**
* Link points to a topic.
*/
TOPIC,
/**
* Link points to a board.
*/
BOARD,
/**
* Link points to user's unread posts.
*/
UNREAD_POSTS,
/**
* Link points to a profile's summary.
*/
PROFILE_SUMMARY,
/**
* Link points to a profile's latest posts.
*/
PROFILE_LATEST_POSTS,
/**
* Link points to a profile's stats.
*/
PROFILE_STATS,
/**
* Link points to a profile.
*/
PROFILE;
/**
* This method defines a custom equality check for {@link Target} enums. It does not check
* whether a url is equal to another.
* <p>Method returns true if parameter's Target is the same as the object and in the specific
* cases described below, false otherwise.</p><ul>
* <li>(Everything but {@link #NOT_THMMY}).is({@link #THMMY}) returns true</li>
* <li>{@link #PROFILE_SUMMARY}.is({@link #PROFILE}) returns true</li>
* <li>{@link #PROFILE_LATEST_POSTS}.is({@link #PROFILE}) returns true</li>
* <li>{@link #PROFILE_STATS}.is({@link #PROFILE}) returns true</li>
* <li>{@link #PROFILE}.is({@link #PROFILE_SUMMARY}) returns false</li>
* <li>{@link #PROFILE}.is({@link #PROFILE_LATEST_POSTS}) returns false</li>
* <li>{@link #PROFILE}.is({@link #PROFILE_STATS}) returns false</li></ul>
*
* @param other another Target
* @return true if <b>enums</b> are equal, false otherwise
*/
public boolean is(Target other) {
return (this == PROFILE_LATEST_POSTS ||
this == PROFILE_STATS ||
this == PROFILE_SUMMARY) && other == PROFILE
|| (this != NOT_THMMY && other == THMMY)
|| this == other;
}
} }
/**
* Simple method the checks whether a url's target is thmmy or not.
*
* @param uri url to check
* @return true if url is pointing to thmmy, false otherwise
*/
public static boolean isThmmy(Uri uri) { public static boolean isThmmy(Uri uri) {
return resolveLinkTarget(uri) != Target.NOT_THMMY; return resolveLinkTarget(uri) != Target.NOT_THMMY;
} }
/**
* This method is used to determine a url's target.
*
* @param uri url to resolve
* @return resolved target
*/
public static Target resolveLinkTarget(Uri uri) { public static Target resolveLinkTarget(Uri uri) {
final String host = uri.getHost(); final String host = uri.getHost();
final String uriString = uri.toString(); final String uriString = uri.toString();
//Checks if app can handle this url
if (Objects.equals(host, "www.thmmy.gr")) { if (Objects.equals(host, "www.thmmy.gr")) {
if (uriString.contains("topic=")) return Target.TOPIC; if (uriString.contains("topic=")) return Target.TOPIC;
else if (uriString.contains("board=")) return Target.BOARD; else if (uriString.contains("board=")) return Target.BOARD;
@ -39,12 +136,4 @@ public class LinkTarget {
} }
return Target.NOT_THMMY; return Target.NOT_THMMY;
} }
public static boolean targetEqual(Target first, Target second) {
return first == Target.PROFILE &&
(second == Target.PROFILE_LATEST_POSTS ||
second == Target.PROFILE_STATS ||
second == Target.PROFILE_SUMMARY)
|| first == second;
}
} }

208
app/src/main/java/gr/thmmy/mthmmy/model/Post.java

@ -1,9 +1,22 @@
package gr.thmmy.mthmmy.model; package gr.thmmy.mthmmy.model;
import android.support.annotation.Nullable;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Objects;
import gr.thmmy.mthmmy.utils.FileManager.ThmmyFile; import gr.thmmy.mthmmy.utils.FileManager.ThmmyFile;
/**
* Class that defines a topic's post. All member variables are declared final (thus no setters are
* supplied). Class has two constructors and getter methods for all variables.
* <p>A post is described by its author's thumbnail image url, author's username, its subject, its
* content, its index on the forum, its (index) number on the topic, its date of post, author's
* user color and a list of its attached files <b>when post's author is a deleted user</b>.</p>
* <p>When the author is an active user, post also needs author's profile url, rank and special rank,
* gender, number of posts, personal text and number of start to be described <b>in addition to
* previous fields</b>.</p>
*/
public class Post { public class Post {
//Standard info (exists in every post) //Standard info (exists in every post)
private final String thumbnailUrl; private final String thumbnailUrl;
@ -11,27 +24,72 @@ public class Post {
private final String subject; private final String subject;
private final String content; private final String content;
private final int postIndex; private final int postIndex;
//Extra info
private final String profileURL;
private final int postNumber; private final int postNumber;
private final String postDate; private final String postDate;
private final boolean isDeleted; private final boolean isDeleted;
private final int userColor;
private final ArrayList<ThmmyFile> attachedFiles;
//Extra info
private final String profileURL;
private final String rank; private final String rank;
private final String specialRank; private final String specialRank;
private final String gender; private final String gender;
private final String numberOfPosts; private final String numberOfPosts;
private final String personalText; private final String personalText;
private final int numberOfStars; private final int numberOfStars;
private final int userColor;
private final ArrayList<ThmmyFile> attachedFiles;
public Post(String thumbnailUrl, String author, String subject, String content // Suppresses default constructor
, int postIndex, int postNumber, String postDate, String profileURl, String rank @SuppressWarnings("unused")
, String special_rank, String gender, String numberOfPosts private Post() {
, String personalText, int numberOfStars, int userColor thumbnailUrl = "";
, ArrayList<ThmmyFile> attachedFiles) { author = null;
this.thumbnailUrl = thumbnailUrl; subject = null;
content = null;
postIndex = -1;
postNumber = -1;
postDate = null;
isDeleted = true;
profileURL = null;
userColor = -1;
rank = "Rank";
specialRank = "Special rank";
gender = "Gender";
numberOfPosts = "Posts: 0";
personalText = "";
numberOfStars = 0;
attachedFiles = null;
}
/**
* Constructor for active user's posts. All variables are declared final, once assigned they
* can not change. Parameters notated as {@link Nullable} can either pass null or empty
* (strings/ArrayList).
*
* @param thumbnailUrl author's thumbnail url
* @param author author's username
* @param subject post's subject
* @param content post itself
* @param postIndex post's index on the forum
* @param postNumber posts index number on this topic
* @param postDate date of submission
* @param profileURl author's profile url
* @param rank author's rank
* @param special_rank author's special rank
* @param gender author's gender
* @param numberOfPosts author's number of posts
* @param personalText author's personal text
* @param numberOfStars author's number of stars
* @param userColor author's user color
* @param attachedFiles post's attached files
*/
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<ThmmyFile> attachedFiles) {
if (Objects.equals(thumbnailUrl, "")) this.thumbnailUrl = null;
else this.thumbnailUrl = thumbnailUrl;
this.author = author; this.author = author;
this.subject = subject; this.subject = subject;
this.content = content; this.content = content;
@ -39,6 +97,8 @@ public class Post {
this.postNumber = postNumber; this.postNumber = postNumber;
this.postDate = postDate; this.postDate = postDate;
this.isDeleted = false; this.isDeleted = false;
this.userColor = userColor;
this.attachedFiles = attachedFiles;
this.profileURL = profileURl; this.profileURL = profileURl;
this.rank = rank; this.rank = rank;
this.specialRank = special_rank; this.specialRank = special_rank;
@ -46,14 +106,28 @@ public class Post {
this.numberOfPosts = numberOfPosts; this.numberOfPosts = numberOfPosts;
this.personalText = personalText; this.personalText = personalText;
this.numberOfStars = numberOfStars; this.numberOfStars = numberOfStars;
this.userColor = userColor;
this.attachedFiles = attachedFiles;
} }
public Post(String thumbnailUrl, String author, String subject, String content /**
* Constructor for deleted user's posts. All variables are declared final, once assigned they
* can not change. Parameters notated as {@link Nullable} can either pass null or empty
* (strings/ArrayList).
*
* @param thumbnailUrl author's thumbnail url
* @param author author's username
* @param subject post's subject
* @param content post itself
* @param postIndex post's index on the forum
* @param postNumber posts index number on this topic
* @param postDate date of submission
* @param userColor author's user color
* @param attachedFiles post's attached files
*/
public Post(@Nullable String thumbnailUrl, String author, String subject, String content
, int postIndex, int postNumber, String postDate, int userColor , int postIndex, int postNumber, String postDate, int userColor
, ArrayList<ThmmyFile> attachedFiles) { , @Nullable ArrayList<ThmmyFile> attachedFiles) {
this.thumbnailUrl = thumbnailUrl; if (Objects.equals(thumbnailUrl, "")) this.thumbnailUrl = null;
else this.thumbnailUrl = thumbnailUrl;
this.author = author; this.author = author;
this.subject = subject; this.subject = subject;
this.content = content; this.content = content;
@ -61,82 +135,180 @@ public class Post {
this.postNumber = postNumber; this.postNumber = postNumber;
this.postDate = postDate; this.postDate = postDate;
this.isDeleted = true; this.isDeleted = true;
profileURL = null;
this.userColor = userColor; this.userColor = userColor;
this.attachedFiles = attachedFiles;
profileURL = null;
rank = "Rank"; rank = "Rank";
specialRank = "Special rank"; specialRank = "Special rank";
gender = "Gender"; gender = "Gender";
numberOfPosts = "Posts: 0"; numberOfPosts = "Posts: 0";
personalText = ""; personalText = "";
numberOfStars = 0; numberOfStars = 0;
this.attachedFiles = attachedFiles;
} }
//Getters //Getters
/**
* Gets this post author's thumbnail url.
*
* @return author's thumbnail url
*/
@Nullable
public String getThumbnailUrl() { public String getThumbnailUrl() {
return thumbnailUrl; return thumbnailUrl;
} }
/**
* Gets this post
*
* @return post's content
*/
@Nullable
public String getContent() { public String getContent() {
return content; return content;
} }
/**
* Gets this post's author.
*
* @return post's author
*/
@Nullable
public String getAuthor() { public String getAuthor() {
return author; return author;
} }
/**
* Gets this post's subject.
*
* @return post's subject
*/
@Nullable
public String getSubject() { public String getSubject() {
return subject; return subject;
} }
/**
* Gets this post's date of submission.
*
* @return post's date
*/
@Nullable
public String getPostDate() { public String getPostDate() {
return postDate; return postDate;
} }
/**
* Gets post's index number on this topic.
*
* @return post's number on topic
*/
public int getPostNumber() { public int getPostNumber() {
return postNumber; return postNumber;
} }
/**
* Gets this post's index on the forum.
*
* @return post's index on the forum
*/
public int getPostIndex() { public int getPostIndex() {
return postIndex; return postIndex;
} }
/**
* Is true if post's author is a deleted user, false otherwise.
*
* @return true is author is deleted, false otherwise
*/
public boolean isDeleted() { public boolean isDeleted() {
return isDeleted; return isDeleted;
} }
/**
* Gets this post's author profile url.
*
* @return author's profile url
*/
@Nullable
public String getProfileURL() { public String getProfileURL() {
return profileURL; return profileURL;
} }
/**
* Gets this post's author rank.
*
* @return author's rank
*/
@Nullable
public String getRank() { public String getRank() {
return rank; return rank;
} }
/**
* Gets this post's author special rank.
*
* @return author's special rank
*/
@Nullable
public String getSpecialRank() { public String getSpecialRank() {
return specialRank; return specialRank;
} }
/**
* Gets this post's author gender.
*
* @return author's gender
*/
@Nullable
public String getGender() { public String getGender() {
return gender; return gender;
} }
/**
* Gets this post's author number of posts.
*
* @return author's number of posts
*/
@Nullable
public String getNumberOfPosts() { public String getNumberOfPosts() {
return numberOfPosts; return numberOfPosts;
} }
/**
* Gets this post's author personal text.
*
* @return author's personal text
*/
@Nullable
public String getPersonalText() { public String getPersonalText() {
return personalText; return personalText;
} }
/**
* Gets this post's author number of stars.
*
* @return author's number of stars
*/
public int getNumberOfStars() { public int getNumberOfStars() {
return numberOfStars; return numberOfStars;
} }
/**
* Gets this post's author user color.
*
* @return author's user color
*/
public int getUserColor() { public int getUserColor() {
return userColor; return userColor;
} }
/**
* Gets this post's attached files.
*
* @return attached files
*/
@Nullable
public ArrayList<ThmmyFile> getAttachedFiles() { public ArrayList<ThmmyFile> getAttachedFiles() {
return attachedFiles; return attachedFiles;
} }

65
app/src/main/java/gr/thmmy/mthmmy/model/PostSummary.java

@ -1,30 +1,75 @@
package gr.thmmy.mthmmy.model; package gr.thmmy.mthmmy.model;
/**
* Class that defines the summary of a post. All member variables are declared final (thus no
* setters are supplied). Class has one constructor and getter methods for all variables.
* <p>A post summary is described by its url, subject, date and time of post and its content</b>.
*/
public class PostSummary { public class PostSummary {
private final String topicUrl; private final String postUrl;
private final String title; private final String subject;
private final String dateTime; private final String dateTime;
private final String post; private final String post;
public PostSummary(String topicUrl, String title, String dateTime, // Suppresses default constructor
@SuppressWarnings("unused")
private PostSummary() {
this.postUrl = null;
this.subject = null;
this.dateTime = null;
this.post = null;
}
/**
* Constructor specifying all class variables necessary to summarise this post. All variables
* are declared final, once assigned they can not change.
*
* @param postUrl this post's url
* @param subject this post's subject
* @param dateTime this post's date and time of submission
* @param post this post's content
*/
public PostSummary(String postUrl, String subject, String dateTime,
String post) { String post) {
this.topicUrl = topicUrl; this.postUrl = postUrl;
this.title = title; this.subject = subject;
this.dateTime = dateTime; this.dateTime = dateTime;
this.post = post; this.post = post;
} }
public String getTopicUrl() { /**
return topicUrl; * Gets this post's url.
*
* @return post's url
*/
public String getPostUrl() {
return postUrl;
} }
public String getTitle() { /**
return title; * Gets this post's subject.
*
* @return post's subject
*/
public String getSubject() {
return subject;
} }
/**
* Gets this post's date and time of submission.
*
* @return post's date and time
*/
public String getDateTime() { public String getDateTime() {
return dateTime; return dateTime;
} }
public String getPost(){ return post;} /**
* Gets this post's content.
*
* @return post's content
*/
public String getPost() {
return post;
}
} }

72
app/src/main/java/gr/thmmy/mthmmy/model/Topic.java

@ -1,9 +1,39 @@
package gr.thmmy.mthmmy.model; package gr.thmmy.mthmmy.model;
/**
* Class that defines a topic. All member variables are declared final (thus no setters are supplied).
* Class has one constructor and getter methods for all variables.
* <p>A topic is described by its url, subject, username of creator, its date and time of this
* topic's last post, url of this topic's last post, its view and reply stats, whether it's locked or
* not and whether it's sticky or not.</b>.
*/
public class Topic extends TopicSummary { public class Topic extends TopicSummary {
private final String lastPostUrl, stats; private final String lastPostUrl, stats;
private final boolean locked, sticky; private final boolean locked, sticky;
// Suppresses default constructor
@SuppressWarnings("unused")
private Topic() {
super();
this.lastPostUrl = null;
this.stats = null;
this.locked = false;
this.sticky = false;
}
/**
* Constructor specifying all class variables necessary to describe this topic. All variables
* are declared final, once assigned they can not change.
*
* @param topicUrl this topic's url
* @param subject this topic's subject
* @param starter this topic starter's username
* @param lastPost username of topic's last post's author
* @param lastPostUrl url of topic's last post
* @param stats this topic's view and reply stats
* @param locked whether this topic is locked or not
* @param sticky whether this topic is sticky or not
*/
public Topic(String topicUrl, String subject, String starter, String lastPost, String lastPostUrl, public Topic(String topicUrl, String subject, String starter, String lastPost, String lastPostUrl,
String stats, boolean locked, boolean sticky) { String stats, boolean locked, boolean sticky) {
super(topicUrl, subject, starter, lastPost); super(topicUrl, subject, starter, lastPost);
@ -13,34 +43,74 @@ public class Topic extends TopicSummary {
this.sticky = sticky; this.sticky = sticky;
} }
/**
* Gets this topic's url.
*
* @return this topic's url
*/
public String getUrl() { public String getUrl() {
return topicUrl; return topicUrl;
} }
/**
* Gets this topic's subject.
*
* @return this topic's subject
*/
public String getSubject() { public String getSubject() {
return subject; return subject;
} }
/**
* Gets this topic's starter username.
*
* @return this topic's starter username
*/
public String getStarter() { public String getStarter() {
return lastUser; return lastUser;
} }
public String getLastPost() { /**
* Gets this topic's last post's date and time.
*
* @return last post's date and time
*/
public String getLastPostDateAndTime() {
return dateTimeModified; return dateTimeModified;
} }
/**
* Gets this topic's last post's url.
*
* @return last post's url
*/
public String getLastPostUrl() { public String getLastPostUrl() {
return lastPostUrl; return lastPostUrl;
} }
/**
* Gets this topic's view and reply stats.
*
* @return this topic's view and reply stats
*/
public String getStats() { public String getStats() {
return stats; return stats;
} }
/**
* Gets this topic's lock status. True if topic is locked, false otherwise.
*
* @return this topic's lock status
*/
public boolean isLocked() { public boolean isLocked() {
return locked; return locked;
} }
/**
* Gets this topic's sticky status. True if topic is locked, false otherwise.
*
* @return this topic's sticky status
*/
public boolean isSticky() { public boolean isSticky() {
return sticky; return sticky;
} }

44
app/src/main/java/gr/thmmy/mthmmy/model/TopicSummary.java

@ -1,11 +1,35 @@
package gr.thmmy.mthmmy.model; package gr.thmmy.mthmmy.model;
/**
* Class that defines the summary of a topic. All member variables are declared final (thus no
* setters are supplied). Class has one constructor and getter methods for all variables.
* <p>A topic summary is described by its url, subject, username of its last author and its date and
* time of this topic's last post.</b>.
*/
public class TopicSummary { public class TopicSummary {
final String topicUrl; final String topicUrl;
final String subject; final String subject;
final String lastUser; final String lastUser;
final String dateTimeModified; final String dateTimeModified;
// Suppresses default constructor
@SuppressWarnings("unused")
TopicSummary() {
this.topicUrl = null;
this.subject = null;
this.lastUser = null;
this.dateTimeModified = null;
}
/**
* Constructor specifying all class variables necessary to summarise this topic. All variables
* are declared final, once assigned they can not change.
*
* @param topicUrl this topic's url
* @param subject this topic's subject
* @param lastUser username of this topic's last author
* @param dateTimeModified this topic's date and time of last post
*/
public TopicSummary(String topicUrl, String subject, String lastUser, String dateTimeModified) { public TopicSummary(String topicUrl, String subject, String lastUser, String dateTimeModified) {
this.topicUrl = topicUrl; this.topicUrl = topicUrl;
this.subject = subject; this.subject = subject;
@ -13,18 +37,38 @@ public class TopicSummary {
this.dateTimeModified = dateTimeModified; this.dateTimeModified = dateTimeModified;
} }
/**
* Gets this topic's url.
*
* @return this topic's url
*/
public String getTopicUrl() { public String getTopicUrl() {
return topicUrl; return topicUrl;
} }
/**
* Gets this topic's subject.
*
* @return this topic's subject
*/
public String getSubject() { public String getSubject() {
return subject; return subject;
} }
/**
* Gets username of this topic's last author.
*
* @return username of last author
*/
public String getLastUser() { public String getLastUser() {
return lastUser; return lastUser;
} }
/**
* Gets this topic's date and time of last post.
*
* @return this topic's date and time of last post
*/
public String getDateTimeModified() { public String getDateTimeModified() {
return dateTimeModified; return dateTimeModified;
} }

96
app/src/main/java/gr/thmmy/mthmmy/utils/ParseHelpers.java

@ -6,42 +6,112 @@ import org.jsoup.select.Elements;
import java.util.ArrayList; import java.util.ArrayList;
/**
* This class consists exclusively of static classes (enums) and methods (excluding methods of inner
* classes). It can be used to resolve a page's language and state or fix embedded videos html code.
*/
public class ParseHelpers { public class ParseHelpers {
/**
* Debug Tag for logging debug output to LogCat
*/
@SuppressWarnings("unused")
private static final String TAG = "ParseHelpers"; private static final String TAG = "ParseHelpers";
/**
* An enum describing a forum page's language by defining the types:<ul>
* <li>{@link #PAGE_INCOMPLETE}</li>
* <li>{@link #UNDEFINED_LANGUAGE}</li>
* <li>{@link #ENGLISH}</li>
* <li>{@link #ENGLISH_GUEST}</li>
* <li>{@link #GREEK}</li>
* </ul>
*/
public enum Language { public enum Language {
GREEK, ENGLISH, ENGLISH_GUEST, PAGE_INCOMPLETE, UNDEFINED_LANGUAGE; /**
* Page language is greek.
*/
GREEK,
/**
* Page language is english.
*/
ENGLISH,
/**
* Page language is english and the user is guest.
*/
ENGLISH_GUEST,
/**
* Page is incomplete. Data are not enough to determine the language.
*/
PAGE_INCOMPLETE,
/**
* Page language is not (yet) supported.
*/
UNDEFINED_LANGUAGE;
/** /**
* Returns one of the supported forum languages. * Returns one of the supported forum languages.
* <p>Forum supports: <ul><li>{@link #ENGLISH}</li>
* <li>{@link #GREEK}</li></ul></p>
* *
* @param page {@link Document} object containing this page's source code * @param page {@link Document} object containing this page's source code
* @return String containing the language of a topic * @return language of this page
* @see org.jsoup.Jsoup Jsoup * @see org.jsoup.Jsoup Jsoup
*/ */
public static Language getLanguage(Document page) { public static Language getLanguage(Document page) {
Element welcoming = page.select("h3").first(); Element welcoming = page.select("h3").first();
if (welcoming == null) { if (welcoming == null) {
if (page.select("div[id=myuser]").first().text().contains("Welcome")) Element welcomingGuest = page.select("div[id=myuser]").first();
return ENGLISH_GUEST; if (welcomingGuest != null) {
if (welcomingGuest.text().contains("Welcome")) return ENGLISH_GUEST;
}
return PAGE_INCOMPLETE; return PAGE_INCOMPLETE;
} else if (welcoming.text().contains("Καλώς ορίσατε")) return GREEK; } else if (welcoming.text().contains("Καλώς ορίσατε")) return GREEK;
else if (welcoming.text().contains("Hey")) return ENGLISH; else if (welcoming.text().contains("Hey")) return ENGLISH;
else return UNDEFINED_LANGUAGE; else return UNDEFINED_LANGUAGE;
} }
/**
* This method defines a custom equality check for {@link Language} enums.
* <p>Method returns true if parameter's Target is the same as the object and in the specific
* cases described below, false otherwise.</p><ul>
* <li>{@link #ENGLISH}.is({@link #ENGLISH_GUEST}) returns true</li>
* <li>{@link #ENGLISH_GUEST}.is({@link #ENGLISH}) returns true</li>
*
* @param other another Language
* @return true if <b>enums</b> are equal, false otherwise
*/
public boolean is(Language other) { public boolean is(Language other) {
return this == ENGLISH && other == ENGLISH_GUEST || return this == ENGLISH && other == ENGLISH_GUEST
this == ENGLISH_GUEST && other == ENGLISH || || this == ENGLISH_GUEST && other == ENGLISH
this == other; || this == other;
} }
} }
/**
* An enum describing the state of a forum page by defining the types:<ul>
* <li>{@link #UNAUTHORIZED_OR_MISSING}</li>
* <li>{@link #NEW_PM}</li>
* <li>{@link #READY}</li>
* </ul>
*/
public enum State { public enum State {
UNAUTHORIZED_OR_MISSING, NEW_PM, READY; /**
* This page is either missing or is off limits.
*/
UNAUTHORIZED_OR_MISSING,
/**
* The page has a popup window from a new personal message.
*/
NEW_PM,
/**
* The page is ready for use.
*/
READY;
/**
* This method checks the state of a page.
*
* @param page a {@link Document} containing this page's source code
* @return page's State
*/
public static State getState(Document page) { public static State getState(Document page) {
Elements warnings = page.select("form[id=frmLogin] tr.catbg~tr>td.windowbg"); Elements warnings = page.select("form[id=frmLogin] tr.catbg~tr>td.windowbg");
if (warnings != null) { if (warnings != null) {
@ -55,6 +125,12 @@ public class ParseHelpers {
} }
} }
/**
* This method fixes html so that embedded videos will render properly and be lightweight.
*
* @param html an {@link Element} containing the (outer) html to be fixed
* @return fixed html String
*/
public static String youtubeEmbeddedFix(Element html) { public static String youtubeEmbeddedFix(Element html) {
//Fixes embedded videos //Fixes embedded videos
Elements noembedTag = html.select("noembed"); Elements noembedTag = html.select("noembed");

Loading…
Cancel
Save