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 16d8d25b..306302fe 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 @@ -101,6 +101,12 @@ class BoardAdapter extends RecyclerView.Adapter { , LinearLayout.LayoutParams.WRAP_CONTENT)); topicTitle.setText(context.getString(R.string.topic_title)); 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.setTextSize(20f); @@ -236,7 +242,7 @@ class BoardAdapter extends RecyclerView.Adapter { topicViewHolder.topicSubject.setText(lockedSticky); topicViewHolder.topicStartedBy.setText(context.getString(R.string.topic_started_by, topic.getStarter())); 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() { @Override public void onClick(View view) { 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 c68befd8..59bb69d0 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 @@ -174,8 +174,8 @@ public class ProfileActivity extends BaseActivity implements LatestPostsFragment @Override public void onLatestPostsFragmentInteraction(PostSummary postSummary) { Intent i = new Intent(ProfileActivity.this, TopicActivity.class); - i.putExtra(BUNDLE_TOPIC_URL, postSummary.getTopicUrl()); - i.putExtra(BUNDLE_TOPIC_TITLE, postSummary.getTitle().substring(postSummary.getTitle(). + i.putExtra(BUNDLE_TOPIC_URL, postSummary.getPostUrl()); + i.putExtra(BUNDLE_TOPIC_TITLE, postSummary.getSubject().substring(postSummary.getSubject(). lastIndexOf("/ ") + 2)); startActivity(i); } 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 9709acfb..7976dd13 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 @@ -66,7 +66,7 @@ class LatestPostsAdapter extends RecyclerView.Adapter { PostSummary topic = parsedTopicSummaries.get(position); final LatestPostViewHolder latestPostViewHolder = (LatestPostViewHolder) holder; - latestPostViewHolder.postTitle.setText(topic.getTitle()); + latestPostViewHolder.postTitle.setText(topic.getSubject()); latestPostViewHolder.postDate.setText(topic.getDateTime()); latestPostViewHolder.post.loadDataWithBaseURL("file:///android_asset/" , topic.getPost(), "text/html", "UTF-8", null); 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 0a2d1e66..3d27e284 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 @@ -385,7 +385,7 @@ public class TopicActivity extends BaseActivity { switch (parseResult) { case SUCCESS: progressBar.setVisibility(ProgressBar.INVISIBLE); - topicAdapter.customNotifyDataSetChanged(); + topicAdapter.customNotifyDataSetChanged(new TopicTask()); replyFAB.setEnabled(true); //Set current page 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 dae50a99..2ec6a4c1 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 @@ -96,7 +96,7 @@ class TopicAdapter extends RecyclerView.Adapter { private static final int isQuoteButtonChecked = 2; private final MaterialProgressBar progressBar; private DownloadTask downloadTask; - private final TopicActivity.TopicTask topicTask; + private TopicActivity.TopicTask topicTask; /** * Custom {@link RecyclerView.ViewHolder} implementation @@ -223,7 +223,7 @@ 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().size() != 0) { + if (currentPost.getAttachedFiles() != null && currentPost.getAttachedFiles().size() != 0) { holder.bodyFooterDivider.setVisibility(View.VISIBLE); int filesTextColor; if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) { @@ -286,7 +286,7 @@ class TopicAdapter extends RecyclerView.Adapter { holder.personalText.setVisibility(View.VISIBLE); } else holder.personalText.setVisibility(View.GONE); - if (mNumberOfStars != 0) { + if (mNumberOfStars > 0) { holder.stars.setTypeface(Typeface.createFromAsset(context.getAssets() , "fonts/fontawesome-webfont.ttf")); @@ -300,6 +300,7 @@ class TopicAdapter extends RecyclerView.Adapter { 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(). @@ -425,7 +426,8 @@ class TopicAdapter extends RecyclerView.Adapter { holder.post.setOnTouchListener(new CustomTouchListener(holder.post, holder.cardView)); } - void customNotifyDataSetChanged() { + void customNotifyDataSetChanged(TopicActivity.TopicTask topicTask) { + this.topicTask = topicTask; viewProperties.clear(); for (int i = 0; i < postsList.size(); ++i) { //Initializes properties, array's values will be false by default @@ -529,7 +531,7 @@ class TopicAdapter extends RecyclerView.Adapter { final String uriString = uri.toString(); 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 //Checks if this is the current topic if (Objects.equals(uriString.substring(0, uriString.lastIndexOf(".")), base_url)) { @@ -551,7 +553,8 @@ class TopicAdapter extends RecyclerView.Adapter { } } 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); Bundle extras = new Bundle(); extras.putString(BUNDLE_BOARD_URL, uriString); @@ -559,7 +562,8 @@ class TopicAdapter extends RecyclerView.Adapter { intent.putExtras(extras); intent.setFlags(FLAG_ACTIVITY_NEW_TASK); 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); Bundle extras = new Bundle(); extras.putString(BUNDLE_PROFILE_URL, uriString); @@ -568,6 +572,7 @@ class TopicAdapter extends RecyclerView.Adapter { intent.putExtras(extras); intent.setFlags(FLAG_ACTIVITY_NEW_TASK); context.startActivity(intent); + return true; } Intent intent = new Intent(Intent.ACTION_VIEW, uri); diff --git a/app/src/main/java/gr/thmmy/mthmmy/model/Board.java b/app/src/main/java/gr/thmmy/mthmmy/model/Board.java index 4934e759..cd45bdf8 100644 --- a/app/src/main/java/gr/thmmy/mthmmy/model/Board.java +++ b/app/src/main/java/gr/thmmy/mthmmy/model/Board.java @@ -1,8 +1,36 @@ 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. + *

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.

+ */ public class Board { 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) { this.url = url; this.title = title; @@ -12,26 +40,56 @@ public class Board { this.lastPostUrl = lastPostUrl; } + /** + * Gets this board's url. + * + * @return this board's url + */ public String getUrl() { return url; } + /** + * Gets this board's title. + * + * @return this board's title + */ public String getTitle() { return title; } + /** + * Gets this board's assigned moderators. + * + * @return this board's moderators + */ public String getMods() { return mods; } + /** + * Gets this board's view and reply stats. + * + * @return this board's stats + */ public String getStats() { return stats; } + /** + * Gets this board's latest post's info. + * + * @return latest post's info + */ public String getLastPost() { return lastPost; } + /** + * Gets this board's latest post's url. + * + * @return latest post's url + */ public String getLastPostUrl() { return lastPostUrl; } diff --git a/app/src/main/java/gr/thmmy/mthmmy/model/LinkTarget.java b/app/src/main/java/gr/thmmy/mthmmy/model/LinkTarget.java index ea283781..aaf14773 100644 --- a/app/src/main/java/gr/thmmy/mthmmy/model/LinkTarget.java +++ b/app/src/main/java/gr/thmmy/mthmmy/model/LinkTarget.java @@ -1,28 +1,125 @@ package gr.thmmy.mthmmy.model; import android.net.Uri; +import android.support.annotation.NonNull; import java.util.Objects; 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 { + /** + * Debug Tag for logging debug output to LogCat + */ + @SuppressWarnings("unused") private static final String TAG = "LinkTarget"; + /** + * An enum describing a link's target by defining the types:
    + *
  • {@link #NOT_THMMY}
  • + *
  • {@link #THMMY}
  • + *
  • {@link #UNKNOWN_THMMY}
  • + *
  • {@link #TOPIC}
  • + *
  • {@link #BOARD}
  • + *
  • {@link #UNREAD_POSTS}
  • + *
  • {@link #PROFILE_SUMMARY}
  • + *
  • {@link #PROFILE_LATEST_POSTS}
  • + *
  • {@link #PROFILE_STATS}
  • + *
  • {@link #PROFILE}
  • + *
+ */ 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. + *

Method returns true if parameter's Target is the same as the object and in the specific + * cases described below, false otherwise.

    + *
  • (Everything but {@link #NOT_THMMY}).is({@link #THMMY}) returns true
  • + *
  • {@link #PROFILE_SUMMARY}.is({@link #PROFILE}) returns true
  • + *
  • {@link #PROFILE_LATEST_POSTS}.is({@link #PROFILE}) returns true
  • + *
  • {@link #PROFILE_STATS}.is({@link #PROFILE}) returns true
  • + *
  • {@link #PROFILE}.is({@link #PROFILE_SUMMARY}) returns false
  • + *
  • {@link #PROFILE}.is({@link #PROFILE_LATEST_POSTS}) returns false
  • + *
  • {@link #PROFILE}.is({@link #PROFILE_STATS}) returns false
+ * + * @param other another Target + * @return true if enums 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) { 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) { final String host = uri.getHost(); final String uriString = uri.toString(); - //Checks if app can handle this url if (Objects.equals(host, "www.thmmy.gr")) { if (uriString.contains("topic=")) return Target.TOPIC; else if (uriString.contains("board=")) return Target.BOARD; @@ -39,12 +136,4 @@ public class LinkTarget { } 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; - } } 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 454ee890..96c5a04e 100644 --- a/app/src/main/java/gr/thmmy/mthmmy/model/Post.java +++ b/app/src/main/java/gr/thmmy/mthmmy/model/Post.java @@ -1,9 +1,22 @@ package gr.thmmy.mthmmy.model; +import android.support.annotation.Nullable; + import java.util.ArrayList; +import java.util.Objects; 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. + *

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 when post's author is a deleted user.

+ *

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 in addition to + * previous fields.

+ */ public class Post { //Standard info (exists in every post) private final String thumbnailUrl; @@ -11,27 +24,72 @@ public class Post { private final String subject; private final String content; private final int postIndex; - - //Extra info - private final String profileURL; private final int postNumber; private final String postDate; private final boolean isDeleted; + private final int userColor; + private final ArrayList attachedFiles; + + //Extra info + private final String profileURL; private final String rank; private final String specialRank; private final String gender; private final String numberOfPosts; private final String personalText; private final int numberOfStars; - private final int userColor; - private final ArrayList attachedFiles; - public Post(String thumbnailUrl, String author, String subject, String content - , int postIndex, int postNumber, String postDate, String profileURl, String rank - , String special_rank, String gender, String numberOfPosts - , String personalText, int numberOfStars, int userColor - , ArrayList attachedFiles) { - this.thumbnailUrl = thumbnailUrl; + // Suppresses default constructor + @SuppressWarnings("unused") + private Post() { + thumbnailUrl = ""; + author = null; + 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 attachedFiles) { + if (Objects.equals(thumbnailUrl, "")) this.thumbnailUrl = null; + else this.thumbnailUrl = thumbnailUrl; this.author = author; this.subject = subject; this.content = content; @@ -39,6 +97,8 @@ public class Post { this.postNumber = postNumber; this.postDate = postDate; this.isDeleted = false; + this.userColor = userColor; + this.attachedFiles = attachedFiles; this.profileURL = profileURl; this.rank = rank; this.specialRank = special_rank; @@ -46,14 +106,28 @@ public class Post { this.numberOfPosts = numberOfPosts; this.personalText = personalText; 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 - , ArrayList attachedFiles) { - this.thumbnailUrl = thumbnailUrl; + , @Nullable ArrayList attachedFiles) { + if (Objects.equals(thumbnailUrl, "")) this.thumbnailUrl = null; + else this.thumbnailUrl = thumbnailUrl; this.author = author; this.subject = subject; this.content = content; @@ -61,82 +135,180 @@ public class Post { this.postNumber = postNumber; this.postDate = postDate; this.isDeleted = true; - profileURL = null; this.userColor = userColor; + this.attachedFiles = attachedFiles; + profileURL = null; rank = "Rank"; specialRank = "Special rank"; gender = "Gender"; numberOfPosts = "Posts: 0"; personalText = ""; numberOfStars = 0; - this.attachedFiles = attachedFiles; } //Getters + + /** + * Gets this post author's thumbnail url. + * + * @return author's thumbnail url + */ + @Nullable public String getThumbnailUrl() { return thumbnailUrl; } + /** + * Gets this post + * + * @return post's content + */ + @Nullable public String getContent() { return content; } + /** + * Gets this post's author. + * + * @return post's author + */ + @Nullable public String getAuthor() { return author; } + /** + * Gets this post's subject. + * + * @return post's subject + */ + @Nullable public String getSubject() { return subject; } + /** + * Gets this post's date of submission. + * + * @return post's date + */ + @Nullable public String getPostDate() { return postDate; } + /** + * Gets post's index number on this topic. + * + * @return post's number on topic + */ public int getPostNumber() { return postNumber; } + /** + * Gets this post's index on the forum. + * + * @return post's index on the forum + */ public int getPostIndex() { 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() { return isDeleted; } + /** + * Gets this post's author profile url. + * + * @return author's profile url + */ + @Nullable public String getProfileURL() { return profileURL; } + /** + * Gets this post's author rank. + * + * @return author's rank + */ + @Nullable public String getRank() { return rank; } + /** + * Gets this post's author special rank. + * + * @return author's special rank + */ + @Nullable public String getSpecialRank() { return specialRank; } + /** + * Gets this post's author gender. + * + * @return author's gender + */ + @Nullable public String getGender() { return gender; } + /** + * Gets this post's author number of posts. + * + * @return author's number of posts + */ + @Nullable public String getNumberOfPosts() { return numberOfPosts; } + /** + * Gets this post's author personal text. + * + * @return author's personal text + */ + @Nullable public String getPersonalText() { return personalText; } + /** + * Gets this post's author number of stars. + * + * @return author's number of stars + */ public int getNumberOfStars() { return numberOfStars; } + /** + * Gets this post's author user color. + * + * @return author's user color + */ public int getUserColor() { return userColor; } + /** + * Gets this post's attached files. + * + * @return attached files + */ + @Nullable public ArrayList getAttachedFiles() { return attachedFiles; } diff --git a/app/src/main/java/gr/thmmy/mthmmy/model/PostSummary.java b/app/src/main/java/gr/thmmy/mthmmy/model/PostSummary.java index cf27691d..bfefc230 100644 --- a/app/src/main/java/gr/thmmy/mthmmy/model/PostSummary.java +++ b/app/src/main/java/gr/thmmy/mthmmy/model/PostSummary.java @@ -1,30 +1,75 @@ 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. + *

A post summary is described by its url, subject, date and time of post and its content. + */ public class PostSummary { - private final String topicUrl; - private final String title; + private final String postUrl; + private final String subject; private final String dateTime; private final String post; - public PostSummary(String topicUrl, String title, String dateTime, - String post) { - this.topicUrl = topicUrl; - this.title = title; + // 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) { + this.postUrl = postUrl; + this.subject = subject; this.dateTime = dateTime; 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() { return dateTime; } - public String getPost(){ return post;} + /** + * Gets this post's content. + * + * @return post's content + */ + public String getPost() { + return post; + } } diff --git a/app/src/main/java/gr/thmmy/mthmmy/model/Topic.java b/app/src/main/java/gr/thmmy/mthmmy/model/Topic.java index 87e70a2f..27f22c31 100644 --- a/app/src/main/java/gr/thmmy/mthmmy/model/Topic.java +++ b/app/src/main/java/gr/thmmy/mthmmy/model/Topic.java @@ -1,9 +1,39 @@ 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. + *

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.. + */ public class Topic extends TopicSummary { private final String lastPostUrl, stats; 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, String stats, boolean locked, boolean sticky) { super(topicUrl, subject, starter, lastPost); @@ -13,34 +43,74 @@ public class Topic extends TopicSummary { this.sticky = sticky; } + /** + * Gets this topic's url. + * + * @return this topic's url + */ public String getUrl() { return topicUrl; } + /** + * Gets this topic's subject. + * + * @return this topic's subject + */ public String getSubject() { return subject; } + /** + * Gets this topic's starter username. + * + * @return this topic's starter username + */ public String getStarter() { 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; } + /** + * Gets this topic's last post's url. + * + * @return last post's url + */ public String getLastPostUrl() { return lastPostUrl; } + /** + * Gets this topic's view and reply stats. + * + * @return this topic's view and reply stats + */ public String getStats() { return stats; } + /** + * Gets this topic's lock status. True if topic is locked, false otherwise. + * + * @return this topic's lock status + */ public boolean isLocked() { return locked; } + /** + * Gets this topic's sticky status. True if topic is locked, false otherwise. + * + * @return this topic's sticky status + */ public boolean isSticky() { return sticky; } diff --git a/app/src/main/java/gr/thmmy/mthmmy/model/TopicSummary.java b/app/src/main/java/gr/thmmy/mthmmy/model/TopicSummary.java index dc9e4098..87e323c7 100644 --- a/app/src/main/java/gr/thmmy/mthmmy/model/TopicSummary.java +++ b/app/src/main/java/gr/thmmy/mthmmy/model/TopicSummary.java @@ -1,11 +1,35 @@ 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. + *

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.. + */ public class TopicSummary { final String topicUrl; final String subject; final String lastUser; 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) { this.topicUrl = topicUrl; this.subject = subject; @@ -13,18 +37,38 @@ public class TopicSummary { this.dateTimeModified = dateTimeModified; } + /** + * Gets this topic's url. + * + * @return this topic's url + */ public String getTopicUrl() { return topicUrl; } + /** + * Gets this topic's subject. + * + * @return this topic's subject + */ public String getSubject() { return subject; } + /** + * Gets username of this topic's last author. + * + * @return username of last author + */ public String getLastUser() { 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() { return dateTimeModified; } 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 83da1c7c..cb0b772c 100644 --- a/app/src/main/java/gr/thmmy/mthmmy/utils/ParseHelpers.java +++ b/app/src/main/java/gr/thmmy/mthmmy/utils/ParseHelpers.java @@ -6,42 +6,112 @@ import org.jsoup.select.Elements; 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 { + /** + * Debug Tag for logging debug output to LogCat + */ + @SuppressWarnings("unused") private static final String TAG = "ParseHelpers"; + /** + * An enum describing a forum page's language by defining the types:

    + *
  • {@link #PAGE_INCOMPLETE}
  • + *
  • {@link #UNDEFINED_LANGUAGE}
  • + *
  • {@link #ENGLISH}
  • + *
  • {@link #ENGLISH_GUEST}
  • + *
  • {@link #GREEK}
  • + *
+ */ 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. - *

Forum supports:

  • {@link #ENGLISH}
  • - *
  • {@link #GREEK}

* * @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 */ public static Language getLanguage(Document page) { Element welcoming = page.select("h3").first(); if (welcoming == null) { - if (page.select("div[id=myuser]").first().text().contains("Welcome")) - return ENGLISH_GUEST; + Element welcomingGuest = page.select("div[id=myuser]").first(); + if (welcomingGuest != null) { + if (welcomingGuest.text().contains("Welcome")) return ENGLISH_GUEST; + } return PAGE_INCOMPLETE; } else if (welcoming.text().contains("Καλώς ορίσατε")) return GREEK; else if (welcoming.text().contains("Hey")) return ENGLISH; else return UNDEFINED_LANGUAGE; } + /** + * This method defines a custom equality check for {@link Language} enums. + *

Method returns true if parameter's Target is the same as the object and in the specific + * cases described below, false otherwise.

    + *
  • {@link #ENGLISH}.is({@link #ENGLISH_GUEST}) returns true
  • + *
  • {@link #ENGLISH_GUEST}.is({@link #ENGLISH}) returns true
  • + * + * @param other another Language + * @return true if enums are equal, false otherwise + */ public boolean is(Language other) { - return this == ENGLISH && other == ENGLISH_GUEST || - this == ENGLISH_GUEST && other == ENGLISH || - this == other; + return this == ENGLISH && other == ENGLISH_GUEST + || this == ENGLISH_GUEST && other == ENGLISH + || this == other; } } + /** + * An enum describing the state of a forum page by defining the types:
      + *
    • {@link #UNAUTHORIZED_OR_MISSING}
    • + *
    • {@link #NEW_PM}
    • + *
    • {@link #READY}
    • + *
    + */ 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) { Elements warnings = page.select("form[id=frmLogin] tr.catbg~tr>td.windowbg"); 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) { //Fixes embedded videos Elements noembedTag = html.select("noembed");