Browse Source

Version 2.1.0

master v2.1.0
Ezerous 2 years ago
parent
commit
51343cc918
  1. 10
      app/build.gradle
  2. 3
      app/src/main/AndroidManifest.xml
  3. 14
      app/src/main/assets/style.css
  4. 17
      app/src/main/java/gr/thmmy/mthmmy/activities/board/BoardActivity.java
  5. 85
      app/src/main/java/gr/thmmy/mthmmy/activities/board/BoardAdapter.java
  6. 13
      app/src/main/java/gr/thmmy/mthmmy/activities/bookmarks/BookmarksActivity.java
  7. 28
      app/src/main/java/gr/thmmy/mthmmy/activities/bookmarks/BookmarksFragment.java
  8. 7
      app/src/main/java/gr/thmmy/mthmmy/activities/topic/TopicActivity.java
  9. 2
      app/src/main/java/gr/thmmy/mthmmy/activities/topic/tasks/TopicTask.java
  10. 60
      app/src/main/java/gr/thmmy/mthmmy/activities/upload/UploadActivity.java
  11. 71
      app/src/main/java/gr/thmmy/mthmmy/activities/upload/UploadsHelper.java
  12. 10
      app/src/main/java/gr/thmmy/mthmmy/base/BaseActivity.java
  13. 2
      app/src/main/java/gr/thmmy/mthmmy/base/BaseApplication.java
  14. 9
      app/src/main/java/gr/thmmy/mthmmy/services/NotificationService.java
  15. 6
      app/src/main/java/gr/thmmy/mthmmy/services/UploadsReceiver.java
  16. 2
      app/src/main/res/drawable/ic_notification_off.xml
  17. 6
      app/src/main/res/layout/activity_upload_file_list_row.xml
  18. 8
      app/src/main/res/layout/fragment_bookmarks.xml
  19. 93
      app/src/main/res/layout/fragment_bookmarks_row.xml
  20. 5
      app/src/main/res/values/strings.xml

10
app/build.gradle

