From 2fa356d16e7ba52e272825b4f1c744f22eb3d742 Mon Sep 17 00:00:00 2001 From: Ezerous Date: Sat, 30 May 2020 14:46:09 +0300 Subject: [PATCH] Add ability to download images/ copy their links --- .../downloads/DownloadsAdapter.java | 59 +++++++---------- .../activities/topic/TopicActivity.java | 4 +- .../gr/thmmy/mthmmy/base/BaseActivity.java | 11 +--- .../java/gr/thmmy/mthmmy/model/ThmmyFile.java | 21 ++++-- .../thmmy/mthmmy/services/DownloadHelper.java | 7 +- .../thmmy/mthmmy/utils/parsing/ParseTask.java | 2 +- .../utils/ui/ImageDownloadDialogBuilder.java | 66 +++++++++++++++++++ .../thmmy/mthmmy/utils/ui/PhotoViewUtils.java | 13 +++- .../thmmy/mthmmy/views/ReactiveWebView.java | 20 ++++-- app/src/main/res/values/strings.xml | 2 +- 10 files changed, 144 insertions(+), 61 deletions(-) create mode 100644 app/src/main/java/gr/thmmy/mthmmy/utils/ui/ImageDownloadDialogBuilder.java diff --git a/app/src/main/java/gr/thmmy/mthmmy/activities/downloads/DownloadsAdapter.java b/app/src/main/java/gr/thmmy/mthmmy/activities/downloads/DownloadsAdapter.java index d5ca46ad..63a2c8a8 100644 --- a/app/src/main/java/gr/thmmy/mthmmy/activities/downloads/DownloadsAdapter.java +++ b/app/src/main/java/gr/thmmy/mthmmy/activities/downloads/DownloadsAdapter.java @@ -34,7 +34,7 @@ class DownloadsAdapter extends RecyclerView.Adapter { private final int VIEW_TYPE_LOADING = 1; private final Context context; - private ArrayList parsedDownloads = new ArrayList<>(); + private ArrayList parsedDownloads; private final ArrayList downloadExpandableVisibility = new ArrayList<>(); DownloadsAdapter(Context context, ArrayList parsedDownloads) { @@ -77,17 +77,14 @@ class DownloadsAdapter extends RecyclerView.Adapter { } if (download.getType() == Download.DownloadItemType.DOWNLOADS_CATEGORY) { - downloadViewHolder.downloadRow.setOnClickListener(new View.OnClickListener() { - @Override - public void onClick(View view) { - Intent intent = new Intent(context, DownloadsActivity.class); - Bundle extras = new Bundle(); - extras.putString(BUNDLE_DOWNLOADS_URL, download.getUrl()); - extras.putString(BUNDLE_DOWNLOADS_TITLE, download.getTitle()); - intent.putExtras(extras); - intent.setFlags(FLAG_ACTIVITY_NEW_TASK); - context.startActivity(intent); - } + downloadViewHolder.downloadRow.setOnClickListener(view -> { + Intent intent = new Intent(context, DownloadsActivity.class); + Bundle extras = new Bundle(); + extras.putString(BUNDLE_DOWNLOADS_URL, download.getUrl()); + extras.putString(BUNDLE_DOWNLOADS_TITLE, download.getTitle()); + intent.putExtras(extras); + intent.setFlags(FLAG_ACTIVITY_NEW_TASK); + context.startActivity(intent); }); if (downloadExpandableVisibility.get(downloadViewHolder.getAdapterPosition())) { @@ -97,20 +94,17 @@ class DownloadsAdapter extends RecyclerView.Adapter { downloadViewHolder.informationExpandable.setVisibility(View.GONE); downloadViewHolder.informationExpandableBtn.setImageResource(R.drawable.ic_arrow_drop_down_accent_24dp); } - downloadViewHolder.informationExpandableBtn.setOnClickListener(new View.OnClickListener() { - @Override - public void onClick(View view) { - final boolean visible = downloadExpandableVisibility.get(downloadViewHolder. - getAdapterPosition()); - if (visible) { - downloadViewHolder.informationExpandable.setVisibility(View.GONE); - downloadViewHolder.informationExpandableBtn.setImageResource(R.drawable.ic_arrow_drop_down_accent_24dp); - } else { - downloadViewHolder.informationExpandable.setVisibility(View.VISIBLE); - downloadViewHolder.informationExpandableBtn.setImageResource(R.drawable.ic_arrow_drop_up_accent_24dp); - } - downloadExpandableVisibility.set(downloadViewHolder.getAdapterPosition(), !visible); + downloadViewHolder.informationExpandableBtn.setOnClickListener(view -> { + final boolean visible = downloadExpandableVisibility.get(downloadViewHolder. + getAdapterPosition()); + if (visible) { + downloadViewHolder.informationExpandable.setVisibility(View.GONE); + downloadViewHolder.informationExpandableBtn.setImageResource(R.drawable.ic_arrow_drop_down_accent_24dp); + } else { + downloadViewHolder.informationExpandable.setVisibility(View.VISIBLE); + downloadViewHolder.informationExpandableBtn.setImageResource(R.drawable.ic_arrow_drop_up_accent_24dp); } + downloadExpandableVisibility.set(downloadViewHolder.getAdapterPosition(), !visible); }); downloadViewHolder.title.setTypeface(Typeface.createFromAsset(context.getAssets() , "fonts/fontawesome-webfont.ttf")); @@ -124,15 +118,12 @@ class DownloadsAdapter extends RecyclerView.Adapter { downloadViewHolder.title.setText(tmp); } } else { - downloadViewHolder.downloadRow.setOnClickListener(new View.OnClickListener() { - @Override - public void onClick(View view) { - try { - ((BaseActivity) context).downloadFile(new ThmmyFile( - new URL(download.getUrl()), download.getFileName(), null)); - } catch (MalformedURLException e) { - e.printStackTrace(); - } + downloadViewHolder.downloadRow.setOnClickListener(view -> { + try { + ((BaseActivity) context).downloadFile(new ThmmyFile( + new URL(download.getUrl()), download.getFileName(), null)); + } catch (MalformedURLException e) { + e.printStackTrace(); } }); 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 629b2f60..4bff495a 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 @@ -187,7 +187,7 @@ public class TopicActivity extends BaseActivity implements TopicAdapter.OnPostFo recyclerView.setLayoutManager(layoutManager); topicAdapter = new TopicAdapter(this, emojiKeyboard, topicItems); recyclerView.setAdapter(topicAdapter); - recyclerView.setItemViewCacheSize(15); //Every page has maximum 15 posts + recyclerView.setItemViewCacheSize(17); //Every page has maximum 15 posts + Poll + EditorView replyFAB = findViewById(R.id.topic_fab); replyFAB.hide(); @@ -814,7 +814,7 @@ public class TopicActivity extends BaseActivity implements TopicAdapter.OnPostFo //Make a toast to inform the user that the url was copied Toast.makeText( TopicActivity.this, - TopicActivity.this.getString(R.string.url_copied_msg), + TopicActivity.this.getString(R.string.link_copied_msg), Toast.LENGTH_SHORT).show(); } //Something happened. Probably the device does not support this (report to Firebase) 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 6068304a..37f88876 100644 --- a/app/src/main/java/gr/thmmy/mthmmy/base/BaseActivity.java +++ b/app/src/main/java/gr/thmmy/mthmmy/base/BaseActivity.java @@ -735,7 +735,6 @@ public abstract class BaseActivity extends AppCompatActivity { } } - @Override public void onRequestPermissionsResult(int permsRequestCode, @NonNull String[] permissions , @NonNull int[] grantResults) { @@ -760,13 +759,7 @@ public abstract class BaseActivity extends AppCompatActivity { } } - //Uses temp file - called after permission grant - private void downloadFile() { - if (checkPerms()) - prepareDownload(tempThmmyFile); - } - - private void prepareDownload(ThmmyFile thmmyFile) { + private void prepareDownload(@NonNull ThmmyFile thmmyFile) { String fileName = thmmyFile.getFilename(); if (FileUtils.fileNameExists(fileName)) openDownloadPrompt(thmmyFile); @@ -774,7 +767,7 @@ public abstract class BaseActivity extends AppCompatActivity { DownloadHelper.enqueueDownload(thmmyFile); } - private void openDownloadPrompt(final ThmmyFile thmmyFile) { + private void openDownloadPrompt(@NonNull final ThmmyFile thmmyFile) { View view = getLayoutInflater().inflate(R.layout.download_prompt_dialog, null); final BottomSheetDialog dialog = new BottomSheetDialog(this); dialog.setContentView(view); diff --git a/app/src/main/java/gr/thmmy/mthmmy/model/ThmmyFile.java b/app/src/main/java/gr/thmmy/mthmmy/model/ThmmyFile.java index e071a6a2..91f7a5d7 100644 --- a/app/src/main/java/gr/thmmy/mthmmy/model/ThmmyFile.java +++ b/app/src/main/java/gr/thmmy/mthmmy/model/ThmmyFile.java @@ -1,5 +1,7 @@ package gr.thmmy.mthmmy.model; +import android.webkit.URLUtil; + import java.net.URL; public class ThmmyFile { @@ -8,27 +10,36 @@ public class ThmmyFile { */ private static final String TAG = "ThmmyFile"; private final URL fileUrl; - private final String filename, fileInfo; + private final String fileName, fileInfo; /** * This constructor only creates a ThmmyFile object and does not download the file. * * @param fileUrl {@link URL} object with file's url - * @param filename {@link String} with desired file name + * @param fileName {@link String} with desired file name * @param fileInfo {@link String} with any extra information (like number of downloads) */ - public ThmmyFile(URL fileUrl, String filename, String fileInfo) { + public ThmmyFile(URL fileUrl, String fileName, String fileInfo) { this.fileUrl = fileUrl; - this.filename = filename; + if(fileName!=null) + this.fileName = fileName; + else + this.fileName = URLUtil.guessFileName(fileUrl.toString(), null, null); this.fileInfo = fileInfo; } + public ThmmyFile(URL fileUrl) { + this.fileUrl = fileUrl; + this.fileName = URLUtil.guessFileName(fileUrl.toString(), null, null); + this.fileInfo = null; + } + public URL getFileUrl() { return fileUrl; } public String getFilename() { - return filename; + return fileName; } public String getFileInfo() { diff --git a/app/src/main/java/gr/thmmy/mthmmy/services/DownloadHelper.java b/app/src/main/java/gr/thmmy/mthmmy/services/DownloadHelper.java index 65b5a426..9ba05eef 100644 --- a/app/src/main/java/gr/thmmy/mthmmy/services/DownloadHelper.java +++ b/app/src/main/java/gr/thmmy/mthmmy/services/DownloadHelper.java @@ -6,6 +6,8 @@ import android.net.Uri; import android.os.Environment; import android.widget.Toast; +import androidx.annotation.NonNull; + import java.io.File; import gr.thmmy.mthmmy.base.BaseApplication; @@ -34,7 +36,8 @@ public class DownloadHelper { DownloadManager.Request request = new DownloadManager.Request(downloadURI); Cookie thmmyCookie = BaseApplication.getInstance().getSessionManager().getThmmyCookie(); - request.addRequestHeader("Cookie", thmmyCookie.name() + "=" + thmmyCookie.value()); + if(thmmyCookie!=null) + request.addRequestHeader("Cookie", thmmyCookie.name() + "=" + thmmyCookie.value()); request.setTitle(fileName); request.setMimeType(getMimeType(fileName)); request.setNotificationVisibility(DownloadManager.Request.VISIBILITY_VISIBLE_NOTIFY_COMPLETED); @@ -49,6 +52,7 @@ public class DownloadHelper { } } + @NonNull private static String renameFileIfExists(String originalFileName) { final String dirPath = SAVE_DIR.getAbsolutePath(); File file = new File(dirPath, originalFileName); @@ -68,7 +72,6 @@ public class DownloadHelper { file = new File(dirPath, String.format(nameFormat, i)); } - return file.getName(); } } diff --git a/app/src/main/java/gr/thmmy/mthmmy/utils/parsing/ParseTask.java b/app/src/main/java/gr/thmmy/mthmmy/utils/parsing/ParseTask.java index 4f335025..9ead4364 100644 --- a/app/src/main/java/gr/thmmy/mthmmy/utils/parsing/ParseTask.java +++ b/app/src/main/java/gr/thmmy/mthmmy/utils/parsing/ParseTask.java @@ -21,7 +21,7 @@ import timber.log.Timber; */ public abstract class ParseTask extends AsyncTask { protected String url; - protected enum ResultCode { + public enum ResultCode { SUCCESS, PARSING_ERROR, NETWORK_ERROR, OTHER_ERROR } diff --git a/app/src/main/java/gr/thmmy/mthmmy/utils/ui/ImageDownloadDialogBuilder.java b/app/src/main/java/gr/thmmy/mthmmy/utils/ui/ImageDownloadDialogBuilder.java new file mode 100644 index 00000000..fe5dc54c --- /dev/null +++ b/app/src/main/java/gr/thmmy/mthmmy/utils/ui/ImageDownloadDialogBuilder.java @@ -0,0 +1,66 @@ +package gr.thmmy.mthmmy.utils.ui; + +import android.content.ClipData; +import android.content.ClipboardManager; +import android.content.Context; +import android.content.ContextWrapper; +import android.widget.Toast; + +import androidx.annotation.NonNull; +import androidx.appcompat.app.AlertDialog; + +import java.net.MalformedURLException; +import java.net.URL; + +import gr.thmmy.mthmmy.R; +import gr.thmmy.mthmmy.base.BaseActivity; +import gr.thmmy.mthmmy.base.BaseApplication; +import gr.thmmy.mthmmy.model.ThmmyFile; +import timber.log.Timber; + +import static android.content.Context.CLIPBOARD_SERVICE; + +public class ImageDownloadDialogBuilder extends AlertDialog.Builder{ + private static final String[] colors = {"Copy image location", "Save Image"}; + + private Context context; + private String imageURL; + + public ImageDownloadDialogBuilder(@NonNull Context context, String imageURL) { + super(context); + this.context = context; + this.imageURL = imageURL; + + setItems(colors, (dialog, which) -> { + if(which == 0) + copyUrlToClipboard(); + else { + try { + getBaseActivity().downloadFile(new ThmmyFile(new URL(imageURL))); + } catch (MalformedURLException e) { + Timber.e(e, "Exception downloading image (MalformedURLException)"); + } catch (NullPointerException e) { + Timber.e(e, "Exception downloading image (NullPointerException)"); + } + } + }); + } + + 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(); + } + + private BaseActivity getBaseActivity() { + Context baseActivityContext = context; + while (baseActivityContext instanceof ContextWrapper) { + if (context instanceof BaseActivity) { + return (BaseActivity) context; + } + baseActivityContext = ((ContextWrapper)context).getBaseContext(); + } + return null; + } +} diff --git a/app/src/main/java/gr/thmmy/mthmmy/utils/ui/PhotoViewUtils.java b/app/src/main/java/gr/thmmy/mthmmy/utils/ui/PhotoViewUtils.java index cb357324..b361c68d 100644 --- a/app/src/main/java/gr/thmmy/mthmmy/utils/ui/PhotoViewUtils.java +++ b/app/src/main/java/gr/thmmy/mthmmy/utils/ui/PhotoViewUtils.java @@ -15,7 +15,7 @@ public class PhotoViewUtils { private final static int screenWidth = BaseApplication.getInstance().getWidthInPixels(); private final static int screenHeight = BaseApplication.getInstance().getHeightInPixels(); - public static void displayPhotoViewImage(Context context, String url) { + public static void displayPhotoViewImage(Context context, String imageURL) { Dialog builder = new Dialog(context); builder.requestWindowFeature(Window.FEATURE_NO_TITLE); builder.getWindow().setLayout(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT); @@ -25,11 +25,20 @@ public class PhotoViewUtils { PhotoView photoView = new PhotoView(context); photoView.setLayoutParams(new ViewGroup.LayoutParams(screenWidth, screenHeight)); - Glide.with(context).load(url).fitCenter().into(photoView); + Glide.with(context) + .load(imageURL) + .fitCenter() + .into(photoView); builder.addContentView(photoView, new ViewGroup.LayoutParams( ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT)); builder.show(); + + photoView.setOnLongClickListener(v -> { + ImageDownloadDialogBuilder imageDownloadDialogBuilder = new ImageDownloadDialogBuilder(context, imageURL); + imageDownloadDialogBuilder.show(); + return false; + }); } } diff --git a/app/src/main/java/gr/thmmy/mthmmy/views/ReactiveWebView.java b/app/src/main/java/gr/thmmy/mthmmy/views/ReactiveWebView.java index 294c6451..7c9efdb8 100644 --- a/app/src/main/java/gr/thmmy/mthmmy/views/ReactiveWebView.java +++ b/app/src/main/java/gr/thmmy/mthmmy/views/ReactiveWebView.java @@ -8,7 +8,9 @@ import android.view.MotionEvent; import android.webkit.WebView; import android.widget.Toast; +import gr.thmmy.mthmmy.R; import gr.thmmy.mthmmy.base.BaseApplication; +import gr.thmmy.mthmmy.utils.ui.ImageDownloadDialogBuilder; import static android.content.Context.CLIPBOARD_SERVICE; import static gr.thmmy.mthmmy.utils.ui.PhotoViewUtils.displayPhotoViewImage; @@ -71,13 +73,21 @@ public class ReactiveWebView extends WebView { private void setOnLongClickListener(){ this.setOnLongClickListener(v -> { HitTestResult result = ReactiveWebView.this.getHitTestResult(); - if(result.getType() == HitTestResult.SRC_ANCHOR_TYPE){ - ClipboardManager clipboard = (ClipboardManager) BaseApplication.getInstance().getSystemService(CLIPBOARD_SERVICE); - ClipData clip = ClipData.newPlainText("ReactiveWebViewCopiedText", result.getExtra()); - clipboard.setPrimaryClip(clip); - Toast.makeText(BaseApplication.getInstance().getApplicationContext(),"Link copied",Toast.LENGTH_SHORT).show(); + if(result.getType() == HitTestResult.SRC_ANCHOR_TYPE) + copyUrlToClipboard(result.getExtra()); + else if(result.getType() == WebView.HitTestResult.IMAGE_TYPE) { + String imageURL = result.getExtra(); + ImageDownloadDialogBuilder builder = new ImageDownloadDialogBuilder(context,imageURL); + builder.show(); } return false; }); } + + 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(); + } } diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index b0cae84b..88e8899f 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -233,5 +233,5 @@ New topic Create topic - URL copied + Link copied