diff options
9 files changed, 149 insertions, 85 deletions
diff --git a/org.fox.ttrss/src/main/java/org/fox/ttrss/GalleryActivity.java b/org.fox.ttrss/src/main/java/org/fox/ttrss/GalleryActivity.java index ced956c2..b0ada038 100755 --- a/org.fox.ttrss/src/main/java/org/fox/ttrss/GalleryActivity.java +++ b/org.fox.ttrss/src/main/java/org/fox/ttrss/GalleryActivity.java @@ -95,7 +95,7 @@ public class GalleryActivity extends CommonActivity { @Override public void onCreate(Bundle savedInstanceState) { - // ActivityCompat.postponeEnterTransition(this); + ActivityCompat.postponeEnterTransition(this); // we use that before parent onCreate so let's init locally m_prefs = PreferenceManager diff --git a/org.fox.ttrss/src/main/java/org/fox/ttrss/GalleryImageFragment.java b/org.fox.ttrss/src/main/java/org/fox/ttrss/GalleryImageFragment.java index db141427..b249b889 100755 --- a/org.fox.ttrss/src/main/java/org/fox/ttrss/GalleryImageFragment.java +++ b/org.fox.ttrss/src/main/java/org/fox/ttrss/GalleryImageFragment.java @@ -71,7 +71,7 @@ public class GalleryImageFragment extends GalleryBaseFragment { progressBar.setVisibility(View.GONE); errorMessage.setVisibility(View.VISIBLE); - // ActivityCompat.startPostponedEnterTransition(m_activity); + ActivityCompat.startPostponedEnterTransition(m_activity); return false; } @@ -81,7 +81,7 @@ public class GalleryImageFragment extends GalleryBaseFragment { progressBar.setVisibility(View.GONE); errorMessage.setVisibility(View.GONE); - // ActivityCompat.startPostponedEnterTransition(m_activity); + ActivityCompat.startPostponedEnterTransition(m_activity); return false; } diff --git a/org.fox.ttrss/src/main/java/org/fox/ttrss/GalleryVideoFragment.java b/org.fox.ttrss/src/main/java/org/fox/ttrss/GalleryVideoFragment.java index a171fb5b..18d08e4f 100755 --- a/org.fox.ttrss/src/main/java/org/fox/ttrss/GalleryVideoFragment.java +++ b/org.fox.ttrss/src/main/java/org/fox/ttrss/GalleryVideoFragment.java @@ -56,7 +56,7 @@ public class GalleryVideoFragment extends GalleryBaseFragment { registerForContextMenu(imgView); - // ActivityCompat.startPostponedEnterTransition(m_activity); + ActivityCompat.startPostponedEnterTransition(m_activity); view.findViewById(R.id.flavor_image_progress).setVisibility(View.VISIBLE); diff --git a/org.fox.ttrss/src/main/java/org/fox/ttrss/HeadlinesFragment.java b/org.fox.ttrss/src/main/java/org/fox/ttrss/HeadlinesFragment.java index d5da9d6e..6c3829cc 100755 --- a/org.fox.ttrss/src/main/java/org/fox/ttrss/HeadlinesFragment.java +++ b/org.fox.ttrss/src/main/java/org/fox/ttrss/HeadlinesFragment.java @@ -22,6 +22,7 @@ import android.transition.Fade; import android.transition.Transition; import android.util.DisplayMetrics; import android.util.Log; +import android.util.Size; import android.util.TypedValue; import android.view.ContextMenu; import android.view.ContextMenu.ContextMenuInfo; @@ -45,6 +46,7 @@ import android.widget.PopupMenu; import android.widget.ProgressBar; import android.widget.TextView; +import androidx.annotation.NonNull; import androidx.annotation.Nullable; import androidx.core.app.ActivityCompat; import androidx.core.app.ActivityOptionsCompat; @@ -64,11 +66,11 @@ import com.bumptech.glide.Glide; import com.bumptech.glide.load.DataSource; import com.bumptech.glide.load.engine.DiskCacheStrategy; import com.bumptech.glide.load.engine.GlideException; -import com.bumptech.glide.load.resource.bitmap.DownsampleStrategy; import com.bumptech.glide.load.resource.drawable.DrawableTransitionOptions; import com.bumptech.glide.request.RequestListener; import com.bumptech.glide.request.RequestOptions; import com.bumptech.glide.request.target.DrawableImageViewTarget; +import com.bumptech.glide.request.target.SimpleTarget; import com.bumptech.glide.request.target.Target; import com.google.android.material.button.MaterialButton; import com.google.android.material.dialog.MaterialAlertDialogBuilder; @@ -124,7 +126,7 @@ public class HeadlinesFragment extends androidx.fragment.app.Fragment { private MediaPlayer m_mediaPlayer; private TextureView m_activeTexture; - protected static HashMap<Integer, Integer> m_flavorHeightsCache = new HashMap<>(); + protected static HashMap<Integer, Integer> m_flavorMeasuredHeightsCache = new HashMap<>(); public ArticleList getSelectedArticles() { return Application.getArticles() @@ -618,7 +620,7 @@ public class HeadlinesFragment extends androidx.fragment.app.Fragment { public View flavorImageOverflow; public TextureView flavorVideoView; public MaterialButton attachmentsView; - public ProgressTarget<String, Drawable> flavorProgressTarget; + // public ProgressTarget<String, Size> flavorProgressTarget; int articleId; public TextView linkHost; @@ -631,7 +633,7 @@ public class HeadlinesFragment extends androidx.fragment.app.Fragment { View flavorImage = view.findViewById(R.id.flavor_image); if (flavorImage != null) { - HeadlinesFragment.m_flavorHeightsCache.put(articleId, flavorImage.getMeasuredHeight()); + HeadlinesFragment.m_flavorMeasuredHeightsCache.put(articleId, flavorImage.getMeasuredHeight()); } return true; @@ -659,11 +661,6 @@ public class HeadlinesFragment extends androidx.fragment.app.Fragment { flavorVideoView = v.findViewById(R.id.flavor_video); attachmentsView = v.findViewById(R.id.attachments); linkHost = v.findViewById(R.id.link_host); - - if (flavorImageView != null && flavorImageLoadingBar != null) { - flavorProgressTarget = new FlavorProgressTarget<>(new DrawableImageViewTarget(flavorImageView), - flavorImageLoadingBar); - } } public void clearAnimation() { @@ -672,10 +669,11 @@ public class HeadlinesFragment extends androidx.fragment.app.Fragment { } private static class FlavorProgressTarget<Z> extends ProgressTarget<String, Z> { - private final ProgressBar progress; - public FlavorProgressTarget(Target<Z> target, ProgressBar progress) { + private final ArticleViewHolder holder; + public FlavorProgressTarget(Target<Z> target, String model, ArticleViewHolder holder) { super(target); - this.progress = progress; + setModel(model); + this.holder = holder; } @Override public float getGranualityPercentage() { @@ -683,18 +681,26 @@ public class HeadlinesFragment extends androidx.fragment.app.Fragment { } @Override protected void onConnecting() { - progress.setIndeterminate(true); - progress.setVisibility(View.VISIBLE); + holder.flavorImageHolder.setVisibility(View.VISIBLE); + + holder.flavorImageLoadingBar.setIndeterminate(true); + holder.flavorImageLoadingBar.setVisibility(View.VISIBLE); } @Override protected void onDownloading(long bytesRead, long expectedLength) { - progress.setIndeterminate(false); - progress.setProgress((int)(100 * bytesRead / expectedLength)); + holder.flavorImageHolder.setVisibility(View.VISIBLE); + + holder.flavorImageLoadingBar.setIndeterminate(false); + holder.flavorImageLoadingBar.setProgress((int)(100 * bytesRead / expectedLength)); } @Override protected void onDownloaded() { - progress.setIndeterminate(true); + holder.flavorImageHolder.setVisibility(View.VISIBLE); + + holder.flavorImageLoadingBar.setIndeterminate(true); } @Override protected void onDelivered() { - progress.setVisibility(View.INVISIBLE); + holder.flavorImageHolder.setVisibility(View.VISIBLE); + + holder.flavorImageLoadingBar.setVisibility(View.INVISIBLE); } } @@ -772,8 +778,6 @@ public class HeadlinesFragment extends androidx.fragment.app.Fragment { View v = LayoutInflater.from(parent.getContext()).inflate(layoutId, parent, false); - //registerForContextMenu(v); - return new ArticleViewHolder(v); } @@ -997,13 +1001,6 @@ public class HeadlinesFragment extends androidx.fragment.app.Fragment { } else { holder.excerptView.setVisibility(View.GONE); } - - if (!canShowFlavorImage()) { - holder.excerptView.setPadding(holder.excerptView.getPaddingLeft(), - 0, - holder.excerptView.getPaddingRight(), - holder.excerptView.getPaddingBottom()); - } } } @@ -1071,67 +1068,76 @@ public class HeadlinesFragment extends androidx.fragment.app.Fragment { }); } - holder.flavorImageView.setVisibility(View.VISIBLE); - int maxImageSize = (int) (m_screenHeight * 0.5f); // we also downsample below using glide to save RAM - // holder.flavorImageView.setMaxHeight(maxImageSize); - - // only show holder if we're about to display a picture - holder.flavorImageHolder.setVisibility(View.VISIBLE); + holder.flavorImageView.setMaxHeight(maxImageSize); // prevent lower listiew entries from jumping around if this row is modified - /* if (m_flavorHeightsCache.containsKey(article.id)) { - int cachedHeight = m_flavorHeightsCache.get(article.id); + if (m_flavorMeasuredHeightsCache.containsKey(article.id)) { + int cachedHeight = m_flavorMeasuredHeightsCache.get(article.id); if (cachedHeight > 0) { FrameLayout.LayoutParams lp = (FrameLayout.LayoutParams) holder.flavorImageView.getLayoutParams(); lp.height = cachedHeight; } - } */ - - holder.flavorProgressTarget.setModel(article.flavorImageUri); + } - Glide.with(HeadlinesFragment.this) - .load(article.flavorImageUri) - .transition(DrawableTransitionOptions.withCrossFade()) - .diskCacheStrategy(DiskCacheStrategy.ALL) - .skipMemoryCache(false) - .listener(new RequestListener<Drawable>() { - @Override - public boolean onLoadFailed(@Nullable GlideException e, Object model, Target<Drawable> target, boolean isFirstResource) { + Log.d(TAG, "checking resource size for " + article.flavorImageUri); - holder.flavorImageLoadingBar.setVisibility(View.GONE); - holder.flavorImageView.setVisibility(View.GONE); + FlavorProgressTarget<Size> flavorProgressTarget = new FlavorProgressTarget<>(new SimpleTarget<Size>() { + @Override + public void onResourceReady(@NonNull Size resource, @Nullable com.bumptech.glide.request.transition.Transition<? super Size> transition) { + Log.d(TAG, "got resource of " + resource.getWidth() + "x" + resource.getHeight()); - return false; - } + if (resource.getWidth() > FLAVOR_IMG_MIN_SIZE && resource.getHeight() > FLAVOR_IMG_MIN_SIZE) { - @Override - public boolean onResourceReady(Drawable resource, Object model, Target<Drawable> target, DataSource dataSource, boolean isFirstResource) { + // now we can actually load the image into our drawable + Glide.with(HeadlinesFragment.this) + .load(article.flavorImageUri) + .transition(DrawableTransitionOptions.withCrossFade()) + .override(maxImageSize) + .diskCacheStrategy(DiskCacheStrategy.DATA) + .skipMemoryCache(true) + .listener(new RequestListener<Drawable>() { + @Override + public boolean onLoadFailed(@Nullable GlideException e, Object model, Target<Drawable> target, boolean isFirstResource) { + holder.flavorImageHolder.setVisibility(View.GONE); - holder.flavorImageLoadingBar.setVisibility(View.GONE); + holder.flavorImageView.setVisibility(View.GONE); + holder.flavorImageOverflow.setVisibility(View.VISIBLE); - if (resource.getIntrinsicWidth() > FLAVOR_IMG_MIN_SIZE && resource.getIntrinsicHeight() > FLAVOR_IMG_MIN_SIZE) { + return false; + } - holder.flavorImageView.setVisibility(View.VISIBLE); - holder.flavorImageOverflow.setVisibility(View.VISIBLE); + @Override + public boolean onResourceReady(Drawable resource, Object model, Target<Drawable> target, DataSource dataSource, boolean isFirstResource) { + holder.flavorImageHolder.setVisibility(View.VISIBLE); - adjustVideoKindView(holder, article); + holder.flavorImageView.setVisibility(View.VISIBLE); + holder.flavorImageOverflow.setVisibility(View.VISIBLE); - return false; - } else { + adjustVideoKindView(holder, article); - holder.flavorImageOverflow.setVisibility(View.GONE); - holder.flavorImageView.setVisibility(View.GONE); + return false; + } + }) + .into(new DrawableImageViewTarget(holder.flavorImageView)); + } else { + holder.flavorImageHolder.setVisibility(View.GONE); - return true; - } - } - }) - .into(holder.flavorProgressTarget); + holder.flavorImageView.setVisibility(View.VISIBLE); + holder.flavorImageOverflow.setVisibility(View.VISIBLE); + } + } + }, article.flavorImageUri, holder); + Glide.with(HeadlinesFragment.this) + .as(Size.class) + .load(article.flavorImageUri) + .diskCacheStrategy(DiskCacheStrategy.DATA) + .skipMemoryCache(true) + .into(flavorProgressTarget); } if (m_prefs.getBoolean("inline_video_player", false) && article.flavorImage != null && @@ -1403,14 +1409,14 @@ public class HeadlinesFragment extends androidx.fragment.app.Fragment { intent.putExtra("content", tempContent); - /* ActivityOptionsCompat options = + ActivityOptionsCompat options = ActivityOptionsCompat.makeSceneTransitionAnimation(m_activity, transitionView != null ? transitionView : holder.flavorImageView, - "gallery:" + (article.flavorStreamUri != null ? article.flavorStreamUri : article.flavorImageUri)); */ + "gallery:" + (article.flavorStreamUri != null ? article.flavorStreamUri : article.flavorImageUri)); - // ActivityCompat.startActivity(m_activity, intent, options.toBundle()) + ActivityCompat.startActivity(m_activity, intent, options.toBundle()); - startActivity(intent); + // startActivity(intent); } } diff --git a/org.fox.ttrss/src/main/java/org/fox/ttrss/glide/BitmapSizeDecoder.java b/org.fox.ttrss/src/main/java/org/fox/ttrss/glide/BitmapSizeDecoder.java new file mode 100644 index 00000000..1a709073 --- /dev/null +++ b/org.fox.ttrss/src/main/java/org/fox/ttrss/glide/BitmapSizeDecoder.java @@ -0,0 +1,30 @@ +package org.fox.ttrss.glide; + +import java.io.File; +import java.io.IOException; + +import com.bumptech.glide.load.Options; +import com.bumptech.glide.load.ResourceDecoder; +import com.bumptech.glide.load.engine.Resource; +import com.bumptech.glide.load.resource.SimpleResource; + +import android.graphics.BitmapFactory; +import android.util.Log; + +import androidx.annotation.NonNull; + +class BitmapSizeDecoder implements ResourceDecoder<File, BitmapFactory.Options> { + @Override + public Resource<BitmapFactory.Options> decode(File file, int width, int height, Options options) throws IOException { + BitmapFactory.Options bmOptions = new BitmapFactory.Options(); + bmOptions.inJustDecodeBounds = true; + BitmapFactory.decodeFile(file.getAbsolutePath(), bmOptions); + return new SimpleResource<>(bmOptions); + } + + @Override + public boolean handles(@NonNull File source, @NonNull Options options) throws IOException { + return true; + } +} + diff --git a/org.fox.ttrss/src/main/java/org/fox/ttrss/glide/OkHttpProgressGlideModule.java b/org.fox.ttrss/src/main/java/org/fox/ttrss/glide/OkHttpProgressGlideModule.java index 561f9a86..44f69b79 100644 --- a/org.fox.ttrss/src/main/java/org/fox/ttrss/glide/OkHttpProgressGlideModule.java +++ b/org.fox.ttrss/src/main/java/org/fox/ttrss/glide/OkHttpProgressGlideModule.java @@ -1,9 +1,11 @@ package org.fox.ttrss.glide; import android.content.Context; +import android.graphics.BitmapFactory; import android.os.Handler; import android.os.Looper; import android.util.Log; +import android.util.Size; import com.bumptech.glide.Glide; import com.bumptech.glide.GlideBuilder; @@ -13,6 +15,7 @@ import com.bumptech.glide.integration.okhttp3.OkHttpUrlLoader; import com.bumptech.glide.load.model.GlideUrl; import com.bumptech.glide.module.AppGlideModule; +import java.io.File; import java.io.IOException; import java.io.InputStream; import java.util.HashMap; @@ -40,6 +43,9 @@ public class OkHttpProgressGlideModule extends AppGlideModule { // registry.append() doesn't work... registry.prepend(GlideUrl.class, InputStream.class, new OkHttpUrlLoader.Factory(client)); + + registry.prepend(File.class, BitmapFactory.Options.class, new BitmapSizeDecoder()); + registry.register(BitmapFactory.Options.class, Size.class, new OptionsSizeResourceTranscoder()); } public static Interceptor createInterceptor(final ResponseProgressListener listener) { @@ -92,6 +98,7 @@ public class OkHttpProgressGlideModule extends AppGlideModule { @Override public void update(HttpUrl url, final long bytesRead, final long contentLength) { //System.out.printf("%s: %d/%d = %.2f%%%n", url, bytesRead, contentLength, (100f * bytesRead) / contentLength); + //Log.d("resource progress", "url=" + url + " bytesRead="+ bytesRead + " of " + contentLength); String key = url.toString(); final UIProgressListener listener = LISTENERS.get(key); diff --git a/org.fox.ttrss/src/main/java/org/fox/ttrss/glide/OptionsSizeResourceTranscoder.java b/org.fox.ttrss/src/main/java/org/fox/ttrss/glide/OptionsSizeResourceTranscoder.java new file mode 100644 index 00000000..2fc56fe7 --- /dev/null +++ b/org.fox.ttrss/src/main/java/org/fox/ttrss/glide/OptionsSizeResourceTranscoder.java @@ -0,0 +1,20 @@ +package org.fox.ttrss.glide; + +import android.graphics.BitmapFactory; +import android.util.Log; +import android.util.Size; + +import com.bumptech.glide.load.Options; +import com.bumptech.glide.load.resource.transcode.ResourceTranscoder; +import com.bumptech.glide.load.engine.Resource; +import com.bumptech.glide.load.resource.SimpleResource; + +class OptionsSizeResourceTranscoder implements ResourceTranscoder<BitmapFactory.Options, Size> { + @Override + public Resource<Size> transcode(Resource<BitmapFactory.Options> resource, Options options) { + BitmapFactory.Options bmOptions = resource.get(); + Size size = new Size(bmOptions.outWidth, bmOptions.outHeight); + return new SimpleResource<>(size); + } +} + diff --git a/org.fox.ttrss/src/main/res/layout/headlines_row.xml b/org.fox.ttrss/src/main/res/layout/headlines_row.xml index d77ad6cc..5e4eca4e 100755 --- a/org.fox.ttrss/src/main/res/layout/headlines_row.xml +++ b/org.fox.ttrss/src/main/res/layout/headlines_row.xml @@ -103,6 +103,7 @@ android:id="@+id/flavorImageHolder" android:layout_width="match_parent" android:layout_height="wrap_content" + android:layout_marginBottom="16dp" android:layout_span="2"> <ProgressBar @@ -121,9 +122,9 @@ android:layout_height="wrap_content" android:layout_gravity="center" android:adjustViewBounds="true" - android:background="@android:color/transparent" + android:background="@null" android:cropToPadding="true" - android:scaleType="fitCenter" + android:scaleType="centerCrop" tools:src="@drawable/ic_launcher_background" android:visibility="visible" /> @@ -178,7 +179,8 @@ android:textAlignment="viewStart" android:lineSpacingExtra="2sp" android:maxLines="5" - android:padding="16dp" + android:paddingStart="16dp" + android:paddingEnd="16dp" tools:text="Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua." android:textSize="13sp" /> </TableRow> @@ -193,8 +195,7 @@ android:layout_height="wrap_content" android:layout_span="2" android:gravity="center_vertical" - android:paddingBottom="8dp" - android:paddingLeft="8dp"> + android:paddingBottom="8dp"> <com.google.android.material.checkbox.MaterialCheckBox android:id="@+id/selected" diff --git a/org.fox.ttrss/src/main/res/layout/headlines_row_unread.xml b/org.fox.ttrss/src/main/res/layout/headlines_row_unread.xml index 7e5f7b48..cff1502d 100755 --- a/org.fox.ttrss/src/main/res/layout/headlines_row_unread.xml +++ b/org.fox.ttrss/src/main/res/layout/headlines_row_unread.xml @@ -104,6 +104,7 @@ android:id="@+id/flavorImageHolder" android:layout_width="match_parent" android:layout_height="wrap_content" + android:layout_marginBottom="16dp" android:layout_span="2"> <ProgressBar @@ -122,9 +123,8 @@ android:layout_height="wrap_content" android:layout_gravity="center" android:adjustViewBounds="true" - android:background="@android:color/transparent" - android:cropToPadding="true" - android:scaleType="fitCenter" + android:background="@null" + android:scaleType="centerCrop" tools:src="@drawable/ic_launcher_background" android:visibility="visible" /> @@ -178,7 +178,8 @@ android:textAlignment="viewStart" android:lineSpacingExtra="2sp" android:maxLines="5" - android:padding="16dp" + android:paddingStart="16dp" + android:paddingEnd="16dp" tools:text="Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua." android:textSize="13sp" /> </TableRow> @@ -193,8 +194,7 @@ android:layout_height="wrap_content" android:layout_span="2" android:gravity="center_vertical" - android:paddingBottom="8dp" - android:paddingLeft="8dp"> + android:paddingBottom="8dp"> <com.google.android.material.checkbox.MaterialCheckBox android:id="@+id/selected" |