Browse Source

feat: up targetSDK, gradle, bump min Android version, refactoring

develop
Ezerous 2 years ago
parent
commit
a0b617f371
  1. 2
      README.md
  2. 11
      app/build.gradle
  3. 4
      app/gradle/grgit.gradle
  4. 2
      app/src/main/AndroidManifest.xml
  5. 16
      app/src/main/java/gr/thmmy/mthmmy/activities/LoginActivity.java
  6. 10
      app/src/main/java/gr/thmmy/mthmmy/activities/board/BoardAdapter.java
  7. 10
      app/src/main/java/gr/thmmy/mthmmy/activities/bookmarks/BookmarksActivity.java
  8. 4
      app/src/main/java/gr/thmmy/mthmmy/activities/create_content/NewTopicTask.java
  9. 4
      app/src/main/java/gr/thmmy/mthmmy/activities/downloads/DownloadsActivity.java
  10. 17
      app/src/main/java/gr/thmmy/mthmmy/activities/downloads/DownloadsAdapter.java
  11. 20
      app/src/main/java/gr/thmmy/mthmmy/activities/main/MainActivity.java
  12. 2
      app/src/main/java/gr/thmmy/mthmmy/activities/main/unread/UnreadFragment.java
  13. 12
      app/src/main/java/gr/thmmy/mthmmy/activities/profile/ProfileActivity.java
  14. 23
      app/src/main/java/gr/thmmy/mthmmy/activities/profile/stats/StatsFragment.java
  15. 5
      app/src/main/java/gr/thmmy/mthmmy/activities/profile/summary/SummaryFragment.java
  16. 4
      app/src/main/java/gr/thmmy/mthmmy/activities/settings/SettingsFragment.java
  17. 16
      app/src/main/java/gr/thmmy/mthmmy/activities/shoutbox/ShoutAdapter.java
  18. 4
      app/src/main/java/gr/thmmy/mthmmy/activities/topic/TopicActivity.java
  19. 39
      app/src/main/java/gr/thmmy/mthmmy/activities/topic/TopicAdapter.java
  20. 4
      app/src/main/java/gr/thmmy/mthmmy/activities/topic/tasks/EditTask.java
  21. 4
      app/src/main/java/gr/thmmy/mthmmy/activities/topic/tasks/ReplyTask.java
  22. 20
      app/src/main/java/gr/thmmy/mthmmy/activities/upload/UploadActivity.java
  23. 5
      app/src/main/java/gr/thmmy/mthmmy/activities/upload/multipart/MultipartUploadTask.java
  24. 53
      app/src/main/java/gr/thmmy/mthmmy/base/BaseActivity.java
  25. 52
      app/src/main/java/gr/thmmy/mthmmy/base/BaseApplication.java
  26. 2
      app/src/main/java/gr/thmmy/mthmmy/base/BaseFragment.java
  27. 4
      app/src/main/java/gr/thmmy/mthmmy/model/Category.java
  28. 4
      app/src/main/java/gr/thmmy/mthmmy/services/DownloadHelper.java
  29. 48
      app/src/main/java/gr/thmmy/mthmmy/services/NotificationService.java
  30. 6
      app/src/main/java/gr/thmmy/mthmmy/session/LogoutTask.java
  31. 6
      app/src/main/java/gr/thmmy/mthmmy/session/MarkAsReadTask.java
  32. 4
      app/src/main/java/gr/thmmy/mthmmy/utils/DateTimeUtils.java
  33. 19
      app/src/main/java/gr/thmmy/mthmmy/utils/FileUtils.java
  34. 14
      app/src/main/java/gr/thmmy/mthmmy/utils/HTMLUtils.java
  35. 4
      app/src/main/java/gr/thmmy/mthmmy/utils/ui/ImageDownloadDialogBuilder.java
  36. 8
      app/src/main/java/gr/thmmy/mthmmy/views/ReactiveWebView.java
  37. 4
      app/src/main/java/gr/thmmy/mthmmy/views/RelativeTimeTextView.java
  38. 33
      app/src/main/java/gr/thmmy/mthmmy/views/editorview/EditorView.java
  39. 52
      app/src/main/res/layout-v23/activity_topic_overflow_menu.xml
  40. 10
      app/src/main/res/layout/activity_topic_overflow_menu.xml
  41. 8
      app/src/test/java/gr/thmmy/mthmmy/utils/DateTimeUtilsTest.java
  42. 10
      app/src/test/java/gr/thmmy/mthmmy/utils/UploadsCoursesJSONReadingTest.java
  43. 14
      app/src/test/java/gr/thmmy/mthmmy/utils/parsing/ThmmyDateTimeParserTest.java
  44. 26
      build.gradle
  45. 11
      emojis/build.gradle
  46. 3
      emojis/src/main/AndroidManifest.xml
  47. 4
      gradle/wrapper/gradle-wrapper.properties

2
README.md

