Browse Source

Version 2.2.0

master v2.2.0
Ezerous 2 years ago
parent
commit
96614bc2ba
  1. 12
      CONTRIBUTING.md
  2. 6
      PRIVACY.md
  3. 8
      README.md
  4. 15
      app/build.gradle
  5. 4
      app/gradle/grgit.gradle
  6. 18
      app/src/main/AndroidManifest.xml
  7. 4
      app/src/main/assets/PRIVACY.md
  8. 2
      app/src/main/java/gr/thmmy/mthmmy/activities/AboutActivity.java
  9. 16
      app/src/main/java/gr/thmmy/mthmmy/activities/LoginActivity.java
  10. 11
      app/src/main/java/gr/thmmy/mthmmy/activities/board/BoardActivity.java
  11. 32
      app/src/main/java/gr/thmmy/mthmmy/activities/board/BoardAdapter.java
  12. 14
      app/src/main/java/gr/thmmy/mthmmy/activities/bookmarks/BookmarksActivity.java
  13. 3
      app/src/main/java/gr/thmmy/mthmmy/activities/bookmarks/BookmarksFragment.java
  14. 4
      app/src/main/java/gr/thmmy/mthmmy/activities/create_content/NewTopicTask.java
  15. 52
      app/src/main/java/gr/thmmy/mthmmy/activities/downloads/DownloadsActivity.java
  16. 15
      app/src/main/java/gr/thmmy/mthmmy/activities/downloads/DownloadsAdapter.java
  17. 20
      app/src/main/java/gr/thmmy/mthmmy/activities/main/MainActivity.java
  18. 10
      app/src/main/java/gr/thmmy/mthmmy/activities/main/forum/ForumFragment.java
  19. 2
      app/src/main/java/gr/thmmy/mthmmy/activities/main/recent/RecentAdapter.java
  20. 6
      app/src/main/java/gr/thmmy/mthmmy/activities/main/recent/RecentFragment.java
  21. 6
      app/src/main/java/gr/thmmy/mthmmy/activities/main/unread/UnreadAdapter.java
  22. 8
      app/src/main/java/gr/thmmy/mthmmy/activities/main/unread/UnreadFragment.java
  23. 12
      app/src/main/java/gr/thmmy/mthmmy/activities/profile/ProfileActivity.java
  24. 5
      app/src/main/java/gr/thmmy/mthmmy/activities/profile/latestPosts/LatestPostsFragment.java
  25. 27
      app/src/main/java/gr/thmmy/mthmmy/activities/profile/stats/StatsFragment.java
  26. 9
      app/src/main/java/gr/thmmy/mthmmy/activities/profile/summary/SummaryFragment.java
  27. 4
      app/src/main/java/gr/thmmy/mthmmy/activities/settings/SettingsFragment.java
  28. 16
      app/src/main/java/gr/thmmy/mthmmy/activities/shoutbox/ShoutAdapter.java
  29. 8
      app/src/main/java/gr/thmmy/mthmmy/activities/shoutbox/ShoutboxFragment.java
  30. 25
      app/src/main/java/gr/thmmy/mthmmy/activities/topic/TopicActivity.java
  31. 39
      app/src/main/java/gr/thmmy/mthmmy/activities/topic/TopicAdapter.java
  32. 4
      app/src/main/java/gr/thmmy/mthmmy/activities/topic/tasks/EditTask.java
  33. 10
      app/src/main/java/gr/thmmy/mthmmy/activities/topic/tasks/PrepareForEditTask.java
  34. 10
      app/src/main/java/gr/thmmy/mthmmy/activities/topic/tasks/PrepareForReplyResult.java
  35. 18
      app/src/main/java/gr/thmmy/mthmmy/activities/topic/tasks/PrepareForReplyTask.java
  36. 6
      app/src/main/java/gr/thmmy/mthmmy/activities/topic/tasks/ReplyTask.java
  37. 26
      app/src/main/java/gr/thmmy/mthmmy/activities/upload/UploadActivity.java
  38. 2
      app/src/main/java/gr/thmmy/mthmmy/activities/upload/UploadFieldsBuilderActivity.java
  39. 5
      app/src/main/java/gr/thmmy/mthmmy/activities/upload/multipart/MultipartUploadTask.java
  40. 67
      app/src/main/java/gr/thmmy/mthmmy/base/BaseActivity.java
  41. 43
      app/src/main/java/gr/thmmy/mthmmy/base/BaseApplication.java
  42. 2
      app/src/main/java/gr/thmmy/mthmmy/base/BaseFragment.java
  43. 4
      app/src/main/java/gr/thmmy/mthmmy/model/Category.java
  44. 29
      app/src/main/java/gr/thmmy/mthmmy/model/ThmmyPage.java
  45. 4
      app/src/main/java/gr/thmmy/mthmmy/services/DownloadHelper.java
  46. 36
      app/src/main/java/gr/thmmy/mthmmy/services/NotificationService.java
  47. 6
      app/src/main/java/gr/thmmy/mthmmy/session/LogoutTask.java
  48. 6
      app/src/main/java/gr/thmmy/mthmmy/session/MarkAsReadTask.java
  49. 22
      app/src/main/java/gr/thmmy/mthmmy/session/SessionManager.java
  50. 4
      app/src/main/java/gr/thmmy/mthmmy/utils/DateTimeUtils.java
  51. 19
      app/src/main/java/gr/thmmy/mthmmy/utils/FileUtils.java
  52. 14
      app/src/main/java/gr/thmmy/mthmmy/utils/HTMLUtils.java
  53. 2
      app/src/main/java/gr/thmmy/mthmmy/utils/networking/NetworkTask.java
  54. 244
      app/src/main/java/gr/thmmy/mthmmy/utils/parsing/ParseHelpers.java
  55. 6
      app/src/main/java/gr/thmmy/mthmmy/utils/parsing/ThmmyDateTimeParser.java
  56. 4
      app/src/main/java/gr/thmmy/mthmmy/utils/ui/ImageDownloadDialogBuilder.java
  57. 4
      app/src/main/java/gr/thmmy/mthmmy/viewmodel/TopicViewModel.java
  58. 8
      app/src/main/java/gr/thmmy/mthmmy/views/ReactiveWebView.java
  59. 4
      app/src/main/java/gr/thmmy/mthmmy/views/RelativeTimeTextView.java
  60. 5
      app/src/main/java/gr/thmmy/mthmmy/views/editorview/EditorView.java
  61. 52
      app/src/main/res/layout-v23/activity_topic_overflow_menu.xml
  62. 2
      app/src/main/res/layout/activity_bookmarks.xml
  63. 22
      app/src/main/res/layout/activity_downloads.xml
  64. 2
      app/src/main/res/layout/activity_login.xml
  65. 1
      app/src/main/res/layout/activity_topic.xml
  66. 10
      app/src/main/res/layout/activity_topic_overflow_menu.xml
  67. 2
      app/src/main/res/menu/downloads_menu.xml
  68. 2
      app/src/main/res/menu/shoutbox_menu.xml
  69. 6
      app/src/main/res/menu/topic_menu.xml
  70. 2
      app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml
  71. 2
      app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml
  72. 4
      app/src/main/res/values/ic_launcher_background.xml
  73. 11
      app/src/main/res/values/strings.xml
  74. 12
      app/src/main/res/xml-v26/app_preferences_user.xml
  75. 12
      app/src/main/res/xml/app_preferences_user.xml
  76. 8
      app/src/test/java/gr/thmmy/mthmmy/utils/DateTimeUtilsTest.java
  77. 12
      app/src/test/java/gr/thmmy/mthmmy/utils/UploadsCoursesJSONReadingTest.java
  78. 14
      app/src/test/java/gr/thmmy/mthmmy/utils/parsing/ThmmyDateTimeParserTest.java
  79. 26
      build.gradle
  80. 11
      emojis/build.gradle
  81. 3
      emojis/src/main/AndroidManifest.xml
  82. 4
      gradle/wrapper/gradle-wrapper.properties

12
CONTRIBUTING.md

