diff --git a/app/build.gradle b/app/build.gradle
index 29faec1f..777af2d6 100644
--- a/app/build.gradle
+++ b/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')
diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml
index 9003cab6..7c7d5b18 100644
--- a/app/src/main/AndroidManifest.xml
+++ b/app/src/main/AndroidManifest.xml
@@ -7,8 +7,8 @@
-
+
@@ -41,6 +41,7 @@
android:configChanges="orientation|screenSize"
android:label="@string/app_name"
android:launchMode="singleTask"
+ android:exported="true"
android:theme="@style/AppTheme.NoActionBar">
diff --git a/app/src/main/assets/style.css b/app/src/main/assets/style.css
index 27c7f39f..6e6feb33 100644
--- a/app/src/main/assets/style.css
+++ b/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;
+}
diff --git a/app/src/main/java/gr/thmmy/mthmmy/activities/board/BoardActivity.java b/app/src/main/java/gr/thmmy/mthmmy/activities/board/BoardActivity.java
index 8c9820cb..3bed0b07 100644
--- a/app/src/main/java/gr/thmmy/mthmmy/activities/board/BoardActivity.java
+++ b/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)
diff --git a/app/src/main/java/gr/thmmy/mthmmy/activities/board/BoardAdapter.java b/app/src/main/java/gr/thmmy/mthmmy/activities/board/BoardAdapter.java
index 3594fe79..6468d130 100644
--- a/app/src/main/java/gr/thmmy/mthmmy/activities/board/BoardAdapter.java
+++ b/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 {
- 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 parsedSubBoards;
@@ -56,13 +54,11 @@ class BoardAdapter extends RecyclerView.Adapter {
@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 {
@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 {
@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 {
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 {
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 {
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 {
}
}
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 {
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 {
}
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 {
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 {
@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 {
}
}
- private static class TitlesViewHolder extends RecyclerView.ViewHolder {
- TitlesViewHolder(View title) {
- super(title);
- }
- }
-
private static class LoadingViewHolder extends RecyclerView.ViewHolder {
final MaterialProgressBar progressBar;
diff --git a/app/src/main/java/gr/thmmy/mthmmy/activities/bookmarks/BookmarksActivity.java b/app/src/main/java/gr/thmmy/mthmmy/activities/bookmarks/BookmarksActivity.java
index 7fbdf746..6ce16ec0 100644
--- a/app/src/main/java/gr/thmmy/mthmmy/activities/bookmarks/BookmarksActivity.java
+++ b/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,
diff --git a/app/src/main/java/gr/thmmy/mthmmy/activities/bookmarks/BookmarksFragment.java b/app/src/main/java/gr/thmmy/mthmmy/activities/bookmarks/BookmarksFragment.java
index 50ecb812..3c2713d1 100644
--- a/app/src/main/java/gr/thmmy/mthmmy/activities/bookmarks/BookmarksFragment.java
+++ b/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);
diff --git a/app/src/main/java/gr/thmmy/mthmmy/activities/topic/TopicActivity.java b/app/src/main/java/gr/thmmy/mthmmy/activities/topic/TopicActivity.java
index c7e3f126..959a0939 100644
--- a/app/src/main/java/gr/thmmy/mthmmy/activities/topic/TopicActivity.java
+++ b/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);
+ }
}
}
});
diff --git a/app/src/main/java/gr/thmmy/mthmmy/activities/topic/tasks/TopicTask.java b/app/src/main/java/gr/thmmy/mthmmy/activities/topic/tasks/TopicTask.java
index 8ba72b74..9b2f8e20 100644
--- a/app/src/main/java/gr/thmmy/mthmmy/activities/topic/tasks/TopicTask.java
+++ b/app/src/main/java/gr/thmmy/mthmmy/activities/topic/tasks/TopicTask.java
@@ -125,7 +125,7 @@ public class TopicTask extends AsyncTask {
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);
}
diff --git a/app/src/main/java/gr/thmmy/mthmmy/activities/upload/UploadActivity.java b/app/src/main/java/gr/thmmy/mthmmy/activities/upload/UploadActivity.java
index e0b5b986..48ec3b5b 100644
--- a/app/src/main/java/gr/thmmy/mthmmy/activities/upload/UploadActivity.java
+++ b/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;
diff --git a/app/src/main/java/gr/thmmy/mthmmy/activities/upload/UploadsHelper.java b/app/src/main/java/gr/thmmy/mthmmy/activities/upload/UploadsHelper.java
index 73b7fd21..af91d72c 100644
--- a/app/src/main/java/gr/thmmy/mthmmy/activities/upload/UploadsHelper.java
+++ b/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!");
}
}
diff --git a/app/src/main/java/gr/thmmy/mthmmy/base/BaseActivity.java b/app/src/main/java/gr/thmmy/mthmmy/base/BaseActivity.java
index f2af6b7e..21e1af95 100644
--- a/app/src/main/java/gr/thmmy/mthmmy/base/BaseActivity.java
+++ b/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;
diff --git a/app/src/main/java/gr/thmmy/mthmmy/base/BaseApplication.java b/app/src/main/java/gr/thmmy/mthmmy/base/BaseApplication.java
index e9293dd2..5b1d0154 100644
--- a/app/src/main/java/gr/thmmy/mthmmy/base/BaseApplication.java
+++ b/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!");
});
}
diff --git a/app/src/main/java/gr/thmmy/mthmmy/services/NotificationService.java b/app/src/main/java/gr/thmmy/mthmmy/services/NotificationService.java
index b271e39f..482dffdb 100644
--- a/app/src/main/java/gr/thmmy/mthmmy/services/NotificationService.java
+++ b/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;
diff --git a/app/src/main/java/gr/thmmy/mthmmy/services/UploadsReceiver.java b/app/src/main/java/gr/thmmy/mthmmy/services/UploadsReceiver.java
index 9823d3d3..19c52396 100644
--- a/app/src/main/java/gr/thmmy/mthmmy/services/UploadsReceiver.java
+++ b/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,
diff --git a/app/src/main/res/drawable/ic_notification_off.xml b/app/src/main/res/drawable/ic_notification_off.xml
index 336141ef..f91fda60 100644
--- a/app/src/main/res/drawable/ic_notification_off.xml
+++ b/app/src/main/res/drawable/ic_notification_off.xml
@@ -6,4 +6,4 @@
-
+
\ No newline at end of file
diff --git a/app/src/main/res/layout/activity_upload_file_list_row.xml b/app/src/main/res/layout/activity_upload_file_list_row.xml
index 08b74a4a..8af02800 100644
--- a/app/src/main/res/layout/activity_upload_file_list_row.xml
+++ b/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">
diff --git a/app/src/main/res/layout/fragment_bookmarks.xml b/app/src/main/res/layout/fragment_bookmarks.xml
index e672fab8..280a9cc4 100644
--- a/app/src/main/res/layout/fragment_bookmarks.xml
+++ b/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" />
+ android:layout_height="wrap_content">
-
+ 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">
+
-
+
-
+
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml
index f203b8cf..1e83bc57 100644
--- a/app/src/main/res/values/strings.xml
+++ b/app/src/main/res/values/strings.xml
@@ -95,9 +95,10 @@
Eclipse Public License v1.0 libraries
Other libraries
Contact
- 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.
+ 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.
+ For account-related issues, please contact the administration team of thmmy.gr by email at contact@thmmy.gr.
Open Source
- The source code of mTHMMY can be found on Github (https://github.com/ThmmyNoLife/mTHMMY) along with further details of how one can contribute.
+ 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.
You should see a funny pic!
Privacy policy