diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index d41efe63..0bd9268e 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -19,6 +19,17 @@ android:usesCleartextTraffic="true" android:requestLegacyExternalStorage="true" tools:ignore="AllowBackup,GoogleAppIndexingWarning,UnusedAttribute"> + + + + + diff --git a/app/src/main/java/com/readrops/app/activities/ItemActivity.java b/app/src/main/java/com/readrops/app/activities/ItemActivity.java index ed8ac4a3..65a1816e 100644 --- a/app/src/main/java/com/readrops/app/activities/ItemActivity.java +++ b/app/src/main/java/com/readrops/app/activities/ItemActivity.java @@ -3,20 +3,31 @@ package com.readrops.app.activities; import android.content.Intent; import android.content.res.ColorStateList; import android.content.res.TypedArray; +import android.graphics.Bitmap; +import android.graphics.drawable.Drawable; import android.net.Uri; import android.os.Bundle; +import android.util.Log; +import android.view.ContextMenu; import android.view.Menu; import android.view.MenuItem; import android.view.View; +import android.webkit.WebView; import android.widget.ImageView; import android.widget.RelativeLayout; import android.widget.TextView; +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; import androidx.appcompat.app.AppCompatActivity; import androidx.appcompat.widget.Toolbar; +import androidx.core.app.ShareCompat; import androidx.lifecycle.ViewModelProvider; +import com.afollestad.materialdialogs.MaterialDialog; import com.bumptech.glide.load.engine.DiskCacheStrategy; +import com.bumptech.glide.request.target.CustomTarget; +import com.bumptech.glide.request.transition.Transition; import com.google.android.material.appbar.AppBarLayout; import com.google.android.material.appbar.CollapsingToolbarLayout; import com.google.android.material.floatingactionbutton.FloatingActionButton; @@ -37,6 +48,8 @@ import static com.readrops.app.utils.ReadropsKeys.WEB_URL; public class ItemActivity extends AppCompatActivity { + private static final String TAG = ItemActivity.class.getSimpleName(); + private ItemViewModel viewModel; private TextView date; private TextView title; @@ -84,6 +97,8 @@ public class ItemActivity extends AppCompatActivity { readTimeLayout = findViewById(R.id.activity_item_readtime_layout); dateLayout = findViewById(R.id.activity_item_date_layout); + registerForContextMenu(webView); + if (imageUrl == null) { getSupportActionBar().setDisplayShowTitleEnabled(false); toolbarLayout.setTitleEnabled(false); @@ -246,4 +261,58 @@ public class ItemActivity extends AppCompatActivity { shareIntent.putExtra(Intent.EXTRA_TEXT, itemWithFeed.getItem().getTitle() + " - " + itemWithFeed.getItem().getLink()); startActivity(Intent.createChooser(shareIntent, getString(R.string.share_article))); } + + @Override + public void onCreateContextMenu(ContextMenu menu, View v, ContextMenu.ContextMenuInfo menuInfo) { + WebView.HitTestResult hitTestResult = webView.getHitTestResult(); + + if (hitTestResult.getType() == WebView.HitTestResult.IMAGE_TYPE || + hitTestResult.getType() == WebView.HitTestResult.SRC_IMAGE_ANCHOR_TYPE) { + new MaterialDialog.Builder(this) + .title(R.string.image_options) + .items(R.array.image_options) + .itemsCallback((dialog, itemView, position, text) -> { + if (position == 0) + shareImage(hitTestResult.getExtra()); + else + downloadImage(hitTestResult.getExtra()); + }) + .show(); + } + } + + private void downloadImage(String url) { + + } + + private void shareImage(String url) { + GlideApp.with(this) + .asBitmap() + .diskCacheStrategy(DiskCacheStrategy.ALL) + .load(url) + .into(new CustomTarget() { + @Override + public void onResourceReady(@NonNull Bitmap resource, @Nullable Transition transition) { + try { + Uri uri = viewModel.saveImageInCache(resource); + Intent intent = ShareCompat.IntentBuilder.from(ItemActivity.this) + .setType("image/png") + .setStream(uri) + .setChooserTitle(R.string.share_image) + .createChooserIntent() + .addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION); + + startActivity(intent); + } catch (Exception e) { + Log.e(TAG, e.getMessage()); + } + } + + @Override + public void onLoadCleared(@Nullable Drawable placeholder) { + // not useful + } + }); + + } } diff --git a/app/src/main/java/com/readrops/app/viewmodels/ItemViewModel.java b/app/src/main/java/com/readrops/app/viewmodels/ItemViewModel.java index d79e2ccd..10585f37 100644 --- a/app/src/main/java/com/readrops/app/viewmodels/ItemViewModel.java +++ b/app/src/main/java/com/readrops/app/viewmodels/ItemViewModel.java @@ -1,14 +1,23 @@ package com.readrops.app.viewmodels; import android.app.Application; +import android.graphics.Bitmap; +import android.net.Uri; + +import androidx.annotation.NonNull; +import androidx.core.content.FileProvider; import androidx.lifecycle.AndroidViewModel; import androidx.lifecycle.LiveData; -import androidx.annotation.NonNull; import com.readrops.app.database.Database; import com.readrops.app.database.dao.ItemDao; import com.readrops.app.database.pojo.ItemWithFeed; +import java.io.File; +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.OutputStream; + public class ItemViewModel extends AndroidViewModel { private ItemDao itemDao; @@ -23,4 +32,19 @@ public class ItemViewModel extends AndroidViewModel { } + public Uri saveImageInCache(Bitmap bitmap) throws IOException { + File imagesFolder = new File(getApplication().getCacheDir().getAbsolutePath(), "images"); + + if (!imagesFolder.exists()) + imagesFolder.mkdirs(); + + File image = new File(imagesFolder, "shared_image.png"); + OutputStream stream = new FileOutputStream(image); + bitmap.compress(Bitmap.CompressFormat.PNG, 90, stream); + + stream.flush(); + stream.close(); + + return FileProvider.getUriForFile(getApplication(), getApplication().getPackageName(), image); + } } diff --git a/app/src/main/res/values-fr-rFR/strings.xml b/app/src/main/res/values-fr-rFR/strings.xml index f5f3ec79..9af48fa0 100644 --- a/app/src/main/res/values-fr-rFR/strings.xml +++ b/app/src/main/res/values-fr-rFR/strings.xml @@ -103,5 +103,8 @@ Réessayer Permissions Ou + Options de l\'image + Télécharger l\'image + Partager l\'image \ No newline at end of file diff --git a/app/src/main/res/values/arrays.xml b/app/src/main/res/values/arrays.xml index 8f06743e..6eb2a4e5 100644 --- a/app/src/main/res/values/arrays.xml +++ b/app/src/main/res/values/arrays.xml @@ -10,6 +10,11 @@ @string/opml_export + + @string/share_image + @string/download_image + + 20 50 diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 74566f17..b12cc24f 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -112,4 +112,7 @@ Try again Permissions Or + Image Options + Download image + Share image diff --git a/app/src/main/res/xml/file_paths.xml b/app/src/main/res/xml/file_paths.xml new file mode 100644 index 00000000..2f2698e3 --- /dev/null +++ b/app/src/main/res/xml/file_paths.xml @@ -0,0 +1,8 @@ + + + + + + \ No newline at end of file