Browse Source

Version 2.3.0

master v2.3.0
Ezerous 2 months ago
parent
commit
4892bd0e21
  1. 4
      app/build.gradle
  2. 16
      app/gradle/grgit.gradle
  3. 2
      app/src/main/java/gr/thmmy/mthmmy/activities/AboutActivity.java
  4. 6
      app/src/main/java/gr/thmmy/mthmmy/activities/board/BoardActivity.java
  5. 24
      app/src/main/java/gr/thmmy/mthmmy/activities/board/BoardAdapter.java
  6. 14
      app/src/main/java/gr/thmmy/mthmmy/activities/create_content/NewTopicTask.java
  7. 9
      app/src/main/java/gr/thmmy/mthmmy/activities/downloads/DownloadsActivity.java
  8. 36
      app/src/main/java/gr/thmmy/mthmmy/activities/downloads/DownloadsAdapter.java
  9. 7
      app/src/main/java/gr/thmmy/mthmmy/activities/main/MainActivity.java
  10. 2
      app/src/main/java/gr/thmmy/mthmmy/activities/main/forum/ForumFragment.java
  11. 1
      app/src/main/java/gr/thmmy/mthmmy/activities/settings/SettingsActivity.java
  12. 8
      app/src/main/java/gr/thmmy/mthmmy/activities/settings/SettingsFragment.java
  13. 7
      app/src/main/java/gr/thmmy/mthmmy/activities/topic/TopicAdapter.java
  14. 84
      app/src/main/java/gr/thmmy/mthmmy/activities/topic/TopicParser.java
  15. 4
      app/src/main/java/gr/thmmy/mthmmy/base/BaseActivity.java
  16. 7
      app/src/main/java/gr/thmmy/mthmmy/base/BaseApplication.java
  17. 18
      app/src/main/java/gr/thmmy/mthmmy/model/Post.java
  18. 19
      app/src/main/java/gr/thmmy/mthmmy/utils/parsing/ThmmyDateTimeParser.java
  19. 27
      app/src/main/res/layout/activity_topic_post_row.xml
  20. 1
      app/src/main/res/values/colors.xml
  21. 10
      app/src/main/res/values/strings.xml
  22. 6
      app/src/main/res/xml-v26/app_preferences_guest.xml
  23. 6
      app/src/main/res/xml-v26/app_preferences_user.xml
  24. 6
      app/src/main/res/xml/app_preferences_guest.xml
  25. 6
      app/src/main/res/xml/app_preferences_user.xml

4
app/build.gradle