@ -7,7 +7,7 @@ to contribute to mTHMMY in a way that is efficient for everyone.
**Important!** Instead of creating publicly viewable issues for suspected security
vulnerabilities, please report them in private to
[thmmynolife@gmail.com](mailto:thmmynolife@gmail.com).
[contact@thmmy.gr](mailto:contact@thmmy.gr).
## I want to contribute!
@ -18,7 +18,7 @@ There are many ways of contributing to mTHMMY:
- Submitting bugs and ideas to our [issue tracker][github-issues]
- Forking mTHMMY and submitting [pull requests](#pull-requests)
- Joining our core team
- Contacting us by email at [thmmynolife@gmail.com](mailto:thmmynolife@gmail.com)
- Contacting us by email at [contact@thmmy.gr](mailto:contact@thmmy.gr)
## Issue tracker
@ -35,15 +35,15 @@ Pull requests with fixes and improvements to mTHMMY are most welcome. Any develo
follow the workflow below to make a pull request (PR):
1. Fork the project into your personal space on Github
1. Create a feature branch, away from [develop](https://github.com/ThmmyNoLife/mTHMMY/tree/develop)
1. Create a feature branch, away from [develop](https://github.com/THMMYgr/mTHMMY/tree/develop)
1. Push the commit(s) to your fork
1. Create a PR targeting [develop at mTHMMY](https://github.com/ThmmyNoLife/mTHMMY/tree/develop)
1. Create a PR targeting [develop at mTHMMY](https://github.com/THMMYgr/mTHMMY/tree/develop)
1. Fill the PR title describing the change you want to make
1. Fill the PR description with a brief motive for your change and the method you used to achieve it
1. Submit the PR.
[google-play]: https://play.google.com/store/apps/details?id=gr.thmmy.mthmmy
[github-issues]: https://github.com/ThmmyNoLife/mTHMMY/issues
[github-issues]: https://github.com/THMMYgr/mTHMMY/issues
[discord-server]: https://discord.gg/CVt3yrn
[sisyphus]: https://github.com/ThmmyNoLife/Sisyphus
[sisyphus]: https://github.com/THMMYgr/Sisyphus
[firebase-console]: https://console.firebase.google.com/

6
PRIVACY.md

@ -29,7 +29,7 @@ The use of each Firebase service is explained below:
### Firebase Cloud Messaging
* **Purpose**: This service is essential for the funcionality of the App. It uses anonymous push notification tokens in order to determine which devices to deliver the appropriate messages to.
* **Purpose**: This service is essential for the functionality of the App. It uses anonymous push notification tokens in order to determine which devices to deliver the appropriate messages to.
* **Data collected**: Instance IDs.
* **Consent**: You will be prompted to agree to the use of this service when you open the App for the first time.
* **Retention**: Firebase retains Instance IDs until we make an API call for deletion. After the call, data are removed from live and backup systems within 180 days.
@ -69,8 +69,8 @@ mTHMMY may contain links to third-party websites. Any access to and use of such
## Policy Updates
We may update this Privacy Policy from time to time and, thus, you are advised to review it periodically. The most recent version of our Privacy Policy can be found at <https://github.com/ThmmyNoLife/mTHMMY/blob/develop/PRIVACY.md>.
We may update this Privacy Policy from time to time and, thus, you are advised to review it periodically. The most recent version of our Privacy Policy can be found at <https://github.com/THMMYgr/mTHMMY/blob/develop/PRIVACY.md>.
## Contact Us
If you have any questions about our Privacy Policy, please contact us at [thmmynolife@gmail.com](mailto:thmmynolife@gmail.com).
If you have any questions about our Privacy Policy, please contact us at [contact@thmmy.gr](mailto:contact@thmmy.gr).

8
README.md

@ -1,9 +1,9 @@
# mTHMMY
[![GitHub release](https://img.shields.io/github/release/ThmmyNoLife/mTHMMY.svg?color=orange)](https://github.com/ThmmyNoLife/mTHMMY/releases)
[![GitHub release](https://img.shields.io/github/release/THMMYgr/mTHMMY.svg?color=orange)](https://github.com/THMMYgr/mTHMMY/releases)
[![API](https://img.shields.io/badge/API-21%2B-blue.svg?style=flat)](https://android-arsenal.com/api?level=21)
[![Discord Channel](https://img.shields.io/discord/252539000571559947?style=flat&color=738bd7&label=discord)][discord-server]
![Last Commit](https://img.shields.io/github/last-commit/ThmmyNoLife/mTHMMY/develop.svg?style=flat)
![Last Commit](https://img.shields.io/github/last-commit/THMMYgr/mTHMMY/develop.svg?style=flat)
![mTHMMY logo](app/src/main/res/mipmap-xhdpi/ic_launcher_round.png)
@ -11,7 +11,7 @@ A mobile app for [thmmy.gr](https://www.thmmy.gr).
## 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
@ -29,7 +29,7 @@ Our Privacy Policy can be found [here](/PRIVACY.md).
## Contact
Do not hesitate to contact us for any matter, either by sending an email to [thmmynolife@gmail.com](mailto:thmmynolife@gmail.com), or by joining our [Discord server][discord-server].
Do not hesitate to contact us for any matter, either by sending an email to [contact@thmmy.gr](mailto:contact@thmmy.gr), or by joining our [Discord server][discord-server].
**Legal attribution: Google Play and the Google Play logo are trademarks of Google Inc.*

15
app/build.gradle

@ -7,15 +7,14 @@ apply plugin: 'com.google.gms.google-services'
apply plugin: 'com.google.firebase.crashlytics'
android {
compileSdkVersion 31
buildToolsVersion = '30.0.2'
compileSdkVersion 33
defaultConfig {
applicationId "gr.thmmy.mthmmy"
minSdkVersion 21
targetSdkVersion 30
versionCode 31
versionName "2.1.0"
minSdkVersion 23
targetSdkVersion 33
versionCode 32
versionName "2.2.0"
archivesBaseName = "mTHMMY-v$versionName"
buildConfigField "String", "CURRENT_BRANCH", "\"" + getCurrentBranch() + "\""
buildConfigField "String", "COMMIT_HASH", "\"" + getCommitHash() + "\""
@ -45,6 +44,8 @@ android {
sourceCompatibility JavaVersion.VERSION_1_8
targetCompatibility JavaVersion.VERSION_1_8
}
namespace 'gr.thmmy.mthmmy'
}
def firebaseReleaseProjectId = "mthmmy-release-3aef0"
@ -92,7 +93,7 @@ dependencies {
implementation 'com.google.firebase:firebase-crashlytics'
implementation 'com.google.firebase:firebase-messaging'
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 'org.jsoup:jsoup:1.14.2'
implementation 'joda-time:joda-time:2.10.10'

4
app/gradle/grgit.gradle

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

18
app/src/main/AndroidManifest.xml

@ -1,11 +1,11 @@
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
package="gr.thmmy.mthmmy"
android:installLocation="auto">
<uses-permission android:name="android.permission.INTERNET" />
<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.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.WAKE_LOCK" />
@ -54,19 +54,21 @@
<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.BROWSABLE" />
<data android:host="@string/forum_host" />
<data
android:host="thmmy.gr"
android:host="@string/forum_host"
android:scheme="http" />
<data
android:host="www.thmmy.gr"
android:scheme="http" />
<data
android:host="www.thmmy.gr"
android:host="@string/forum_host"
android:scheme="https" />
<data android:host="@string/forum_host_simple" />
<data
android:host="@string/forum_host_simple"
android:scheme="http" />
<data
android:host="thmmy.gr"
android:host="@string/forum_host_simple"
android:scheme="https" />
<data android:host="thmmy.gr" />
</intent-filter>
</activity>
<activity

4
app/src/main/assets/PRIVACY.md

@ -69,8 +69,8 @@ mTHMMY may contain links to third-party websites. Any access to and use of such
## Policy Updates
We may update this Privacy Policy from time to time and, thus, you are advised to review it periodically. The most recent version of our Privacy Policy can be found at <https://github.com/ThmmyNoLife/mTHMMY/blob/develop/PRIVACY.md>.
We may update this Privacy Policy from time to time and, thus, you are advised to review it periodically. The most recent version of our Privacy Policy can be found at <https://github.com/THMMYgr/mTHMMY/blob/develop/PRIVACY.md>.
## Contact Us
If you have any questions about our Privacy Policy, please contact us at [thmmynolife@gmail.com](mailto:thmmynolife@gmail.com).
If you have any questions about our Privacy Policy, please contact us at [contact@thmmy.gr](mailto:contact@thmmy.gr).

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

@ -105,7 +105,7 @@ public class AboutActivity extends BaseActivity {
if (gitExists) {
versionTextView.setOnClickListener(view -> {
Intent intent = new Intent(Intent.ACTION_VIEW, Uri.parse("https://github.com/ThmmyNoLife/mTHMMY/commit/" + BuildConfig.COMMIT_HASH));
Intent intent = new Intent(Intent.ACTION_VIEW, Uri.parse("https://github.com/THMMYgr/mTHMMY/commit/" + BuildConfig.COMMIT_HASH));
startActivity(intent);
});
}

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

@ -1,5 +1,13 @@
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.os.AsyncTask;
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.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 {
//-----------------------------------------CLASS VARIABLES------------------------------------------

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

@ -59,6 +59,7 @@ public class BoardActivity extends BaseActivity implements BoardAdapter.OnLoadMo
private String boardUrl;
private String boardTitle;
private String boardId;
private String parsedTitle;
private String newTopicUrl;
@ -88,6 +89,8 @@ public class BoardActivity extends BaseActivity implements BoardAdapter.OnLoadMo
if (!tmpUrlSbstr.substring(tmpUrlSbstr.indexOf("board=")).contains("."))
boardUrl = tmpUrlSbstr + ".0";
boardId = ThmmyPage.getBoardId(boardUrl);
//Initializes graphics
toolbar = findViewById(R.id.toolbar);
if (boardTitle != null && !Objects.equals(boardTitle, "")) toolbar.setTitle(boardTitle);
@ -98,7 +101,7 @@ public class BoardActivity extends BaseActivity implements BoardAdapter.OnLoadMo
getSupportActionBar().setDisplayShowHomeEnabled(true);
}
thisPageBookmark = new Bookmark(boardTitle, ThmmyPage.getBoardId(boardUrl), true);
thisPageBookmark = new Bookmark(boardTitle, boardId, true);
if (boardTitle != null && !Objects.equals(boardTitle, ""))
setBoardBookmark(findViewById(R.id.bookmark));
@ -303,7 +306,8 @@ public class BoardActivity extends BaseActivity implements BoardAdapter.OnLoadMo
if (!parsingFailed)
tempSubBoards.add(new Board(pUrl, pTitle, pMods, pStats, pLastPost, pLastPostUrl));
else
Timber.e("Parsing failed (pLastPost came with: \"%s\", subBoardColumns html was \"%s\")", pLastPost, subBoardColumns);
Timber.e("Parsing failed for a subBoard in board %s (subBoardRow html was \"%s\")",
boardId, subBoardRow);
}
}
}
@ -338,7 +342,8 @@ public class BoardActivity extends BaseActivity implements BoardAdapter.OnLoadMo
pLastUser = matcher.group(2);
}
else {
Timber.e("Parsing failed (pLastPost came with: \"%s\", topicColumns html was \"%s\")", pLastPost, topicColumns);
Timber.e("Parsing failed for a topic in board %s (topicRow html was \"%s\")",
boardId, topicRow);
continue;
}

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

@ -1,9 +1,13 @@
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.Intent;
import android.graphics.Typeface;
import android.os.Build;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
@ -23,11 +27,6 @@ import gr.thmmy.mthmmy.model.Board;
import gr.thmmy.mthmmy.model.Topic;
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}.
*/
@ -104,7 +103,7 @@ class BoardAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> {
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
context.startActivity(intent);
});
if (boardExpandableVisibility.get(subBoardViewHolder.getAdapterPosition())) {
if (boardExpandableVisibility.get(subBoardViewHolder.getBindingAdapterPosition())) {
subBoardViewHolder.boardExpandable.setVisibility(View.VISIBLE);
subBoardViewHolder.showHideExpandable.setImageResource(R.drawable.ic_arrow_drop_up_accent_24dp);
}
@ -113,7 +112,9 @@ class BoardAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> {
subBoardViewHolder.showHideExpandable.setImageResource(R.drawable.ic_arrow_drop_down_accent_24dp);
}
subBoardViewHolder.showHideExpandable.setOnClickListener(view -> {
final boolean visible = boardExpandableVisibility.get(subBoardViewHolder.getAdapterPosition());
final int pos = subBoardViewHolder.getBindingAdapterPosition();
if (pos >=0 && pos < boardExpandableVisibility.size()){
final boolean visible = boardExpandableVisibility.get(subBoardViewHolder.getBindingAdapterPosition());
if (visible) {
subBoardViewHolder.boardExpandable.setVisibility(View.GONE);
subBoardViewHolder.showHideExpandable.setImageResource(R.drawable.ic_arrow_drop_down_accent_24dp);
@ -122,7 +123,8 @@ class BoardAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> {
subBoardViewHolder.boardExpandable.setVisibility(View.VISIBLE);
subBoardViewHolder.showHideExpandable.setImageResource(R.drawable.ic_arrow_drop_up_accent_24dp);
}
boardExpandableVisibility.set(subBoardViewHolder.getAdapterPosition(), !visible);
boardExpandableVisibility.set(subBoardViewHolder.getBindingAdapterPosition(), !visible);
}
});
subBoardViewHolder.boardTitle.setText(subBoard.getTitle());
String mods = subBoard.getMods();
@ -174,7 +176,7 @@ class BoardAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> {
intent.addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP);
context.startActivity(intent);
});
if (topicExpandableVisibility.get(topicViewHolder.getAdapterPosition() - parsedSubBoards
if (topicExpandableVisibility.get(topicViewHolder.getBindingAdapterPosition() - parsedSubBoards
.size())) {
topicViewHolder.topicExpandable.setVisibility(View.VISIBLE);
topicViewHolder.showHideExpandable.setImageResource(R.drawable.ic_arrow_drop_up_accent_24dp);
@ -184,8 +186,10 @@ class BoardAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> {
topicViewHolder.showHideExpandable.setImageResource(R.drawable.ic_arrow_drop_down_accent_24dp);
}
topicViewHolder.showHideExpandable.setOnClickListener(view -> {
final int pos = topicViewHolder.getBindingAdapterPosition() - parsedSubBoards.size();
if (pos >=0 && pos < topicExpandableVisibility.size()) {
final boolean visible = topicExpandableVisibility.get(topicViewHolder.
getAdapterPosition() - parsedSubBoards.size());
getBindingAdapterPosition() - parsedSubBoards.size());
if (visible) {
topicViewHolder.topicExpandable.setVisibility(View.GONE);
topicViewHolder.showHideExpandable.setImageResource(R.drawable.ic_arrow_drop_down_accent_24dp);
@ -194,17 +198,17 @@ class BoardAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> {
topicViewHolder.topicExpandable.setVisibility(View.VISIBLE);
topicViewHolder.showHideExpandable.setImageResource(R.drawable.ic_arrow_drop_up_accent_24dp);
}
topicExpandableVisibility.set(topicViewHolder.getAdapterPosition() -
topicExpandableVisibility.set(topicViewHolder.getBindingAdapterPosition() -
parsedSubBoards.size(), !visible);
}
});
topicViewHolder.topicSubject.setTypeface(Typeface.createFromAsset(context.getAssets()
, "fonts/fontawesome-webfont.ttf"));
topicViewHolder.topicUnreadDot.setTypeface(Typeface.createFromAsset(context.getAssets(), "fonts/fontawesome-webfont.ttf"));
if (topic.isUnread())
topicViewHolder.topicUnreadDot.setVisibility(View.VISIBLE);
else {
else
topicViewHolder.topicUnreadDot.setVisibility(View.GONE);
}
String lockedSticky = topic.getSubject();
if (topic.isLocked())
lockedSticky += " " + context.getResources().getString(R.string.fa_lock);

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

@ -1,5 +1,10 @@
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.os.Bundle;
import android.widget.Toast;
@ -23,14 +28,9 @@ import gr.thmmy.mthmmy.base.BaseActivity;
import gr.thmmy.mthmmy.base.BaseApplication;
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 {
private static final String TOPIC_URL = "https://www.thmmy.gr/smf/index.php?topic=";
private static final String BOARD_URL = "https://www.thmmy.gr/smf/index.php?board=";
private static final String TOPIC_URL = forumUrl + "index.php?topic=";
private static final String BOARD_URL = forumUrl + "index.php?board=";
@Override
protected void onCreate(Bundle savedInstanceState) {

3
app/src/main/java/gr/thmmy/mthmmy/activities/bookmarks/BookmarksFragment.java

@ -1,7 +1,6 @@
package gr.thmmy.mthmmy.activities.bookmarks;
import android.app.Activity;
import android.content.Intent;
import android.graphics.drawable.Drawable;
import android.os.Bundle;
import android.view.LayoutInflater;
@ -18,8 +17,6 @@ import androidx.fragment.app.Fragment;
import java.util.ArrayList;
import gr.thmmy.mthmmy.R;
import gr.thmmy.mthmmy.activities.LoginActivity;
import gr.thmmy.mthmmy.activities.board.BoardActivity;
import gr.thmmy.mthmmy.model.Bookmark;
//TODO refactor using RecyclerView

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

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

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

@ -1,5 +1,7 @@
package gr.thmmy.mthmmy.activities.downloads;
import static gr.thmmy.mthmmy.activities.upload.UploadActivity.BUNDLE_UPLOAD_CATEGORY;
import android.content.Intent;
import android.net.Uri;
import android.os.AsyncTask;
@ -37,8 +39,6 @@ import okhttp3.Request;
import okhttp3.Response;
import timber.log.Timber;
import static gr.thmmy.mthmmy.activities.upload.UploadActivity.BUNDLE_UPLOAD_CATEGORY;
public class DownloadsActivity extends BaseActivity implements DownloadsAdapter.OnLoadMoreListener {
/**
* The key to use when putting download's url String to {@link DownloadsActivity}'s Bundle.
@ -48,7 +48,7 @@ public class DownloadsActivity extends BaseActivity implements DownloadsAdapter.
* The key to use when putting download's title String to {@link DownloadsActivity}'s Bundle.
*/
public static final String BUNDLE_DOWNLOADS_TITLE = "DOWNLOADS_TITLE";
private static final String downloadsIndexUrl = "https://www.thmmy.gr/smf/index.php?action=tpmod;dl;";
private static final String downloadsIndexUrl = forumUrl + "index.php?action=tpmod;dl;";
private String downloadsUrl;
private String downloadsNav;
private String downloadsTitle;
@ -57,7 +57,7 @@ public class DownloadsActivity extends BaseActivity implements DownloadsAdapter.
private MaterialProgressBar progressBar;
private RecyclerView recyclerView;
private DownloadsAdapter downloadsAdapter;
private FloatingActionButton uploadFAB;
// private FloatingActionButton uploadFAB;
private ParseDownloadPageTask parseDownloadPageTask;
private int numberOfPages = -1;
@ -124,9 +124,9 @@ public class DownloadsActivity extends BaseActivity implements DownloadsAdapter.
}
});
uploadFAB = findViewById(R.id.upload_fab);
uploadFAB.setEnabled(false);
uploadFAB.hide();
// uploadFAB = findViewById(R.id.upload_fab);
// uploadFAB.setEnabled(false);
// uploadFAB.hide();
parseDownloadPageTask = new ParseDownloadPageTask();
parseDownloadPageTask.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR, downloadsUrl);
@ -135,26 +135,26 @@ public class DownloadsActivity extends BaseActivity implements DownloadsAdapter.
@Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflates the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.downloads_menu, menu);
// getMenuInflater().inflate(R.menu.downloads_menu, menu);
super.onCreateOptionsMenu(menu);
return true;
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
// Handle presses on the action bar items
switch (item.getItemId()) {
case R.id.menu_upload:
Intent intent = new Intent(DownloadsActivity.this, UploadActivity.class);
Bundle extras = new Bundle();
extras.putString(BUNDLE_UPLOAD_CATEGORY, downloadsNav);
intent.putExtras(extras);
startActivity(intent);
return true;
default:
return super.onOptionsItemSelected(item);
}
}
// @Override
// public boolean onOptionsItemSelected(MenuItem item) {
// // Handle presses on the action bar items
// switch (item.getItemId()) {
// case R.id.menu_upload:
// Intent intent = new Intent(DownloadsActivity.this, UploadActivity.class);
// Bundle extras = new Bundle();
// extras.putString(BUNDLE_UPLOAD_CATEGORY, downloadsNav);
// intent.putExtras(extras);
// startActivity(intent);
// return true;
// default:
// return super.onOptionsItemSelected(item);
// }
// }
@Override
public void onLoadMore() {
@ -210,7 +210,7 @@ public class DownloadsActivity extends BaseActivity implements DownloadsAdapter.
@Override
protected void onPreExecute() {
if (!isLoadingMore) progressBar.setVisibility(ProgressBar.VISIBLE);
if (uploadFAB.getVisibility() != View.GONE) uploadFAB.setEnabled(false);
// if (uploadFAB.getVisibility() != View.GONE) uploadFAB.setEnabled(false);
}
@Override
@ -283,7 +283,7 @@ public class DownloadsActivity extends BaseActivity implements DownloadsAdapter.
parsedDownloads.add(download);
}
} catch (Exception e) {
throw new ParseException("Parsing failed (DownloadsActivity)");
throw new ParseException("Parsing failed (DownloadsActivity) for url " + downloadsUrl);
}
}
@ -312,7 +312,7 @@ public class DownloadsActivity extends BaseActivity implements DownloadsAdapter.
toolbar.setTitle(downloadsTitle);
++pagesLoaded;
if (uploadFAB.getVisibility() != View.GONE) uploadFAB.setEnabled(true);
// if (uploadFAB.getVisibility() != View.GONE) uploadFAB.setEnabled(true);
progressBar.setVisibility(ProgressBar.INVISIBLE);
downloadsAdapter.notifyDataSetChanged();
isLoadingMore = false;

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

@ -1,9 +1,12 @@
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.Intent;
import android.graphics.Typeface;
import android.os.Build;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
@ -25,10 +28,6 @@ import gr.thmmy.mthmmy.model.Download;
import gr.thmmy.mthmmy.model.ThmmyFile;
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> {
private final int VIEW_TYPE_DOWNLOAD = 0;
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));
}
else {
//noinspection deprecation
downloadViewHolder.upperLinear.setBackgroundColor(context.getResources().getColor(R.color.background));
}
downloadViewHolder.informationExpandable.setVisibility(View.VISIBLE);
downloadViewHolder.informationExpandableBtn.setVisibility(View.GONE);
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;
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.SharedPreferences;
import android.net.Uri;
@ -37,16 +47,6 @@ import gr.thmmy.mthmmy.model.ThmmyPage;
import gr.thmmy.mthmmy.model.TopicSummary;
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 {
//-----------------------------------------CLASS VARIABLES------------------------------------------

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

@ -9,6 +9,8 @@ import android.widget.ProgressBar;
import android.widget.RelativeLayout;
import android.widget.Toast;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.recyclerview.widget.DividerItemDecoration;
import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.swiperefreshlayout.widget.SwipeRefreshLayout;
@ -87,14 +89,14 @@ public class ForumFragment extends BaseFragment {
}
@Override
public void onActivityCreated(Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
if (categories.isEmpty()) {
forumTask = new ForumTask(this::onForumTaskStarted, this::onForumTaskFinished);
forumTask.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
}
Timber.d("onActivityCreated");
Timber.d("onViewCreated");
}
@Override
@ -197,7 +199,7 @@ public class ForumFragment extends BaseFragment {
//---------------------------------------ASYNC TASK-----------------------------------
private class ForumTask extends NewParseTask<ArrayList<Category>> {
private HttpUrl forumUrl = SessionManager.forumUrl; //may change upon collapse/expand
private HttpUrl forumUrl = SessionManager.getForumUrl(); //may change upon collapse/expand
ForumTask(OnTaskStartedListener onTaskStartedListener,
OnNetworkTaskFinishedListener<ArrayList<Category>> onParseTaskFinishedListener) {

2
app/src/main/java/gr/thmmy/mthmmy/activities/main/recent/RecentAdapter.java

@ -47,7 +47,7 @@ class RecentAdapter extends RecyclerView.Adapter<RecentAdapter.ViewHolder> {
if (BaseApplication.getInstance().isDisplayRelativeTimeEnabled()) {
String timestamp = topicSummary.getLastPostTimestamp();
try {
holder.mDateTimeView.setReferenceTime(Long.valueOf(timestamp));
holder.mDateTimeView.setReferenceTime(Long.parseLong(timestamp));
} catch (NumberFormatException e) {
Timber.e(e, "Invalid number format: %s", timestamp);
holder.mDateTimeView.setText(topicSummary.getLastPostSimplifiedDateTime());

6
app/src/main/java/gr/thmmy/mthmmy/activities/main/recent/RecentFragment.java

@ -9,6 +9,8 @@ import android.widget.ProgressBar;
import android.widget.RelativeLayout;
import android.widget.Toast;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.recyclerview.widget.DividerItemDecoration;
import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.swiperefreshlayout.widget.SwipeRefreshLayout;
@ -79,8 +81,8 @@ public class RecentFragment extends BaseFragment {
}
@Override
public void onActivityCreated(Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
if (topicSummaries.isEmpty()) {
recentTask = new RecentTask(this::onRecentTaskStarted, this::onRecentTaskFinished);
recentTask.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR, SessionManager.indexUrl.toString());

6
app/src/main/java/gr/thmmy/mthmmy/activities/main/unread/UnreadAdapter.java

@ -37,16 +37,16 @@ class UnreadAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> {
@Override
public void onBindViewHolder(@NonNull final RecyclerView.ViewHolder holder, final int position) {
TopicSummary topicSummary = unreadList.get(holder.getAdapterPosition());
TopicSummary topicSummary = unreadList.get(holder.getBindingAdapterPosition());
final UnreadAdapter.ViewHolder viewHolder = (UnreadAdapter.ViewHolder) holder;
viewHolder.mTitleView.setText(topicSummary.getSubject());
if (BaseApplication.getInstance().isDisplayRelativeTimeEnabled()) {
String timestamp = topicSummary.getLastPostTimestamp();
try {
viewHolder.mDateTimeView.setReferenceTime(Long.valueOf(timestamp));
viewHolder.mDateTimeView.setReferenceTime(Long.parseLong(timestamp));
} catch (NumberFormatException e) {
Timber.e(e, "Invalid number format: %s", timestamp);
Timber.e(e, "Invalid number format \"%s\" for %s", timestamp, topicSummary.getTopicUrl());
viewHolder.mDateTimeView.setText(topicSummary.getLastPostSimplifiedDateTime());
}
}

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

@ -10,6 +10,7 @@ import android.widget.TextView;
import android.widget.Toast;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.appcompat.app.AlertDialog;
import androidx.coordinatorlayout.widget.CoordinatorLayout;
import androidx.recyclerview.widget.DividerItemDecoration;
@ -91,8 +92,8 @@ public class UnreadFragment extends BaseFragment {
}
@Override
public void onActivityCreated(Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
if (topicSummaries.isEmpty()) {
hideMarkAsReadFAB();
unreadTask = new UnreadTask(this::onUnreadTaskStarted, UnreadFragment.this::onUnreadTaskCancelled, this::onUnreadTaskFinished);
@ -104,7 +105,6 @@ public class UnreadFragment extends BaseFragment {
markAsReadTask = new MarkAsReadTask(UnreadFragment.this::onMarkAsReadTaskStarted, UnreadFragment.this::onMarkAsReadTaskFinished);
}
@Override
public View onCreateView(@NonNull LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
@ -244,7 +244,7 @@ public class UnreadFragment extends BaseFragment {
if (loadedPages < numberOfPages) {
unreadTask = new UnreadTask(this::onUnreadTaskStarted, UnreadFragment.this::onUnreadTaskCancelled, this::onUnreadTaskFinished);
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
hideProgressUI();

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

@ -1,5 +1,11 @@
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.graphics.Color;
import android.graphics.Typeface;
@ -54,12 +60,6 @@ import me.zhanghai.android.materialprogressbar.MaterialProgressBar;
import okhttp3.Response;
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>
* containing this user's profile url using the key {@link #BUNDLE_PROFILE_URL}, a <b>String</b> containing

5
app/src/main/java/gr/thmmy/mthmmy/activities/profile/latestPosts/LatestPostsFragment.java

@ -7,6 +7,7 @@ import android.view.View;
import android.view.ViewGroup;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView;
@ -118,8 +119,8 @@ public class LatestPostsFragment extends BaseFragment {
}
@Override
public void onActivityCreated(Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
if (parsedTopicSummaries.isEmpty() && userHasPosts) {
profileLatestPostsTask = new LatestPostsTask();
profileLatestPostsTask.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR, profileUrl + ";sa=showPosts");

27
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.os.AsyncTask;
import android.os.Build;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
@ -10,6 +9,8 @@ import android.view.ViewGroup;
import android.widget.LinearLayout;
import android.widget.TextView;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.fragment.app.Fragment;
import com.github.mikephil.charting.charts.HorizontalBarChart;
@ -99,13 +100,13 @@ public class StatsFragment extends Fragment {
}
@Override
public void onActivityCreated(Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
if (profileStatsTask == null) {
profileStatsTask = new ProfileStatsTask();
profileStatsTask.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR, profileUrl + ";sa=statPanel");
}
Timber.d("onActivityCreated");
Timber.d("onViewCreated");
}
@Override
@ -228,7 +229,6 @@ public class StatsFragment extends Fragment {
private void populateLayout() {
onLoadingListener.onLoadingStats(true);
;
((TextView) mainContent.findViewById(R.id.general_statistics_title))
.setText(generalStatisticsTitle);
((TextView) mainContent.findViewById(R.id.general_statistics))
@ -294,14 +294,9 @@ public class StatsFragment extends Fragment {
mostPopularBoardsByPostsChartYAxis.setGranularity(1f);
BarDataSet mostPopularBoardsByPostsDataSet = new BarDataSet(mostPopularBoardsByPosts, null);
if (isAdded()) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
if (isAdded())
mostPopularBoardsByPostsDataSet.setColors(getResources().getColor(R.color.accent, null));
}
else
//noinspection deprecation
mostPopularBoardsByPostsDataSet.setColors(getResources().getColor(R.color.accent));
}
mostPopularBoardsByPostsDataSet.setDrawValues(false);
mostPopularBoardsByPostsDataSet.setValueTextColor(Color.WHITE);
@ -336,14 +331,8 @@ public class StatsFragment extends Fragment {
mostPopularBoardsByActivityChartYAxis.setLabelCount(10, false);
BarDataSet mostPopularBoardsByActivityDataSet = new BarDataSet(mostPopularBoardsByActivity, null);
if (isAdded()) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
if (isAdded())
mostPopularBoardsByActivityDataSet.setColors(getResources().getColor(R.color.accent, null));
}
else
//noinspection deprecation
mostPopularBoardsByActivityDataSet.setColors(getResources().getColor(R.color.accent));
}
mostPopularBoardsByActivityDataSet.setDrawValues(false);
mostPopularBoardsByActivityDataSet.setValueTextColor(Color.WHITE);

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

@ -12,6 +12,8 @@ import android.view.ViewGroup;
import android.widget.LinearLayout;
import android.widget.TextView;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.fragment.app.Fragment;
import org.jsoup.Jsoup;
@ -84,8 +86,8 @@ public class SummaryFragment extends Fragment {
}
@Override
public void onActivityCreated(Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
if (parsedProfileSummaryData.isEmpty()) {
summaryTask = new SummaryTask();
summaryTask.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR, profileSummaryDocument);
@ -187,10 +189,7 @@ public class SummaryFragment extends Fragment {
&& value.contains("@")) || key.startsWith("Website") || key.startsWith("Ιστοτόπος"))
textView.setMovementMethod(LinkMovementMethod.getInstance());
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M)
textView.setTextColor(getResources().getColor(R.color.primary_text, null));
else
textView.setTextColor(getResources().getColor(R.color.primary_text));
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;
import static gr.thmmy.mthmmy.activities.settings.SettingsActivity.DEFAULT_HOME_TAB;
import android.app.Activity;
import android.content.Context;
import android.content.Intent;
@ -22,8 +24,6 @@ import gr.thmmy.mthmmy.R;
import gr.thmmy.mthmmy.base.BaseApplication;
import timber.log.Timber;
import static gr.thmmy.mthmmy.activities.settings.SettingsActivity.DEFAULT_HOME_TAB;
public class SettingsFragment extends PreferenceFragmentCompat implements SharedPreferences.OnSharedPreferenceChangeListener {
private enum PREFS_TYPE {
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;
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.Intent;
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.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> {
private Context context;
private Shout[] shouts;

8
app/src/main/java/gr/thmmy/mthmmy/activities/shoutbox/ShoutboxFragment.java

@ -14,7 +14,7 @@ import android.widget.Toast;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.fragment.app.Fragment;
import androidx.lifecycle.ViewModelProviders;
import androidx.lifecycle.ViewModelProvider;
import androidx.recyclerview.widget.LinearLayoutManager;
import gr.thmmy.mthmmy.R;
@ -100,9 +100,9 @@ public class ShoutboxFragment extends Fragment {
}
@Override
public void onActivityCreated(@Nullable Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
shoutboxViewModel = ViewModelProviders.of(getActivity()).get(ShoutboxViewModel.class);
public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
shoutboxViewModel = new ViewModelProvider(getActivity()).get(ShoutboxViewModel.class);
shoutboxViewModel.getShoutboxMutableLiveData().observe(getViewLifecycleOwner(), shoutbox -> {
if (shoutbox != null) {
Timber.i("Shoutbox loaded successfully");

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

@ -1,5 +1,7 @@
package gr.thmmy.mthmmy.activities.topic;
import static gr.thmmy.mthmmy.services.NotificationService.NEW_POST_TAG;
import android.annotation.SuppressLint;
import android.app.NotificationManager;
import android.content.ClipData;
@ -31,7 +33,7 @@ import android.widget.Toast;
import androidx.appcompat.app.AlertDialog;
import androidx.core.content.res.ResourcesCompat;
import androidx.lifecycle.ViewModelProviders;
import androidx.lifecycle.ViewModelProvider;
import androidx.recyclerview.widget.RecyclerView;
import com.google.android.material.floatingactionbutton.FloatingActionButton;
@ -60,8 +62,6 @@ import gr.thmmy.mthmmy.views.editorview.EmojiKeyboard;
import me.zhanghai.android.materialprogressbar.MaterialProgressBar;
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
* bundle a <b>String</b> containing this topic's url using the key {@link #BUNDLE_TOPIC_URL}.
@ -131,7 +131,7 @@ public class TopicActivity extends BaseActivity implements TopicAdapter.OnPostFo
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_topic);
// get TopicViewModel instance
viewModel = ViewModelProviders.of(this).get(TopicViewModel.class);
viewModel = new ViewModelProvider(this).get(TopicViewModel.class);
subscribeUI();
Bundle extras = getIntent().getExtras();
@ -228,11 +228,12 @@ public class TopicActivity extends BaseActivity implements TopicAdapter.OnPostFo
@Override
public boolean onOptionsItemSelected(MenuItem item) {
// Handle presses on the action bar items
switch (item.getItemId()) {
case R.id.menu_bookmark:
int itemId = item.getItemId();
if (itemId == R.id.menu_bookmark) {
topicMenuBookmarkClick();
return true;
case R.id.menu_info:
}
else if (itemId == R.id.menu_info) {
AlertDialog.Builder builder = new AlertDialog.Builder(this, R.style.AppCompatAlertDialogStyleAccent);
LayoutInflater inflater = this.getLayoutInflater();
LinearLayout infoDialog = (LinearLayout) inflater.inflate(R.layout.dialog_topic_info
@ -255,15 +256,15 @@ public class TopicActivity extends BaseActivity implements TopicAdapter.OnPostFo
topicInfoDialog = builder.create();
topicInfoDialog.show();
return true;
case R.id.menu_share:
Intent sendIntent = new Intent(android.content.Intent.ACTION_SEND);
}
else if (itemId == R.id.menu_share) {
Intent sendIntent = new Intent(Intent.ACTION_SEND);
sendIntent.setType("text/plain");
sendIntent.putExtra(android.content.Intent.EXTRA_TEXT, viewModel.getTopicUrl());
sendIntent.putExtra(Intent.EXTRA_TEXT, viewModel.getTopicUrl());
startActivity(Intent.createChooser(sendIntent, "Share via"));
return true; //invalidateOptionsMenu();
default:
return super.onOptionsItemSelected(item);
}
return super.onOptionsItemSelected(item);
}
@Override

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

@ -1,5 +1,18 @@
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.TargetApi;
import android.content.Context;
@ -77,19 +90,6 @@ import gr.thmmy.mthmmy.views.editorview.EditorView;
import gr.thmmy.mthmmy.views.editorview.IEmojiKeyboard;
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.
*/
@ -393,11 +393,7 @@ class TopicAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> {
if (currentPost.getAttachedFiles() != null && currentPost.getAttachedFiles().size() != 0) {
int filesTextColor;
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
filesTextColor = context.getResources().getColor(R.color.accent, null);
}
else
filesTextColor = context.getResources().getColor(R.color.accent);
for (final ThmmyFile attachedFile : currentPost.getAttachedFiles()) {
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) {
int lastEditTextColor;
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
lastEditTextColor = context.getResources().getColor(R.color.white, null);
}
else
lastEditTextColor = context.getResources().getColor(R.color.white);
final TextView lastEdit = new TextView(context);
lastEdit.setTextSize(12f);
@ -709,8 +702,8 @@ class TopicAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> {
SharedPreferences drafts = context.getSharedPreferences(context.getString(R.string.pref_topic_drafts_key),
Context.MODE_PRIVATE);
replyText += drafts.getString(String.valueOf(viewModel.getTopicId()), "");
if (viewModel.getBuildedQuotes() != null && !viewModel.getBuildedQuotes().isEmpty())
replyText += viewModel.getBuildedQuotes();
if (viewModel.getBuiltQuotes() != null && !viewModel.getBuiltQuotes().isEmpty())
replyText += viewModel.getBuiltQuotes();
}
holder.replyEditor.setText(replyText);
holder.replyEditor.getEditText().setSelection(holder.replyEditor.getText().length());

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

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

10
app/src/main/java/gr/thmmy/mthmmy/activities/topic/tasks/PrepareForEditTask.java

@ -7,8 +7,6 @@ import org.jsoup.nodes.Document;
import org.jsoup.nodes.Element;
import org.jsoup.select.Selector;
import java.io.IOException;
import gr.thmmy.mthmmy.base.BaseApplication;
import okhttp3.OkHttpClient;
import okhttp3.Request;
@ -61,8 +59,12 @@ public class PrepareForEditTask extends AsyncTask<String, Void, PrepareForEditRe
icon = form.select("select[name=icon]>option[selected]").first().attr("value");
return new PrepareForEditResult(postText, commitEditURL, numReplies, seqnum, sc, topic, icon, position, true);
} catch (IOException | Selector.SelectorParseException e) {
Timber.e(e, "Prepare failed.");
} catch (NullPointerException | Selector.SelectorParseException e) {
// TODO: Convert this task to (New)ParseTask (?) / handle parsing errors in a better way
Timber.e(e, "Preparing for edit failed (parsing error).");
return new PrepareForEditResult(null, null, null, null, null, null, null, position, false);
} catch (Exception e) {
Timber.i("Preparing for edit failed (other error).");
return new PrepareForEditResult(null, null, null, null, null, null, null, position, false);
}
}

10
app/src/main/java/gr/thmmy/mthmmy/activities/topic/tasks/PrepareForReplyResult.java

@ -1,17 +1,17 @@
package gr.thmmy.mthmmy.activities.topic.tasks;
public class PrepareForReplyResult {
private final String numReplies, seqnum, sc, topic, buildedQuotes;
private final String numReplies, seqnum, sc, topic, builtQuotes;
private boolean successful;
public PrepareForReplyResult(boolean successful, String numReplies, String seqnum, String sc, String topic, String buildedQuotes) {
public PrepareForReplyResult(boolean successful, String numReplies, String seqnum, String sc, String topic, String builtQuotes) {
this.successful = successful;
this.numReplies = numReplies;
this.seqnum = seqnum;
this.sc = sc;
this.topic = topic;
this.buildedQuotes = buildedQuotes;
this.builtQuotes = builtQuotes;
}
public String getNumReplies() {
@ -30,8 +30,8 @@ public class PrepareForReplyResult {
return topic;
}
public String getBuildedQuotes() {
return buildedQuotes;
public String getBuiltQuotes() {
return builtQuotes;
}
public boolean isSuccessful() {

18
app/src/main/java/gr/thmmy/mthmmy/activities/topic/tasks/PrepareForReplyTask.java

@ -49,33 +49,33 @@ public class PrepareForReplyTask extends AsyncTask<Integer, Void, PrepareForRepl
seqnum = document.select("input[name=seqnum]").first().attr("value");
sc = document.select("input[name=sc]").first().attr("value");
topic = document.select("input[name=topic]").first().attr("value");
} catch (NullPointerException e) {
} catch (NullPointerException | Selector.SelectorParseException e) {
// TODO: Convert this task to (New)ParseTask (?) / handle parsing errors in a better way
Timber.e(e, "Prepare failed (1)");
Timber.e(e, "Preparing for reply failed (parsing error).");
return new PrepareForReplyResult(false, null, null, null, null, null);
} catch (IOException | Selector.SelectorParseException e) {
Timber.e(e, "Prepare failed (2)");
} catch (Exception e) {
Timber.i("Preparing for reply failed (other error).");
return new PrepareForReplyResult(false, null, null, null, null, null);
}
StringBuilder buildedQuotes = new StringBuilder();
StringBuilder builtQuotes = new StringBuilder();
for (Integer postIndex : postIndices) {
request = new Request.Builder()
.url("https://www.thmmy.gr/smf/index.php?action=quotefast;quote=" +
.url(BaseApplication.getForumUrl() + "index.php?action=quotefast;quote=" +
postIndex + ";" + "sesc=" + sc + ";xml")
.build();
try {
Response response = client.newCall(request).execute();
String body = response.body().string();
body = Parser.unescapeEntities(body, false);
buildedQuotes.append(body.substring(body.indexOf("<quote>") + 7, body.indexOf("</quote>")));
buildedQuotes.append("\n\n");
builtQuotes.append(body.substring(body.indexOf("<quote>") + 7, body.indexOf("</quote>")));
builtQuotes.append("\n\n");
} catch (IOException | Selector.SelectorParseException e) {
Timber.e(e, "Quote building failed.");
return new PrepareForReplyResult(false, null, null, null, null, null);
}
}
return new PrepareForReplyResult(true, numReplies, seqnum, sc, topic, buildedQuotes.toString());
return new PrepareForReplyResult(true, numReplies, seqnum, sc, topic, builtQuotes.toString());
}
@Override

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

@ -1,5 +1,7 @@
package gr.thmmy.mthmmy.activities.topic.tasks;
import static gr.thmmy.mthmmy.activities.topic.Posting.replyStatus;
import android.os.AsyncTask;
import java.io.IOException;
@ -13,8 +15,6 @@ import okhttp3.RequestBody;
import okhttp3.Response;
import timber.log.Timber;
import static gr.thmmy.mthmmy.activities.topic.Posting.replyStatus;
public class ReplyTask extends AsyncTask<String, Void, Posting.REPLY_STATUS> {
private ReplyTaskCallbacks listener;
private boolean includeAppSignature;
@ -45,7 +45,7 @@ public class ReplyTask extends AsyncTask<String, Void, Posting.REPLY_STATUS> {
.addFormDataPart("icon", "xx")
.build();
Request post = new Request.Builder()
.url("https://www.thmmy.gr/smf/index.php?action=post2")
.url(BaseApplication.getForumUrl() + "index.php?action=post2")
.header("User-Agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/56.0.2924.87 Safari/537.36")
.post(postBody)
.build();

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

@ -1,5 +1,15 @@
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.PendingIntent;
import android.content.Context;
@ -74,16 +84,6 @@ import gr.thmmy.mthmmy.views.AppCompatSpinnerWithoutDefault;
import me.zhanghai.android.materialprogressbar.MaterialProgressBar;
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 {
/**
* The key to use when putting upload's category String to {@link UploadActivity}'s Bundle.
@ -91,7 +91,7 @@ public class UploadActivity extends BaseActivity {
public static final String BUNDLE_UPLOAD_CATEGORY = "UPLOAD_CATEGORY";
public static final String firebaseConfigUploadsCoursesKey = "uploads_courses";
private static final String uploadIndexUrl = "https://www.thmmy.gr/smf/index.php?action=tpmod;dl=upload";
private static final String uploadIndexUrl = forumUrl + "index.php?action=tpmod;dl=upload";
private static final String uploadedFromTHMMYPromptHtml = "<br /><div style=\"text-align: right;\"><span style=\"font-style: italic;\">uploaded from <a href=\"https://play.google.com/store/apps/details?id=gr.thmmy.mthmmy\">mTHMMY</a></span>";
/**
* Request codes used in activities for result (AFR) calls
@ -169,7 +169,7 @@ public class UploadActivity extends BaseActivity {
}
createDrawer();
drawer.setSelection(UPLOAD_ID);
// drawer.setSelection(UPLOAD_ID);
progressBar = findViewById(R.id.progressBar);
@ -434,7 +434,7 @@ public class UploadActivity extends BaseActivity {
@Override
protected void onResume() {
drawer.setSelection(UPLOAD_ID);
// drawer.setSelection(UPLOAD_ID);
super.onResume();
}

2
app/src/main/java/gr/thmmy/mthmmy/activities/upload/UploadFieldsBuilderActivity.java

@ -99,7 +99,7 @@ public class UploadFieldsBuilderActivity extends BaseActivity {
}
createDrawer();
drawer.setSelection(UPLOAD_ID, false);
// drawer.setSelection(UPLOAD_ID, false);
semesterChooserLinear = findViewById(R.id.upload_fields_builder_choose_semester);
semesterRadio = findViewById(R.id.upload_fields_builder_semester_radio_group);

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.UnsupportedEncodingException;
import java.nio.charset.Charset;
import java.nio.charset.StandardCharsets;
/**
* 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";
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 TWO_HYPHENS = "--";
@ -42,7 +43,7 @@ public class MultipartUploadTask extends HttpUploadTask {
boundaryBytes = (TWO_HYPHENS + boundary + NEW_LINE).getBytes(US_ASCII);
trailerBytes = (TWO_HYPHENS + boundary + TWO_HYPHENS + NEW_LINE).getBytes(US_ASCII);
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("Content-Type", "multipart/form-data; boundary=" + boundary);

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

@ -1,5 +1,15 @@
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.app.ProgressDialog;
import android.content.Context;
@ -8,7 +18,6 @@ import android.content.SharedPreferences;
import android.content.pm.PackageManager;
import android.net.Uri;
import android.os.AsyncTask;
import android.os.Build;
import android.os.Bundle;
import android.view.MenuItem;
import android.view.View;
@ -23,7 +32,7 @@ import androidx.appcompat.app.AppCompatActivity;
import androidx.appcompat.widget.Toolbar;
import androidx.core.content.ContextCompat;
import androidx.core.content.FileProvider;
import androidx.lifecycle.ViewModelProviders;
import androidx.lifecycle.ViewModelProvider;
import androidx.preference.PreferenceManager;
import com.google.android.material.bottomsheet.BottomSheetDialog;
@ -67,16 +76,6 @@ import ru.noties.markwon.Markwon;
import ru.noties.markwon.SpannableConfiguration;
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 {
// Client & Cookies
protected static OkHttpClient client;
@ -106,6 +105,8 @@ public abstract class BaseActivity extends AppCompatActivity {
private boolean isMainActivity;
private boolean isUserConsentDialogShown; //Needed because sometimes onResume is being called twice
protected static String forumUrl = BaseApplication.getForumUrl(); // For convenience
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
@ -126,7 +127,7 @@ public abstract class BaseActivity extends AppCompatActivity {
sharedPreferences = PreferenceManager.getDefaultSharedPreferences(this);
BaseViewModel baseViewModel = ViewModelProviders.of(this).get(BaseViewModel.class);
BaseViewModel baseViewModel = new ViewModelProvider(this).get(BaseViewModel.class);
baseViewModel.getCurrentPageBookmark().observe(this, thisPageBookmark -> setTopicBookmark(thisPageBookmarkMenuButton));
storage = new Storage(getApplicationContext());
@ -166,7 +167,7 @@ public abstract class BaseActivity extends AppCompatActivity {
//------------------------------------------DRAWER STUFF----------------------------------------
protected static final int HOME_ID = 0;
protected static final int DOWNLOADS_ID = 1;
protected static final int UPLOAD_ID = 2;
//protected static final int UPLOAD_ID = 2; //Removed until fixed
protected static final int BOOKMARKS_ID = 3;
protected static final int LOG_ID = 4;
protected static final int ABOUT_ID = 5;
@ -266,14 +267,14 @@ public abstract class BaseActivity extends AppCompatActivity {
.withIcon(downloadsIcon)
.withSelectedIcon(downloadsIconSelected);
uploadItem = new PrimaryDrawerItem()
.withTextColor(primaryColor)
.withSelectedColor(selectedPrimaryColor)
.withSelectedTextColor(selectedSecondaryColor)
.withIdentifier(UPLOAD_ID)
.withName(R.string.upload)
.withIcon(uploadIcon)
.withSelectedIcon(uploadIconSelected);
// uploadItem = new PrimaryDrawerItem()
// .withTextColor(primaryColor)
// .withSelectedColor(selectedPrimaryColor)
// .withSelectedTextColor(selectedSecondaryColor)
// .withIdentifier(UPLOAD_ID)
// .withName(R.string.upload)
// .withIcon(uploadIcon)
// .withSelectedIcon(uploadIconSelected);
shoutboxItem = new PrimaryDrawerItem()
.withTextColor(primaryColor)
@ -346,7 +347,7 @@ public abstract class BaseActivity extends AppCompatActivity {
if (sessionManager.isLoggedIn()) {
Intent intent = new Intent(BaseActivity.this, ProfileActivity.class);
Bundle extras = new Bundle();
extras.putString(BUNDLE_PROFILE_URL, "https://www.thmmy.gr/smf/index.php?action=profile");
extras.putString(BUNDLE_PROFILE_URL, forumUrl + "index.php?action=profile");
if (!sessionManager.hasAvatar())
extras.putString(BUNDLE_PROFILE_THUMBNAIL_URL, "");
else
@ -394,12 +395,12 @@ public abstract class BaseActivity extends AppCompatActivity {
startActivity(intent);
}
}
else if (drawerItem.equals(UPLOAD_ID)) {
if (!(BaseActivity.this instanceof UploadActivity)) {
Intent intent = new Intent(BaseActivity.this, UploadActivity.class);
startActivity(intent);
}
}
// else if (drawerItem.equals(UPLOAD_ID)) {
// if (!(BaseActivity.this instanceof UploadActivity)) {
// Intent intent = new Intent(BaseActivity.this, UploadActivity.class);
// startActivity(intent);
// }
// }
else if (drawerItem.equals(BOOKMARKS_ID)) {
if (!(BaseActivity.this instanceof BookmarksActivity)) {
Intent intent = new Intent(BaseActivity.this, BookmarksActivity.class);
@ -452,7 +453,7 @@ public abstract class BaseActivity extends AppCompatActivity {
if (drawer != null) {
if (!sessionManager.isLoggedIn()) { //When logged out or if user is guest
drawer.removeItem(DOWNLOADS_ID);
drawer.removeItem(UPLOAD_ID);
//drawer.removeItem(UPLOAD_ID);
loginLogoutItem.withName(R.string.login).withIcon(loginIcon); //Swap logout with login
profileDrawerItem.withName(sessionManager.getUsername());
setDefaultAvatar();
@ -693,7 +694,6 @@ public abstract class BaseActivity extends AppCompatActivity {
//True if permissions are OK
protected boolean checkPerms() {
if (Build.VERSION.SDK_INT > Build.VERSION_CODES.LOLLIPOP_MR1) {
Timber.i("Checking storage permissions.");
String[] PERMISSIONS_STORAGE = {
Manifest.permission.READ_EXTERNAL_STORAGE,
@ -702,13 +702,9 @@ public abstract class BaseActivity extends AppCompatActivity {
return !(checkSelfPermission(PERMISSIONS_STORAGE[0]) == PackageManager.PERMISSION_DENIED ||
checkSelfPermission(PERMISSIONS_STORAGE[1]) == PackageManager.PERMISSION_DENIED);
}
return true;
}
//Display popup for user to grant permission
protected void requestPerms(int code) {
//Runtime permissions request for devices with API >= 23
if (Build.VERSION.SDK_INT > Build.VERSION_CODES.LOLLIPOP_MR1) {
String[] PERMISSIONS_STORAGE = {
Manifest.permission.READ_EXTERNAL_STORAGE,
Manifest.permission.WRITE_EXTERNAL_STORAGE};
@ -716,7 +712,6 @@ public abstract class BaseActivity extends AppCompatActivity {
Timber.i("Requesting storage permissions (code %d).", code);
requestPermissions(PERMISSIONS_STORAGE, code);
}
}
@Override
public void onRequestPermissionsResult(int permsRequestCode, @NonNull String[] permissions

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

@ -1,8 +1,14 @@
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.content.Context;
import android.content.SharedPreferences;
import android.content.res.Resources;
import android.graphics.drawable.Drawable;
import android.net.Uri;
import android.os.Bundle;
@ -44,16 +50,16 @@ import okhttp3.OkHttpClient;
import okhttp3.Request;
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{
private static BaseApplication baseApplication; //BaseApplication singleton
private CrashReportingTree crashReportingTree;
//Global variables
private static String forumUrl;
private static String forumHost;
private static String forumHostSimple;
//Firebase
private static String firebaseProjectId;
private FirebaseAnalytics firebaseAnalytics;
@ -70,10 +76,6 @@ public class BaseApplication extends Application implements Executor{
private static float widthDp;
private static int widthPxl, heightPxl;
public static BaseApplication getInstance() {
return baseApplication;
}
@Override
public void onCreate() {
super.onCreate();
@ -83,6 +85,11 @@ public class BaseApplication extends Application implements Executor{
if (BuildConfig.DEBUG)
Timber.plant(new Timber.DebugTree());
Resources resources = getApplicationContext().getResources();
forumUrl = resources.getString(R.string.forum_url);
forumHost = resources.getString(R.string.forum_host);
forumHostSimple= resources.getString(R.string.forum_host_simple);
//Shared Preferences
SharedPreferences sessionSharedPrefs = getSharedPreferences(getString(R.string.session_shared_prefs), MODE_PRIVATE);
SharedPreferences settingsSharedPrefs = PreferenceManager.getDefaultSharedPreferences(this);
@ -157,7 +164,7 @@ public class BaseApplication extends Application implements Executor{
.addInterceptor(chain -> {
Request request = chain.request();
HttpUrl oldUrl = chain.request().url();
if (Objects.equals(chain.request().url().host(), "www.thmmy.gr")
if (Objects.equals(chain.request().url().host(), forumHost)
&& !oldUrl.toString().contains("theme=4")) {
//Probably works but needs more testing:
HttpUrl newUrl = oldUrl.newBuilder().addQueryParameter("theme", "4").build();
@ -208,6 +215,22 @@ public class BaseApplication extends Application implements Executor{
//-------------------- 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() {
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)
fragmentInteractionListener = (FragmentInteractionListener) context;
else
throw new RuntimeException(context.toString()
throw new RuntimeException(context
+ " must implement OnFragmentInteractionListener");
}

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

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

29
app/src/main/java/gr/thmmy/mthmmy/model/ThmmyPage.java

@ -6,6 +6,7 @@ import java.util.Objects;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import gr.thmmy.mthmmy.base.BaseApplication;
import timber.log.Timber;
/**
@ -20,6 +21,14 @@ public class ThmmyPage {
@SuppressWarnings("unused")
private static final String TAG = "LinkTarget";
private static final String forumUrl = BaseApplication.getForumUrl();
private static final String forumHost = BaseApplication.getForumHost();
private static final String forumHostHttp = "http://" + forumHost;
private static final String forumHostHttps = "https://" + forumHost;
private static final String forumHostSimple = BaseApplication.getForumHostSimple();
private static final String forumHostSimpleHttp = "http://" + forumHostSimple;
private static final String forumHostSimpleHttps = "https://" + forumHostSimple;
/**
* An enum describing a link's target by defining the types:<ul>
* <li>{@link #NOT_THMMY}</li>
@ -142,9 +151,9 @@ public class ThmmyPage {
final String host = uri.getHost();
final String uriString = uri.toString();
if (Objects.equals(uriString, "http://thmmy.gr")
|| Objects.equals(uriString, "https://thmmy.gr")) return PageCategory.INDEX;
if (Objects.equals(host, "www.thmmy.gr")) {
if (Objects.equals(uriString, forumHostSimpleHttp)
|| Objects.equals(uriString, forumHostSimpleHttps)) return PageCategory.INDEX;
if (Objects.equals(host, forumHost)) {
if (uriString.contains("topic=")) return PageCategory.TOPIC;
else if (uriString.contains("board=")) return PageCategory.BOARD;
else if (uriString.contains("action=profile")) {
@ -160,12 +169,12 @@ public class ThmmyPage {
return PageCategory.DOWNLOADS_FILE;
else if (uriString.contains("action=tpmod;dl"))
return PageCategory.DOWNLOADS_CATEGORY;
else if (uriString.contains("action=forum") || Objects.equals(uriString, "www.thmmy.gr")
|| Objects.equals(uriString, "http://www.thmmy.gr")
|| Objects.equals(uriString, "https://www.thmmy.gr")
|| Objects.equals(uriString, "https://www.thmmy.gr/smf/index.php"))
else if (uriString.contains("action=forum") || Objects.equals(uriString, forumHost)
|| Objects.equals(uriString, forumHostHttp)
|| Objects.equals(uriString, forumHostHttps)
|| Objects.equals(uriString, forumUrl + "index.php"))
return PageCategory.INDEX;
Timber.v("Unknown thmmy link found, link: %s", uriString);
Timber.v("Unknown thmmy link found, link: %s", uriString); //TODO: maybe report this?
return PageCategory.UNKNOWN_THMMY;
}
return PageCategory.NOT_THMMY;
@ -184,11 +193,9 @@ public class ThmmyPage {
public static String getTopicId(String topicUrl) {
if (resolvePageCategory(Uri.parse(topicUrl)) == PageCategory.TOPIC) {
Matcher topicIdMatcher = Pattern.compile("topic=[0-9]+").matcher(topicUrl);
if (topicIdMatcher.find()) {
if (topicIdMatcher.find())
return topicUrl.substring(topicIdMatcher.start() + 6, topicIdMatcher.end());
}
else return null;
}
return null;
}

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

@ -1,5 +1,7 @@
package gr.thmmy.mthmmy.services;
import static gr.thmmy.mthmmy.utils.FileUtils.getMimeType;
import android.app.DownloadManager;
import android.content.Context;
import android.net.Uri;
@ -15,8 +17,6 @@ import gr.thmmy.mthmmy.model.ThmmyFile;
import okhttp3.Cookie;
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
* DownloadManager system service.

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

@ -1,5 +1,17 @@
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.NotificationChannel;
import android.app.NotificationManager;
@ -13,7 +25,6 @@ import android.os.Build;
import android.os.Bundle;
import android.service.notification.StatusBarNotification;
import androidx.annotation.RequiresApi;
import androidx.core.app.NotificationCompat;
import androidx.preference.PreferenceManager;
@ -34,18 +45,6 @@ import gr.thmmy.mthmmy.model.Bookmark;
import gr.thmmy.mthmmy.model.PostNotification;
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 {
private static final int buildVersion = Build.VERSION.SDK_INT;
private static final int disabledNotifiationsLedColor = Color.argb(0, 0, 0, 0);
@ -171,7 +170,7 @@ public class NotificationService extends FirebaseMessagingService {
}
//Builds notification
String topicUrl = "https://www.thmmy.gr/smf/index.php?topic=" + postNotification.getTopicId() + "." + postNotification.getPostId();
String topicUrl = BaseApplication.getForumUrl() + "index.php?topic=" + postNotification.getTopicId() + "." + postNotification.getPostId();
Intent intent = new Intent(this, MainActivity.class);
Bundle extras = new Bundle();
extras.putString(BUNDLE_TOPIC_URL, topicUrl);
@ -204,7 +203,6 @@ public class NotificationService extends FirebaseMessagingService {
int newPostsCount = 1;
if (buildVersion >= Build.VERSION_CODES.M) {
Notification existingNotification = getActiveNotification(notificationId);
if (existingNotification != null) {
newPostsCount = existingNotification.extras.getInt(NEW_POSTS_COUNT) + 1;
@ -213,7 +211,6 @@ public class NotificationService extends FirebaseMessagingService {
else
contentText = newPostsCount + " new posts in " + postNotification.getTopicTitle();
}
}
Bundle notificationExtras = new Bundle();
notificationExtras.putInt(NEW_POSTS_COUNT, newPostsCount);
@ -250,10 +247,7 @@ public class NotificationService extends FirebaseMessagingService {
if (buildVersion < Build.VERSION_CODES.O)
notificationBuilder.setPriority(PRIORITY_MAX);
boolean createSummaryNotification = false;
if (buildVersion >= Build.VERSION_CODES.M)
createSummaryNotification = otherNotificationsExist(notificationId);
boolean createSummaryNotification = otherNotificationsExist(notificationId);
NotificationCompat.Builder summaryNotificationBuilder = null;
if (createSummaryNotification) {
@ -281,7 +275,6 @@ public class NotificationService extends FirebaseMessagingService {
notificationManager.notify(SUMMARY_TAG, 0, summaryNotificationBuilder.build());
}
@RequiresApi(api = Build.VERSION_CODES.M)
private Notification getActiveNotification(int notificationId) {
NotificationManager notificationManager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
if (notificationManager != null) {
@ -295,7 +288,6 @@ public class NotificationService extends FirebaseMessagingService {
return null;
}
@RequiresApi(api = Build.VERSION_CODES.M)
private boolean otherNotificationsExist(int notificationId) {
NotificationManager notificationManager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
if (notificationManager != null) {

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

@ -1,5 +1,8 @@
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.select.Elements;
@ -11,9 +14,6 @@ import gr.thmmy.mthmmy.utils.parsing.ParseException;
import okhttp3.Response;
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> {
private String logoutLink;

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

@ -1,5 +1,8 @@
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.select.Elements;
@ -9,9 +12,6 @@ import gr.thmmy.mthmmy.utils.networking.NetworkTask;
import gr.thmmy.mthmmy.utils.parsing.ParseException;
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> {
private String markAsReadLink;

22
app/src/main/java/gr/thmmy/mthmmy/session/SessionManager.java

@ -18,6 +18,7 @@ import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import gr.thmmy.mthmmy.base.BaseApplication;
import gr.thmmy.mthmmy.utils.parsing.ParseException;
import okhttp3.Cookie;
import okhttp3.FormBody;
@ -34,13 +35,14 @@ import timber.log.Timber;
*/
public class SessionManager {
//Generic constants
public static final HttpUrl indexUrl = HttpUrl.parse("https://www.thmmy.gr/smf/index.php?theme=4");
public static final HttpUrl forumUrl = HttpUrl.parse("https://www.thmmy.gr/smf/index.php?action=forum;theme=4");
private static final HttpUrl loginUrl = HttpUrl.parse("https://www.thmmy.gr/smf/index.php?action=login2");
public static final HttpUrl unreadUrl = HttpUrl.parse("https://www.thmmy.gr/smf/index.php?action=unread;all;start=0;theme=4");
public static final HttpUrl shoutboxUrl = HttpUrl.parse("https://www.thmmy.gr/smf/index.php?action=tpmod;sa=shoutbox;theme=4");
static final String baseLogoutLink = "https://www.thmmy.gr/smf/index.php?action=logout;sesc=";
static final String baseMarkAllAsReadLink = "https://www.thmmy.gr/smf/index.php?action=markasread;sa=all;sesc=";
private final static String FORUM_URL = BaseApplication.getForumUrl();
public static final HttpUrl indexUrl = HttpUrl.parse(FORUM_URL + "index.php?theme=4");
private static final HttpUrl forumUrl = HttpUrl.parse(FORUM_URL + "index.php?action=forum;theme=4");
private static final HttpUrl loginUrl = HttpUrl.parse(FORUM_URL + "index.php?action=login2");
public static final HttpUrl unreadUrl = HttpUrl.parse(FORUM_URL + "index.php?action=unread;all;start=0;theme=4");
public static final HttpUrl shoutboxUrl = HttpUrl.parse(FORUM_URL + "index.php?action=tpmod;sa=shoutbox;theme=4");
static final String baseLogoutLink = FORUM_URL + "index.php?action=logout;sesc=";
static final String baseMarkAllAsReadLink = FORUM_URL + "index.php?action=markasread;sa=all;sesc=";
private static final String guestName = "Guest";
//Response Codes - make sure they do not overlap with NetworkResultCodes, just in case
@ -190,6 +192,10 @@ public class SessionManager {
}
//--------------------------------------- GETTERS ------------------------------------------------
public static HttpUrl getForumUrl() {
return forumUrl;
}
public String getUsername() {
return sessionSharedPrefs.getString(USERNAME, USERNAME);
}
@ -291,7 +297,7 @@ public class SessionManager {
if (elements.size() == 1) {
String link = elements.first().attr("href");
Pattern pattern = Pattern.compile("https://www.thmmy.gr/smf/index.php\\?action=profile;u=(\\d*);sa=showPosts");
Pattern pattern = Pattern.compile(FORUM_URL + "index.php\\?action=profile;u=(\\d*);sa=showPosts");
Matcher matcher = pattern.matcher(link);
if (matcher.find())
return Integer.parseInt(matcher.group(1));

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

@ -1,13 +1,13 @@
package gr.thmmy.mthmmy.utils;
import androidx.annotation.VisibleForTesting;
import static android.text.format.DateUtils.DAY_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.SECOND_IN_MILLIS;
import static android.text.format.DateUtils.YEAR_IN_MILLIS;
import androidx.annotation.VisibleForTesting;
public class DateTimeUtils {
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;
import static gr.thmmy.mthmmy.services.DownloadHelper.SAVE_DIR;
import android.content.Context;
import android.database.Cursor;
import android.net.Uri;
@ -10,18 +12,17 @@ import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import java.io.File;
import java.util.Locale;
import gr.thmmy.mthmmy.R;
import static gr.thmmy.mthmmy.services.DownloadHelper.SAVE_DIR;
public class FileUtils {
@NonNull
public static String getMimeType(@NonNull String fileName) {
String type = null;
final String extension = MimeTypeMap.getFileExtensionFromUrl(fileName);
if (extension != null)
type = MimeTypeMap.getSingleton().getMimeTypeFromExtension(extension.toLowerCase());
type = MimeTypeMap.getSingleton().getMimeTypeFromExtension(extension.toLowerCase(Locale.ROOT));
if (type == null)
type = "*/*";
@ -39,7 +40,7 @@ public class FileUtils {
if (!filename.contains(".")) {
return null;
}
if (filename.toLowerCase().endsWith(".tar.gz")) {
if (filename.toLowerCase(Locale.ROOT).endsWith(".tar.gz")) {
fileExtension = filename.substring(filename.length() - 7);
}
else {
@ -63,7 +64,9 @@ public class FileUtils {
if (uri.getScheme().equals("content")) {
try (Cursor cursor = context.getContentResolver().query(uri, null, null, null, null)) {
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) {
try (Cursor cursor = context.getContentResolver().query(uri, null, null, null, null)) {
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;
@ -97,7 +102,7 @@ public class FileUtils {
*/
@NonNull
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")
|| filename.contains("png"))

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

@ -1,5 +1,12 @@
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.content.Context;
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.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 {
private HTMLUtils() {
}

2
app/src/main/java/gr/thmmy/mthmmy/utils/networking/NetworkTask.java

@ -57,7 +57,7 @@ public abstract class NetworkTask<T> extends ExternalAsyncTask<String, Parcel<T>
try {
response = sendRequest(BaseApplication.getInstance().getClient(), input);
} catch (IOException e) {
Timber.e(e, "Error connecting to thmmy.gr");
Timber.e(e, "Error connecting to forum!");
return new Parcel<>(NetworkResultCodes.NETWORK_ERROR, null);
}
String responseBodyString;

244
app/src/main/java/gr/thmmy/mthmmy/utils/parsing/ParseHelpers.java

@ -9,13 +9,15 @@ import java.util.HashMap;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import gr.thmmy.mthmmy.base.BaseApplication;
/**
* This class consists exclusively of static classes (enums) and methods (excluding methods of inner
* classes). It can be used to resolve a page's language and state or fix embedded videos html code
* and obfuscated emails.
*/
public class ParseHelpers {
private final static String FORUM_URL = BaseApplication.getForumUrl();
/**
* An enum describing a forum page's language by defining the types:<ul>
* <li>{@link #PAGE_INCOMPLETE}</li>
@ -185,138 +187,138 @@ public class ParseHelpers {
* @return the base URL of the given topic
*/
public static String getBaseURL(String topicURL) {
String forumUrl = "https://www.thmmy.gr/smf/index.php?";
String indexUrl = FORUM_URL + "index.php?";
Matcher baseUrlMatcher = Pattern.compile("topic=[0-9]+").matcher(topicURL);
if (baseUrlMatcher.find())
return forumUrl + topicURL.substring(baseUrlMatcher.start(), baseUrlMatcher.end());
return indexUrl + topicURL.substring(baseUrlMatcher.start(), baseUrlMatcher.end());
else return "";
}
public static String emojiTagToHtml(String emojiTagedString) {
HashMap<Pattern, String> tagToHtmlMap = new HashMap<>();
tagToHtmlMap.put(Pattern.compile(Pattern.quote(":)"), Pattern.MULTILINE), "<img src=\"https://www.thmmy.gr/smf/Smileys/default_dither/smiley.gif\" alt=\"Smiley\" border=\"0\">");
tagToHtmlMap.put(Pattern.compile(Pattern.quote(";)"), Pattern.MULTILINE), "<img src=\"https://www.thmmy.gr/smf/Smileys/default_dither/wink.gif\" alt=\"Wink\" border=\"0\">");
tagToHtmlMap.put(Pattern.compile(Pattern.quote(":D"), Pattern.MULTILINE), "<img src=\"https://www.thmmy.gr/smf/Smileys/default_dither/cheesy.gif\" alt=\"Cheesy\" border=\"0\">");
tagToHtmlMap.put(Pattern.compile(Pattern.quote(";D"), Pattern.MULTILINE), "<img src=\"https://www.thmmy.gr/smf/Smileys/default_dither/grin.gif\" alt=\"Grin\" border=\"0\">");
tagToHtmlMap.put(Pattern.compile(Pattern.quote("&gt;:("), Pattern.MULTILINE), "<img src=\"https://www.thmmy.gr/smf/Smileys/default_dither/angry.gif\" alt=\"Angry\" border=\"0\">");
tagToHtmlMap.put(Pattern.compile(Pattern.quote(":("), Pattern.MULTILINE), "<img src=\"https://www.thmmy.gr/smf/Smileys/default_dither/sad.gif\" alt=\"Sad\" border=\"0\">");
tagToHtmlMap.put(Pattern.compile(Pattern.quote(":o"), Pattern.MULTILINE), "<img src=\"https://www.thmmy.gr/smf/Smileys/default_dither/shocked.gif\" alt=\"Shocked\" border=\"0\">");
tagToHtmlMap.put(Pattern.compile(Pattern.quote("8))"), Pattern.MULTILINE), "<img src=\"https://www.thmmy.gr/smf/Smileys/default_dither/cool.gif\" alt=\"Cool\" border=\"0\">");
tagToHtmlMap.put(Pattern.compile(Pattern.quote(":???:"), Pattern.MULTILINE), "<img src=\"https://www.thmmy.gr/smf/Smileys/default_dither/huh.gif\" alt=\"Huh\" border=\"0\">");
tagToHtmlMap.put(Pattern.compile(Pattern.quote(":P"), Pattern.MULTILINE), "<img src=\"https://www.thmmy.gr/smf/Smileys/default_dither/tongue.gif\" alt=\"Tongue\" border=\"0\">");
tagToHtmlMap.put(Pattern.compile(Pattern.quote(":-["), Pattern.MULTILINE), "<img src=\"https://www.thmmy.gr/smf/Smileys/default_dither/embarrassed.gif\" alt=\"Embarrassed\" border=\"0\">");
tagToHtmlMap.put(Pattern.compile(Pattern.quote(":-X"), Pattern.MULTILINE), "<img src=\"https://www.thmmy.gr/smf/Smileys/default_dither/lipsrsealed.gif\" alt=\"Lips Sealed\" border=\"0\">");
tagToHtmlMap.put(Pattern.compile(Pattern.quote(":-\\"), Pattern.MULTILINE), "<img src =\"https://www.thmmy.gr/smf/Smileys/default_dither/undecided.gif\" alt=\"Undecided\" border=\"0\">");
tagToHtmlMap.put(Pattern.compile(Pattern.quote(":-*"), Pattern.MULTILINE), "<img src=\"https://www.thmmy.gr/smf/Smileys/default_dither/kiss.gif\" alt=\"Kiss\" border=\"0\">");
tagToHtmlMap.put(Pattern.compile(Pattern.quote(":'("), Pattern.MULTILINE), "<img src=\"https://www.thmmy.gr/smf/Smileys/default_dither/cry.gif\" alt=\"Cry\" border=\"0\">");
tagToHtmlMap.put(Pattern.compile(Pattern.quote("&lt;3"), Pattern.MULTILINE), "<img src=\"https://www.thmmy.gr/smf/Smileys/default_dither/heart.gif\" alt=\"heart\" border=\"0\">");
tagToHtmlMap.put(Pattern.compile(Pattern.quote("^locked^"), Pattern.MULTILINE), "<img src=\"https://www.thmmy.gr/smf/Smileys/default_dither/locked.gif\" alt=\"kleidaria\" border=\"0\">");
tagToHtmlMap.put(Pattern.compile(Pattern.quote("^rollover^"), Pattern.MULTILINE), "<img src=\"https://www.thmmy.gr/smf/Smileys/default_dither/roll_over.gif\" alt=\"roll_over\" border=\"0\">");
tagToHtmlMap.put(Pattern.compile(Pattern.quote("^redface^"), Pattern.MULTILINE), "<img src=\"https://www.thmmy.gr/smf/Smileys/default_dither/redface.gif\" alt=\"redface\" border=\"0\">");
tagToHtmlMap.put(Pattern.compile(Pattern.quote("^confused^"), Pattern.MULTILINE), "<img src=\"https://www.thmmy.gr/smf/Smileys/default_dither/confused.gif\" alt=\"confused\" border=\"0\">");
tagToHtmlMap.put(Pattern.compile(Pattern.quote("^innocent^"), Pattern.MULTILINE), "<img src=\"https://www.thmmy.gr/smf/Smileys/default_dither/innocent.gif\" alt=\"innocent\" border=\"0\">");
tagToHtmlMap.put(Pattern.compile(Pattern.quote("^sleep^"), Pattern.MULTILINE), "<img src=\"https://www.thmmy.gr/smf/Smileys/default_dither/sleep.gif\" alt=\"sleep\" border=\"0\">");
tagToHtmlMap.put(Pattern.compile(Pattern.quote("^sealed^"), Pattern.MULTILINE), "<img src=\"https://www.thmmy.gr/smf/Smileys/default_dither/lips_sealed.gif\" alt=\"lips_sealed\" border=\"0\">");
tagToHtmlMap.put(Pattern.compile(Pattern.quote("^cool^"), Pattern.MULTILINE), "<img src=\"https://www.thmmy.gr/smf/Smileys/default_dither/cool.bmp\" alt=\"cool\" border=\"0\">");
tagToHtmlMap.put(Pattern.compile(Pattern.quote("^crazy^"), Pattern.MULTILINE), "<img src=\"https://www.thmmy.gr/smf/Smileys/default_dither/crazy.jpg\" alt=\"crazy\" border=\"0\">");
tagToHtmlMap.put(Pattern.compile(Pattern.quote("^mad^"), Pattern.MULTILINE), "<img src=\"https://www.thmmy.gr/smf/Smileys/default_dither/mad.jpg\" alt=\"mad\" border=\"0\">");
tagToHtmlMap.put(Pattern.compile(Pattern.quote("^wav^"), Pattern.MULTILINE), "<img src=\"https://www.thmmy.gr/smf/Smileys/default_dither/wav.gif\" alt=\"wav\" border=\"0\">");
tagToHtmlMap.put(Pattern.compile(Pattern.quote("^binkybaby^"), Pattern.MULTILINE), "<img src=\"https://www.thmmy.gr/smf/Smileys/default_dither/binkybaby.gif\" alt=\"BinkyBaby\" border=\"0\">");
tagToHtmlMap.put(Pattern.compile(Pattern.quote("^Police^"), Pattern.MULTILINE), "<img src=\"https://www.thmmy.gr/smf/Smileys/default_dither/Police.gif\" alt=\"\" border=\"0\">");
tagToHtmlMap.put(Pattern.compile(Pattern.quote("^dontknow^"), Pattern.MULTILINE), "<img src=\"https://www.thmmy.gr/smf/Smileys/default_dither/dontknow.gif\" alt=\"DontKnow\" border=\"0\">");
tagToHtmlMap.put(Pattern.compile(Pattern.quote(":angry4:"), Pattern.MULTILINE), "<img src=\"https://www.thmmy.gr/smf/Smileys/default_dither/angry4.gif\" alt=\"angry4\" border=\"0\">");
tagToHtmlMap.put(Pattern.compile(Pattern.quote("^angryhot^"), Pattern.MULTILINE), "<img src=\"https://www.thmmy.gr/smf/Smileys/default_dither/angry_hot.gif\" alt=\"angryAndHot\" border=\"0\">");
tagToHtmlMap.put(Pattern.compile(Pattern.quote("^angry^"), Pattern.MULTILINE), "<img src=\"https://www.thmmy.gr/smf/Smileys/default_dither/angry.gif\" alt=\"angry\" border=\"0\">");
tagToHtmlMap.put(Pattern.compile(Pattern.quote("^fouska^"), Pattern.MULTILINE), "<img src=\"https://www.thmmy.gr/smf/Smileys/default_dither/foyska.gif\" alt=\"\" border=\"0\">");
tagToHtmlMap.put(Pattern.compile(Pattern.quote("^nysta^"), Pattern.MULTILINE), "<img src=\"https://www.thmmy.gr/smf/Smileys/default_dither/nista.gif\" alt=\"\" border=\"0\">");
tagToHtmlMap.put(Pattern.compile(Pattern.quote("^sfinaki^"), Pattern.MULTILINE), "<img src=\"https://www.thmmy.gr/smf/Smileys/default_dither/10_7_3.gif\" alt=\"\" border=\"0\">");
tagToHtmlMap.put(Pattern.compile(Pattern.quote("^banghead^"), Pattern.MULTILINE), "<img src=\"https://www.thmmy.gr/smf/Smileys/default_dither/BangHead.gif\" alt=\"bang_head\" border=\"0\">");
tagToHtmlMap.put(Pattern.compile(Pattern.quote("^crybaby^"), Pattern.MULTILINE), "<img src=\"https://www.thmmy.gr/smf/Smileys/default_dither/crybaby.gif\" alt=\"CryBaby\" border=\"0\">");
tagToHtmlMap.put(Pattern.compile(Pattern.quote("^hello^"), Pattern.MULTILINE), "<img src=\"https://www.thmmy.gr/smf/Smileys/default_dither/hello.gif\" alt=\"Hello\" border=\"0\">");
tagToHtmlMap.put(Pattern.compile(Pattern.quote("^jerk^"), Pattern.MULTILINE), "<img src=\"https://www.thmmy.gr/smf/Smileys/default_dither/jerk.gif\" alt=\"jerk\" border=\"0\">");
tagToHtmlMap.put(Pattern.compile(Pattern.quote("^nono^"), Pattern.MULTILINE), "<img src=\"https://www.thmmy.gr/smf/Smileys/default_dither/nono.gif\" alt=\"NoNo\" border=\"0\">");
tagToHtmlMap.put(Pattern.compile(Pattern.quote("^notworthy^"), Pattern.MULTILINE), "<img src=\"https://www.thmmy.gr/smf/Smileys/default_dither/notworthy.gif\" alt=\"NotWorthy\" border=\"0\">");
tagToHtmlMap.put(Pattern.compile(Pattern.quote("^off-topic^"), Pattern.MULTILINE), "<img src=\"https://www.thmmy.gr/smf/Smileys/default_dither/off -topic.gif\" alt=\"Off-topic\" border=\"0\">");
tagToHtmlMap.put(Pattern.compile(Pattern.quote("^puke^"), Pattern.MULTILINE), "<img src=\"https://www.thmmy.gr/smf/Smileys/default_dither/puke.gif\" alt=\"Puke\" border=\"0\">");
tagToHtmlMap.put(Pattern.compile(Pattern.quote("^shout^"), Pattern.MULTILINE), "<img src=\"https://www.thmmy.gr/smf/Smileys/default_dither/shout.gif\" alt=\"Shout\" border=\"0\">");
tagToHtmlMap.put(Pattern.compile(Pattern.quote("^slurp^"), Pattern.MULTILINE), "<img src=\"https://www.thmmy.gr/smf/Smileys/default_dither/slurp.gif\" alt=\"Slurp\" border=\"0\">");
tagToHtmlMap.put(Pattern.compile(Pattern.quote("^superconfused^"), Pattern.MULTILINE), "<img src=\"https://www.thmmy.gr/smf/Smileys/default_dither/superconfused.gif\" alt=\"SuperConfused\" border=\"0\">");
tagToHtmlMap.put(Pattern.compile(Pattern.quote("^superinnocent^"), Pattern.MULTILINE), "<img src=\"https://www.thmmy.gr/smf/Smileys/default_dither/superinnocent.gif\" alt=\"SuperInnocent\" border=\"0\">");
tagToHtmlMap.put(Pattern.compile(Pattern.quote("^cellPhone^"), Pattern.MULTILINE), "<img src=\"https://www.thmmy.gr/smf/Smileys/default_dither/cellPhone.gif\" alt=\"CellPhone\" border=\"0\">");
tagToHtmlMap.put(Pattern.compile(Pattern.quote("^idiot^"), Pattern.MULTILINE), "<img src=\"https://www.thmmy.gr/smf/Smileys/default_dither/idiot.gif\" alt=\"Idiot\" border=\"0\">");
tagToHtmlMap.put(Pattern.compile(Pattern.quote("^knuppel^"), Pattern.MULTILINE), "<img src=\"https://www.thmmy.gr/smf/Smileys/default_dither/knuppel.gif\" alt=\"Knuppel\" border=\"0\">");
tagToHtmlMap.put(Pattern.compile(Pattern.quote("^tickedOff^"), Pattern.MULTILINE), "<img src=\"https://www.thmmy.gr/smf/Smileys/default_dither/tickedoff.gif\" alt=\"TickedOff\" border=\"0\">");
tagToHtmlMap.put(Pattern.compile(Pattern.quote("^peace^"), Pattern.MULTILINE), "<img src=\"https://www.thmmy.gr/smf/Smileys/default_dither/peace.gif\" alt=\"Peace\" border=\"0\">");
tagToHtmlMap.put(Pattern.compile(Pattern.quote("^suspicious^"), Pattern.MULTILINE), "<img src=\"https://www.thmmy.gr/smf/Smileys/default_dither/suspicious.gif\" alt=\"Suspicious\" border=\"0\">");
tagToHtmlMap.put(Pattern.compile(Pattern.quote("^caffine^"), Pattern.MULTILINE), "<img src=\"https://www.thmmy.gr/smf/Smileys/default_dither/caffine.gif\" alt=\"Caffine\" border=\"0\">");
tagToHtmlMap.put(Pattern.compile(Pattern.quote("^argue^"), Pattern.MULTILINE), "<img src=\"https://www.thmmy.gr/smf/Smileys/default_dither/argue.gif\" alt=\"argue\" border=\"0\">");
tagToHtmlMap.put(Pattern.compile(Pattern.quote("^banned2^"), Pattern.MULTILINE), "<img src=\"https://www.thmmy.gr/smf/Smileys/default_dither/banned2.gif\" alt=\"banned2\" border=\"0\">");
tagToHtmlMap.put(Pattern.compile(Pattern.quote("^banned^"), Pattern.MULTILINE), "<img src=\"https://www.thmmy.gr/smf/Smileys/default_dither/banned.gif\" alt=\"banned\" border=\"0\">");
tagToHtmlMap.put(Pattern.compile(Pattern.quote("^bath^"), Pattern.MULTILINE), "<img src=\"https://www.thmmy.gr/smf/Smileys/default_dither/bath.gif\" alt=\"bath\" border=\"0\">");
tagToHtmlMap.put(Pattern.compile(Pattern.quote("^beg^"), Pattern.MULTILINE), "<img src=\"https://www.thmmy.gr/smf/Smileys/default_dither/beg.gif\" alt=\"beg\" border=\"0\">");
tagToHtmlMap.put(Pattern.compile(Pattern.quote("^bluescreen^"), Pattern.MULTILINE), "<img src=\"https://www.thmmy.gr/smf/Smileys/default_dither/bluescreen.gif\" alt=\"bluescreen\" border=\"0\">");
tagToHtmlMap.put(Pattern.compile(Pattern.quote("^boil^"), Pattern.MULTILINE), "<img src=\"https://www.thmmy.gr/smf/Smileys/default_dither/boil.gif\" alt=\"boil\" border=\"0\">");
tagToHtmlMap.put(Pattern.compile(Pattern.quote("^bye^"), Pattern.MULTILINE), "<img src=\"https://www.thmmy.gr/smf/Smileys/default_dither/bye.gif\" alt=\"bye\" border=\"0\">");
tagToHtmlMap.put(Pattern.compile(Pattern.quote("^callmerip^"), Pattern.MULTILINE), "<img src=\"https://www.thmmy.gr/smf/Smileys/default_dither/callmerip.gif\" alt=\"callmerip\" border=\"0\">");
tagToHtmlMap.put(Pattern.compile(Pattern.quote("^carnaval^"), Pattern.MULTILINE), "<img src=\"https://www.thmmy.gr/smf/Smileys/default_dither/carnaval.gif\" alt=\"carnaval\" border=\"0\">");
tagToHtmlMap.put(Pattern.compile(Pattern.quote("^clap^"), Pattern.MULTILINE), "<img src=\"https://www.thmmy.gr/smf/Smileys/default_dither/clap.gif\" alt=\"clap\" border=\"0\">");
tagToHtmlMap.put(Pattern.compile(Pattern.quote("^coffepot^"), Pattern.MULTILINE), "<img src=\"https://www.thmmy.gr/smf/Smileys/default_dither/coffeepot.gif\" alt=\"coffepot\" border=\"0\">");
tagToHtmlMap.put(Pattern.compile(Pattern.quote("^crap^"), Pattern.MULTILINE), "<img src=\"https://www.thmmy.gr/smf/Smileys/default_dither/crap.gif\" alt=\"crap\" border=\"0\">");
tagToHtmlMap.put(Pattern.compile(Pattern.quote("^curses^"), Pattern.MULTILINE), "<img src=\"https://www.thmmy.gr/smf/Smileys/default_dither/curses.gif\" alt=\"curses\" border=\"0\">");
tagToHtmlMap.put(Pattern.compile(Pattern.quote("^funny^"), Pattern.MULTILINE), "<img src=\"https://www.thmmy.gr/smf/Smileys/default_dither/funny.gif\" alt=\"funny\" border=\"0\">");
tagToHtmlMap.put(Pattern.compile(Pattern.quote("^guitar^"), Pattern.MULTILINE), "<img src=\"https://www.thmmy.gr/smf/Smileys/default_dither/guitar1.gif\" alt=\"guitar\" border=\"0\">");
tagToHtmlMap.put(Pattern.compile(Pattern.quote("^kissy^"), Pattern.MULTILINE), "<img src=\"https://www.thmmy.gr/smf/Smileys/default_dither/icon_kissy.gif\" alt=\"kissy\" border=\"0\">");
tagToHtmlMap.put(Pattern.compile(Pattern.quote("^band^"), Pattern.MULTILINE), "<img src=\"https://www.thmmy.gr/smf/Smileys/default_dither/band.gif\" alt=\"band\" border=\"0\">");
tagToHtmlMap.put(Pattern.compile(Pattern.quote("^ivres^"), Pattern.MULTILINE), "<img src=\"https://www.thmmy.gr/smf/Smileys/default_dither/ivres.gif\" alt=\"ivres\" border=\"0\">");
tagToHtmlMap.put(Pattern.compile(Pattern.quote("^kaloe^"), Pattern.MULTILINE), "<img src=\"https://www.thmmy.gr/smf/Smileys/default_dither/kaloe.gif\" alt=\"kaloe\" border=\"0\">");
tagToHtmlMap.put(Pattern.compile(Pattern.quote("^kremala^"), Pattern.MULTILINE), "<img src=\"https://www.thmmy.gr/smf/Smileys/default_dither/kremala.gif\" alt=\"kremala\" border=\"0\">");
tagToHtmlMap.put(Pattern.compile(Pattern.quote("^moon^"), Pattern.MULTILINE), "<img src=\"https://www.thmmy.gr/smf/Smileys/default_dither/moon.gif\" alt=\"moon\" border=\"0\">");
tagToHtmlMap.put(Pattern.compile(Pattern.quote("^mopping^"), Pattern.MULTILINE), "<img src=\"https://www.thmmy.gr/smf/Smileys/default_dither/mopping.gif\" alt=\"mopping\" border=\"0\">");
tagToHtmlMap.put(Pattern.compile(Pattern.quote("^mountza^"), Pattern.MULTILINE), "<img src=\"https://www.thmmy.gr/smf/Smileys/default_dither/mountza.gif\" alt=\"mountza\" border=\"0\">");
tagToHtmlMap.put(Pattern.compile(Pattern.quote("^pcsleep^"), Pattern.MULTILINE), "<img src=\"https://www.thmmy.gr/smf/Smileys/default_dither/pcsleep.gif\" alt=\"pcsleep\" border=\"0\">");
tagToHtmlMap.put(Pattern.compile(Pattern.quote("^pinokio^"), Pattern.MULTILINE), "<img src=\"https://www.thmmy.gr/smf/Smileys/default_dither/pinokio.gif\" alt=\"pinokio\" border=\"0\">");
tagToHtmlMap.put(Pattern.compile(Pattern.quote("^poke^"), Pattern.MULTILINE), "<img src=\"https://www.thmmy.gr/smf/Smileys/default_dither/poke.gif\" alt=\"poke\" border=\"0\">");
tagToHtmlMap.put(Pattern.compile(Pattern.quote("^seestars^"), Pattern.MULTILINE), "<img src=\"https://www.thmmy.gr/smf/Smileys/default_dither/seestars.gif\" alt=\"seestars\" border=\"0\">");
tagToHtmlMap.put(Pattern.compile(Pattern.quote("^sfyri^"), Pattern.MULTILINE), "<img src=\"https://www.thmmy.gr/smf/Smileys/default_dither/sfyri.gif\" alt=\"sfyri\" border=\"0\">");
tagToHtmlMap.put(Pattern.compile(Pattern.quote("^spam^"), Pattern.MULTILINE), "<img src=\"https://www.thmmy.gr/smf/Smileys/default_dither/spam2.gif\" alt=\"spam\" border=\"0\">");
tagToHtmlMap.put(Pattern.compile(Pattern.quote("^super^"), Pattern.MULTILINE), "<img src=\"https://www.thmmy.gr/smf/Smileys/default_dither/super.gif\" alt=\"super\" border=\"0\">");
tagToHtmlMap.put(Pattern.compile(Pattern.quote("^tafos^"), Pattern.MULTILINE), "<img src=\"https://www.thmmy.gr/smf/Smileys/default_dither/tafos.gif\" alt=\"tafos\" border=\"0\">");
tagToHtmlMap.put(Pattern.compile(Pattern.quote("^tomato^"), Pattern.MULTILINE), "<img src=\"https://www.thmmy.gr/smf/Smileys/default_dither/tomatomourh.gif\" alt=\"tomato\" border=\"0\">");
tagToHtmlMap.put(Pattern.compile(Pattern.quote("^ytold^"), Pattern.MULTILINE), "<img src=\"https://www.thmmy.gr/smf/Smileys/default_dither/ytold.gif\" alt=\"ytold\" border=\"0\">");
tagToHtmlMap.put(Pattern.compile(Pattern.quote("^beer^"), Pattern.MULTILINE), "<img src=\"https://www.thmmy.gr/smf/Smileys/default_dither/beer2.gif\" alt=\"beer\" border=\"0\">");
tagToHtmlMap.put(Pattern.compile(Pattern.quote("^yue^"), Pattern.MULTILINE), "<img src=\"https://www.thmmy.gr/smf/Smileys/default_dither/yu.gif\" alt=\"\" border=\"0\">");
tagToHtmlMap.put(Pattern.compile(Pattern.quote("^eatpaper^"), Pattern.MULTILINE), "<img src=\"https://www.thmmy.gr/smf/Smileys/default_dither/a-eatpaper.gif\" alt=\"\" border=\"0\">");
tagToHtmlMap.put(Pattern.compile(Pattern.quote("^fritz^"), Pattern.MULTILINE), "<img src=\"https://www.thmmy.gr/smf/Smileys/default_dither/fritz.gif\" alt=\"ο fritz!!!\" border=\"0\">");
tagToHtmlMap.put(Pattern.compile(Pattern.quote("^wade^"), Pattern.MULTILINE), "<img src=\"https://www.thmmy.gr/smf/Smileys/default_dither/wade.gif\" alt=\"o Wade!!!\" border=\"0\">");
tagToHtmlMap.put(Pattern.compile(Pattern.quote("^lypi^"), Pattern.MULTILINE), "<img src=\"https://www.thmmy.gr/smf/Smileys/default_dither/lypi.gif\" alt=\"\" border=\"0\">");
tagToHtmlMap.put(Pattern.compile(Pattern.quote("^aytoxeir^"), Pattern.MULTILINE), "<img src=\"https://www.thmmy.gr/smf/Smileys/default_dither/megashok1wq.gif\" alt=\"\" border=\"0\">");
tagToHtmlMap.put(Pattern.compile(Pattern.quote("^victory^"), Pattern.MULTILINE), "<img src=\"https://www.thmmy.gr/smf/Smileys/default_dither/victory.gif\" alt=\"\" border=\"0\">");
tagToHtmlMap.put(Pattern.compile(Pattern.quote("^filarakia^"), Pattern.MULTILINE), "<img src=\"https://www.thmmy.gr/smf/Smileys/default_dither/filarakia.gif\" alt=\"\" border=\"0\">");
tagToHtmlMap.put(Pattern.compile(Pattern.quote("^hat^"), Pattern.MULTILINE), "<img src=\"https://www.thmmy.gr/smf/Smileys/default_dither/bonjour-97213.gif\" alt=\"bonjour\" border=\"0\">");
tagToHtmlMap.put(Pattern.compile(Pattern.quote("^miss^"), Pattern.MULTILINE), "<img src=\"https://www.thmmy.gr/smf/Smileys/default_dither/curtseyqi9.gif\" alt=\"bonjour2\" border=\"0\">");
tagToHtmlMap.put(Pattern.compile(Pattern.quote("^rolfmao^"), Pattern.MULTILINE), "<img src=\"https://www.thmmy.gr/smf/Smileys/default_dither/rofl.gif\" alt=\"\" border=\"0\">");
tagToHtmlMap.put(Pattern.compile(Pattern.quote("^lock^"), Pattern.MULTILINE), "<img src=\"https://www.thmmy.gr/smf/Smileys/default_dither/locked.gif\" alt=\"\" border=\"0\">");
tagToHtmlMap.put(Pattern.compile(Pattern.quote("^que^"), Pattern.MULTILINE), "<img src=\"https://www.thmmy.gr/smf/Smileys/default_dither/question.gif\" alt=\"question\" border=\"0\">");
tagToHtmlMap.put(Pattern.compile(Pattern.quote("^shifty^"), Pattern.MULTILINE), "<img src=\"https://www.thmmy.gr/smf/Smileys/default_dither/shifty.gif\" alt=\"shifty\" border=\"0\">");
tagToHtmlMap.put(Pattern.compile(Pattern.quote("^shy^"), Pattern.MULTILINE), "<img src=\"https://www.thmmy.gr/smf/Smileys/default_dither/shy.png\" alt=\"shy\" border=\"0\">");
tagToHtmlMap.put(Pattern.compile(Pattern.quote("^music_listen^"), Pattern.MULTILINE), "<img src=\"https://www.thmmy.gr/smf/Smileys/default_dither/music.gif\" alt=\"music_listenning\" border=\"0\">");
tagToHtmlMap.put(Pattern.compile(Pattern.quote("^bagface^"), Pattern.MULTILINE), "<img src=\"https://www.thmmy.gr/smf/Smileys/default_dither/shamed_bag.jpg\" alt=\"bag_face\" border=\"0\">");
tagToHtmlMap.put(Pattern.compile(Pattern.quote("^rotate^"), Pattern.MULTILINE), "<img src=\"https://www.thmmy.gr/smf/Smileys/default_dither/rotfl.gif\" alt=\"rotation\" border=\"0\">");
tagToHtmlMap.put(Pattern.compile(Pattern.quote("^love^"), Pattern.MULTILINE), "<img src=\"https://www.thmmy.gr/smf/Smileys/default_dither/love.jpg\" alt=\"love\" border=\"0\">");
tagToHtmlMap.put(Pattern.compile(Pattern.quote("^speech^"), Pattern.MULTILINE), "<img src=\"https://www.thmmy.gr/smf/Smileys/default_dither/speech.gif\" alt=\"speech\" border=\"0\">");
tagToHtmlMap.put(Pattern.compile(Pattern.quote("^facepalm^"), Pattern.MULTILINE), "<img src=\"https://www.thmmy.gr/smf/Smileys/default_dither/facepalm.gif\" alt=\"\" border=\"0\">");
tagToHtmlMap.put(Pattern.compile(Pattern.quote("^shocked^"), Pattern.MULTILINE), "<img src=\"https://www.thmmy.gr/smf/Smileys/default_dither/shocked.png\" alt=\"shocked\" border=\"0\">");
tagToHtmlMap.put(Pattern.compile(Pattern.quote("^ex_shocked^"), Pattern.MULTILINE), "<img src=\"https://www.thmmy.gr/smf/Smileys/default_dither/extremely_shocked.png\" alt=\"extremely_shocked\" border=\"0\">");
tagToHtmlMap.put(Pattern.compile(Pattern.quote("^smurf^"), Pattern.MULTILINE), "<img src=\"https://www.thmmy.gr/smf/Smileys/default_dither/smurf.gif\" alt=\"smurf\" border=\"0\">");
tagToHtmlMap.put(Pattern.compile(Pattern.quote("^monster^"), Pattern.MULTILINE), "<img src=\"https://www.thmmy.gr/smf/Smileys/default_dither/monster.bmp\" alt=\"monster\" border=\"0\">");
tagToHtmlMap.put(Pattern.compile(Pattern.quote("^pig^"), Pattern.MULTILINE), "<img src=\"https://www.thmmy.gr/smf/Smileys/default_dither/noffe.gif\" alt=\"pig\" border=\"0\">");
tagToHtmlMap.put(Pattern.compile(Pattern.quote("^lol^"), Pattern.MULTILINE), "<img src=\"https://www.thmmy.gr/smf/Smileys/default_dither/LoL.jpg\" alt=\"lol\" border=\"0\">");
tagToHtmlMap.put(Pattern.compile(Pattern.quote(":)"), Pattern.MULTILINE), "<img src=\"" + FORUM_URL + "Smileys/default_dither/smiley.gif\" alt=\"Smiley\" border=\"0\">");
tagToHtmlMap.put(Pattern.compile(Pattern.quote(";)"), Pattern.MULTILINE), "<img src=\"" + FORUM_URL + "Smileys/default_dither/wink.gif\" alt=\"Wink\" border=\"0\">");
tagToHtmlMap.put(Pattern.compile(Pattern.quote(":D"), Pattern.MULTILINE), "<img src=\"" + FORUM_URL + "Smileys/default_dither/cheesy.gif\" alt=\"Cheesy\" border=\"0\">");
tagToHtmlMap.put(Pattern.compile(Pattern.quote(";D"), Pattern.MULTILINE), "<img src=\"" + FORUM_URL + "Smileys/default_dither/grin.gif\" alt=\"Grin\" border=\"0\">");
tagToHtmlMap.put(Pattern.compile(Pattern.quote("&gt;:("), Pattern.MULTILINE), "<img src=\"" + FORUM_URL + "Smileys/default_dither/angry.gif\" alt=\"Angry\" border=\"0\">");
tagToHtmlMap.put(Pattern.compile(Pattern.quote(":("), Pattern.MULTILINE), "<img src=\"" + FORUM_URL + "Smileys/default_dither/sad.gif\" alt=\"Sad\" border=\"0\">");
tagToHtmlMap.put(Pattern.compile(Pattern.quote(":o"), Pattern.MULTILINE), "<img src=\"" + FORUM_URL + "Smileys/default_dither/shocked.gif\" alt=\"Shocked\" border=\"0\">");
tagToHtmlMap.put(Pattern.compile(Pattern.quote("8))"), Pattern.MULTILINE), "<img src=\"" + FORUM_URL + "Smileys/default_dither/cool.gif\" alt=\"Cool\" border=\"0\">");
tagToHtmlMap.put(Pattern.compile(Pattern.quote(":???:"), Pattern.MULTILINE), "<img src=\"" + FORUM_URL + "Smileys/default_dither/huh.gif\" alt=\"Huh\" border=\"0\">");
tagToHtmlMap.put(Pattern.compile(Pattern.quote(":P"), Pattern.MULTILINE), "<img src=\"" + FORUM_URL + "Smileys/default_dither/tongue.gif\" alt=\"Tongue\" border=\"0\">");
tagToHtmlMap.put(Pattern.compile(Pattern.quote(":-["), Pattern.MULTILINE), "<img src=\"" + FORUM_URL + "Smileys/default_dither/embarrassed.gif\" alt=\"Embarrassed\" border=\"0\">");
tagToHtmlMap.put(Pattern.compile(Pattern.quote(":-X"), Pattern.MULTILINE), "<img src=\"" + FORUM_URL + "Smileys/default_dither/lipsrsealed.gif\" alt=\"Lips Sealed\" border=\"0\">");
tagToHtmlMap.put(Pattern.compile(Pattern.quote(":-\\"), Pattern.MULTILINE), "<img src =\"" + FORUM_URL + "Smileys/default_dither/undecided.gif\" alt=\"Undecided\" border=\"0\">");
tagToHtmlMap.put(Pattern.compile(Pattern.quote(":-*"), Pattern.MULTILINE), "<img src=\"" + FORUM_URL + "Smileys/default_dither/kiss.gif\" alt=\"Kiss\" border=\"0\">");
tagToHtmlMap.put(Pattern.compile(Pattern.quote(":'("), Pattern.MULTILINE), "<img src=\"" + FORUM_URL + "Smileys/default_dither/cry.gif\" alt=\"Cry\" border=\"0\">");
tagToHtmlMap.put(Pattern.compile(Pattern.quote("&lt;3"), Pattern.MULTILINE), "<img src=\"" + FORUM_URL + "Smileys/default_dither/heart.gif\" alt=\"heart\" border=\"0\">");
tagToHtmlMap.put(Pattern.compile(Pattern.quote("^locked^"), Pattern.MULTILINE), "<img src=\"" + FORUM_URL + "Smileys/default_dither/locked.gif\" alt=\"kleidaria\" border=\"0\">");
tagToHtmlMap.put(Pattern.compile(Pattern.quote("^rollover^"), Pattern.MULTILINE), "<img src=\"" + FORUM_URL + "Smileys/default_dither/roll_over.gif\" alt=\"roll_over\" border=\"0\">");
tagToHtmlMap.put(Pattern.compile(Pattern.quote("^redface^"), Pattern.MULTILINE), "<img src=\"" + FORUM_URL + "Smileys/default_dither/redface.gif\" alt=\"redface\" border=\"0\">");
tagToHtmlMap.put(Pattern.compile(Pattern.quote("^confused^"), Pattern.MULTILINE), "<img src=\"" + FORUM_URL + "Smileys/default_dither/confused.gif\" alt=\"confused\" border=\"0\">");
tagToHtmlMap.put(Pattern.compile(Pattern.quote("^innocent^"), Pattern.MULTILINE), "<img src=\"" + FORUM_URL + "Smileys/default_dither/innocent.gif\" alt=\"innocent\" border=\"0\">");
tagToHtmlMap.put(Pattern.compile(Pattern.quote("^sleep^"), Pattern.MULTILINE), "<img src=\"" + FORUM_URL + "Smileys/default_dither/sleep.gif\" alt=\"sleep\" border=\"0\">");
tagToHtmlMap.put(Pattern.compile(Pattern.quote("^sealed^"), Pattern.MULTILINE), "<img src=\"" + FORUM_URL + "Smileys/default_dither/lips_sealed.gif\" alt=\"lips_sealed\" border=\"0\">");
tagToHtmlMap.put(Pattern.compile(Pattern.quote("^cool^"), Pattern.MULTILINE), "<img src=\"" + FORUM_URL + "Smileys/default_dither/cool.bmp\" alt=\"cool\" border=\"0\">");
tagToHtmlMap.put(Pattern.compile(Pattern.quote("^crazy^"), Pattern.MULTILINE), "<img src=\"" + FORUM_URL + "Smileys/default_dither/crazy.jpg\" alt=\"crazy\" border=\"0\">");
tagToHtmlMap.put(Pattern.compile(Pattern.quote("^mad^"), Pattern.MULTILINE), "<img src=\"" + FORUM_URL + "Smileys/default_dither/mad.jpg\" alt=\"mad\" border=\"0\">");
tagToHtmlMap.put(Pattern.compile(Pattern.quote("^wav^"), Pattern.MULTILINE), "<img src=\"" + FORUM_URL + "Smileys/default_dither/wav.gif\" alt=\"wav\" border=\"0\">");
tagToHtmlMap.put(Pattern.compile(Pattern.quote("^binkybaby^"), Pattern.MULTILINE), "<img src=\"" + FORUM_URL + "Smileys/default_dither/binkybaby.gif\" alt=\"BinkyBaby\" border=\"0\">");
tagToHtmlMap.put(Pattern.compile(Pattern.quote("^Police^"), Pattern.MULTILINE), "<img src=\"" + FORUM_URL + "Smileys/default_dither/Police.gif\" alt=\"\" border=\"0\">");
tagToHtmlMap.put(Pattern.compile(Pattern.quote("^dontknow^"), Pattern.MULTILINE), "<img src=\"" + FORUM_URL + "Smileys/default_dither/dontknow.gif\" alt=\"DontKnow\" border=\"0\">");
tagToHtmlMap.put(Pattern.compile(Pattern.quote(":angry4:"), Pattern.MULTILINE), "<img src=\"" + FORUM_URL + "Smileys/default_dither/angry4.gif\" alt=\"angry4\" border=\"0\">");
tagToHtmlMap.put(Pattern.compile(Pattern.quote("^angryhot^"), Pattern.MULTILINE), "<img src=\"" + FORUM_URL + "Smileys/default_dither/angry_hot.gif\" alt=\"angryAndHot\" border=\"0\">");
tagToHtmlMap.put(Pattern.compile(Pattern.quote("^angry^"), Pattern.MULTILINE), "<img src=\"" + FORUM_URL + "Smileys/default_dither/angry.gif\" alt=\"angry\" border=\"0\">");
tagToHtmlMap.put(Pattern.compile(Pattern.quote("^fouska^"), Pattern.MULTILINE), "<img src=\"" + FORUM_URL + "Smileys/default_dither/foyska.gif\" alt=\"\" border=\"0\">");
tagToHtmlMap.put(Pattern.compile(Pattern.quote("^nysta^"), Pattern.MULTILINE), "<img src=\"" + FORUM_URL + "Smileys/default_dither/nista.gif\" alt=\"\" border=\"0\">");
tagToHtmlMap.put(Pattern.compile(Pattern.quote("^sfinaki^"), Pattern.MULTILINE), "<img src=\"" + FORUM_URL + "Smileys/default_dither/10_7_3.gif\" alt=\"\" border=\"0\">");
tagToHtmlMap.put(Pattern.compile(Pattern.quote("^banghead^"), Pattern.MULTILINE), "<img src=\"" + FORUM_URL + "Smileys/default_dither/BangHead.gif\" alt=\"bang_head\" border=\"0\">");
tagToHtmlMap.put(Pattern.compile(Pattern.quote("^crybaby^"), Pattern.MULTILINE), "<img src=\"" + FORUM_URL + "Smileys/default_dither/crybaby.gif\" alt=\"CryBaby\" border=\"0\">");
tagToHtmlMap.put(Pattern.compile(Pattern.quote("^hello^"), Pattern.MULTILINE), "<img src=\"" + FORUM_URL + "Smileys/default_dither/hello.gif\" alt=\"Hello\" border=\"0\">");
tagToHtmlMap.put(Pattern.compile(Pattern.quote("^jerk^"), Pattern.MULTILINE), "<img src=\"" + FORUM_URL + "Smileys/default_dither/jerk.gif\" alt=\"jerk\" border=\"0\">");
tagToHtmlMap.put(Pattern.compile(Pattern.quote("^nono^"), Pattern.MULTILINE), "<img src=\"" + FORUM_URL + "Smileys/default_dither/nono.gif\" alt=\"NoNo\" border=\"0\">");
tagToHtmlMap.put(Pattern.compile(Pattern.quote("^notworthy^"), Pattern.MULTILINE), "<img src=\"" + FORUM_URL + "Smileys/default_dither/notworthy.gif\" alt=\"NotWorthy\" border=\"0\">");
tagToHtmlMap.put(Pattern.compile(Pattern.quote("^off-topic^"), Pattern.MULTILINE), "<img src=\"" + FORUM_URL + "Smileys/default_dither/off -topic.gif\" alt=\"Off-topic\" border=\"0\">");
tagToHtmlMap.put(Pattern.compile(Pattern.quote("^puke^"), Pattern.MULTILINE), "<img src=\"" + FORUM_URL + "Smileys/default_dither/puke.gif\" alt=\"Puke\" border=\"0\">");
tagToHtmlMap.put(Pattern.compile(Pattern.quote("^shout^"), Pattern.MULTILINE), "<img src=\"" + FORUM_URL + "Smileys/default_dither/shout.gif\" alt=\"Shout\" border=\"0\">");
tagToHtmlMap.put(Pattern.compile(Pattern.quote("^slurp^"), Pattern.MULTILINE), "<img src=\"" + FORUM_URL + "Smileys/default_dither/slurp.gif\" alt=\"Slurp\" border=\"0\">");
tagToHtmlMap.put(Pattern.compile(Pattern.quote("^superconfused^"), Pattern.MULTILINE), "<img src=\"" + FORUM_URL + "Smileys/default_dither/superconfused.gif\" alt=\"SuperConfused\" border=\"0\">");
tagToHtmlMap.put(Pattern.compile(Pattern.quote("^superinnocent^"), Pattern.MULTILINE), "<img src=\"" + FORUM_URL + "Smileys/default_dither/superinnocent.gif\" alt=\"SuperInnocent\" border=\"0\">");
tagToHtmlMap.put(Pattern.compile(Pattern.quote("^cellPhone^"), Pattern.MULTILINE), "<img src=\"" + FORUM_URL + "Smileys/default_dither/cellPhone.gif\" alt=\"CellPhone\" border=\"0\">");
tagToHtmlMap.put(Pattern.compile(Pattern.quote("^idiot^"), Pattern.MULTILINE), "<img src=\"" + FORUM_URL + "Smileys/default_dither/idiot.gif\" alt=\"Idiot\" border=\"0\">");
tagToHtmlMap.put(Pattern.compile(Pattern.quote("^knuppel^"), Pattern.MULTILINE), "<img src=\"" + FORUM_URL + "Smileys/default_dither/knuppel.gif\" alt=\"Knuppel\" border=\"0\">");
tagToHtmlMap.put(Pattern.compile(Pattern.quote("^tickedOff^"), Pattern.MULTILINE), "<img src=\"" + FORUM_URL + "Smileys/default_dither/tickedoff.gif\" alt=\"TickedOff\" border=\"0\">");
tagToHtmlMap.put(Pattern.compile(Pattern.quote("^peace^"), Pattern.MULTILINE), "<img src=\"" + FORUM_URL + "Smileys/default_dither/peace.gif\" alt=\"Peace\" border=\"0\">");
tagToHtmlMap.put(Pattern.compile(Pattern.quote("^suspicious^"), Pattern.MULTILINE), "<img src=\"" + FORUM_URL + "Smileys/default_dither/suspicious.gif\" alt=\"Suspicious\" border=\"0\">");
tagToHtmlMap.put(Pattern.compile(Pattern.quote("^caffine^"), Pattern.MULTILINE), "<img src=\"" + FORUM_URL + "Smileys/default_dither/caffine.gif\" alt=\"Caffine\" border=\"0\">");
tagToHtmlMap.put(Pattern.compile(Pattern.quote("^argue^"), Pattern.MULTILINE), "<img src=\"" + FORUM_URL + "Smileys/default_dither/argue.gif\" alt=\"argue\" border=\"0\">");
tagToHtmlMap.put(Pattern.compile(Pattern.quote("^banned2^"), Pattern.MULTILINE), "<img src=\"" + FORUM_URL + "Smileys/default_dither/banned2.gif\" alt=\"banned2\" border=\"0\">");
tagToHtmlMap.put(Pattern.compile(Pattern.quote("^banned^"), Pattern.MULTILINE), "<img src=\"" + FORUM_URL + "Smileys/default_dither/banned.gif\" alt=\"banned\" border=\"0\">");
tagToHtmlMap.put(Pattern.compile(Pattern.quote("^bath^"), Pattern.MULTILINE), "<img src=\"" + FORUM_URL + "Smileys/default_dither/bath.gif\" alt=\"bath\" border=\"0\">");
tagToHtmlMap.put(Pattern.compile(Pattern.quote("^beg^"), Pattern.MULTILINE), "<img src=\"" + FORUM_URL + "Smileys/default_dither/beg.gif\" alt=\"beg\" border=\"0\">");
tagToHtmlMap.put(Pattern.compile(Pattern.quote("^bluescreen^"), Pattern.MULTILINE), "<img src=\"" + FORUM_URL + "Smileys/default_dither/bluescreen.gif\" alt=\"bluescreen\" border=\"0\">");
tagToHtmlMap.put(Pattern.compile(Pattern.quote("^boil^"), Pattern.MULTILINE), "<img src=\"" + FORUM_URL + "Smileys/default_dither/boil.gif\" alt=\"boil\" border=\"0\">");
tagToHtmlMap.put(Pattern.compile(Pattern.quote("^bye^"), Pattern.MULTILINE), "<img src=\"" + FORUM_URL + "Smileys/default_dither/bye.gif\" alt=\"bye\" border=\"0\">");
tagToHtmlMap.put(Pattern.compile(Pattern.quote("^callmerip^"), Pattern.MULTILINE), "<img src=\"" + FORUM_URL + "Smileys/default_dither/callmerip.gif\" alt=\"callmerip\" border=\"0\">");
tagToHtmlMap.put(Pattern.compile(Pattern.quote("^carnaval^"), Pattern.MULTILINE), "<img src=\"" + FORUM_URL + "Smileys/default_dither/carnaval.gif\" alt=\"carnaval\" border=\"0\">");
tagToHtmlMap.put(Pattern.compile(Pattern.quote("^clap^"), Pattern.MULTILINE), "<img src=\"" + FORUM_URL + "Smileys/default_dither/clap.gif\" alt=\"clap\" border=\"0\">");
tagToHtmlMap.put(Pattern.compile(Pattern.quote("^coffepot^"), Pattern.MULTILINE), "<img src=\"" + FORUM_URL + "Smileys/default_dither/coffeepot.gif\" alt=\"coffepot\" border=\"0\">");
tagToHtmlMap.put(Pattern.compile(Pattern.quote("^crap^"), Pattern.MULTILINE), "<img src=\"" + FORUM_URL + "Smileys/default_dither/crap.gif\" alt=\"crap\" border=\"0\">");
tagToHtmlMap.put(Pattern.compile(Pattern.quote("^curses^"), Pattern.MULTILINE), "<img src=\"" + FORUM_URL + "Smileys/default_dither/curses.gif\" alt=\"curses\" border=\"0\">");
tagToHtmlMap.put(Pattern.compile(Pattern.quote("^funny^"), Pattern.MULTILINE), "<img src=\"" + FORUM_URL + "Smileys/default_dither/funny.gif\" alt=\"funny\" border=\"0\">");
tagToHtmlMap.put(Pattern.compile(Pattern.quote("^guitar^"), Pattern.MULTILINE), "<img src=\"" + FORUM_URL + "Smileys/default_dither/guitar1.gif\" alt=\"guitar\" border=\"0\">");
tagToHtmlMap.put(Pattern.compile(Pattern.quote("^kissy^"), Pattern.MULTILINE), "<img src=\"" + FORUM_URL + "Smileys/default_dither/icon_kissy.gif\" alt=\"kissy\" border=\"0\">");
tagToHtmlMap.put(Pattern.compile(Pattern.quote("^band^"), Pattern.MULTILINE), "<img src=\"" + FORUM_URL + "Smileys/default_dither/band.gif\" alt=\"band\" border=\"0\">");
tagToHtmlMap.put(Pattern.compile(Pattern.quote("^ivres^"), Pattern.MULTILINE), "<img src=\"" + FORUM_URL + "Smileys/default_dither/ivres.gif\" alt=\"ivres\" border=\"0\">");
tagToHtmlMap.put(Pattern.compile(Pattern.quote("^kaloe^"), Pattern.MULTILINE), "<img src=\"" + FORUM_URL + "Smileys/default_dither/kaloe.gif\" alt=\"kaloe\" border=\"0\">");
tagToHtmlMap.put(Pattern.compile(Pattern.quote("^kremala^"), Pattern.MULTILINE), "<img src=\"" + FORUM_URL + "Smileys/default_dither/kremala.gif\" alt=\"kremala\" border=\"0\">");
tagToHtmlMap.put(Pattern.compile(Pattern.quote("^moon^"), Pattern.MULTILINE), "<img src=\"" + FORUM_URL + "Smileys/default_dither/moon.gif\" alt=\"moon\" border=\"0\">");
tagToHtmlMap.put(Pattern.compile(Pattern.quote("^mopping^"), Pattern.MULTILINE), "<img src=\"" + FORUM_URL + "Smileys/default_dither/mopping.gif\" alt=\"mopping\" border=\"0\">");
tagToHtmlMap.put(Pattern.compile(Pattern.quote("^mountza^"), Pattern.MULTILINE), "<img src=\"" + FORUM_URL + "Smileys/default_dither/mountza.gif\" alt=\"mountza\" border=\"0\">");
tagToHtmlMap.put(Pattern.compile(Pattern.quote("^pcsleep^"), Pattern.MULTILINE), "<img src=\"" + FORUM_URL + "Smileys/default_dither/pcsleep.gif\" alt=\"pcsleep\" border=\"0\">");
tagToHtmlMap.put(Pattern.compile(Pattern.quote("^pinokio^"), Pattern.MULTILINE), "<img src=\"" + FORUM_URL + "Smileys/default_dither/pinokio.gif\" alt=\"pinokio\" border=\"0\">");
tagToHtmlMap.put(Pattern.compile(Pattern.quote("^poke^"), Pattern.MULTILINE), "<img src=\"" + FORUM_URL + "Smileys/default_dither/poke.gif\" alt=\"poke\" border=\"0\">");
tagToHtmlMap.put(Pattern.compile(Pattern.quote("^seestars^"), Pattern.MULTILINE), "<img src=\"" + FORUM_URL + "Smileys/default_dither/seestars.gif\" alt=\"seestars\" border=\"0\">");
tagToHtmlMap.put(Pattern.compile(Pattern.quote("^sfyri^"), Pattern.MULTILINE), "<img src=\"" + FORUM_URL + "Smileys/default_dither/sfyri.gif\" alt=\"sfyri\" border=\"0\">");
tagToHtmlMap.put(Pattern.compile(Pattern.quote("^spam^"), Pattern.MULTILINE), "<img src=\"" + FORUM_URL + "Smileys/default_dither/spam2.gif\" alt=\"spam\" border=\"0\">");
tagToHtmlMap.put(Pattern.compile(Pattern.quote("^super^"), Pattern.MULTILINE), "<img src=\"" + FORUM_URL + "Smileys/default_dither/super.gif\" alt=\"super\" border=\"0\">");
tagToHtmlMap.put(Pattern.compile(Pattern.quote("^tafos^"), Pattern.MULTILINE), "<img src=\"" + FORUM_URL + "Smileys/default_dither/tafos.gif\" alt=\"tafos\" border=\"0\">");
tagToHtmlMap.put(Pattern.compile(Pattern.quote("^tomato^"), Pattern.MULTILINE), "<img src=\"" + FORUM_URL + "Smileys/default_dither/tomatomourh.gif\" alt=\"tomato\" border=\"0\">");
tagToHtmlMap.put(Pattern.compile(Pattern.quote("^ytold^"), Pattern.MULTILINE), "<img src=\"" + FORUM_URL + "Smileys/default_dither/ytold.gif\" alt=\"ytold\" border=\"0\">");
tagToHtmlMap.put(Pattern.compile(Pattern.quote("^beer^"), Pattern.MULTILINE), "<img src=\"" + FORUM_URL + "Smileys/default_dither/beer2.gif\" alt=\"beer\" border=\"0\">");
tagToHtmlMap.put(Pattern.compile(Pattern.quote("^yue^"), Pattern.MULTILINE), "<img src=\"" + FORUM_URL + "Smileys/default_dither/yu.gif\" alt=\"\" border=\"0\">");
tagToHtmlMap.put(Pattern.compile(Pattern.quote("^eatpaper^"), Pattern.MULTILINE), "<img src=\"" + FORUM_URL + "Smileys/default_dither/a-eatpaper.gif\" alt=\"\" border=\"0\">");
tagToHtmlMap.put(Pattern.compile(Pattern.quote("^fritz^"), Pattern.MULTILINE), "<img src=\"" + FORUM_URL + "Smileys/default_dither/fritz.gif\" alt=\"ο fritz!!!\" border=\"0\">");
tagToHtmlMap.put(Pattern.compile(Pattern.quote("^wade^"), Pattern.MULTILINE), "<img src=\"" + FORUM_URL + "Smileys/default_dither/wade.gif\" alt=\"o Wade!!!\" border=\"0\">");
tagToHtmlMap.put(Pattern.compile(Pattern.quote("^lypi^"), Pattern.MULTILINE), "<img src=\"" + FORUM_URL + "Smileys/default_dither/lypi.gif\" alt=\"\" border=\"0\">");
tagToHtmlMap.put(Pattern.compile(Pattern.quote("^aytoxeir^"), Pattern.MULTILINE), "<img src=\"" + FORUM_URL + "Smileys/default_dither/megashok1wq.gif\" alt=\"\" border=\"0\">");
tagToHtmlMap.put(Pattern.compile(Pattern.quote("^victory^"), Pattern.MULTILINE), "<img src=\"" + FORUM_URL + "Smileys/default_dither/victory.gif\" alt=\"\" border=\"0\">");
tagToHtmlMap.put(Pattern.compile(Pattern.quote("^filarakia^"), Pattern.MULTILINE), "<img src=\"" + FORUM_URL + "Smileys/default_dither/filarakia.gif\" alt=\"\" border=\"0\">");
tagToHtmlMap.put(Pattern.compile(Pattern.quote("^hat^"), Pattern.MULTILINE), "<img src=\"" + FORUM_URL + "Smileys/default_dither/bonjour-97213.gif\" alt=\"bonjour\" border=\"0\">");
tagToHtmlMap.put(Pattern.compile(Pattern.quote("^miss^"), Pattern.MULTILINE), "<img src=\"" + FORUM_URL + "Smileys/default_dither/curtseyqi9.gif\" alt=\"bonjour2\" border=\"0\">");
tagToHtmlMap.put(Pattern.compile(Pattern.quote("^rolfmao^"), Pattern.MULTILINE), "<img src=\"" + FORUM_URL + "Smileys/default_dither/rofl.gif\" alt=\"\" border=\"0\">");
tagToHtmlMap.put(Pattern.compile(Pattern.quote("^lock^"), Pattern.MULTILINE), "<img src=\"" + FORUM_URL + "Smileys/default_dither/locked.gif\" alt=\"\" border=\"0\">");
tagToHtmlMap.put(Pattern.compile(Pattern.quote("^que^"), Pattern.MULTILINE), "<img src=\"" + FORUM_URL + "Smileys/default_dither/question.gif\" alt=\"question\" border=\"0\">");
tagToHtmlMap.put(Pattern.compile(Pattern.quote("^shifty^"), Pattern.MULTILINE), "<img src=\"" + FORUM_URL + "Smileys/default_dither/shifty.gif\" alt=\"shifty\" border=\"0\">");
tagToHtmlMap.put(Pattern.compile(Pattern.quote("^shy^"), Pattern.MULTILINE), "<img src=\"" + FORUM_URL + "Smileys/default_dither/shy.png\" alt=\"shy\" border=\"0\">");
tagToHtmlMap.put(Pattern.compile(Pattern.quote("^music_listen^"), Pattern.MULTILINE), "<img src=\"" + FORUM_URL + "Smileys/default_dither/music.gif\" alt=\"music_listenning\" border=\"0\">");
tagToHtmlMap.put(Pattern.compile(Pattern.quote("^bagface^"), Pattern.MULTILINE), "<img src=\"" + FORUM_URL + "Smileys/default_dither/shamed_bag.jpg\" alt=\"bag_face\" border=\"0\">");
tagToHtmlMap.put(Pattern.compile(Pattern.quote("^rotate^"), Pattern.MULTILINE), "<img src=\"" + FORUM_URL + "Smileys/default_dither/rotfl.gif\" alt=\"rotation\" border=\"0\">");
tagToHtmlMap.put(Pattern.compile(Pattern.quote("^love^"), Pattern.MULTILINE), "<img src=\"" + FORUM_URL + "Smileys/default_dither/love.jpg\" alt=\"love\" border=\"0\">");
tagToHtmlMap.put(Pattern.compile(Pattern.quote("^speech^"), Pattern.MULTILINE), "<img src=\"" + FORUM_URL + "Smileys/default_dither/speech.gif\" alt=\"speech\" border=\"0\">");
tagToHtmlMap.put(Pattern.compile(Pattern.quote("^facepalm^"), Pattern.MULTILINE), "<img src=\"" + FORUM_URL + "Smileys/default_dither/facepalm.gif\" alt=\"\" border=\"0\">");
tagToHtmlMap.put(Pattern.compile(Pattern.quote("^shocked^"), Pattern.MULTILINE), "<img src=\"" + FORUM_URL + "Smileys/default_dither/shocked.png\" alt=\"shocked\" border=\"0\">");
tagToHtmlMap.put(Pattern.compile(Pattern.quote("^ex_shocked^"), Pattern.MULTILINE), "<img src=\"" + FORUM_URL + "Smileys/default_dither/extremely_shocked.png\" alt=\"extremely_shocked\" border=\"0\">");
tagToHtmlMap.put(Pattern.compile(Pattern.quote("^smurf^"), Pattern.MULTILINE), "<img src=\"" + FORUM_URL + "Smileys/default_dither/smurf.gif\" alt=\"smurf\" border=\"0\">");
tagToHtmlMap.put(Pattern.compile(Pattern.quote("^monster^"), Pattern.MULTILINE), "<img src=\"" + FORUM_URL + "Smileys/default_dither/monster.bmp\" alt=\"monster\" border=\"0\">");
tagToHtmlMap.put(Pattern.compile(Pattern.quote("^pig^"), Pattern.MULTILINE), "<img src=\"" + FORUM_URL + "Smileys/default_dither/noffe.gif\" alt=\"pig\" border=\"0\">");
tagToHtmlMap.put(Pattern.compile(Pattern.quote("^lol^"), Pattern.MULTILINE), "<img src=\"" + FORUM_URL + "Smileys/default_dither/LoL.jpg\" alt=\"lol\" border=\"0\">");
//Needs priority over the rest tags
final Pattern pattern = Pattern.compile(Pattern.quote("::)"), Pattern.MULTILINE);
Matcher matcher = pattern.matcher(emojiTagedString);
emojiTagedString = matcher.replaceAll("<img src=\"https://www.thmmy.gr/smf/Smileys/default_dither/rolleyes.gif\" alt=\"Roll Eyes\" border=\"0\">");
emojiTagedString = matcher.replaceAll("<img src=\"" + FORUM_URL + "Smileys/default_dither/rolleyes.gif\" alt=\"Roll Eyes\" border=\"0\">");
for (Pattern patternKey : tagToHtmlMap.keySet()) {
matcher = patternKey.matcher(emojiTagedString);

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

@ -40,8 +40,7 @@ public class ThmmyDateTimeParser {
private static final Pattern pattern = Pattern.compile("\\s((1[3-9]|2[0-3]):)");
private ThmmyDateTimeParser() {
}
private ThmmyDateTimeParser() {}
public static String convertToTimestamp(String thmmyDateTime) {
Timber.v("Will attempt to convert %s to timestamp.", thmmyDateTime);
@ -78,7 +77,8 @@ public class ThmmyDateTimeParser {
localDateTime = formatter.withLocale(greekLocale).parseLocalDateTime(thmmyDateTime);
} catch (IllegalArgumentException e2) {
Timber.v("Parsing DateTime %s using Greek Locale failed too.", thmmyDateTime);
Timber.e("Couldn't convert DateTime %s to timestamp!", originalDateTime);
Timber.e("Couldn't convert DateTime to timestamp (original: \"%s\", modified: \"%s\")!",
originalDateTime, thmmyDateTime);
return null;
}
}

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

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

4
app/src/main/java/gr/thmmy/mthmmy/viewmodel/TopicViewModel.java

@ -484,10 +484,10 @@ public class TopicViewModel extends BaseViewModel implements TopicTask.OnTopicTa
return prepareForEditResult.getValue().getPostText();
}
public String getBuildedQuotes() {
public String getBuiltQuotes() {
if (prepareForReplyResult.getValue() == null)
throw new NullPointerException("Reply preparation was not found");
return prepareForReplyResult.getValue().getBuildedQuotes();
return prepareForReplyResult.getValue().getBuiltQuotes();
}
public int postCount() {

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

@ -1,5 +1,9 @@
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.ClipboardManager;
import android.content.Context;
@ -13,10 +17,6 @@ import gr.thmmy.mthmmy.R;
import gr.thmmy.mthmmy.base.BaseApplication;
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 {
private final static long MAX_TOUCH_DURATION = 100;
private final Context context;

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

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

5
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.graphics.drawable.Drawable;
import android.os.AsyncTask;
import android.os.Build;
import android.text.Editable;
import android.text.TextUtils;
import android.util.AttributeSet;
@ -201,7 +200,7 @@ public class EditorView extends LinearLayout implements EmojiInputField {
});
}
popupWindow.showAsDropDown(view);
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.M) {
new AsyncTask<Void, Void, Void>() {
@Override
protected Void doInBackground(Void... voids) {
@ -218,7 +217,7 @@ public class EditorView extends LinearLayout implements EmojiInputField {
editText.setSelection(selectionStart, selectionEnd);
}
}.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
}
break;
case R.drawable.ic_format_size:
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>

2
app/src/main/res/layout/activity_bookmarks.xml

@ -21,7 +21,7 @@
android:layout_height="?attr/actionBarSize"
android:background="?attr/colorPrimary"
android:gravity="center"
app:popupTheme="@style/ToolbarTheme"></androidx.appcompat.widget.Toolbar>
app:popupTheme="@style/ToolbarTheme" />
<com.google.android.material.tabs.TabLayout
android:id="@+id/bookmark_tabs"

22
app/src/main/res/layout/activity_downloads.xml

@ -20,7 +20,7 @@
android:layout_width="match_parent"
android:layout_height="?attr/actionBarSize"
android:background="?attr/colorPrimary"
app:popupTheme="@style/ToolbarTheme"></androidx.appcompat.widget.Toolbar>
app:popupTheme="@style/ToolbarTheme" />
</com.google.android.material.appbar.AppBarLayout>
<androidx.recyclerview.widget.RecyclerView
@ -31,7 +31,7 @@
android:background="@color/background"
android:scrollbars="none"
app:layout_behavior="@string/appbar_scrolling_view_behavior"
tools:context="gr.thmmy.mthmmy.activities.downloads.DownloadsActivity"></androidx.recyclerview.widget.RecyclerView>
tools:context="gr.thmmy.mthmmy.activities.downloads.DownloadsActivity" />
<me.zhanghai.android.materialprogressbar.MaterialProgressBar
android:id="@+id/progressBar"
@ -45,13 +45,13 @@
app:mpb_indeterminateTint="@color/accent"
app:mpb_progressStyle="horizontal" />
<com.google.android.material.floatingactionbutton.FloatingActionButton
android:id="@+id/upload_fab"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="bottom|end"
android:layout_marginBottom="@dimen/fab_margins"
android:layout_marginEnd="@dimen/fab_margins"
app:layout_behavior="gr.thmmy.mthmmy.utils.ui.ScrollAwareFABBehavior"
app:srcCompat="@drawable/ic_file_upload_white_24dp" />
<!-- <com.google.android.material.floatingactionbutton.FloatingActionButton-->
<!-- android:id="@+id/upload_fab"-->
<!-- android:layout_width="wrap_content"-->
<!-- android:layout_height="wrap_content"-->
<!-- android:layout_gravity="bottom|end"-->
<!-- android:layout_marginBottom="@dimen/fab_margins"-->
<!-- android:layout_marginEnd="@dimen/fab_margins"-->
<!-- app:layout_behavior="gr.thmmy.mthmmy.utils.ui.ScrollAwareFABBehavior"-->
<!-- app:srcCompat="@drawable/ic_file_upload_white_24dp" />-->
</androidx.coordinatorlayout.widget.CoordinatorLayout>

2
app/src/main/res/layout/activity_login.xml

@ -31,7 +31,7 @@
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal"
android:contentDescription="@string/thmmy_img_description" />
android:contentDescription="@string/mthmmy_logo" />
<Space
android:layout_width="match_parent"

1
app/src/main/res/layout/activity_topic.xml

@ -148,6 +148,7 @@
android:layout_gravity="bottom|end"
android:layout_marginEnd="@dimen/fab_margins"
android:layout_marginBottom="50dp"
android:contentDescription="@string/reply_button"
app:layout_behavior="gr.thmmy.mthmmy.utils.ui.ScrollAwareFABBehavior"
app:srcCompat="@drawable/ic_reply" />
</androidx.coordinatorlayout.widget.CoordinatorLayout>

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"
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="?android:attr/selectableItemBackground"
android:background="@color/background_light"
android:foreground="?android:attr/selectableItemBackground"
android:drawablePadding="5dp"
android:gravity="center_vertical"
android:paddingBottom="6dp"
@ -22,7 +24,8 @@
android:id="@+id/edit_post"
android:layout_width="wrap_content"
android:layout_height="35dp"
android:background="?android:attr/selectableItemBackground"
android:background="@color/background_light"
android:foreground="?android:attr/selectableItemBackground"
android:drawablePadding="5dp"
android:gravity="center_vertical"
android:paddingBottom="6dp"
@ -36,7 +39,8 @@
android:id="@+id/delete_post"
android:layout_width="wrap_content"
android:layout_height="35dp"
android:background="?android:attr/selectableItemBackground"
android:background="@color/background_light"
android:foreground="?android:attr/selectableItemBackground"
android:drawablePadding="5dp"
android:gravity="center_vertical"
android:paddingBottom="6dp"

2
app/src/main/res/menu/downloads_menu.xml

@ -5,5 +5,5 @@
android:id="@+id/menu_upload"
android:icon="@drawable/ic_file_upload_white_24dp"
app:showAsAction="ifRoom"
android:title="@string/upload_button"></item>
android:title="@string/upload_button" />
</menu>

2
app/src/main/res/menu/shoutbox_menu.xml

@ -5,5 +5,5 @@
android:id="@+id/menu_refresh"
android:icon="@drawable/ic_refresh_white_24dp"
app:showAsAction="ifRoom"
android:title="@string/refresh"></item>
android:title="@string/refresh" />
</menu>

6
app/src/main/res/menu/topic_menu.xml

@ -5,15 +5,15 @@
android:id="@+id/menu_bookmark"
android:icon="@drawable/ic_bookmark_false_accent_24dp"
app:showAsAction="ifRoom"
android:title="@string/bookmark"></item>
android:title="@string/bookmark" />
<item
android:id="@+id/menu_share"
android:icon="@drawable/ic_share_white_24dp"
app:showAsAction="ifRoom"
android:title="@string/share"></item>
android:title="@string/share" />
<item
android:id="@+id/menu_info"
android:icon="@drawable/ic_info_outline_white_24dp"
app:showAsAction="ifRoom"
android:title="@string/info"></item>
android:title="@string/info" />
</menu>

2
app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml

@ -1,5 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
<adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android">
<background android:drawable="@color/ic_launcher_background" />
<background android:drawable="@color/primary_light" />
<foreground android:drawable="@drawable/ic_launcher_foreground" />
</adaptive-icon>

2
app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml

@ -1,5 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
<adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android">
<background android:drawable="@color/ic_launcher_background" />
<background android:drawable="@color/primary_light" />
<foreground android:drawable="@drawable/ic_launcher_foreground" />
</adaptive-icon>

4
app/src/main/res/values/ic_launcher_background.xml

@ -1,4 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<color name="ic_launcher_background">#333333</color>
</resources>

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

@ -1,5 +1,8 @@
<resources>
<string name="app_name">mTHMMY</string>
<string name="forum_url">https://www.thmmy.gr/smf/</string>
<string name="forum_host">www.thmmy.gr</string>
<string name="forum_host_simple">thmmy.gr</string>
<!--Base Activity-->
<string name="login">Login</string>
@ -26,7 +29,7 @@
<string name="no_unread_topics">No unread topics!</string>
<!--Login Activity-->
<string name="thmmy_img_description">thmmy.gr</string>
<string name="mthmmy_logo">mTHMMY</string>
<string name="hint_username">Username</string>
<string name="hint_password">Password</string>
<string name="btn_login">LOGIN</string>
@ -76,6 +79,7 @@
</plurals>
<string name="show_vote_options_button">hide results</string>
<string name="pref_topic_drafts_key">preference-topic-drafts-key</string>
<string name="reply_button">Reply</string>
<!--Profile Activity-->
<string name="username">Username</string>
@ -95,10 +99,9 @@
<string name="epl_libraries"><u>Eclipse Public License v1.0 libraries</u></string>
<string name="other_libraries"><u>Other libraries</u></string>
<string name="contact">Contact</string>
<string name="contact_text">Do not hesitate to contact us for any technical matter, either by email at thmmynolife@gmail.com, or by joining our Discord server using https://discord.gg/CVt3yrn&#8203;.
For account-related issues, please contact the administration team of thmmy.gr by email at contact@thmmy.gr.</string>
<string name="contact_text">Do not hesitate to contact us for any matter, either by email at contact@thmmy.gr, or by joining our Discord server using https://discord.gg/CVt3yrn .</string>
<string name="open_source">Open Source</string>
<string name="open_source_text">The source code of mTHMMY can be found on Github at https://github.com/ThmmyNoLife/mTHMMY, along with further details of how one can contribute.</string>
<string name="open_source_text">The source code of mTHMMY can be found on Github at https://github.com/THMMYgr/mTHMMY, along with further details of how one can contribute.</string>
<string name="trollPic">You should see a funny pic!</string>
<string name="privacy_policy">Privacy policy</string>

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

@ -40,18 +40,6 @@
app:iconSpaceReserved="false" />
</androidx.preference.PreferenceCategory>
<androidx.preference.PreferenceCategory
android:key="@string/pref_category_uploading_key"
android:title="@string/pref_category_uploading"
app:iconSpaceReserved="false">
<androidx.preference.SwitchPreferenceCompat
android:defaultValue="true"
android:key="@string/pref_uploading_app_signature_enable_key"
android:title="@string/pref_title_uploading_app_signature_enable"
android:summary="@string/pref_summary_uploading_app_signature_enable"
app:iconSpaceReserved="false" />
</androidx.preference.PreferenceCategory>
<androidx.preference.PreferenceCategory
android:key="@string/pref_category_privacy_key"
android:title="@string/pref_category_privacy"

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

@ -61,18 +61,6 @@
app:iconSpaceReserved="false" />
</androidx.preference.PreferenceCategory>
<androidx.preference.PreferenceCategory
android:key="@string/pref_category_uploading_key"
android:title="@string/pref_category_uploading"
app:iconSpaceReserved="false">
<androidx.preference.SwitchPreferenceCompat
android:defaultValue="true"
android:key="@string/pref_uploading_app_signature_enable_key"
android:title="@string/pref_title_uploading_app_signature_enable"
android:summary="@string/pref_summary_uploading_app_signature_enable"
app:iconSpaceReserved="false" />
</androidx.preference.PreferenceCategory>
<androidx.preference.PreferenceCategory
android:key="@string/pref_category_privacy_key"
android:title="@string/pref_category_privacy"

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

@ -1,5 +1,9 @@
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 org.joda.time.DateTime;
@ -10,10 +14,6 @@ import org.powermock.api.mockito.PowerMockito;
import org.powermock.core.classloader.annotations.PrepareForTest;
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)
@PrepareForTest(DateTimeUtils.class)
public class DateTimeUtilsTest {

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

@ -1,5 +1,10 @@
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 org.json.JSONObject;
@ -15,11 +20,6 @@ import java.util.HashMap;
import gr.thmmy.mthmmy.activities.upload.UploadsCourse;
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)
@PrepareForTest(JSONObject.class)
public class UploadsCoursesJSONReadingTest {
@ -33,7 +33,7 @@ public class UploadsCoursesJSONReadingTest {
InputStream is = this.getClass().getClassLoader().getResourceAsStream(filePath);
assertNotNull(is);
String uploadsCoursesJSON = ResourceUtils.readJSONResourceToString(is);
assertNotNull(uploadsCoursesJSON);;
assertNotNull(uploadsCoursesJSON);
JSONObject jsonObject = new JSONObject(uploadsCoursesJSON);
assertTrue(jsonObject.has("categories"));
HashMap<Integer, UploadsCourse> coursesHashMap = generateCoursesFromJSON(jsonObject);

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

@ -1,5 +1,12 @@
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 org.joda.time.DateTimeZone;
@ -9,13 +16,6 @@ import org.junit.runner.RunWith;
import org.powermock.core.classloader.annotations.PrepareForTest;
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)
@PrepareForTest(ThmmyDateTimeParser.class)
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.
apply plugin: "com.github.ben-manes.versions"
buildscript {
repositories {
google()
jcenter()
mavenCentral()
maven { url "https://jitpack.io" }
jcenter() // Just for snatik and uploadservice
}
dependencies {
classpath 'com.android.tools.build:gradle:4.1.3'
classpath 'com.google.gms:google-services:4.3.10'
classpath 'com.google.firebase:firebase-crashlytics-gradle:2.7.1'
classpath 'org.ajoberstar.grgit:grgit-core:3.1.1' // Also change in app/gradle/grgit.gradle
classpath "com.github.ben-manes:gradle-versions-plugin:0.21.0"
classpath 'com.android.tools.build:gradle:7.4.2'
classpath 'com.google.gms:google-services:4.3.15'
classpath 'com.google.firebase:firebase-crashlytics-gradle:2.9.4'
classpath 'org.ajoberstar.grgit:grgit-core:5.0.0' // Also change in app/gradle/grgit.gradle
}
}
plugins {
id("com.github.ben-manes.versions") version "0.46.0"
}
allprojects {
repositories {
maven { url "https://maven.google.com" }
google()
jcenter()
mavenCentral()
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'
android {
compileSdkVersion 29
buildToolsVersion "29.0.3"
compileSdkVersion 33
defaultConfig {
minSdkVersion 19
targetSdkVersion 29
versionCode 1
versionName "1.0"
minSdkVersion 21
targetSdkVersion 33
consumerProguardFiles 'consumer-rules.pro'
}
@ -19,4 +16,6 @@ android {
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"
package="gr.thmmy.emojis" />
<manifest xmlns:android="http://schemas.android.com/apk/res/android" />

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
distributionPath=wrapper/dists
zipStoreBase=GRADLE_USER_HOME
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