@ -11,7 +11,7 @@ A mobile app for [thmmy.gr](https://www.thmmy.gr).
## Requirements ## Requirements
mTHMMY can be installed on any smartphone with Android 5.0 Lollipop or newer. mTHMMY can be installed on any smartphone with Android 6.0 (M) or newer.
## Download ## Download

11
app/build.gradle

@ -7,13 +7,12 @@ apply plugin: 'com.google.gms.google-services'
apply plugin: 'com.google.firebase.crashlytics' apply plugin: 'com.google.firebase.crashlytics'
android { android {
compileSdkVersion 31 compileSdkVersion 33
buildToolsVersion = '30.0.2'
defaultConfig { defaultConfig {
applicationId "gr.thmmy.mthmmy" applicationId "gr.thmmy.mthmmy"
minSdkVersion 21 minSdkVersion 23
targetSdkVersion 30 targetSdkVersion 33
versionCode 31 versionCode 31
versionName "2.1.0" versionName "2.1.0"
archivesBaseName = "mTHMMY-v$versionName" archivesBaseName = "mTHMMY-v$versionName"
@ -45,6 +44,8 @@ android {
sourceCompatibility JavaVersion.VERSION_1_8 sourceCompatibility JavaVersion.VERSION_1_8
targetCompatibility JavaVersion.VERSION_1_8 targetCompatibility JavaVersion.VERSION_1_8
} }
namespace 'gr.thmmy.mthmmy'
} }
def firebaseReleaseProjectId = "mthmmy-release-3aef0" def firebaseReleaseProjectId = "mthmmy-release-3aef0"
@ -92,7 +93,7 @@ dependencies {
implementation 'com.google.firebase:firebase-crashlytics' implementation 'com.google.firebase:firebase-crashlytics'
implementation 'com.google.firebase:firebase-messaging' implementation 'com.google.firebase:firebase-messaging'
implementation 'com.google.code.gson:gson:2.8.8' implementation 'com.google.code.gson:gson:2.8.8'
implementation 'com.snatik:storage:2.1.0' implementation 'com.snatik:storage:2.1.0' //TODO: Replace (e.g. with https://github.com/anggrayudi/SimpleStorage)
implementation 'com.squareup.okhttp3:okhttp:3.14.9' implementation 'com.squareup.okhttp3:okhttp:3.14.9'
implementation 'org.jsoup:jsoup:1.14.2' implementation 'org.jsoup:jsoup:1.14.2'
implementation 'joda-time:joda-time:2.10.10' implementation 'joda-time:joda-time:2.10.10'

4
app/gradle/grgit.gradle

@ -2,11 +2,11 @@ import org.ajoberstar.grgit.Grgit
buildscript { buildscript {
repositories { repositories {
jcenter() mavenCentral()
} }
dependencies { dependencies {
classpath 'org.ajoberstar.grgit:grgit-core:3.1.1' classpath 'org.ajoberstar.grgit:grgit-core:5.0.0'
} }
} }

2
app/src/main/AndroidManifest.xml

@ -1,11 +1,11 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android" <manifest xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools" xmlns:tools="http://schemas.android.com/tools"
package="gr.thmmy.mthmmy"
android:installLocation="auto"> android:installLocation="auto">
<uses-permission android:name="android.permission.INTERNET" /> <uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" /> <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.POST_NOTIFICATIONS" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" /> <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" /> <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.WAKE_LOCK" /> <uses-permission android:name="android.permission.WAKE_LOCK" />

16
app/src/main/java/gr/thmmy/mthmmy/activities/LoginActivity.java

@ -1,5 +1,13 @@
package gr.thmmy.mthmmy.activities; package gr.thmmy.mthmmy.activities;
import static gr.thmmy.mthmmy.session.SessionManager.BANNED_USER;
import static gr.thmmy.mthmmy.session.SessionManager.CONNECTION_ERROR;
import static gr.thmmy.mthmmy.session.SessionManager.EXCEPTION;
import static gr.thmmy.mthmmy.session.SessionManager.FAILURE;
import static gr.thmmy.mthmmy.session.SessionManager.SUCCESS;
import static gr.thmmy.mthmmy.session.SessionManager.WRONG_PASSWORD;
import static gr.thmmy.mthmmy.session.SessionManager.WRONG_USER;
import android.content.Intent; import android.content.Intent;
import android.os.AsyncTask; import android.os.AsyncTask;
import android.os.Bundle; import android.os.Bundle;
@ -22,14 +30,6 @@ import gr.thmmy.mthmmy.activities.main.MainActivity;
import gr.thmmy.mthmmy.base.BaseActivity; import gr.thmmy.mthmmy.base.BaseActivity;
import gr.thmmy.mthmmy.base.BaseApplication; import gr.thmmy.mthmmy.base.BaseApplication;
import static gr.thmmy.mthmmy.session.SessionManager.BANNED_USER;
import static gr.thmmy.mthmmy.session.SessionManager.CONNECTION_ERROR;
import static gr.thmmy.mthmmy.session.SessionManager.EXCEPTION;
import static gr.thmmy.mthmmy.session.SessionManager.FAILURE;
import static gr.thmmy.mthmmy.session.SessionManager.SUCCESS;
import static gr.thmmy.mthmmy.session.SessionManager.WRONG_PASSWORD;
import static gr.thmmy.mthmmy.session.SessionManager.WRONG_USER;
public class LoginActivity extends BaseActivity { public class LoginActivity extends BaseActivity {
//-----------------------------------------CLASS VARIABLES------------------------------------------ //-----------------------------------------CLASS VARIABLES------------------------------------------

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

@ -1,5 +1,10 @@
package gr.thmmy.mthmmy.activities.board; package gr.thmmy.mthmmy.activities.board;
import static gr.thmmy.mthmmy.activities.board.BoardActivity.BUNDLE_BOARD_TITLE;
import static gr.thmmy.mthmmy.activities.board.BoardActivity.BUNDLE_BOARD_URL;
import static gr.thmmy.mthmmy.activities.topic.TopicActivity.BUNDLE_TOPIC_TITLE;
import static gr.thmmy.mthmmy.activities.topic.TopicActivity.BUNDLE_TOPIC_URL;
import android.content.Context; import android.content.Context;
import android.content.Intent; import android.content.Intent;
import android.graphics.Typeface; import android.graphics.Typeface;
@ -22,11 +27,6 @@ import gr.thmmy.mthmmy.model.Board;
import gr.thmmy.mthmmy.model.Topic; import gr.thmmy.mthmmy.model.Topic;
import me.zhanghai.android.materialprogressbar.MaterialProgressBar; import me.zhanghai.android.materialprogressbar.MaterialProgressBar;
import static gr.thmmy.mthmmy.activities.board.BoardActivity.BUNDLE_BOARD_TITLE;
import static gr.thmmy.mthmmy.activities.board.BoardActivity.BUNDLE_BOARD_URL;
import static gr.thmmy.mthmmy.activities.topic.TopicActivity.BUNDLE_TOPIC_TITLE;
import static gr.thmmy.mthmmy.activities.topic.TopicActivity.BUNDLE_TOPIC_URL;
/** /**
* {@link RecyclerView.Adapter} that can display a {@link gr.thmmy.mthmmy.model.Board}. * {@link RecyclerView.Adapter} that can display a {@link gr.thmmy.mthmmy.model.Board}.
*/ */

10
app/src/main/java/gr/thmmy/mthmmy/activities/bookmarks/BookmarksActivity.java

@ -1,5 +1,10 @@
package gr.thmmy.mthmmy.activities.bookmarks; package gr.thmmy.mthmmy.activities.bookmarks;
import static gr.thmmy.mthmmy.activities.board.BoardActivity.BUNDLE_BOARD_TITLE;
import static gr.thmmy.mthmmy.activities.board.BoardActivity.BUNDLE_BOARD_URL;
import static gr.thmmy.mthmmy.activities.topic.TopicActivity.BUNDLE_TOPIC_TITLE;
import static gr.thmmy.mthmmy.activities.topic.TopicActivity.BUNDLE_TOPIC_URL;
import android.content.Intent; import android.content.Intent;
import android.os.Bundle; import android.os.Bundle;
import android.widget.Toast; import android.widget.Toast;
@ -23,11 +28,6 @@ import gr.thmmy.mthmmy.base.BaseActivity;
import gr.thmmy.mthmmy.base.BaseApplication; import gr.thmmy.mthmmy.base.BaseApplication;
import gr.thmmy.mthmmy.model.Bookmark; import gr.thmmy.mthmmy.model.Bookmark;
import static gr.thmmy.mthmmy.activities.board.BoardActivity.BUNDLE_BOARD_TITLE;
import static gr.thmmy.mthmmy.activities.board.BoardActivity.BUNDLE_BOARD_URL;
import static gr.thmmy.mthmmy.activities.topic.TopicActivity.BUNDLE_TOPIC_TITLE;
import static gr.thmmy.mthmmy.activities.topic.TopicActivity.BUNDLE_TOPIC_URL;
public class BookmarksActivity extends BaseActivity { public class BookmarksActivity extends BaseActivity {
private static final String TOPIC_URL = forumUrl + "index.php?topic="; private static final String TOPIC_URL = forumUrl + "index.php?topic=";
private static final String BOARD_URL = forumUrl + "index.php?board="; private static final String BOARD_URL = forumUrl + "index.php?board=";

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

@ -1,5 +1,7 @@
package gr.thmmy.mthmmy.activities.create_content; package gr.thmmy.mthmmy.activities.create_content;
import static gr.thmmy.mthmmy.activities.topic.Posting.replyStatus;
import android.os.AsyncTask; import android.os.AsyncTask;
import org.jsoup.Jsoup; import org.jsoup.Jsoup;
@ -15,8 +17,6 @@ import okhttp3.RequestBody;
import okhttp3.Response; import okhttp3.Response;
import timber.log.Timber; import timber.log.Timber;
import static gr.thmmy.mthmmy.activities.topic.Posting.replyStatus;
public class NewTopicTask extends AsyncTask<String, Void, Boolean> { public class NewTopicTask extends AsyncTask<String, Void, Boolean> {
private NewTopicTaskCallbacks listener; private NewTopicTaskCallbacks listener;

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

@ -1,5 +1,7 @@
package gr.thmmy.mthmmy.activities.downloads; package gr.thmmy.mthmmy.activities.downloads;
import static gr.thmmy.mthmmy.activities.upload.UploadActivity.BUNDLE_UPLOAD_CATEGORY;
import android.content.Intent; import android.content.Intent;
import android.net.Uri; import android.net.Uri;
import android.os.AsyncTask; import android.os.AsyncTask;
@ -37,8 +39,6 @@ import okhttp3.Request;
import okhttp3.Response; import okhttp3.Response;
import timber.log.Timber; import timber.log.Timber;
import static gr.thmmy.mthmmy.activities.upload.UploadActivity.BUNDLE_UPLOAD_CATEGORY;
public class DownloadsActivity extends BaseActivity implements DownloadsAdapter.OnLoadMoreListener { public class DownloadsActivity extends BaseActivity implements DownloadsAdapter.OnLoadMoreListener {
/** /**
* The key to use when putting download's url String to {@link DownloadsActivity}'s Bundle. * The key to use when putting download's url String to {@link DownloadsActivity}'s Bundle.

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

@ -1,9 +1,12 @@
package gr.thmmy.mthmmy.activities.downloads; package gr.thmmy.mthmmy.activities.downloads;
import static android.content.Intent.FLAG_ACTIVITY_NEW_TASK;
import static gr.thmmy.mthmmy.activities.downloads.DownloadsActivity.BUNDLE_DOWNLOADS_TITLE;
import static gr.thmmy.mthmmy.activities.downloads.DownloadsActivity.BUNDLE_DOWNLOADS_URL;
import android.content.Context; import android.content.Context;
import android.content.Intent; import android.content.Intent;
import android.graphics.Typeface; import android.graphics.Typeface;
import android.os.Build;
import android.os.Bundle; import android.os.Bundle;
import android.view.LayoutInflater; import android.view.LayoutInflater;
import android.view.View; import android.view.View;
@ -25,10 +28,6 @@ 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 static android.content.Intent.FLAG_ACTIVITY_NEW_TASK;
import static gr.thmmy.mthmmy.activities.downloads.DownloadsActivity.BUNDLE_DOWNLOADS_TITLE;
import static gr.thmmy.mthmmy.activities.downloads.DownloadsActivity.BUNDLE_DOWNLOADS_URL;
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;
private final int VIEW_TYPE_LOADING = 1; private final int VIEW_TYPE_LOADING = 1;
@ -132,13 +131,7 @@ class DownloadsAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> {
} }
}); });
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) { downloadViewHolder.upperLinear.setBackgroundColor(context.getResources().getColor(R.color.background, null));
downloadViewHolder.upperLinear.setBackgroundColor(context.getResources().getColor(R.color.background, null));
}
else {
//noinspection deprecation
downloadViewHolder.upperLinear.setBackgroundColor(context.getResources().getColor(R.color.background));
}
downloadViewHolder.informationExpandable.setVisibility(View.VISIBLE); downloadViewHolder.informationExpandable.setVisibility(View.VISIBLE);
downloadViewHolder.informationExpandableBtn.setVisibility(View.GONE); downloadViewHolder.informationExpandableBtn.setVisibility(View.GONE);
downloadViewHolder.informationExpandableBtn.setEnabled(false); downloadViewHolder.informationExpandableBtn.setEnabled(false);

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

@ -1,5 +1,15 @@
package gr.thmmy.mthmmy.activities.main; package gr.thmmy.mthmmy.activities.main;
import static gr.thmmy.mthmmy.activities.board.BoardActivity.BUNDLE_BOARD_TITLE;
import static gr.thmmy.mthmmy.activities.board.BoardActivity.BUNDLE_BOARD_URL;
import static gr.thmmy.mthmmy.activities.downloads.DownloadsActivity.BUNDLE_DOWNLOADS_TITLE;
import static gr.thmmy.mthmmy.activities.downloads.DownloadsActivity.BUNDLE_DOWNLOADS_URL;
import static gr.thmmy.mthmmy.activities.profile.ProfileActivity.BUNDLE_PROFILE_THUMBNAIL_URL;
import static gr.thmmy.mthmmy.activities.profile.ProfileActivity.BUNDLE_PROFILE_URL;
import static gr.thmmy.mthmmy.activities.profile.ProfileActivity.BUNDLE_PROFILE_USERNAME;
import static gr.thmmy.mthmmy.activities.topic.TopicActivity.BUNDLE_TOPIC_TITLE;
import static gr.thmmy.mthmmy.activities.topic.TopicActivity.BUNDLE_TOPIC_URL;
import android.content.Intent; import android.content.Intent;
import android.content.SharedPreferences; import android.content.SharedPreferences;
import android.net.Uri; import android.net.Uri;
@ -37,16 +47,6 @@ import gr.thmmy.mthmmy.model.ThmmyPage;
import gr.thmmy.mthmmy.model.TopicSummary; import gr.thmmy.mthmmy.model.TopicSummary;
import timber.log.Timber; import timber.log.Timber;
import static gr.thmmy.mthmmy.activities.board.BoardActivity.BUNDLE_BOARD_TITLE;
import static gr.thmmy.mthmmy.activities.board.BoardActivity.BUNDLE_BOARD_URL;
import static gr.thmmy.mthmmy.activities.downloads.DownloadsActivity.BUNDLE_DOWNLOADS_TITLE;
import static gr.thmmy.mthmmy.activities.downloads.DownloadsActivity.BUNDLE_DOWNLOADS_URL;
import static gr.thmmy.mthmmy.activities.profile.ProfileActivity.BUNDLE_PROFILE_THUMBNAIL_URL;
import static gr.thmmy.mthmmy.activities.profile.ProfileActivity.BUNDLE_PROFILE_URL;
import static gr.thmmy.mthmmy.activities.profile.ProfileActivity.BUNDLE_PROFILE_USERNAME;
import static gr.thmmy.mthmmy.activities.topic.TopicActivity.BUNDLE_TOPIC_TITLE;
import static gr.thmmy.mthmmy.activities.topic.TopicActivity.BUNDLE_TOPIC_URL;
public class MainActivity extends BaseActivity implements RecentFragment.RecentFragmentInteractionListener, ForumFragment.ForumFragmentInteractionListener, UnreadFragment.UnreadFragmentInteractionListener { public class MainActivity extends BaseActivity implements RecentFragment.RecentFragmentInteractionListener, ForumFragment.ForumFragmentInteractionListener, UnreadFragment.UnreadFragmentInteractionListener {
//-----------------------------------------CLASS VARIABLES------------------------------------------ //-----------------------------------------CLASS VARIABLES------------------------------------------

2
app/src/main/java/gr/thmmy/mthmmy/activities/main/unread/UnreadFragment.java

@ -244,7 +244,7 @@ public class UnreadFragment extends BaseFragment {
if (loadedPages < numberOfPages) { if (loadedPages < numberOfPages) {
unreadTask = new UnreadTask(this::onUnreadTaskStarted, UnreadFragment.this::onUnreadTaskCancelled, this::onUnreadTaskFinished); unreadTask = new UnreadTask(this::onUnreadTaskStarted, UnreadFragment.this::onUnreadTaskCancelled, this::onUnreadTaskFinished);
assert SessionManager.unreadUrl != null; assert SessionManager.unreadUrl != null;
unreadTask.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR, SessionManager.unreadUrl.toString() + ";start=" + loadedPages * 20); unreadTask.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR, SessionManager.unreadUrl + ";start=" + loadedPages * 20);
} }
else else
hideProgressUI(); hideProgressUI();

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

@ -1,5 +1,11 @@
package gr.thmmy.mthmmy.activities.profile; package gr.thmmy.mthmmy.activities.profile;
import static gr.thmmy.mthmmy.activities.topic.TopicActivity.BUNDLE_TOPIC_TITLE;
import static gr.thmmy.mthmmy.activities.topic.TopicActivity.BUNDLE_TOPIC_URL;
import static gr.thmmy.mthmmy.utils.parsing.ParseHelpers.emojiTagToHtml;
import static gr.thmmy.mthmmy.utils.ui.GlideUtils.isValidContextForGlide;
import static gr.thmmy.mthmmy.utils.ui.PhotoViewUtils.displayPhotoViewImage;
import android.content.Intent; import android.content.Intent;
import android.graphics.Color; import android.graphics.Color;
import android.graphics.Typeface; import android.graphics.Typeface;
@ -54,12 +60,6 @@ import me.zhanghai.android.materialprogressbar.MaterialProgressBar;
import okhttp3.Response; import okhttp3.Response;
import timber.log.Timber; import timber.log.Timber;
import static gr.thmmy.mthmmy.activities.topic.TopicActivity.BUNDLE_TOPIC_TITLE;
import static gr.thmmy.mthmmy.activities.topic.TopicActivity.BUNDLE_TOPIC_URL;
import static gr.thmmy.mthmmy.utils.parsing.ParseHelpers.emojiTagToHtml;
import static gr.thmmy.mthmmy.utils.ui.GlideUtils.isValidContextForGlide;
import static gr.thmmy.mthmmy.utils.ui.PhotoViewUtils.displayPhotoViewImage;
/** /**
* Activity for user profile. When creating an Intent of this activity you need to bundle a <b>String</b> * Activity for user profile. When creating an Intent of this activity you need to bundle a <b>String</b>
* containing this user's profile url using the key {@link #BUNDLE_PROFILE_URL}, a <b>String</b> containing * containing this user's profile url using the key {@link #BUNDLE_PROFILE_URL}, a <b>String</b> containing

23
app/src/main/java/gr/thmmy/mthmmy/activities/profile/stats/StatsFragment.java

@ -2,7 +2,6 @@ package gr.thmmy.mthmmy.activities.profile.stats;
import android.graphics.Color; import android.graphics.Color;
import android.os.AsyncTask; import android.os.AsyncTask;
import android.os.Build;
import android.os.Bundle; import android.os.Bundle;
import android.view.LayoutInflater; import android.view.LayoutInflater;
import android.view.View; import android.view.View;
@ -230,7 +229,6 @@ public class StatsFragment extends Fragment {
private void populateLayout() { private void populateLayout() {
onLoadingListener.onLoadingStats(true); onLoadingListener.onLoadingStats(true);
;
((TextView) mainContent.findViewById(R.id.general_statistics_title)) ((TextView) mainContent.findViewById(R.id.general_statistics_title))
.setText(generalStatisticsTitle); .setText(generalStatisticsTitle);
((TextView) mainContent.findViewById(R.id.general_statistics)) ((TextView) mainContent.findViewById(R.id.general_statistics))
@ -296,14 +294,9 @@ public class StatsFragment extends Fragment {
mostPopularBoardsByPostsChartYAxis.setGranularity(1f); mostPopularBoardsByPostsChartYAxis.setGranularity(1f);
BarDataSet mostPopularBoardsByPostsDataSet = new BarDataSet(mostPopularBoardsByPosts, null); BarDataSet mostPopularBoardsByPostsDataSet = new BarDataSet(mostPopularBoardsByPosts, null);
if (isAdded()) { if (isAdded())
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) { mostPopularBoardsByPostsDataSet.setColors(getResources().getColor(R.color.accent, null));
mostPopularBoardsByPostsDataSet.setColors(getResources().getColor(R.color.accent, null));
}
else
//noinspection deprecation
mostPopularBoardsByPostsDataSet.setColors(getResources().getColor(R.color.accent));
}
mostPopularBoardsByPostsDataSet.setDrawValues(false); mostPopularBoardsByPostsDataSet.setDrawValues(false);
mostPopularBoardsByPostsDataSet.setValueTextColor(Color.WHITE); mostPopularBoardsByPostsDataSet.setValueTextColor(Color.WHITE);
@ -338,14 +331,8 @@ public class StatsFragment extends Fragment {
mostPopularBoardsByActivityChartYAxis.setLabelCount(10, false); mostPopularBoardsByActivityChartYAxis.setLabelCount(10, false);
BarDataSet mostPopularBoardsByActivityDataSet = new BarDataSet(mostPopularBoardsByActivity, null); BarDataSet mostPopularBoardsByActivityDataSet = new BarDataSet(mostPopularBoardsByActivity, null);
if (isAdded()) { if (isAdded())
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) { mostPopularBoardsByActivityDataSet.setColors(getResources().getColor(R.color.accent, null));
mostPopularBoardsByActivityDataSet.setColors(getResources().getColor(R.color.accent, null));
}
else
//noinspection deprecation
mostPopularBoardsByActivityDataSet.setColors(getResources().getColor(R.color.accent));
}
mostPopularBoardsByActivityDataSet.setDrawValues(false); mostPopularBoardsByActivityDataSet.setDrawValues(false);
mostPopularBoardsByActivityDataSet.setValueTextColor(Color.WHITE); mostPopularBoardsByActivityDataSet.setValueTextColor(Color.WHITE);

5
app/src/main/java/gr/thmmy/mthmmy/activities/profile/summary/SummaryFragment.java

@ -189,10 +189,7 @@ public class SummaryFragment extends Fragment {
&& value.contains("@")) || key.startsWith("Website") || key.startsWith("Ιστοτόπος")) && value.contains("@")) || key.startsWith("Website") || key.startsWith("Ιστοτόπος"))
textView.setMovementMethod(LinkMovementMethod.getInstance()); textView.setMovementMethod(LinkMovementMethod.getInstance());
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) textView.setTextColor(getResources().getColor(R.color.primary_text, null));
textView.setTextColor(getResources().getColor(R.color.primary_text, null));
else
textView.setTextColor(getResources().getColor(R.color.primary_text));
String textViewContent = "<b>" + key + "</b> " + value; String textViewContent = "<b>" + key + "</b> " + value;

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

@ -1,5 +1,7 @@
package gr.thmmy.mthmmy.activities.settings; package gr.thmmy.mthmmy.activities.settings;
import static gr.thmmy.mthmmy.activities.settings.SettingsActivity.DEFAULT_HOME_TAB;
import android.app.Activity; import android.app.Activity;
import android.content.Context; import android.content.Context;
import android.content.Intent; import android.content.Intent;
@ -22,8 +24,6 @@ import gr.thmmy.mthmmy.R;
import gr.thmmy.mthmmy.base.BaseApplication; import gr.thmmy.mthmmy.base.BaseApplication;
import timber.log.Timber; import timber.log.Timber;
import static gr.thmmy.mthmmy.activities.settings.SettingsActivity.DEFAULT_HOME_TAB;
public class SettingsFragment extends PreferenceFragmentCompat implements SharedPreferences.OnSharedPreferenceChangeListener { public class SettingsFragment extends PreferenceFragmentCompat implements SharedPreferences.OnSharedPreferenceChangeListener {
private enum PREFS_TYPE { private enum PREFS_TYPE {
NOT_SET, USER, GUEST NOT_SET, USER, GUEST

16
app/src/main/java/gr/thmmy/mthmmy/activities/shoutbox/ShoutAdapter.java

@ -1,5 +1,13 @@
package gr.thmmy.mthmmy.activities.shoutbox; package gr.thmmy.mthmmy.activities.shoutbox;
import static android.content.Intent.FLAG_ACTIVITY_NEW_TASK;
import static gr.thmmy.mthmmy.activities.board.BoardActivity.BUNDLE_BOARD_TITLE;
import static gr.thmmy.mthmmy.activities.board.BoardActivity.BUNDLE_BOARD_URL;
import static gr.thmmy.mthmmy.activities.profile.ProfileActivity.BUNDLE_PROFILE_THUMBNAIL_URL;
import static gr.thmmy.mthmmy.activities.profile.ProfileActivity.BUNDLE_PROFILE_URL;
import static gr.thmmy.mthmmy.activities.profile.ProfileActivity.BUNDLE_PROFILE_USERNAME;
import static gr.thmmy.mthmmy.activities.topic.TopicActivity.BUNDLE_TOPIC_URL;
import android.content.Context; import android.content.Context;
import android.content.Intent; import android.content.Intent;
import android.graphics.Color; import android.graphics.Color;
@ -24,14 +32,6 @@ import gr.thmmy.mthmmy.model.ThmmyPage;
import gr.thmmy.mthmmy.views.CustomRecyclerView; import gr.thmmy.mthmmy.views.CustomRecyclerView;
import gr.thmmy.mthmmy.views.ReactiveWebView; import gr.thmmy.mthmmy.views.ReactiveWebView;
import static android.content.Intent.FLAG_ACTIVITY_NEW_TASK;
import static gr.thmmy.mthmmy.activities.board.BoardActivity.BUNDLE_BOARD_TITLE;
import static gr.thmmy.mthmmy.activities.board.BoardActivity.BUNDLE_BOARD_URL;
import static gr.thmmy.mthmmy.activities.profile.ProfileActivity.BUNDLE_PROFILE_THUMBNAIL_URL;
import static gr.thmmy.mthmmy.activities.profile.ProfileActivity.BUNDLE_PROFILE_URL;
import static gr.thmmy.mthmmy.activities.profile.ProfileActivity.BUNDLE_PROFILE_USERNAME;
import static gr.thmmy.mthmmy.activities.topic.TopicActivity.BUNDLE_TOPIC_URL;
public class ShoutAdapter extends CustomRecyclerView.Adapter<ShoutAdapter.ShoutViewHolder> { public class ShoutAdapter extends CustomRecyclerView.Adapter<ShoutAdapter.ShoutViewHolder> {
private Context context; private Context context;
private Shout[] shouts; private Shout[] shouts;

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

@ -1,5 +1,7 @@
package gr.thmmy.mthmmy.activities.topic; package gr.thmmy.mthmmy.activities.topic;
import static gr.thmmy.mthmmy.services.NotificationService.NEW_POST_TAG;
import android.annotation.SuppressLint; import android.annotation.SuppressLint;
import android.app.NotificationManager; import android.app.NotificationManager;
import android.content.ClipData; import android.content.ClipData;
@ -60,8 +62,6 @@ import gr.thmmy.mthmmy.views.editorview.EmojiKeyboard;
import me.zhanghai.android.materialprogressbar.MaterialProgressBar; import me.zhanghai.android.materialprogressbar.MaterialProgressBar;
import timber.log.Timber; import timber.log.Timber;
import static gr.thmmy.mthmmy.services.NotificationService.NEW_POST_TAG;
/** /**
* Activity for parsing and rendering topics. When creating an Intent of this activity you need to * Activity for parsing and rendering topics. When creating an Intent of this activity you need to
* bundle a <b>String</b> containing this topic's url using the key {@link #BUNDLE_TOPIC_URL}. * bundle a <b>String</b> containing this topic's url using the key {@link #BUNDLE_TOPIC_URL}.

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

@ -1,5 +1,18 @@
package gr.thmmy.mthmmy.activities.topic; package gr.thmmy.mthmmy.activities.topic;
import static android.content.Intent.FLAG_ACTIVITY_NEW_TASK;
import static gr.thmmy.mthmmy.activities.board.BoardActivity.BUNDLE_BOARD_TITLE;
import static gr.thmmy.mthmmy.activities.board.BoardActivity.BUNDLE_BOARD_URL;
import static gr.thmmy.mthmmy.activities.profile.ProfileActivity.BUNDLE_PROFILE_THUMBNAIL_URL;
import static gr.thmmy.mthmmy.activities.profile.ProfileActivity.BUNDLE_PROFILE_URL;
import static gr.thmmy.mthmmy.activities.profile.ProfileActivity.BUNDLE_PROFILE_USERNAME;
import static gr.thmmy.mthmmy.activities.topic.TopicActivity.BUNDLE_TOPIC_URL;
import static gr.thmmy.mthmmy.activities.topic.TopicParser.USER_COLOR_WHITE;
import static gr.thmmy.mthmmy.activities.topic.TopicParser.USER_COLOR_YELLOW;
import static gr.thmmy.mthmmy.base.BaseActivity.getSessionManager;
import static gr.thmmy.mthmmy.utils.FileUtils.faIconFromFilename;
import static gr.thmmy.mthmmy.utils.ui.GlideUtils.isValidContextForGlide;
import android.annotation.SuppressLint; import android.annotation.SuppressLint;
import android.annotation.TargetApi; import android.annotation.TargetApi;
import android.content.Context; import android.content.Context;
@ -77,19 +90,6 @@ import gr.thmmy.mthmmy.views.editorview.EditorView;
import gr.thmmy.mthmmy.views.editorview.IEmojiKeyboard; import gr.thmmy.mthmmy.views.editorview.IEmojiKeyboard;
import timber.log.Timber; import timber.log.Timber;
import static android.content.Intent.FLAG_ACTIVITY_NEW_TASK;
import static gr.thmmy.mthmmy.activities.board.BoardActivity.BUNDLE_BOARD_TITLE;
import static gr.thmmy.mthmmy.activities.board.BoardActivity.BUNDLE_BOARD_URL;
import static gr.thmmy.mthmmy.activities.profile.ProfileActivity.BUNDLE_PROFILE_THUMBNAIL_URL;
import static gr.thmmy.mthmmy.activities.profile.ProfileActivity.BUNDLE_PROFILE_URL;
import static gr.thmmy.mthmmy.activities.profile.ProfileActivity.BUNDLE_PROFILE_USERNAME;
import static gr.thmmy.mthmmy.activities.topic.TopicActivity.BUNDLE_TOPIC_URL;
import static gr.thmmy.mthmmy.activities.topic.TopicParser.USER_COLOR_WHITE;
import static gr.thmmy.mthmmy.activities.topic.TopicParser.USER_COLOR_YELLOW;
import static gr.thmmy.mthmmy.base.BaseActivity.getSessionManager;
import static gr.thmmy.mthmmy.utils.FileUtils.faIconFromFilename;
import static gr.thmmy.mthmmy.utils.ui.GlideUtils.isValidContextForGlide;
/** /**
* Custom {@link RecyclerView.Adapter} used for topics. * Custom {@link RecyclerView.Adapter} used for topics.
*/ */
@ -393,11 +393,7 @@ class TopicAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> {
if (currentPost.getAttachedFiles() != null && currentPost.getAttachedFiles().size() != 0) { if (currentPost.getAttachedFiles() != null && currentPost.getAttachedFiles().size() != 0) {
int filesTextColor; int filesTextColor;
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) { filesTextColor = context.getResources().getColor(R.color.accent, null);
filesTextColor = context.getResources().getColor(R.color.accent, null);
}
else
filesTextColor = context.getResources().getColor(R.color.accent);
for (final ThmmyFile attachedFile : currentPost.getAttachedFiles()) { for (final ThmmyFile attachedFile : currentPost.getAttachedFiles()) {
final TextView attached = new TextView(context); final TextView attached = new TextView(context);
@ -417,11 +413,8 @@ class TopicAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> {
} }
if (currentPost.getLastEdit() != null && currentPost.getLastEdit().length() > 0) { if (currentPost.getLastEdit() != null && currentPost.getLastEdit().length() > 0) {
int lastEditTextColor; int lastEditTextColor;
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
lastEditTextColor = context.getResources().getColor(R.color.white, null); lastEditTextColor = context.getResources().getColor(R.color.white, null);
}
else
lastEditTextColor = context.getResources().getColor(R.color.white);
final TextView lastEdit = new TextView(context); final TextView lastEdit = new TextView(context);
lastEdit.setTextSize(12f); lastEdit.setTextSize(12f);

4
app/src/main/java/gr/thmmy/mthmmy/activities/topic/tasks/EditTask.java

@ -1,5 +1,7 @@
package gr.thmmy.mthmmy.activities.topic.tasks; package gr.thmmy.mthmmy.activities.topic.tasks;
import static gr.thmmy.mthmmy.activities.topic.Posting.replyStatus;
import android.os.AsyncTask; import android.os.AsyncTask;
import java.io.IOException; import java.io.IOException;
@ -12,8 +14,6 @@ import okhttp3.RequestBody;
import okhttp3.Response; import okhttp3.Response;
import timber.log.Timber; import timber.log.Timber;
import static gr.thmmy.mthmmy.activities.topic.Posting.replyStatus;
public class EditTask extends AsyncTask<String, Void, Boolean> { public class EditTask extends AsyncTask<String, Void, Boolean> {
private EditTaskCallbacks listener; private EditTaskCallbacks listener;
private int position; private int position;

4
app/src/main/java/gr/thmmy/mthmmy/activities/topic/tasks/ReplyTask.java

@ -1,5 +1,7 @@
package gr.thmmy.mthmmy.activities.topic.tasks; package gr.thmmy.mthmmy.activities.topic.tasks;
import static gr.thmmy.mthmmy.activities.topic.Posting.replyStatus;
import android.os.AsyncTask; import android.os.AsyncTask;
import java.io.IOException; import java.io.IOException;
@ -13,8 +15,6 @@ import okhttp3.RequestBody;
import okhttp3.Response; import okhttp3.Response;
import timber.log.Timber; import timber.log.Timber;
import static gr.thmmy.mthmmy.activities.topic.Posting.replyStatus;
public class ReplyTask extends AsyncTask<String, Void, Posting.REPLY_STATUS> { public class ReplyTask extends AsyncTask<String, Void, Posting.REPLY_STATUS> {
private ReplyTaskCallbacks listener; private ReplyTaskCallbacks listener;
private boolean includeAppSignature; private boolean includeAppSignature;

20
app/src/main/java/gr/thmmy/mthmmy/activities/upload/UploadActivity.java

@ -1,5 +1,15 @@
package gr.thmmy.mthmmy.activities.upload; package gr.thmmy.mthmmy.activities.upload;
import static gr.thmmy.mthmmy.activities.settings.SettingsActivity.UPLOADING_APP_SIGNATURE_ENABLE_KEY;
import static gr.thmmy.mthmmy.activities.upload.UploadFieldsBuilderActivity.BUNDLE_UPLOAD_FIELD_BUILDER_COURSE_GREEKLISH_NAME;
import static gr.thmmy.mthmmy.activities.upload.UploadFieldsBuilderActivity.BUNDLE_UPLOAD_FIELD_BUILDER_COURSE_MINIFIED_NAME;
import static gr.thmmy.mthmmy.activities.upload.UploadFieldsBuilderActivity.BUNDLE_UPLOAD_FIELD_BUILDER_COURSE_NAME;
import static gr.thmmy.mthmmy.activities.upload.UploadFieldsBuilderActivity.BUNDLE_UPLOAD_FIELD_BUILDER_SEMESTER;
import static gr.thmmy.mthmmy.activities.upload.UploadFieldsBuilderActivity.RESULT_DESCRIPTION;
import static gr.thmmy.mthmmy.activities.upload.UploadFieldsBuilderActivity.RESULT_FILENAME;
import static gr.thmmy.mthmmy.activities.upload.UploadFieldsBuilderActivity.RESULT_TITLE;
import static gr.thmmy.mthmmy.utils.FileUtils.faIconFromFilename;
import android.app.Activity; import android.app.Activity;
import android.app.PendingIntent; import android.app.PendingIntent;
import android.content.Context; import android.content.Context;
@ -74,16 +84,6 @@ import gr.thmmy.mthmmy.views.AppCompatSpinnerWithoutDefault;
import me.zhanghai.android.materialprogressbar.MaterialProgressBar; import me.zhanghai.android.materialprogressbar.MaterialProgressBar;
import timber.log.Timber; import timber.log.Timber;
import static gr.thmmy.mthmmy.activities.settings.SettingsActivity.UPLOADING_APP_SIGNATURE_ENABLE_KEY;
import static gr.thmmy.mthmmy.activities.upload.UploadFieldsBuilderActivity.BUNDLE_UPLOAD_FIELD_BUILDER_COURSE_GREEKLISH_NAME;
import static gr.thmmy.mthmmy.activities.upload.UploadFieldsBuilderActivity.BUNDLE_UPLOAD_FIELD_BUILDER_COURSE_MINIFIED_NAME;
import static gr.thmmy.mthmmy.activities.upload.UploadFieldsBuilderActivity.BUNDLE_UPLOAD_FIELD_BUILDER_COURSE_NAME;
import static gr.thmmy.mthmmy.activities.upload.UploadFieldsBuilderActivity.BUNDLE_UPLOAD_FIELD_BUILDER_SEMESTER;
import static gr.thmmy.mthmmy.activities.upload.UploadFieldsBuilderActivity.RESULT_DESCRIPTION;
import static gr.thmmy.mthmmy.activities.upload.UploadFieldsBuilderActivity.RESULT_FILENAME;
import static gr.thmmy.mthmmy.activities.upload.UploadFieldsBuilderActivity.RESULT_TITLE;
import static gr.thmmy.mthmmy.utils.FileUtils.faIconFromFilename;
public class UploadActivity extends BaseActivity { public class UploadActivity extends BaseActivity {
/** /**
* The key to use when putting upload's category String to {@link UploadActivity}'s Bundle. * The key to use when putting upload's category String to {@link UploadActivity}'s Bundle.

5
app/src/main/java/gr/thmmy/mthmmy/activities/upload/multipart/MultipartUploadTask.java

@ -11,6 +11,7 @@ import net.gotev.uploadservice.http.BodyWriter;
import java.io.IOException; import java.io.IOException;
import java.io.UnsupportedEncodingException; import java.io.UnsupportedEncodingException;
import java.nio.charset.Charset; import java.nio.charset.Charset;
import java.nio.charset.StandardCharsets;
/** /**
* Extended MultipartUploadTask from gotev/android-upload-service to include a fix for the parameter * Extended MultipartUploadTask from gotev/android-upload-service to include a fix for the parameter
@ -21,7 +22,7 @@ public class MultipartUploadTask extends HttpUploadTask {
static final String PARAM_UTF8_CHARSET = "multipartUtf8Charset"; static final String PARAM_UTF8_CHARSET = "multipartUtf8Charset";
private static final String BOUNDARY_SIGNATURE = "-------AndroidUploadService"; private static final String BOUNDARY_SIGNATURE = "-------AndroidUploadService";
private static final Charset US_ASCII = Charset.forName("US-ASCII"); private static final Charset US_ASCII = StandardCharsets.US_ASCII;
private static final String NEW_LINE = "\r\n"; private static final String NEW_LINE = "\r\n";
private static final String TWO_HYPHENS = "--"; private static final String TWO_HYPHENS = "--";
@ -42,7 +43,7 @@ public class MultipartUploadTask extends HttpUploadTask {
boundaryBytes = (TWO_HYPHENS + boundary + NEW_LINE).getBytes(US_ASCII); boundaryBytes = (TWO_HYPHENS + boundary + NEW_LINE).getBytes(US_ASCII);
trailerBytes = (TWO_HYPHENS + boundary + TWO_HYPHENS + NEW_LINE).getBytes(US_ASCII); trailerBytes = (TWO_HYPHENS + boundary + TWO_HYPHENS + NEW_LINE).getBytes(US_ASCII);
charset = intent.getBooleanExtra(PARAM_UTF8_CHARSET, false) ? charset = intent.getBooleanExtra(PARAM_UTF8_CHARSET, false) ?
Charset.forName("UTF-8") : US_ASCII; StandardCharsets.UTF_8 : US_ASCII;
httpParams.addHeader("Connection", "Keep-Alive"); httpParams.addHeader("Connection", "Keep-Alive");
httpParams.addHeader("Content-Type", "multipart/form-data; boundary=" + boundary); httpParams.addHeader("Content-Type", "multipart/form-data; boundary=" + boundary);

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

@ -1,5 +1,15 @@
package gr.thmmy.mthmmy.base; package gr.thmmy.mthmmy.base;
import static android.content.Intent.FLAG_ACTIVITY_NEW_TASK;
import static gr.thmmy.mthmmy.activities.downloads.DownloadsActivity.BUNDLE_DOWNLOADS_TITLE;
import static gr.thmmy.mthmmy.activities.downloads.DownloadsActivity.BUNDLE_DOWNLOADS_URL;
import static gr.thmmy.mthmmy.activities.profile.ProfileActivity.BUNDLE_PROFILE_THUMBNAIL_URL;
import static gr.thmmy.mthmmy.activities.profile.ProfileActivity.BUNDLE_PROFILE_URL;
import static gr.thmmy.mthmmy.activities.profile.ProfileActivity.BUNDLE_PROFILE_USERNAME;
import static gr.thmmy.mthmmy.activities.settings.SettingsActivity.DEFAULT_HOME_TAB;
import static gr.thmmy.mthmmy.services.DownloadHelper.SAVE_DIR;
import static gr.thmmy.mthmmy.utils.FileUtils.getMimeType;
import android.Manifest; import android.Manifest;
import android.app.ProgressDialog; import android.app.ProgressDialog;
import android.content.Context; import android.content.Context;
@ -8,7 +18,6 @@ import android.content.SharedPreferences;
import android.content.pm.PackageManager; import android.content.pm.PackageManager;
import android.net.Uri; import android.net.Uri;
import android.os.AsyncTask; import android.os.AsyncTask;
import android.os.Build;
import android.os.Bundle; import android.os.Bundle;
import android.view.MenuItem; import android.view.MenuItem;
import android.view.View; import android.view.View;
@ -67,16 +76,6 @@ import ru.noties.markwon.Markwon;
import ru.noties.markwon.SpannableConfiguration; import ru.noties.markwon.SpannableConfiguration;
import timber.log.Timber; import timber.log.Timber;
import static android.content.Intent.FLAG_ACTIVITY_NEW_TASK;
import static gr.thmmy.mthmmy.activities.downloads.DownloadsActivity.BUNDLE_DOWNLOADS_TITLE;
import static gr.thmmy.mthmmy.activities.downloads.DownloadsActivity.BUNDLE_DOWNLOADS_URL;
import static gr.thmmy.mthmmy.activities.profile.ProfileActivity.BUNDLE_PROFILE_THUMBNAIL_URL;
import static gr.thmmy.mthmmy.activities.profile.ProfileActivity.BUNDLE_PROFILE_URL;
import static gr.thmmy.mthmmy.activities.profile.ProfileActivity.BUNDLE_PROFILE_USERNAME;
import static gr.thmmy.mthmmy.activities.settings.SettingsActivity.DEFAULT_HOME_TAB;
import static gr.thmmy.mthmmy.services.DownloadHelper.SAVE_DIR;
import static gr.thmmy.mthmmy.utils.FileUtils.getMimeType;
public abstract class BaseActivity extends AppCompatActivity { public abstract class BaseActivity extends AppCompatActivity {
// Client & Cookies // Client & Cookies
protected static OkHttpClient client; protected static OkHttpClient client;
@ -695,29 +694,23 @@ public abstract class BaseActivity extends AppCompatActivity {
//True if permissions are OK //True if permissions are OK
protected boolean checkPerms() { protected boolean checkPerms() {
if (Build.VERSION.SDK_INT > Build.VERSION_CODES.LOLLIPOP_MR1) { Timber.i("Checking storage permissions.");
Timber.i("Checking storage permissions."); String[] PERMISSIONS_STORAGE = {
String[] PERMISSIONS_STORAGE = { Manifest.permission.READ_EXTERNAL_STORAGE,
Manifest.permission.READ_EXTERNAL_STORAGE, Manifest.permission.WRITE_EXTERNAL_STORAGE};
Manifest.permission.WRITE_EXTERNAL_STORAGE};
return !(checkSelfPermission(PERMISSIONS_STORAGE[0]) == PackageManager.PERMISSION_DENIED ||
return !(checkSelfPermission(PERMISSIONS_STORAGE[0]) == PackageManager.PERMISSION_DENIED || checkSelfPermission(PERMISSIONS_STORAGE[1]) == PackageManager.PERMISSION_DENIED);
checkSelfPermission(PERMISSIONS_STORAGE[1]) == PackageManager.PERMISSION_DENIED);
}
return true;
} }
//Display popup for user to grant permission //Display popup for user to grant permission
protected void requestPerms(int code) { protected void requestPerms(int code) {
//Runtime permissions request for devices with API >= 23 String[] PERMISSIONS_STORAGE = {
if (Build.VERSION.SDK_INT > Build.VERSION_CODES.LOLLIPOP_MR1) { Manifest.permission.READ_EXTERNAL_STORAGE,
String[] PERMISSIONS_STORAGE = { Manifest.permission.WRITE_EXTERNAL_STORAGE};
Manifest.permission.READ_EXTERNAL_STORAGE,
Manifest.permission.WRITE_EXTERNAL_STORAGE}; Timber.i("Requesting storage permissions (code %d).", code);
requestPermissions(PERMISSIONS_STORAGE, code);
Timber.i("Requesting storage permissions (code %d).", code);
requestPermissions(PERMISSIONS_STORAGE, code);
}
} }
@Override @Override

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

@ -1,5 +1,10 @@
package gr.thmmy.mthmmy.base; 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.upload.UploadActivity.firebaseConfigUploadsCoursesKey;
import static gr.thmmy.mthmmy.utils.io.ResourceUtils.readJSONResourceToString;
import android.app.Application; import android.app.Application;
import android.content.Context; import android.content.Context;
import android.content.SharedPreferences; import android.content.SharedPreferences;
@ -45,16 +50,16 @@ import okhttp3.OkHttpClient;
import okhttp3.Request; import okhttp3.Request;
import timber.log.Timber; import timber.log.Timber;
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.upload.UploadActivity.firebaseConfigUploadsCoursesKey;
import static gr.thmmy.mthmmy.utils.io.ResourceUtils.readJSONResourceToString;
public class BaseApplication extends Application implements Executor{ public class BaseApplication extends Application implements Executor{
private static BaseApplication baseApplication; //BaseApplication singleton private static BaseApplication baseApplication; //BaseApplication singleton
private CrashReportingTree crashReportingTree; private CrashReportingTree crashReportingTree;
//Global variables
private static String forumUrl;
private static String forumHost;
private static String forumHostSimple;
//Firebase //Firebase
private static String firebaseProjectId; private static String firebaseProjectId;
private FirebaseAnalytics firebaseAnalytics; private FirebaseAnalytics firebaseAnalytics;
@ -71,27 +76,6 @@ public class BaseApplication extends Application implements Executor{
private static float widthDp; private static float widthDp;
private static int widthPxl, heightPxl; private static int widthPxl, heightPxl;
private static String forumUrl;
private static String forumHost;
private static String forumHostSimple;
public static BaseApplication getInstance() {
return baseApplication;
}
public static String getForumUrl() {
return forumUrl;
}
public static String getForumHost() {
return forumHost;
}
public static String getForumHostSimple() {
return forumHostSimple;
}
@Override @Override
public void onCreate() { public void onCreate() {
super.onCreate(); super.onCreate();
@ -231,6 +215,22 @@ public class BaseApplication extends Application implements Executor{
//-------------------- Getters -------------------- //-------------------- Getters --------------------
public static BaseApplication getInstance() {
return baseApplication;
}
public static String getForumUrl() {
return forumUrl;
}
public static String getForumHost() {
return forumHost;
}
public static String getForumHostSimple() {
return forumHostSimple;
}
public Context getContext() { public Context getContext() {
return getApplicationContext(); return getApplicationContext();
} }

2
app/src/main/java/gr/thmmy/mthmmy/base/BaseFragment.java

@ -31,7 +31,7 @@ public abstract class BaseFragment extends Fragment {
if (context instanceof FragmentInteractionListener) if (context instanceof FragmentInteractionListener)
fragmentInteractionListener = (FragmentInteractionListener) context; fragmentInteractionListener = (FragmentInteractionListener) context;
else else
throw new RuntimeException(context.toString() throw new RuntimeException(context
+ " must implement OnFragmentInteractionListener"); + " must implement OnFragmentInteractionListener");
} }

4
app/src/main/java/gr/thmmy/mthmmy/model/Category.java

@ -1,12 +1,12 @@
package gr.thmmy.mthmmy.model; package gr.thmmy.mthmmy.model;
import static android.R.attr.id;
import com.bignerdranch.expandablerecyclerview.model.Parent; import com.bignerdranch.expandablerecyclerview.model.Parent;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
import static android.R.attr.id;
public class Category implements Parent<Board> { public class Category implements Parent<Board> {
private final String title; private final String title;
private final String categoryURL; private final String categoryURL;

4
app/src/main/java/gr/thmmy/mthmmy/services/DownloadHelper.java

@ -1,5 +1,7 @@
package gr.thmmy.mthmmy.services; package gr.thmmy.mthmmy.services;
import static gr.thmmy.mthmmy.utils.FileUtils.getMimeType;
import android.app.DownloadManager; import android.app.DownloadManager;
import android.content.Context; import android.content.Context;
import android.net.Uri; import android.net.Uri;
@ -15,8 +17,6 @@ import gr.thmmy.mthmmy.model.ThmmyFile;
import okhttp3.Cookie; import okhttp3.Cookie;
import timber.log.Timber; import timber.log.Timber;
import static gr.thmmy.mthmmy.utils.FileUtils.getMimeType;
/** /**
* Not an actual service, but simply a helper class that adds a download to the queue of Android's * Not an actual service, but simply a helper class that adds a download to the queue of Android's
* DownloadManager system service. * DownloadManager system service.

48
app/src/main/java/gr/thmmy/mthmmy/services/NotificationService.java

@ -1,5 +1,17 @@
package gr.thmmy.mthmmy.services; package gr.thmmy.mthmmy.services;
import static androidx.core.app.NotificationCompat.PRIORITY_MAX;
import static gr.thmmy.mthmmy.activities.settings.SettingsActivity.NOTIFICATION_LED_KEY;
import static gr.thmmy.mthmmy.activities.settings.SettingsActivity.NOTIFICATION_VIBRATION_KEY;
import static gr.thmmy.mthmmy.activities.settings.SettingsFragment.SELECTED_RINGTONE;
import static gr.thmmy.mthmmy.activities.settings.SettingsFragment.SETTINGS_SHARED_PREFS;
import static gr.thmmy.mthmmy.activities.topic.TopicActivity.BUNDLE_TOPIC_TITLE;
import static gr.thmmy.mthmmy.activities.topic.TopicActivity.BUNDLE_TOPIC_URL;
import static gr.thmmy.mthmmy.base.BaseActivity.BOOKMARKED_BOARDS_KEY;
import static gr.thmmy.mthmmy.base.BaseActivity.BOOKMARKED_TOPICS_KEY;
import static gr.thmmy.mthmmy.base.BaseActivity.BOOKMARKS_SHARED_PREFS;
import static gr.thmmy.mthmmy.model.Bookmark.matchExistsById;
import android.app.Notification; import android.app.Notification;
import android.app.NotificationChannel; import android.app.NotificationChannel;
import android.app.NotificationManager; import android.app.NotificationManager;
@ -13,7 +25,6 @@ import android.os.Build;
import android.os.Bundle; import android.os.Bundle;
import android.service.notification.StatusBarNotification; import android.service.notification.StatusBarNotification;
import androidx.annotation.RequiresApi;
import androidx.core.app.NotificationCompat; import androidx.core.app.NotificationCompat;
import androidx.preference.PreferenceManager; import androidx.preference.PreferenceManager;
@ -34,18 +45,6 @@ import gr.thmmy.mthmmy.model.Bookmark;
import gr.thmmy.mthmmy.model.PostNotification; import gr.thmmy.mthmmy.model.PostNotification;
import timber.log.Timber; import timber.log.Timber;
import static androidx.core.app.NotificationCompat.PRIORITY_MAX;
import static gr.thmmy.mthmmy.activities.settings.SettingsActivity.NOTIFICATION_LED_KEY;
import static gr.thmmy.mthmmy.activities.settings.SettingsActivity.NOTIFICATION_VIBRATION_KEY;
import static gr.thmmy.mthmmy.activities.settings.SettingsFragment.SELECTED_RINGTONE;
import static gr.thmmy.mthmmy.activities.settings.SettingsFragment.SETTINGS_SHARED_PREFS;
import static gr.thmmy.mthmmy.activities.topic.TopicActivity.BUNDLE_TOPIC_TITLE;
import static gr.thmmy.mthmmy.activities.topic.TopicActivity.BUNDLE_TOPIC_URL;
import static gr.thmmy.mthmmy.base.BaseActivity.BOOKMARKED_BOARDS_KEY;
import static gr.thmmy.mthmmy.base.BaseActivity.BOOKMARKED_TOPICS_KEY;
import static gr.thmmy.mthmmy.base.BaseActivity.BOOKMARKS_SHARED_PREFS;
import static gr.thmmy.mthmmy.model.Bookmark.matchExistsById;
public class NotificationService extends FirebaseMessagingService { public class NotificationService extends FirebaseMessagingService {
private static final int buildVersion = Build.VERSION.SDK_INT; private static final int buildVersion = Build.VERSION.SDK_INT;
private static final int disabledNotifiationsLedColor = Color.argb(0, 0, 0, 0); private static final int disabledNotifiationsLedColor = Color.argb(0, 0, 0, 0);
@ -204,15 +203,13 @@ public class NotificationService extends FirebaseMessagingService {
int newPostsCount = 1; int newPostsCount = 1;
if (buildVersion >= Build.VERSION_CODES.M) { Notification existingNotification = getActiveNotification(notificationId);
Notification existingNotification = getActiveNotification(notificationId); if (existingNotification != null) {
if (existingNotification != null) { newPostsCount = existingNotification.extras.getInt(NEW_POSTS_COUNT) + 1;
newPostsCount = existingNotification.extras.getInt(NEW_POSTS_COUNT) + 1; if (isTopicNotification)
if (isTopicNotification) contentText = newPostsCount + " new posts";
contentText = newPostsCount + " new posts"; else
else contentText = newPostsCount + " new posts in " + postNotification.getTopicTitle();
contentText = newPostsCount + " new posts in " + postNotification.getTopicTitle();
}
} }
Bundle notificationExtras = new Bundle(); Bundle notificationExtras = new Bundle();
@ -250,10 +247,7 @@ public class NotificationService extends FirebaseMessagingService {
if (buildVersion < Build.VERSION_CODES.O) if (buildVersion < Build.VERSION_CODES.O)
notificationBuilder.setPriority(PRIORITY_MAX); notificationBuilder.setPriority(PRIORITY_MAX);
boolean createSummaryNotification = false; boolean createSummaryNotification = otherNotificationsExist(notificationId);
if (buildVersion >= Build.VERSION_CODES.M)
createSummaryNotification = otherNotificationsExist(notificationId);
NotificationCompat.Builder summaryNotificationBuilder = null; NotificationCompat.Builder summaryNotificationBuilder = null;
if (createSummaryNotification) { if (createSummaryNotification) {
@ -281,7 +275,6 @@ public class NotificationService extends FirebaseMessagingService {
notificationManager.notify(SUMMARY_TAG, 0, summaryNotificationBuilder.build()); notificationManager.notify(SUMMARY_TAG, 0, summaryNotificationBuilder.build());
} }
@RequiresApi(api = Build.VERSION_CODES.M)
private Notification getActiveNotification(int notificationId) { private Notification getActiveNotification(int notificationId) {
NotificationManager notificationManager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE); NotificationManager notificationManager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
if (notificationManager != null) { if (notificationManager != null) {
@ -295,7 +288,6 @@ public class NotificationService extends FirebaseMessagingService {
return null; return null;
} }
@RequiresApi(api = Build.VERSION_CODES.M)
private boolean otherNotificationsExist(int notificationId) { private boolean otherNotificationsExist(int notificationId) {
NotificationManager notificationManager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE); NotificationManager notificationManager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
if (notificationManager != null) { if (notificationManager != null) {

6
app/src/main/java/gr/thmmy/mthmmy/session/LogoutTask.java

@ -1,5 +1,8 @@
package gr.thmmy.mthmmy.session; package gr.thmmy.mthmmy.session;
import static gr.thmmy.mthmmy.session.SessionManager.baseLogoutLink;
import static gr.thmmy.mthmmy.session.SessionManager.indexUrl;
import org.jsoup.nodes.Document; import org.jsoup.nodes.Document;
import org.jsoup.select.Elements; import org.jsoup.select.Elements;
@ -11,9 +14,6 @@ import gr.thmmy.mthmmy.utils.parsing.ParseException;
import okhttp3.Response; import okhttp3.Response;
import timber.log.Timber; import timber.log.Timber;
import static gr.thmmy.mthmmy.session.SessionManager.baseLogoutLink;
import static gr.thmmy.mthmmy.session.SessionManager.indexUrl;
public class LogoutTask extends NetworkTask<Void> { public class LogoutTask extends NetworkTask<Void> {
private String logoutLink; private String logoutLink;

6
app/src/main/java/gr/thmmy/mthmmy/session/MarkAsReadTask.java

@ -1,5 +1,8 @@
package gr.thmmy.mthmmy.session; package gr.thmmy.mthmmy.session;
import static gr.thmmy.mthmmy.session.SessionManager.baseMarkAllAsReadLink;
import static gr.thmmy.mthmmy.session.SessionManager.unreadUrl;
import org.jsoup.nodes.Document; import org.jsoup.nodes.Document;
import org.jsoup.select.Elements; import org.jsoup.select.Elements;
@ -9,9 +12,6 @@ import gr.thmmy.mthmmy.utils.networking.NetworkTask;
import gr.thmmy.mthmmy.utils.parsing.ParseException; import gr.thmmy.mthmmy.utils.parsing.ParseException;
import okhttp3.Response; import okhttp3.Response;
import static gr.thmmy.mthmmy.session.SessionManager.baseMarkAllAsReadLink;
import static gr.thmmy.mthmmy.session.SessionManager.unreadUrl;
public class MarkAsReadTask extends NetworkTask<Void> { public class MarkAsReadTask extends NetworkTask<Void> {
private String markAsReadLink; private String markAsReadLink;

4
app/src/main/java/gr/thmmy/mthmmy/utils/DateTimeUtils.java

@ -1,13 +1,13 @@
package gr.thmmy.mthmmy.utils; package gr.thmmy.mthmmy.utils;
import androidx.annotation.VisibleForTesting;
import static android.text.format.DateUtils.DAY_IN_MILLIS; import static android.text.format.DateUtils.DAY_IN_MILLIS;
import static android.text.format.DateUtils.HOUR_IN_MILLIS; import static android.text.format.DateUtils.HOUR_IN_MILLIS;
import static android.text.format.DateUtils.MINUTE_IN_MILLIS; import static android.text.format.DateUtils.MINUTE_IN_MILLIS;
import static android.text.format.DateUtils.SECOND_IN_MILLIS; import static android.text.format.DateUtils.SECOND_IN_MILLIS;
import static android.text.format.DateUtils.YEAR_IN_MILLIS; import static android.text.format.DateUtils.YEAR_IN_MILLIS;
import androidx.annotation.VisibleForTesting;
public class DateTimeUtils { public class DateTimeUtils {
private static final long MONTH_IN_MILLIS = 30 * DAY_IN_MILLIS; private static final long MONTH_IN_MILLIS = 30 * DAY_IN_MILLIS;

19
app/src/main/java/gr/thmmy/mthmmy/utils/FileUtils.java

@ -1,5 +1,7 @@
package gr.thmmy.mthmmy.utils; package gr.thmmy.mthmmy.utils;
import static gr.thmmy.mthmmy.services.DownloadHelper.SAVE_DIR;
import android.content.Context; import android.content.Context;
import android.database.Cursor; import android.database.Cursor;
import android.net.Uri; import android.net.Uri;
@ -10,18 +12,17 @@ import androidx.annotation.NonNull;
import androidx.annotation.Nullable; import androidx.annotation.Nullable;
import java.io.File; import java.io.File;
import java.util.Locale;
import gr.thmmy.mthmmy.R; import gr.thmmy.mthmmy.R;
import static gr.thmmy.mthmmy.services.DownloadHelper.SAVE_DIR;
public class FileUtils { public class FileUtils {
@NonNull @NonNull
public static String getMimeType(@NonNull String fileName) { public static String getMimeType(@NonNull String fileName) {
String type = null; String type = null;
final String extension = MimeTypeMap.getFileExtensionFromUrl(fileName); final String extension = MimeTypeMap.getFileExtensionFromUrl(fileName);
if (extension != null) if (extension != null)
type = MimeTypeMap.getSingleton().getMimeTypeFromExtension(extension.toLowerCase()); type = MimeTypeMap.getSingleton().getMimeTypeFromExtension(extension.toLowerCase(Locale.ROOT));
if (type == null) if (type == null)
type = "*/*"; type = "*/*";
@ -39,7 +40,7 @@ public class FileUtils {
if (!filename.contains(".")) { if (!filename.contains(".")) {
return null; return null;
} }
if (filename.toLowerCase().endsWith(".tar.gz")) { if (filename.toLowerCase(Locale.ROOT).endsWith(".tar.gz")) {
fileExtension = filename.substring(filename.length() - 7); fileExtension = filename.substring(filename.length() - 7);
} }
else { else {
@ -63,7 +64,9 @@ public class FileUtils {
if (uri.getScheme().equals("content")) { if (uri.getScheme().equals("content")) {
try (Cursor cursor = context.getContentResolver().query(uri, null, null, null, null)) { try (Cursor cursor = context.getContentResolver().query(uri, null, null, null, null)) {
if (cursor != null && cursor.moveToFirst()) { if (cursor != null && cursor.moveToFirst()) {
filename = cursor.getString(cursor.getColumnIndex(OpenableColumns.DISPLAY_NAME)); final int columnIndex = (cursor.getColumnIndex(OpenableColumns.DISPLAY_NAME));
if(columnIndex>=0)
filename = cursor.getString(columnIndex);
} }
} }
} }
@ -81,7 +84,9 @@ public class FileUtils {
public static long sizeFromUri(Context context, @NonNull Uri uri) { public static long sizeFromUri(Context context, @NonNull Uri uri) {
try (Cursor cursor = context.getContentResolver().query(uri, null, null, null, null)) { try (Cursor cursor = context.getContentResolver().query(uri, null, null, null, null)) {
if (cursor != null && cursor.moveToFirst()) { if (cursor != null && cursor.moveToFirst()) {
return cursor.getLong(cursor.getColumnIndex(OpenableColumns.SIZE)); final int columnIndex = (cursor.getColumnIndex(OpenableColumns.SIZE));
if(columnIndex>=0)
return cursor.getLong(columnIndex);
} }
} }
return -1; return -1;
@ -97,7 +102,7 @@ public class FileUtils {
*/ */
@NonNull @NonNull
public static String faIconFromFilename(Context context, String filename) { public static String faIconFromFilename(Context context, String filename) {
filename = filename.toLowerCase(); filename = filename.toLowerCase(Locale.ROOT);
if (filename.contains("jpg") || filename.contains("gif") || filename.contains("jpeg") if (filename.contains("jpg") || filename.contains("gif") || filename.contains("jpeg")
|| filename.contains("png")) || filename.contains("png"))

14
app/src/main/java/gr/thmmy/mthmmy/utils/HTMLUtils.java

@ -1,5 +1,12 @@
package gr.thmmy.mthmmy.utils; package gr.thmmy.mthmmy.utils;
import static android.content.Intent.FLAG_ACTIVITY_NEW_TASK;
import static gr.thmmy.mthmmy.activities.board.BoardActivity.BUNDLE_BOARD_TITLE;
import static gr.thmmy.mthmmy.activities.board.BoardActivity.BUNDLE_BOARD_URL;
import static gr.thmmy.mthmmy.activities.profile.ProfileActivity.BUNDLE_PROFILE_THUMBNAIL_URL;
import static gr.thmmy.mthmmy.activities.profile.ProfileActivity.BUNDLE_PROFILE_URL;
import static gr.thmmy.mthmmy.activities.profile.ProfileActivity.BUNDLE_PROFILE_USERNAME;
import android.app.Activity; import android.app.Activity;
import android.content.Context; import android.content.Context;
import android.content.Intent; import android.content.Intent;
@ -17,13 +24,6 @@ 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.model.ThmmyPage; import gr.thmmy.mthmmy.model.ThmmyPage;
import static android.content.Intent.FLAG_ACTIVITY_NEW_TASK;
import static gr.thmmy.mthmmy.activities.board.BoardActivity.BUNDLE_BOARD_TITLE;
import static gr.thmmy.mthmmy.activities.board.BoardActivity.BUNDLE_BOARD_URL;
import static gr.thmmy.mthmmy.activities.profile.ProfileActivity.BUNDLE_PROFILE_THUMBNAIL_URL;
import static gr.thmmy.mthmmy.activities.profile.ProfileActivity.BUNDLE_PROFILE_URL;
import static gr.thmmy.mthmmy.activities.profile.ProfileActivity.BUNDLE_PROFILE_USERNAME;
public class HTMLUtils { public class HTMLUtils {
private HTMLUtils() { private HTMLUtils() {
} }

4
app/src/main/java/gr/thmmy/mthmmy/utils/ui/ImageDownloadDialogBuilder.java

@ -1,5 +1,7 @@
package gr.thmmy.mthmmy.utils.ui; package gr.thmmy.mthmmy.utils.ui;
import static android.content.Context.CLIPBOARD_SERVICE;
import android.content.ClipData; import android.content.ClipData;
import android.content.ClipboardManager; import android.content.ClipboardManager;
import android.content.Context; import android.content.Context;
@ -18,8 +20,6 @@ import gr.thmmy.mthmmy.base.BaseApplication;
import gr.thmmy.mthmmy.model.ThmmyFile; import gr.thmmy.mthmmy.model.ThmmyFile;
import timber.log.Timber; import timber.log.Timber;
import static android.content.Context.CLIPBOARD_SERVICE;
public class ImageDownloadDialogBuilder extends AlertDialog.Builder { public class ImageDownloadDialogBuilder extends AlertDialog.Builder {
private static final String[] colors = {"Copy image location", "Save Image"}; private static final String[] colors = {"Copy image location", "Save Image"};

8
app/src/main/java/gr/thmmy/mthmmy/views/ReactiveWebView.java

@ -1,5 +1,9 @@
package gr.thmmy.mthmmy.views; package gr.thmmy.mthmmy.views;
import static android.content.Context.CLIPBOARD_SERVICE;
import static gr.thmmy.mthmmy.utils.parsing.ParseHelpers.VIDEO_ID_PARAMETER;
import static gr.thmmy.mthmmy.utils.ui.PhotoViewUtils.displayPhotoViewImage;
import android.content.ClipData; import android.content.ClipData;
import android.content.ClipboardManager; import android.content.ClipboardManager;
import android.content.Context; import android.content.Context;
@ -13,10 +17,6 @@ import gr.thmmy.mthmmy.R;
import gr.thmmy.mthmmy.base.BaseApplication; import gr.thmmy.mthmmy.base.BaseApplication;
import gr.thmmy.mthmmy.utils.ui.ImageDownloadDialogBuilder; import gr.thmmy.mthmmy.utils.ui.ImageDownloadDialogBuilder;
import static android.content.Context.CLIPBOARD_SERVICE;
import static gr.thmmy.mthmmy.utils.parsing.ParseHelpers.VIDEO_ID_PARAMETER;
import static gr.thmmy.mthmmy.utils.ui.PhotoViewUtils.displayPhotoViewImage;
public class ReactiveWebView extends WebView { public class ReactiveWebView extends WebView {
private final static long MAX_TOUCH_DURATION = 100; private final static long MAX_TOUCH_DURATION = 100;
private final Context context; private final Context context;

4
app/src/main/java/gr/thmmy/mthmmy/views/RelativeTimeTextView.java

@ -1,5 +1,7 @@
package gr.thmmy.mthmmy.views; package gr.thmmy.mthmmy.views;
import static gr.thmmy.mthmmy.utils.DateTimeUtils.getRelativeTimeSpanString;
import android.annotation.SuppressLint; import android.annotation.SuppressLint;
import android.content.Context; import android.content.Context;
import android.content.res.TypedArray; import android.content.res.TypedArray;
@ -15,8 +17,6 @@ import java.lang.ref.WeakReference;
import gr.thmmy.mthmmy.R; import gr.thmmy.mthmmy.R;
import static gr.thmmy.mthmmy.utils.DateTimeUtils.getRelativeTimeSpanString;
/** /**
* A modified version of https://github.com/curioustechizen/android-ago * A modified version of https://github.com/curioustechizen/android-ago
*/ */

33
app/src/main/java/gr/thmmy/mthmmy/views/editorview/EditorView.java

@ -8,7 +8,6 @@ import android.content.Context;
import android.content.res.TypedArray; import android.content.res.TypedArray;
import android.graphics.drawable.Drawable; import android.graphics.drawable.Drawable;
import android.os.AsyncTask; import android.os.AsyncTask;
import android.os.Build;
import android.text.Editable; import android.text.Editable;
import android.text.TextUtils; import android.text.TextUtils;
import android.util.AttributeSet; import android.util.AttributeSet;
@ -201,24 +200,24 @@ public class EditorView extends LinearLayout implements EmojiInputField {
}); });
} }
popupWindow.showAsDropDown(view); popupWindow.showAsDropDown(view);
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.M) {
new AsyncTask<Void, Void, Void>() {
@Override
protected Void doInBackground(Void... voids) {
try {
Thread.sleep(100);
} catch (InterruptedException e) {
Timber.e(e);
}
return null;
}
@Override new AsyncTask<Void, Void, Void>() {
protected void onPostExecute(Void aVoid) { @Override
editText.setSelection(selectionStart, selectionEnd); protected Void doInBackground(Void... voids) {
try {
Thread.sleep(100);
} catch (InterruptedException e) {
Timber.e(e);
} }
}.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR); return null;
} }
@Override
protected void onPostExecute(Void aVoid) {
editText.setSelection(selectionStart, selectionEnd);
}
}.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
break; break;
case R.drawable.ic_format_size: case R.drawable.ic_format_size:
hadTextSelection = editText.hasSelection(); hadTextSelection = editText.hasSelection();

52
app/src/main/res/layout-v23/activity_topic_overflow_menu.xml

@ -1,52 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="@color/background_light"
android:orientation="vertical">
<TextView
android:id="@+id/post_share_button"
android:layout_width="wrap_content"
android:layout_height="35dp"
android:background="@color/background_light"
android:foreground="?android:attr/selectableItemBackground"
android:drawablePadding="5dp"
android:gravity="center_vertical"
android:paddingBottom="6dp"
android:paddingEnd="12dp"
android:paddingStart="12dp"
android:paddingTop="6dp"
android:text="@string/post_share_button"
android:textColor="@color/primary_text" />
<TextView
android:id="@+id/edit_post"
android:layout_width="wrap_content"
android:layout_height="35dp"
android:background="@color/background_light"
android:foreground="?android:attr/selectableItemBackground"
android:drawablePadding="5dp"
android:gravity="center_vertical"
android:paddingBottom="6dp"
android:paddingEnd="12dp"
android:paddingStart="12dp"
android:paddingTop="6dp"
android:text="@string/post_edit_button"
android:textColor="@color/primary_text" />
<TextView
android:id="@+id/delete_post"
android:layout_width="wrap_content"
android:layout_height="35dp"
android:background="@color/background_light"
android:foreground="?android:attr/selectableItemBackground"
android:drawablePadding="5dp"
android:gravity="center_vertical"
android:paddingBottom="6dp"
android:paddingEnd="12dp"
android:paddingStart="12dp"
android:paddingTop="6dp"
android:text="@string/post_delete_button"
android:textColor="@color/primary_text" />
</LinearLayout>

10
app/src/main/res/layout/activity_topic_overflow_menu.xml

@ -2,13 +2,15 @@
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:background="@color/background_light"
android:orientation="vertical"> android:orientation="vertical">
<TextView <TextView
android:id="@+id/post_share_button" android:id="@+id/post_share_button"
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="35dp" android:layout_height="35dp"
android:background="?android:attr/selectableItemBackground" android:background="@color/background_light"
android:foreground="?android:attr/selectableItemBackground"
android:drawablePadding="5dp" android:drawablePadding="5dp"
android:gravity="center_vertical" android:gravity="center_vertical"
android:paddingBottom="6dp" android:paddingBottom="6dp"
@ -22,7 +24,8 @@
android:id="@+id/edit_post" android:id="@+id/edit_post"
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="35dp" android:layout_height="35dp"
android:background="?android:attr/selectableItemBackground" android:background="@color/background_light"
android:foreground="?android:attr/selectableItemBackground"
android:drawablePadding="5dp" android:drawablePadding="5dp"
android:gravity="center_vertical" android:gravity="center_vertical"
android:paddingBottom="6dp" android:paddingBottom="6dp"
@ -36,7 +39,8 @@
android:id="@+id/delete_post" android:id="@+id/delete_post"
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="35dp" android:layout_height="35dp"
android:background="?android:attr/selectableItemBackground" android:background="@color/background_light"
android:foreground="?android:attr/selectableItemBackground"
android:drawablePadding="5dp" android:drawablePadding="5dp"
android:gravity="center_vertical" android:gravity="center_vertical"
android:paddingBottom="6dp" android:paddingBottom="6dp"

8
app/src/test/java/gr/thmmy/mthmmy/utils/DateTimeUtilsTest.java

@ -1,5 +1,9 @@
package gr.thmmy.mthmmy.utils; package gr.thmmy.mthmmy.utils;
import static org.junit.Assert.assertArrayEquals;
import static org.mockito.Mockito.when;
import static gr.thmmy.mthmmy.utils.DateTimeUtils.getRelativeTimeSpanString;
import net.lachlanmckee.timberjunit.TimberTestRule; import net.lachlanmckee.timberjunit.TimberTestRule;
import org.joda.time.DateTime; import org.joda.time.DateTime;
@ -10,10 +14,6 @@ import org.powermock.api.mockito.PowerMockito;
import org.powermock.core.classloader.annotations.PrepareForTest; import org.powermock.core.classloader.annotations.PrepareForTest;
import org.powermock.modules.junit4.PowerMockRunner; import org.powermock.modules.junit4.PowerMockRunner;
import static gr.thmmy.mthmmy.utils.DateTimeUtils.getRelativeTimeSpanString;
import static org.junit.Assert.assertArrayEquals;
import static org.mockito.Mockito.when;
@RunWith(PowerMockRunner.class) @RunWith(PowerMockRunner.class)
@PrepareForTest(DateTimeUtils.class) @PrepareForTest(DateTimeUtils.class)
public class DateTimeUtilsTest { public class DateTimeUtilsTest {

10
app/src/test/java/gr/thmmy/mthmmy/utils/UploadsCoursesJSONReadingTest.java

@ -1,5 +1,10 @@
package gr.thmmy.mthmmy.utils; package gr.thmmy.mthmmy.utils;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertTrue;
import static gr.thmmy.mthmmy.activities.upload.UploadsCourse.generateCoursesFromJSON;
import net.lachlanmckee.timberjunit.TimberTestRule; import net.lachlanmckee.timberjunit.TimberTestRule;
import org.json.JSONObject; import org.json.JSONObject;
@ -15,11 +20,6 @@ import java.util.HashMap;
import gr.thmmy.mthmmy.activities.upload.UploadsCourse; import gr.thmmy.mthmmy.activities.upload.UploadsCourse;
import gr.thmmy.mthmmy.utils.io.ResourceUtils; import gr.thmmy.mthmmy.utils.io.ResourceUtils;
import static gr.thmmy.mthmmy.activities.upload.UploadsCourse.generateCoursesFromJSON;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertTrue;
@RunWith(PowerMockRunner.class) @RunWith(PowerMockRunner.class)
@PrepareForTest(JSONObject.class) @PrepareForTest(JSONObject.class)
public class UploadsCoursesJSONReadingTest { public class UploadsCoursesJSONReadingTest {

14
app/src/test/java/gr/thmmy/mthmmy/utils/parsing/ThmmyDateTimeParserTest.java

@ -1,5 +1,12 @@
package gr.thmmy.mthmmy.utils.parsing; package gr.thmmy.mthmmy.utils.parsing;
import static org.junit.Assert.assertArrayEquals;
import static org.junit.Assert.assertNotNull;
import static org.powermock.api.support.membermodification.MemberMatcher.method;
import static org.powermock.api.support.membermodification.MemberModifier.stub;
import static gr.thmmy.mthmmy.utils.parsing.ThmmyDateTimeParser.convertToTimestamp;
import static gr.thmmy.mthmmy.utils.parsing.ThmmyDateTimeParser.purifyTodayDateTime;
import net.lachlanmckee.timberjunit.TimberTestRule; import net.lachlanmckee.timberjunit.TimberTestRule;
import org.joda.time.DateTimeZone; import org.joda.time.DateTimeZone;
@ -9,13 +16,6 @@ import org.junit.runner.RunWith;
import org.powermock.core.classloader.annotations.PrepareForTest; import org.powermock.core.classloader.annotations.PrepareForTest;
import org.powermock.modules.junit4.PowerMockRunner; import org.powermock.modules.junit4.PowerMockRunner;
import static gr.thmmy.mthmmy.utils.parsing.ThmmyDateTimeParser.convertToTimestamp;
import static gr.thmmy.mthmmy.utils.parsing.ThmmyDateTimeParser.purifyTodayDateTime;
import static org.junit.Assert.assertArrayEquals;
import static org.junit.Assert.assertNotNull;
import static org.powermock.api.support.membermodification.MemberMatcher.method;
import static org.powermock.api.support.membermodification.MemberModifier.stub;
@RunWith(PowerMockRunner.class) @RunWith(PowerMockRunner.class)
@PrepareForTest(ThmmyDateTimeParser.class) @PrepareForTest(ThmmyDateTimeParser.class)
public class ThmmyDateTimeParserTest { public class ThmmyDateTimeParserTest {

26
build.gradle

@ -1,27 +1,33 @@
// Top-level build file where you can add configuration options common to all sub-projects/modules. // Top-level build file where you can add configuration options common to all sub-projects/modules.
apply plugin: "com.github.ben-manes.versions"
buildscript { buildscript {
repositories { repositories {
google() google()
jcenter() mavenCentral()
maven { url "https://jitpack.io" } maven { url "https://jitpack.io" }
jcenter() // Just for snatik and uploadservice
} }
dependencies { dependencies {
classpath 'com.android.tools.build:gradle:4.1.3' classpath 'com.android.tools.build:gradle:7.4.2'
classpath 'com.google.gms:google-services:4.3.10' classpath 'com.google.gms:google-services:4.3.15'
classpath 'com.google.firebase:firebase-crashlytics-gradle:2.7.1' classpath 'com.google.firebase:firebase-crashlytics-gradle:2.9.4'
classpath 'org.ajoberstar.grgit:grgit-core:3.1.1' // Also change in app/gradle/grgit.gradle classpath 'org.ajoberstar.grgit:grgit-core:5.0.0' // Also change in app/gradle/grgit.gradle
classpath "com.github.ben-manes:gradle-versions-plugin:0.21.0"
} }
} }
plugins {
id("com.github.ben-manes.versions") version "0.46.0"
}
allprojects { allprojects {
repositories { repositories {
maven { url "https://maven.google.com" }
google() google()
jcenter() mavenCentral()
maven { url "https://jitpack.io" } maven { url "https://jitpack.io" }
jcenter() // Just for snatik and uploadservice
}
tasks.withType(JavaCompile) {
options.compilerArgs << "-Xlint:unchecked" << "-Xlint:deprecation"
} }
} }

11
emojis/build.gradle

@ -1,14 +1,11 @@
apply plugin: 'com.android.library' apply plugin: 'com.android.library'
android { android {
compileSdkVersion 29 compileSdkVersion 33
buildToolsVersion "29.0.3"
defaultConfig { defaultConfig {
minSdkVersion 19 minSdkVersion 21
targetSdkVersion 29 targetSdkVersion 33
versionCode 1
versionName "1.0"
consumerProguardFiles 'consumer-rules.pro' consumerProguardFiles 'consumer-rules.pro'
} }
@ -19,4 +16,6 @@ android {
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro' proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
} }
} }
namespace 'gr.thmmy.emojis'
} }

3
emojis/src/main/AndroidManifest.xml

@ -1,2 +1 @@
<manifest xmlns:android="http://schemas.android.com/apk/res/android" <manifest xmlns:android="http://schemas.android.com/apk/res/android" />
package="gr.thmmy.emojis" />

4
gradle/wrapper/gradle-wrapper.properties

@ -1,6 +1,6 @@
#Thu Dec 03 14:56:57 EET 2020 #Sun Apr 02 13:22:00 EEST 2023
distributionBase=GRADLE_USER_HOME distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists distributionPath=wrapper/dists
zipStoreBase=GRADLE_USER_HOME zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists zipStorePath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-6.5-all.zip distributionUrl=https\://services.gradle.org/distributions/gradle-7.5-bin.zip

Loading…
Cancel
Save