@ -13,8 +13,8 @@ android {
compileSdk 33
minSdkVersion 23
targetSdkVersion 33
versionCode 33
versionName "2.2.1"
versionCode 34
versionName "2.3.0"
archivesBaseName = "mTHMMY-v$versionName"
buildConfigField "String", "CURRENT_BRANCH", "\"" + getCurrentBranch() + "\""
buildConfigField "String", "COMMIT_HASH", "\"" + getCommitHash() + "\""

16
app/gradle/grgit.gradle

@ -10,9 +10,13 @@ buildscript {
}
}
static def getCurrentBranch() {
def getGrgit() {
return Grgit.open(currentDir: project.rootDir)
}
def getCurrentBranch() {
try {
def grgit = Grgit.open()
def grgit = getGrgit()
def currentBranch = grgit.branch.getCurrent().name
grgit.close()
return currentBranch
@ -21,9 +25,9 @@ static def getCurrentBranch() {
}
}
static def getCommitHash() {
def getCommitHash() {
try {
def grgit = Grgit.open()
def grgit = getGrgit()
def commitHash = grgit.head().id
grgit.close()
return commitHash
@ -33,9 +37,9 @@ static def getCommitHash() {
}
//Will return true if there are no uncommitted changes
static def isClean() {
def isClean() {
try {
def grgit = Grgit.open()
def grgit = getGrgit()
def isClean = grgit.status().isClean()
grgit.close()
return isClean

2
app/src/main/java/gr/thmmy/mthmmy/activities/AboutActivity.java

@ -60,7 +60,7 @@ public class AboutActivity extends BaseActivity {
String versionInfo = "";
if (gitExists)
versionInfo = "-" + BuildConfig.CURRENT_BRANCH + "-" + commitHash
+ (BuildConfig.IS_CLEAN ? "" : "-dirty")
+ (BuildConfig.IS_CLEAN ? "" : "~")
+ " "; // Avoid last letter being cut in italics styled TextView
//Initialize appbar

6
app/src/main/java/gr/thmmy/mthmmy/activities/board/BoardActivity.java

@ -219,7 +219,7 @@ public class BoardActivity extends BaseActivity implements BoardAdapter.OnLoadMo
try {
Elements pages = boardPage.select("table.tborder td.catbg[height=30]").first()
.select("a.navPages");
if (pages != null && !pages.isEmpty()) {
if (!pages.isEmpty()) {
for (Element page : pages) {
if (Integer.parseInt(page.text()) > numberOfPages)
numberOfPages = Integer.parseInt(page.text());
@ -240,7 +240,7 @@ public class BoardActivity extends BaseActivity implements BoardAdapter.OnLoadMo
if (pagesLoaded == 0) { //Finds sub boards
Elements subBoardRows = boardPage.select("div.tborder>table>tbody>tr");
if (subBoardRows != null && !subBoardRows.isEmpty()) {
if (!subBoardRows.isEmpty()) {
for (Element subBoardRow : subBoardRows) {
if (!Objects.equals(subBoardRow.className(), "titlebg")) {
String pUrl = "", pTitle = "", pMods = "", pStats = "",
@ -314,7 +314,7 @@ public class BoardActivity extends BaseActivity implements BoardAdapter.OnLoadMo
}
//Finds topics
Elements topicRows = boardPage.select("table.bordercolor>tbody>tr");
if (topicRows != null && !topicRows.isEmpty()) {
if (!topicRows.isEmpty()) {
for (Element topicRow : topicRows) {
if (!Objects.equals(topicRow.className(), "titlebg")) {
String pTopicUrl, pSubject, pStarter, pLastUser = "", pLastPostDateTime = "00:00:00", pLastPost, pLastPostUrl, pStats;

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

@ -16,6 +16,7 @@ import android.widget.ImageButton;
import android.widget.LinearLayout;
import android.widget.TextView;
import androidx.annotation.NonNull;
import androidx.recyclerview.widget.RecyclerView;
import java.util.ArrayList;
@ -63,6 +64,7 @@ class BoardAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> {
return VIEW_TYPE_LOADING;
}
@NonNull
@Override
public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
if (viewType == VIEW_TYPE_SUB_BOARD) {
@ -75,16 +77,16 @@ class BoardAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> {
inflate(R.layout.activity_board_topic_row, parent, false);
return new TopicViewHolder(topic);
}
else if (viewType == VIEW_TYPE_LOADING) {
// viewType == VIEW_TYPE_LOADING
else {
View loading = LayoutInflater.from(parent.getContext()).
inflate(R.layout.recycler_loading_item, parent, false);
return new LoadingViewHolder(loading);
}
return null;
}
@Override
public void onBindViewHolder(final RecyclerView.ViewHolder holder, final int position) {
public void onBindViewHolder(@NonNull final RecyclerView.ViewHolder holder, final int position) {
if (holder instanceof SubBoardViewHolder) {
final Board subBoard = parsedSubBoards.get(position);
final SubBoardViewHolder subBoardViewHolder = (SubBoardViewHolder) holder;
@ -176,8 +178,9 @@ class BoardAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> {
intent.addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP);
context.startActivity(intent);
});
if (topicExpandableVisibility.get(topicViewHolder.getBindingAdapterPosition() - parsedSubBoards
.size())) {
final int pos = topicViewHolder.getBindingAdapterPosition() - parsedSubBoards.size();
if (pos >=0 && pos < topicExpandableVisibility.size() && topicExpandableVisibility.get(pos)) {
topicViewHolder.topicExpandable.setVisibility(View.VISIBLE);
topicViewHolder.showHideExpandable.setImageResource(R.drawable.ic_arrow_drop_up_accent_24dp);
}
@ -185,11 +188,11 @@ class BoardAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> {
topicViewHolder.topicExpandable.setVisibility(View.GONE);
topicViewHolder.showHideExpandable.setImageResource(R.drawable.ic_arrow_drop_down_accent_24dp);
}
topicViewHolder.showHideExpandable.setOnClickListener(view -> {
final int pos = topicViewHolder.getBindingAdapterPosition() - parsedSubBoards.size();
if (pos >=0 && pos < topicExpandableVisibility.size()) {
final boolean visible = topicExpandableVisibility.get(topicViewHolder.
getBindingAdapterPosition() - parsedSubBoards.size());
final int pos2 = topicViewHolder.getBindingAdapterPosition() - parsedSubBoards.size();
if (pos2 >=0 && pos2 < topicExpandableVisibility.size()) {
final boolean visible = topicExpandableVisibility.get(pos2);
if (visible) {
topicViewHolder.topicExpandable.setVisibility(View.GONE);
topicViewHolder.showHideExpandable.setImageResource(R.drawable.ic_arrow_drop_down_accent_24dp);
@ -198,8 +201,7 @@ class BoardAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> {
topicViewHolder.topicExpandable.setVisibility(View.VISIBLE);
topicViewHolder.showHideExpandable.setImageResource(R.drawable.ic_arrow_drop_up_accent_24dp);
}
topicExpandableVisibility.set(topicViewHolder.getBindingAdapterPosition() -
parsedSubBoards.size(), !visible);
topicExpandableVisibility.set(pos2, !visible);
}
});
topicViewHolder.topicSubject.setTypeface(Typeface.createFromAsset(context.getAssets()

14
app/src/main/java/gr/thmmy/mthmmy/activities/create_content/NewTopicTask.java

@ -8,7 +8,9 @@ import org.jsoup.Jsoup;
import org.jsoup.nodes.Document;
import java.io.IOException;
import java.util.Objects;
import gr.thmmy.mthmmy.activities.topic.Posting;
import gr.thmmy.mthmmy.base.BaseApplication;
import okhttp3.MultipartBody;
import okhttp3.OkHttpClient;
@ -73,14 +75,12 @@ public class NewTopicTask extends AsyncTask<String, Void, Boolean> {
try {
client.newCall(post).execute();
Response response2 = client.newCall(post).execute();
switch (replyStatus(response2)) {
case SUCCESSFUL:
BaseApplication.getInstance().logFirebaseAnalyticsEvent("new_topic_creation", null);
return true;
default:
Timber.e("Malformed post. Request string: %s", post.toString());
return false;
if (Objects.requireNonNull(replyStatus(response2)) == Posting.REPLY_STATUS.SUCCESSFUL) {
BaseApplication.getInstance().logFirebaseAnalyticsEvent("new_topic_creation", null);
return true;
}
Timber.e("Malformed post. Request string: %s", post.toString());
return false;
} catch (IOException e) {
return false;
}

9
app/src/main/java/gr/thmmy/mthmmy/activities/downloads/DownloadsActivity.java

@ -234,13 +234,10 @@ public class DownloadsActivity extends BaseActivity implements DownloadsAdapter.
type = Download.DownloadItemType.DOWNLOADS_FILE;
Elements pages = downloadPage.select("a.navPages");
if (pages != null) {
for (Element page : pages) {
int pageNumber = Integer.parseInt(page.text());
if (pageNumber > numberOfPages) numberOfPages = pageNumber;
}
for (Element page : pages) {
int pageNumber = Integer.parseInt(page.text());
if (pageNumber > numberOfPages) numberOfPages = pageNumber;
}
else numberOfPages = 1;
Elements rows = downloadPage.select("table.tborder>tbody>tr");
if (type == Download.DownloadItemType.DOWNLOADS_CATEGORY) {

36
app/src/main/java/gr/thmmy/mthmmy/activities/downloads/DownloadsAdapter.java

@ -15,6 +15,7 @@ import android.widget.ImageButton;
import android.widget.LinearLayout;
import android.widget.TextView;
import androidx.annotation.NonNull;
import androidx.recyclerview.widget.RecyclerView;
import java.net.MalformedURLException;
@ -27,6 +28,7 @@ import gr.thmmy.mthmmy.base.BaseActivity;
import gr.thmmy.mthmmy.model.Download;
import gr.thmmy.mthmmy.model.ThmmyFile;
import me.zhanghai.android.materialprogressbar.MaterialProgressBar;
import timber.log.Timber;
class DownloadsAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> {
private final int VIEW_TYPE_DOWNLOAD = 0;
@ -50,6 +52,7 @@ class DownloadsAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> {
return (parsedDownloads.get(position) == null) ? VIEW_TYPE_LOADING : VIEW_TYPE_DOWNLOAD;
}
@NonNull
@Override
public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
if (viewType == VIEW_TYPE_DOWNLOAD) {
@ -57,12 +60,12 @@ class DownloadsAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> {
inflate(R.layout.activity_downloads_row, parent, false);
return new DownloadViewHolder(download);
}
else if (viewType == VIEW_TYPE_LOADING) {
// viewType == VIEW_TYPE_LOADING
else {
View loading = LayoutInflater.from(parent.getContext()).
inflate(R.layout.recycler_loading_item, parent, false);
return new LoadingViewHolder(loading);
}
return null;
}
@Override
@ -87,7 +90,9 @@ class DownloadsAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> {
context.startActivity(intent);
});
if (downloadExpandableVisibility.get(downloadViewHolder.getAdapterPosition())) {
final int pos = downloadViewHolder.getBindingAdapterPosition();
if (pos >=0 && pos < downloadExpandableVisibility.size() && downloadExpandableVisibility.get(pos)) {
downloadViewHolder.informationExpandable.setVisibility(View.VISIBLE);
downloadViewHolder.informationExpandableBtn.setImageResource(R.drawable.ic_arrow_drop_up_accent_24dp);
}
@ -95,18 +100,21 @@ class DownloadsAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> {
downloadViewHolder.informationExpandable.setVisibility(View.GONE);
downloadViewHolder.informationExpandableBtn.setImageResource(R.drawable.ic_arrow_drop_down_accent_24dp);
}
downloadViewHolder.informationExpandableBtn.setOnClickListener(view -> {
final boolean visible = downloadExpandableVisibility.get(downloadViewHolder.
getAdapterPosition());
if (visible) {
downloadViewHolder.informationExpandable.setVisibility(View.GONE);
downloadViewHolder.informationExpandableBtn.setImageResource(R.drawable.ic_arrow_drop_down_accent_24dp);
}
else {
downloadViewHolder.informationExpandable.setVisibility(View.VISIBLE);
downloadViewHolder.informationExpandableBtn.setImageResource(R.drawable.ic_arrow_drop_up_accent_24dp);
final int pos2 = downloadViewHolder.getBindingAdapterPosition();
if (pos2 >=0 && pos2 < downloadExpandableVisibility.size()){
final boolean visible = downloadExpandableVisibility.get(pos2);
if (visible) {
downloadViewHolder.informationExpandable.setVisibility(View.GONE);
downloadViewHolder.informationExpandableBtn.setImageResource(R.drawable.ic_arrow_drop_down_accent_24dp);
}
else {
downloadViewHolder.informationExpandable.setVisibility(View.VISIBLE);
downloadViewHolder.informationExpandableBtn.setImageResource(R.drawable.ic_arrow_drop_up_accent_24dp);
}
downloadExpandableVisibility.set(pos2, !visible);
}
downloadExpandableVisibility.set(downloadViewHolder.getAdapterPosition(), !visible);
});
downloadViewHolder.title.setTypeface(Typeface.createFromAsset(context.getAssets()
, "fonts/fontawesome-webfont.ttf"));
@ -127,7 +135,7 @@ class DownloadsAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> {
((BaseActivity) context).downloadFile(new ThmmyFile(
new URL(download.getUrl()), download.getFileName(), null));
} catch (MalformedURLException e) {
e.printStackTrace();
Timber.e(e, "MalformedURLException");
}
});

7
app/src/main/java/gr/thmmy/mthmmy/activities/main/MainActivity.java

@ -18,6 +18,7 @@ import android.view.ViewGroup;
import android.widget.LinearLayout;
import android.widget.Toast;
import androidx.core.content.ContextCompat;
import androidx.fragment.app.Fragment;
import androidx.fragment.app.FragmentManager;
import androidx.fragment.app.FragmentPagerAdapter;
@ -228,11 +229,11 @@ public class MainActivity extends BaseActivity implements RecentFragment.RecentF
public void updateTabIcon(int position) {
if (position >= tabLayout.getTabCount()) return;
if (position == 0)
tabLayout.getTabAt(0).setIcon(getResources().getDrawable(R.drawable.ic_access_time_white_24dp));
tabLayout.getTabAt(0).setIcon(ContextCompat.getDrawable(this, R.drawable.ic_access_time_white_24dp));
else if (position == 1)
tabLayout.getTabAt(1).setIcon(getResources().getDrawable(R.drawable.ic_forum_white_24dp));
tabLayout.getTabAt(1).setIcon(ContextCompat.getDrawable(this, R.drawable.ic_forum_white_24dp));
else if (position == 2)
tabLayout.getTabAt(2).setIcon(getResources().getDrawable(R.drawable.ic_fiber_new_white_24dp));
tabLayout.getTabAt(2).setIcon(ContextCompat.getDrawable(this, R.drawable.ic_fiber_new_white_24dp));
}
private void updateTabIcons() {

2
app/src/main/java/gr/thmmy/mthmmy/activities/main/forum/ForumFragment.java

@ -209,7 +209,7 @@ public class ForumFragment extends BaseFragment {
@Override
protected ArrayList<Category> parse(Document document, Response response) throws ParseException {
Elements categoryBlocks = document.select(".tborder:not([style])>table[cellpadding=5]");
if (categoryBlocks.size() != 0) {
if (!categoryBlocks.isEmpty()) {
ArrayList<Category> fetchedCategories = new ArrayList<>();
for (Element categoryBlock : categoryBlocks) {
Element categoryElement = categoryBlock.select("td[colspan=2]>[name]").first();

1
app/src/main/java/gr/thmmy/mthmmy/activities/settings/SettingsActivity.java

@ -11,6 +11,7 @@ public class SettingsActivity extends BaseActivity {
public static final String DEFAULT_HOME_TAB = "pref_app_main_default_tab_key";
public static final String DISPLAY_COMPACT_TABS = "pref_app_display_compact_tabs_key";
public static final String DISPLAY_RELATIVE_TIME = "pref_app_display_relative_time_key";
public static final String USE_GREEK_TIMEZONE = "pref_app_use_greek_timezone_key";
public static final String NOTIFICATION_LED_KEY = "pref_notification_led_enable_key";
public static final String NOTIFICATION_VIBRATION_KEY = "pref_notification_vibration_enable_key";
public static final String POSTING_APP_SIGNATURE_ENABLE_KEY = "pref_posting_app_signature_enable_key";

8
app/src/main/java/gr/thmmy/mthmmy/activities/settings/SettingsFragment.java

@ -66,7 +66,9 @@ public class SettingsFragment extends PreferenceFragmentCompat implements Shared
defaultHomeTabValues.add("0");
defaultHomeTabValues.add("1");
if (isLoggedIn = BaseApplication.getInstance().getSessionManager().isLoggedIn()) {
isLoggedIn = BaseApplication.getInstance().getSessionManager().isLoggedIn();
if (isLoggedIn) {
defaultHomeTabEntries.add(UNREAD);
defaultHomeTabValues.add("2");
}
@ -228,6 +230,10 @@ public class SettingsFragment extends PreferenceFragmentCompat implements Shared
&& BaseApplication.getInstance().isDisplayCompactTabsEnabled() != sharedPreferences.getBoolean(key, false)) {
displayRestartAppToTakeEffectToast();
}
else if (key.equals(getString(R.string.pref_app_use_greek_timezone_key))
&& BaseApplication.getInstance().isUseGreekTimezoneEnabled() != sharedPreferences.getBoolean(key, false)) {
displayRestartAppToTakeEffectToast();
}
}
private void displayRestartAppToTakeEffectToast() {

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

@ -378,6 +378,10 @@ class TopicAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> {
//Sets username,submit date, index number, subject, post's and attached files texts
holder.username.setText(currentPost.getAuthor());
if(currentPost.getUserOnlineStatus())
holder.onlineStatusDot.setVisibility(View.VISIBLE);
holder.postDate.setText(currentPost.getPostDate());
if (currentPost.getPostNumber() != 0)
holder.postNum.setText(context.getString(
@ -822,7 +826,7 @@ class TopicAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> {
final View bodyFooterDivider;
final LinearLayout postFooter;
final TextView specialRank, rank, gender, numberOfPosts, personalText, stars;
final TextView specialRank, rank, gender, numberOfPosts, personalText, stars, onlineStatusDot;
PostViewHolder(View view) {
super(view);
@ -835,6 +839,7 @@ class TopicAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> {
username = view.findViewById(R.id.username);
subject = view.findViewById(R.id.subject);
post = view.findViewById(R.id.post);
onlineStatusDot = view.findViewById(R.id.online_status_dot);
post.setBackgroundColor(Color.argb(1, 255, 255, 255));
quoteToggle = view.findViewById(R.id.toggle_quote_button);
overflowButton = view.findViewById(R.id.post_overflow_menu);

84
app/src/main/java/gr/thmmy/mthmmy/activities/topic/TopicParser.java

@ -46,6 +46,7 @@ public class TopicParser {
private static final int USER_COLOR_BLUE = Color.parseColor("#536DFE");
static final int USER_COLOR_PINK = Color.parseColor("#FF4081");
static final int USER_COLOR_YELLOW = Color.parseColor("#FFEB3B");
static final int USER_COLOR_PURPLE = Color.parseColor("#8C7DF2");
static final int USER_COLOR_WHITE = Color.WHITE;
/**
@ -177,7 +178,7 @@ public class TopicParser {
p_specialRank, p_gender, p_personalText, p_numberOfPosts, p_postLastEditDate,
p_postURL, p_deletePostURL, p_editPostURL;
int p_postNum, p_postIndex, p_numberOfStars, p_userColor;
boolean p_isDeleted = false, p_isUserMentionedInPost = false;
boolean p_isDeleted = false, p_isUserMentionedInPost = false, p_isUserOnline = false;
ArrayList<ThmmyFile> p_attachedFiles;
//Initialize variables
@ -396,51 +397,38 @@ public class TopicParser {
Element usersExtraInfo = userName.parent().nextElementSibling(); //Get sibling "div"
List<String> infoList = Arrays.asList(usersExtraInfo.html().split("<br>"));
if (language == ParseHelpers.Language.GREEK) {
for (String line : infoList) {
if (line.contains("Μηνύματα:")) {
postsLineIndex = infoList.indexOf(line);
//Remove any line breaks and spaces on the start and end
p_numberOfPosts = line.replace("\n", "").replace("\r", "").trim();
}
if (line.contains("Φύλο:")) {
if (line.contains("alt=\"Άντρας\""))
p_gender = "Φύλο: Άντρας";
else
p_gender = "Φύλο: Γυναίκα";
}
if (line.contains("alt=\"*\"")) {
starsLineIndex = infoList.indexOf(line);
Document starsHtml = Jsoup.parse(line);
p_numberOfStars = starsHtml.select("img[alt]").size();
p_userColor = colorPicker(starsHtml.select("img[alt]").first()
.attr("abs:src"));
}
final boolean displayedLanguageGreek = language == ParseHelpers.Language.GREEK;
final String genderStr = displayedLanguageGreek ? "Φύλο:" : "Gender:";
final String altMaleStr = displayedLanguageGreek ? "alt=\"Άντρας\"" : "alt=\"Male\"";
final String genderMaleStr = displayedLanguageGreek ? "Φύλο: Άντρας" : "Gender: Male";
final String genderFemaleStr = displayedLanguageGreek ? "Φύλο: Γυναίκα" : "Gender: Female";
final String postsStr = displayedLanguageGreek ? "Μηνύματα:" : "Posts:";
final String pmTitleWithOnlineStatusStr = displayedLanguageGreek ? "title=\"Προσωπικό μήνυμα (Σε σύνδεση)\"" : "title=\"Personal Message (Online)\"";
Document starsHtml= Jsoup.parse("");
for (String line : infoList) {
if (line.contains(postsStr)) {
postsLineIndex = infoList.indexOf(line);
//Remove any line breaks and spaces on the start and end
p_numberOfPosts = line.replace("\n", "").replace("\r", "").trim();
}
}
else {
for (String line : infoList) {
if (line.contains("Posts:")) {
postsLineIndex = infoList.indexOf(line);
//Remove any line breaks and spaces on the start and end
p_numberOfPosts = line.replace("\n", "").replace("\r", "").trim();
}
if (line.contains("Gender:")) {
if (line.contains("alt=\"Male\""))
p_gender = "Gender: Male";
else
p_gender = "Gender: Female";
}
if (line.contains("alt=\"*\"")) {
starsLineIndex = infoList.indexOf(line);
Document starsHtml = Jsoup.parse(line);
p_numberOfStars = starsHtml.select("img[alt]").size();
p_userColor = colorPicker(starsHtml.select("img[alt]").first()
.attr("abs:src"));
}
if (line.contains(genderStr)) {
if (line.contains(altMaleStr))
p_gender = genderMaleStr;
else
p_gender = genderFemaleStr;
}
if (line.contains("alt=\"*\"")) {
starsLineIndex = infoList.indexOf(line);
starsHtml = Jsoup.parse(line);
}
if (line.contains(pmTitleWithOnlineStatusStr))
p_isUserOnline = true;
}
p_numberOfStars = starsHtml.select("img[alt]").size();
//If this member has no stars yet ==> New member,
//or is just a member
if (starsLineIndex == -1 || starsLineIndex == 1) {
@ -451,6 +439,12 @@ public class TopicParser {
p_specialRank = infoList.get(0).trim(); //First line has the special rank
p_rank = infoList.get(1).trim(); //Second line has the rank
}
Element starsHtmlEl = starsHtml.select("img[alt]").first();
if (p_numberOfStars>0 && starsHtmlEl!=null)
p_userColor = colorPicker(starsHtmlEl.attr("abs:src"), p_specialRank);
for (int i = postsLineIndex + 1; i < infoList.size() - 1; ++i) {
//Searches under "Posts:"
//and above "Personal Message", "View Profile" etc buttons
@ -475,7 +469,7 @@ public class TopicParser {
, p_postNum, p_postDate, p_profileURL, p_rank, p_specialRank, p_gender
, p_numberOfPosts, p_personalText, p_numberOfStars, p_userColor
, p_attachedFiles, p_postLastEditDate, p_postURL, p_deletePostURL, p_editPostURL
, p_isUserMentionedInPost, Post.TYPE_POST));
, p_isUserOnline, p_isUserMentionedInPost, Post.TYPE_POST));
}
else { //Deleted user
@ -586,7 +580,9 @@ public class TopicParser {
* @param starsUrl String containing the URL of a user's stars
* @return an int corresponding to the right color
*/
private static int colorPicker(String starsUrl) {
private static int colorPicker(String starsUrl, String specialRank) {
if(Objects.equals(specialRank, "Veteran"))
return USER_COLOR_PURPLE;
if (starsUrl.contains("/star.gif"))
return USER_COLOR_YELLOW;
else if (starsUrl.contains("/starmod.gif"))

4
app/src/main/java/gr/thmmy/mthmmy/base/BaseActivity.java

@ -20,7 +20,7 @@ import android.net.Uri;
import android.os.AsyncTask;
import android.os.Build;
import android.os.Bundle;
import android.text.Html;
// import android.text.Html;
import android.view.MenuItem;
import android.view.View;
import android.widget.Button;
@ -62,7 +62,7 @@ import gr.thmmy.mthmmy.activities.main.MainActivity;
import gr.thmmy.mthmmy.activities.profile.ProfileActivity;
import gr.thmmy.mthmmy.activities.settings.SettingsActivity;
import gr.thmmy.mthmmy.activities.shoutbox.ShoutboxActivity;
import gr.thmmy.mthmmy.activities.upload.UploadActivity;
// import gr.thmmy.mthmmy.activities.upload.UploadActivity;
import gr.thmmy.mthmmy.model.Bookmark;
import gr.thmmy.mthmmy.model.ThmmyFile;
import gr.thmmy.mthmmy.services.DownloadHelper;

7
app/src/main/java/gr/thmmy/mthmmy/base/BaseApplication.java

@ -2,6 +2,7 @@ package gr.thmmy.mthmmy.base;
import static gr.thmmy.mthmmy.activities.settings.SettingsActivity.DISPLAY_COMPACT_TABS;
import static gr.thmmy.mthmmy.activities.settings.SettingsActivity.DISPLAY_RELATIVE_TIME;
import static gr.thmmy.mthmmy.activities.settings.SettingsActivity.USE_GREEK_TIMEZONE;
import static gr.thmmy.mthmmy.activities.upload.UploadActivity.firebaseConfigUploadsCoursesKey;
import static gr.thmmy.mthmmy.utils.io.ResourceUtils.readJSONResourceToString;
@ -71,6 +72,7 @@ public class BaseApplication extends Application implements Executor{
private boolean displayRelativeTime;
private boolean displayCompactTabs;
private boolean useGreekTimezone;
//Display Metrics
private static float widthDp;
@ -115,6 +117,7 @@ public class BaseApplication extends Application implements Executor{
displayRelativeTime = settingsSharedPrefs.getBoolean(DISPLAY_RELATIVE_TIME, true);
displayCompactTabs = settingsSharedPrefs.getBoolean(DISPLAY_COMPACT_TABS, true);
useGreekTimezone = settingsSharedPrefs.getBoolean(USE_GREEK_TIMEZONE, true);
}
private void initFirebase(SharedPreferences settingsSharedPrefs) {
@ -263,6 +266,10 @@ public class BaseApplication extends Application implements Executor{
return displayCompactTabs;
}
public boolean isUseGreekTimezoneEnabled() {
return useGreekTimezone;
}
//-------------------- Firebase --------------------
public void logFirebaseAnalyticsEvent(String event, Bundle params) {

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

@ -47,6 +47,7 @@ public class Post extends TopicItem {
private final String personalText;
private final int numberOfStars;
private final boolean isUserMentionedInPost;
private final boolean isUserOnline;
// Suppresses default constructor
@SuppressWarnings("unused")
@ -73,6 +74,7 @@ public class Post extends TopicItem {
postURL = null;
postDeleteURL = null;
postEditURL = null;
isUserOnline = false;
isUserMentionedInPost = false;
postType = -1;
}
@ -101,13 +103,14 @@ public class Post extends TopicItem {
* @param attachedFiles post's attached files
* @param lastEdit post's last edit date
* @param postURL post's URL
* @param isUserOnline author's online status
*/
public Post(@Nullable String thumbnailUrl, String author, String subject, String content
, String bbContent, 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, @Nullable String lastEdit, String postURL
, @Nullable String postDeleteURL, @Nullable String postEditURL, boolean isUserMentionedInPost
, @Nullable String postDeleteURL, @Nullable String postEditURL, boolean isUserOnline, boolean isUserMentionedInPost
, int postType) {
this.bbContent = bbContent;
if (Objects.equals(thumbnailUrl, "")) this.thumbnailUrl = null;
@ -132,6 +135,7 @@ public class Post extends TopicItem {
this.postURL = postURL;
this.postDeleteURL = postDeleteURL;
this.postEditURL = postEditURL;
this.isUserOnline = isUserOnline;
this.isUserMentionedInPost = isUserMentionedInPost;
this.postType = postType;
}
@ -182,6 +186,7 @@ public class Post extends TopicItem {
this.postURL = postURL;
this.postDeleteURL = postDeleteURL;
this.postEditURL = postEditURL;
this.isUserOnline = false;
this.isUserMentionedInPost = isUserMentionedInPost;
this.postType = postType;
}
@ -362,6 +367,17 @@ public class Post extends TopicItem {
return userColor;
}
/**
* Gets the online status of this post's author.
*
* @return online status of this post's author
*/
@Nullable
public boolean getUserOnlineStatus() {
return isUserOnline;
}
/**
* Gets this post's attached files.
*

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

@ -45,7 +45,16 @@ public class ThmmyDateTimeParser {
public static String convertToTimestamp(String thmmyDateTime) {
Timber.v("Will attempt to convert %s to timestamp.", thmmyDateTime);
String originalDateTime = thmmyDateTime;
DateTimeZone dtz = getDtz();
DateTimeZone dtz;
// This was added for people who briefly travelled abroad and didn't change the displayed time in their profile settings
final boolean useeGreekTimezone = BaseApplication.getInstance().isUseGreekTimezoneEnabled();
if(useeGreekTimezone)
dtz = DateTimeZone.forID("Europe/Athens");
else
dtz = DateTimeZone.getDefault();
// Remove any unnecessary "Today at" strings
thmmyDateTime = purifyTodayDateTime(thmmyDateTime);
@ -112,12 +121,4 @@ public class ThmmyDateTimeParser {
private static String removeSeconds(String dateTime) {
return dateTime.replaceAll("(.*):\\d+($|\\s.*)", "$1$2");
}
@VisibleForTesting
private static DateTimeZone getDtz() {
if (!BaseApplication.getInstance().getSessionManager().isLoggedIn())
return DateTimeZone.forID("Europe/Athens");
else
return DateTimeZone.getDefault();
}
}

27
app/src/main/res/layout/activity_topic_post_row.xml

@ -9,17 +9,17 @@
android:paddingStart="4dp"
tools:ignore="SmallSp">
<androidx.cardview.widget.CardView xmlns:card_view="http://schemas.android.com/apk/res-auto"
<androidx.cardview.widget.CardView
android:id="@+id/card_view"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_gravity="center"
android:foreground="?android:attr/selectableItemBackground"
card_view:cardBackgroundColor="@color/background_light"
card_view:cardCornerRadius="5dp"
card_view:cardElevation="2dp"
card_view:cardPreventCornerOverlap="false"
card_view:cardUseCompatPadding="true">
app:cardBackgroundColor="@color/background_light"
app:cardCornerRadius="5dp"
app:cardElevation="2dp"
app:cardPreventCornerOverlap="false"
app:cardUseCompatPadding="true">
<LinearLayout
android:id="@+id/card_child_linear"
@ -63,11 +63,24 @@
</FrameLayout>
<TextView
android:id="@+id/username"
android:id="@+id/online_status_dot"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentTop="true"
android:layout_marginEnd="4dp"
android:layout_toEndOf="@+id/thumbnail_holder"
android:fontFamily="sans-serif"
android:gravity="center"
android:text="@string/online_status_dot"
android:textColor="@color/online_green"
android:visibility="gone" />
<TextView
android:id="@+id/username"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentTop="true"
android:layout_toEndOf="@+id/online_status_dot"
android:ellipsize="end"
android:maxLines="1"
android:text="@string/post_author"

1
app/src/main/res/values/colors.xml

@ -21,6 +21,7 @@
<color name="link_color">#FF9800</color>
<color name="mention_color">#FAA61A</color>
<color name="error_red">#890d0d</color>
<color name="online_green">#4CAF50</color>
<color name="white">#FFFFFF</color>
<color name="iron">#CCCCCC</color>

10
app/src/main/res/values/strings.xml

@ -73,13 +73,14 @@
<string name="unauthorized_topic_error">This topic is either missing or off limits to you</string>
<string name="remove_vote_button">Remove vote</string>
<string name="show_vote_results_button">show results</string>
<string name="show_vote_options_button">hide results</string>
<string name="pref_topic_drafts_key">preference-topic-drafts-key</string>
<string name="reply_button">Reply</string>
<string name="online_status_dot"></string>
<plurals name="error_too_many_checked">
<item quantity="one">You may only select %d option</item>
<item quantity="other">You may only select %d options</item>
</plurals>
<string name="show_vote_options_button">hide results</string>
<string name="pref_topic_drafts_key">preference-topic-drafts-key</string>
<string name="reply_button">Reply</string>
<!--Profile Activity-->
<string name="username">Username</string>
@ -179,6 +180,9 @@
<string name="pref_app_display_relative_time_key">pref_app_display_relative_time_key</string>
<string name="pref_title_display_relative_time">Display relative time</string>
<string name="pref_summary_display_relative_time">Considering that you haven\'t set some weird custom time format</string>
<string name="pref_app_use_greek_timezone_key">pref_app_use_greek_timezone_key</string>
<string name="pref_title_use_greek_timezone">Use Greek timezone</string>
<string name="pref_summary_use_greek_timezone">For relative time only. Disable this if you have also set a custom displayed time in your profile.</string>
<string name="pref_app_display_compact_tabs_key">pref_app_display_compact_tabs_key</string>
<string name="pref_title_display_compact_tabs">Display compact tabs</string>
<string name="pref_summary_display_compact_tabs">Home screen tabs will occupy less space</string>

6
app/src/main/res/xml-v26/app_preferences_guest.xml

@ -20,6 +20,12 @@
android:title="@string/pref_title_display_relative_time"
android:summary="@string/pref_summary_display_relative_time"
app:iconSpaceReserved="false" />
<androidx.preference.SwitchPreferenceCompat
android:defaultValue="true"
android:key="@string/pref_app_use_greek_timezone_key"
android:title="@string/pref_title_use_greek_timezone"
android:summary="@string/pref_summary_use_greek_timezone"
app:iconSpaceReserved="false" />
<androidx.preference.SwitchPreferenceCompat
android:defaultValue="true"
android:key="@string/pref_app_display_compact_tabs_key"

6
app/src/main/res/xml-v26/app_preferences_user.xml

@ -20,6 +20,12 @@
android:title="@string/pref_title_display_relative_time"
android:summary="@string/pref_summary_display_relative_time"
app:iconSpaceReserved="false" />
<androidx.preference.SwitchPreferenceCompat
android:defaultValue="true"
android:key="@string/pref_app_use_greek_timezone_key"
android:title="@string/pref_title_use_greek_timezone"
android:summary="@string/pref_summary_use_greek_timezone"
app:iconSpaceReserved="false" />
<androidx.preference.SwitchPreferenceCompat
android:defaultValue="true"
android:key="@string/pref_app_display_compact_tabs_key"

6
app/src/main/res/xml/app_preferences_guest.xml

@ -20,6 +20,12 @@
android:title="@string/pref_title_display_relative_time"
android:summary="@string/pref_summary_display_relative_time"
app:iconSpaceReserved="false" />
<androidx.preference.SwitchPreferenceCompat
android:defaultValue="true"
android:key="@string/pref_app_use_greek_timezone_key"
android:title="@string/pref_title_use_greek_timezone"
android:summary="@string/pref_summary_use_greek_timezone"
app:iconSpaceReserved="false" />
<androidx.preference.SwitchPreferenceCompat
android:defaultValue="true"
android:key="@string/pref_app_display_compact_tabs_key"

6
app/src/main/res/xml/app_preferences_user.xml

@ -20,6 +20,12 @@
android:title="@string/pref_title_display_relative_time"
android:summary="@string/pref_summary_display_relative_time"
app:iconSpaceReserved="false" />
<androidx.preference.SwitchPreferenceCompat
android:defaultValue="true"
android:key="@string/pref_app_use_greek_timezone_key"
android:title="@string/pref_title_use_greek_timezone"
android:summary="@string/pref_summary_use_greek_timezone"
app:iconSpaceReserved="false" />
<androidx.preference.SwitchPreferenceCompat
android:defaultValue="true"
android:key="@string/pref_app_display_compact_tabs_key"

Loading…
Cancel
Save