Browse Source

Merge branch 'develop' into bookdrag

pull/71/head
Nikolaos Bampaliaris 4 years ago
committed by GitHub
parent
commit
8fe7cfdb29
No known key found for this signature in database GPG Key ID: 4AEE18F83AFDEB23
  1. 31
      app/build.gradle
  2. 124
      app/src/main/assets/apache_libraries.html
  3. 7
      app/src/main/assets/epl_libraries.html
  4. 13
      app/src/main/assets/mit_libraries.html
  5. 4
      app/src/main/assets/other_libraries.html
  6. 39
      app/src/main/java/gr/thmmy/mthmmy/activities/AboutActivity.java
  7. 13
      app/src/main/java/gr/thmmy/mthmmy/activities/LoginActivity.java
  8. 27
      app/src/main/java/gr/thmmy/mthmmy/activities/board/BoardActivity.java
  9. 45
      app/src/main/java/gr/thmmy/mthmmy/activities/board/BoardAdapter.java
  10. 4
      app/src/main/java/gr/thmmy/mthmmy/activities/bookmarks/BookmarksActivity.java
  11. 26
      app/src/main/java/gr/thmmy/mthmmy/activities/bookmarks/BookmarksFragment.java
  12. 7
      app/src/main/java/gr/thmmy/mthmmy/activities/create_content/CreateContentActivity.java
  13. 3
      app/src/main/java/gr/thmmy/mthmmy/activities/create_content/NewTopicTask.java
  14. 18
      app/src/main/java/gr/thmmy/mthmmy/activities/downloads/DownloadsActivity.java
  15. 21
      app/src/main/java/gr/thmmy/mthmmy/activities/downloads/DownloadsAdapter.java
  16. 48
      app/src/main/java/gr/thmmy/mthmmy/activities/main/MainActivity.java
  17. 21
      app/src/main/java/gr/thmmy/mthmmy/activities/main/forum/ForumFragment.java
  18. 7
      app/src/main/java/gr/thmmy/mthmmy/activities/main/recent/RecentAdapter.java
  19. 18
      app/src/main/java/gr/thmmy/mthmmy/activities/main/recent/RecentFragment.java
  20. 7
      app/src/main/java/gr/thmmy/mthmmy/activities/main/unread/UnreadAdapter.java
  21. 64
      app/src/main/java/gr/thmmy/mthmmy/activities/main/unread/UnreadFragment.java
  22. 32
      app/src/main/java/gr/thmmy/mthmmy/activities/profile/ProfileActivity.java
  23. 8
      app/src/main/java/gr/thmmy/mthmmy/activities/profile/latestPosts/LatestPostsAdapter.java
  24. 11
      app/src/main/java/gr/thmmy/mthmmy/activities/profile/latestPosts/LatestPostsFragment.java
  25. 18
      app/src/main/java/gr/thmmy/mthmmy/activities/profile/stats/StatsFragment.java
  26. 14
      app/src/main/java/gr/thmmy/mthmmy/activities/profile/summary/SummaryFragment.java
  27. 3
      app/src/main/java/gr/thmmy/mthmmy/activities/settings/SettingsActivity.java
  28. 53
      app/src/main/java/gr/thmmy/mthmmy/activities/settings/SettingsFragment.java
  29. 1
      app/src/main/java/gr/thmmy/mthmmy/activities/shoutbox/SendShoutTask.java
  30. 9
      app/src/main/java/gr/thmmy/mthmmy/activities/shoutbox/ShoutAdapter.java
  31. 3
      app/src/main/java/gr/thmmy/mthmmy/activities/shoutbox/ShoutboxActivity.java
  32. 12
      app/src/main/java/gr/thmmy/mthmmy/activities/shoutbox/ShoutboxFragment.java
  33. 2
      app/src/main/java/gr/thmmy/mthmmy/activities/topic/Posting.java
  34. 76
      app/src/main/java/gr/thmmy/mthmmy/activities/topic/TopicActivity.java
  35. 126
      app/src/main/java/gr/thmmy/mthmmy/activities/topic/TopicAdapter.java
  36. 41
      app/src/main/java/gr/thmmy/mthmmy/activities/topic/TopicParser.java
  37. 1
      app/src/main/java/gr/thmmy/mthmmy/activities/topic/tasks/EditTask.java
  38. 1
      app/src/main/java/gr/thmmy/mthmmy/activities/topic/tasks/PrepareForEditTask.java
  39. 5
      app/src/main/java/gr/thmmy/mthmmy/activities/topic/tasks/PrepareForReplyTask.java
  40. 1
      app/src/main/java/gr/thmmy/mthmmy/activities/topic/tasks/ReplyTask.java
  41. 4
      app/src/main/java/gr/thmmy/mthmmy/activities/topic/tasks/TopicTask.java
  42. 111
      app/src/main/java/gr/thmmy/mthmmy/activities/upload/UploadActivity.java
  43. 18
      app/src/main/java/gr/thmmy/mthmmy/activities/upload/UploadFieldsBuilderActivity.java
  44. 14
      app/src/main/java/gr/thmmy/mthmmy/activities/upload/UploadsCourse.java
  45. 4
      app/src/main/java/gr/thmmy/mthmmy/activities/upload/UploadsHelper.java
  46. 10
      app/src/main/java/gr/thmmy/mthmmy/activities/upload/multipart/MultipartUploadRequest.java
  47. 8
      app/src/main/java/gr/thmmy/mthmmy/activities/upload/multipart/MultipartUploadTask.java
  48. 74
      app/src/main/java/gr/thmmy/mthmmy/base/BaseActivity.java
  49. 29
      app/src/main/java/gr/thmmy/mthmmy/base/BaseApplication.java
  50. 3
      app/src/main/java/gr/thmmy/mthmmy/base/BaseFragment.java
  51. 2
      app/src/main/java/gr/thmmy/mthmmy/model/Bookmark.java
  52. 4
      app/src/main/java/gr/thmmy/mthmmy/model/Download.java
  53. 3
      app/src/main/java/gr/thmmy/mthmmy/model/Poll.java
  54. 6
      app/src/main/java/gr/thmmy/mthmmy/model/Post.java
  55. 12
      app/src/main/java/gr/thmmy/mthmmy/model/PostNotification.java
  56. 2
      app/src/main/java/gr/thmmy/mthmmy/model/ThmmyFile.java
  57. 11
      app/src/main/java/gr/thmmy/mthmmy/model/ThmmyPage.java
  58. 9
      app/src/main/java/gr/thmmy/mthmmy/services/DownloadHelper.java
  59. 43
      app/src/main/java/gr/thmmy/mthmmy/services/NotificationService.java
  60. 17
      app/src/main/java/gr/thmmy/mthmmy/services/UploadsReceiver.java
  61. 3
      app/src/main/java/gr/thmmy/mthmmy/session/InvalidSessionException.java
  62. 8
      app/src/main/java/gr/thmmy/mthmmy/session/LogoutTask.java
  63. 8
      app/src/main/java/gr/thmmy/mthmmy/session/MarkAsReadTask.java
  64. 26
      app/src/main/java/gr/thmmy/mthmmy/session/SessionManager.java
  65. 56
      app/src/main/java/gr/thmmy/mthmmy/utils/DateTimeUtils.java
  66. 5
      app/src/main/java/gr/thmmy/mthmmy/utils/ExternalAsyncTask.java
  67. 3
      app/src/main/java/gr/thmmy/mthmmy/utils/FileUtils.java
  68. 12
      app/src/main/java/gr/thmmy/mthmmy/utils/HTMLUtils.java
  69. 6
      app/src/main/java/gr/thmmy/mthmmy/utils/LaunchType.java
  70. 2
      app/src/main/java/gr/thmmy/mthmmy/utils/TakePhoto.java
  71. 3
      app/src/main/java/gr/thmmy/mthmmy/utils/crashreporting/CrashReporter.java
  72. 9
      app/src/main/java/gr/thmmy/mthmmy/utils/crashreporting/CrashReportingTree.java
  73. 5
      app/src/main/java/gr/thmmy/mthmmy/utils/networking/NetworkTask.java
  74. 5
      app/src/main/java/gr/thmmy/mthmmy/utils/parsing/NewParseTask.java
  75. 3
      app/src/main/java/gr/thmmy/mthmmy/utils/parsing/ParseException.java
  76. 7
      app/src/main/java/gr/thmmy/mthmmy/utils/parsing/ParseHelpers.java
  77. 7
      app/src/main/java/gr/thmmy/mthmmy/utils/parsing/ParseTask.java
  78. 56
      app/src/main/java/gr/thmmy/mthmmy/utils/parsing/ThmmyDateTimeParser.java
  79. 6
      app/src/main/java/gr/thmmy/mthmmy/utils/parsing/ThmmyParser.java
  80. 2
      app/src/main/java/gr/thmmy/mthmmy/utils/ui/CenterVerticalSpan.java
  81. 10
      app/src/main/java/gr/thmmy/mthmmy/utils/ui/ImageDownloadDialogBuilder.java
  82. 3
      app/src/main/java/gr/thmmy/mthmmy/utils/ui/ScrollAwareFABBehavior.java
  83. 3
      app/src/main/java/gr/thmmy/mthmmy/utils/ui/ScrollAwareLinearBehavior.java
  84. 3
      app/src/main/java/gr/thmmy/mthmmy/viewmodel/ShoutboxViewModel.java
  85. 32
      app/src/main/java/gr/thmmy/mthmmy/viewmodel/TopicViewModel.java
  86. 22
      app/src/main/java/gr/thmmy/mthmmy/views/ReactiveWebView.java
  87. 16
      app/src/main/java/gr/thmmy/mthmmy/views/RelativeTimeTextView.java
  88. 1
      app/src/main/java/gr/thmmy/mthmmy/views/ToggledBackgroundButton.java
  89. 495
      app/src/main/java/gr/thmmy/mthmmy/views/editorview/EditorView.java
  90. 1
      app/src/main/java/gr/thmmy/mthmmy/views/editorview/EmojiInputField.java
  91. 9
      app/src/main/java/gr/thmmy/mthmmy/views/editorview/FormatButtonsAdapter.java
  92. 4
      app/src/main/java/gr/thmmy/mthmmy/views/editorview/IEmojiKeyboard.java
  93. 2
      app/src/main/res/anim/push_left_in.xml
  94. 2
      app/src/main/res/anim/push_left_out.xml
  95. 2
      app/src/main/res/anim/push_right_in.xml
  96. 2
      app/src/main/res/anim/push_right_out.xml
  97. 8
      app/src/main/res/drawable/guest_button_border_bg.xml
  98. 13
      app/src/main/res/drawable/ic_access_time_white_24dp.xml
  99. 10
      app/src/main/res/drawable/ic_add_fab.xml
  100. 13
      app/src/main/res/drawable/ic_announcement.xml

31
app/build.gradle