@ -7,15 +7,15 @@ apply plugin: 'com.google.gms.google-services'
apply plugin: 'com.google.firebase.crashlytics'
android {
compileSdkVersion 30
compileSdkVersion 31
buildToolsVersion = '30.0.2'
defaultConfig {
applicationId "gr.thmmy.mthmmy"
minSdkVersion 21
targetSdkVersion 30
versionCode 30
versionName "2.0.0"
versionCode 31
versionName "2.1.0"
archivesBaseName = "mTHMMY-v$versionName"
buildConfigField "String", "CURRENT_BRANCH", "\"" + getCurrentBranch() + "\""
buildConfigField "String", "COMMIT_HASH", "\"" + getCommitHash() + "\""
@ -76,14 +76,14 @@ tasks.whenTaskAdded { task ->
dependencies {
implementation fileTree(dir: 'libs', include: ['*.jar'])
implementation project(":emojis")
implementation 'androidx.appcompat:appcompat:1.4.0-alpha03'
implementation 'androidx.appcompat:appcompat:1.4.1'
implementation 'androidx.preference:preference:1.1.1'
implementation 'androidx.legacy:legacy-preference-v14:1.0.0'
implementation 'androidx.legacy:legacy-support-v4:1.0.0'
implementation 'androidx.cardview:cardview:1.0.0'
implementation 'androidx.recyclerview:recyclerview:1.2.1'
implementation 'androidx.lifecycle:lifecycle-extensions:2.2.0'
implementation 'androidx.constraintlayout:constraintlayout:2.1.0'
implementation 'androidx.constraintlayout:constraintlayout:2.1.3'
implementation 'androidx.exifinterface:exifinterface:1.3.3'
implementation 'com.google.android.material:material:1.4.0'
implementation platform('com.google.firebase:firebase-bom:28.4.0')

3
app/src/main/AndroidManifest.xml

@ -7,8 +7,8 @@
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.WAKE_LOCK" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.WAKE_LOCK" />
<uses-permission android:name="android.permission.DOWNLOAD_WITHOUT_NOTIFICATION" />
<uses-permission android:name="android.permission.FOREGROUND_SERVICE" />
@ -41,6 +41,7 @@
android:configChanges="orientation|screenSize"
android:label="@string/app_name"
android:launchMode="singleTask"
android:exported="true"
android:theme="@style/AppTheme.NoActionBar">
<intent-filter>
<action android:name="android.intent.action.MAIN" />

14
app/src/main/assets/style.css

@ -188,7 +188,7 @@ a img {
margin: 1px;
padding: 1px;
font-size: x-small;
line-height: 1.4em;
line-height: 1.4;
}
@ -199,7 +199,7 @@ a img {
background-color: #626566;
font-family: "Comic Sans MS", "times new roman", monospace;
font-size: x-small;
line-height: 1.3em;
line-height: 1.3;
/* Put a nice border around it. */
border: 1px solid #FFFFFF;
margin: 1px auto 1px auto;
@ -223,7 +223,7 @@ a img {
font-style: normal;
font-weight: bold;
font-size: x-small;
line-height: 1.2em;
line-height: 1.2;
}
@ -361,7 +361,7 @@ tr.titlebg2 td,
.personalmessage {
width: 100%;
overflow: auto;
line-height: 1.3em;
line-height: 1.3;
color: white;
background: #3C3F41 !important;
}
@ -373,7 +373,7 @@ tr.titlebg2 td,
width: 100%;
overflow: auto;
padding-bottom: 3px;
line-height: 1.3em;
line-height: 1.3;
}
#left {
@ -597,3 +597,7 @@ span[style="background-color: yellow;"] {
[style="color: white;"]>span[style="background-color: yellow;"] {
color: white !important;
}
span[style*="line-height: 1.3em;"] {
line-height: 1.3 !important;
}

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

@ -250,7 +250,6 @@ public class BoardActivity extends BaseActivity implements BoardAdapter.OnLoadMo
if (pStats.equals("--"))
pStats = "";
}
else if (Objects.equals(subBoardCol.className(), "smalltext")) {
pLastPost = subBoardCol.text();
if (pLastPost.contains(" in ") || pLastPost.contains(" σε ")) {
@ -281,7 +280,6 @@ public class BoardActivity extends BaseActivity implements BoardAdapter.OnLoadMo
parsingFailed = true;
break;
}
}
else if (pLastPost.contains("redirected clicks") || pLastPost.contains("N/A"))
pLastPost = "";
@ -289,10 +287,17 @@ public class BoardActivity extends BaseActivity implements BoardAdapter.OnLoadMo
pLastPost = "No posts yet";
}
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();
Element subBoardTitleElement = subBoardCol.select("a").first();
if (subBoardTitleElement != null) {
pUrl = subBoardTitleElement.attr("href");
pTitle = subBoardTitleElement.text();
if (subBoardCol.select("div.smalltext").first() != null)
pMods = subBoardCol.select("div.smalltext").first().text();
}
else {
parsingFailed = true;
break;
}
}
}
if (!parsingFailed)

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

@ -32,11 +32,9 @@ import static gr.thmmy.mthmmy.activities.topic.TopicActivity.BUNDLE_TOPIC_URL;
* {@link RecyclerView.Adapter} that can display a {@link gr.thmmy.mthmmy.model.Board}.
*/
class BoardAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> {
private final int VIEW_TYPE_SUB_BOARD_TITLE = 0;
private final int VIEW_TYPE_SUB_BOARD = 1;
private final int VIEW_TYPE_TOPIC_TITLE = 2;
private final int VIEW_TYPE_TOPIC = 3;
private final int VIEW_TYPE_LOADING = 4;
private final int VIEW_TYPE_SUB_BOARD = 0;
private final int VIEW_TYPE_TOPIC = 1;
private final int VIEW_TYPE_LOADING = 2;
private final Context context;
private ArrayList<Board> parsedSubBoards;
@ -56,13 +54,11 @@ class BoardAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> {
@Override
public int getItemViewType(int position) {
if (position <= parsedSubBoards.size()) {
if (position == 0) return VIEW_TYPE_SUB_BOARD_TITLE;
if (position < parsedSubBoards.size()) {
return VIEW_TYPE_SUB_BOARD;
}
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)
else if (position < parsedSubBoards.size() + parsedTopics.size()) {
if (parsedTopics.get(position - parsedSubBoards.size()) != null) //??
return VIEW_TYPE_TOPIC;
}
return VIEW_TYPE_LOADING;
@ -70,52 +66,11 @@ class BoardAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> {
@Override
public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
if (viewType == VIEW_TYPE_SUB_BOARD_TITLE) {
TextView subBoardTitle = new TextView(context);
subBoardTitle.setLayoutParams(new LinearLayout.LayoutParams(
LinearLayout.LayoutParams.MATCH_PARENT
, LinearLayout.LayoutParams.WRAP_CONTENT));
subBoardTitle.setText(context.getString(R.string.child_board_title));
subBoardTitle.setTypeface(subBoardTitle.getTypeface(), Typeface.BOLD);
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 {
//noinspection deprecation
subBoardTitle.setBackgroundColor(context.getResources().getColor(R.color.background_light));
//noinspection deprecation
subBoardTitle.setTextColor(context.getResources().getColor(R.color.accent));
}
subBoardTitle.setTextAlignment(View.TEXT_ALIGNMENT_CENTER);
subBoardTitle.setTextSize(20f);
return new TitlesViewHolder(subBoardTitle);
}
else if (viewType == VIEW_TYPE_SUB_BOARD) {
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) {
TextView topicTitle = new TextView(context);
topicTitle.setLayoutParams(new LinearLayout.LayoutParams(
LinearLayout.LayoutParams.MATCH_PARENT
, LinearLayout.LayoutParams.WRAP_CONTENT));
topicTitle.setText(context.getString(R.string.topic_title));
topicTitle.setTypeface(topicTitle.getTypeface(), Typeface.BOLD);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
topicTitle.setTextColor(context.getColor(R.color.primary_text));
}
else {
//noinspection deprecation
topicTitle.setTextColor(context.getResources().getColor(R.color.primary_text));
}
topicTitle.setTextAlignment(View.TEXT_ALIGNMENT_CENTER);
topicTitle.setTextSize(20f);
return new TitlesViewHolder(topicTitle);
}
else if (viewType == VIEW_TYPE_TOPIC) {
View topic = LayoutInflater.from(parent.getContext()).
inflate(R.layout.activity_board_topic_row, parent, false);
@ -132,7 +87,7 @@ class BoardAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> {
@Override
public void onBindViewHolder(final RecyclerView.ViewHolder holder, final int position) {
if (holder instanceof SubBoardViewHolder) {
final Board subBoard = parsedSubBoards.get(position - 1);
final Board subBoard = parsedSubBoards.get(position);
final SubBoardViewHolder subBoardViewHolder = (SubBoardViewHolder) holder;
if (boardExpandableVisibility.size() != parsedSubBoards.size()) {
@ -149,7 +104,7 @@ class BoardAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> {
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
context.startActivity(intent);
});
if (boardExpandableVisibility.get(subBoardViewHolder.getAdapterPosition() - 1)) {
if (boardExpandableVisibility.get(subBoardViewHolder.getAdapterPosition())) {
subBoardViewHolder.boardExpandable.setVisibility(View.VISIBLE);
subBoardViewHolder.showHideExpandable.setImageResource(R.drawable.ic_arrow_drop_up_accent_24dp);
}
@ -158,7 +113,7 @@ class BoardAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> {
subBoardViewHolder.showHideExpandable.setImageResource(R.drawable.ic_arrow_drop_down_accent_24dp);
}
subBoardViewHolder.showHideExpandable.setOnClickListener(view -> {
final boolean visible = boardExpandableVisibility.get(subBoardViewHolder.getAdapterPosition() - 1);
final boolean visible = boardExpandableVisibility.get(subBoardViewHolder.getAdapterPosition());
if (visible) {
subBoardViewHolder.boardExpandable.setVisibility(View.GONE);
subBoardViewHolder.showHideExpandable.setImageResource(R.drawable.ic_arrow_drop_down_accent_24dp);
@ -167,7 +122,7 @@ class BoardAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> {
subBoardViewHolder.boardExpandable.setVisibility(View.VISIBLE);
subBoardViewHolder.showHideExpandable.setImageResource(R.drawable.ic_arrow_drop_up_accent_24dp);
}
boardExpandableVisibility.set(subBoardViewHolder.getAdapterPosition() - 1, !visible);
boardExpandableVisibility.set(subBoardViewHolder.getAdapterPosition(), !visible);
});
subBoardViewHolder.boardTitle.setText(subBoard.getTitle());
String mods = subBoard.getMods();
@ -202,7 +157,7 @@ class BoardAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> {
}
}
else if (holder instanceof TopicViewHolder) {
final Topic topic = parsedTopics.get(position - parsedSubBoards.size() - 1 - 1);
final Topic topic = parsedTopics.get(position - parsedSubBoards.size());
final TopicViewHolder topicViewHolder = (TopicViewHolder) holder;
if (topicExpandableVisibility.size() != parsedTopics.size()) {
@ -220,7 +175,7 @@ class BoardAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> {
context.startActivity(intent);
});
if (topicExpandableVisibility.get(topicViewHolder.getAdapterPosition() - parsedSubBoards
.size() - 2)) {
.size())) {
topicViewHolder.topicExpandable.setVisibility(View.VISIBLE);
topicViewHolder.showHideExpandable.setImageResource(R.drawable.ic_arrow_drop_up_accent_24dp);
}
@ -230,7 +185,7 @@ class BoardAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> {
}
topicViewHolder.showHideExpandable.setOnClickListener(view -> {
final boolean visible = topicExpandableVisibility.get(topicViewHolder.
getAdapterPosition() - parsedSubBoards.size() - 2);
getAdapterPosition() - parsedSubBoards.size());
if (visible) {
topicViewHolder.topicExpandable.setVisibility(View.GONE);
topicViewHolder.showHideExpandable.setImageResource(R.drawable.ic_arrow_drop_down_accent_24dp);
@ -240,7 +195,7 @@ class BoardAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> {
topicViewHolder.showHideExpandable.setImageResource(R.drawable.ic_arrow_drop_up_accent_24dp);
}
topicExpandableVisibility.set(topicViewHolder.getAdapterPosition() -
parsedSubBoards.size() - 2, !visible);
parsedSubBoards.size(), !visible);
});
topicViewHolder.topicSubject.setTypeface(Typeface.createFromAsset(context.getAssets()
, "fonts/fontawesome-webfont.ttf"));
@ -280,8 +235,8 @@ class BoardAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> {
@Override
public int getItemCount() {
int items = 0;
if (parsedSubBoards != null) items += parsedSubBoards.size() + 1;
if (parsedTopics != null) items += parsedTopics.size() + 1;
if (parsedSubBoards != null) items += parsedSubBoards.size();
if (parsedTopics != null) items += parsedTopics.size();
return items;
}
@ -320,12 +275,6 @@ class BoardAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> {
}
}
private static class TitlesViewHolder extends RecyclerView.ViewHolder {
TitlesViewHolder(View title) {
super(title);
}
}
private static class LoadingViewHolder extends RecyclerView.ViewHolder {
final MaterialProgressBar progressBar;

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

@ -89,7 +89,9 @@ public class BookmarksActivity extends BaseActivity {
startActivity(intent);
break;
case BookmarksFragment.INTERACTION_TOGGLE_TOPIC_NOTIFICATION:
return toggleNotification(bookmarkedTopic);
boolean notificationsEnabled = toggleNotification(bookmarkedTopic);
displayNotificationsToggleToast(notificationsEnabled);
return notificationsEnabled;
case BookmarksFragment.INTERACTION_REMOVE_TOPIC_BOOKMARK:
removeBookmark(bookmarkedTopic);
Toast.makeText(BaseApplication.getInstance().getApplicationContext(), "Bookmark removed", Toast.LENGTH_SHORT).show();
@ -112,7 +114,9 @@ public class BookmarksActivity extends BaseActivity {
startActivity(intent);
break;
case BookmarksFragment.INTERACTION_TOGGLE_BOARD_NOTIFICATION:
return toggleNotification(bookmarkedBoard);
boolean notificationsEnabled = toggleNotification(bookmarkedBoard);
displayNotificationsToggleToast(notificationsEnabled);
return notificationsEnabled;
case BookmarksFragment.INTERACTION_REMOVE_BOARD_BOOKMARK:
removeBookmark(bookmarkedBoard);
Toast.makeText(getApplicationContext(), "Bookmark removed", Toast.LENGTH_SHORT).show();
@ -123,6 +127,11 @@ public class BookmarksActivity extends BaseActivity {
return true;
}
private void displayNotificationsToggleToast (boolean notificationsEnabled){
String toastText = notificationsEnabled ? "Notifications enabled" : "Notifications disabled";
Toast.makeText(BaseApplication.getInstance().getApplicationContext(), toastText, Toast.LENGTH_SHORT).show();
}
/**
* A {@link FragmentPagerAdapter} that returns a fragment corresponding to
* one of the sections/tabs/pages. If it becomes too memory intensive,

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

@ -1,6 +1,7 @@
package gr.thmmy.mthmmy.activities.bookmarks;
import android.app.Activity;
import android.content.Intent;
import android.graphics.drawable.Drawable;
import android.os.Bundle;
import android.view.LayoutInflater;
@ -11,11 +12,14 @@ import android.widget.LinearLayout;
import android.widget.TextView;
import androidx.annotation.NonNull;
import androidx.appcompat.app.AlertDialog;
import androidx.fragment.app.Fragment;
import java.util.ArrayList;
import gr.thmmy.mthmmy.R;
import gr.thmmy.mthmmy.activities.LoginActivity;
import gr.thmmy.mthmmy.activities.board.BoardActivity;
import gr.thmmy.mthmmy.model.Bookmark;
//TODO refactor using RecyclerView
@ -83,10 +87,8 @@ public class BookmarksFragment extends Fragment {
}
}
notificationsEnabledButtonImage = getResources().getDrawable(R.drawable.ic_notification_on, null);
notificationsDisabledButtonImage = getResources().getDrawable(R.drawable.ic_notification_off, null);
}
@Override
@ -104,7 +106,7 @@ public class BookmarksFragment extends Fragment {
if (bookmark != null && bookmark.getTitle() != null) {
final LinearLayout row = (LinearLayout) layoutInflater.inflate(
R.layout.fragment_bookmarks_row, bookmarksLinearView, false);
row.setOnClickListener(view -> {
row.findViewById(R.id.bookmark_card).setOnClickListener(view -> {
Activity activity = getActivity();
if (activity instanceof BookmarksActivity)
((BookmarksActivity) activity).onFragmentRowInteractionListener(type, interactionClick, bookmark);
@ -129,13 +131,19 @@ public class BookmarksFragment extends Fragment {
(row.findViewById(R.id.remove_bookmark)).setOnClickListener(view -> {
Activity activity = getActivity();
if (activity instanceof BookmarksActivity) {
((BookmarksActivity) activity).onFragmentRowInteractionListener(type, interactionRemove, bookmark);
bookmarks.remove(bookmark);
}
row.setVisibility(View.GONE);
if (bookmarks.isEmpty()) {
showNothingBookmarked();
new AlertDialog.Builder(activity)
.setMessage("Are you sure that you want to remove this bookmark?")
.setPositiveButton("Yes", (dialogInterface, i) -> {
((BookmarksActivity) activity).onFragmentRowInteractionListener(type, interactionRemove, bookmark);
bookmarks.remove(bookmark);
row.setVisibility(View.GONE);
if (bookmarks.isEmpty()) {
showNothingBookmarked();
}
})
.setNegativeButton("No", (dialogInterface, i) -> {
})
.show();
}
});
bookmarksLinearView.addView(row);

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

@ -633,8 +633,11 @@ public class TopicActivity extends BaseActivity implements TopicAdapter.OnPostFo
else {
Timber.i("Post edit unsuccessful");
Toast.makeText(BaseApplication.getInstance().getApplicationContext(), "Edit failed!", Toast.LENGTH_SHORT).show();
recyclerView.getChildAt(viewModel.getPostBeingEditedPosition()).setAlpha(1);
recyclerView.getChildAt(viewModel.getPostBeingEditedPosition()).setEnabled(true);
View postBeingEditedView = recyclerView.getChildAt(viewModel.getPostBeingEditedPosition());
if (postBeingEditedView != null) {
postBeingEditedView.setAlpha(1);
postBeingEditedView.setEnabled(true);
}
}
}
});

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

@ -125,7 +125,7 @@ public class TopicTask extends AsyncTask<String, Void, TopicTaskResult> {
0, 0, 0, 0, null, null);
}
else {
Timber.e(e, "Topic parse failed");
Timber.e(e, "Topic parsing failed (%s)!", newPageUrl);
return new TopicTaskResult(ResultCode.PARSING_ERROR, null, null, null,
0, 0, 0, 0, null, null);
}

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

@ -10,6 +10,7 @@ import android.graphics.Typeface;
import android.graphics.drawable.Drawable;
import android.net.Uri;
import android.os.AsyncTask;
import android.os.Build;
import android.os.Bundle;
import android.text.Editable;
import android.text.Spannable;
@ -327,30 +328,20 @@ public class UploadActivity extends BaseActivity {
//File should be uploaded with a different name
if (checkPerms()) {
if (!uploadFile.isCameraPhoto()) {
//Temporarily copies the file to a another location and renames it
tempFileUri = UploadsHelper.createTempFile(this, storage,
uploadFile.getFileUri(),
FileUtils.getFilenameWithoutExtension(editTextFilename));
}
else {
//Renames the photo taken
String photoPath = uploadFile.getPhotoFile().getPath();
photoPath = photoPath.substring(0, photoPath.lastIndexOf(File.separator));
String destinationFilename = photoPath + File.separator +
FileUtils.getFilenameWithoutExtension(editTextFilename) + ".jpg";
if (!storage.rename(uploadFile.getPhotoFile().getAbsolutePath(), destinationFilename)) {
//Something went wrong, abort
Toast.makeText(BaseApplication.getInstance().getApplicationContext(), "Could not create temporary file for renaming", Toast.LENGTH_SHORT).show();
progressBar.setVisibility(View.GONE);
return;
}
//Points photoFile and fileUri to the new copied and renamed file
uploadFile.setPhotoFile(storage.getFile(destinationFilename));
uploadFile.setFileUri(FileProvider.getUriForFile(this, getPackageName() +
".provider", uploadFile.getPhotoFile()));
String newFileName = FileUtils.getFilenameWithoutExtension(editTextFilename);
if(uploadFile.isCameraPhoto())
newFileName = newFileName + ".jpg";
//Temporarily copies the file to another location (external cache) and renames it
tempFileUri = UploadsHelper.createTempFile(this, storage,
uploadFile.getFileUri(),
newFileName);
//Something went wrong while creating temporary file, abort
if(tempFileUri == null){
progressBar.setVisibility(View.GONE);
return;
}
}
else {
@ -561,7 +552,7 @@ public class UploadActivity extends BaseActivity {
UploadFile newFile = new UploadFile(true, TakePhoto.processResult(this,
photoFileCreated), photoFileCreated);
addFileViewToList(FileUtils.getFilenameWithoutExtension(FileUtils.
filenameFromUri(this, newFile.getFileUri())));
filenameFromUri(this, newFile.getFileUri())) + ".jpg");
filesList.add(newFile);
}
else if (requestCode == AFR_REQUEST_CODE_FIELDS_BUILDER) {
@ -596,6 +587,10 @@ public class UploadActivity extends BaseActivity {
case UPLOAD_REQUEST_CAMERA_CODE:
if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED)
takePhoto();
else {
Timber.w("Take photo failed (permission denied).");
Toast.makeText(BaseApplication.getInstance().getApplicationContext(), "Take photo failed (storage permission denied)", Toast.LENGTH_SHORT).show();
}
break;
case UPLOAD_REQUEST_STORAGE_CODE:
if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED &&
@ -609,6 +604,7 @@ public class UploadActivity extends BaseActivity {
finish();
}
else {
Timber.w("Zip task failed (permission denied).");
Toast.makeText(BaseApplication.getInstance().getApplicationContext(), "Please retry uploading.", Toast.LENGTH_SHORT).show();
}
break;
@ -720,17 +716,23 @@ public class UploadActivity extends BaseActivity {
cancelIntent.setAction(UploadsReceiver.ACTION_CANCEL_UPLOAD);
cancelIntent.putExtra(UploadsReceiver.UPLOAD_ID_KEY, uploadID);
int pendingIntentFlags;
if (android.os.Build.VERSION.SDK_INT >= Build.VERSION_CODES.S)
pendingIntentFlags = PendingIntent.FLAG_MUTABLE |PendingIntent.FLAG_UPDATE_CURRENT;
else
pendingIntentFlags = PendingIntent.FLAG_UPDATE_CURRENT;
uploadNotificationConfig.getProgress().actions.add(new UploadNotificationAction(
R.drawable.ic_cancel_accent_24dp,
context.getString(R.string.cancel),
PendingIntent.getBroadcast(context, 0, cancelIntent,
PendingIntent.FLAG_UPDATE_CURRENT)
pendingIntentFlags)
));
uploadNotificationConfig.getError().actions.add(new UploadNotificationAction(
R.drawable.ic_notification,
context.getString(R.string.upload_retry),
PendingIntent.getBroadcast(context, 0, retryIntent,
PendingIntent.FLAG_UPDATE_CURRENT)
pendingIntentFlags)
));
return uploadNotificationConfig;
@ -1069,7 +1071,7 @@ public class UploadActivity extends BaseActivity {
@Override
protected void onPreExecute() {
assert weakActivity != null;
Toast.makeText(BaseApplication.getInstance().getApplicationContext(), "Zipping files", Toast.LENGTH_SHORT).show();
Toast.makeText(BaseApplication.getInstance().getApplicationContext(), "Zipping files...", Toast.LENGTH_SHORT).show();
}
@Override
@ -1077,7 +1079,7 @@ public class UploadActivity extends BaseActivity {
if (weakActivity == null || zipFilename == null)
return false;
File zipFile = UploadsHelper.createZipFile(zipFilename);
File zipFile = UploadsHelper.createZipFile(weakActivity.get(), zipFilename);
if (zipFile == null)
return false;

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

@ -2,7 +2,6 @@ package gr.thmmy.mthmmy.activities.upload;
import android.content.Context;
import android.net.Uri;
import android.os.Environment;
import android.widget.Toast;
import androidx.annotation.NonNull;
@ -27,24 +26,19 @@ import timber.log.Timber;
public class UploadsHelper {
private static final int BUFFER = 4096;
private static final String TEMP_FILES_DIRECTORY = "~tmp_mTHMMY_uploads";
@SuppressWarnings("ResultOfMethodCallIgnored")
@Nullable
static Uri createTempFile(Context context, Storage storage, Uri fileUri, String newFilename) {
Timber.i("Creating new temporary file (%s)", newFilename);
String oldFilename = FileUtils.filenameFromUri(context, fileUri);
String fileExtension = oldFilename.substring(oldFilename.indexOf('.'));
String destinationFilename = Environment.getExternalStorageDirectory().getPath() +
File.separatorChar + TEMP_FILES_DIRECTORY + File.separatorChar + newFilename + fileExtension;
File tempDirectory = new File(android.os.Environment.getExternalStorageDirectory().getPath() +
File.separatorChar + TEMP_FILES_DIRECTORY);
if (!tempDirectory.exists() && !tempDirectory.mkdirs()) {
Timber.w("Temporary directory build returned false in %s", UploadActivity.class.getSimpleName());
Toast.makeText(BaseApplication.getInstance().getApplicationContext(), "Couldn't create temporary directory", Toast.LENGTH_SHORT).show();
File tempFilesDirectory = createTempFilesDir(context);
if (tempFilesDirectory==null)
return null;
}
String destinationFilename = tempFilesDirectory.getAbsolutePath() + File.separatorChar + newFilename + fileExtension;
InputStream inputStream;
BufferedInputStream bufferedInputStream = null;
@ -53,7 +47,7 @@ public class UploadsHelper {
try {
inputStream = context.getContentResolver().openInputStream(fileUri);
if (inputStream == null) {
Timber.w("Input stream was null, %s", UploadActivity.class.getSimpleName());
Timber.e("Input stream was null, %s", UploadActivity.class.getSimpleName());
return null;
}
@ -81,20 +75,19 @@ public class UploadsHelper {
}
@Nullable
static File createZipFile(@NonNull String zipFilename) {
// Create a zip file name
File zipFolder = new File(Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOCUMENTS) +
File.separator + "mTHMMY");
static File createZipFile(Context context, @NonNull String zipFilename) {
// Create a zip file in temp directory
Timber.i("Creating temporary zip file %s", zipFilename);
if (!zipFolder.exists() && !zipFolder.mkdirs()) {
Timber.w("Zip folder build returned false in %s", UploadsHelper.class.getSimpleName());
File tempFilesDirectory = createTempFilesDir(context);
if (tempFilesDirectory==null)
return null;
}
return new File(zipFolder, zipFilename);
return new File(tempFilesDirectory, zipFilename);
}
static void zip(Context context, Uri[] files, Uri zipFile) {
Timber.i("Adding files to %s...", zipFile.getPath());
try {
BufferedInputStream origin;
OutputStream dest = context.getContentResolver().openOutputStream(zipFile);
@ -117,21 +110,45 @@ public class UploadsHelper {
origin.close();
}
Timber.i("Files added successfully to %s.", zipFile.getPath());
out.close();
} catch (Exception e) {
e.printStackTrace();
}
}
public static void deleteTempFiles(Storage storage) {
File tempFilesDirectory = new File(Environment.getExternalStorageDirectory().getPath() +
File.separatorChar + TEMP_FILES_DIRECTORY);
private static File createTempFilesDir(Context context){
File tempFilesDirectory = context.getExternalCacheDir();
if (tempFilesDirectory == null){
Timber.e("Temporary files directory error (%s)!", UploadActivity.class.getSimpleName());
Toast.makeText(BaseApplication.getInstance().getApplicationContext(), "Temporary files directory error (%s)!", Toast.LENGTH_SHORT).show();
return null;
}
if (storage.isDirectoryExists(tempFilesDirectory.getAbsolutePath())) {
for (File tempFile : storage.getFiles(tempFilesDirectory.getAbsolutePath())) {
storage.deleteFile(tempFile.getAbsolutePath());
if (!tempFilesDirectory.exists() && !tempFilesDirectory.mkdirs()) {
Timber.e("Temporary directory %s creation returned false (%s)", tempFilesDirectory.getAbsolutePath(), UploadActivity.class.getSimpleName());
Toast.makeText(BaseApplication.getInstance().getApplicationContext(), "Couldn't create temporary directory for file renaming!", Toast.LENGTH_SHORT).show();
return null;
}
return tempFilesDirectory;
}
public static void deleteTempFiles(Context context, Storage storage) {
File tempFilesDirectory = context.getExternalCacheDir();
if (tempFilesDirectory != null){
if (storage.isDirectoryExists(tempFilesDirectory.getAbsolutePath())) {
for (File tempFile : storage.getFiles(tempFilesDirectory.getAbsolutePath())) {
storage.deleteFile(tempFile.getAbsolutePath());
}
storage.deleteDirectory(tempFilesDirectory.getAbsolutePath());
Timber.i("Deleted temp files from cache.");
}
storage.deleteDirectory(tempFilesDirectory.getAbsolutePath());
}
else
Timber.e("Couldn't delete temp files!");
}
}

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

@ -694,6 +694,7 @@ public abstract class BaseActivity extends AppCompatActivity {
//True if permissions are OK
protected boolean checkPerms() {
if (Build.VERSION.SDK_INT > Build.VERSION_CODES.LOLLIPOP_MR1) {
Timber.i("Checking storage permissions.");
String[] PERMISSIONS_STORAGE = {
Manifest.permission.READ_EXTERNAL_STORAGE,
Manifest.permission.WRITE_EXTERNAL_STORAGE};
@ -705,12 +706,14 @@ public abstract class BaseActivity extends AppCompatActivity {
}
//Display popup for user to grant permission
protected void requestPerms(int code) { //Runtime permissions request for devices with API >= 23
protected void requestPerms(int code) {
//Runtime permissions request for devices with API >= 23
if (Build.VERSION.SDK_INT > Build.VERSION_CODES.LOLLIPOP_MR1) {
String[] PERMISSIONS_STORAGE = {
Manifest.permission.READ_EXTERNAL_STORAGE,
Manifest.permission.WRITE_EXTERNAL_STORAGE};
Timber.i("Requesting storage permissions (code %d).", code);
requestPermissions(PERMISSIONS_STORAGE, code);
}
}
@ -722,10 +725,13 @@ public abstract class BaseActivity extends AppCompatActivity {
if (permsRequestCode == DOWNLOAD_REQUEST_CODE) {
if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED)
prepareDownload(tempThmmyFile);
else {
Timber.w("Download failed (permission denied).");
Toast.makeText(BaseApplication.getInstance().getApplicationContext(), "Download failed (storage permission denied)", Toast.LENGTH_SHORT).show();
}
}
}
//----------------------------------DOWNLOAD----------------------
private ThmmyFile tempThmmyFile;

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

@ -147,7 +147,7 @@ public class BaseApplication extends Application implements Executor{
boolean updated = task.getResult();
Timber.i("Firebase remote config params updated: %s", updated);
} else
Timber.e("Fetching Firebase remote config params failed!");
Timber.w("Fetching Firebase remote config params failed!");
});
}

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

@ -178,8 +178,15 @@ public class NotificationService extends FirebaseMessagingService {
extras.putString(BUNDLE_TOPIC_TITLE, postNotification.getTopicTitle());
intent.putExtras(extras);
intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
int pendingIntentFlags;
if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.S)
pendingIntentFlags = PendingIntent.FLAG_IMMUTABLE |PendingIntent.FLAG_ONE_SHOT;
else
pendingIntentFlags = PendingIntent.FLAG_ONE_SHOT;
PendingIntent pendingIntent = PendingIntent.getActivity(this, requestCode++, intent,
PendingIntent.FLAG_ONE_SHOT);
pendingIntentFlags);
int notificationId;
String contentText;

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

@ -105,7 +105,7 @@ 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());
Toast.makeText(context.getApplicationContext(), "Upload completed successfully", Toast.LENGTH_SHORT).show();
Toast.makeText(context.getApplicationContext(), "Upload completed successfully!", Toast.LENGTH_SHORT).show();
BaseApplication.getInstance().logFirebaseAnalyticsEvent("file_upload", null);
}
else {
@ -118,7 +118,7 @@ public class UploadsReceiver extends UploadServiceBroadcastReceiver {
storage = new Storage(context.getApplicationContext());
}
UploadsHelper.deleteTempFiles(storage);
UploadsHelper.deleteTempFiles(context, storage);
}
@Override
@ -130,7 +130,7 @@ public class UploadsReceiver extends UploadServiceBroadcastReceiver {
storage = new Storage(context.getApplicationContext());
//cancelNotification(context, uploadInfo.getNotificationID());
UploadsHelper.deleteTempFiles(storage);
UploadsHelper.deleteTempFiles(context, storage);
}
public static void setDialogDisplay(AlertDialog uploadProgressDialog, String dialogUploadID,

2
app/src/main/res/drawable/ic_notification_off.xml

@ -6,4 +6,4 @@
<path
android:fillColor="#26A69A"
android:pathData="M12,22c1.1,0 2,-0.9 2,-2h-4c0,1.1 0.9,2 2,2zM18,16v-5c0,-3.07 -1.63,-5.64 -4.5,-6.32L13.5,4c0,-0.83 -0.67,-1.5 -1.5,-1.5s-1.5,0.67 -1.5,1.5v0.68C7.64,5.36 6,7.92 6,11v5l-2,2v1h16v-1l-2,-2zM16,17L8,17v-6c0,-2.48 1.51,-4.5 4,-4.5s4,2.02 4,4.5v6z" />
</vector>
</vector>

6
app/src/main/res/layout/activity_upload_file_list_row.xml

@ -3,7 +3,9 @@
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal">
android:orientation="horizontal"
android:paddingStart="8dp"
android:paddingEnd="0dp">
<androidx.appcompat.widget.AppCompatTextView
android:id="@+id/upload_file_item_text"
@ -11,6 +13,8 @@
android:layout_height="wrap_content"
android:layout_gravity="center"
android:layout_weight="1"
android:paddingTop="0dp"
android:paddingBottom="1dp"
android:ellipsize="marquee"
android:singleLine="true"
android:textColor="@color/primary_text" />

8
app/src/main/res/layout/fragment_bookmarks.xml

@ -9,7 +9,7 @@
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_gravity="top|start"
android:background="@color/primary_lighter"
android:background="@color/primary_lighter_2"
android:scrollbars="none"
app:layout_behavior="@string/appbar_scrolling_view_behavior">
@ -17,10 +17,8 @@
android:id="@+id/bookmarks_container"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
android:showDividers="middle"
android:divider="?android:listDivider"
android:dividerPadding="16dp" />
android:layout_margin="2dp"
android:orientation="vertical" />
</androidx.core.widget.NestedScrollView>
<TextView

93
app/src/main/res/layout/fragment_bookmarks_row.xml

@ -1,49 +1,62 @@
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:id="@+id/bookmark_row"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="?android:attr/selectableItemBackground"
android:clickable="true"
android:focusable="true"
android:gravity="center_vertical"
android:orientation="horizontal">
android:layout_height="wrap_content">
<TextView
android:id="@+id/bookmark_title"
android:layout_width="0dp"
<androidx.cardview.widget.CardView xmlns:card_view="http://schemas.android.com/apk/res-auto"
android:id="@+id/bookmark_card"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_weight="1"
android:paddingBottom="8dp"
android:paddingTop="6dp"
android:paddingStart="16dp"
android:paddingEnd="0dp"
android:textColor="@color/primary_text"
android:textSize="18sp" />
android:foreground="?android:attr/selectableItemBackground"
card_view:cardBackgroundColor="@color/background"
card_view:cardCornerRadius="5dp"
card_view:cardElevation="2dp"
card_view:cardPreventCornerOverlap="false"
card_view:cardUseCompatPadding="true"
android:clickable="true"
android:focusable="true">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center_vertical"
android:orientation="horizontal">
<ImageButton
android:id="@+id/toggle_notification"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:paddingBottom="3dp"
android:paddingTop="3dp"
android:paddingStart="6dp"
android:paddingEnd="6dp"
android:background="@android:color/transparent"
android:contentDescription="@string/toggle_notification"
app:srcCompat="@drawable/ic_notification_on" />
<TextView
android:id="@+id/bookmark_title"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:paddingBottom="8dp"
android:paddingTop="6dp"
android:paddingStart="16dp"
android:paddingEnd="0dp"
android:textColor="@color/primary_text"
android:textSize="18sp" />
<ImageButton
android:id="@+id/remove_bookmark"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:paddingBottom="3dp"
android:paddingTop="3dp"
android:paddingStart="6dp"
android:paddingEnd="6dp"
android:layout_marginEnd="12dp"
android:background="@android:color/transparent"
android:contentDescription="@string/remove_bookmark"
app:srcCompat="@drawable/ic_delete_accent_24dp" />
<ImageButton
android:id="@+id/toggle_notification"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:paddingBottom="3dp"
android:paddingTop="3dp"
android:paddingStart="6dp"
android:paddingEnd="6dp"
android:background="@android:color/transparent"
android:contentDescription="@string/toggle_notification"
app:srcCompat="@drawable/ic_notification_on" />
<ImageButton
android:id="@+id/remove_bookmark"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:paddingBottom="3dp"
android:paddingTop="3dp"
android:paddingStart="6dp"
android:paddingEnd="12dp"
android:background="@android:color/transparent"
android:contentDescription="@string/remove_bookmark"
app:srcCompat="@drawable/ic_delete_accent_24dp" />
</LinearLayout>
</androidx.cardview.widget.CardView>
</LinearLayout>

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

@ -95,9 +95,10 @@
<string name="epl_libraries"><u>Eclipse Public License v1.0 libraries</u></string>
<string name="other_libraries"><u>Other libraries</u></string>
<string name="contact">Contact</string>
<string name="contact_text">Do not hesitate to contact us for any matter either by email at thmmynolife@gmail.com, or by joining our discord server at https://discord.gg/CVt3yrn.</string>
<string name="contact_text">Do not hesitate to contact us for any technical matter, either by email at thmmynolife@gmail.com, or by joining our Discord server using https://discord.gg/CVt3yrn&#8203;.
For account-related issues, please contact the administration team of thmmy.gr by email at contact@thmmy.gr.</string>
<string name="open_source">Open Source</string>
<string name="open_source_text">The source code of mTHMMY can be found on Github (https://github.com/ThmmyNoLife/mTHMMY) along with further details of how one can contribute.</string>
<string name="open_source_text">The source code of mTHMMY can be found on Github at https://github.com/ThmmyNoLife/mTHMMY, along with further details of how one can contribute.</string>
<string name="trollPic">You should see a funny pic!</string>
<string name="privacy_policy">Privacy policy</string>

Loading…
Cancel
Save