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. 8
      app/src/main/java/gr/thmmy/mthmmy/activities/create_content/NewTopicTask.java
  7. 3
      app/src/main/java/gr/thmmy/mthmmy/activities/downloads/DownloadsActivity.java
  8. 22
      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. 66
      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 compileSdk 33
minSdkVersion 23 minSdkVersion 23
targetSdkVersion 33 targetSdkVersion 33
versionCode 33 versionCode 34
versionName "2.2.1" versionName "2.3.0"
archivesBaseName = "mTHMMY-v$versionName" archivesBaseName = "mTHMMY-v$versionName"
buildConfigField "String", "CURRENT_BRANCH", "\"" + getCurrentBranch() + "\"" buildConfigField "String", "CURRENT_BRANCH", "\"" + getCurrentBranch() + "\""
buildConfigField "String", "COMMIT_HASH", "\"" + getCommitHash() + "\"" 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 { try {
def grgit = Grgit.open() def grgit = getGrgit()
def currentBranch = grgit.branch.getCurrent().name def currentBranch = grgit.branch.getCurrent().name
grgit.close() grgit.close()
return currentBranch return currentBranch
@ -21,9 +25,9 @@ static def getCurrentBranch() {
} }
} }
static def getCommitHash() { def getCommitHash() {
try { try {
def grgit = Grgit.open() def grgit = getGrgit()
def commitHash = grgit.head().id def commitHash = grgit.head().id
grgit.close() grgit.close()
return commitHash return commitHash
@ -33,9 +37,9 @@ static def getCommitHash() {
} }
//Will return true if there are no uncommitted changes //Will return true if there are no uncommitted changes
static def isClean() { def isClean() {
try { try {
def grgit = Grgit.open() def grgit = getGrgit()
def isClean = grgit.status().isClean() def isClean = grgit.status().isClean()
grgit.close() grgit.close()
return isClean return isClean

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

@ -60,7 +60,7 @@ public class AboutActivity extends BaseActivity {
String versionInfo = ""; String versionInfo = "";
if (gitExists) if (gitExists)
versionInfo = "-" + BuildConfig.CURRENT_BRANCH + "-" + commitHash versionInfo = "-" + BuildConfig.CURRENT_BRANCH + "-" + commitHash
+ (BuildConfig.IS_CLEAN ? "" : "-dirty") + (BuildConfig.IS_CLEAN ? "" : "~")
+ " "; // Avoid last letter being cut in italics styled TextView + " "; // Avoid last letter being cut in italics styled TextView
//Initialize appbar //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 { try {
Elements pages = boardPage.select("table.tborder td.catbg[height=30]").first() Elements pages = boardPage.select("table.tborder td.catbg[height=30]").first()
.select("a.navPages"); .select("a.navPages");
if (pages != null && !pages.isEmpty()) { if (!pages.isEmpty()) {
for (Element page : pages) { for (Element page : pages) {
if (Integer.parseInt(page.text()) > numberOfPages) if (Integer.parseInt(page.text()) > numberOfPages)
numberOfPages = Integer.parseInt(page.text()); numberOfPages = Integer.parseInt(page.text());
@ -240,7 +240,7 @@ public class BoardActivity extends BaseActivity implements BoardAdapter.OnLoadMo
if (pagesLoaded == 0) { //Finds sub boards if (pagesLoaded == 0) { //Finds sub boards
Elements subBoardRows = boardPage.select("div.tborder>table>tbody>tr"); Elements subBoardRows = boardPage.select("div.tborder>table>tbody>tr");
if (subBoardRows != null && !subBoardRows.isEmpty()) { if (!subBoardRows.isEmpty()) {
for (Element subBoardRow : subBoardRows) { for (Element subBoardRow : subBoardRows) {
if (!Objects.equals(subBoardRow.className(), "titlebg")) { if (!Objects.equals(subBoardRow.className(), "titlebg")) {
String pUrl = "", pTitle = "", pMods = "", pStats = "", String pUrl = "", pTitle = "", pMods = "", pStats = "",
@ -314,7 +314,7 @@ public class BoardActivity extends BaseActivity implements BoardAdapter.OnLoadMo
} }
//Finds topics //Finds topics
Elements topicRows = boardPage.select("table.bordercolor>tbody>tr"); Elements topicRows = boardPage.select("table.bordercolor>tbody>tr");
if (topicRows != null && !topicRows.isEmpty()) { if (!topicRows.isEmpty()) {
for (Element topicRow : topicRows) { for (Element topicRow : topicRows) {
if (!Objects.equals(topicRow.className(), "titlebg")) { if (!Objects.equals(topicRow.className(), "titlebg")) {
String pTopicUrl, pSubject, pStarter, pLastUser = "", pLastPostDateTime = "00:00:00", pLastPost, pLastPostUrl, pStats; 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.LinearLayout;
import android.widget.TextView; import android.widget.TextView;
import androidx.annotation.NonNull;
import androidx.recyclerview.widget.RecyclerView; import androidx.recyclerview.widget.RecyclerView;
import java.util.ArrayList; import java.util.ArrayList;
@ -63,6 +64,7 @@ class BoardAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> {
return VIEW_TYPE_LOADING; return VIEW_TYPE_LOADING;
} }
@NonNull
@Override @Override
public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) { public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
if (viewType == VIEW_TYPE_SUB_BOARD) { 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); inflate(R.layout.activity_board_topic_row, parent, false);
return new TopicViewHolder(topic); return new TopicViewHolder(topic);
} }
else if (viewType == VIEW_TYPE_LOADING) { // viewType == VIEW_TYPE_LOADING
else {
View loading = LayoutInflater.from(parent.getContext()). View loading = LayoutInflater.from(parent.getContext()).
inflate(R.layout.recycler_loading_item, parent, false); inflate(R.layout.recycler_loading_item, parent, false);
return new LoadingViewHolder(loading); return new LoadingViewHolder(loading);
} }
return null;
} }
@Override @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) { if (holder instanceof SubBoardViewHolder) {
final Board subBoard = parsedSubBoards.get(position); final Board subBoard = parsedSubBoards.get(position);
final SubBoardViewHolder subBoardViewHolder = (SubBoardViewHolder) holder; final SubBoardViewHolder subBoardViewHolder = (SubBoardViewHolder) holder;
@ -176,8 +178,9 @@ class BoardAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> {
intent.addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP); intent.addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP);
context.startActivity(intent); 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.topicExpandable.setVisibility(View.VISIBLE);
topicViewHolder.showHideExpandable.setImageResource(R.drawable.ic_arrow_drop_up_accent_24dp); 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.topicExpandable.setVisibility(View.GONE);
topicViewHolder.showHideExpandable.setImageResource(R.drawable.ic_arrow_drop_down_accent_24dp); topicViewHolder.showHideExpandable.setImageResource(R.drawable.ic_arrow_drop_down_accent_24dp);
} }
topicViewHolder.showHideExpandable.setOnClickListener(view -> { topicViewHolder.showHideExpandable.setOnClickListener(view -> {
final int pos = topicViewHolder.getBindingAdapterPosition() - parsedSubBoards.size(); final int pos2 = topicViewHolder.getBindingAdapterPosition() - parsedSubBoards.size();
if (pos >=0 && pos < topicExpandableVisibility.size()) { if (pos2 >=0 && pos2 < topicExpandableVisibility.size()) {
final boolean visible = topicExpandableVisibility.get(topicViewHolder. final boolean visible = topicExpandableVisibility.get(pos2);
getBindingAdapterPosition() - parsedSubBoards.size());
if (visible) { if (visible) {
topicViewHolder.topicExpandable.setVisibility(View.GONE); topicViewHolder.topicExpandable.setVisibility(View.GONE);
topicViewHolder.showHideExpandable.setImageResource(R.drawable.ic_arrow_drop_down_accent_24dp); 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.topicExpandable.setVisibility(View.VISIBLE);
topicViewHolder.showHideExpandable.setImageResource(R.drawable.ic_arrow_drop_up_accent_24dp); topicViewHolder.showHideExpandable.setImageResource(R.drawable.ic_arrow_drop_up_accent_24dp);
} }
topicExpandableVisibility.set(topicViewHolder.getBindingAdapterPosition() - topicExpandableVisibility.set(pos2, !visible);
parsedSubBoards.size(), !visible);
} }
}); });
topicViewHolder.topicSubject.setTypeface(Typeface.createFromAsset(context.getAssets() topicViewHolder.topicSubject.setTypeface(Typeface.createFromAsset(context.getAssets()

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

3
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; type = Download.DownloadItemType.DOWNLOADS_FILE;
Elements pages = downloadPage.select("a.navPages"); Elements pages = downloadPage.select("a.navPages");
if (pages != null) {
for (Element page : pages) { for (Element page : pages) {
int pageNumber = Integer.parseInt(page.text()); int pageNumber = Integer.parseInt(page.text());
if (pageNumber > numberOfPages) numberOfPages = pageNumber; if (pageNumber > numberOfPages) numberOfPages = pageNumber;
} }
}
else numberOfPages = 1;
Elements rows = downloadPage.select("table.tborder>tbody>tr"); Elements rows = downloadPage.select("table.tborder>tbody>tr");
if (type == Download.DownloadItemType.DOWNLOADS_CATEGORY) { if (type == Download.DownloadItemType.DOWNLOADS_CATEGORY) {

22
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.LinearLayout;
import android.widget.TextView; import android.widget.TextView;
import androidx.annotation.NonNull;
import androidx.recyclerview.widget.RecyclerView; import androidx.recyclerview.widget.RecyclerView;
import java.net.MalformedURLException; 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.Download;
import gr.thmmy.mthmmy.model.ThmmyFile; import gr.thmmy.mthmmy.model.ThmmyFile;
import me.zhanghai.android.materialprogressbar.MaterialProgressBar; import me.zhanghai.android.materialprogressbar.MaterialProgressBar;
import timber.log.Timber;
class DownloadsAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> { class DownloadsAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> {
private final int VIEW_TYPE_DOWNLOAD = 0; 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; return (parsedDownloads.get(position) == null) ? VIEW_TYPE_LOADING : VIEW_TYPE_DOWNLOAD;
} }
@NonNull
@Override @Override
public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) { public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
if (viewType == VIEW_TYPE_DOWNLOAD) { if (viewType == VIEW_TYPE_DOWNLOAD) {
@ -57,12 +60,12 @@ class DownloadsAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> {
inflate(R.layout.activity_downloads_row, parent, false); inflate(R.layout.activity_downloads_row, parent, false);
return new DownloadViewHolder(download); return new DownloadViewHolder(download);
} }
else if (viewType == VIEW_TYPE_LOADING) { // viewType == VIEW_TYPE_LOADING
else {
View loading = LayoutInflater.from(parent.getContext()). View loading = LayoutInflater.from(parent.getContext()).
inflate(R.layout.recycler_loading_item, parent, false); inflate(R.layout.recycler_loading_item, parent, false);
return new LoadingViewHolder(loading); return new LoadingViewHolder(loading);
} }
return null;
} }
@Override @Override
@ -87,7 +90,9 @@ class DownloadsAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> {
context.startActivity(intent); 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.informationExpandable.setVisibility(View.VISIBLE);
downloadViewHolder.informationExpandableBtn.setImageResource(R.drawable.ic_arrow_drop_up_accent_24dp); downloadViewHolder.informationExpandableBtn.setImageResource(R.drawable.ic_arrow_drop_up_accent_24dp);
} }
@ -95,9 +100,11 @@ class DownloadsAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> {
downloadViewHolder.informationExpandable.setVisibility(View.GONE); downloadViewHolder.informationExpandable.setVisibility(View.GONE);
downloadViewHolder.informationExpandableBtn.setImageResource(R.drawable.ic_arrow_drop_down_accent_24dp); downloadViewHolder.informationExpandableBtn.setImageResource(R.drawable.ic_arrow_drop_down_accent_24dp);
} }
downloadViewHolder.informationExpandableBtn.setOnClickListener(view -> { downloadViewHolder.informationExpandableBtn.setOnClickListener(view -> {
final boolean visible = downloadExpandableVisibility.get(downloadViewHolder. final int pos2 = downloadViewHolder.getBindingAdapterPosition();
getAdapterPosition()); if (pos2 >=0 && pos2 < downloadExpandableVisibility.size()){
final boolean visible = downloadExpandableVisibility.get(pos2);
if (visible) { if (visible) {
downloadViewHolder.informationExpandable.setVisibility(View.GONE); downloadViewHolder.informationExpandable.setVisibility(View.GONE);
downloadViewHolder.informationExpandableBtn.setImageResource(R.drawable.ic_arrow_drop_down_accent_24dp); downloadViewHolder.informationExpandableBtn.setImageResource(R.drawable.ic_arrow_drop_down_accent_24dp);
@ -106,7 +113,8 @@ class DownloadsAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> {
downloadViewHolder.informationExpandable.setVisibility(View.VISIBLE); downloadViewHolder.informationExpandable.setVisibility(View.VISIBLE);
downloadViewHolder.informationExpandableBtn.setImageResource(R.drawable.ic_arrow_drop_up_accent_24dp); downloadViewHolder.informationExpandableBtn.setImageResource(R.drawable.ic_arrow_drop_up_accent_24dp);
} }
downloadExpandableVisibility.set(downloadViewHolder.getAdapterPosition(), !visible); downloadExpandableVisibility.set(pos2, !visible);
}
}); });
downloadViewHolder.title.setTypeface(Typeface.createFromAsset(context.getAssets() downloadViewHolder.title.setTypeface(Typeface.createFromAsset(context.getAssets()
, "fonts/fontawesome-webfont.ttf")); , "fonts/fontawesome-webfont.ttf"));
@ -127,7 +135,7 @@ class DownloadsAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> {
((BaseActivity) context).downloadFile(new ThmmyFile( ((BaseActivity) context).downloadFile(new ThmmyFile(
new URL(download.getUrl()), download.getFileName(), null)); new URL(download.getUrl()), download.getFileName(), null));
} catch (MalformedURLException e) { } 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.LinearLayout;
import android.widget.Toast; import android.widget.Toast;
import androidx.core.content.ContextCompat;
import androidx.fragment.app.Fragment; import androidx.fragment.app.Fragment;
import androidx.fragment.app.FragmentManager; import androidx.fragment.app.FragmentManager;
import androidx.fragment.app.FragmentPagerAdapter; import androidx.fragment.app.FragmentPagerAdapter;
@ -228,11 +229,11 @@ public class MainActivity extends BaseActivity implements RecentFragment.RecentF
public void updateTabIcon(int position) { public void updateTabIcon(int position) {
if (position >= tabLayout.getTabCount()) return; if (position >= tabLayout.getTabCount()) return;
if (position == 0) 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) 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) 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() { 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 @Override
protected ArrayList<Category> parse(Document document, Response response) throws ParseException { protected ArrayList<Category> parse(Document document, Response response) throws ParseException {
Elements categoryBlocks = document.select(".tborder:not([style])>table[cellpadding=5]"); Elements categoryBlocks = document.select(".tborder:not([style])>table[cellpadding=5]");
if (categoryBlocks.size() != 0) { if (!categoryBlocks.isEmpty()) {
ArrayList<Category> fetchedCategories = new ArrayList<>(); ArrayList<Category> fetchedCategories = new ArrayList<>();
for (Element categoryBlock : categoryBlocks) { for (Element categoryBlock : categoryBlocks) {
Element categoryElement = categoryBlock.select("td[colspan=2]>[name]").first(); 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 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_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 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_LED_KEY = "pref_notification_led_enable_key";
public static final String NOTIFICATION_VIBRATION_KEY = "pref_notification_vibration_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"; 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("0");
defaultHomeTabValues.add("1"); defaultHomeTabValues.add("1");
if (isLoggedIn = BaseApplication.getInstance().getSessionManager().isLoggedIn()) { isLoggedIn = BaseApplication.getInstance().getSessionManager().isLoggedIn();
if (isLoggedIn) {
defaultHomeTabEntries.add(UNREAD); defaultHomeTabEntries.add(UNREAD);
defaultHomeTabValues.add("2"); defaultHomeTabValues.add("2");
} }
@ -228,6 +230,10 @@ public class SettingsFragment extends PreferenceFragmentCompat implements Shared
&& BaseApplication.getInstance().isDisplayCompactTabsEnabled() != sharedPreferences.getBoolean(key, false)) { && BaseApplication.getInstance().isDisplayCompactTabsEnabled() != sharedPreferences.getBoolean(key, false)) {
displayRestartAppToTakeEffectToast(); 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() { 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 //Sets username,submit date, index number, subject, post's and attached files texts
holder.username.setText(currentPost.getAuthor()); holder.username.setText(currentPost.getAuthor());
if(currentPost.getUserOnlineStatus())
holder.onlineStatusDot.setVisibility(View.VISIBLE);
holder.postDate.setText(currentPost.getPostDate()); holder.postDate.setText(currentPost.getPostDate());
if (currentPost.getPostNumber() != 0) if (currentPost.getPostNumber() != 0)
holder.postNum.setText(context.getString( holder.postNum.setText(context.getString(
@ -822,7 +826,7 @@ class TopicAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> {
final View bodyFooterDivider; final View bodyFooterDivider;
final LinearLayout postFooter; final LinearLayout postFooter;
final TextView specialRank, rank, gender, numberOfPosts, personalText, stars; final TextView specialRank, rank, gender, numberOfPosts, personalText, stars, onlineStatusDot;
PostViewHolder(View view) { PostViewHolder(View view) {
super(view); super(view);
@ -835,6 +839,7 @@ class TopicAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> {
username = view.findViewById(R.id.username); username = view.findViewById(R.id.username);
subject = view.findViewById(R.id.subject); subject = view.findViewById(R.id.subject);
post = view.findViewById(R.id.post); post = view.findViewById(R.id.post);
onlineStatusDot = view.findViewById(R.id.online_status_dot);
post.setBackgroundColor(Color.argb(1, 255, 255, 255)); post.setBackgroundColor(Color.argb(1, 255, 255, 255));
quoteToggle = view.findViewById(R.id.toggle_quote_button); quoteToggle = view.findViewById(R.id.toggle_quote_button);
overflowButton = view.findViewById(R.id.post_overflow_menu); overflowButton = view.findViewById(R.id.post_overflow_menu);

66
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"); private static final int USER_COLOR_BLUE = Color.parseColor("#536DFE");
static final int USER_COLOR_PINK = Color.parseColor("#FF4081"); static final int USER_COLOR_PINK = Color.parseColor("#FF4081");
static final int USER_COLOR_YELLOW = Color.parseColor("#FFEB3B"); 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; 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_specialRank, p_gender, p_personalText, p_numberOfPosts, p_postLastEditDate,
p_postURL, p_deletePostURL, p_editPostURL; p_postURL, p_deletePostURL, p_editPostURL;
int p_postNum, p_postIndex, p_numberOfStars, p_userColor; 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; ArrayList<ThmmyFile> p_attachedFiles;
//Initialize variables //Initialize variables
@ -396,50 +397,37 @@ public class TopicParser {
Element usersExtraInfo = userName.parent().nextElementSibling(); //Get sibling "div" Element usersExtraInfo = userName.parent().nextElementSibling(); //Get sibling "div"
List<String> infoList = Arrays.asList(usersExtraInfo.html().split("<br>")); List<String> infoList = Arrays.asList(usersExtraInfo.html().split("<br>"));
if (language == ParseHelpers.Language.GREEK) { 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) { for (String line : infoList) {
if (line.contains("Μηνύματα:")) { if (line.contains(postsStr)) {
postsLineIndex = infoList.indexOf(line); postsLineIndex = infoList.indexOf(line);
//Remove any line breaks and spaces on the start and end //Remove any line breaks and spaces on the start and end
p_numberOfPosts = line.replace("\n", "").replace("\r", "").trim(); p_numberOfPosts = line.replace("\n", "").replace("\r", "").trim();
} }
if (line.contains("Φύλο:")) { if (line.contains(genderStr)) {
if (line.contains("alt=\"Άντρας\"")) if (line.contains(altMaleStr))
p_gender = "Φύλο: Άντρας"; p_gender = genderMaleStr;
else else
p_gender = "Φύλο: Γυναίκα"; p_gender = genderFemaleStr;
} }
if (line.contains("alt=\"*\"")) { if (line.contains("alt=\"*\"")) {
starsLineIndex = infoList.indexOf(line); starsLineIndex = infoList.indexOf(line);
Document starsHtml = Jsoup.parse(line); starsHtml = Jsoup.parse(line);
p_numberOfStars = starsHtml.select("img[alt]").size();
p_userColor = colorPicker(starsHtml.select("img[alt]").first()
.attr("abs:src"));
}
}
} }
else { if (line.contains(pmTitleWithOnlineStatusStr))
for (String line : infoList) { p_isUserOnline = true;
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_numberOfStars = starsHtml.select("img[alt]").size();
p_userColor = colorPicker(starsHtml.select("img[alt]").first()
.attr("abs:src"));
}
}
}
//If this member has no stars yet ==> New member, //If this member has no stars yet ==> New member,
//or is just a member //or is just a member
@ -451,6 +439,12 @@ public class TopicParser {
p_specialRank = infoList.get(0).trim(); //First line has the special rank p_specialRank = infoList.get(0).trim(); //First line has the special rank
p_rank = infoList.get(1).trim(); //Second line has the 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) { for (int i = postsLineIndex + 1; i < infoList.size() - 1; ++i) {
//Searches under "Posts:" //Searches under "Posts:"
//and above "Personal Message", "View Profile" etc buttons //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_postNum, p_postDate, p_profileURL, p_rank, p_specialRank, p_gender
, p_numberOfPosts, p_personalText, p_numberOfStars, p_userColor , p_numberOfPosts, p_personalText, p_numberOfStars, p_userColor
, p_attachedFiles, p_postLastEditDate, p_postURL, p_deletePostURL, p_editPostURL , 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 else { //Deleted user
@ -586,7 +580,9 @@ public class TopicParser {
* @param starsUrl String containing the URL of a user's stars * @param starsUrl String containing the URL of a user's stars
* @return an int corresponding to the right color * @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")) if (starsUrl.contains("/star.gif"))
return USER_COLOR_YELLOW; return USER_COLOR_YELLOW;
else if (starsUrl.contains("/starmod.gif")) 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.AsyncTask;
import android.os.Build; import android.os.Build;
import android.os.Bundle; import android.os.Bundle;
import android.text.Html; // import android.text.Html;
import android.view.MenuItem; import android.view.MenuItem;
import android.view.View; import android.view.View;
import android.widget.Button; 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.profile.ProfileActivity;
import gr.thmmy.mthmmy.activities.settings.SettingsActivity; import gr.thmmy.mthmmy.activities.settings.SettingsActivity;
import gr.thmmy.mthmmy.activities.shoutbox.ShoutboxActivity; 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.Bookmark;
import gr.thmmy.mthmmy.model.ThmmyFile; import gr.thmmy.mthmmy.model.ThmmyFile;
import gr.thmmy.mthmmy.services.DownloadHelper; 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_COMPACT_TABS;
import static gr.thmmy.mthmmy.activities.settings.SettingsActivity.DISPLAY_RELATIVE_TIME; 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.activities.upload.UploadActivity.firebaseConfigUploadsCoursesKey;
import static gr.thmmy.mthmmy.utils.io.ResourceUtils.readJSONResourceToString; 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 displayRelativeTime;
private boolean displayCompactTabs; private boolean displayCompactTabs;
private boolean useGreekTimezone;
//Display Metrics //Display Metrics
private static float widthDp; private static float widthDp;
@ -115,6 +117,7 @@ public class BaseApplication extends Application implements Executor{
displayRelativeTime = settingsSharedPrefs.getBoolean(DISPLAY_RELATIVE_TIME, true); displayRelativeTime = settingsSharedPrefs.getBoolean(DISPLAY_RELATIVE_TIME, true);
displayCompactTabs = settingsSharedPrefs.getBoolean(DISPLAY_COMPACT_TABS, true); displayCompactTabs = settingsSharedPrefs.getBoolean(DISPLAY_COMPACT_TABS, true);
useGreekTimezone = settingsSharedPrefs.getBoolean(USE_GREEK_TIMEZONE, true);
} }
private void initFirebase(SharedPreferences settingsSharedPrefs) { private void initFirebase(SharedPreferences settingsSharedPrefs) {
@ -263,6 +266,10 @@ public class BaseApplication extends Application implements Executor{
return displayCompactTabs; return displayCompactTabs;
} }
public boolean isUseGreekTimezoneEnabled() {
return useGreekTimezone;
}
//-------------------- Firebase -------------------- //-------------------- Firebase --------------------
public void logFirebaseAnalyticsEvent(String event, Bundle params) { 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 String personalText;
private final int numberOfStars; private final int numberOfStars;
private final boolean isUserMentionedInPost; private final boolean isUserMentionedInPost;
private final boolean isUserOnline;
// Suppresses default constructor // Suppresses default constructor
@SuppressWarnings("unused") @SuppressWarnings("unused")
@ -73,6 +74,7 @@ public class Post extends TopicItem {
postURL = null; postURL = null;
postDeleteURL = null; postDeleteURL = null;
postEditURL = null; postEditURL = null;
isUserOnline = false;
isUserMentionedInPost = false; isUserMentionedInPost = false;
postType = -1; postType = -1;
} }
@ -101,13 +103,14 @@ public class Post extends TopicItem {
* @param attachedFiles post's attached files * @param attachedFiles post's attached files
* @param lastEdit post's last edit date * @param lastEdit post's last edit date
* @param postURL post's URL * @param postURL post's URL
* @param isUserOnline author's online status
*/ */
public Post(@Nullable String thumbnailUrl, String author, String subject, String content public Post(@Nullable String thumbnailUrl, String author, String subject, String content
, String bbContent, int postIndex, int postNumber, String postDate, String profileURl, @Nullable String rank , 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 special_rank, @Nullable String gender, @Nullable String numberOfPosts
, @Nullable String personalText, int numberOfStars, int userColor , @Nullable String personalText, int numberOfStars, int userColor
, @Nullable ArrayList<ThmmyFile> attachedFiles, @Nullable String lastEdit, String postURL , @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) { , int postType) {
this.bbContent = bbContent; this.bbContent = bbContent;
if (Objects.equals(thumbnailUrl, "")) this.thumbnailUrl = null; if (Objects.equals(thumbnailUrl, "")) this.thumbnailUrl = null;
@ -132,6 +135,7 @@ public class Post extends TopicItem {
this.postURL = postURL; this.postURL = postURL;
this.postDeleteURL = postDeleteURL; this.postDeleteURL = postDeleteURL;
this.postEditURL = postEditURL; this.postEditURL = postEditURL;
this.isUserOnline = isUserOnline;
this.isUserMentionedInPost = isUserMentionedInPost; this.isUserMentionedInPost = isUserMentionedInPost;
this.postType = postType; this.postType = postType;
} }
@ -182,6 +186,7 @@ public class Post extends TopicItem {
this.postURL = postURL; this.postURL = postURL;
this.postDeleteURL = postDeleteURL; this.postDeleteURL = postDeleteURL;
this.postEditURL = postEditURL; this.postEditURL = postEditURL;
this.isUserOnline = false;
this.isUserMentionedInPost = isUserMentionedInPost; this.isUserMentionedInPost = isUserMentionedInPost;
this.postType = postType; this.postType = postType;
} }
@ -362,6 +367,17 @@ public class Post extends TopicItem {
return userColor; 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. * 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) { public static String convertToTimestamp(String thmmyDateTime) {
Timber.v("Will attempt to convert %s to timestamp.", thmmyDateTime); Timber.v("Will attempt to convert %s to timestamp.", thmmyDateTime);
String originalDateTime = thmmyDateTime; String originalDateTime = thmmyDateTime;
DateTimeZone dtz = getDtz();
DateTimeZone dtz;
// 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 // Remove any unnecessary "Today at" strings
thmmyDateTime = purifyTodayDateTime(thmmyDateTime); thmmyDateTime = purifyTodayDateTime(thmmyDateTime);
@ -112,12 +121,4 @@ public class ThmmyDateTimeParser {
private static String removeSeconds(String dateTime) { private static String removeSeconds(String dateTime) {
return dateTime.replaceAll("(.*):\\d+($|\\s.*)", "$1$2"); 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" android:paddingStart="4dp"
tools:ignore="SmallSp"> 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:id="@+id/card_view"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="match_parent" android:layout_height="match_parent"
android:layout_gravity="center" android:layout_gravity="center"
android:foreground="?android:attr/selectableItemBackground" android:foreground="?android:attr/selectableItemBackground"
card_view:cardBackgroundColor="@color/background_light" app:cardBackgroundColor="@color/background_light"
card_view:cardCornerRadius="5dp" app:cardCornerRadius="5dp"
card_view:cardElevation="2dp" app:cardElevation="2dp"
card_view:cardPreventCornerOverlap="false" app:cardPreventCornerOverlap="false"
card_view:cardUseCompatPadding="true"> app:cardUseCompatPadding="true">
<LinearLayout <LinearLayout
android:id="@+id/card_child_linear" android:id="@+id/card_child_linear"
@ -63,11 +63,24 @@
</FrameLayout> </FrameLayout>
<TextView <TextView
android:id="@+id/username" android:id="@+id/online_status_dot"
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_alignParentTop="true" android:layout_alignParentTop="true"
android:layout_marginEnd="4dp"
android:layout_toEndOf="@+id/thumbnail_holder" 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:ellipsize="end"
android:maxLines="1" android:maxLines="1"
android:text="@string/post_author" 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="link_color">#FF9800</color>
<color name="mention_color">#FAA61A</color> <color name="mention_color">#FAA61A</color>
<color name="error_red">#890d0d</color> <color name="error_red">#890d0d</color>
<color name="online_green">#4CAF50</color>
<color name="white">#FFFFFF</color> <color name="white">#FFFFFF</color>
<color name="iron">#CCCCCC</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="unauthorized_topic_error">This topic is either missing or off limits to you</string>
<string name="remove_vote_button">Remove vote</string> <string name="remove_vote_button">Remove vote</string>
<string name="show_vote_results_button">show results</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"> <plurals name="error_too_many_checked">
<item quantity="one">You may only select %d option</item> <item quantity="one">You may only select %d option</item>
<item quantity="other">You may only select %d options</item> <item quantity="other">You may only select %d options</item>
</plurals> </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--> <!--Profile Activity-->
<string name="username">Username</string> <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_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_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_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_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_title_display_compact_tabs">Display compact tabs</string>
<string name="pref_summary_display_compact_tabs">Home screen tabs will occupy less space</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:title="@string/pref_title_display_relative_time"
android:summary="@string/pref_summary_display_relative_time" android:summary="@string/pref_summary_display_relative_time"
app:iconSpaceReserved="false" /> 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 <androidx.preference.SwitchPreferenceCompat
android:defaultValue="true" android:defaultValue="true"
android:key="@string/pref_app_display_compact_tabs_key" 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:title="@string/pref_title_display_relative_time"
android:summary="@string/pref_summary_display_relative_time" android:summary="@string/pref_summary_display_relative_time"
app:iconSpaceReserved="false" /> 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 <androidx.preference.SwitchPreferenceCompat
android:defaultValue="true" android:defaultValue="true"
android:key="@string/pref_app_display_compact_tabs_key" 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:title="@string/pref_title_display_relative_time"
android:summary="@string/pref_summary_display_relative_time" android:summary="@string/pref_summary_display_relative_time"
app:iconSpaceReserved="false" /> 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 <androidx.preference.SwitchPreferenceCompat
android:defaultValue="true" android:defaultValue="true"
android:key="@string/pref_app_display_compact_tabs_key" 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:title="@string/pref_title_display_relative_time"
android:summary="@string/pref_summary_display_relative_time" android:summary="@string/pref_summary_display_relative_time"
app:iconSpaceReserved="false" /> 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 <androidx.preference.SwitchPreferenceCompat
android:defaultValue="true" android:defaultValue="true"
android:key="@string/pref_app_display_compact_tabs_key" android:key="@string/pref_app_display_compact_tabs_key"

Loading…
Cancel
Save