mirror of
https://github.com/TeamNewPipe/NewPipe
synced 2024-12-23 16:40:32 +00:00
Addressed code review comments
This commit is contained in:
parent
da83646303
commit
4ec7532126
@ -1473,6 +1473,7 @@ public final class VideoDetailFragment
|
|||||||
CoilUtils.dispose(binding.detailThumbnailImageView);
|
CoilUtils.dispose(binding.detailThumbnailImageView);
|
||||||
CoilUtils.dispose(binding.detailSubChannelThumbnailView);
|
CoilUtils.dispose(binding.detailSubChannelThumbnailView);
|
||||||
CoilUtils.dispose(binding.overlayThumbnail);
|
CoilUtils.dispose(binding.overlayThumbnail);
|
||||||
|
CoilUtils.dispose(binding.detailUploaderThumbnailView);
|
||||||
|
|
||||||
binding.detailThumbnailImageView.setImageBitmap(null);
|
binding.detailThumbnailImageView.setImageBitmap(null);
|
||||||
binding.detailSubChannelThumbnailView.setImageBitmap(null);
|
binding.detailSubChannelThumbnailView.setImageBitmap(null);
|
||||||
|
@ -76,8 +76,7 @@ class NotificationHelper(val context: Context) {
|
|||||||
|
|
||||||
summaryBuilder.setLargeIcon(avatarIcon)
|
summaryBuilder.setLargeIcon(avatarIcon)
|
||||||
|
|
||||||
// Show individual stream notifications, set channel icon only if there is actually
|
// Show individual stream notifications, set channel icon only if there is actually one
|
||||||
// one
|
|
||||||
showStreamNotifications(newStreams, data.serviceId, avatarIcon)
|
showStreamNotifications(newStreams, data.serviceId, avatarIcon)
|
||||||
// Show summary notification
|
// Show summary notification
|
||||||
manager.notify(data.pseudoId, summaryBuilder.build())
|
manager.notify(data.pseudoId, summaryBuilder.build())
|
||||||
|
@ -192,6 +192,8 @@ public final class Player implements PlaybackListener, Listener {
|
|||||||
private MediaItemTag currentMetadata;
|
private MediaItemTag currentMetadata;
|
||||||
@Nullable
|
@Nullable
|
||||||
private Bitmap currentThumbnail;
|
private Bitmap currentThumbnail;
|
||||||
|
@Nullable
|
||||||
|
private coil.request.Disposable thumbnailDisposable;
|
||||||
|
|
||||||
/*//////////////////////////////////////////////////////////////////////////
|
/*//////////////////////////////////////////////////////////////////////////
|
||||||
// Player
|
// Player
|
||||||
@ -772,6 +774,11 @@ public final class Player implements PlaybackListener, Listener {
|
|||||||
+ thumbnails.size() + "]");
|
+ thumbnails.size() + "]");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Cancel any ongoing image loading
|
||||||
|
if (thumbnailDisposable != null) {
|
||||||
|
thumbnailDisposable.dispose();
|
||||||
|
}
|
||||||
|
|
||||||
// Unset currentThumbnail, since it is now outdated. This ensures it is not used in media
|
// Unset currentThumbnail, since it is now outdated. This ensures it is not used in media
|
||||||
// session metadata while the new thumbnail is being loaded by Coil.
|
// session metadata while the new thumbnail is being loaded by Coil.
|
||||||
onThumbnailLoaded(null);
|
onThumbnailLoaded(null);
|
||||||
@ -780,7 +787,7 @@ public final class Player implements PlaybackListener, Listener {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// scale down the notification thumbnail for performance
|
// scale down the notification thumbnail for performance
|
||||||
final var target = new Target() {
|
final var thumbnailTarget = new Target() {
|
||||||
@Override
|
@Override
|
||||||
public void onError(@Nullable final Drawable error) {
|
public void onError(@Nullable final Drawable error) {
|
||||||
Log.e(TAG, "Thumbnail - onError() called");
|
Log.e(TAG, "Thumbnail - onError() called");
|
||||||
@ -805,7 +812,8 @@ public final class Player implements PlaybackListener, Listener {
|
|||||||
result.getIntrinsicHeight(), null));
|
result.getIntrinsicHeight(), null));
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
CoilHelper.INSTANCE.loadScaledDownThumbnail(context, thumbnails, target);
|
thumbnailDisposable = CoilHelper.INSTANCE
|
||||||
|
.loadScaledDownThumbnail(context, thumbnails, thumbnailTarget);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void onThumbnailLoaded(@Nullable final Bitmap bitmap) {
|
private void onThumbnailLoaded(@Nullable final Bitmap bitmap) {
|
||||||
|
@ -42,12 +42,8 @@ public class ContentSettingsFragment extends BasePreferenceFragment {
|
|||||||
ImageStrategy.setPreferredImageQuality(PreferredImageQuality
|
ImageStrategy.setPreferredImageQuality(PreferredImageQuality
|
||||||
.fromPreferenceKey(requireContext(), (String) newValue));
|
.fromPreferenceKey(requireContext(), (String) newValue));
|
||||||
final var loader = Coil.imageLoader(preference.getContext());
|
final var loader = Coil.imageLoader(preference.getContext());
|
||||||
if (loader.getMemoryCache() != null) {
|
loader.getMemoryCache().clear();
|
||||||
loader.getMemoryCache().clear();
|
loader.getDiskCache().clear();
|
||||||
}
|
|
||||||
if (loader.getDiskCache() != null) {
|
|
||||||
loader.getDiskCache().clear();
|
|
||||||
}
|
|
||||||
Toast.makeText(preference.getContext(),
|
Toast.makeText(preference.getContext(),
|
||||||
R.string.thumbnail_cache_wipe_complete_notice, Toast.LENGTH_SHORT)
|
R.string.thumbnail_cache_wipe_complete_notice, Toast.LENGTH_SHORT)
|
||||||
.show();
|
.show();
|
||||||
|
@ -10,6 +10,7 @@ import android.content.Intent;
|
|||||||
import android.content.pm.PackageManager;
|
import android.content.pm.PackageManager;
|
||||||
import android.content.pm.ResolveInfo;
|
import android.content.pm.ResolveInfo;
|
||||||
import android.graphics.Bitmap;
|
import android.graphics.Bitmap;
|
||||||
|
import android.graphics.BitmapFactory;
|
||||||
import android.net.Uri;
|
import android.net.Uri;
|
||||||
import android.os.Build;
|
import android.os.Build;
|
||||||
import android.text.TextUtils;
|
import android.text.TextUtils;
|
||||||
@ -24,13 +25,16 @@ import androidx.core.content.FileProvider;
|
|||||||
import org.schabi.newpipe.BuildConfig;
|
import org.schabi.newpipe.BuildConfig;
|
||||||
import org.schabi.newpipe.R;
|
import org.schabi.newpipe.R;
|
||||||
import org.schabi.newpipe.extractor.Image;
|
import org.schabi.newpipe.extractor.Image;
|
||||||
import org.schabi.newpipe.util.image.CoilHelper;
|
|
||||||
import org.schabi.newpipe.util.image.ImageStrategy;
|
import org.schabi.newpipe.util.image.ImageStrategy;
|
||||||
|
|
||||||
import java.io.File;
|
import java.nio.file.Files;
|
||||||
import java.io.FileOutputStream;
|
import java.util.Collections;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
|
import coil.Coil;
|
||||||
|
import coil.disk.DiskCache;
|
||||||
|
import coil.memory.MemoryCache;
|
||||||
|
|
||||||
public final class ShareUtils {
|
public final class ShareUtils {
|
||||||
private static final String TAG = ShareUtils.class.getSimpleName();
|
private static final String TAG = ShareUtils.class.getSimpleName();
|
||||||
|
|
||||||
@ -335,7 +339,13 @@ public final class ShareUtils {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Generate a {@link ClipData} with the image of the content shared.
|
* Generate a {@link ClipData} with the image of the content shared, if it's in the app cache.
|
||||||
|
*
|
||||||
|
* <p>
|
||||||
|
* In order not to worry about network issues (timeouts, DNS issues, low connection speed, ...)
|
||||||
|
* when sharing a content, only images in the {@link MemoryCache} or {@link DiskCache}
|
||||||
|
* used by the Coil library are used as preview images. If the thumbnail image is not in the
|
||||||
|
* cache, no {@link ClipData} will be generated and {@code null} will be returned.
|
||||||
*
|
*
|
||||||
* <p>
|
* <p>
|
||||||
* In order to display the image in the content preview of the Android share sheet, an URI of
|
* In order to display the image in the content preview of the Android share sheet, an URI of
|
||||||
@ -351,11 +361,6 @@ public final class ShareUtils {
|
|||||||
* </p>
|
* </p>
|
||||||
*
|
*
|
||||||
* <p>
|
* <p>
|
||||||
* This method will call {@link CoilHelper#loadBitmapBlocking(Context, String)} to get the
|
|
||||||
* thumbnail of the content.
|
|
||||||
* </p>
|
|
||||||
*
|
|
||||||
* <p>
|
|
||||||
* Using the result of this method when sharing has only an effect on the system share sheet (if
|
* Using the result of this method when sharing has only an effect on the system share sheet (if
|
||||||
* OEMs didn't change Android system standard behavior) on Android API 29 and higher.
|
* OEMs didn't change Android system standard behavior) on Android API 29 and higher.
|
||||||
* </p>
|
* </p>
|
||||||
@ -369,33 +374,46 @@ public final class ShareUtils {
|
|||||||
@NonNull final Context context,
|
@NonNull final Context context,
|
||||||
@NonNull final String thumbnailUrl) {
|
@NonNull final String thumbnailUrl) {
|
||||||
try {
|
try {
|
||||||
final var bitmap = CoilHelper.INSTANCE.loadBitmapBlocking(context, thumbnailUrl);
|
|
||||||
if (bitmap == null) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Save the image in memory to the application's cache because we need a URI to the
|
// Save the image in memory to the application's cache because we need a URI to the
|
||||||
// image to generate a ClipData which will show the share sheet, and so an image file
|
// image to generate a ClipData which will show the share sheet, and so an image file
|
||||||
final Context applicationContext = context.getApplicationContext();
|
final Context applicationContext = context.getApplicationContext();
|
||||||
final String appFolder = applicationContext.getCacheDir().getAbsolutePath();
|
final var loader = Coil.imageLoader(context);
|
||||||
final File thumbnailPreviewFile = new File(appFolder
|
final var value = loader.getMemoryCache()
|
||||||
+ "/android_share_sheet_image_preview.jpg");
|
.get(new MemoryCache.Key(thumbnailUrl, Collections.emptyMap()));
|
||||||
|
|
||||||
// Any existing file will be overwritten with FileOutputStream
|
final Bitmap cachedBitmap;
|
||||||
final FileOutputStream fileOutputStream = new FileOutputStream(thumbnailPreviewFile);
|
if (value != null) {
|
||||||
bitmap.compress(Bitmap.CompressFormat.JPEG, 90, fileOutputStream);
|
cachedBitmap = value.getBitmap();
|
||||||
fileOutputStream.close();
|
} else {
|
||||||
|
try (var snapshot = loader.getDiskCache().openSnapshot(thumbnailUrl)) {
|
||||||
|
if (snapshot != null) {
|
||||||
|
cachedBitmap = BitmapFactory.decodeFile(snapshot.getData().toString());
|
||||||
|
} else {
|
||||||
|
cachedBitmap = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (cachedBitmap == null) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
final var path = applicationContext.getCacheDir().toPath()
|
||||||
|
.resolve("android_share_sheet_image_preview.jpg");
|
||||||
|
// Any existing file will be overwritten
|
||||||
|
try (var outputStream = Files.newOutputStream(path)) {
|
||||||
|
cachedBitmap.compress(Bitmap.CompressFormat.JPEG, 90, outputStream);
|
||||||
|
}
|
||||||
|
|
||||||
final ClipData clipData = ClipData.newUri(applicationContext.getContentResolver(), "",
|
final ClipData clipData = ClipData.newUri(applicationContext.getContentResolver(), "",
|
||||||
FileProvider.getUriForFile(applicationContext,
|
FileProvider.getUriForFile(applicationContext,
|
||||||
BuildConfig.APPLICATION_ID + ".provider",
|
BuildConfig.APPLICATION_ID + ".provider",
|
||||||
thumbnailPreviewFile));
|
path.toFile()));
|
||||||
|
|
||||||
if (DEBUG) {
|
if (DEBUG) {
|
||||||
Log.d(TAG, "ClipData successfully generated for Android share sheet: " + clipData);
|
Log.d(TAG, "ClipData successfully generated for Android share sheet: " + clipData);
|
||||||
}
|
}
|
||||||
return clipData;
|
return clipData;
|
||||||
|
|
||||||
} catch (final Exception e) {
|
} catch (final Exception e) {
|
||||||
Log.w(TAG, "Error when setting preview image for share sheet", e);
|
Log.w(TAG, "Error when setting preview image for share sheet", e);
|
||||||
return null;
|
return null;
|
||||||
|
@ -8,6 +8,7 @@ import androidx.annotation.DrawableRes
|
|||||||
import androidx.core.graphics.drawable.toBitmapOrNull
|
import androidx.core.graphics.drawable.toBitmapOrNull
|
||||||
import coil.executeBlocking
|
import coil.executeBlocking
|
||||||
import coil.imageLoader
|
import coil.imageLoader
|
||||||
|
import coil.request.Disposable
|
||||||
import coil.request.ImageRequest
|
import coil.request.ImageRequest
|
||||||
import coil.size.Size
|
import coil.size.Size
|
||||||
import coil.target.Target
|
import coil.target.Target
|
||||||
@ -47,7 +48,7 @@ object CoilHelper {
|
|||||||
loadImageDefault(target, url, R.drawable.placeholder_thumbnail_video)
|
loadImageDefault(target, url, R.drawable.placeholder_thumbnail_video)
|
||||||
}
|
}
|
||||||
|
|
||||||
fun loadScaledDownThumbnail(context: Context, images: List<Image>, target: Target) {
|
fun loadScaledDownThumbnail(context: Context, images: List<Image>, target: Target): Disposable {
|
||||||
val url = ImageStrategy.choosePreferredImage(images)
|
val url = ImageStrategy.choosePreferredImage(images)
|
||||||
val request = getImageRequest(context, url, R.drawable.placeholder_thumbnail_video)
|
val request = getImageRequest(context, url, R.drawable.placeholder_thumbnail_video)
|
||||||
.target(target)
|
.target(target)
|
||||||
@ -79,7 +80,7 @@ object CoilHelper {
|
|||||||
})
|
})
|
||||||
.build()
|
.build()
|
||||||
|
|
||||||
context.imageLoader.enqueue(request)
|
return context.imageLoader.enqueue(request)
|
||||||
}
|
}
|
||||||
|
|
||||||
fun loadDetailsThumbnail(target: ImageView, images: List<Image>) {
|
fun loadDetailsThumbnail(target: ImageView, images: List<Image>) {
|
||||||
@ -133,6 +134,8 @@ object CoilHelper {
|
|||||||
return ImageRequest.Builder(context)
|
return ImageRequest.Builder(context)
|
||||||
.data(takenUrl)
|
.data(takenUrl)
|
||||||
.error(placeholderResId)
|
.error(placeholderResId)
|
||||||
|
.memoryCacheKey(takenUrl)
|
||||||
|
.diskCacheKey(takenUrl)
|
||||||
.apply {
|
.apply {
|
||||||
if (takenUrl != null || showPlaceholderWhileLoading) {
|
if (takenUrl != null || showPlaceholderWhileLoading) {
|
||||||
placeholder(placeholderResId)
|
placeholder(placeholderResId)
|
||||||
|
Loading…
Reference in New Issue
Block a user