@ -15,8 +15,8 @@ android {
applicationId "gr.thmmy.mthmmy"
minSdkVersion 19
targetSdkVersion 29
versionCode 28
versionName "1.8.5"
versionCode 29
versionName "1.9.0"
archivesBaseName = "mTHMMY-v$versionName"
buildConfigField "String", "CURRENT_BRANCH", "\"" + getCurrentBranch() + "\""
buildConfigField "String", "COMMIT_HASH", "\"" + getCommitHash() + "\""
@ -53,23 +53,21 @@ tasks.whenTaskAdded { task ->
if (task.name.contains("assembleRelease")) {
task.getDependsOn().add({
def googleServicesFile = new File("app/src/release/google-services.json")
if(googleServicesFile.exists()){
if (googleServicesFile.exists()) {
def json = new JsonSlurper().parseText(googleServicesFile.text)
if (json.project_info.project_id != firebaseReleaseProjectId)
throw new GradleException('Please supply the correct google-services.json for release in app/src/release/ directory!')
}
else
} else
throw new GradleException('Please add the release google-services.json in app/src/release/ directory!')
})
} else if (task.name.contains("assembleDebug")) {
task.getDependsOn().add({
def googleServicesFile = new File("app/src/debug/google-services.json")
if(googleServicesFile.exists()){
if (googleServicesFile.exists()) {
def json = new JsonSlurper().parseText(googleServicesFile.text)
if (json.project_info.project_id == firebaseReleaseProjectId)
throw new GradleException('Please replace google-services.json in app/src/debug/ with a debug one!')
}
else
} else
throw new GradleException('Please add a debug google-services.json in app/src/debug/ directory!')
})
}
@ -85,19 +83,20 @@ dependencies {
implementation 'androidx.cardview:cardview:1.0.0'
implementation 'androidx.recyclerview:recyclerview:1.1.0'
implementation 'androidx.lifecycle:lifecycle-extensions:2.2.0'
implementation 'androidx.constraintlayout:constraintlayout:1.1.3'
implementation 'androidx.constraintlayout:constraintlayout:2.0.4'
implementation 'androidx.exifinterface:exifinterface:1.2.0'
implementation 'androidx.multidex:multidex:2.0.1' //TODO: Remove when minSdkVersion >= 21
implementation 'com.google.android.material:material:1.1.0'
implementation 'com.google.firebase:firebase-analytics:17.4.4'
implementation 'com.google.firebase:firebase-crashlytics:17.1.1'
implementation 'com.google.firebase:firebase-messaging:20.2.4'
implementation 'com.google.firebase:firebase-crashlytics:17.3.0'
implementation 'com.google.firebase:firebase-messaging:21.0.0'
implementation 'com.snatik:storage:2.1.0'
implementation ('com.squareup.okhttp3:okhttp:3.12.12') { //TODO: Warning: OkHttp has dropped support for Android 19 since OkHttp 3.13!
implementation('com.squareup.okhttp3:okhttp:3.12.12') {
//TODO: Warning: OkHttp has dropped support for Android 19 since OkHttp 3.13!
force = true //TODO: Remove when minSdkVersion >= 21
}
implementation 'org.jsoup:jsoup:1.13.1'
implementation 'joda-time:joda-time:2.10.4'
implementation 'joda-time:joda-time:2.10.8'
implementation 'com.github.franmontiel:PersistentCookieJar:1.0.1'
implementation 'com.github.PhilJay:MPAndroidChart:3.0.3'
implementation 'com.mikepenz:materialdrawer:6.1.1'
@ -109,8 +108,10 @@ dependencies {
implementation 'com.jakewharton.timber:timber:4.7.1'
implementation 'ru.noties:markwon:2.0.2'
implementation 'net.gotev:uploadservice:3.5.2'
implementation 'net.gotev:uploadservice-okhttp:3.4.2' //TODO: Warning: v.3.5 depends on okhttp 3.13!
implementation 'com.itkacher.okhttpprofiler:okhttpprofiler:1.0.7' //Plugin: https://plugins.jetbrains.com/plugin/11249-okhttp-profiler
implementation 'net.gotev:uploadservice-okhttp:3.4.2'
//TODO: Warning: v.3.5 depends on okhttp 3.13!
implementation 'com.itkacher.okhttpprofiler:okhttpprofiler:1.0.7'
//Plugin: https://plugins.jetbrains.com/plugin/11249-okhttp-profiler
implementation 'com.github.bumptech.glide:glide:4.11.0'
annotationProcessor 'com.github.bumptech.glide:compiler:4.11.0'
testImplementation 'junit:junit:4.12'

124
app/src/main/assets/apache_libraries.html

@ -1,60 +1,72 @@
<html>
<head>
<link rel="stylesheet" type="text/css" href="libraries_style.css" />
<link rel="stylesheet" type="text/css" href="libraries_style.css"/>
</head>
<body>
<ul>
<li>
<h5><a href="https://square.github.io/okhttp/">OkHttp</a>&nbsp;v3.12.12 (Copyright ©2019 Square, Inc.)</h5>
</li>
<li>
<h5><a href="https://github.com/franmontiel/PersistentCookieJar">PersistentCookieJar</a>&nbsp;v1.0.1 (Copyright ©2016 Francisco José Montiel Navarro)</h5>
</li>
<li>
<h5><a href="https://github.com/PhilJay/MPAndroidChart">MPAndroidChart</a>&nbsp;v3.0.3 (Copyright ©2018 Philipp Jahoda)</h5>
</li>
<li>
<h5><a href="https://github.com/mikepenz/MaterialDrawer">MaterialDrawer</a>&nbsp;v6.1.1 (Copyright ©2018 Mike Penz)</h5>
</li>
<li>
<h5><a href="https://github.com/chrisbanes/PhotoView">PhotoView</a>&nbsp;v2.3.0 (Copyright ©2018 Chris Banes)</h5>
</li>
<li>
<h5><a href="https://github.com/mikepenz/Android-Iconics">Android-Iconics</a>&nbsp;v2.9.5 (Copyright ©2016 Mike Penz)</h5>
</li>
<li>
<h5><a href="https://github.com/DreaminginCodeZH/MaterialProgressBar">MaterialProgressBar</a>&nbsp;v1.4.2 (Copyright ©2015 Zhang Hai)</h5>
</li>
<li>
<h5><a href="https://github.com/JakeWharton/timber">Timber</a>&nbsp;v4.7.1 (Copyright ©2013 Jake Wharton)</h5>
</li>
<li>
<h5><a href="https://github.com/gotev/android-upload-service">Android Upload Service</a>&nbsp;v3.5.2 (Copyright ©2013-2019 Aleksandar Gotev)</h5>
</li>
<li>
<h5><a href="https://github.com/noties/Markwon">Markwon</a>&nbsp;v2.0.2 (Copyright ©2017 Dimitry Ivanov)</h5>
</li>
<li>
<h5><a href="https://github.com/ajoberstar/grgit">Grgit</a>&nbsp;v3.0.0 (Copyright ©2018 Andrew Oberstar)</h5>
</li>
<li>
<h5><a href="https://github.com/JodaOrg/joda-time">Joda-Time</a>&nbsp;v2.10.4 (Copyright ©2002-2019 Joda.org)</h5>
</li>
<li>
<h5><a href="https://github.com/powermock/powermock">PowerMock</a>&nbsp;v2.0.2</h5>
</li>
<li>
<h5><a href="https://github.com/sromku/android-storage">android-storage</a>&nbsp;v2.1.0</h5>
</li>
<li>
<h5><a href=https://github.com/itkacher/OkHttpProfiler">OkHttpProfiler</a>&nbsp;v1.0.7</h5>
</li>
</ul>
<pre>
<ul>
<li>
<h5><a href="https://square.github.io/okhttp/">OkHttp</a>&nbsp;v3.12.12 (Copyright ©2019
Square, Inc.)</h5>
</li>
<li>
<h5><a href="https://github.com/franmontiel/PersistentCookieJar">PersistentCookieJar</a>&nbsp;v1.0.1
(Copyright ©2016 Francisco José Montiel Navarro)</h5>
</li>
<li>
<h5><a href="https://github.com/PhilJay/MPAndroidChart">MPAndroidChart</a>&nbsp;v3.0.3
(Copyright ©2018 Philipp Jahoda)</h5>
</li>
<li>
<h5><a href="https://github.com/mikepenz/MaterialDrawer">MaterialDrawer</a>&nbsp;v6.1.1
(Copyright ©2018 Mike Penz)</h5>
</li>
<li>
<h5><a href="https://github.com/chrisbanes/PhotoView">PhotoView</a>&nbsp;v2.3.0 (Copyright
©2018 Chris Banes)</h5>
</li>
<li>
<h5><a href="https://github.com/mikepenz/Android-Iconics">Android-Iconics</a>&nbsp;v2.9.5
(Copyright ©2016 Mike Penz)</h5>
</li>
<li>
<h5>
<a href="https://github.com/DreaminginCodeZH/MaterialProgressBar">MaterialProgressBar</a>&nbsp;v1.4.2
(Copyright ©2015 Zhang Hai)</h5>
</li>
<li>
<h5><a href="https://github.com/JakeWharton/timber">Timber</a>&nbsp;v4.7.1 (Copyright ©2013
Jake Wharton)</h5>
</li>
<li>
<h5><a href="https://github.com/gotev/android-upload-service">Android Upload Service</a>&nbsp;v3.5.2
(Copyright ©2013-2019 Aleksandar Gotev)</h5>
</li>
<li>
<h5><a href="https://github.com/noties/Markwon">Markwon</a>&nbsp;v2.0.2 (Copyright ©2017
Dimitry Ivanov)</h5>
</li>
<li>
<h5><a href="https://github.com/ajoberstar/grgit">Grgit</a>&nbsp;v3.0.0 (Copyright ©2018
Andrew Oberstar)</h5>
</li>
<li>
<h5><a href="https://github.com/JodaOrg/joda-time">Joda-Time</a>&nbsp;v2.10.8 (Copyright
©2002-2020 Joda.org)</h5>
</li>
<li>
<h5><a href="https://github.com/powermock/powermock">PowerMock</a>&nbsp;v2.0.2</h5>
</li>
<li>
<h5><a href="https://github.com/sromku/android-storage">android-storage</a>&nbsp;v2.1.0</h5>
</li>
<li>
<h5><a href=https://github.com/itkacher/OkHttpProfiler">OkHttpProfiler</a>&nbsp;v1.0.7</h5>
</li>
</ul>
<pre>
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
@ -67,9 +79,9 @@ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
</pre>
<br/>
<h4>Apache License v2.0</h4>
<pre>
<br/>
<h4>Apache License v2.0</h4>
<pre>
Apache License
Version 2.0, January 2004
@ -125,6 +137,6 @@ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
END OF TERMS AND CONDITIONS
</pre>
</body>
</body>
</html>

7
app/src/main/assets/epl_libraries.html

@ -1,19 +1,20 @@
<html>
<head>
<link rel="stylesheet" type="text/css" href="libraries_style.css" />
<link rel="stylesheet" type="text/css" href="libraries_style.css"/>
</head>
<body>
<ul>
<li>
<h5><a href="https://github.com/junit-team/junit4">JUnit</a>&nbsp;v4.12 (Copyright © 2002-2019, JUnit)</h5>
<h5><a href="https://github.com/junit-team/junit4">JUnit</a>&nbsp;v4.12 (Copyright ©
2002-2019, JUnit)</h5>
</li>
</ul>
<br/>
<h4>Eclipse Public License v1.0</h4>
<pre>
<pre>
THE ACCOMPANYING PROGRAM IS PROVIDED UNDER THE TERMS OF THIS ECLIPSE PUBLIC
LICENSE ("AGREEMENT"). ANY USE, REPRODUCTION OR DISTRIBUTION OF THE PROGRAM
CONSTITUTES RECIPIENT'S ACCEPTANCE OF THIS AGREEMENT.

13
app/src/main/assets/mit_libraries.html

@ -1,25 +1,28 @@
<html>
<head>
<link rel="stylesheet" type="text/css" href="libraries_style.css" />
<link rel="stylesheet" type="text/css" href="libraries_style.css"/>
</head>
<body>
<ul>
<li>
<h5><a href="https://jsoup.org">jsoup</a>&nbsp;v1.13.1 (Copyright ©2009-2020, Jonathan Hedley &lt;jonathan@hedley.net&gt;)</h5>
<h5><a href="https://jsoup.org">jsoup</a>&nbsp;v1.13.1 (Copyright ©2009-2020, Jonathan
Hedley &lt;jonathan@hedley.net&gt;)</h5>
</li>
<li>
<h5><a href="https://github.com/bignerdranch/expandable-recycler-view">Expandable RecyclerView</a>&nbsp;v3.0.0-RC1 (Copyright ©2015, Big Nerd Ranch)</h5>
<h5><a href="https://github.com/bignerdranch/expandable-recycler-view">Expandable
RecyclerView</a>&nbsp;v3.0.0-RC1 (Copyright ©2015, Big Nerd Ranch)</h5>
</li>
<li>
<h5><a href="https://github.com/LachlanMcKee/timber-junit-rule">Timber JUnit-Rule</a>&nbsp;v1.0.1 (Copyright ©2017, Lachlan McKee)</h5>
<h5><a href="https://github.com/LachlanMcKee/timber-junit-rule">Timber JUnit-Rule</a>&nbsp;v1.0.1
(Copyright ©2017, Lachlan McKee)</h5>
</li>
</ul>
<br/>
<h4>The MIT License</h4>
<pre>
<pre>
Copyright &lt;YEAR&gt; &lt;COPYRIGHT HOLDER&gt;
Permission is hereby granted, free of charge, to any person obtaining a copy

4
app/src/main/assets/other_libraries.html

@ -1,6 +1,6 @@
<html>
<head>
<link rel="stylesheet" type="text/css" href="libraries_style.css" />
<link rel="stylesheet" type="text/css" href="libraries_style.css"/>
</head>
<body>
@ -13,7 +13,7 @@
<br/>
<h4>Glide License</h4>
<pre>
<pre>
License for everything not in third_party and not otherwise marked:
Copyright 2014 Google, Inc. All rights reserved.

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

@ -58,7 +58,7 @@ public class AboutActivity extends BaseActivity {
gitExists = false;
String versionInfo = "";
if(gitExists)
if (gitExists)
versionInfo = "-" + BuildConfig.CURRENT_BRANCH + "-" + commitHash
+ (BuildConfig.IS_CLEAN ? "" : "-dirty")
+ " "; // Avoid last letter being cut in italics styled TextView
@ -89,7 +89,8 @@ public class AboutActivity extends BaseActivity {
showEasterEgg();
mVersionLastPressedTime = System.currentTimeMillis();
++mVersionPressedCounter;
} else {
}
else {
mVersionLastPressedTime = System.currentTimeMillis();
mVersionPressedCounter = 0;
}
@ -102,7 +103,7 @@ public class AboutActivity extends BaseActivity {
else
versionTextView.setText(getString(R.string.version, versionName));
if(gitExists){
if (gitExists) {
versionTextView.setOnClickListener(view -> {
Intent intent = new Intent(Intent.ACTION_VIEW, Uri.parse("https://github.com/ThmmyNoLife/mTHMMY/commit/" + BuildConfig.COMMIT_HASH));
startActivity(intent);
@ -132,7 +133,7 @@ public class AboutActivity extends BaseActivity {
@Override
public void onBackPressed() {
if(easterEggImage.getVisibility()==View.INVISIBLE)
if (easterEggImage.getVisibility() == View.INVISIBLE)
super.onBackPressed();
else
hideEasterEgg();
@ -140,29 +141,29 @@ public class AboutActivity extends BaseActivity {
public void displayLibraries(View v) {
String libraryType = v.getTag().toString();
String title="", fileName="";
switch(libraryType) {
String title = "", fileName = "";
switch (libraryType) {
case "APACHE":
title=getString(R.string.apache_v2_0_libraries);
fileName="apache_libraries.html";
title = getString(R.string.apache_v2_0_libraries);
fileName = "apache_libraries.html";
break;
case "MIT":
title=getString(R.string.the_mit_libraries);
fileName="mit_libraries.html";
title = getString(R.string.the_mit_libraries);
fileName = "mit_libraries.html";
break;
case "EPL":
title=getString(R.string.epl_libraries);
fileName="epl_libraries.html";
title = getString(R.string.epl_libraries);
fileName = "epl_libraries.html";
break;
case "OTHER":
title=getString(R.string.other_libraries);
fileName="other_libraries.html";
title = getString(R.string.other_libraries);
fileName = "other_libraries.html";
break;
default:
break;
}
String htmlContent = AssetUtils.readFileToText(this,fileName);
String htmlContent = AssetUtils.readFileToText(this, fileName);
LayoutInflater inflater = LayoutInflater.from(this);
WebView webView = (WebView) inflater.inflate(R.layout.dialog_licenses, coordinatorLayout, false);
@ -176,13 +177,13 @@ public class AboutActivity extends BaseActivity {
.setView(webView)
.setPositiveButton(android.R.string.ok, null)
.show();
if(alertDialog.getWindow()!=null)
if (alertDialog.getWindow() != null)
alertDialog.getWindow().setLayout(width, height);
}
@SuppressLint("SourceLockedOrientationActivity")
private void showEasterEgg(){
if(getResources().getConfiguration().orientation==ActivityInfo.SCREEN_ORIENTATION_PORTRAIT){
private void showEasterEgg() {
if (getResources().getConfiguration().orientation == ActivityInfo.SCREEN_ORIENTATION_PORTRAIT) {
setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT); //TODO: why?
appBar.setVisibility(View.INVISIBLE);
mainContent.setVisibility(View.INVISIBLE);
@ -191,7 +192,7 @@ public class AboutActivity extends BaseActivity {
}
}
private void hideEasterEgg(){
private void hideEasterEgg() {
appBar.setVisibility(View.VISIBLE);
mainContent.setVisibility(View.VISIBLE);
easterEggImage.setVisibility(View.INVISIBLE);

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

@ -100,7 +100,7 @@ public class LoginActivity extends BaseActivity {
if (loginTask != null && loginTask.getStatus() == AsyncTask.Status.RUNNING) {
loginTask.cancel(true);
}
if(!isTaskRoot())
if (!isTaskRoot())
overridePendingTransition(R.anim.push_left_in, R.anim.push_left_out);
}
@ -117,7 +117,8 @@ public class LoginActivity extends BaseActivity {
inputUsername.setError("Enter a valid username");
inputUsername.requestFocus();
valid = false;
} else {
}
else {
inputUsername.setError(null);
}
@ -126,7 +127,8 @@ public class LoginActivity extends BaseActivity {
if (valid)
inputPassword.requestFocus();
valid = false;
} else {
}
else {
inputPassword.setError(null);
}
@ -170,10 +172,11 @@ public class LoginActivity extends BaseActivity {
"Welcome, " + sessionManager.getUsername() + "!", Toast.LENGTH_LONG)
.show();
BaseApplication.getInstance().logFirebaseAnalyticsEvent(FirebaseAnalytics.Event.LOGIN, null);
if(initialRedirect){
if (initialRedirect) {
Intent intent = new Intent(LoginActivity.this, MainActivity.class);
startActivity(intent);
} else
}
else
onBackPressed();
finish();

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

@ -116,7 +116,8 @@ public class BoardActivity extends BaseActivity implements BoardAdapter.OnLoadMo
intent.putExtra(CreateContentActivity.EXTRA_NEW_TOPIC_URL, newTopicUrl);
startActivity(intent);
}
} else {
}
else {
new AlertDialog.Builder(BoardActivity.this)
.setMessage("You need to be logged in to create a new topic!")
.setPositiveButton("Login", (dialogInterface, i) -> {
@ -234,7 +235,7 @@ public class BoardActivity extends BaseActivity implements BoardAdapter.OnLoadMo
final Pattern pLastPostPattern = Pattern.compile("((?:(?!(?:by|από)).)*)\\s(?:by|από)\\s(.*)");
if(pagesLoaded == 0) { //Finds sub boards
if (pagesLoaded == 0) { //Finds sub boards
Elements subBoardRows = boardPage.select("div.tborder>table>tbody>tr");
if (subBoardRows != null && !subBoardRows.isEmpty()) {
for (Element subBoardRow : subBoardRows) {
@ -244,9 +245,9 @@ public class BoardActivity extends BaseActivity implements BoardAdapter.OnLoadMo
boolean parsingFailed = false;
Elements subBoardColumns = subBoardRow.select(">td");
for (Element subBoardCol : subBoardColumns) {
if (Objects.equals(subBoardCol.className(), "windowbg")){
if (Objects.equals(subBoardCol.className(), "windowbg")) {
pStats = subBoardCol.text();
if(pStats.equals("--"))
if (pStats.equals("--"))
pStats = "";
}
@ -255,7 +256,7 @@ public class BoardActivity extends BaseActivity implements BoardAdapter.OnLoadMo
if (pLastPost.contains(" in ") || pLastPost.contains(" σε ")) {
Pattern pattern = Pattern.compile("(?:Last post on |Τελευταίο μήνυμα στις )((?:(?!(?:in|σε)).)*)\\s(?:in|σε)\\s.*");
Matcher matcher = pattern.matcher(pLastPost);
if (matcher.find()){
if (matcher.find()) {
String pLastPostDateTime = matcher.group(1);
String pSubject = subBoardCol.select("a").first().attr("title");
@ -272,7 +273,7 @@ public class BoardActivity extends BaseActivity implements BoardAdapter.OnLoadMo
break;
}
pLastPost = "Last post on: " + pLastPostDateTime + "\nin: " + pSubject + "\nby " +pLastUser;
pLastPost = "Last post on: " + pLastPostDateTime + "\nin: " + pSubject + "\nby " + pLastUser;
pLastPostUrl = subBoardCol.select("a").first().attr("href");
}
@ -281,18 +282,20 @@ public class BoardActivity extends BaseActivity implements BoardAdapter.OnLoadMo
break;
}
} else if (pLastPost.contains("redirected clicks")||pLastPost.contains("N/A"))
}
else if (pLastPost.contains("redirected clicks") || pLastPost.contains("N/A"))
pLastPost = "";
else
pLastPost = "No posts yet";
} else {
}
else {
pUrl = subBoardCol.select("a").first().attr("href");
pTitle = subBoardCol.select("a").first().text();
if (subBoardCol.select("div.smalltext").first() != null)
pMods = subBoardCol.select("div.smalltext").first().text();
}
}
if(!parsingFailed)
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);
@ -305,7 +308,7 @@ public class BoardActivity extends BaseActivity implements BoardAdapter.OnLoadMo
if (topicRows != null && !topicRows.isEmpty()) {
for (Element topicRow : topicRows) {
if (!Objects.equals(topicRow.className(), "titlebg")) {
String pTopicUrl, pSubject, pStarter, pLastUser="", pLastPostDateTime="00:00:00", pLastPost, pLastPostUrl, pStats;
String pTopicUrl, pSubject, pStarter, pLastUser = "", pLastPostDateTime = "00:00:00", pLastPost, pLastPostUrl, pStats;
boolean pLocked = false, pSticky = false, pUnread = false;
Elements topicColumns = topicRow.select(">td");
@ -325,11 +328,11 @@ public class BoardActivity extends BaseActivity implements BoardAdapter.OnLoadMo
pLastPost = topicColumns.get(6).text();
Matcher matcher = pLastPostPattern.matcher(pLastPost);
if (matcher.find()){
if (matcher.find()) {
pLastPostDateTime = matcher.group(1);
pLastUser = matcher.group(2);
}
else{
else {
Timber.e("Parsing failed (pLastPost came with: \"%s\", topicColumns html was \"%s\")", pLastPost, topicColumns);
continue;
}

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

@ -59,7 +59,8 @@ class BoardAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> {
if (position <= parsedSubBoards.size()) {
if (position == 0) return VIEW_TYPE_SUB_BOARD_TITLE;
return VIEW_TYPE_SUB_BOARD;
} else if (position <= parsedSubBoards.size() + parsedTopics.size() + 1) {
}
else if (position <= parsedSubBoards.size() + parsedTopics.size() + 1) {
if (position == parsedSubBoards.size() + 1) return VIEW_TYPE_TOPIC_TITLE;
if (parsedTopics.get(position - parsedSubBoards.size() - 1 - 1) != null)
return VIEW_TYPE_TOPIC;
@ -79,7 +80,8 @@ class BoardAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
subBoardTitle.setBackgroundColor(context.getColor(R.color.background_light));
subBoardTitle.setTextColor(context.getColor(R.color.accent));
} else {
}
else {
//noinspection deprecation
subBoardTitle.setBackgroundColor(context.getResources().getColor(R.color.background_light));
//noinspection deprecation
@ -89,11 +91,13 @@ class BoardAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> {
subBoardTitle.setTextSize(20f);
return new TitlesViewHolder(subBoardTitle);
} else if (viewType == VIEW_TYPE_SUB_BOARD) {
}
else if (viewType == VIEW_TYPE_SUB_BOARD) {
View subBoard = LayoutInflater.from(parent.getContext()).
inflate(R.layout.activity_board_sub_board_row, parent, false);
return new SubBoardViewHolder(subBoard);
} else if (viewType == VIEW_TYPE_TOPIC_TITLE) {
}
else if (viewType == VIEW_TYPE_TOPIC_TITLE) {
TextView topicTitle = new TextView(context);
topicTitle.setLayoutParams(new LinearLayout.LayoutParams(
LinearLayout.LayoutParams.MATCH_PARENT
@ -102,7 +106,8 @@ class BoardAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> {
topicTitle.setTypeface(topicTitle.getTypeface(), Typeface.BOLD);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
topicTitle.setTextColor(context.getColor(R.color.primary_text));
} else {
}
else {
//noinspection deprecation
topicTitle.setTextColor(context.getResources().getColor(R.color.primary_text));
}
@ -110,11 +115,13 @@ class BoardAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> {
topicTitle.setTextSize(20f);
return new TitlesViewHolder(topicTitle);
} else if (viewType == VIEW_TYPE_TOPIC) {
}
else if (viewType == VIEW_TYPE_TOPIC) {
View topic = LayoutInflater.from(parent.getContext()).
inflate(R.layout.activity_board_topic_row, parent, false);
return new TopicViewHolder(topic);
} else if (viewType == VIEW_TYPE_LOADING) {
}
else if (viewType == VIEW_TYPE_LOADING) {
View loading = LayoutInflater.from(parent.getContext()).
inflate(R.layout.recycler_loading_item, parent, false);
return new LoadingViewHolder(loading);
@ -145,7 +152,8 @@ class BoardAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> {
if (boardExpandableVisibility.get(subBoardViewHolder.getAdapterPosition() - 1)) {
subBoardViewHolder.boardExpandable.setVisibility(View.VISIBLE);
subBoardViewHolder.showHideExpandable.setImageResource(R.drawable.ic_arrow_drop_up_accent_24dp);
} else {
}
else {
subBoardViewHolder.boardExpandable.setVisibility(View.GONE);
subBoardViewHolder.showHideExpandable.setImageResource(R.drawable.ic_arrow_drop_down_accent_24dp);
}
@ -154,7 +162,8 @@ class BoardAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> {
if (visible) {
subBoardViewHolder.boardExpandable.setVisibility(View.GONE);
subBoardViewHolder.showHideExpandable.setImageResource(R.drawable.ic_arrow_drop_down_accent_24dp);
} else {
}
else {
subBoardViewHolder.boardExpandable.setVisibility(View.VISIBLE);
subBoardViewHolder.showHideExpandable.setImageResource(R.drawable.ic_arrow_drop_up_accent_24dp);
}
@ -165,17 +174,17 @@ class BoardAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> {
String stats = subBoard.getStats();
String lastPost = subBoard.getLastPost();
if(!mods.isEmpty()){
if (!mods.isEmpty()) {
subBoardViewHolder.boardMods.setText(mods);
subBoardViewHolder.boardMods.setVisibility(View.VISIBLE);
}
if(!stats.isEmpty()){
if (!stats.isEmpty()) {
subBoardViewHolder.boardStats.setText(stats);
subBoardViewHolder.boardStats.setVisibility(View.VISIBLE);
}
if(!lastPost.isEmpty()){
if (!lastPost.isEmpty()) {
subBoardViewHolder.boardLastPost.setText(lastPost);
subBoardViewHolder.boardLastPost.setVisibility(View.VISIBLE);
}
@ -191,7 +200,8 @@ class BoardAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> {
context.startActivity(intent);
});
}
} else if (holder instanceof TopicViewHolder) {
}
else if (holder instanceof TopicViewHolder) {
final Topic topic = parsedTopics.get(position - parsedSubBoards.size() - 1 - 1);
final TopicViewHolder topicViewHolder = (TopicViewHolder) holder;
@ -213,7 +223,8 @@ class BoardAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> {
.size() - 2)) {
topicViewHolder.topicExpandable.setVisibility(View.VISIBLE);
topicViewHolder.showHideExpandable.setImageResource(R.drawable.ic_arrow_drop_up_accent_24dp);
} else {
}
else {
topicViewHolder.topicExpandable.setVisibility(View.GONE);
topicViewHolder.showHideExpandable.setImageResource(R.drawable.ic_arrow_drop_down_accent_24dp);
}
@ -223,7 +234,8 @@ class BoardAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> {
if (visible) {
topicViewHolder.topicExpandable.setVisibility(View.GONE);
topicViewHolder.showHideExpandable.setImageResource(R.drawable.ic_arrow_drop_down_accent_24dp);
} else {
}
else {
topicViewHolder.topicExpandable.setVisibility(View.VISIBLE);
topicViewHolder.showHideExpandable.setImageResource(R.drawable.ic_arrow_drop_up_accent_24dp);
}
@ -258,7 +270,8 @@ class BoardAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> {
intent.addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP);
context.startActivity(intent);
});
} else if (holder instanceof LoadingViewHolder) {
}
else if (holder instanceof LoadingViewHolder) {
LoadingViewHolder loadingViewHolder = (LoadingViewHolder) holder;
loadingViewHolder.progressBar.setIndeterminate(true);
}

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

@ -69,9 +69,9 @@ public class BookmarksActivity extends BaseActivity {
}
public boolean onFragmentRowInteractionListener(BookmarksFragment.Type type, String interactionType, Bookmark bookmark) {
if(type== BookmarksFragment.Type.TOPIC)
if (type == BookmarksFragment.Type.TOPIC)
return onTopicInteractionListener(interactionType, bookmark);
else if (type==BookmarksFragment.Type.BOARD)
else if (type == BookmarksFragment.Type.BOARD)
return onBoardInteractionListener(interactionType, bookmark);
return false;

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

@ -26,6 +26,7 @@ import gr.thmmy.mthmmy.model.Bookmark;
//TODO refactor using RecyclerView
public class BookmarksFragment extends Fragment {
enum Type {TOPIC, BOARD}
private static final String ARG_SECTION_NUMBER = "SECTION_NUMBER";
private static final String ARG_BOOKMARKS = "BOOKMARKS";
@ -35,7 +36,7 @@ public class BookmarksFragment extends Fragment {
static final String INTERACTION_CLICK_BOARD_BOOKMARK = "CLICK_BOARD_BOOKMARK";
static final String INTERACTION_TOGGLE_BOARD_NOTIFICATION = "TOGGLE_BOARD_NOTIFICATION";
static final String INTERACTION_REMOVE_BOARD_BOOKMARK= "REMOVE_BOARD_BOOKMARK";
static final String INTERACTION_REMOVE_BOARD_BOOKMARK = "REMOVE_BOARD_BOOKMARK";
private TextView nothingBookmarkedTextView;
@ -49,16 +50,16 @@ public class BookmarksFragment extends Fragment {
public BookmarksFragment() {/* Required empty public constructor */}
private BookmarksFragment(Type type) {
this.type=type;
if(type==Type.TOPIC){
this.interactionClick=INTERACTION_CLICK_TOPIC_BOOKMARK;
this.interactionToggle=INTERACTION_TOGGLE_TOPIC_NOTIFICATION;
this.interactionRemove=INTERACTION_REMOVE_TOPIC_BOOKMARK;
this.type = type;
if (type == Type.TOPIC) {
this.interactionClick = INTERACTION_CLICK_TOPIC_BOOKMARK;
this.interactionToggle = INTERACTION_TOGGLE_TOPIC_NOTIFICATION;
this.interactionRemove = INTERACTION_REMOVE_TOPIC_BOOKMARK;
}
else if (type==Type.BOARD){
this.interactionClick=INTERACTION_CLICK_BOARD_BOOKMARK;
this.interactionToggle=INTERACTION_TOGGLE_BOARD_NOTIFICATION;
this.interactionRemove=INTERACTION_REMOVE_BOARD_BOOKMARK;
else if (type == Type.BOARD) {
this.interactionClick = INTERACTION_CLICK_BOARD_BOOKMARK;
this.interactionToggle = INTERACTION_TOGGLE_BOARD_NOTIFICATION;
this.interactionRemove = INTERACTION_REMOVE_BOARD_BOOKMARK;
}
}
@ -107,12 +108,14 @@ public class BookmarksFragment extends Fragment {
//Get the nothing bookmarked text view.
nothingBookmarkedTextView = rootView.findViewById(R.id.nothing_bookmarked);
//Create the adapter.
BookmarksAdapter adapter = new BookmarksAdapter(this, notificationsEnabledButtonImage, notificationsDisabledButtonImage);
//Get the drag list view.
DragListView mDragListView = (DragListView) rootView.findViewById(R.id.fragment_bookmarks_dragList);
//Set the Drag List Listener.
mDragListView.setDragListListener(new DragListView.DragListListener()
{
@ -217,6 +220,7 @@ public class BookmarksFragment extends Fragment {
//Notify the adapter, because I made changes to the bookmarks array.
adapter.notifyDataSetChanged();
}
});
//====================================This is the code for the Drag and Drop Functionality====================================//
@ -241,6 +245,7 @@ public class BookmarksFragment extends Fragment {
}
public void showNothingBookmarked() {
if(nothingBookmarkedTextView!=null)
nothingBookmarkedTextView.setVisibility(View.VISIBLE);
@ -248,6 +253,7 @@ public class BookmarksFragment extends Fragment {
public void hideNothingBookmarked(){
if(nothingBookmarkedTextView!=null)
nothingBookmarkedTextView.setVisibility(View.INVISIBLE);
}

7
app/src/main/java/gr/thmmy/mthmmy/activities/create_content/CreateContentActivity.java

@ -82,11 +82,13 @@ public class CreateContentActivity extends BaseActivity implements NewTopicTask.
}
});
}
@Override
public void onBackPressed() {
if (emojiKeyboard.getVisibility() == View.VISIBLE) {
emojiKeyboard.setVisibility(View.GONE);
} else {
}
else {
super.onBackPressed();
}
}
@ -103,7 +105,8 @@ public class CreateContentActivity extends BaseActivity implements NewTopicTask.
if (success) {
Timber.i("New topic created successfully");
finish();
} else {
}
else {
Timber.w("New topic creation failed");
Toast.makeText(BaseApplication.getInstance().getApplicationContext(), "Failed to create new topic!", Toast.LENGTH_LONG).show();
finish();

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

@ -22,7 +22,7 @@ public class NewTopicTask extends AsyncTask<String, Void, Boolean> {
private NewTopicTaskCallbacks listener;
private boolean includeAppSignature;
public NewTopicTask(NewTopicTaskCallbacks listener, boolean includeAppSignature){
public NewTopicTask(NewTopicTaskCallbacks listener, boolean includeAppSignature) {
this.listener = listener;
this.includeAppSignature = includeAppSignature;
}
@ -96,6 +96,7 @@ public class NewTopicTask extends AsyncTask<String, Void, Boolean> {
public interface NewTopicTaskCallbacks {
void onNewTopicTaskStarted();
void onNewTopicTaskFinished(boolean success);
}
}

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

@ -81,7 +81,8 @@ public class DownloadsActivity extends BaseActivity implements DownloadsAdapter.
Toast.makeText(BaseApplication.getInstance().getApplicationContext(), "An error has occurred\nAborting.", Toast.LENGTH_SHORT).show();
finish();
}
} else downloadsUrl = downloadsIndexUrl;
}
else downloadsUrl = downloadsIndexUrl;
//Initialize toolbar
toolbar = findViewById(R.id.toolbar);
@ -166,7 +167,8 @@ public class DownloadsActivity extends BaseActivity implements DownloadsAdapter.
if (downloadsUrl.contains("tpstart"))
parseDownloadPageTask.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR, downloadsUrl.substring(0
, downloadsUrl.lastIndexOf(";tpstart=")) + ";tpstart=" + pagesLoaded * 10);
else parseDownloadPageTask.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR, downloadsUrl + ";tpstart=" + pagesLoaded * 10);
else
parseDownloadPageTask.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR, downloadsUrl + ";tpstart=" + pagesLoaded * 10);
}
}
@ -237,7 +239,8 @@ public class DownloadsActivity extends BaseActivity implements DownloadsAdapter.
int pageNumber = Integer.parseInt(page.text());
if (pageNumber > numberOfPages) numberOfPages = pageNumber;
}
} else numberOfPages = 1;
}
else numberOfPages = 1;
Elements rows = downloadPage.select("table.tborder>tbody>tr");
if (type == Download.DownloadItemType.DOWNLOADS_CATEGORY) {
@ -253,20 +256,23 @@ public class DownloadsActivity extends BaseActivity implements DownloadsAdapter.
parsedDownloads.add(new Download(type, url, title, subtitle, null,
true, null));
} else {
}
else {
String stats = row.text();
stats = stats.replace(title, "").replace(subtitle, "").trim();
parsedDownloads.add(new Download(type, url, title, subtitle, stats,
false, null));
}
} else {
}
else {
String stats = row.text();
stats = stats.replace(title, "").replace(subtitle, "").trim();
parsedDownloads.add(new Download(type, url, title, subtitle, stats,
false, null));
}
}
} else {
}
else {
download = new Download(type,
rows.select("b>a").first().attr("href"),
rows.select("b>a").first().text(),

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

@ -57,7 +57,8 @@ class DownloadsAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> {
View download = LayoutInflater.from(parent.getContext()).
inflate(R.layout.activity_downloads_row, parent, false);
return new DownloadViewHolder(download);
} else if (viewType == VIEW_TYPE_LOADING) {
}
else if (viewType == VIEW_TYPE_LOADING) {
View loading = LayoutInflater.from(parent.getContext()).
inflate(R.layout.recycler_loading_item, parent, false);
return new LoadingViewHolder(loading);
@ -90,7 +91,8 @@ class DownloadsAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> {
if (downloadExpandableVisibility.get(downloadViewHolder.getAdapterPosition())) {
downloadViewHolder.informationExpandable.setVisibility(View.VISIBLE);
downloadViewHolder.informationExpandableBtn.setImageResource(R.drawable.ic_arrow_drop_up_accent_24dp);
} else {
}
else {
downloadViewHolder.informationExpandable.setVisibility(View.GONE);
downloadViewHolder.informationExpandableBtn.setImageResource(R.drawable.ic_arrow_drop_down_accent_24dp);
}
@ -100,7 +102,8 @@ class DownloadsAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> {
if (visible) {
downloadViewHolder.informationExpandable.setVisibility(View.GONE);
downloadViewHolder.informationExpandableBtn.setImageResource(R.drawable.ic_arrow_drop_down_accent_24dp);
} else {
}
else {
downloadViewHolder.informationExpandable.setVisibility(View.VISIBLE);
downloadViewHolder.informationExpandableBtn.setImageResource(R.drawable.ic_arrow_drop_up_accent_24dp);
}
@ -112,12 +115,14 @@ class DownloadsAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> {
String tmp = context.getResources().getString(R.string.fa_folder) + " "
+ download.getTitle();
downloadViewHolder.title.setText(tmp);
} else {
}
else {
String tmp = context.getResources().getString(R.string.fa_file) + " "
+ download.getTitle();
downloadViewHolder.title.setText(tmp);
}
} else {
}
else {
downloadViewHolder.downloadRow.setOnClickListener(view -> {
try {
((BaseActivity) context).downloadFile(new ThmmyFile(
@ -129,7 +134,8 @@ 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 {
}
else {
//noinspection deprecation
downloadViewHolder.upperLinear.setBackgroundColor(context.getResources().getColor(R.color.background));
}
@ -148,7 +154,8 @@ class DownloadsAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> {
if (tmp != null && !Objects.equals(tmp, ""))
downloadViewHolder.uploaderDate.setText(tmp);
else downloadViewHolder.uploaderDate.setVisibility(View.GONE);
} else if (holder instanceof LoadingViewHolder) {
}
else if (holder instanceof LoadingViewHolder) {
LoadingViewHolder loadingViewHolder = (LoadingViewHolder) holder;
loadingViewHolder.progressBar.setIndeterminate(true);
}

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

@ -5,6 +5,8 @@ import android.content.SharedPreferences;
import android.net.Uri;
import android.os.Build;
import android.os.Bundle;
import android.view.ViewGroup;
import android.widget.LinearLayout;
import android.widget.Toast;
import androidx.appcompat.app.AppCompatDelegate;
@ -55,6 +57,7 @@ public class MainActivity extends BaseActivity implements RecentFragment.RecentF
private SectionsPagerAdapter sectionsPagerAdapter;
private ViewPager viewPager;
private TabLayout tabLayout;
private boolean displayCompactTabs;
//Fix for vector drawables on android <21
static {
@ -82,9 +85,15 @@ public class MainActivity extends BaseActivity implements RecentFragment.RecentF
return; //Avoid executing the code below
}
toolbar = findViewById(R.id.toolbar);
toolbar.setTitle("");
setSupportActionBar(toolbar);
displayCompactTabs = BaseApplication.getInstance().isDisplayCompactTabsEnabled();
if (displayCompactTabs) {
toolbar = findViewById(R.id.toolbar);
ViewGroup.LayoutParams currentParams = toolbar.getLayoutParams();
toolbar.setLayoutParams(new LinearLayout.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT, currentParams.height));
toolbar.setTitle("");
setSupportActionBar(toolbar);
}
//Initialize drawer
createDrawer();
@ -108,8 +117,8 @@ public class MainActivity extends BaseActivity implements RecentFragment.RecentF
if ((preferredTab != 3 && preferredTab != 4) || sessionManager.isLoggedIn())
tabLayout.getTabAt(preferredTab).select();
for (int i = 0; i < tabLayout.getTabCount(); i++)
updateTabIcon(i);
if (!displayCompactTabs)
updateTabIcons();
setMainActivity(this);
}
@ -164,7 +173,8 @@ public class MainActivity extends BaseActivity implements RecentFragment.RecentF
i.putExtra(BUNDLE_TOPIC_TITLE, topicSummary.getSubject());
i.addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP);
startActivity(i);
} else
}
else
Timber.e("onUnreadFragmentInteraction TopicSummary came without a link");
}
@ -188,7 +198,8 @@ public class MainActivity extends BaseActivity implements RecentFragment.RecentF
fragmentList.add(fragment);
fragmentTitleList.add(title);
notifyDataSetChanged();
updateTabIcon(fragmentList.size() - 1);
if (!displayCompactTabs)
updateTabIcon(fragmentList.size() - 1);
}
void removeFragment(int position) {
@ -233,6 +244,10 @@ public class MainActivity extends BaseActivity implements RecentFragment.RecentF
tabLayout.getTabAt(2).setIcon(getResources().getDrawable(R.drawable.ic_fiber_new_white_24dp));
}
private void updateTabIcons() {
for (int i = 0; i < tabLayout.getTabCount(); i++)
updateTabIcon(i);
}
public void updateTabs() {
if (!sessionManager.isLoggedIn() && sectionsPagerAdapter.getCount() == 3)
@ -240,8 +255,8 @@ public class MainActivity extends BaseActivity implements RecentFragment.RecentF
else if (sessionManager.isLoggedIn() && sectionsPagerAdapter.getCount() == 2)
sectionsPagerAdapter.addFragment(UnreadFragment.newInstance(3), "UNREAD");
for (int i = 0; i < tabLayout.getTabCount(); i++)
updateTabIcon(i);
if (!displayCompactTabs)
updateTabIcons();
}
//-------------------------------FragmentPagerAdapter END-------------------------------------------
@ -256,26 +271,31 @@ public class MainActivity extends BaseActivity implements RecentFragment.RecentF
redirectIntent.putExtra(BUNDLE_BOARD_URL, uri.toString());
redirectIntent.putExtra(BUNDLE_BOARD_TITLE, "");
startActivity(redirectIntent);
} else if (page.is(ThmmyPage.PageCategory.TOPIC)) {
}
else if (page.is(ThmmyPage.PageCategory.TOPIC)) {
Intent redirectIntent = new Intent(MainActivity.this, TopicActivity.class);
redirectIntent.putExtra(BUNDLE_TOPIC_URL, uri.toString());
redirectIntent.putExtra(BUNDLE_TOPIC_TITLE, "");
startActivity(redirectIntent);
} else if (page.is(ThmmyPage.PageCategory.PROFILE)) {
}
else if (page.is(ThmmyPage.PageCategory.PROFILE)) {
Intent redirectIntent = new Intent(MainActivity.this, ProfileActivity.class);
redirectIntent.putExtra(BUNDLE_PROFILE_URL, uri.toString());
redirectIntent.putExtra(BUNDLE_PROFILE_THUMBNAIL_URL, "");
redirectIntent.putExtra(BUNDLE_PROFILE_USERNAME, "");
startActivity(redirectIntent);
} else if (page.is(ThmmyPage.PageCategory.DOWNLOADS)) {
}
else if (page.is(ThmmyPage.PageCategory.DOWNLOADS)) {
Intent redirectIntent = new Intent(MainActivity.this, DownloadsActivity.class);
redirectIntent.putExtra(BUNDLE_DOWNLOADS_URL, uri.toString());
redirectIntent.putExtra(BUNDLE_DOWNLOADS_TITLE, "");
startActivity(redirectIntent);
} else if (!page.is(ThmmyPage.PageCategory.INDEX)) {
}
else if (!page.is(ThmmyPage.PageCategory.INDEX)) {
Toast.makeText(BaseApplication.getInstance().getApplicationContext(), "This thmmy sector is not yet supported.", Toast.LENGTH_LONG).show();
}
} else {
}
else {
Toast.makeText(BaseApplication.getInstance().getApplicationContext(), "This is not thmmy.", Toast.LENGTH_LONG).show();
}
}

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

@ -158,12 +158,13 @@ public class ForumFragment extends BaseFragment {
@Override
public void onDestroy() {
super.onDestroy();
if (forumTask!=null){
try{
if(forumTask.isRunning())
if (forumTask != null) {
try {
if (forumTask.isRunning())
forumTask.cancel(true);
} // Yes, it happens even though we checked
catch (NullPointerException ignored){ }
catch (NullPointerException ignored) {
}
}
}
@ -180,9 +181,11 @@ public class ForumFragment extends BaseFragment {
categories.clear();
categories.addAll(fetchedCategories);
forumAdapter.notifyParentDataSetChanged(false);
} else if (resultCode == NetworkResultCodes.NETWORK_ERROR) {
}
else if (resultCode == NetworkResultCodes.NETWORK_ERROR) {
Toast.makeText(BaseApplication.getInstance().getApplicationContext(), "Network error", Toast.LENGTH_SHORT).show();
} else {
}
else {
Toast.makeText(BaseApplication.getInstance().getApplicationContext(), "Unexpected error," +
" please contact the developers with the details", Toast.LENGTH_LONG).show();
}
@ -218,13 +221,15 @@ public class ForumFragment extends BaseFragment {
Board board = new Board(boardElement.attr("href"), boardElement.text(), null, null, null, null);
category.getBoards().add(board);
}
} else
}
else
category.setExpanded(false);
fetchedCategories.add(category);
}
return fetchedCategories;
} else
}
else
throw new ParseException("Parsing failed");
}

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

@ -44,12 +44,11 @@ class RecentAdapter extends RecyclerView.Adapter<RecentAdapter.ViewHolder> {
public void onBindViewHolder(final ViewHolder holder, final int position) {
TopicSummary topicSummary = recentList.get(position);
holder.mTitleView.setText(topicSummary.getSubject());
if(BaseApplication.getInstance().isDisplayRelativeTimeEnabled()){
if (BaseApplication.getInstance().isDisplayRelativeTimeEnabled()) {
String timestamp = topicSummary.getLastPostTimestamp();
try{
try {
holder.mDateTimeView.setReferenceTime(Long.valueOf(timestamp));
}
catch(NumberFormatException e){
} catch (NumberFormatException e) {
Timber.e(e, "Invalid number format: %s", timestamp);
holder.mDateTimeView.setText(topicSummary.getLastPostSimplifiedDateTime());
}

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

@ -54,7 +54,8 @@ public class RecentFragment extends BaseFragment {
private RecentTask recentTask;
// Required empty public constructor
public RecentFragment() {}
public RecentFragment() {
}
/**
* Use ONLY this factory method to create a new instance of
@ -123,12 +124,13 @@ public class RecentFragment extends BaseFragment {
@Override
public void onDestroy() {
super.onDestroy();
if (recentTask!=null){
try{
if(recentTask.isRunning())
if (recentTask != null) {
try {
if (recentTask.isRunning())
recentTask.cancel(true);
} // Yes, it happens even though we checked
catch (NullPointerException ignored){ }
catch (NullPointerException ignored) {
}
}
}
@ -146,9 +148,11 @@ public class RecentFragment extends BaseFragment {
topicSummaries.clear();
topicSummaries.addAll(fetchedRecent);
recentAdapter.notifyDataSetChanged();
} else if (resultCode == NetworkResultCodes.NETWORK_ERROR) {
}
else if (resultCode == NetworkResultCodes.NETWORK_ERROR) {
Toast.makeText(BaseApplication.getInstance().getApplicationContext(), "Network error", Toast.LENGTH_SHORT).show();
} else {
}
else {
Toast.makeText(BaseApplication.getInstance().getApplicationContext(), "Unexpected error," +
" please contact the developers with the details", Toast.LENGTH_LONG).show();
}

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

@ -41,12 +41,11 @@ class UnreadAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> {
final UnreadAdapter.ViewHolder viewHolder = (UnreadAdapter.ViewHolder) holder;
viewHolder.mTitleView.setText(topicSummary.getSubject());
if(BaseApplication.getInstance().isDisplayRelativeTimeEnabled()){
if (BaseApplication.getInstance().isDisplayRelativeTimeEnabled()) {
String timestamp = topicSummary.getLastPostTimestamp();
try{
try {
viewHolder.mDateTimeView.setReferenceTime(Long.valueOf(timestamp));
}
catch(NumberFormatException e){
} catch (NumberFormatException e) {
Timber.e(e, "Invalid number format: %s", timestamp);
viewHolder.mDateTimeView.setText(topicSummary.getLastPostSimplifiedDateTime());
}

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

@ -66,7 +66,8 @@ public class UnreadFragment extends BaseFragment {
private MarkAsReadTask markAsReadTask;
// Required empty public constructor
public UnreadFragment() {}
public UnreadFragment() {
}
/**
* Use ONLY this factory method to create a new instance of
@ -92,7 +93,7 @@ public class UnreadFragment extends BaseFragment {
@Override
public void onActivityCreated(Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
if (topicSummaries.isEmpty()){
if (topicSummaries.isEmpty()) {
hideMarkAsReadFAB();
unreadTask = new UnreadTask(this::onUnreadTaskStarted, UnreadFragment.this::onUnreadTaskCancelled, this::onUnreadTaskFinished);
assert SessionManager.unreadUrl != null;
@ -115,7 +116,7 @@ public class UnreadFragment extends BaseFragment {
progressBar = rootView.findViewById(R.id.progressBar);
noUnreadTopicsTextView = rootView.findViewById(R.id.no_unread_topics);
markAsReadFAB = rootView.findViewById(R.id.unread_fab);
unreadAdapter = new UnreadAdapter(topicSummaries, fragmentInteractionListener);
CustomRecyclerView recyclerView = rootView.findViewById(R.id.list);
@ -140,39 +141,41 @@ public class UnreadFragment extends BaseFragment {
public void onDestroy() {
super.onDestroy();
cancelUnreadTaskIfRunning();
if (markAsReadTask !=null){
try{
if(markAsReadTask.isRunning())
if (markAsReadTask != null) {
try {
if (markAsReadTask.isRunning())
markAsReadTask.cancel(true);
} // Yes, it happens even though we checked
catch (NullPointerException ignored){ }
catch (NullPointerException ignored) {
}
}
if(topicSummaries!=null)
if (topicSummaries != null)
topicSummaries.clear();
}
private void startUnreadTask(){
if (unreadTask!=null) {
try{
if(!unreadTask.isRunning()){
private void startUnreadTask() {
if (unreadTask != null) {
try {
if (!unreadTask.isRunning()) {
numberOfPages = 0;
loadedPages = 0;
unreadTask = new UnreadTask(UnreadFragment.this::onUnreadTaskStarted, UnreadFragment.this::onUnreadTaskCancelled, UnreadFragment.this::onUnreadTaskFinished);
assert SessionManager.unreadUrl != null;
unreadTask.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR, SessionManager.unreadUrl.toString());
}
} catch (NullPointerException ignored) {
}
catch (NullPointerException ignored){ }
}
}
private void cancelUnreadTaskIfRunning(){
if (unreadTask!=null){
try{
if(unreadTask.isRunning())
private void cancelUnreadTaskIfRunning() {
if (unreadTask != null) {
try {
if (unreadTask.isRunning())
unreadTask.cancel(true);
} // Yes, it happens even though we checked
catch (NullPointerException ignored){ }
catch (NullPointerException ignored) {
}
}
}
@ -197,16 +200,17 @@ public class UnreadFragment extends BaseFragment {
builder.setTitle("Mark all as read");
builder.setMessage("Are you sure that you want to mark ALL topics as read?");
builder.setPositiveButton("Yep", (dialogInterface, i) -> {
if (!markAsReadTask.isRunning()){
if (!markAsReadTask.isRunning()) {
markAsReadTask = new MarkAsReadTask(this::onMarkAsReadTaskStarted, this::onMarkAsReadTaskFinished);
markAsReadTask.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
}
});
builder.setNegativeButton("Nope", (dialogInterface, i) -> {});
builder.setNegativeButton("Nope", (dialogInterface, i) -> {
});
builder.create().show();
}
private void hideProgressUI(){
private void hideProgressUI() {
progressBar.setVisibility(ProgressBar.INVISIBLE);
swipeRefreshLayout.setRefreshing(false);
}
@ -221,10 +225,10 @@ public class UnreadFragment extends BaseFragment {
swipeRefreshLayout.setRefreshing(false);
}
private void onUnreadTaskFinished(int resultCode, ArrayList<TopicSummary> fetchedUnread) {
private void onUnreadTaskFinished(int resultCode, ArrayList<TopicSummary> fetchedUnread) {
if (resultCode == NetworkResultCodes.SUCCESSFUL) {
if(!fetchedUnread.isEmpty()){
if(loadedPages==0)
if (!fetchedUnread.isEmpty()) {
if (loadedPages == 0)
topicSummaries.clear();
topicSummaries.addAll(fetchedUnread);
noUnreadTopicsTextView.setVisibility(View.INVISIBLE);
@ -245,7 +249,7 @@ public class UnreadFragment extends BaseFragment {
else
hideProgressUI();
}
else{
else {
hideProgressUI();
if (resultCode == NetworkResultCodes.NETWORK_ERROR)
Toast.makeText(BaseApplication.getInstance().getApplicationContext(), "Network error", Toast.LENGTH_SHORT).show();
@ -258,13 +262,13 @@ public class UnreadFragment extends BaseFragment {
}
private class UnreadTask extends NewParseTask<ArrayList<TopicSummary>> {
UnreadTask(OnTaskStartedListener onTaskStartedListener, OnTaskCancelledListener onTaskCancelledListener, OnNetworkTaskFinishedListener<ArrayList<TopicSummary>> onParseTaskFinishedListener) {
UnreadTask(OnTaskStartedListener onTaskStartedListener, OnTaskCancelledListener onTaskCancelledListener, OnNetworkTaskFinishedListener<ArrayList<TopicSummary>> onParseTaskFinishedListener) {
super(onTaskStartedListener, onTaskCancelledListener, onParseTaskFinishedListener);
}
@Override
protected ArrayList<TopicSummary> parse(Document document, Response response) throws ParseException, InvalidSessionException {
if(!document.select("td:containsOwn(Only registered members are allowed to access this section.)").isEmpty())
if (!document.select("td:containsOwn(Only registered members are allowed to access this section.)").isEmpty())
throw new InvalidSessionException();
Elements unread = document.select("table.bordercolor[cellspacing=1] tr:not(.titlebg)");
@ -316,11 +320,11 @@ public class UnreadFragment extends BaseFragment {
progressBar.setVisibility(ProgressBar.VISIBLE);
}
private void onMarkAsReadTaskFinished(int resultCode, Void v) {
private void onMarkAsReadTaskFinished(int resultCode, Void v) {
hideProgressUI();
if (resultCode == NetworkResultCodes.SUCCESSFUL)
startUnreadTask();
else{
startUnreadTask();
else {
hideProgressUI();
if (resultCode == NetworkResultCodes.NETWORK_ERROR)
Toast.makeText(BaseApplication.getInstance().getApplicationContext(), "Network error", Toast.LENGTH_SHORT).show();

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

@ -68,7 +68,7 @@ import static gr.thmmy.mthmmy.utils.ui.PhotoViewUtils.displayPhotoViewImage;
* this user's avatar url using the key {@link #BUNDLE_PROFILE_THUMBNAIL_URL} and a <b>String</b> containing
* the username using the key {@link #BUNDLE_PROFILE_USERNAME}.
*/
public class ProfileActivity extends BaseActivity implements LatestPostsFragment.LatestPostsFragmentInteractionListener, LatestPostsFragment.OnLoadingListener, StatsFragment.OnLoadingListener{
public class ProfileActivity extends BaseActivity implements LatestPostsFragment.LatestPostsFragmentInteractionListener, LatestPostsFragment.OnLoadingListener, StatsFragment.OnLoadingListener {
/**
* The key to use when putting profile's url String to {@link ProfileActivity}'s Bundle.
*/
@ -185,7 +185,8 @@ public class ProfileActivity extends BaseActivity implements LatestPostsFragment
if (target.is(ThmmyPage.PageCategory.PROFILE_STATS)) {
profileUrl = profileUrl.substring(0, profileUrl.indexOf(";sa=statPanel"));
tabSelect = 2;
} else if (target.is(ThmmyPage.PageCategory.PROFILE_LATEST_POSTS)) {
}
else if (target.is(ThmmyPage.PageCategory.PROFILE_LATEST_POSTS)) {
profileUrl = profileUrl.substring(0, profileUrl.indexOf(";sa=showPosts"));
tabSelect = 1;
}
@ -220,8 +221,8 @@ public class ProfileActivity extends BaseActivity implements LatestPostsFragment
setBarVisibility(loading);
}
private void setBarVisibility (boolean visible){
if(visible)
private void setBarVisibility(boolean visible) {
if (visible)
progressBar.setVisibility(ProgressBar.VISIBLE);
else
progressBar.setVisibility(ProgressBar.INVISIBLE);
@ -233,17 +234,17 @@ public class ProfileActivity extends BaseActivity implements LatestPostsFragment
if (pmFAB.getVisibility() != View.GONE) pmFAB.setEnabled(false);
}
private void loadAvatar(Boolean loadDefault){
private void loadAvatar(Boolean loadDefault) {
String avatarUri;
if(loadDefault)
if (loadDefault)
avatarUri = "R.drawable.ic_default_user_avatar";
else {
avatarUri = avatarUrl;
if(avatarUrl!=null)
if (avatarUrl != null)
avatarView.setOnClickListener(v -> displayPhotoViewImage(ProfileActivity.this, avatarUrl));
}
if(isValidContextForGlide(this)){
if (isValidContextForGlide(this)) {
Glide.with(this)
.load(avatarUri)
.circleCrop()
@ -292,7 +293,8 @@ public class ProfileActivity extends BaseActivity implements LatestPostsFragment
Element tmpEl = profilePage.select("td.windowbg:nth-child(2)").first();
if (tmpEl != null) {
personalText = emojiTagToHtml(tmpEl.text().trim());
} else {
}
else {
//Should never get here!
//Something is wrong.
Timber.e("An error occurred while trying to find profile's personal text.");
@ -328,11 +330,13 @@ public class ProfileActivity extends BaseActivity implements LatestPostsFragment
if (usernameSpan != null) {
if (isOnline) {
usernameView.setTextColor(Color.parseColor("#4CAF50"));
} else {
}
else {
usernameView.setTextColor(Color.GRAY);
}
usernameView.setText(usernameSpan);
} else if (usernameView.getText() != username) usernameView.setText(username);
}
else if (usernameView.getText() != username) usernameView.setText(username);
if (avatarUrl != null && !Objects.equals(avatarUrl, ""))
loadAvatar(false);
else
@ -349,12 +353,14 @@ public class ProfileActivity extends BaseActivity implements LatestPostsFragment
TabLayout.Tab tab = tabLayout.getTabAt(tabSelect);
if (tab != null) tab.select();
}
} else if (result == NetworkResultCodes.NETWORK_ERROR) {
}
else if (result == NetworkResultCodes.NETWORK_ERROR) {
Timber.w("Network error while excecuting profile activity");
Toast.makeText(BaseApplication.getInstance().getApplicationContext(), "Network error"
, Toast.LENGTH_LONG).show();
finish();
} else {
}
else {
Toast.makeText(BaseApplication.getInstance().getApplicationContext(), "Fatal error!\n Aborting..."
, Toast.LENGTH_LONG).show();
finish();

8
app/src/main/java/gr/thmmy/mthmmy/activities/profile/latestPosts/LatestPostsAdapter.java

@ -51,17 +51,19 @@ class LatestPostsAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> {
View view = LayoutInflater.from(parent.getContext()).
inflate(R.layout.fragment_profile_latest_posts_row, parent, false);
return new LatestPostViewHolder(view);
} else { // viewType == VIEW_TYPE_EMPTY
}
else { // viewType == VIEW_TYPE_EMPTY
View view = LayoutInflater.from(parent.getContext()).
inflate(R.layout.fragment_profile_latest_posts_empty_message, parent, false);
return new RecyclerView.ViewHolder(view){};
return new RecyclerView.ViewHolder(view) {
};
}
}
@SuppressLint("ClickableViewAccessibility")
@Override
public void onBindViewHolder(@NonNull final RecyclerView.ViewHolder holder, int position) {
if (holder instanceof LatestPostViewHolder){
if (holder instanceof LatestPostViewHolder) {
PostSummary topic = parsedTopicSummaries.get(position);
final LatestPostViewHolder latestPostViewHolder = (LatestPostViewHolder) holder;
latestPostViewHolder.postTitle.setText(topic.getSubject());

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

@ -182,7 +182,7 @@ public class LatestPostsFragment extends BaseFragment {
protected void onPostExecute(Boolean result) {
if (Boolean.FALSE.equals(result))
Timber.e(new ParseException("Parsing failed (latest posts)"),"ParseException"); //TODO: This is inaccurate (e.g. can also have an I/O cause)
Timber.e(new ParseException("Parsing failed (latest posts)"), "ParseException"); //TODO: This is inaccurate (e.g. can also have an I/O cause)
int prevSize = parsedTopicSummaries.size();
parsedTopicSummaries.addAll(fetchedParsedTopicSummaries);
latestPostsAdapter.notifyItemRangeInserted(prevSize, parsedTopicSummaries.size() - prevSize);
@ -200,7 +200,7 @@ public class LatestPostsFragment extends BaseFragment {
select("td:has(table:Contains(Εμφάνιση μηνυμάτων)):not([style]) > table");
if (!latestPostsRows.select("td:contains(Sorry, no matches were found)").isEmpty() ||
!latestPostsRows.select("td:contains(Δυστυχώς δεν βρέθηκε τίποτα)").isEmpty()){
!latestPostsRows.select("td:contains(Δυστυχώς δεν βρέθηκε τίποτα)").isEmpty()) {
userHasPosts = false;
fetchedParsedTopicSummaries.add(null);
return true;
@ -216,14 +216,15 @@ public class LatestPostsFragment extends BaseFragment {
numberOfPages = Integer.parseInt(page.text());
}
}
} else {
}
else {
Elements rowHeader = row.select("td.middletext");
if (rowHeader.size() != 2)
return false;
else {
pTopicTitle = rowHeader.first().text().replaceAll("\\u00a0","").trim();
pTopicTitle = rowHeader.first().text().replaceAll("\\u00a0", "").trim();
pTopicUrl = rowHeader.first().select("a").last().attr("href");
pDateTime = rowHeader.last().text().replaceAll("(on: )|(στις: )","");
pDateTime = rowHeader.last().text().replaceAll("(on: )|(στις: )", "");
}
pPost = ParseHelpers.youtubeEmbeddedFix(row.select("div.post").first());

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

@ -93,7 +93,7 @@ public class StatsFragment extends Fragment {
Bundle savedInstanceState) {
final View rootView = inflater.inflate(R.layout.fragment_profile_stats, container, false);
mainContent = rootView.findViewById(R.id.main_content);
if (profileStatsTask!=null && profileStatsTask.getStatus() == AsyncTask.Status.FINISHED)
if (profileStatsTask != null && profileStatsTask.getStatus() == AsyncTask.Status.FINISHED)
populateLayout();
return rootView;
}
@ -101,7 +101,7 @@ public class StatsFragment extends Fragment {
@Override
public void onActivityCreated(Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
if (profileStatsTask==null) {
if (profileStatsTask == null) {
profileStatsTask = new ProfileStatsTask();
profileStatsTask.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR, profileUrl + ";sa=statPanel");
}
@ -158,7 +158,7 @@ public class StatsFragment extends Fragment {
protected void onPostExecute(Boolean result) {
onLoadingListener.onLoadingStats(false);
if (!result)
Timber.e(new ParseException("Parsing failed (user stats)"),"ParseException"); //TODO: This is inaccurate (e.g. can also have an I/O cause)
Timber.e(new ParseException("Parsing failed (user stats)"), "ParseException"); //TODO: This is inaccurate (e.g. can also have an I/O cause)
else
populateLayout();
}
@ -227,7 +227,8 @@ public class StatsFragment extends Fragment {
}
private void populateLayout() {
onLoadingListener.onLoadingStats(true);;
onLoadingListener.onLoadingStats(true);
;
((TextView) mainContent.findViewById(R.id.general_statistics_title))
.setText(generalStatisticsTitle);
((TextView) mainContent.findViewById(R.id.general_statistics))
@ -261,7 +262,8 @@ public class StatsFragment extends Fragment {
if (isAdded()) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
postingActivityByTimeDataSet.setFillDrawable(getResources().getDrawable(R.drawable.line_chart_gradient, null));
} else
}
else
//noinspection deprecation
postingActivityByTimeDataSet.setFillDrawable(getResources().getDrawable(R.drawable.line_chart_gradient));
}
@ -300,7 +302,8 @@ public class StatsFragment extends Fragment {
if (isAdded()) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
mostPopularBoardsByPostsDataSet.setColors(getResources().getColor(R.color.accent, null));
} else
}
else
//noinspection deprecation
mostPopularBoardsByPostsDataSet.setColors(getResources().getColor(R.color.accent));
}
@ -341,7 +344,8 @@ public class StatsFragment extends Fragment {
if (isAdded()) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
mostPopularBoardsByActivityDataSet.setColors(getResources().getColor(R.color.accent, null));
} else
}
else
//noinspection deprecation
mostPopularBoardsByActivityDataSet.setColors(getResources().getColor(R.color.accent));
}

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

@ -125,7 +125,7 @@ public class SummaryFragment extends Fragment {
* @see org.jsoup.Jsoup Jsoup
*/
LinkedHashMap<String, String> parseProfileSummary(Document profile) {
LinkedHashMap<String, String> parsedInformation = new LinkedHashMap<>();
LinkedHashMap<String, String> parsedInformation = new LinkedHashMap<>();
//Contains all summary's rows
Elements summaryRows = profile.select("td.windowbg > table > tbody > tr");
@ -135,16 +135,16 @@ public class SummaryFragment extends Fragment {
int tdSize = summaryRow.select("td").size();
if (tdSize > 1){
if (tdSize > 1) {
key = summaryRow.select("td").first().text().trim();
if (key.startsWith("Name") || key.startsWith("Όνομα"))
continue;
else if (key.startsWith("Signature") || key.startsWith("Υπογραφή")){
else if (key.startsWith("Signature") || key.startsWith("Υπογραφή")) {
key = summaryRow.selectFirst("td > table > tbody > tr > td").text().trim();
summaryRow.selectFirst("td > table > tbody > tr").remove(); //key not needed, outer html needed for CSS
value = ParseHelpers.emojiTagToHtml(ParseHelpers.youtubeEmbeddedFix(summaryRow)); // Is emojiTagToHtml() really needed here?
if(summaryRow.text().trim().isEmpty())
if (summaryRow.text().trim().isEmpty())
continue;
value = ("<link rel=\"stylesheet\" type=\"text/css\" href=\"style.css\" />\n" +
"<link rel=\"stylesheet\" type=\"text/css\" href=\"style_light.css\" />\n" +
@ -176,7 +176,7 @@ public class SummaryFragment extends Fragment {
String key = entry.getKey();
String value = entry.getValue();
if (key.startsWith("Current Status") || key.startsWith("Κατάσταση")){
if (key.startsWith("Current Status") || key.startsWith("Κατάσταση")) {
addEmptyView();
continue;
}
@ -194,7 +194,7 @@ public class SummaryFragment extends Fragment {
String textViewContent = "<b>" + key + "</b> " + value;
if (key.startsWith("Signature") || key.startsWith("Υπογραφή")){
if (key.startsWith("Signature") || key.startsWith("Υπογραφή")) {
addEmptyView();
textViewContent = "<b>" + key + "</b>";
}
@ -219,7 +219,7 @@ public class SummaryFragment extends Fragment {
}
}
private void addEmptyView(){
private void addEmptyView() {
mainContent.addView(new TextView(this.getContext()));
}
}

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

@ -7,8 +7,9 @@ import androidx.fragment.app.FragmentTransaction;
import gr.thmmy.mthmmy.R;
import gr.thmmy.mthmmy.base.BaseActivity;
public class SettingsActivity extends BaseActivity {
public class SettingsActivity extends BaseActivity {
public static final String DEFAULT_HOME_TAB = "pref_app_main_default_tab_key";
public static final String DISPLAY_COMPACT_TABS = "pref_app_display_compact_tabs_key";
public static final String DISPLAY_RELATIVE_TIME = "pref_app_display_relative_time_key";
public static final String NOTIFICATION_LED_KEY = "pref_notification_led_enable_key";
public static final String NOTIFICATION_VIBRATION_KEY = "pref_notification_vibration_enable_key";

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

@ -66,7 +66,7 @@ public class SettingsFragment extends PreferenceFragmentCompat implements Shared
defaultHomeTabValues.add("0");
defaultHomeTabValues.add("1");
if(isLoggedIn = BaseApplication.getInstance().getSessionManager().isLoggedIn()){
if (isLoggedIn = BaseApplication.getInstance().getSessionManager().isLoggedIn()) {
defaultHomeTabEntries.add(UNREAD);
defaultHomeTabValues.add("2");
}
@ -97,11 +97,11 @@ public class SettingsFragment extends PreferenceFragmentCompat implements Shared
public void onCreatePreferences(Bundle bundle, String rootKey) {
isLoggedIn = BaseApplication.getInstance().getSessionManager().isLoggedIn(); //Ensures it stays updated
// Add the Preferences from the XML file if needed
if(isLoggedIn&&(prefs_type==PREFS_TYPE.GUEST||prefs_type==PREFS_TYPE.NOT_SET)){
if (isLoggedIn && (prefs_type == PREFS_TYPE.GUEST || prefs_type == PREFS_TYPE.NOT_SET)) {
prefs_type = PREFS_TYPE.USER;
addPreferencesFromResource(R.xml.app_preferences_user);
}
else if(!isLoggedIn&&(prefs_type==PREFS_TYPE.USER||prefs_type==PREFS_TYPE.NOT_SET)){
else if (!isLoggedIn && (prefs_type == PREFS_TYPE.USER || prefs_type == PREFS_TYPE.NOT_SET)) {
prefs_type = PREFS_TYPE.GUEST;
addPreferencesFromResource(R.xml.app_preferences_guest);
}
@ -133,17 +133,20 @@ public class SettingsFragment extends PreferenceFragmentCompat implements Shared
if (existingValue.equals(SILENT_SELECTED)) {
//Selects "Silent"
intent.putExtra(RingtoneManager.EXTRA_RINGTONE_EXISTING_URI, (Uri) null);
} else {
}
else {
intent.putExtra(RingtoneManager.EXTRA_RINGTONE_EXISTING_URI, Uri.parse(existingValue));
}
} else {
}
else {
//No ringtone has been selected, set to the default
intent.putExtra(RingtoneManager.EXTRA_RINGTONE_EXISTING_URI, Settings.System.DEFAULT_NOTIFICATION_URI);
}
startActivityForResult(intent, REQUEST_CODE_ALERT_RINGTONE);
return true;
} else {
}
else {
return super.onPreferenceTreeClick(preference);
}
}
@ -155,11 +158,13 @@ public class SettingsFragment extends PreferenceFragmentCompat implements Shared
SharedPreferences.Editor editor = settingsFile.edit();
if (ringtone != null) {
editor.putString(SELECTED_RINGTONE, ringtone.toString()).apply();
} else {
}
else {
//"Silent" was selected
editor.putString(SELECTED_RINGTONE, SILENT_SELECTED).apply();
}
} else {
}
else {
super.onActivityResult(requestCode, resultCode, data);
}
}
@ -169,19 +174,19 @@ public class SettingsFragment extends PreferenceFragmentCompat implements Shared
updatePreferenceVisibility();
}
private void updatePreferenceVisibility(){
if(isLoggedIn&& prefs_type==PREFS_TYPE.GUEST) {
private void updatePreferenceVisibility() {
if (isLoggedIn && prefs_type == PREFS_TYPE.GUEST) {
prefs_type = PREFS_TYPE.USER;
setPreferencesFromResource(R.xml.app_preferences_user, getPreferenceScreen().getKey());
if(!defaultHomeTabEntries.contains(UNREAD)){
if (!defaultHomeTabEntries.contains(UNREAD)) {
defaultHomeTabEntries.add(UNREAD);
defaultHomeTabValues.add("2");
}
}
else if(!isLoggedIn&&prefs_type==PREFS_TYPE.USER){
else if (!isLoggedIn && prefs_type == PREFS_TYPE.USER) {
prefs_type = PREFS_TYPE.GUEST;
setPreferencesFromResource(R.xml.app_preferences_guest,getPreferenceScreen().getKey());
if(defaultHomeTabEntries.contains(UNREAD)){
setPreferencesFromResource(R.xml.app_preferences_guest, getPreferenceScreen().getKey());
if (defaultHomeTabEntries.contains(UNREAD)) {
defaultHomeTabEntries.remove(UNREAD);
defaultHomeTabValues.remove("2");
}
@ -199,27 +204,33 @@ public class SettingsFragment extends PreferenceFragmentCompat implements Shared
boolean enabled;
if (key.equals(getString(R.string.pref_privacy_crashlytics_enable_key))) {
enabled = sharedPreferences.getBoolean(key, false);
if(enabled)
if (enabled)
BaseApplication.getInstance().setFirebaseCrashlyticsEnabled(true);
else {
Timber.i("Crashlytics collection will be disabled after restarting.");
BaseApplication.getInstance().setFirebaseCrashlyticsEnabled(false);
displayRestartAppToTakeEffectToast();
}
} else if (key.equals(getString(R.string.pref_privacy_analytics_enable_key))) {
}
else if (key.equals(getString(R.string.pref_privacy_analytics_enable_key))) {
enabled = sharedPreferences.getBoolean(key, false);
BaseApplication.getInstance().setFirebaseAnalyticsEnabled(enabled);
if(enabled)
if (enabled)
Timber.i("Analytics collection enabled.");
else
Timber.i("Analytics collection disabled.");
} else if (key.equals(getString(R.string.pref_app_display_relative_time_key))
&& BaseApplication.getInstance().isDisplayRelativeTimeEnabled()!=sharedPreferences.getBoolean(key, false)){
displayRestartAppToTakeEffectToast();
}
else if (key.equals(getString(R.string.pref_app_display_relative_time_key))
&& BaseApplication.getInstance().isDisplayRelativeTimeEnabled() != sharedPreferences.getBoolean(key, false)) {
displayRestartAppToTakeEffectToast();
}
else if (key.equals(getString(R.string.pref_app_display_compact_tabs_key))
&& BaseApplication.getInstance().isDisplayCompactTabsEnabled() != sharedPreferences.getBoolean(key, false)) {
displayRestartAppToTakeEffectToast();
}
}
private void displayRestartAppToTakeEffectToast(){
private void displayRestartAppToTakeEffectToast() {
Toast.makeText(BaseApplication.getInstance().getApplicationContext(), "This change will take effect once you restart the app.", Toast.LENGTH_SHORT).show();
}
}

1
app/src/main/java/gr/thmmy/mthmmy/activities/shoutbox/SendShoutTask.java

@ -37,7 +37,6 @@ public class SendShoutTask extends NetworkTask<Void> {
}
@Override
protected Void performTask(Document document, Response response) {
return null;

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

@ -59,7 +59,8 @@ public class ShoutAdapter extends CustomRecyclerView.Adapter<ShoutAdapter.ShoutV
public void onBindViewHolder(@NonNull ShoutViewHolder holder, int position) {
Shout currentShout = shouts[position];
holder.author.setText(currentShout.getShouter());
if (currentShout.isMemberOfTheMonth()) holder.author.setTextColor(context.getResources().getColor(R.color.member_of_the_month));
if (currentShout.isMemberOfTheMonth())
holder.author.setTextColor(context.getResources().getColor(R.color.member_of_the_month));
else holder.author.setTextColor(context.getResources().getColor(R.color.accent));
holder.author.setOnClickListener(view -> {
Intent intent = new Intent(context, ProfileActivity.class);
@ -125,7 +126,8 @@ public class ShoutAdapter extends CustomRecyclerView.Adapter<ShoutAdapter.ShoutV
intent.setFlags(FLAG_ACTIVITY_NEW_TASK);
context.startActivity(intent);
return true;
} else if (target.is(ThmmyPage.PageCategory.BOARD)) {
}
else if (target.is(ThmmyPage.PageCategory.BOARD)) {
Intent intent = new Intent(context, BoardActivity.class);
Bundle extras = new Bundle();
extras.putString(BUNDLE_BOARD_URL, uriString);
@ -134,7 +136,8 @@ public class ShoutAdapter extends CustomRecyclerView.Adapter<ShoutAdapter.ShoutV
intent.setFlags(FLAG_ACTIVITY_NEW_TASK);
context.startActivity(intent);
return true;
} else if (target.is(ThmmyPage.PageCategory.PROFILE)) {
}
else if (target.is(ThmmyPage.PageCategory.PROFILE)) {
Intent intent = new Intent(context, ProfileActivity.class);
Bundle extras = new Bundle();
extras.putString(BUNDLE_PROFILE_URL, uriString);

3
app/src/main/java/gr/thmmy/mthmmy/activities/shoutbox/ShoutboxActivity.java

@ -45,7 +45,8 @@ public class ShoutboxActivity extends BaseActivity {
if (count == 0) {
if (!shoutboxFragment.onBackPressed())
super.onBackPressed();
} else {
}
else {
getSupportFragmentManager().popBackStack();
}
}

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

@ -93,7 +93,8 @@ public class ShoutboxFragment extends Fragment {
if (item.getItemId() == R.id.menu_refresh) {
shoutboxViewModel.loadShoutbox(true);
return true;
} else {
}
else {
return false;
}
}
@ -142,7 +143,8 @@ public class ShoutboxFragment extends Fragment {
BaseApplication.getInstance().logFirebaseAnalyticsEvent("shout", null);
editorView.getEditText().getText().clear();
shoutboxViewModel.loadShoutbox(true);
} else if (resultCode == NetworkResultCodes.NETWORK_ERROR) {
}
else if (resultCode == NetworkResultCodes.NETWORK_ERROR) {
Timber.w("Failed to send shout");
Toast.makeText(BaseApplication.getInstance().getApplicationContext(), "NetworkError", Toast.LENGTH_SHORT).show();
}
@ -154,10 +156,12 @@ public class ShoutboxFragment extends Fragment {
shoutboxViewModel.setShoutbox(shoutbox);
if (shoutbox.getShoutSend() != null)
editorView.setVisibility(View.VISIBLE);
} else if (resultCode == NetworkResultCodes.NETWORK_ERROR) {
}
else if (resultCode == NetworkResultCodes.NETWORK_ERROR) {
Timber.w("Failed to retreive shoutbox due to network error");
Toast.makeText(BaseApplication.getInstance().getApplicationContext(), "NetworkError", Toast.LENGTH_SHORT).show();
} else {
}
else {
Timber.wtf("Failed to retreive shoutbox due to unknown error");
Toast.makeText(BaseApplication.getInstance().getApplicationContext(), "Failed to retrieve shoutbox, please contact mthmmy developer team", Toast.LENGTH_LONG).show();
}

2
app/src/main/java/gr/thmmy/mthmmy/activities/topic/Posting.java

@ -62,7 +62,7 @@ public class Posting {
if (finalUrl.contains("action=post")) {
Document postErrorPage = Jsoup.parse(response.body().string());
Element errorsElement = postErrorPage.select("tr[id=errors] div[id=error_list]").first();
if(errorsElement!=null){
if (errorsElement != null) {
String[] errors = errorsElement.toString().split("<br>");
for (int i = 0; i < errors.length; ++i) { //TODO test
Timber.d(String.valueOf(i));

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

@ -198,7 +198,8 @@ public class TopicActivity extends BaseActivity implements TopicAdapter.OnPostFo
if (!sessionManager.isLoggedIn()) {
replyFAB.hide();
replyFAB.setTag(false);
} else {
}
else {
replyFAB.setOnClickListener(view -> {
if (sessionManager.isLoggedIn())
viewModel.prepareForReply();
@ -279,10 +280,12 @@ public class TopicActivity extends BaseActivity implements TopicAdapter.OnPostFo
if (drawer.isDrawerOpen()) {
drawer.closeDrawer();
return;
} else if (emojiKeyboard.getVisibility() == View.VISIBLE) {
}
else if (emojiKeyboard.getVisibility() == View.VISIBLE) {
emojiKeyboard.setVisibility(View.GONE);
return;
} else if (viewModel.isWritingReply()) {
}
else if (viewModel.isWritingReply()) {
// persist reply
SharedPreferences drafts = getSharedPreferences(getString(R.string.pref_topic_drafts_key), MODE_PRIVATE);
Post reply = (Post) topicItems.get(topicItems.size() - 1);
@ -296,7 +299,8 @@ public class TopicActivity extends BaseActivity implements TopicAdapter.OnPostFo
replyFAB.setTag(true);
bottomNavBar.setVisibility(View.VISIBLE);
return;
} else if (viewModel.isEditingPost()) {
}
else if (viewModel.isEditingPost()) {
((Post) topicItems.get(viewModel.getPostBeingEditedPosition())).setPostType(Post.TYPE_POST);
topicAdapter.notifyItemChanged(viewModel.getPostBeingEditedPosition());
topicAdapter.setBackButtonHidden();
@ -319,9 +323,9 @@ public class TopicActivity extends BaseActivity implements TopicAdapter.OnPostFo
@Override
protected void onDestroy() {
super.onDestroy();
if(topicInfoDialog!=null){
if (topicInfoDialog != null) {
topicInfoDialog.dismiss();
topicInfoDialog=null;
topicInfoDialog = null;
}
recyclerView.setAdapter(null);
viewModel.stopLoading();
@ -364,7 +368,8 @@ public class TopicActivity extends BaseActivity implements TopicAdapter.OnPostFo
if (autoIncrement) {
viewModel.incrementPageRequestValue(step, false);
repeatUpdateHandler.postDelayed(new RepetitiveUpdater(step), REPEAT_DELAY);
} else if (autoDecrement) {
}
else if (autoDecrement) {
viewModel.decrementPageRequestValue(step, false);
repeatUpdateHandler.postDelayed(new RepetitiveUpdater(step), REPEAT_DELAY);
}
@ -383,19 +388,23 @@ public class TopicActivity extends BaseActivity implements TopicAdapter.OnPostFo
previousPage.setEnabled(false);
nextPage.setEnabled(false);
lastPage.setEnabled(false);
} else if (exception == previousPage) {
}
else if (exception == previousPage) {
firstPage.setEnabled(false);
nextPage.setEnabled(false);
lastPage.setEnabled(false);
} else if (exception == nextPage) {
}
else if (exception == nextPage) {
firstPage.setEnabled(false);
previousPage.setEnabled(false);
lastPage.setEnabled(false);
} else if (exception == lastPage) {
}
else if (exception == lastPage) {
firstPage.setEnabled(false);
previousPage.setEnabled(false);
nextPage.setEnabled(false);
} else {
}
else {
paginationEnabled(false);
}
}
@ -406,7 +415,8 @@ public class TopicActivity extends BaseActivity implements TopicAdapter.OnPostFo
increment.setOnClickListener(v -> {
if (!autoIncrement && step == LARGE_STEP) {
viewModel.setPageIndicatorIndex(viewModel.getPageCount(), true);
} else if (!autoIncrement) {
}
else if (!autoIncrement) {
viewModel.incrementPageRequestValue(step, true);
}
});
@ -428,11 +438,13 @@ public class TopicActivity extends BaseActivity implements TopicAdapter.OnPostFo
public boolean onTouch(View v, MotionEvent event) {
if (event.getAction() == MotionEvent.ACTION_DOWN) {
rect = new Rect(v.getLeft(), v.getTop(), v.getRight(), v.getBottom());
} else if (rect != null && event.getAction() == MotionEvent.ACTION_UP && autoIncrement) {
}
else if (rect != null && event.getAction() == MotionEvent.ACTION_UP && autoIncrement) {
autoIncrement = false;
paginationEnabled(true);
viewModel.loadPageIndicated();
} else if (rect != null && event.getAction() == MotionEvent.ACTION_MOVE) {
}
else if (rect != null && event.getAction() == MotionEvent.ACTION_MOVE) {
if (!rect.contains(v.getLeft() + (int) event.getX(), v.getTop() + (int) event.getY())) {
autoIncrement = false;
viewModel.setPageIndicatorIndex(viewModel.getCurrentPageIndex(), false);
@ -450,7 +462,8 @@ public class TopicActivity extends BaseActivity implements TopicAdapter.OnPostFo
decrement.setOnClickListener(v -> {
if (!autoDecrement && step == LARGE_STEP) {
viewModel.setPageIndicatorIndex(1, true);
} else if (!autoDecrement) {
}
else if (!autoDecrement) {
viewModel.decrementPageRequestValue(step, true);
}
});
@ -472,11 +485,13 @@ public class TopicActivity extends BaseActivity implements TopicAdapter.OnPostFo
public boolean onTouch(View v, MotionEvent event) {
if (event.getAction() == MotionEvent.ACTION_DOWN) {
rect = new Rect(v.getLeft(), v.getTop(), v.getRight(), v.getBottom());
} else if (event.getAction() == MotionEvent.ACTION_UP && autoDecrement) {
}
else if (event.getAction() == MotionEvent.ACTION_UP && autoDecrement) {
autoDecrement = false;
paginationEnabled(true);
viewModel.loadPageIndicated();
} else if (event.getAction() == MotionEvent.ACTION_MOVE) {
}
else if (event.getAction() == MotionEvent.ACTION_MOVE) {
if (rect != null &&
!rect.contains(v.getLeft() + (int) event.getX(), v.getTop() + (int) event.getY())) {
autoIncrement = false;
@ -514,7 +529,8 @@ public class TopicActivity extends BaseActivity implements TopicAdapter.OnPostFo
if (resultCode == NetworkResultCodes.SUCCESSFUL) {
Timber.i("Post deleted successfully");
viewModel.reloadPage();
} else {
}
else {
Timber.w("Failed to delete post");
Toast.makeText(BaseApplication.getInstance().getApplicationContext(), "Delete failed!", Toast.LENGTH_SHORT).show();
}
@ -551,7 +567,8 @@ public class TopicActivity extends BaseActivity implements TopicAdapter.OnPostFo
if ((((Post) topicItems.get(topicItems.size() - 1)).getPostNumber() + 1) % 15 == 0) {
Timber.i("Reply was posted in new page. Switching to last page.");
viewModel.loadUrl(ParseHelpers.getBaseURL(viewModel.getTopicUrl()) + "." + 2147483647);
} else {
}
else {
viewModel.reloadPage();
}
break;
@ -621,7 +638,8 @@ public class TopicActivity extends BaseActivity implements TopicAdapter.OnPostFo
bottomNavBar.setVisibility(View.VISIBLE);
viewModel.setEditingPost(false);
viewModel.reloadPage();
} else {
}
else {
Timber.i("Post edit unsuccessful");
Toast.makeText(BaseApplication.getInstance().getApplicationContext(), "Edit failed!", Toast.LENGTH_SHORT).show();
recyclerView.getChildAt(viewModel.getPostBeingEditedPosition()).setAlpha(1);
@ -689,7 +707,8 @@ public class TopicActivity extends BaseActivity implements TopicAdapter.OnPostFo
if (replyPageUrl == null) {
replyFAB.hide();
replyFAB.setTag(false);
} else {
}
else {
replyFAB.show();
replyFAB.setTag(true);
}
@ -742,7 +761,8 @@ public class TopicActivity extends BaseActivity implements TopicAdapter.OnPostFo
errorTextview.setVisibility(View.GONE);
recyclerView.setVisibility(View.VISIBLE);
});
} else {
}
else {
// a page has already been loaded
viewModel.setPageIndicatorIndex(viewModel.getCurrentPageIndex(), false);
snackbar = Snackbar.make(findViewById(R.id.main_content),
@ -787,7 +807,8 @@ public class TopicActivity extends BaseActivity implements TopicAdapter.OnPostFo
replyFAB.hide();
replyFAB.setTag(false);
bottomNavBar.setVisibility(View.GONE);
} else {
}
else {
Timber.i("Prepare for reply unsuccessful");
Snackbar.make(findViewById(R.id.main_content), getString(R.string.generic_network_error), Snackbar.LENGTH_SHORT).show();
}
@ -803,16 +824,19 @@ public class TopicActivity extends BaseActivity implements TopicAdapter.OnPostFo
replyFAB.hide();
replyFAB.setTag(false);
bottomNavBar.setVisibility(View.GONE);
} else {
}
else {
Timber.i("Prepare for edit unsuccessful");
Snackbar.make(findViewById(R.id.main_content), getString(R.string.generic_network_error), Snackbar.LENGTH_SHORT).show();
}
});
}
/**This method sets a long click listener on the title of the topic. Once the
/**
* This method sets a long click listener on the title of the topic. Once the
* listener gets triggered, it copies the link url of the topic in the clipboard.
* This method is getting called on the onCreate() of the TopicActivity*/
* This method is getting called on the onCreate() of the TopicActivity
*/
void setToolbarOnLongClickListener(String url) {
toolbar.setOnLongClickListener(view -> {
//Try to set the clipboard text

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

@ -129,7 +129,8 @@ class TopicAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> {
View itemView = LayoutInflater.from(parent.getContext())
.inflate(R.layout.activity_topic_post_row, parent, false);
return new PostViewHolder(itemView);
} else if (viewType == Post.TYPE_QUICK_REPLY) {
}
else if (viewType == Post.TYPE_QUICK_REPLY) {
View view = LayoutInflater.from(parent.getContext()).
inflate(R.layout.activity_topic_quick_reply_row, parent, false);
@ -143,7 +144,8 @@ class TopicAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> {
quickReplyText.requestFocus();
return new QuickReplyViewHolder(view);
} else if (viewType == Post.TYPE_EDIT) {
}
else if (viewType == Post.TYPE_EDIT) {
View view = LayoutInflater.from(parent.getContext()).
inflate(R.layout.activity_topic_edit_row, parent, false);
@ -157,11 +159,13 @@ class TopicAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> {
editPostEdittext.requestFocus();
return new EditMessageViewHolder(view);
} else if (viewType == Poll.TYPE_POLL) {
}
else if (viewType == Poll.TYPE_POLL) {
View view = LayoutInflater.from(parent.getContext()).
inflate(R.layout.activity_topic_poll, parent, false);
return new PollViewHolder(view);
} else {
}
else {
throw new IllegalArgumentException("Unknown view type");
}
}
@ -227,7 +231,8 @@ class TopicAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> {
holder.voteChart.setVisibility(View.GONE);
holder.selectedEntry.setVisibility(View.GONE);
holder.optionsLayout.setVisibility(View.VISIBLE);
} else if (poll.getAvailableVoteCount() == 1) {
}
else if (poll.getAvailableVoteCount() == 1) {
// vote single option
RadioGroup radioGroup = new RadioGroup(context);
for (int i = 0; i < entries.length; i++) {
@ -236,7 +241,8 @@ class TopicAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> {
radioButton.setMovementMethod(LinkMovementMethod.getInstance());
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
radioButton.setText(Html.fromHtml(entries[i].getEntryName(), Html.FROM_HTML_MODE_LEGACY));
} else
}
else
radioButton.setText(Html.fromHtml(entries[i].getEntryName()));
radioButton.setText(ThmmyParser.html2span(context, entries[i].getEntryName()));
@ -247,7 +253,8 @@ class TopicAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> {
holder.voteChart.setVisibility(View.GONE);
holder.selectedEntry.setVisibility(View.GONE);
holder.optionsLayout.setVisibility(View.VISIBLE);
} else if (poll.isPollResultsHidden()) {
}
else if (poll.isPollResultsHidden()) {
// vote already submitted but results are hidden
Poll.Entry[] entries1 = poll.getEntries();
for (int i = 0; i < entries1.length; i++) {
@ -272,7 +279,8 @@ class TopicAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> {
holder.voteChart.setVisibility(View.GONE);
holder.selectedEntry.setVisibility(View.GONE);
holder.optionsLayout.setVisibility(View.VISIBLE);
} else {
}
else {
// Showing results
holder.optionsLayout.setVisibility(View.GONE);
@ -331,16 +339,19 @@ class TopicAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> {
if (poll.getRemoveVoteUrl() != null) {
holder.removeVotesButton.setOnClickListener(v -> viewModel.removeVote());
holder.removeVotesButton.setVisibility(View.VISIBLE);
} else holder.removeVotesButton.setVisibility(View.GONE);
}
else holder.removeVotesButton.setVisibility(View.GONE);
if (poll.getShowVoteResultsUrl() != null) {
holder.showPollResultsButton.setOnClickListener(v -> viewModel.loadUrl(poll.getShowVoteResultsUrl()));
holder.showPollResultsButton.setVisibility(View.VISIBLE);
} else holder.showPollResultsButton.setVisibility(View.GONE);
}
else holder.showPollResultsButton.setVisibility(View.GONE);
if (poll.getShowOptionsUrl() != null) {
holder.hidePollResultsButton.setOnClickListener(v -> viewModel.loadUrl(poll.getShowOptionsUrl()));
holder.hidePollResultsButton.setVisibility(View.VISIBLE);
} else holder.hidePollResultsButton.setVisibility(View.GONE);
}
else holder.hidePollResultsButton.setVisibility(View.GONE);
if (poll.getPollFormUrl() != null) {
holder.submitButton.setOnClickListener(v -> {
if (!viewModel.submitVote(holder.optionsLayout)) {
@ -351,8 +362,10 @@ class TopicAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> {
}
});
holder.submitButton.setVisibility(View.VISIBLE);
} else holder.submitButton.setVisibility(View.GONE);
} else {
}
else holder.submitButton.setVisibility(View.GONE);
}
else {
Post currentPost = (Post) topicItems.get(position);
if (currentHolder instanceof PostViewHolder) {
final PostViewHolder holder = (PostViewHolder) currentHolder;
@ -382,7 +395,8 @@ class TopicAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> {
int filesTextColor;
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
filesTextColor = context.getResources().getColor(R.color.accent, null);
} else
}
else
filesTextColor = context.getResources().getColor(R.color.accent);
for (final ThmmyFile attachedFile : currentPost.getAttachedFiles()) {
@ -405,7 +419,8 @@ class TopicAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> {
int lastEditTextColor;
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
lastEditTextColor = context.getResources().getColor(R.color.white, null);
} else
}
else
lastEditTextColor = context.getResources().getColor(R.color.white);
final TextView lastEdit = new TextView(context);
@ -415,7 +430,8 @@ class TopicAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> {
lastEdit.setPadding(0, 3, 0, 3);
holder.postFooter.addView(lastEdit);
}
} else {
}
else {
holder.bodyFooterDivider.setVisibility(View.GONE);
holder.postFooter.removeAllViews();
}
@ -430,7 +446,8 @@ class TopicAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> {
mNumberOfPosts = currentPost.getNumberOfPosts();
mPersonalText = currentPost.getPersonalText();
mNumberOfStars = currentPost.getNumberOfStars();
} else {
}
else {
mSpecialRank = null;
mRank = null;
mGender = null;
@ -443,27 +460,32 @@ class TopicAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> {
if (!Objects.equals(mSpecialRank, "") && mSpecialRank != null) {
holder.specialRank.setText(mSpecialRank);
holder.specialRank.setVisibility(View.VISIBLE);
} else
}
else
holder.specialRank.setVisibility(View.GONE);
if (!Objects.equals(mRank, "") && mRank != null) {
holder.rank.setText(mRank);
holder.rank.setVisibility(View.VISIBLE);
} else
}
else
holder.rank.setVisibility(View.GONE);
if (!Objects.equals(mGender, "") && mGender != null) {
holder.gender.setText(mGender);
holder.gender.setVisibility(View.VISIBLE);
} else
}
else
holder.gender.setVisibility(View.GONE);
if (!Objects.equals(mNumberOfPosts, "") && mNumberOfPosts != null) {
holder.numberOfPosts.setText(mNumberOfPosts);
holder.numberOfPosts.setVisibility(View.VISIBLE);
} else
}
else
holder.numberOfPosts.setVisibility(View.GONE);
if (!Objects.equals(mPersonalText, "") && mPersonalText != null) {
holder.personalText.setText("\"" + mPersonalText + "\"");
holder.personalText.setVisibility(View.VISIBLE);
} else
}
else
holder.personalText.setVisibility(View.GONE);
if (mUserColor != USER_COLOR_YELLOW)
holder.username.setTextColor(mUserColor);
@ -482,25 +504,30 @@ class TopicAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> {
holder.stars.setText(usersStars.toString());
holder.stars.setTextColor(mUserColor);
holder.stars.setVisibility(View.VISIBLE);
} else
}
else
holder.stars.setVisibility(View.GONE);
if (currentPost.isUserMentionedInPost()) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
holder.cardChildLinear.setBackground(context.getResources().
getDrawable(R.drawable.mention_card, null));
} else
}
else
holder.cardChildLinear.setBackground(context.getResources().
getDrawable(R.drawable.mention_card));
} else if (mUserColor == TopicParser.USER_COLOR_PINK) {
}
else if (mUserColor == TopicParser.USER_COLOR_PINK) {
//Special card for special member of the month!
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
holder.cardChildLinear.setBackground(context.getResources().
getDrawable(R.drawable.member_of_the_month_card, null));
} else
}
else
holder.cardChildLinear.setBackground(context.getResources().
getDrawable(R.drawable.member_of_the_month_card));
} else holder.cardChildLinear.setBackground(null);
}
else holder.cardChildLinear.setBackground(null);
//Avoid's view's visibility recycling
if (!currentPost.isDeleted() && viewModel.isUserExtraInfoVisible(holder.getAdapterPosition())) {
@ -513,7 +540,8 @@ class TopicAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> {
holder.subject.setTextColor(Color.parseColor("#FFFFFF"));
holder.subject.setMaxLines(Integer.MAX_VALUE);
holder.subject.setEllipsize(null);
} else {
}
else {
holder.userExtraInfo.setVisibility(View.GONE);
holder.userExtraInfo.setAlpha(0.0f);
@ -554,7 +582,8 @@ class TopicAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> {
holder.subject, Color.parseColor("#FFFFFF"),
Color.parseColor("#757575"), (LinearLayout) v);
});
} else {
}
else {
holder.header.setOnClickListener(null);
holder.userExtraInfo.setOnClickListener(null);
}
@ -636,7 +665,8 @@ class TopicAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> {
holder.quoteToggle.setImageResource(R.drawable.ic_format_quote_unchecked_24dp);
});
}
} else if (currentHolder instanceof QuickReplyViewHolder) {
}
else if (currentHolder instanceof QuickReplyViewHolder) {
final QuickReplyViewHolder holder = (QuickReplyViewHolder) currentHolder;
Post reply = (Post) topicItems.get(position);
@ -647,7 +677,8 @@ class TopicAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> {
holder.itemView.setEnabled(true);
if (reply.getSubject() != null) {
holder.quickReplySubject.setText(reply.getSubject());
} else {
}
else {
holder.quickReplySubject.setText("Re: " + viewModel.getTopicTitle().getValue());
}
holder.quickReplySubject.setRawInputType(InputType.TYPE_CLASS_TEXT);
@ -700,10 +731,11 @@ class TopicAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> {
backPressHidden = false;
}
holder.quickReplySubject.addTextChangedListener(createTextWatcher(holder, TextWatcherType.SUBJECT));
} else if (currentHolder instanceof EditMessageViewHolder) {
}
else if (currentHolder instanceof EditMessageViewHolder) {
final EditMessageViewHolder holder = (EditMessageViewHolder) currentHolder;
loadAvatar(getSessionManager().getAvatarLink(), holder.thumbnail, holder.itemView.getContext());
loadAvatar(getSessionManager().getAvatarLink(), holder.thumbnail, holder.itemView.getContext());
holder.username.setText(getSessionManager().getUsername());
holder.editSubject.setText(currentPost.getSubject());
@ -749,33 +781,36 @@ class TopicAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> {
private enum TextWatcherType {
CONTENT, SUBJECT
}
private TextWatcher createTextWatcher(@NonNull final RecyclerView.ViewHolder holder, TextWatcherType type){
private TextWatcher createTextWatcher(@NonNull final RecyclerView.ViewHolder holder, TextWatcherType type) {
return new TextWatcher() {
@Override
public void beforeTextChanged(CharSequence charSequence, int i, int i1, int i2) { }
public void beforeTextChanged(CharSequence charSequence, int i, int i1, int i2) {
}
@Override
public void onTextChanged(CharSequence charSequence, int i, int i1, int i2) {
int position = holder.getAdapterPosition();
if (position >= 0 && position < topicItems.size()){
if (position >= 0 && position < topicItems.size()) {
Post post = ((Post) topicItems.get(position));
if(type == TextWatcherType.CONTENT)
if (type == TextWatcherType.CONTENT)
post.setBbContent(charSequence.toString());
else if(type == TextWatcherType.SUBJECT)
else if (type == TextWatcherType.SUBJECT)
post.setSubject(charSequence.toString());
}
}
@Override
public void afterTextChanged(Editable editable) { }
public void afterTextChanged(Editable editable) {
}
};
}
private void loadAvatar(String imageUrl, ImageView imageView, Context context) {
if(imageUrl!=null)
if (imageUrl != null)
imageUrl = imageUrl.trim();
if(isValidContextForGlide(context)) {
if (isValidContextForGlide(context)) {
Glide.with(context)
.load(imageUrl)
.circleCrop()
@ -948,7 +983,8 @@ class TopicAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> {
return true;
}
}
} else if ((Objects.equals(uriString, ParseHelpers.getBaseURL(viewModel.getTopicUrl())) &&
}
else if ((Objects.equals(uriString, ParseHelpers.getBaseURL(viewModel.getTopicUrl())) &&
viewModel.getCurrentPageIndex() == 1) ||
Integer.parseInt(uriString.substring(ParseHelpers.getBaseURL(viewModel.getTopicUrl()).length() + 1)) / 15 + 1 ==
viewModel.getCurrentPageIndex()) {
@ -964,7 +1000,8 @@ class TopicAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> {
intent.setFlags(FLAG_ACTIVITY_NEW_TASK);
context.startActivity(intent);
return true;
} else if (target.is(ThmmyPage.PageCategory.BOARD)) {
}
else if (target.is(ThmmyPage.PageCategory.BOARD)) {
Intent intent = new Intent(context, BoardActivity.class);
Bundle extras = new Bundle();
extras.putString(BUNDLE_BOARD_URL, uriString);
@ -973,7 +1010,8 @@ class TopicAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> {
intent.setFlags(FLAG_ACTIVITY_NEW_TASK);
context.startActivity(intent);
return true;
} else if (target.is(ThmmyPage.PageCategory.PROFILE)) {
}
else if (target.is(ThmmyPage.PageCategory.PROFILE)) {
Intent intent = new Intent(context, ProfileActivity.class);
Bundle extras = new Bundle();
extras.putString(BUNDLE_PROFILE_URL, uriString);

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

@ -37,7 +37,7 @@ import timber.log.Timber;
public class TopicParser {
private static Pattern mentionsPattern = Pattern.
compile("<div class=\"quoteheader\">\\n\\s+?<a href=.+?>(Quote from|Παράθεση από): "
+ BaseActivity.getSessionManager().getUsername() +"\\s(στις|on)");
+ BaseActivity.getSessionManager().getUsername() + "\\s(στις|on)");
//User colors
private static final int USER_COLOR_BLACK = Color.parseColor("#000000");
@ -87,7 +87,8 @@ public class TopicParser {
break;
}
}
} else {
}
else {
Elements findCurrentPage = topic.select("td:contains(Pages:)>b");
for (Element item : findCurrentPage) {
@ -125,7 +126,8 @@ public class TopicParser {
returnPages = Integer.parseInt(item.text());
}
}
} else {
}
else {
Elements pages = topic.select("td:contains(Pages:)>a.navPages");
if (pages.size() != 0) {
@ -220,7 +222,8 @@ public class TopicParser {
if (postIndex != null) {
String tmp = postIndex.attr("name");
p_postIndex = Integer.parseInt(tmp.substring(tmp.indexOf("msg") + 3));
} else {
}
else {
postIndex = thisRow.select("div[id^=subject]").first();
if (postIndex == null)
p_postIndex = NO_INDEX;
@ -246,7 +249,8 @@ public class TopicParser {
.first().text();
p_userName = p_userName.substring(0, p_userName.indexOf(" Επισκέπτης"));
p_userColor = USER_COLOR_YELLOW;
} else {
}
else {
p_userName = userName.html();
p_profileURL = userName.attr("href");
}
@ -271,7 +275,8 @@ public class TopicParser {
Element postNum = thisRow.select("div.smalltext:matches(Απάντηση #)").first();
if (postNum == null) { //Topic starter
p_postNum = 0;
} else {
}
else {
String tmp_str = postNum.text().substring(12);
p_postNum = Integer.parseInt(tmp_str.substring(0, tmp_str.indexOf(" στις")));
}
@ -306,7 +311,8 @@ public class TopicParser {
p_attachedFiles.add(new ThmmyFile(attachedUrl, attachedFileName, attachedFileInfo));
}
}
} else {
}
else {
//Finds username
userName = thisRow.select("a[title^=View the profile of]").first();
if (userName == null) { //Deleted profile
@ -316,7 +322,8 @@ public class TopicParser {
.first().text();
p_userName = p_userName.substring(0, p_userName.indexOf(" Guest"));
p_userColor = USER_COLOR_YELLOW;
} else {
}
else {
p_userName = userName.html();
p_profileURL = userName.attr("href");
}
@ -343,7 +350,8 @@ public class TopicParser {
Element postNum = thisRow.select("div.smalltext:matches(Reply #)").first();
if (postNum == null) { //Topic starter
p_postNum = 0;
} else {
}
else {
String tmp_str = postNum.text().substring(9);
p_postNum = Integer.parseInt(tmp_str.substring(0, tmp_str.indexOf(" on")));
}
@ -409,7 +417,8 @@ public class TopicParser {
.attr("abs:src"));
}
}
} else {
}
else {
for (String line : infoList) {
if (line.contains("Posts:")) {
postsLineIndex = infoList.indexOf(line);
@ -437,7 +446,8 @@ public class TopicParser {
if (starsLineIndex == -1 || starsLineIndex == 1) {
p_rank = infoList.get(0).trim(); //First line has the rank
p_specialRank = null; //They don't have a special rank
} else if (starsLineIndex == 2) { //This member has a special rank
}
else if (starsLineIndex == 2) { //This member has a special rank
p_specialRank = infoList.get(0).trim(); //First line has the special rank
p_rank = infoList.get(1).trim(); //Second line has the rank
}
@ -467,7 +477,8 @@ public class TopicParser {
, p_attachedFiles, p_postLastEditDate, p_postURL, p_deletePostURL, p_editPostURL
, p_isUserMentionedInPost, Post.TYPE_POST));
} else { //Deleted user
}
else { //Deleted user
//Add new post in postsList, only standard information needed
parsedPostsList.add(new Post(p_thumbnailURL, p_userName, p_subject, p_post
, null, p_postIndex, p_postNum, p_postDate, p_userColor, p_attachedFiles
@ -516,7 +527,8 @@ public class TopicParser {
availableVoteCount = Integer.parseInt(prompt.substring(integerMatcher.start(), integerMatcher.end()));
}
links = formTableRows.get(1).child(1).select("a");
} else {
}
else {
availableVoteCount = 1;
links = formTableRows.first().child(1).select("a");
}
@ -524,7 +536,8 @@ public class TopicParser {
if (links != null && links.size() > 0) {
showVoteResultsUrl = links.first().attr("href");
}
} else {
}
else {
// poll in results mode
Elements entryRows = pollColumn.select("table[cellspacing] tr");
for (int i = 0; i < entryRows.size(); i++) {

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

@ -74,6 +74,7 @@ public class EditTask extends AsyncTask<String, Void, Boolean> {
public interface EditTaskCallbacks {
void onEditTaskStarted();
void onEditTaskFinished(boolean result, int position);
}
}

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

@ -74,6 +74,7 @@ public class PrepareForEditTask extends AsyncTask<String, Void, PrepareForEditRe
public interface PrepareForEditCallbacks {
void onPrepareEditStarted();
void onPrepareEditCancelled();
}

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

@ -53,7 +53,7 @@ public class PrepareForReplyTask extends AsyncTask<Integer, Void, PrepareForRepl
// TODO: Convert this task to (New)ParseTask (?) / handle parsing errors in a better way
Timber.e(e, "Prepare failed (1)");
return new PrepareForReplyResult(false, null, null, null, null, null);
} catch (IOException | Selector.SelectorParseException e){
} catch (IOException | Selector.SelectorParseException e) {
Timber.e(e, "Prepare failed (2)");
return new PrepareForReplyResult(false, null, null, null, null, null);
}
@ -62,7 +62,7 @@ public class PrepareForReplyTask extends AsyncTask<Integer, Void, PrepareForRepl
for (Integer postIndex : postIndices) {
request = new Request.Builder()
.url("https://www.thmmy.gr/smf/index.php?action=quotefast;quote=" +
postIndex + ";" + "sesc=" + sc + ";xml")
postIndex + ";" + "sesc=" + sc + ";xml")
.build();
try {
Response response = client.newCall(request).execute();
@ -85,6 +85,7 @@ public class PrepareForReplyTask extends AsyncTask<Integer, Void, PrepareForRepl
public interface PrepareForReplyCallbacks {
void onPrepareForReplyStarted();
void onPrepareForReplyCancelled();
}

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

@ -68,6 +68,7 @@ public class ReplyTask extends AsyncTask<String, Void, Posting.REPLY_STATUS> {
public interface ReplyTaskCallbacks {
void onReplyTaskStarted();
void onReplyTaskFinished(Posting.REPLY_STATUS result);
}
}

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

@ -123,7 +123,8 @@ public class TopicTask extends AsyncTask<String, Void, TopicTaskResult> {
if (isUnauthorized(topic)) {
return new TopicTaskResult(ResultCode.UNAUTHORIZED, null, null, null,
0, 0, 0, 0, null, null);
} else {
}
else {
Timber.e(e, "Topic parse failed");
return new TopicTaskResult(ResultCode.PARSING_ERROR, null, null, null,
0, 0, 0, 0, null, null);
@ -149,6 +150,7 @@ public class TopicTask extends AsyncTask<String, Void, TopicTaskResult> {
public interface TopicTaskObserver {
void onTopicTaskStarted();
void onTopicTaskCancelled();
}

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

@ -177,7 +177,7 @@ public class UploadActivity extends BaseActivity {
generateFieldsButton = findViewById(R.id.upload_title_description_builder);
generateFieldsButton.setEnabled(false);
generateFieldsButton.setOnClickListener(view -> {
if(uploadsCourse!=null && !uploadsCourse.getName().equals("") && !semester.equals("")){
if (uploadsCourse != null && !uploadsCourse.getName().equals("") && !semester.equals("")) {
Intent intent = new Intent(UploadActivity.this, UploadFieldsBuilderActivity.class);
Bundle builderExtras = new Bundle();
builderExtras.putString(BUNDLE_UPLOAD_FIELD_BUILDER_COURSE_NAME, uploadsCourse.getName());
@ -329,7 +329,8 @@ public class UploadActivity extends BaseActivity {
tempFileUri = UploadsHelper.createTempFile(this, storage,
uploadFile.getFileUri(),
FileUtils.getFilenameWithoutExtension(editTextFilename));
} else {
}
else {
//Renames the photo taken
String photoPath = uploadFile.getPhotoFile().getPath();
photoPath = photoPath.substring(0, photoPath.lastIndexOf(File.separator));
@ -348,14 +349,16 @@ public class UploadActivity extends BaseActivity {
uploadFile.setFileUri(FileProvider.getUriForFile(this, getPackageName() +
".provider", uploadFile.getPhotoFile()));
}
} else {
}
else {
requestPerms(UPLOAD_REQUEST_STORAGE_CODE);
zipTask = null;
dialog.cancel();
return;
}
}
} else {
}
else {
Uri[] filesListArray = new Uri[filesList.size()];
for (int i = 0; i < filesList.size(); ++i) {
filesListArray[i] = filesList.get(i).getFileUri();
@ -368,7 +371,8 @@ public class UploadActivity extends BaseActivity {
if (checkPerms()) {
zipTask.execute(filesListArray);
finish();
} else {
}
else {
requestPerms(UPLOAD_REQUEST_STORAGE_CODE);
dialog.cancel();
}
@ -384,7 +388,8 @@ public class UploadActivity extends BaseActivity {
? filesList.get(0).getFileUri()
: tempFileUri)) {
finish();
} else {
}
else {
Toast.makeText(BaseApplication.getInstance().getApplicationContext(), "Couldn't initiate upload.", Toast.LENGTH_SHORT).show();
}
});
@ -406,7 +411,8 @@ public class UploadActivity extends BaseActivity {
//Parses the uploads page
parseUploadPageTask = new ParseUploadPageTask();
parseUploadPageTask.execute(uploadIndexUrl);
} else {
}
else {
//Renders the already parsed data
updateUIElements();
generateFieldsButton.setEnabled(true);
@ -465,7 +471,8 @@ public class UploadActivity extends BaseActivity {
addFileViewToList(filename);
filesList.add(new UploadFile(false, newFileUri, null));
}
} else {
}
else {
Uri newFileUri = data.getData();
if (newFileUri != null) {
String filename = FileUtils.filenameFromUri(this, newFileUri);
@ -481,23 +488,30 @@ public class UploadActivity extends BaseActivity {
filename = filename.toLowerCase();
if (filename.endsWith(".jpg")) {
fileIcon = "jpg_image.gif";
} else if (filename.endsWith(".gif")) {
}
else if (filename.endsWith(".gif")) {
fileIcon = "gif_image.gif";
} else if (filename.endsWith(".png")) {
}
else if (filename.endsWith(".png")) {
fileIcon = "png_image.gif";
} else if (filename.endsWith(".html") || filename.endsWith(".htm")) {
}
else if (filename.endsWith(".html") || filename.endsWith(".htm")) {
fileIcon = "html_file.gif";
} else if (filename.endsWith(".pdf") || filename.endsWith(".doc") ||
}
else if (filename.endsWith(".pdf") || filename.endsWith(".doc") ||
filename.endsWith("djvu")) {
fileIcon = "text_file.gif";
} else if (filename.endsWith(".zip") || filename.endsWith(".rar") ||
}
else if (filename.endsWith(".zip") || filename.endsWith(".rar") ||
filename.endsWith(".tar") || filename.endsWith(".tar.gz") ||
filename.endsWith(".gz")) {
fileIcon = "archive.gif";
} else {
}
else {
fileIcon = "blank.gif";
}
} else {
}
else {
fileIcon = "archive.gif";
textWatcher.setFileExtension(".zip");
@ -509,7 +523,8 @@ public class UploadActivity extends BaseActivity {
filesList.add(new UploadFile(false, newFileUri, null));
}
}
} else if (requestCode == AFR_REQUEST_CODE_CAMERA) {
}
else if (requestCode == AFR_REQUEST_CODE_CAMERA) {
if (resultCode == Activity.RESULT_CANCELED) {
//Deletes image file
storage.deleteFile(photoFileCreated.getAbsolutePath());
@ -525,7 +540,8 @@ public class UploadActivity extends BaseActivity {
}
fileIcon = "jpg_image.gif";
} else {
}
else {
fileIcon = "archive.gif";
textWatcher.setFileExtension(".zip");
@ -538,7 +554,8 @@ public class UploadActivity extends BaseActivity {
addFileViewToList(FileUtils.getFilenameWithoutExtension(FileUtils.
filenameFromUri(this, newFile.getFileUri())));
filesList.add(newFile);
} else if (requestCode == AFR_REQUEST_CODE_FIELDS_BUILDER) {
}
else if (requestCode == AFR_REQUEST_CODE_FIELDS_BUILDER) {
if (resultCode == Activity.RESULT_CANCELED) {
return;
}
@ -546,7 +563,8 @@ public class UploadActivity extends BaseActivity {
String previousName = uploadFilename.getText().toString();
if (previousName.isEmpty()) {
uploadFilename.setText(data.getStringExtra(RESULT_FILENAME));
} else {
}
else {
String extractedExtension = FileUtils.getFileExtension(previousName);
String filenameWithExtension = data.getStringExtra(RESULT_FILENAME) +
(extractedExtension != null ? extractedExtension : "");
@ -556,7 +574,8 @@ public class UploadActivity extends BaseActivity {
uploadTitle.setText(data.getStringExtra(RESULT_TITLE));
uploadDescription.setText(data.getStringExtra(RESULT_DESCRIPTION));
} else {
}
else {
super.onActivityResult(requestCode, resultCode, data);
}
}
@ -579,14 +598,15 @@ public class UploadActivity extends BaseActivity {
zipTask.execute(filesListArray);
finish();
} else {
}
else {
Toast.makeText(BaseApplication.getInstance().getApplicationContext(), "Please retry uploading.", Toast.LENGTH_SHORT).show();
}
break;
}
}
private void setZipUploadFilename(){
private void setZipUploadFilename() {
String timeStamp = new SimpleDateFormat("yyyyMMdd_HHmmss", Locale.FRANCE).format(new Date());
String zipFilename = "mTHMMY_" + timeStamp + ".zip";
uploadFilename.setText(zipFilename);
@ -656,7 +676,8 @@ public class UploadActivity extends BaseActivity {
filesList.remove(fileIndex);
if (filesList.isEmpty()) {
filesListView.setVisibility(View.GONE);
} else if (filesList.size() == 1) {
}
else if (filesList.size() == 1) {
textWatcher.setFileExtension(FileUtils.getFileExtension(FileUtils.
filenameFromUri(this, filesList.get(0).getFileUri())));
}
@ -667,7 +688,7 @@ public class UploadActivity extends BaseActivity {
}
public UploadNotificationConfig getConfigForUpload(Context context, String uploadID,
String filename) {
String filename) {
UploadNotificationConfig uploadNotificationConfig = new UploadNotificationConfig();
uploadNotificationConfig.setIconForAllStatuses(android.R.drawable.stat_sys_upload);
uploadNotificationConfig.setTitleForAllStatuses("Uploading " + filename);
@ -764,7 +785,8 @@ public class UploadActivity extends BaseActivity {
}
@Override
public void onTextChanged(CharSequence s, int start, int before, int count) { }
public void onTextChanged(CharSequence s, int start, int before, int count) {
}
@Override
public void afterTextChanged(Editable s) {
@ -773,7 +795,8 @@ public class UploadActivity extends BaseActivity {
if (filenameWithoutExtension != null && !filenameWithoutExtension.isEmpty() &&
!filenameWithoutExtension.matches("[0-9a-zA-Z~!@#$%^&()_+=\\-`\\[\\]{};',.]+")) {
uploadFilenameInfo.setImageResource(R.drawable.ic_info_outline_warning_24dp);
} else {
}
else {
uploadFilenameInfo.setImageResource(R.drawable.ic_info_outline_white_24dp);
}
@ -811,7 +834,8 @@ public class UploadActivity extends BaseActivity {
if (!oldFilename.isEmpty()) {
newFilename = FileUtils.getFilenameWithoutExtension(oldFilename) + extension;
} else {
}
else {
newFilename = extension;
}
@ -888,9 +912,10 @@ public class UploadActivity extends BaseActivity {
}
@Override
public void onNothingSelected(AdapterView<?> parent) { }
public void onNothingSelected(AdapterView<?> parent) {
}
private void setCourseAndSemester(){
private void setCourseAndSemester() {
uploadsCourse = null;
semester = "";
if (categorySelected.equals("-1")) return;
@ -910,12 +935,14 @@ public class UploadActivity extends BaseActivity {
categoriesSpinners.getChildAt(numberOfSpinners - 2)).getSelectedItem();
}
else return;
} else if (numberOfSpinners == 4) {
}
else if (numberOfSpinners == 4) {
maybeSemester = (String) ((AppCompatSpinnerWithoutDefault)
categoriesSpinners.getChildAt(numberOfSpinners - 3)).getSelectedItem();
maybeCourse = (String) ((AppCompatSpinnerWithoutDefault)
categoriesSpinners.getChildAt(numberOfSpinners - 1)).getSelectedItem();
} else {
}
else {
maybeSemester = (String) ((AppCompatSpinnerWithoutDefault)
categoriesSpinners.getChildAt(numberOfSpinners - 2)).getSelectedItem();
maybeCourse = (String) ((AppCompatSpinnerWithoutDefault)
@ -926,14 +953,14 @@ public class UploadActivity extends BaseActivity {
if (maybeCourse == null) return;
String retrievedCourse = maybeCourse.replaceAll("-", "")
.replaceAll("\\((πρώην|πρωην).*\\)","")
.replace("(ΝΠΣ)", "")
.trim();
.replaceAll("\\((πρώην|πρωην).*\\)", "")
.replace("(ΝΠΣ)", "")
.trim();
if(!retrievedCourse.isEmpty()){
if (!retrievedCourse.isEmpty()) {
UploadsCourse foundUploadsCourse = UploadsCourse.findCourse(retrievedCourse, uploadsCourses);
if(foundUploadsCourse != null){
if (foundUploadsCourse != null) {
uploadsCourse = foundUploadsCourse;
semester = maybeSemester.replaceAll("-", "").trim().substring(0, 1);
Timber.d("Selected course: %s, semester: %s", uploadsCourse.getName(), semester);
@ -974,25 +1001,29 @@ public class UploadActivity extends BaseActivity {
if (categoryText.startsWith("- ")) {
//This is a level one subcategory
uploadRootCategories.get(uploadRootCategories.size() - 1).addSubCategory(categoryValue, categoryText);
} else if (categoryText.startsWith("-- ")) {
}
else if (categoryText.startsWith("-- ")) {
//This is a level two subcategory
UploadCategory rootLevelCategory = uploadRootCategories.get(uploadRootCategories.size() - 1);
UploadCategory firstLevelCategory = rootLevelCategory.getSubCategories().get(rootLevelCategory.getSubCategories().size() - 1);
firstLevelCategory.addSubCategory(categoryValue, categoryText);
} else if (categoryText.startsWith("--- ")) {
}
else if (categoryText.startsWith("--- ")) {
//This is a level three subcategory
UploadCategory rootLevelCategory = uploadRootCategories.get(uploadRootCategories.size() - 1);
UploadCategory firstLevelCategory = rootLevelCategory.getSubCategories().get(rootLevelCategory.getSubCategories().size() - 1);
UploadCategory secondLevelCategory = firstLevelCategory.getSubCategories().get(firstLevelCategory.getSubCategories().size() - 1);
secondLevelCategory.addSubCategory(categoryValue, categoryText);
} else if (categoryText.startsWith("---- ")) {
}
else if (categoryText.startsWith("---- ")) {
//This is a level four subcategory
UploadCategory rootLevelCategory = uploadRootCategories.get(uploadRootCategories.size() - 1);
UploadCategory firstLevelCategory = rootLevelCategory.getSubCategories().get(rootLevelCategory.getSubCategories().size() - 1);
UploadCategory secondLevelCategory = firstLevelCategory.getSubCategories().get(firstLevelCategory.getSubCategories().size() - 1);
UploadCategory thirdLevelCategory = secondLevelCategory.getSubCategories().get(secondLevelCategory.getSubCategories().size() - 1);
thirdLevelCategory.addSubCategory(categoryValue, categoryText);
} else {
}
else {
//This is a root category
uploadRootCategories.add(new UploadCategory(categoryValue, categoryText));
}

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

@ -49,7 +49,8 @@ public class UploadFieldsBuilderActivity extends BaseActivity {
int inputYear = Integer.parseInt(working);
isValidYear = inputYear <= currentYear && inputYear > 1980;
} else
}
else
isValidYear = false;
if (!isValidYear)
@ -59,10 +60,12 @@ public class UploadFieldsBuilderActivity extends BaseActivity {
}
@Override
public void afterTextChanged(Editable s) { }
public void afterTextChanged(Editable s) {
}
@Override
public void beforeTextChanged(CharSequence s, int start, int count, int after) { }
public void beforeTextChanged(CharSequence s, int start, int count, int after) {
}
};
@Override
@ -111,7 +114,8 @@ public class UploadFieldsBuilderActivity extends BaseActivity {
typeRadio.setOnCheckedChangeListener((group, checkedId) -> {
if (checkedId == R.id.upload_fields_builder_radio_button_notes) {
semesterChooserLinear.setVisibility(View.GONE);
} else {
}
else {
semesterChooserLinear.setVisibility(View.VISIBLE);
}
});
@ -122,10 +126,12 @@ public class UploadFieldsBuilderActivity extends BaseActivity {
if (typeId == -1) {
Toast.makeText(BaseApplication.getInstance().getApplicationContext(), "Please choose a type for the upload", Toast.LENGTH_SHORT).show();
return;
} else if (semesterChooserLinear.getVisibility() == View.VISIBLE && semesterId == -1) {
}
else if (semesterChooserLinear.getVisibility() == View.VISIBLE && semesterId == -1) {
Toast.makeText(BaseApplication.getInstance().getApplicationContext(), "Please choose a semester for the upload", Toast.LENGTH_SHORT).show();
return;
} else if (year.getText().toString().isEmpty() || !isValidYear) {
}
else if (year.getText().toString().isEmpty() || !isValidYear) {
Toast.makeText(BaseApplication.getInstance().getApplicationContext(), "Please choose a valid year for the upload", Toast.LENGTH_SHORT).show();
return;
}

14
app/src/main/java/gr/thmmy/mthmmy/activities/upload/UploadsCourse.java

@ -33,31 +33,31 @@ class UploadsCourse {
return greeklishName;
}
static Map<String, UploadsCourse> generateUploadsCourses(String[] uploadsCoursesRes){
static Map<String, UploadsCourse> generateUploadsCourses(String[] uploadsCoursesRes) {
Map<String, UploadsCourse> uploadsCourses = new HashMap<>();
for(String uploadsCourseStr:uploadsCoursesRes) {
for (String uploadsCourseStr : uploadsCoursesRes) {
String[] split = uploadsCourseStr.split(":");
UploadsCourse uploadsCourse = new UploadsCourse(split[0], split[1], split[2]);
uploadsCourses.put(uploadsCourse.getName(),uploadsCourse);
uploadsCourses.put(uploadsCourse.getName(), uploadsCourse);
}
return uploadsCourses;
}
static UploadsCourse findCourse(String retrievedCourse,
Map<String, UploadsCourse> uploadsCourses){
Map<String, UploadsCourse> uploadsCourses) {
retrievedCourse = normalizeGreekNumbers(retrievedCourse);
UploadsCourse uploadsCourse = uploadsCourses.get(retrievedCourse);
if(uploadsCourse != null) return uploadsCourse;
if (uploadsCourse != null) return uploadsCourse;
String foundKey = null;
for (Map.Entry<String, UploadsCourse> entry : uploadsCourses.entrySet()) {
String key = entry.getKey();
if ((key.contains(retrievedCourse) || retrievedCourse.contains(key))
&& (foundKey==null || key.length()>foundKey.length()))
&& (foundKey == null || key.length() > foundKey.length()))
foundKey = key;
}
if(foundKey==null){
if (foundKey == null) {
Timber.w("Couldn't find course that matches %s", retrievedCourse);
Bundle bundle = new Bundle();
bundle.putString("course_name", retrievedCourse);

4
app/src/main/java/gr/thmmy/mthmmy/activities/upload/UploadsHelper.java

@ -87,8 +87,8 @@ public class UploadsHelper {
File.separator + "mTHMMY");
if (!zipFolder.exists() && !zipFolder.mkdirs()) {
Timber.w("Zip folder build returned false in %s", UploadsHelper.class.getSimpleName());
return null;
Timber.w("Zip folder build returned false in %s", UploadsHelper.class.getSimpleName());
return null;
}
return new File(zipFolder, zipFilename);

10
app/src/main/java/gr/thmmy/mthmmy/activities/upload/multipart/MultipartUploadRequest.java

@ -12,8 +12,8 @@ import java.io.FileNotFoundException;
import java.net.MalformedURLException;
/**
From MultipartUploadRequest gotev/android-upload-service in order to use the local custom
MultipartUploadTask.
* From MultipartUploadRequest gotev/android-upload-service in order to use the local custom
* MultipartUploadTask.
*/
public class MultipartUploadRequest extends HttpUploadRequest<MultipartUploadRequest> {
@ -61,7 +61,8 @@ public class MultipartUploadRequest extends HttpUploadRequest<MultipartUploadReq
contentType = file.getContentType(context);
Logger.debug(LOG_TAG, "Auto-detected MIME type for " + filePath
+ " is: " + contentType);
} else {
}
else {
Logger.debug(LOG_TAG, "Content Type set for " + filePath
+ " is: " + contentType);
}
@ -71,7 +72,8 @@ public class MultipartUploadRequest extends HttpUploadRequest<MultipartUploadReq
if (fileName == null || "".equals(fileName)) {
fileName = file.getName(context);
Logger.debug(LOG_TAG, "Using original file name: " + fileName);
} else {
}
else {
Logger.debug(LOG_TAG, "Using custom file name: " + fileName);
}

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

@ -13,8 +13,8 @@ import java.io.UnsupportedEncodingException;
import java.nio.charset.Charset;
/**
Extended MultipartUploadTask from gotev/android-upload-service to include a fix for the parameter
tp_dluploadpic. Also changed Connection to keep-alive.
* Extended MultipartUploadTask from gotev/android-upload-service to include a fix for the parameter
* tp_dluploadpic. Also changed Connection to keep-alive.
*/
public class MultipartUploadTask extends HttpUploadTask {
@ -90,7 +90,7 @@ public class MultipartUploadTask extends HttpUploadTask {
}
private byte[] getMultipartBytes(NameValue parameter) throws UnsupportedEncodingException {
if(parameter.getName().equals("tp_dluploadpic")){
if (parameter.getName().equals("tp_dluploadpic")) {
String header = "Content-Disposition: form-data; name=\"" +
parameter.getName() + "\"; filename=\"\"" + NEW_LINE +
"Content-Type: application/octet-stream" + NEW_LINE + NEW_LINE;
@ -98,7 +98,7 @@ public class MultipartUploadTask extends HttpUploadTask {
}
else
return ("Content-Disposition: form-data; name=\"" + parameter.getName() + "\""
+ NEW_LINE + NEW_LINE + parameter.getValue() + NEW_LINE).getBytes(charset);
+ NEW_LINE + NEW_LINE + parameter.getValue() + NEW_LINE).getBytes(charset);
}
private byte[] getMultipartHeader(UploadFile file)

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

@ -319,7 +319,8 @@ public abstract class BaseActivity extends AppCompatActivity {
.withName(R.string.logout)
.withIcon(logoutIcon)
.withSelectable(false);
} else
}
else
loginLogoutItem = new PrimaryDrawerItem()
.withTextColor(primaryColor)
.withSelectedColor(selectedSecondaryColor)
@ -379,7 +380,8 @@ public abstract class BaseActivity extends AppCompatActivity {
intent.setFlags(FLAG_ACTIVITY_NEW_TASK);
startActivity(intent);
return false;
} else
}
else
startLoginActivity();
return true;
@ -399,12 +401,14 @@ public abstract class BaseActivity extends AppCompatActivity {
Intent intent = new Intent(BaseActivity.this, MainActivity.class);
startActivity(intent);
}
} else if (drawerItem.equals(SHOUTBOX_ID)) {
}
else if (drawerItem.equals(SHOUTBOX_ID)) {
if (!(BaseActivity.this instanceof ShoutboxActivity)) {
Intent intent = new Intent(BaseActivity.this, ShoutboxActivity.class);
startActivity(intent);
}
} else if (drawerItem.equals(DOWNLOADS_ID)) {
}
else if (drawerItem.equals(DOWNLOADS_ID)) {
if (!(BaseActivity.this instanceof DownloadsActivity)) {
Intent intent = new Intent(BaseActivity.this, DownloadsActivity.class);
Bundle extras = new Bundle();
@ -413,29 +417,34 @@ public abstract class BaseActivity extends AppCompatActivity {
intent.putExtras(extras);
startActivity(intent);
}
} else if (drawerItem.equals(UPLOAD_ID)) {
}
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)) {
}
else if (drawerItem.equals(BOOKMARKS_ID)) {
if (!(BaseActivity.this instanceof BookmarksActivity)) {
Intent intent = new Intent(BaseActivity.this, BookmarksActivity.class);
intent.addFlags(Intent.FLAG_ACTIVITY_REORDER_TO_FRONT);
startActivity(intent);
}
} else if (drawerItem.equals(LOG_ID)) {
}
else if (drawerItem.equals(LOG_ID)) {
if (!sessionManager.isLoggedIn()) //When logged out or if user is guest
startLoginActivity();
else
showLogoutDialog();
} else if (drawerItem.equals(ABOUT_ID)) {
}
else if (drawerItem.equals(ABOUT_ID)) {
if (!(BaseActivity.this instanceof AboutActivity)) {
Intent intent = new Intent(BaseActivity.this, AboutActivity.class);
intent.addFlags(Intent.FLAG_ACTIVITY_REORDER_TO_FRONT);
startActivity(intent);
}
} else if (drawerItem.equals(SETTINGS_ID)) {
}
else if (drawerItem.equals(SETTINGS_ID)) {
if (!(BaseActivity.this instanceof SettingsActivity)) {
Intent intent = new Intent(BaseActivity.this, SettingsActivity.class);
intent.addFlags(Intent.FLAG_ACTIVITY_REORDER_TO_FRONT);
@ -465,13 +474,14 @@ public abstract class BaseActivity extends AppCompatActivity {
private void updateDrawer() {
if (drawer != null) {
if (!sessionManager.isLoggedIn()){ //When logged out or if user is guest
if (!sessionManager.isLoggedIn()) { //When logged out or if user is guest
drawer.removeItem(DOWNLOADS_ID);
drawer.removeItem(UPLOAD_ID);
loginLogoutItem.withName(R.string.login).withIcon(loginIcon); //Swap logout with login
profileDrawerItem.withName(sessionManager.getUsername());
setDefaultAvatar();
} else {
}
else {
if (!drawer.getDrawerItems().contains(downloadsItem)) {
drawer.addItemAtPosition(downloadsItem, 4);
}
@ -494,8 +504,9 @@ public abstract class BaseActivity extends AppCompatActivity {
profileDrawerItem.withIcon(R.drawable.ic_default_user_avatar);
}
//-------------------------------------------LOGOUT-------------------------------------------------
//-------------------------------------------LOGOUT-------------------------------------------------
private ProgressDialog progressDialog;
private void onLogoutTaskStarted() {
progressDialog = new ProgressDialog(BaseActivity.this,
R.style.AppTheme_Dark_Dialog);
@ -505,7 +516,7 @@ public abstract class BaseActivity extends AppCompatActivity {
progressDialog.show();
}
private void onLogoutTaskFinished(int resultCode, Void v) {
private void onLogoutTaskFinished(int resultCode, Void v) {
if (resultCode == NetworkResultCodes.SUCCESSFUL) {
SharedPreferences sharedPrefs = PreferenceManager.getDefaultSharedPreferences(getApplicationContext());
if (sharedPrefs.getString(DEFAULT_HOME_TAB, "0").equals("2")) {
@ -533,7 +544,8 @@ public abstract class BaseActivity extends AppCompatActivity {
builder.setPositiveButton("Yep", (dialogInterface, i) -> {
new LogoutTask(this::onLogoutTaskStarted, this::onLogoutTaskFinished).executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR); //Avoid delays between onPreExecute() and doInBackground()
});
builder.setNegativeButton("Nope", (dialogInterface, i) -> {});
builder.setNegativeButton("Nope", (dialogInterface, i) -> {
});
builder.create().show();
}
//-----------------------------------------LOGOUT END-----------------------------------------------
@ -571,7 +583,8 @@ public abstract class BaseActivity extends AppCompatActivity {
thisPageBookmarkMenuButton.setIcon(R.drawable.ic_bookmark_false_accent_24dp);
toggleTopicToBookmarks(thisPageBookmark);
Toast.makeText(BaseApplication.getInstance().getApplicationContext(), "Bookmark removed", Toast.LENGTH_SHORT).show();
} else {
}
else {
thisPageBookmarkMenuButton.setIcon(R.drawable.ic_bookmark_true_accent_24dp);
toggleTopicToBookmarks(thisPageBookmark);
Toast.makeText(BaseApplication.getInstance().getApplicationContext(), "Bookmark added", Toast.LENGTH_SHORT).show();
@ -581,14 +594,16 @@ public abstract class BaseActivity extends AppCompatActivity {
protected void setBoardBookmark(final ImageButton thisPageBookmarkImageButton) {
if (thisPageBookmark.matchExists(boardsBookmarked)) {
thisPageBookmarkImageButton.setImageResource(R.drawable.ic_bookmark_true_accent_24dp);
} else {
}
else {
thisPageBookmarkImageButton.setImageResource(R.drawable.ic_bookmark_false_accent_24dp);
}
thisPageBookmarkImageButton.setOnClickListener(view -> {
if (thisPageBookmark.matchExists(boardsBookmarked)) {
thisPageBookmarkImageButton.setImageResource(R.drawable.ic_bookmark_false_accent_24dp);
Toast.makeText(BaseApplication.getInstance().getApplicationContext(), "Bookmark removed", Toast.LENGTH_SHORT).show();
} else {
}
else {
thisPageBookmarkImageButton.setImageResource(R.drawable.ic_bookmark_true_accent_24dp);
Toast.makeText(BaseApplication.getInstance().getApplicationContext(), "Bookmark added", Toast.LENGTH_SHORT).show();
}
@ -602,7 +617,8 @@ public abstract class BaseActivity extends AppCompatActivity {
loadSavedBookmarks();
if (thisPageBookmark.matchExists(boardsBookmarked)) {
thisPageBookmarkImageButton.setImageResource(R.drawable.ic_bookmark_true_accent_24dp);
} else {
}
else {
thisPageBookmarkImageButton.setImageResource(R.drawable.ic_bookmark_false_accent_24dp);
}
}
@ -627,7 +643,8 @@ public abstract class BaseActivity extends AppCompatActivity {
if (bookmark.matchExists(boardsBookmarked)) {
boardsBookmarked.remove(bookmark.findIndex(boardsBookmarked));
FirebaseMessaging.getInstance().unsubscribeFromTopic("b" + bookmark.getId());
} else {
}
else {
boardsBookmarked.add(new Bookmark(bookmark.getTitle(), bookmark.getId(), true));
FirebaseMessaging.getInstance().subscribeToTopic("b" + bookmark.getId());
}
@ -639,7 +656,8 @@ public abstract class BaseActivity extends AppCompatActivity {
if (bookmark.matchExists(topicsBookmarked)) {
topicsBookmarked.remove(bookmark.findIndex(topicsBookmarked));
FirebaseMessaging.getInstance().unsubscribeFromTopic(bookmark.getId());
} else {
}
else {
topicsBookmarked.add(new Bookmark(bookmark.getTitle(), bookmark.getId(), true));
FirebaseMessaging.getInstance().subscribeToTopic(bookmark.getId());
}
@ -676,7 +694,8 @@ public abstract class BaseActivity extends AppCompatActivity {
FirebaseMessaging.getInstance().unsubscribeFromTopic(bookmark.getId());
return topicsBookmarked.get(bookmark.findIndex(topicsBookmarked)).isNotificationsEnabled();
} else if (bookmark.matchExists(boardsBookmarked)) {
}
else if (bookmark.matchExists(boardsBookmarked)) {
boardsBookmarked.get(bookmark.findIndex(boardsBookmarked)).toggleNotificationsEnabled();
updateBoardBookmarks();
@ -686,7 +705,8 @@ public abstract class BaseActivity extends AppCompatActivity {
FirebaseMessaging.getInstance().unsubscribeFromTopic("b" + bookmark.getId());
return boardsBookmarked.get(bookmark.findIndex(boardsBookmarked)).isNotificationsEnabled();
} else
}
else
Timber.w("No bookmark match exists!");
return false;
}
@ -855,8 +875,8 @@ public abstract class BaseActivity extends AppCompatActivity {
privacyPolicyTextView.setTextColor(ContextCompat.getColor(this, R.color.primary_text));
SpannableConfiguration configuration = SpannableConfiguration.builder(this).linkResolver(new LinkResolverDef()).build();
String privacyPolicy = AssetUtils.readFileToText(BaseActivity.this,"PRIVACY.md");
if(privacyPolicy!=null){
String privacyPolicy = AssetUtils.readFileToText(BaseActivity.this, "PRIVACY.md");
if (privacyPolicy != null) {
Markwon.setMarkdown(privacyPolicyTextView, configuration, privacyPolicy);
AlertDialog.Builder builder = new AlertDialog.Builder(this, R.style.AppCompatAlertDialogStyle);
builder.setView(privacyPolicyTextView);
@ -943,7 +963,8 @@ public abstract class BaseActivity extends AppCompatActivity {
dialogProgressText.setText(getString(R.string.upload_failed));
uploadsProgressDialog.show();
} else {
}
else {
//Empty buttons are needed, they are updated with correct values in the receiver
uploadsProgressDialog.setButton(AlertDialog.BUTTON_NEUTRAL, "placeholder", (progressDialog, progressWhich) -> {
});
@ -954,7 +975,8 @@ public abstract class BaseActivity extends AppCompatActivity {
//UploadsReceiver.setDialogDisplay(uploadsProgressDialog, dialogUploadID, retryIntent);
uploadsProgressDialog.show();
}
} else {
}
else {
UploadsReceiver.setDialogDisplay(uploadsProgressDialog, dialogUploadID, null);
//UploadsReceiver.setDialogDisplay(uploadsProgressDialog, dialogUploadID, retryIntent);
uploadsProgressDialog.show();

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

@ -46,6 +46,7 @@ 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;
// TODO: Replace MultiDexApplication with Application after KitKat support is dropped
@ -63,6 +64,7 @@ public class BaseApplication extends MultiDexApplication {
private SessionManager sessionManager;
private boolean displayRelativeTime;
private boolean displayCompactTabs;
//Display Metrics
private static float widthDp;
@ -105,10 +107,11 @@ public class BaseApplication extends MultiDexApplication {
setDisplayMetrics();
displayRelativeTime = settingsSharedPrefs.getBoolean(DISPLAY_RELATIVE_TIME, true);
displayCompactTabs = settingsSharedPrefs.getBoolean(DISPLAY_COMPACT_TABS, true);
}
private void initFirebase(SharedPreferences settingsSharedPrefs){
if (settingsSharedPrefs.getBoolean(getString(R.string.pref_privacy_crashlytics_enable_key), false)){
private void initFirebase(SharedPreferences settingsSharedPrefs) {
if (settingsSharedPrefs.getBoolean(getString(R.string.pref_privacy_crashlytics_enable_key), false)) {
Timber.i("Starting app with Firebase Crashlytics enabled.");
setFirebaseCrashlyticsEnabled(true);
}
@ -127,7 +130,7 @@ public class BaseApplication extends MultiDexApplication {
Timber.i("Starting app with Firebase Analytics disabled.");
}
private void initOkHttp(PersistentCookieJar cookieJar){
private void initOkHttp(PersistentCookieJar cookieJar) {
OkHttpClient.Builder builder = new OkHttpClient.Builder()
.cookieJar(cookieJar)
.addInterceptor(chain -> {
@ -165,7 +168,7 @@ public class BaseApplication extends MultiDexApplication {
client = builder.build();
}
private void initDrawerImageLoader(){
private void initDrawerImageLoader() {
DrawerImageLoader.init(new AbstractDrawerImageLoader() {
@Override
public void set(ImageView imageView, Uri uri, Drawable placeholder, String tag) {
@ -179,7 +182,7 @@ public class BaseApplication extends MultiDexApplication {
@Override
public Drawable placeholder(Context ctx, String tag) {
if (DrawerImageLoader.Tags.PROFILE.name().equals(tag)){
if (DrawerImageLoader.Tags.PROFILE.name().equals(tag)) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP)
return ContextCompat.getDrawable(BaseApplication.getInstance(), R.drawable.ic_default_user_avatar);
else { // Just for KitKats
@ -194,7 +197,7 @@ public class BaseApplication extends MultiDexApplication {
});
}
private void setDisplayMetrics(){
private void setDisplayMetrics() {
DisplayMetrics displayMetrics = getApplicationContext().getResources().getDisplayMetrics();
widthPxl = displayMetrics.widthPixels;
@ -233,6 +236,10 @@ public class BaseApplication extends MultiDexApplication {
return displayRelativeTime;
}
public boolean isDisplayCompactTabsEnabled() {
return displayCompactTabs;
}
//-------------------- Firebase --------------------
public void logFirebaseAnalyticsEvent(String event, Bundle params) {
@ -244,7 +251,7 @@ public class BaseApplication extends MultiDexApplication {
if (!enabled)
firebaseAnalytics.resetAnalyticsData();
if(enabled)
if (enabled)
Timber.i("Firebase Analytics enabled.");
else
Timber.i("Firebase Analytics disabled.");
@ -252,14 +259,14 @@ public class BaseApplication extends MultiDexApplication {
public void setFirebaseCrashlyticsEnabled(boolean enable) {
FirebaseCrashlytics.getInstance().setCrashlyticsCollectionEnabled(enable);
if(enable){
if (enable) {
crashReportingTree = new CrashReportingTree();
Timber.plant(crashReportingTree);
Timber.i("CrashReporting tree planted.");
Timber.i("Firebase Crashlytics enabled.");
}
else{
if(crashReportingTree!=null) {
else {
if (crashReportingTree != null) {
Timber.uproot(crashReportingTree);
Timber.i("CrashReporting tree uprooted.");
}
@ -267,7 +274,7 @@ public class BaseApplication extends MultiDexApplication {
}
}
public static String getFirebaseProjectId(){
public static String getFirebaseProjectId() {
return firebaseProjectId;
}
}

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

@ -46,5 +46,6 @@ public abstract class BaseFragment extends Fragment {
* the activity that contains it, to allow communication upon interaction,
* between the fragment and the activity/ other fragments
*/
public interface FragmentInteractionListener {}
public interface FragmentInteractionListener {
}
}

2
app/src/main/java/gr/thmmy/mthmmy/model/Bookmark.java

@ -28,7 +28,7 @@ public class Bookmark implements java.io.Serializable {
return isNotificationsEnabled;
}
public void toggleNotificationsEnabled(){
public void toggleNotificationsEnabled() {
this.isNotificationsEnabled = !this.isNotificationsEnabled;
}

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

@ -57,11 +57,11 @@ public class Download {
return hasSubCategory;
}
public String getFileName(){
public String getFileName() {
return fileName;
}
public void setFileName(String fileName){
public void setFileName(String fileName) {
this.fileName = fileName;
}
}

3
app/src/main/java/gr/thmmy/mthmmy/model/Poll.java

@ -91,8 +91,7 @@ public class Poll extends TopicItem {
/**
* Constructor for entry with unknown number of votes
*
* @param entryName
* The name of the entry
* @param entryName The name of the entry
*/
public Entry(String entryName) {
this.entryName = entryName;

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

@ -81,7 +81,8 @@ public class Post extends TopicItem {
* Constructor for active user's posts. All variables are declared final, once assigned they
* can not change. Parameters notated as {@link Nullable} can either pass null or empty
* (strings/ArrayList).
* @param thumbnailUrl author's thumbnail url
*
* @param thumbnailUrl author's thumbnail url
* @param author author's username
* @param subject post's subject
* @param content post itself
@ -139,7 +140,8 @@ public class Post extends TopicItem {
* Constructor for deleted user's posts. All variables are declared final, once assigned they
* can not change. Parameters notated as {@link Nullable} can either pass null or empty
* (strings/ArrayList).
* @param thumbnailUrl author's thumbnail url
*
* @param thumbnailUrl author's thumbnail url
* @param author author's username
* @param subject post's subject
* @param content post itself

12
app/src/main/java/gr/thmmy/mthmmy/model/PostNotification.java

@ -30,12 +30,12 @@ public class PostNotification {
* Constructor specifying all class variables necessary to summarize this post. All variables
* are declared final, once assigned they cannot change.
*
* @param postId this post's id
* @param topicId this post's topicId
* @param topicTitle this post's topicTitle
* @param poster username of this post's author
* @param boardId one of this post's boardIds (-1 if it is a topic notification)
* @param boardTitle one of this post's boardTitles (null if it is a topic notification)
* @param postId this post's id
* @param topicId this post's topicId
* @param topicTitle this post's topicTitle
* @param poster username of this post's author
* @param boardId one of this post's boardIds (-1 if it is a topic notification)
* @param boardTitle one of this post's boardTitles (null if it is a topic notification)
*/
public PostNotification(int postId, int topicId, String topicTitle, String poster, int boardId, String boardTitle) {
this.postId = postId;

2
app/src/main/java/gr/thmmy/mthmmy/model/ThmmyFile.java

@ -21,7 +21,7 @@ public class ThmmyFile {
*/
public ThmmyFile(URL fileUrl, String fileName, String fileInfo) {
this.fileUrl = fileUrl;
if(fileName!=null)
if (fileName != null)
this.fileName = fileName;
else
this.fileName = URLUtil.guessFileName(fileUrl.toString(), null, null);

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

@ -153,7 +153,8 @@ public class ThmmyPage {
else if (uriString.contains(";sa=statPanel"))
return PageCategory.PROFILE_STATS;
else return PageCategory.PROFILE_SUMMARY;
} else if (uriString.contains("action=unread"))
}
else if (uriString.contains("action=unread"))
return PageCategory.UNREAD_POSTS;
else if (uriString.contains("action=tpmod;dl=item"))
return PageCategory.DOWNLOADS_FILE;
@ -185,17 +186,19 @@ public class ThmmyPage {
Matcher topicIdMatcher = Pattern.compile("topic=[0-9]+").matcher(topicUrl);
if (topicIdMatcher.find()) {
return topicUrl.substring(topicIdMatcher.start() + 6, topicIdMatcher.end());
} else return null;
}
else return null;
}
return null;
}
/**
* This method gets a VALID topic url and strips it off any unnecessary stuff (e.g. wap2).
*
* @param topicUrl a valid topic url
* @return sanitized topic url
*/
public static String sanitizeTopicUrl(String topicUrl) {
return topicUrl.replace("action=printpage;","").replace("wap2","");
public static String sanitizeTopicUrl(String topicUrl) {
return topicUrl.replace("action=printpage;", "").replace("wap2", "");
}
}

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

@ -24,7 +24,7 @@ import static gr.thmmy.mthmmy.utils.FileUtils.getMimeType;
public class DownloadHelper {
public static final File SAVE_DIR = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS);
public static void enqueueDownload(ThmmyFile thmmyFile){
public static void enqueueDownload(ThmmyFile thmmyFile) {
Context applicationContext = BaseApplication.getInstance().getApplicationContext();
Toast.makeText(applicationContext, "Download started!", Toast.LENGTH_SHORT).show();
@ -32,11 +32,11 @@ public class DownloadHelper {
String fileName = renameFileIfExists(thmmyFile.getFilename());
Uri downloadURI = Uri.parse(thmmyFile.getFileUrl().toString());
DownloadManager downloadManager = (DownloadManager)applicationContext.getSystemService(Context.DOWNLOAD_SERVICE);
DownloadManager downloadManager = (DownloadManager) applicationContext.getSystemService(Context.DOWNLOAD_SERVICE);
DownloadManager.Request request = new DownloadManager.Request(downloadURI);
Cookie thmmyCookie = BaseApplication.getInstance().getSessionManager().getThmmyCookie();
if(thmmyCookie!=null)
if (thmmyCookie != null)
request.addRequestHeader("Cookie", thmmyCookie.name() + "=" + thmmyCookie.value());
request.setTitle(fileName);
request.setMimeType(getMimeType(fileName));
@ -63,7 +63,8 @@ public class DownloadHelper {
if (tokens.length != 2) {
Timber.w("Couldn't get file extension...");
nameFormat = originalFileName + "(%d)";
} else
}
else
nameFormat = tokens[0] + "-%d." + tokens[1];
for (int i = 1; ; i++) {

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

@ -63,12 +63,12 @@ public class NotificationService extends FirebaseMessagingService {
int boardId = -1;
String boardTitle = null;
int topicId = Integer.parseInt(json.getString("topicId"));
if(remoteMessage.getFrom().contains("b")){
if (remoteMessage.getFrom().contains("b")) {
Timber.i("FCM BOARD type message detected.");
SharedPreferences bookmarksFile = getSharedPreferences(BOOKMARKS_SHARED_PREFS, Context.MODE_PRIVATE);
String bookmarkedTopicsString = bookmarksFile.getString(BOOKMARKED_TOPICS_KEY, null);
if (bookmarkedTopicsString != null && matchExistsById(Bookmark.stringToArrayList(bookmarkedTopicsString), topicId)){
if (bookmarkedTopicsString != null && matchExistsById(Bookmark.stringToArrayList(bookmarkedTopicsString), topicId)) {
Timber.i("Board notification suppressed (already subscribed to topic).");
return;
}
@ -76,12 +76,12 @@ public class NotificationService extends FirebaseMessagingService {
boardId = Integer.parseInt(json.getString("boardId"));
String bookmarkedBoardsString = bookmarksFile.getString(BOOKMARKED_BOARDS_KEY, null);
if (bookmarkedBoardsString != null){
if (bookmarkedBoardsString != null) {
ArrayList<Bookmark> boardBookmarks = Bookmark.stringToArrayList(bookmarkedBoardsString);
ArrayList<Integer> subBoardIds = getSubBoardIds(json.getString("boardIds"), boardId);
//TODO: Also suppress if user has chosen to be notified only for direct children of boardId && !subBoardIds.isEmpty()
for(int subId:subBoardIds){
if(matchExistsById(boardBookmarks, subId)){
for (int subId : subBoardIds) {
if (matchExistsById(boardBookmarks, subId)) {
Timber.i("Board notification suppressed (already subscribed to a subBoard).");
return;
}
@ -98,7 +98,8 @@ public class NotificationService extends FirebaseMessagingService {
String poster = json.getString("poster");
sendNotification(new PostNotification(postId, topicId, topicTitle, poster, boardId, boardTitle));
} else
}
else
Timber.i("Notification suppressed (own userID).");
} catch (JSONException e) {
Timber.e(e, "JSON Exception");
@ -106,17 +107,17 @@ public class NotificationService extends FirebaseMessagingService {
}
}
private static ArrayList<Integer> getSubBoardIds(String boardIdsString, int boardId){
private static ArrayList<Integer> getSubBoardIds(String boardIdsString, int boardId) {
ArrayList<Integer> subBoardIds = new ArrayList<>();
Pattern p = Pattern.compile("(\\d+)");
Matcher m = p.matcher(boardIdsString);
boolean boardIdfound=false;
while (m.find()){
boolean boardIdfound = false;
while (m.find()) {
int subBoardId = Integer.parseInt(m.group());
if(boardIdfound)
if (boardIdfound)
subBoardIds.add(subBoardId);
else if(boardId==subBoardId)
boardIdfound=true;
else if (boardId == subBoardId)
boardIdfound = true;
}
return subBoardIds;
}
@ -154,7 +155,8 @@ public class NotificationService extends FirebaseMessagingService {
if (notificationsVibrateEnabled) {
if (notificationDefaultValues != -1) {
notificationDefaultValues |= Notification.DEFAULT_VIBRATE;
} else {
}
else {
notificationDefaultValues = Notification.DEFAULT_VIBRATE;
}
@ -162,7 +164,8 @@ public class NotificationService extends FirebaseMessagingService {
if (notificationSoundUri == null) {
if (notificationDefaultValues != -1) {
notificationDefaultValues = Notification.DEFAULT_SOUND;
} else {
}
else {
notificationDefaultValues |= Notification.DEFAULT_SOUND;
}
}
@ -180,15 +183,15 @@ public class NotificationService extends FirebaseMessagingService {
int notificationId;
String contentText;
if(isTopicNotification){
if (isTopicNotification) {
notificationId = postNotification.getTopicId();
contentText = "New post by " + postNotification.getPoster();
}
else{
else {
// Using Cantor pairing function (plus the minus sign) for id uniqueness
int k1 = postNotification.getTopicId();
int k2 = postNotification.getBoardId();
notificationId = -(((k1+k2)*(k1+k2+1))/2+k2);
notificationId = -(((k1 + k2) * (k1 + k2 + 1)) / 2 + k2);
contentText = "New post in \"" + postNotification.getTopicTitle() + "\"";
}
@ -198,7 +201,7 @@ public class NotificationService extends FirebaseMessagingService {
Notification existingNotification = getActiveNotification(notificationId);
if (existingNotification != null) {
newPostsCount = existingNotification.extras.getInt(NEW_POSTS_COUNT) + 1;
if(isTopicNotification)
if (isTopicNotification)
contentText = newPostsCount + " new posts";
else
contentText = newPostsCount + " new posts in " + postNotification.getTopicTitle();
@ -217,7 +220,7 @@ public class NotificationService extends FirebaseMessagingService {
.setGroup(GROUP_KEY)
.addExtras(notificationExtras);
if(isTopicNotification)
if (isTopicNotification)
notificationBuilder.setContentTitle(postNotification.getTopicTitle());
else
@ -262,7 +265,7 @@ public class NotificationService extends FirebaseMessagingService {
// Since Android Oreo notification channel is needed.
if (buildVersion >= Build.VERSION_CODES.O && notificationManager.getNotificationChannel(CHANNEL_ID) == null)
notificationManager.createNotificationChannel(new NotificationChannel(CHANNEL_ID, CHANNEL_NAME, NotificationManager.IMPORTANCE_HIGH));
notificationManager.createNotificationChannel(new NotificationChannel(CHANNEL_ID, CHANNEL_NAME, NotificationManager.IMPORTANCE_HIGH));
notificationManager.notify(NEW_POST_TAG, notificationId, notificationBuilder.build());

17
app/src/main/java/gr/thmmy/mthmmy/services/UploadsReceiver.java

@ -87,7 +87,7 @@ public class UploadsReceiver extends UploadServiceBroadcastReceiver {
@Override
public void onProgress(Context context, UploadInfo uploadInfo) {
Timber.i("Upload in progress (id: %s)",uploadInfo.getUploadId());
Timber.i("Upload in progress (id: %s)", uploadInfo.getUploadId());
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.LOLLIPOP &&
uploadInfo.getUploadId().equals(dialogUploadID) &&
uploadProgressDialog != null) {
@ -127,7 +127,7 @@ public class UploadsReceiver extends UploadServiceBroadcastReceiver {
@Override
public void onError(Context context, UploadInfo uploadInfo, ServerResponse serverResponse,
Exception exception) {
Timber.i("Error while uploading (id: %s)",uploadInfo.getUploadId());
Timber.i("Error while uploading (id: %s)", uploadInfo.getUploadId());
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.LOLLIPOP &&
uploadInfo.getUploadId().equals(dialogUploadID) &&
uploadProgressDialog != null) {
@ -162,7 +162,8 @@ public class UploadsReceiver extends UploadServiceBroadcastReceiver {
uploadProgressDialog.dismiss();
}
}
} else {
}
else {
cancelNotification(context, uploadInfo.getNotificationID());
Intent combinedActionsIntent = new Intent(UploadsReceiver.ACTION_COMBINED_UPLOAD);
combinedActionsIntent.putExtra(UploadsReceiver.UPLOAD_ID_KEY, uploadInfo.getUploadId());
@ -183,17 +184,17 @@ public class UploadsReceiver extends UploadServiceBroadcastReceiver {
}
String response = serverResponse.getBodyAsString();
if(response.contains("Η προσθήκη του αρχείου ήταν επιτυχημένη.")||response.contains("The upload was successful.")){
Timber.i("Upload completed successfully (id: %s)",uploadInfo.getUploadId());
if (response.contains("Η προσθήκη του αρχείου ήταν επιτυχημένη.") || response.contains("The upload was successful.")) {
Timber.i("Upload completed successfully (id: %s)", uploadInfo.getUploadId());
Toast.makeText(context.getApplicationContext(), "Upload completed successfully", Toast.LENGTH_SHORT).show();
BaseApplication.getInstance().logFirebaseAnalyticsEvent("file_upload", null);
}
else {
MultipartUploadException multipartUploadException = new MultipartUploadException(response);
Timber.e(multipartUploadException);
onError(context,uploadInfo,serverResponse,multipartUploadException);
onError(context, uploadInfo, serverResponse, multipartUploadException);
}
if (storage == null) {
storage = new Storage(context.getApplicationContext());
}
@ -224,7 +225,7 @@ public class UploadsReceiver extends UploadServiceBroadcastReceiver {
//UploadsReceiver.multipartUploadRetryIntent = multipartUploadRetryIntent;
}
private void cancelNotification(Context context, int notificationId){
private void cancelNotification(Context context, int notificationId) {
NotificationManager notificationManager = (NotificationManager) context.getApplicationContext().
getSystemService(Context.NOTIFICATION_SERVICE);
if (notificationManager != null)

3
app/src/main/java/gr/thmmy/mthmmy/session/InvalidSessionException.java

@ -1,7 +1,8 @@
package gr.thmmy.mthmmy.session;
public class InvalidSessionException extends RuntimeException {
public InvalidSessionException() {}
public InvalidSessionException() {
}
public InvalidSessionException(String message) {
super(message);

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

@ -28,7 +28,7 @@ public class LogoutTask extends NetworkTask<Void> {
Keep in mind, server changes sesc at will over time for a given session!
*/
Parcel<Void> parcel = executeInBackground(indexUrl.toString());
if(parcel.getResultCode() == NetworkResultCodes.SUCCESSFUL)
if (parcel.getResultCode() == NetworkResultCodes.SUCCESSFUL)
return executeInBackground(logoutLink); // Now we will attempt to logout
else return parcel;
}
@ -36,14 +36,14 @@ public class LogoutTask extends NetworkTask<Void> {
@Override
protected Void performTask(Document document, Response response) {
try {
if(logoutLink==null)
if (logoutLink == null)
logoutLink = extractLogoutLink(document);
else { // Just for logging purposes
Elements sessionVerificationFailed = document.select("td:containsOwn(Session " +
"verification failed. Please try logging out and back in again, and then try " +
"again.), td:containsOwn(Η επαλήθευση συνόδου απέτυχε. Παρακαλούμε κάντε " +
"αποσύνδεση, επανασύνδεση και ξαναδοκιμάστε.)");
if(!sessionVerificationFailed.isEmpty()){
if (!sessionVerificationFailed.isEmpty()) {
Timber.i("Logout failed (invalid session)");
throw new InvalidSessionException();
}
@ -73,7 +73,7 @@ public class LogoutTask extends NetworkTask<Void> {
return NetworkResultCodes.SUCCESSFUL;
}
private String extractLogoutLink(Document document){
private String extractLogoutLink(Document document) {
Elements logoutLink = document.select("a[href^=" + baseLogoutLink + "]");
if (!logoutLink.isEmpty()) {

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

@ -22,7 +22,7 @@ public class MarkAsReadTask extends NetworkTask<Void> {
@Override
protected Parcel<Void> doInBackground(String... input) {
Parcel<Void> parcel = executeInBackground(unreadUrl.toString());
if(parcel.getResultCode() == NetworkResultCodes.SUCCESSFUL)
if (parcel.getResultCode() == NetworkResultCodes.SUCCESSFUL)
return executeInBackground(markAsReadLink);
else return parcel;
}
@ -34,9 +34,9 @@ public class MarkAsReadTask extends NetworkTask<Void> {
"verification failed. Please try logging out and back in again, and then try " +
"again.), td:containsOwn(Η επαλήθευση συνόδου απέτυχε. Παρακαλούμε κάντε " +
"αποσύνδεση, επανασύνδεση και ξαναδοκιμάστε.)");
if(!sessionVerificationFailed.isEmpty())
if (!sessionVerificationFailed.isEmpty())
throw new InvalidSessionException();
if(markAsReadLink==null)
if (markAsReadLink == null)
markAsReadLink = extractMarkAsReadLink(document);
} catch (InvalidSessionException ise) {
@ -52,7 +52,7 @@ public class MarkAsReadTask extends NetworkTask<Void> {
return NetworkResultCodes.SUCCESSFUL;
}
private String extractMarkAsReadLink(Document document){
private String extractMarkAsReadLink(Document document) {
Elements markAllAsReadLink = document.select("a[href^=" + baseMarkAllAsReadLink + "]");
if (!markAllAsReadLink.isEmpty()) {

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

@ -125,7 +125,8 @@ public class SessionManager {
editor.apply();
return SUCCESS;
} else {
}
else {
Timber.i("Login failed.");
//Investigate login failure
@ -156,7 +157,7 @@ public class SessionManager {
Timber.i("Login InterruptedIOException"); //users cancels LoginTask
return CANCELLED;
} catch (IOException e) {
Timber.w(e ,"Login IOException");
Timber.w(e, "Login IOException");
return CONNECTION_ERROR;
} catch (Exception e) {
Timber.e(e, "Login Exception (other)");
@ -203,8 +204,8 @@ public class SessionManager {
public Cookie getThmmyCookie() {
List<Cookie> cookieList = cookieJar.loadForRequest(indexUrl);
for(Cookie cookie: cookieList) {
if(cookie.name().equals("THMMYgrC00ki3"))
for (Cookie cookie : cookieList) {
if (cookie.name().equals("THMMYgrC00ki3"))
return cookie;
}
return null;
@ -225,8 +226,8 @@ public class SessionManager {
//------------------------------------ OTHER -------------------------------------------
private boolean validateRetrievedCookies() {
List<Cookie> cookieList = cookieJar.loadForRequest(indexUrl);
for(Cookie cookie: cookieList) {
if(cookie.name().equals("THMMYgrC00ki3"))
for (Cookie cookie : cookieList) {
if (cookie.name().equals("THMMYgrC00ki3"))
return true;
}
return false;
@ -246,7 +247,7 @@ public class SessionManager {
cookiePersistor.saveAll(cookieList);
}
private void setLoginScreenAsDefault(boolean b){
private void setLoginScreenAsDefault(boolean b) {
sessionSharedPrefs.edit().putBoolean(LOGIN_SCREEN_AS_DEFAULT, b).apply();
}
@ -263,7 +264,8 @@ public class SessionManager {
Matcher matcher = pattern.matcher(txt);
if (matcher.find())
userName = matcher.group(1);
} else {
}
else {
//Helios_Multi and SMF_oneBlue
user = doc.select("td.smalltext[width=100%] b");
if (user.size() == 1)
@ -279,12 +281,12 @@ public class SessionManager {
if (userName != null && !userName.isEmpty())
return userName;
Timber.e(new ParseException("Parsing failed(username extraction)"),"ParseException");
Timber.e(new ParseException("Parsing failed(username extraction)"), "ParseException");
return "User"; //return a default username
}
private int extractUserId(@NonNull Document doc) {
try{
try {
Elements elements = doc.select("a:containsOwn(Εμφάνιση των μηνυμάτων σας), a:containsOwn(Show own posts)");
if (elements.size() == 1) {
String link = elements.first().attr("href");
@ -295,9 +297,9 @@ public class SessionManager {
return Integer.parseInt(matcher.group(1));
}
} catch (Exception e) {
Timber.e(new ParseException("Parsing failed(user id extraction)"),"ParseException");
Timber.e(new ParseException("Parsing failed(user id extraction)"), "ParseException");
}
Timber.e(new ParseException("Parsing failed(user id extraction)"),"ParseException");
Timber.e(new ParseException("Parsing failed(user id extraction)"), "ParseException");
return -1;
}

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

@ -10,8 +10,8 @@ import static android.text.format.DateUtils.YEAR_IN_MILLIS;
public class DateTimeUtils {
private static final long MONTH_IN_MILLIS = 30*DAY_IN_MILLIS;
private static final long DECADE_IN_MILLIS = 10*YEAR_IN_MILLIS;
private static final long MONTH_IN_MILLIS = 30 * DAY_IN_MILLIS;
private static final long DECADE_IN_MILLIS = 10 * YEAR_IN_MILLIS;
@VisibleForTesting
public static String getRelativeTimeSpanString(long time) {
@ -21,51 +21,55 @@ public class DateTimeUtils {
long duration = Math.abs(now - time);
String format;
long count, mod;
if(duration < 45*SECOND_IN_MILLIS)
if (duration < 45 * SECOND_IN_MILLIS)
return "just now";
else if (duration < 45*MINUTE_IN_MILLIS) {
count = duration/MINUTE_IN_MILLIS;
else if (duration < 45 * MINUTE_IN_MILLIS) {
count = duration / MINUTE_IN_MILLIS;
mod = duration % MINUTE_IN_MILLIS;
if(mod >= 30*SECOND_IN_MILLIS)
if (mod >= 30 * SECOND_IN_MILLIS)
count += 1;
format = "%dm";
} else if (duration < 22*HOUR_IN_MILLIS) {
count = duration/HOUR_IN_MILLIS;
}
else if (duration < 22 * HOUR_IN_MILLIS) {
count = duration / HOUR_IN_MILLIS;
format = "%dh";
mod = (duration%HOUR_IN_MILLIS)/MINUTE_IN_MILLIS;
if(count<3 && mod>9 && mod<51){
if(count==0)
format = mod +"m";
mod = (duration % HOUR_IN_MILLIS) / MINUTE_IN_MILLIS;
if (count < 3 && mod > 9 && mod < 51) {
if (count == 0)
format = mod + "m";
else
format = format + " " + mod +"m";
format = format + " " + mod + "m";
}
else if(mod >= 30)
else if (mod >= 30)
count += 1;
} else if (duration < 26*DAY_IN_MILLIS) {
count = duration/DAY_IN_MILLIS;
}
else if (duration < 26 * DAY_IN_MILLIS) {
count = duration / DAY_IN_MILLIS;
format = "%dd";
mod = duration % DAY_IN_MILLIS;
if(mod >= 12*HOUR_IN_MILLIS)
if (mod >= 12 * HOUR_IN_MILLIS)
count += 1;
} else if (duration < 320*DAY_IN_MILLIS) {
count = duration/MONTH_IN_MILLIS;
}
else if (duration < 320 * DAY_IN_MILLIS) {
count = duration / MONTH_IN_MILLIS;
format = "%d month";
mod = duration % MONTH_IN_MILLIS;
if(mod >= 15*DAY_IN_MILLIS)
if (mod >= 15 * DAY_IN_MILLIS)
count += 1;
if(count>1)
if (count > 1)
format = format + 's';
} else if (duration < DECADE_IN_MILLIS) {
count = duration/YEAR_IN_MILLIS;
}
else if (duration < DECADE_IN_MILLIS) {
count = duration / YEAR_IN_MILLIS;
format = "%d year";
mod = duration % YEAR_IN_MILLIS;
if(mod >= 183*DAY_IN_MILLIS)
if (mod >= 183 * DAY_IN_MILLIS)
count += 1;
if(count>1)
if (count > 1)
format = format + 's';
}
else
return past ? "a long time ago": "in the distant future";
return past ? "a long time ago" : "in the distant future";
format = past ? format : "in " + format;
return String.format(format, (int) count);

5
app/src/main/java/gr/thmmy/mthmmy/utils/ExternalAsyncTask.java

@ -52,7 +52,8 @@ public abstract class ExternalAsyncTask<U, V> extends AsyncTask<U, Void, V> {
this.onTaskFinishedListener = onTaskFinishedListener;
}
public ExternalAsyncTask() { }
public ExternalAsyncTask() {
}
public void setOnTaskStartedListener(OnTaskStartedListener onTaskStartedListener) {
this.onTaskStartedListener = onTaskStartedListener;
@ -78,7 +79,7 @@ public abstract class ExternalAsyncTask<U, V> extends AsyncTask<U, Void, V> {
void onTaskFinished(V result);
}
public boolean isRunning(){
public boolean isRunning() {
return getStatus() == AsyncTask.Status.RUNNING;
}
}

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

@ -41,7 +41,8 @@ public class FileUtils {
}
if (filename.toLowerCase().endsWith(".tar.gz")) {
fileExtension = filename.substring(filename.length() - 7);
} else {
}
else {
fileExtension = filename.substring(filename.lastIndexOf("."));
}

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

@ -25,13 +25,15 @@ import static gr.thmmy.mthmmy.activities.profile.ProfileActivity.BUNDLE_PROFILE_
import static gr.thmmy.mthmmy.activities.profile.ProfileActivity.BUNDLE_PROFILE_USERNAME;
public class HTMLUtils {
private HTMLUtils() {}
private HTMLUtils() {
}
public static SpannableStringBuilder getSpannableFromHtml(Activity activity, String html) {
CharSequence sequence;
if (Build.VERSION.SDK_INT >= 24) {
sequence = Html.fromHtml(html, Html.FROM_HTML_MODE_LEGACY);
} else {
}
else {
//noinspection deprecation
sequence = Html.fromHtml(html);
}
@ -59,7 +61,8 @@ public class HTMLUtils {
intent.putExtras(extras);
intent.setFlags(FLAG_ACTIVITY_NEW_TASK);
context.startActivity(intent);
} else if (target.is(ThmmyPage.PageCategory.PROFILE)) {
}
else if (target.is(ThmmyPage.PageCategory.PROFILE)) {
Intent intent = new Intent(context, ProfileActivity.class);
Bundle extras = new Bundle();
extras.putString(BUNDLE_PROFILE_URL, span.getURL());
@ -68,7 +71,8 @@ public class HTMLUtils {
intent.putExtras(extras);
intent.setFlags(FLAG_ACTIVITY_NEW_TASK);
context.startActivity(intent);
} else if (target.is(ThmmyPage.PageCategory.INDEX)) {
}
else if (target.is(ThmmyPage.PageCategory.INDEX)) {
Intent intent = new Intent(context, MainActivity.class);
intent.setFlags(FLAG_ACTIVITY_NEW_TASK);
context.startActivity(intent);

6
app/src/main/java/gr/thmmy/mthmmy/utils/LaunchType.java

@ -24,11 +24,13 @@ public class LaunchType {
if (currentVersionCode == savedVersionCode) {
//This is just a normal run
return LAUNCH_TYPE.NORMAL_LAUNCH;
} else if (savedVersionCode == notThere) {
}
else if (savedVersionCode == notThere) {
//Updates the shared preferences with the current version code
prefs.edit().putInt(PREF_VERSION_CODE_KEY, currentVersionCode).apply();
return LAUNCH_TYPE.FIRST_LAUNCH_EVER;
} else if (currentVersionCode > savedVersionCode) {
}
else if (currentVersionCode > savedVersionCode) {
//Updates the shared preferences with the current version code
prefs.edit().putInt(PREF_VERSION_CODE_KEY, currentVersionCode).apply();
return LAUNCH_TYPE.FIRST_LAUNCH_AFTER_UPDATE;

2
app/src/main/java/gr/thmmy/mthmmy/utils/TakePhoto.java

@ -86,7 +86,7 @@ public class TakePhoto {
File imageFolder = new File(Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DCIM) +
File.separator + "mTHMMY");
if (!imageFolder.exists()&&!imageFolder.mkdirs()) {
if (!imageFolder.exists() && !imageFolder.mkdirs()) {
Timber.w("Photos folder build returned false in %s", TakePhoto.class.getSimpleName());
Toast.makeText(context, "Couldn't create photos directory", Toast.LENGTH_SHORT).show();
return null;

3
app/src/main/java/gr/thmmy/mthmmy/utils/crashreporting/CrashReporter.java

@ -13,7 +13,8 @@ import gr.thmmy.mthmmy.utils.parsing.ParseHelpers;
public class CrashReporter {
private static final int STRING_BATCH_LENGTH = 250;
private CrashReporter() {}
private CrashReporter() {
}
public static void reportForumInfo(Document document) {
ParseHelpers.Theme theme = ParseHelpers.parseTheme(document);

9
app/src/main/java/gr/thmmy/mthmmy/utils/crashreporting/CrashReportingTree.java

@ -9,7 +9,8 @@ import com.google.firebase.crashlytics.FirebaseCrashlytics;
import timber.log.Timber.DebugTree;
public class CrashReportingTree extends DebugTree {
private FirebaseCrashlytics firebaseCrashlytics;
private FirebaseCrashlytics firebaseCrashlytics;
public CrashReportingTree() {
super();
firebaseCrashlytics = FirebaseCrashlytics.getInstance();
@ -27,15 +28,15 @@ public class CrashReportingTree extends DebugTree {
level = 'I';
else if (priority == Log.WARN)
level = 'W';
else if(priority == Log.ERROR)
else if (priority == Log.ERROR)
level = 'E';
else
level = 'A';
firebaseCrashlytics.log(level + "/" + tag + ": " + message);
if(priority == Log.ERROR) {
if (t!=null)
if (priority == Log.ERROR) {
if (t != null)
firebaseCrashlytics.recordException(t);
else
firebaseCrashlytics.recordException(new Exception(message));

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

@ -36,7 +36,8 @@ public abstract class NetworkTask<T> extends ExternalAsyncTask<String, Parcel<T>
this.onNetworkTaskFinishedListener = onNetworkTaskFinishedListener;
}
public NetworkTask() {}
public NetworkTask() {
}
@Override
protected Parcel<T> doInBackground(String... input) {
@ -85,7 +86,7 @@ public abstract class NetworkTask<T> extends ExternalAsyncTask<String, Parcel<T>
// BaseApplication.getInstance().getSessionManager().clearSessionData();
// BaseApplication.getInstance().getSessionManager().guestLogin();
return new Parcel<>(SessionManager.INVALID_SESSION, null);
}catch (Exception e) {
} catch (Exception e) {
Timber.e(e);
return new Parcel<>(NetworkResultCodes.PERFORM_TASK_ERROR, null);
}

5
app/src/main/java/gr/thmmy/mthmmy/utils/parsing/NewParseTask.java

@ -17,7 +17,8 @@ public abstract class NewParseTask<T> extends NetworkTask<T> {
super(onTaskStartedListener, onParseTaskFinishedListener);
}
public NewParseTask() {}
public NewParseTask() {
}
@Override
protected final T performTask(Document document, Response response) {
@ -30,5 +31,5 @@ public abstract class NewParseTask<T> extends NetworkTask<T> {
}
}
protected abstract T parse (Document document, Response response) throws ParseException;
protected abstract T parse(Document document, Response response) throws ParseException;
}

3
app/src/main/java/gr/thmmy/mthmmy/utils/parsing/ParseException.java

@ -4,7 +4,8 @@ package gr.thmmy.mthmmy.utils.parsing;
* Use ParseException for errors while parsing.
*/
public class ParseException extends RuntimeException {
public ParseException() {}
public ParseException() {
}
public ParseException(String message) {
super(message);

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

@ -56,7 +56,8 @@ public class ParseHelpers {
if (welcomingGuest != null && welcomingGuest.text().contains("Welcome"))
return ENGLISH;
return PAGE_INCOMPLETE;
} else if (welcoming.text().contains("Καλώς ορίσατε")) return GREEK;
}
else if (welcoming.text().contains("Καλώς ορίσατε")) return GREEK;
else if (welcoming.text().contains("Hey")) return ENGLISH;
else return UNKNOWN_LANGUAGE;
}
@ -72,7 +73,7 @@ public class ParseHelpers {
public static Theme parseTheme(Document page) {
Element stylesheet = page.select("link[rel=stylesheet]").first();
if(stylesheet!=null){
if (stylesheet != null) {
if (stylesheet.attr("href").contains("scribbles2"))
return Theme.SCRIBBLES2;
else if (stylesheet.attr("href").contains("helios_multi"))
@ -168,7 +169,7 @@ public class ParseHelpers {
+ "https://img.youtube.com/vi/"
+ videoId
+ "/default.jpg');\"></a></div>"
);
);
++counter;
}
return fixed;

7
app/src/main/java/gr/thmmy/mthmmy/utils/parsing/ParseTask.java

@ -21,14 +21,17 @@ import timber.log.Timber;
*/
public abstract class ParseTask extends AsyncTask<String, Void, ParseTask.ResultCode> {
protected String url;
public enum ResultCode {
SUCCESS, PARSING_ERROR, NETWORK_ERROR, OTHER_ERROR
}
protected abstract void parse (Document document) throws ParseException;
protected abstract void parse(Document document) throws ParseException;
protected abstract void postExecution(ParseTask.ResultCode result); //ResultCode.NETWORK_ERROR is handled automatically
protected void postParsing (){}
protected void postParsing() {
}
protected Request prepareRequest(String... params) {
url = params[0];

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

@ -5,6 +5,8 @@ import androidx.annotation.VisibleForTesting;
import org.joda.time.DateTime;
import org.joda.time.DateTimeUtils;
import org.joda.time.DateTimeZone;
import org.joda.time.IllegalInstantException;
import org.joda.time.LocalDateTime;
import org.joda.time.format.DateTimeFormat;
import org.joda.time.format.DateTimeFormatter;
import org.joda.time.format.DateTimeFormatterBuilder;
@ -39,9 +41,10 @@ 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){
public static String convertToTimestamp(String thmmyDateTime) {
Timber.v("Will attempt to convert %s to timestamp.", thmmyDateTime);
String originalDateTime = thmmyDateTime;
DateTimeZone dtz = getDtz();
@ -50,61 +53,70 @@ public class ThmmyDateTimeParser {
thmmyDateTime = purifyTodayDateTime(thmmyDateTime);
// Add today's date for the first two cases
if(thmmyDateTime.charAt(2)==':')
if (thmmyDateTime.charAt(2) == ':')
thmmyDateTime = (new DateTime()).toString("MMMM d, Y, ") + thmmyDateTime;
// Don't even ask
if(thmmyDateTime.contains("am"))
thmmyDateTime = thmmyDateTime.replaceAll("\\s00:"," 12:");
if (thmmyDateTime.contains("am"))
thmmyDateTime = thmmyDateTime.replaceAll("\\s00:", " 12:");
// For the stupid format 23:54:12 pm
Matcher matcher = pattern.matcher(thmmyDateTime);
if (matcher.find())
thmmyDateTime = thmmyDateTime.replaceAll("\\spm","");
thmmyDateTime = thmmyDateTime.replaceAll("\\spm", "");
DateTime dateTime;
try{
dateTime=formatter.withZone(dtz).withLocale(englishLocale).parseDateTime(thmmyDateTime);
}
catch (IllegalArgumentException e1){
LocalDateTime localDateTime;
try {
localDateTime = formatter.withLocale(englishLocale).parseLocalDateTime(thmmyDateTime);
} catch (IllegalArgumentException e1) {
Timber.v("Parsing DateTime %s using English Locale failed.", thmmyDateTime);
try{
try {
DateFormatSymbols dfs = DateTimeUtils.getDateFormatSymbols(greekLocale);
thmmyDateTime = thmmyDateTime.replace("am",dfs.getAmPmStrings()[0]);
thmmyDateTime = thmmyDateTime.replace("pm",dfs.getAmPmStrings()[1]);
thmmyDateTime = thmmyDateTime.replace("am", dfs.getAmPmStrings()[0]);
thmmyDateTime = thmmyDateTime.replace("pm", dfs.getAmPmStrings()[1]);
Timber.v("Attempting to parse DateTime %s using Greek Locale...", thmmyDateTime);
dateTime=formatter.withZone(dtz).withLocale(greekLocale).parseDateTime(thmmyDateTime);
}
catch (IllegalArgumentException e2){
Timber.d("Parsing DateTime %s using Greek Locale failed too.", thmmyDateTime);
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);
return null;
}
}
// Ensure DST time overlaps/ gaps are handled properly
try{
// For autumn overlaps
dateTime = localDateTime.toDateTime(dtz).withEarlierOffsetAtOverlap();
} catch (IllegalInstantException e2) {
// For spring gaps
dateTime = localDateTime.plusHours(1).toDateTime(dtz);
}
String timestamp = Long.toString(dateTime.getMillis());
Timber.v("DateTime %s was converted to %s, or %s", originalDateTime, timestamp, dateTime.toString());
return timestamp;
}
public static String simplifyDateTime(String dateTime){
public static String simplifyDateTime(String dateTime) {
return removeSeconds(purifyTodayDateTime(dateTime));
}
// Converts e.g. Today at 12:16:48 -> 12:16:48, but October 03, 2019, 16:40:18 remains as is
@VisibleForTesting
static String purifyTodayDateTime(String dateTime){
static String purifyTodayDateTime(String dateTime) {
return dateTime.replaceAll("(Today at |Σήμερα στις )(.+)", "$2");
}
// Converts e.g. 12:16:48 -> 12:16, October 03, 2019, 16:40:18 -> 12:16 October 03, 2019, 16:40
private static String removeSeconds(String dateTime){
private static String removeSeconds(String dateTime) {
return dateTime.replaceAll("(.*):\\d+($|\\s.*)", "$1$2");
}
@VisibleForTesting
private static DateTimeZone getDtz(){
if(!BaseApplication.getInstance().getSessionManager().isLoggedIn())
private static DateTimeZone getDtz() {
if (!BaseApplication.getInstance().getSessionManager().isLoggedIn())
return DateTimeZone.forID("Europe/Athens");
else
return DateTimeZone.getDefault();

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

@ -138,7 +138,8 @@ public class ThmmyParser {
if (separatorIndex > 0) {
attribute = startTag.substring(separatorIndex);
name = startTag.substring(0, separatorIndex);
} else
}
else
name = startTag;
if (name.startsWith("/")) {
@ -177,7 +178,8 @@ public class ThmmyParser {
attribute = fullAttribute.substring(1, equalsIndex);
attributeValue = fullAttribute.substring(equalsIndex + 2, fullAttribute.length() - 1);
name = startTag.substring(0, separatorIndex);
} else
}
else
name = startTag;
if (name.startsWith("/")) {

2
app/src/main/java/gr/thmmy/mthmmy/utils/ui/CenterVerticalSpan.java

@ -15,7 +15,7 @@ public class CenterVerticalSpan extends ReplacementSpan {
}
@Override
public void draw(@NonNull Canvas canvas, CharSequence text, int start, int end, float x, int top, int y, int bottom,@NonNull Paint paint) {
public void draw(@NonNull Canvas canvas, CharSequence text, int start, int end, float x, int top, int y, int bottom, @NonNull Paint paint) {
text = text.subSequence(start, end);
Rect charSize = new Rect();
paint.getTextBounds(text.toString(), 0, 1, charSize);

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

@ -20,7 +20,7 @@ import timber.log.Timber;
import static android.content.Context.CLIPBOARD_SERVICE;
public class ImageDownloadDialogBuilder extends AlertDialog.Builder{
public class ImageDownloadDialogBuilder extends AlertDialog.Builder {
private static final String[] colors = {"Copy image location", "Save Image"};
private Context context;
@ -32,7 +32,7 @@ public class ImageDownloadDialogBuilder extends AlertDialog.Builder{
this.imageURL = imageURL;
setItems(colors, (dialog, which) -> {
if(which == 0)
if (which == 0)
copyUrlToClipboard();
else {
try {
@ -46,11 +46,11 @@ public class ImageDownloadDialogBuilder extends AlertDialog.Builder{
});
}
private void copyUrlToClipboard(){
private void copyUrlToClipboard() {
ClipboardManager clipboard = (ClipboardManager) BaseApplication.getInstance().getSystemService(CLIPBOARD_SERVICE);
ClipData clip = ClipData.newPlainText("ReactiveWebViewCopiedText", imageURL);
clipboard.setPrimaryClip(clip);
Toast.makeText(BaseApplication.getInstance().getApplicationContext(),context.getString(R.string.link_copied_msg),Toast.LENGTH_SHORT).show();
Toast.makeText(BaseApplication.getInstance().getApplicationContext(), context.getString(R.string.link_copied_msg), Toast.LENGTH_SHORT).show();
}
private BaseActivity getBaseActivity() {
@ -58,7 +58,7 @@ public class ImageDownloadDialogBuilder extends AlertDialog.Builder{
while (baseActivityContext instanceof ContextWrapper) {
if (context instanceof BaseActivity)
return (BaseActivity) context;
baseActivityContext = ((ContextWrapper)context).getBaseContext();
baseActivityContext = ((ContextWrapper) context).getBaseContext();
}
return null;
}

3
app/src/main/java/gr/thmmy/mthmmy/utils/ui/ScrollAwareFABBehavior.java

@ -45,7 +45,8 @@ public class ScrollAwareFABBehavior extends CoordinatorLayout.Behavior<FloatingA
fab.setVisibility(View.INVISIBLE);
}
});
} else if (child.getTag() != null && (boolean) child.getTag() && (dyConsumed < 0 ||
}
else if (child.getTag() != null && (boolean) child.getTag() && (dyConsumed < 0 ||
!target.canScrollVertically(-1) && dyUnconsumed < -50)) {
child.show(new FloatingActionButton.OnVisibilityChangedListener() {
@Override

3
app/src/main/java/gr/thmmy/mthmmy/utils/ui/ScrollAwareLinearBehavior.java

@ -45,7 +45,8 @@ public class ScrollAwareLinearBehavior extends CoordinatorLayout.Behavior<View>
if (bottomNavBar.getVisibility() == View.VISIBLE && (dyConsumed > 0
|| (!target.canScrollVertically(-1) && dyConsumed == 0 && dyUnconsumed > 50))) {
hide(bottomNavBar);
} else if (bottomNavBar.getVisibility() == View.INVISIBLE && (dyConsumed < 0
}
else if (bottomNavBar.getVisibility() == View.INVISIBLE && (dyConsumed < 0
|| (!target.canScrollVertically(-1) && dyConsumed == 0 && dyUnconsumed < -50))) {
show(bottomNavBar);
}

3
app/src/main/java/gr/thmmy/mthmmy/viewmodel/ShoutboxViewModel.java

@ -28,7 +28,8 @@ public class ShoutboxViewModel extends ViewModel {
}
public void sendShout(String shout) {
if (shoutboxMutableLiveData.getValue() == null) throw new IllegalStateException("Shoutbox task has not finished yet!");
if (shoutboxMutableLiveData.getValue() == null)
throw new IllegalStateException("Shoutbox task has not finished yet!");
Shoutbox shoutbox = shoutboxMutableLiveData.getValue();
new SendShoutTask(onSendShoutTaskStarted, onSendShoutTaskFinished)
.execute(shoutbox.getSendShoutUrl(), shout, shoutbox.getSc(),

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

@ -100,7 +100,8 @@ public class TopicViewModel extends BaseViewModel implements TopicTask.OnTopicTa
}
public void reloadPage() {
if (topicUrl == null) throw new NullPointerException("No topic task has been requested yet!");
if (topicUrl == null)
throw new NullPointerException("No topic task has been requested yet!");
Timber.i("Reloading page");
loadUrl(topicUrl);
}
@ -110,13 +111,15 @@ public class TopicViewModel extends BaseViewModel implements TopicTask.OnTopicTa
* in the url before refreshing
*/
public void resetPage() {
if (topicUrl == null) throw new NullPointerException("No topic task has been requested yet!");
if (topicUrl == null)
throw new NullPointerException("No topic task has been requested yet!");
Timber.i("Resetting page");
loadUrl(ParseHelpers.getBaseURL(topicUrl) + "." + String.valueOf(currentPageIndex * 15));
}
public void resetPageThen(Runnable runnable) {
if (topicUrl == null) throw new NullPointerException("No topic task has been requested yet!");
if (topicUrl == null)
throw new NullPointerException("No topic task has been requested yet!");
Timber.i("Resetting page");
stopLoading();
currentTopicTask = new TopicTask(topicTaskObserver, result -> {
@ -134,18 +137,21 @@ public class TopicViewModel extends BaseViewModel implements TopicTask.OnTopicTa
Timber.i("Changing to page " + pageRequested + 1);
loadUrl(ParseHelpers.getBaseURL(topicUrl) + "." + pageRequested * 15);
pageIndicatorIndex.setValue(pageRequested + 1);
} else {
}
else {
stopLoading();
}
}
public boolean submitVote(LinearLayout optionsLayout) {
if (topicItems.getValue() == null) throw new NullPointerException("Topic task has not finished yet!");
if (topicItems.getValue() == null)
throw new NullPointerException("Topic task has not finished yet!");
ArrayList<Integer> votes = new ArrayList<>();
if (optionsLayout.getChildAt(0) instanceof RadioGroup) {
RadioGroup optionsRadioGroup = (RadioGroup) optionsLayout.getChildAt(0);
votes.add(optionsRadioGroup.getCheckedRadioButtonId());
} else if (optionsLayout.getChildAt(0) instanceof CheckBox) {
}
else if (optionsLayout.getChildAt(0) instanceof CheckBox) {
for (int i = 0; i < optionsLayout.getChildCount(); i++) {
CheckBox checkBox = (CheckBox) optionsLayout.getChildAt(i);
if (checkBox.isChecked())
@ -164,7 +170,8 @@ public class TopicViewModel extends BaseViewModel implements TopicTask.OnTopicTa
}
public void removeVote() {
if (topicItems.getValue() == null) throw new NullPointerException("Topic task has not finished yet!");
if (topicItems.getValue() == null)
throw new NullPointerException("Topic task has not finished yet!");
RemoveVoteTask removeVoteTask = new RemoveVoteTask();
removeVoteTask.setOnTaskStartedListener(removeVoteTaskStartedListener);
removeVoteTask.setOnNetworkTaskFinishedListener(removeVoteTaskFinishedListener);
@ -308,14 +315,15 @@ public class TopicViewModel extends BaseViewModel implements TopicTask.OnTopicTa
throw new NullPointerException("No page has been loaded yet!");
int oldIndicatorIndex = this.pageIndicatorIndex.getValue();
this.pageIndicatorIndex.setValue(pageIndicatorIndex);
if (changePage && oldIndicatorIndex != this.pageIndicatorIndex.getValue()) loadPageIndicated();
if (changePage && oldIndicatorIndex != this.pageIndicatorIndex.getValue())
loadPageIndicated();
}
// <-------------Just getters, setters and helper methods below here---------------->
public int getTopicId() {
if (pageTopicId.getValue() == null)
throw new NullPointerException("No page has been loaded yet!");
throw new NullPointerException("No page has been loaded yet!");
return pageTopicId.getValue();
}
@ -461,12 +469,12 @@ public class TopicViewModel extends BaseViewModel implements TopicTask.OnTopicTa
}
public int getCurrentPageIndex() {
if (currentPageIndex == 0) throw new NullPointerException("No page has been loaded yet!");
if (currentPageIndex == 0) throw new NullPointerException("No page has been loaded yet!");
return currentPageIndex;
}
public int getPageCount() {
if (pageCount == 0) throw new NullPointerException("No page has been loaded yet!");
if (pageCount == 0) throw new NullPointerException("No page has been loaded yet!");
return pageCount;
}
@ -484,7 +492,7 @@ public class TopicViewModel extends BaseViewModel implements TopicTask.OnTopicTa
public int postCount() {
if (topicItems.getValue() == null)
throw new NullPointerException("No page has been loaded yet!");
throw new NullPointerException("No page has been loaded yet!");
return topicItems.getValue().size();
}
}

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

@ -41,7 +41,7 @@ public class ReactiveWebView extends WebView {
init();
}
private void init(){
private void init() {
setOnLongClickListener();
this.setVerticalScrollBarEnabled(false);
}
@ -53,7 +53,7 @@ public class ReactiveWebView extends WebView {
downTime = event.getEventTime();
break;
case MotionEvent.ACTION_UP:
if(event.getEventTime() - downTime <= MAX_TOUCH_DURATION)
if (event.getEventTime() - downTime <= MAX_TOUCH_DURATION)
performClick();
break;
default:
@ -65,27 +65,27 @@ public class ReactiveWebView extends WebView {
@Override
public boolean performClick() {
WebView.HitTestResult result = this.getHitTestResult();
if(result.getType() == WebView.HitTestResult.IMAGE_TYPE){
if (result.getType() == WebView.HitTestResult.IMAGE_TYPE) {
String imageURL = result.getExtra();
displayPhotoViewImage(context, imageURL);
}
return super.performClick();
}
private void setOnLongClickListener(){
private void setOnLongClickListener() {
this.setOnLongClickListener(v -> {
HitTestResult result = ReactiveWebView.this.getHitTestResult();
if(result.getType() == HitTestResult.SRC_ANCHOR_TYPE)
if (result.getType() == HitTestResult.SRC_ANCHOR_TYPE)
copyUrlToClipboard(result.getExtra());
else if(result.getType() == WebView.HitTestResult.IMAGE_TYPE) {
else if (result.getType() == WebView.HitTestResult.IMAGE_TYPE) {
String imageURL = result.getExtra();
showImageDownloadDialog(imageURL);
}
else if(result.getType() == HitTestResult.SRC_IMAGE_ANCHOR_TYPE) {
else if (result.getType() == HitTestResult.SRC_IMAGE_ANCHOR_TYPE) {
final String imageURL = result.getExtra();
Uri uri = Uri.parse(imageURL);
String videoId = uri.getQueryParameter(VIDEO_ID_PARAMETER);
if (videoId!=null)
if (videoId != null)
copyUrlToClipboard("https://www.youtube.com/watch?v=" + videoId);
else
showImageDownloadDialog(imageURL);
@ -94,14 +94,14 @@ public class ReactiveWebView extends WebView {
});
}
private void copyUrlToClipboard(String urlToCopy){
private void copyUrlToClipboard(String urlToCopy) {
ClipboardManager clipboard = (ClipboardManager) BaseApplication.getInstance().getSystemService(CLIPBOARD_SERVICE);
ClipData clip = ClipData.newPlainText("ReactiveWebViewCopiedText", urlToCopy);
clipboard.setPrimaryClip(clip);
Toast.makeText(BaseApplication.getInstance().getApplicationContext(),context.getString(R.string.link_copied_msg),Toast.LENGTH_SHORT).show();
Toast.makeText(BaseApplication.getInstance().getApplicationContext(), context.getString(R.string.link_copied_msg), Toast.LENGTH_SHORT).show();
}
private void showImageDownloadDialog(String imageURL){
private void showImageDownloadDialog(String imageURL) {
ImageDownloadDialogBuilder builder = new ImageDownloadDialogBuilder(context, imageURL);
builder.show();
}

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

@ -67,6 +67,7 @@ public class RelativeTimeTextView extends TextView {
* Sets the reference time for this view. At any moment, the view will render a relative time period relative to the time set here.
* <p/>
* This value can also be set with the XML attribute {@code reference_time}
*
* @param referenceTime The timestamp (in milliseconds since epoch) that will be the reference point for this view.
*/
public void setReferenceTime(long referenceTime) {
@ -120,13 +121,14 @@ public class RelativeTimeTextView extends TextView {
super.onVisibilityChanged(changedView, visibility);
if (visibility == GONE || visibility == INVISIBLE) {
stopTaskForPeriodicallyUpdatingRelativeTime();
} else {
}
else {
startTaskForPeriodicallyUpdatingRelativeTime();
}
}
private void startTaskForPeriodicallyUpdatingRelativeTime() {
if(mUpdateTimeTask.isDetached()) initUpdateTimeTask();
if (mUpdateTimeTask.isDetached()) initUpdateTimeTask();
mHandler.post(mUpdateTimeTask);
isUpdateTaskRunning = true;
}
@ -136,7 +138,7 @@ public class RelativeTimeTextView extends TextView {
}
private void stopTaskForPeriodicallyUpdatingRelativeTime() {
if(isUpdateTaskRunning) {
if (isUpdateTaskRunning) {
mUpdateTimeTask.detach();
mHandler.removeCallbacks(mUpdateTimeTask);
isUpdateTaskRunning = false;
@ -158,7 +160,7 @@ public class RelativeTimeTextView extends TextView {
return;
}
SavedState ss = (SavedState)state;
SavedState ss = (SavedState) state;
mReferenceTime = ss.referenceTime;
super.onRestoreInstanceState(ss.getSuperState());
}
@ -219,9 +221,11 @@ public class RelativeTimeTextView extends TextView {
long interval = INITIAL_UPDATE_INTERVAL;
if (difference > DateUtils.WEEK_IN_MILLIS) {
interval = DateUtils.WEEK_IN_MILLIS;
} else if (difference > DateUtils.DAY_IN_MILLIS) {
}
else if (difference > DateUtils.DAY_IN_MILLIS) {
interval = DateUtils.DAY_IN_MILLIS;
} else if (difference > DateUtils.HOUR_IN_MILLIS) {
}
else if (difference > DateUtils.HOUR_IN_MILLIS) {
interval = DateUtils.HOUR_IN_MILLIS;
}
rttv.updateTextDisplay();

1
app/src/main/java/gr/thmmy/mthmmy/views/ToggledBackgroundButton.java

@ -1,4 +1,5 @@
package gr.thmmy.mthmmy.views;
import android.content.Context;
import android.util.AttributeSet;

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

@ -85,7 +85,8 @@ public class EditorView extends LinearLayout implements EmojiInputField {
if (!emojiKeyboard.isVisible()) {
InputMethodManager imm = (InputMethodManager) context.getSystemService(Activity.INPUT_METHOD_SERVICE);
imm.showSoftInput(editText, InputMethodManager.SHOW_IMPLICIT);
} else {
}
else {
InputMethodManager imm = (InputMethodManager) context.getSystemService(Activity.INPUT_METHOD_SERVICE);
imm.hideSoftInputFromWindow(getWindowToken(), 0);
requestEditTextFocus();
@ -128,244 +129,246 @@ public class EditorView extends LinearLayout implements EmojiInputField {
getResources().getDimension(R.dimen.editor_format_button_margin_between);
int columns = (int) Math.floor(displayMetrics.widthPixels / itemWidth);
formatButtonsRecyclerview.setLayoutManager(new GridLayoutManager(context, columns));
formatButtonsRecyclerview.setAdapter(
new FormatButtonsAdapter(
(view, drawableId) -> {
boolean hadTextSelection;
switch (drawableId) {
case R.drawable.ic_format_bold:
hadTextSelection = editText.hasSelection();
getText().insert(editText.getSelectionStart(), "[b]");
getText().insert(editText.getSelectionEnd(), "[/b]");
editText.setSelection(
hadTextSelection
? editText.getSelectionEnd()
: editText.getSelectionStart() - 4);
break;
case R.drawable.ic_format_italic:
hadTextSelection = editText.hasSelection();
getText().insert(editText.getSelectionStart(), "[i]");
getText().insert(editText.getSelectionEnd(), "[/i]");
editText.setSelection(
hadTextSelection
? editText.getSelectionEnd()
: editText.getSelectionStart() - 4);
break;
case R.drawable.ic_format_underlined:
hadTextSelection = editText.hasSelection();
getText().insert(editText.getSelectionStart(), "[u]");
getText().insert(editText.getSelectionEnd(), "[/u]");
editText.setSelection(
hadTextSelection
? editText.getSelectionEnd()
: editText.getSelectionStart() - 4);
break;
case R.drawable.ic_strikethrough_s:
hadTextSelection = editText.hasSelection();
getText().insert(editText.getSelectionStart(), "[s]");
getText().insert(editText.getSelectionEnd(), "[/s]");
editText.setSelection(
hadTextSelection
? editText.getSelectionEnd()
: editText.getSelectionStart() - 4);
break;
case R.drawable.ic_format_color_text:
int selectionStart = editText.getSelectionStart();
int selectionEnd = editText.getSelectionEnd();
PopupWindow popupWindow = new PopupWindow(view.getContext());
popupWindow.setHeight(LayoutParams.WRAP_CONTENT);
popupWindow.setWidth(LayoutParams.WRAP_CONTENT);
popupWindow.setFocusable(true);
ScrollView colorPickerScrollview =
(ScrollView)
LayoutInflater.from(context)
.inflate(R.layout.editor_view_color_picker, null);
LinearLayout colorPicker = (LinearLayout) colorPickerScrollview.getChildAt(0);
popupWindow.setContentView(colorPickerScrollview);
for (int i = 0; i < colorPicker.getChildCount(); i++) {
TextView child = (TextView) colorPicker.getChildAt(i);
child.setOnClickListener(
v -> {
boolean hadTextSelection2 = editText.hasSelection();
getText()
.insert(
editText.getSelectionStart(),
"[color=" + colors.get(v.getId()) + "]");
getText().insert(editText.getSelectionEnd(), "[/color]");
editText.setSelection(
hadTextSelection2
? editText.getSelectionEnd()
: editText.getSelectionStart() - 8);
popupWindow.dismiss();
});
}
popupWindow.showAsDropDown(view);
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.M) {
new AsyncTask<Void, Void, Void>() {
@Override
protected Void doInBackground(Void... voids) {
try {
Thread.sleep(100);
} catch (InterruptedException e) {
Timber.e(e);
}
return null;
}
@Override
protected void onPostExecute(Void aVoid) {
editText.setSelection(selectionStart, selectionEnd);
}
}.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
}
break;
case R.drawable.ic_format_size:
hadTextSelection = editText.hasSelection();
getText().insert(editText.getSelectionStart(), "[size=10pt]");
getText().insert(editText.getSelectionEnd(), "[/size]");
editText.setSelection(
hadTextSelection
? editText.getSelectionEnd()
: editText.getSelectionStart() - 7);
break;
case R.drawable.ic_text_format:
hadTextSelection = editText.hasSelection();
getText().insert(editText.getSelectionStart(), "[font=Verdana]");
getText().insert(editText.getSelectionEnd(), "[/font]");
editText.setSelection(
hadTextSelection
? editText.getSelectionEnd()
: editText.getSelectionStart() - 7);
break;
case R.drawable.ic_format_list_bulleted:
hadTextSelection = editText.hasSelection();
getText().insert(editText.getSelectionStart(), "[list]\n[li]");
getText().insert(editText.getSelectionEnd(), "[/li]\n[li][/li]\n[/list]");
editText.setSelection(
hadTextSelection
? editText.getSelectionEnd() - 13
: editText.getSelectionStart() - 23);
break;
case R.drawable.ic_format_align_left:
hadTextSelection = editText.hasSelection();
getText().insert(editText.getSelectionStart(), "[left]");
getText().insert(editText.getSelectionEnd(), "[/left]");
editText.setSelection(
hadTextSelection
? editText.getSelectionEnd()
: editText.getSelectionStart() - 7);
break;
case R.drawable.ic_format_align_center:
hadTextSelection = editText.hasSelection();
getText().insert(editText.getSelectionStart(), "[center]");
getText().insert(editText.getSelectionEnd(), "[/center]");
editText.setSelection(
hadTextSelection
? editText.getSelectionEnd()
: editText.getSelectionStart() - 9);
break;
case R.drawable.ic_format_align_right:
hadTextSelection = editText.hasSelection();
getText().insert(editText.getSelectionStart(), "[right]");
getText().insert(editText.getSelectionEnd(), "[/right]");
editText.setSelection(
hadTextSelection
? editText.getSelectionEnd()
: editText.getSelectionStart() - 8);
break;
case R.drawable.ic_insert_link:
LinearLayout dialogBody =
(LinearLayout)
LayoutInflater.from(context).inflate(R.layout.dialog_create_link, null);
TextInputLayout linkUrl = dialogBody.findViewById(R.id.link_url_input);
linkUrl.setOnClickListener(view1 -> linkUrl.setError(null));
TextInputLayout linkText = dialogBody.findViewById(R.id.link_text_input);
linkText.setOnClickListener(view2 -> linkText.setError(null));
hadTextSelection = editText.hasSelection();
int start = editText.getSelectionStart(), end = editText.getSelectionEnd();
if (editText.hasSelection()) {
linkText
.getEditText()
.setText(
editText
.getText()
.toString()
.substring(
editText.getSelectionStart(), editText.getSelectionEnd()));
}
AlertDialog linkDialog =
new AlertDialog.Builder(context, R.style.AppTheme_Dark_Dialog)
.setTitle(R.string.dialog_create_link_title)
.setView(dialogBody)
.setPositiveButton(R.string.ok, null)
.setNegativeButton(R.string.cancel, (dialog, which) -> dialog.dismiss())
.create();
linkDialog.setOnShowListener(
dialogInterface -> {
Button button = linkDialog.getButton(AlertDialog.BUTTON_POSITIVE);
button.setOnClickListener(
view12 -> {
if (TextUtils.isEmpty(
Objects.requireNonNull(linkUrl.getEditText())
.getText()
.toString())) {
linkUrl.setError(context.getString(R.string.input_field_required));
return;
}
if (hadTextSelection) editText.getText().delete(start, end);
if (!TextUtils.isEmpty(linkText.getEditText().getText())) {
getText()
.insert(
editText.getSelectionStart(),
"[url="
+ linkUrl.getEditText().getText().toString()
+ "]"
+ linkText.getEditText().getText().toString()
+ "[/url]");
} else
getText()
.insert(
editText.getSelectionStart(),
"[url]"
+ linkUrl.getEditText().getText().toString()
+ "[/url]");
linkDialog.dismiss();
});
});
linkDialog.show();
break;
case R.drawable.ic_format_quote:
hadTextSelection = editText.hasSelection();
getText().insert(editText.getSelectionStart(), "[quote]");
getText().insert(editText.getSelectionEnd(), "[/quote]");
editText.setSelection(
hadTextSelection
? editText.getSelectionEnd()
: editText.getSelectionStart() - 8);
break;
case R.drawable.ic_code:
hadTextSelection = editText.hasSelection();
getText().insert(editText.getSelectionStart(), "[code]");
getText().insert(editText.getSelectionEnd(), "[/code]");
editText.setSelection(
hadTextSelection
? editText.getSelectionEnd()
: editText.getSelectionStart() - 7);
break;
case R.drawable.ic_functions:
hadTextSelection = editText.hasSelection();
getText().insert(editText.getSelectionStart(), "[tex]");
getText().insert(editText.getSelectionEnd(), "[/tex]");
editText.setSelection(
hadTextSelection
? editText.getSelectionEnd()
: editText.getSelectionStart() - 6);
break;
default:
throw new IllegalArgumentException("Unknown format button click");
}
}));
formatButtonsRecyclerview.setAdapter(
new FormatButtonsAdapter(
(view, drawableId) -> {
boolean hadTextSelection;
switch (drawableId) {
case R.drawable.ic_format_bold:
hadTextSelection = editText.hasSelection();
getText().insert(editText.getSelectionStart(), "[b]");
getText().insert(editText.getSelectionEnd(), "[/b]");
editText.setSelection(
hadTextSelection
? editText.getSelectionEnd()
: editText.getSelectionStart() - 4);
break;
case R.drawable.ic_format_italic:
hadTextSelection = editText.hasSelection();
getText().insert(editText.getSelectionStart(), "[i]");
getText().insert(editText.getSelectionEnd(), "[/i]");
editText.setSelection(
hadTextSelection
? editText.getSelectionEnd()
: editText.getSelectionStart() - 4);
break;
case R.drawable.ic_format_underlined:
hadTextSelection = editText.hasSelection();
getText().insert(editText.getSelectionStart(), "[u]");
getText().insert(editText.getSelectionEnd(), "[/u]");
editText.setSelection(
hadTextSelection
? editText.getSelectionEnd()
: editText.getSelectionStart() - 4);
break;
case R.drawable.ic_strikethrough_s:
hadTextSelection = editText.hasSelection();
getText().insert(editText.getSelectionStart(), "[s]");
getText().insert(editText.getSelectionEnd(), "[/s]");
editText.setSelection(
hadTextSelection
? editText.getSelectionEnd()
: editText.getSelectionStart() - 4);
break;
case R.drawable.ic_format_color_text:
int selectionStart = editText.getSelectionStart();
int selectionEnd = editText.getSelectionEnd();
PopupWindow popupWindow = new PopupWindow(view.getContext());
popupWindow.setHeight(LayoutParams.WRAP_CONTENT);
popupWindow.setWidth(LayoutParams.WRAP_CONTENT);
popupWindow.setFocusable(true);
ScrollView colorPickerScrollview =
(ScrollView)
LayoutInflater.from(context)
.inflate(R.layout.editor_view_color_picker, null);
LinearLayout colorPicker = (LinearLayout) colorPickerScrollview.getChildAt(0);
popupWindow.setContentView(colorPickerScrollview);
for (int i = 0; i < colorPicker.getChildCount(); i++) {
TextView child = (TextView) colorPicker.getChildAt(i);
child.setOnClickListener(
v -> {
boolean hadTextSelection2 = editText.hasSelection();
getText()
.insert(
editText.getSelectionStart(),
"[color=" + colors.get(v.getId()) + "]");
getText().insert(editText.getSelectionEnd(), "[/color]");
editText.setSelection(
hadTextSelection2
? editText.getSelectionEnd()
: editText.getSelectionStart() - 8);
popupWindow.dismiss();
});
}
popupWindow.showAsDropDown(view);
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.M) {
new AsyncTask<Void, Void, Void>() {
@Override
protected Void doInBackground(Void... voids) {
try {
Thread.sleep(100);
} catch (InterruptedException e) {
Timber.e(e);
}
return null;
}
@Override
protected void onPostExecute(Void aVoid) {
editText.setSelection(selectionStart, selectionEnd);
}
}.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
}
break;
case R.drawable.ic_format_size:
hadTextSelection = editText.hasSelection();
getText().insert(editText.getSelectionStart(), "[size=10pt]");
getText().insert(editText.getSelectionEnd(), "[/size]");
editText.setSelection(
hadTextSelection
? editText.getSelectionEnd()
: editText.getSelectionStart() - 7);
break;
case R.drawable.ic_text_format:
hadTextSelection = editText.hasSelection();
getText().insert(editText.getSelectionStart(), "[font=Verdana]");
getText().insert(editText.getSelectionEnd(), "[/font]");
editText.setSelection(
hadTextSelection
? editText.getSelectionEnd()
: editText.getSelectionStart() - 7);
break;
case R.drawable.ic_format_list_bulleted:
hadTextSelection = editText.hasSelection();
getText().insert(editText.getSelectionStart(), "[list]\n[li]");
getText().insert(editText.getSelectionEnd(), "[/li]\n[li][/li]\n[/list]");
editText.setSelection(
hadTextSelection
? editText.getSelectionEnd() - 13
: editText.getSelectionStart() - 23);
break;
case R.drawable.ic_format_align_left:
hadTextSelection = editText.hasSelection();
getText().insert(editText.getSelectionStart(), "[left]");
getText().insert(editText.getSelectionEnd(), "[/left]");
editText.setSelection(
hadTextSelection
? editText.getSelectionEnd()
: editText.getSelectionStart() - 7);
break;
case R.drawable.ic_format_align_center:
hadTextSelection = editText.hasSelection();
getText().insert(editText.getSelectionStart(), "[center]");
getText().insert(editText.getSelectionEnd(), "[/center]");
editText.setSelection(
hadTextSelection
? editText.getSelectionEnd()
: editText.getSelectionStart() - 9);
break;
case R.drawable.ic_format_align_right:
hadTextSelection = editText.hasSelection();
getText().insert(editText.getSelectionStart(), "[right]");
getText().insert(editText.getSelectionEnd(), "[/right]");
editText.setSelection(
hadTextSelection
? editText.getSelectionEnd()
: editText.getSelectionStart() - 8);
break;
case R.drawable.ic_insert_link:
LinearLayout dialogBody =
(LinearLayout)
LayoutInflater.from(context).inflate(R.layout.dialog_create_link, null);
TextInputLayout linkUrl = dialogBody.findViewById(R.id.link_url_input);
linkUrl.setOnClickListener(view1 -> linkUrl.setError(null));
TextInputLayout linkText = dialogBody.findViewById(R.id.link_text_input);
linkText.setOnClickListener(view2 -> linkText.setError(null));
hadTextSelection = editText.hasSelection();
int start = editText.getSelectionStart(), end = editText.getSelectionEnd();
if (editText.hasSelection()) {
linkText
.getEditText()
.setText(
editText
.getText()
.toString()
.substring(
editText.getSelectionStart(), editText.getSelectionEnd()));
}
AlertDialog linkDialog =
new AlertDialog.Builder(context, R.style.AppTheme_Dark_Dialog)
.setTitle(R.string.dialog_create_link_title)
.setView(dialogBody)
.setPositiveButton(R.string.ok, null)
.setNegativeButton(R.string.cancel, (dialog, which) -> dialog.dismiss())
.create();
linkDialog.setOnShowListener(
dialogInterface -> {
Button button = linkDialog.getButton(AlertDialog.BUTTON_POSITIVE);
button.setOnClickListener(
view12 -> {
if (TextUtils.isEmpty(
Objects.requireNonNull(linkUrl.getEditText())
.getText()
.toString())) {
linkUrl.setError(context.getString(R.string.input_field_required));
return;
}
if (hadTextSelection)
editText.getText().delete(start, end);
if (!TextUtils.isEmpty(linkText.getEditText().getText())) {
getText()
.insert(
editText.getSelectionStart(),
"[url="
+ linkUrl.getEditText().getText().toString()
+ "]"
+ linkText.getEditText().getText().toString()
+ "[/url]");
}
else
getText()
.insert(
editText.getSelectionStart(),
"[url]"
+ linkUrl.getEditText().getText().toString()
+ "[/url]");
linkDialog.dismiss();
});
});
linkDialog.show();
break;
case R.drawable.ic_format_quote:
hadTextSelection = editText.hasSelection();
getText().insert(editText.getSelectionStart(), "[quote]");
getText().insert(editText.getSelectionEnd(), "[/quote]");
editText.setSelection(
hadTextSelection
? editText.getSelectionEnd()
: editText.getSelectionStart() - 8);
break;
case R.drawable.ic_code:
hadTextSelection = editText.hasSelection();
getText().insert(editText.getSelectionStart(), "[code]");
getText().insert(editText.getSelectionEnd(), "[/code]");
editText.setSelection(
hadTextSelection
? editText.getSelectionEnd()
: editText.getSelectionStart() - 7);
break;
case R.drawable.ic_functions:
hadTextSelection = editText.hasSelection();
getText().insert(editText.getSelectionStart(), "[tex]");
getText().insert(editText.getSelectionEnd(), "[/tex]");
editText.setSelection(
hadTextSelection
? editText.getSelectionEnd()
: editText.getSelectionStart() - 6);
break;
default:
throw new IllegalArgumentException("Unknown format button click");
}
}));
emojiButton.setOnClickListener(view -> {
InputMethodManager imm = (InputMethodManager) context.getSystemService(Activity.INPUT_METHOD_SERVICE);
@ -402,7 +405,8 @@ public class EditorView extends LinearLayout implements EmojiInputField {
InputMethodManager imm = (InputMethodManager) getContext().getSystemService(Activity.INPUT_METHOD_SERVICE);
if (imm != null)
imm.showSoftInput(editText, InputMethodManager.SHOW_IMPLICIT);
} else {
}
else {
InputMethodManager imm = (InputMethodManager) getContext().getSystemService(Activity.INPUT_METHOD_SERVICE);
if (imm != null)
imm.hideSoftInputFromWindow(getWindowToken(), 0);
@ -414,19 +418,20 @@ public class EditorView extends LinearLayout implements EmojiInputField {
if (b) {
emojiKeyboard.onEmojiInputFieldFocused(EditorView.this);
showMarkdown();
} else hideMarkdown();
}
else hideMarkdown();
});
editText.setOnFocusChangeListener((view, b) -> {
if (b) {
emojiKeyboard.onEmojiInputFieldFocused(EditorView.this);
showMarkdown();
} else hideMarkdown();
}
else hideMarkdown();
});
}
/**
* Animates the hiding of the markdown options.
*
*/
public void hideMarkdown() {
if (formatButtonsRecyclerview.getVisibility() == GONE) return;
@ -459,7 +464,6 @@ public class EditorView extends LinearLayout implements EmojiInputField {
/**
* Animates the showing of the markdown options.
*
*/
public void showMarkdown() {
if (formatButtonsRecyclerview.getVisibility() == VISIBLE) return;
@ -523,7 +527,8 @@ public class EditorView extends LinearLayout implements EmojiInputField {
public void onKeyboardVisibilityChange(boolean visible) {
if (visible) {
emojiButton.setImageResource(R.drawable.ic_keyboard_24dp);
} else {
}
else {
emojiButton.setImageResource(R.drawable.ic_tag_faces_24dp);
}
}

1
app/src/main/java/gr/thmmy/mthmmy/views/editorview/EmojiInputField.java

@ -4,5 +4,6 @@ import android.view.inputmethod.InputConnection;
public interface EmojiInputField {
void onKeyboardVisibilityChange(boolean visible);
InputConnection getInputConnection();
}

9
app/src/main/java/gr/thmmy/mthmmy/views/editorview/FormatButtonsAdapter.java

@ -14,10 +14,10 @@ public class FormatButtonsAdapter extends RecyclerView.Adapter<FormatButtonsAdap
private OnFormatButtonClickListener listener;
public static final int[] FORMAT_BUTTON_IDS = {R.drawable.ic_format_bold, R.drawable.ic_format_italic,
R.drawable.ic_format_underlined, R.drawable.ic_strikethrough_s, R.drawable.ic_format_color_text,
R.drawable.ic_format_size, R.drawable.ic_text_format, R.drawable.ic_format_list_bulleted,
R.drawable.ic_format_align_left, R.drawable.ic_format_align_center, R.drawable.ic_format_align_right,
R.drawable.ic_insert_link, R.drawable.ic_format_quote, R.drawable.ic_code, R.drawable.ic_functions};
R.drawable.ic_format_underlined, R.drawable.ic_strikethrough_s, R.drawable.ic_format_color_text,
R.drawable.ic_format_size, R.drawable.ic_text_format, R.drawable.ic_format_list_bulleted,
R.drawable.ic_format_align_left, R.drawable.ic_format_align_center, R.drawable.ic_format_align_right,
R.drawable.ic_insert_link, R.drawable.ic_format_quote, R.drawable.ic_code, R.drawable.ic_functions};
public FormatButtonsAdapter(OnFormatButtonClickListener listener) {
this.listener = listener;
@ -45,6 +45,7 @@ public class FormatButtonsAdapter extends RecyclerView.Adapter<FormatButtonsAdap
static class FormatButtonViewHolder extends RecyclerView.ViewHolder {
AppCompatImageButton formatButton;
FormatButtonViewHolder(AppCompatImageButton formatButton) {
super(formatButton);
this.formatButton = formatButton;

4
app/src/main/java/gr/thmmy/mthmmy/views/editorview/IEmojiKeyboard.java

@ -8,24 +8,28 @@ public interface IEmojiKeyboard {
/**
* Check if keyboard is visible
*
* @return true, if {@link EmojiKeyboard#getVisibility()} returns View.VISIBLE, otherwise false
*/
boolean isVisible();
/**
* Callback to the keyboard when {@link EditorView#emojiButton} is clicked
*
* @return whether the keyboard became visible or not
*/
boolean onEmojiButtonToggle();
/**
* Callback to create input connection with {@link EmojiInputField}
*
* @param emojiInputField the connected input field
*/
void onEmojiInputFieldFocused(EmojiInputField emojiInputField);
/**
* Persist a set of all input fields to update all of them when visibility changes
*
* @param emojiInputField the input field to be added
*/
void registerEmojiInputField(EmojiInputField emojiInputField);

2
app/src/main/res/anim/push_left_in.xml

@ -3,6 +3,6 @@
<translate
android:duration="500"
android:fromXDelta="100%p"
android:toXDelta="0"/>
android:toXDelta="0" />
</set>

2
app/src/main/res/anim/push_left_out.xml

@ -3,5 +3,5 @@
<translate
android:duration="500"
android:fromXDelta="0"
android:toXDelta="-100%p"/>
android:toXDelta="-100%p" />
</set>

2
app/src/main/res/anim/push_right_in.xml

@ -3,6 +3,6 @@
<translate
android:duration="500"
android:fromXDelta="-100%p"
android:toXDelta="0"/>
android:toXDelta="0" />
</set>

2
app/src/main/res/anim/push_right_out.xml

@ -3,6 +3,6 @@
<translate
android:duration="500"
android:fromXDelta="0"
android:toXDelta="100%p"/>
android:toXDelta="100%p" />
</set>

8
app/src/main/res/drawable/guest_button_border_bg.xml

@ -1,13 +1,13 @@
<?xml version="1.0" encoding="UTF-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android">
<solid android:color="@null"/>
<solid android:color="@null" />
<stroke
android:width="1dip"
android:color="@color/accent"/>
<corners android:radius="5dip"/>
android:color="@color/accent" />
<corners android:radius="5dip" />
<padding
android:bottom="0dip"
android:left="0dip"
android:right="0dip"
android:top="0dip"/>
android:top="0dip" />
</shape>

13
app/src/main/res/drawable/ic_access_time_white_24dp.xml

@ -1,5 +1,10 @@
<vector android:height="24dp" android:tint="#FFFFFF"
android:viewportHeight="24.0" android:viewportWidth="24.0"
android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android">
<path android:fillColor="#FF000000" android:pathData="M11.99,2C6.47,2 2,6.48 2,12s4.47,10 9.99,10C17.52,22 22,17.52 22,12S17.52,2 11.99,2zM12,20c-4.42,0 -8,-3.58 -8,-8s3.58,-8 8,-8 8,3.58 8,8 -3.58,8 -8,8zM12.5,7H11v6l5.25,3.15 0.75,-1.23 -4.5,-2.67z"/>
<vector android:height="24dp"
android:tint="#FFFFFF"
android:viewportHeight="24.0"
android:viewportWidth="24.0"
android:width="24dp"
xmlns:android="http://schemas.android.com/apk/res/android">
<path
android:fillColor="#FF000000"
android:pathData="M11.99,2C6.47,2 2,6.48 2,12s4.47,10 9.99,10C17.52,22 22,17.52 22,12S17.52,2 11.99,2zM12,20c-4.42,0 -8,-3.58 -8,-8s3.58,-8 8,-8 8,3.58 8,8 -3.58,8 -8,8zM12.5,7H11v6l5.25,3.15 0.75,-1.23 -4.5,-2.67z" />
</vector>

10
app/src/main/res/drawable/ic_add_fab.xml

@ -1,9 +1,9 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportWidth="24.0"
android:viewportHeight="24.0">
android:width="24dp"
android:height="24dp"
android:viewportWidth="24.0"
android:viewportHeight="24.0">
<path
android:fillColor="#FFFFFF"
android:pathData="M19,13h-6v6h-2v-6H5v-2h6V5h2v6h6v2z"/>
android:pathData="M19,13h-6v6h-2v-6H5v-2h6V5h2v6h6v2z" />
</vector>

13
app/src/main/res/drawable/ic_announcement.xml

@ -1,7 +1,12 @@
<vector android:height="24dp" android:viewportHeight="297"
android:viewportWidth="297" android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android"
<vector android:height="24dp"
android:viewportHeight="297"
android:viewportWidth="297"
android:width="24dp"
xmlns:android="http://schemas.android.com/apk/res/android"
android:tint="#FFFFFF">
<path android:fillColor="#FF000000"
<path
android:fillColor="#FF000000"
android:pathData="M282.82,107.559h-25.792V10.025c0,-4.056 -2.443,-7.711 -6.19,-9.261c-3.745,-1.555 -8.059,-0.693 -10.925,2.177C195.46,47.434 157.039,68.643 132.635,78.6C106.33,89.333 90.261,89.635 90.159,89.637H14.18c-5.536,0 -10.023,4.488 -10.023,10.024v89.631c0,5.536 4.487,10.023 10.023,10.023h10.2l37.887,91.497c1.551,3.746 5.206,6.189 9.261,6.189h55.538c0.006,-0.001 0.012,-0.001 0.02,0c5.536,0 10.023,-4.488 10.023,-10.023c0,-1.588 -0.37,-3.09 -1.025,-4.424l-33.809,-81.646c22.4,4.443 73.884,21.285 137.641,85.1c1.917,1.921 4.483,2.939 7.094,2.939c0.055,0 0.109,0 0.164,0c5.468,-0.079 9.877,-4.536 9.877,-10.023c0,-0.214 -0.006,-0.428 -0.02,-0.639l-0.002,-96.896h25.792c5.536,0 10.023,-4.488 10.023,-10.024v-53.779C292.844,112.048 288.356,107.559 282.82,107.559zM24.204,109.683h55.932v69.584H24.204V109.683zM78.226,276.952l-31.139,-75.196h33.839l31.138,75.196H78.226zM100.183,180.201v-71.452c20.889,-3.123 72.28,-16.674 136.797,-75.301v84.121v0.015v53.779c0,0.008 0,0.017 0,0.025l0.002,84.111C172.466,196.876 121.072,183.326 100.183,180.201zM272.796,161.34h-15.768v-33.732h15.768V161.34z"
android:strokeColor="#000000" android:strokeWidth="1"/>
android:strokeColor="#000000"
android:strokeWidth="1" />
</vector>

Some files were not shown because too many files changed in this diff

Loading…
Cancel
Save