Nicer placeholder images (#5679)
Shows randomly generated placeholder images for: - Feeds that do not have a cover (usually happens for text-only feeds) - Feeds that specify an invalid cover still show a gray square - Local folders when there is no image file in the folder that we could use
This commit is contained in:
parent
08bd963fd9
commit
d953ad0869
@ -33,7 +33,6 @@ import java.util.Locale;
|
|||||||
|
|
||||||
import de.danoeh.antennapod.R;
|
import de.danoeh.antennapod.R;
|
||||||
import de.danoeh.antennapod.activity.MainActivity;
|
import de.danoeh.antennapod.activity.MainActivity;
|
||||||
import de.danoeh.antennapod.core.feed.LocalFeedUpdater;
|
|
||||||
import de.danoeh.antennapod.core.preferences.UserPreferences;
|
import de.danoeh.antennapod.core.preferences.UserPreferences;
|
||||||
import de.danoeh.antennapod.core.storage.NavDrawerData;
|
import de.danoeh.antennapod.core.storage.NavDrawerData;
|
||||||
import de.danoeh.antennapod.fragment.FeedItemlistFragment;
|
import de.danoeh.antennapod.fragment.FeedItemlistFragment;
|
||||||
@ -255,7 +254,7 @@ public class SubscriptionsRecyclerAdapter extends SelectableAdapter<Subscription
|
|||||||
if (drawerItem.type == NavDrawerData.DrawerItem.Type.FEED) {
|
if (drawerItem.type == NavDrawerData.DrawerItem.Type.FEED) {
|
||||||
Feed feed = ((NavDrawerData.FeedDrawerItem) drawerItem).feed;
|
Feed feed = ((NavDrawerData.FeedDrawerItem) drawerItem).feed;
|
||||||
boolean textAndImageCombind = feed.isLocalFeed()
|
boolean textAndImageCombind = feed.isLocalFeed()
|
||||||
&& LocalFeedUpdater.getDefaultIconUrl(itemView.getContext()).equals(feed.getImageUrl());
|
&& feed.getImageUrl() != null && feed.getImageUrl().startsWith(Feed.PREFIX_GENERATIVE_COVER);
|
||||||
new CoverLoader(mainActivityRef.get())
|
new CoverLoader(mainActivityRef.get())
|
||||||
.withUri(feed.getImageUrl())
|
.withUri(feed.getImageUrl())
|
||||||
.withPlaceholderView(feedTitle, textAndImageCombind)
|
.withPlaceholderView(feedTitle, textAndImageCombind)
|
||||||
|
@ -1,6 +1,5 @@
|
|||||||
package de.danoeh.antennapod.core.feed;
|
package de.danoeh.antennapod.core.feed;
|
||||||
|
|
||||||
import android.content.ContentResolver;
|
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.media.MediaMetadataRetriever;
|
import android.media.MediaMetadataRetriever;
|
||||||
import android.net.Uri;
|
import android.net.Uri;
|
||||||
@ -104,7 +103,7 @@ public class LocalFeedUpdater {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
feed.setImageUrl(getImageUrl(context, documentFolder));
|
feed.setImageUrl(getImageUrl(documentFolder));
|
||||||
|
|
||||||
feed.getPreferences().setAutoDownload(false);
|
feed.getPreferences().setAutoDownload(false);
|
||||||
feed.getPreferences().setAutoDeleteAction(FeedPreferences.AutoDeleteAction.NO);
|
feed.getPreferences().setAutoDeleteAction(FeedPreferences.AutoDeleteAction.NO);
|
||||||
@ -122,7 +121,7 @@ public class LocalFeedUpdater {
|
|||||||
* Returns the image URL for the local feed.
|
* Returns the image URL for the local feed.
|
||||||
*/
|
*/
|
||||||
@NonNull
|
@NonNull
|
||||||
static String getImageUrl(@NonNull Context context, @NonNull DocumentFile documentFolder) {
|
static String getImageUrl(@NonNull DocumentFile documentFolder) {
|
||||||
// look for special file names
|
// look for special file names
|
||||||
for (String iconLocation : PREFERRED_FEED_IMAGE_FILENAMES) {
|
for (String iconLocation : PREFERRED_FEED_IMAGE_FILENAMES) {
|
||||||
DocumentFile image = documentFolder.findFile(iconLocation);
|
DocumentFile image = documentFolder.findFile(iconLocation);
|
||||||
@ -140,17 +139,7 @@ public class LocalFeedUpdater {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// use default icon as fallback
|
// use default icon as fallback
|
||||||
return getDefaultIconUrl(context);
|
return Feed.PREFIX_GENERATIVE_COVER + documentFolder.getUri();
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns the URL of the default icon for a local feed. The URL refers to an app resource file.
|
|
||||||
*/
|
|
||||||
public static String getDefaultIconUrl(Context context) {
|
|
||||||
String resourceEntryName = context.getResources().getResourceEntryName(R.raw.local_feed_default_icon);
|
|
||||||
return ContentResolver.SCHEME_ANDROID_RESOURCE + "://"
|
|
||||||
+ context.getPackageName() + "/raw/"
|
|
||||||
+ resourceEntryName;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private static FeedItem feedContainsFile(Feed feed, String filename) {
|
private static FeedItem feedContainsFile(Feed feed, String filename) {
|
||||||
|
@ -42,6 +42,7 @@ public class ApGlideModule extends AppGlideModule {
|
|||||||
@Override
|
@Override
|
||||||
public void registerComponents(@NonNull Context context, @NonNull Glide glide, @NonNull Registry registry) {
|
public void registerComponents(@NonNull Context context, @NonNull Glide glide, @NonNull Registry registry) {
|
||||||
registry.replace(String.class, InputStream.class, new MetadataRetrieverLoader.Factory(context));
|
registry.replace(String.class, InputStream.class, new MetadataRetrieverLoader.Factory(context));
|
||||||
|
registry.append(String.class, InputStream.class, new GenerativePlaceholderImageModelLoader.Factory());
|
||||||
registry.append(String.class, InputStream.class, new ApOkHttpUrlLoader.Factory());
|
registry.append(String.class, InputStream.class, new ApOkHttpUrlLoader.Factory());
|
||||||
registry.append(String.class, InputStream.class, new NoHttpStringLoader.StreamFactory());
|
registry.append(String.class, InputStream.class, new NoHttpStringLoader.StreamFactory());
|
||||||
|
|
||||||
|
@ -0,0 +1,139 @@
|
|||||||
|
package de.danoeh.antennapod.core.glide;
|
||||||
|
|
||||||
|
import android.graphics.Bitmap;
|
||||||
|
import android.graphics.Canvas;
|
||||||
|
import android.graphics.LinearGradient;
|
||||||
|
import android.graphics.Paint;
|
||||||
|
import android.graphics.PorterDuff;
|
||||||
|
import android.graphics.PorterDuffColorFilter;
|
||||||
|
import android.graphics.Shader;
|
||||||
|
import androidx.annotation.NonNull;
|
||||||
|
import com.bumptech.glide.Priority;
|
||||||
|
import com.bumptech.glide.load.DataSource;
|
||||||
|
import com.bumptech.glide.load.Options;
|
||||||
|
import com.bumptech.glide.load.data.DataFetcher;
|
||||||
|
import com.bumptech.glide.load.model.ModelLoader;
|
||||||
|
import com.bumptech.glide.load.model.ModelLoaderFactory;
|
||||||
|
import com.bumptech.glide.load.model.MultiModelLoaderFactory;
|
||||||
|
import com.bumptech.glide.signature.ObjectKey;
|
||||||
|
import de.danoeh.antennapod.model.feed.Feed;
|
||||||
|
|
||||||
|
import java.io.ByteArrayInputStream;
|
||||||
|
import java.io.ByteArrayOutputStream;
|
||||||
|
import java.io.InputStream;
|
||||||
|
import java.util.Random;
|
||||||
|
|
||||||
|
public final class GenerativePlaceholderImageModelLoader implements ModelLoader<String, InputStream> {
|
||||||
|
|
||||||
|
public static class Factory implements ModelLoaderFactory<String, InputStream> {
|
||||||
|
@NonNull
|
||||||
|
@Override
|
||||||
|
public ModelLoader<String, InputStream> build(@NonNull MultiModelLoaderFactory unused) {
|
||||||
|
return new GenerativePlaceholderImageModelLoader();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void teardown() {
|
||||||
|
// Do nothing.
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public LoadData<InputStream> buildLoadData(@NonNull String model, int width, int height, @NonNull Options options) {
|
||||||
|
return new LoadData<>(new ObjectKey(model), new EmbeddedImageFetcher(model, width, height));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean handles(@NonNull String model) {
|
||||||
|
return model.startsWith(Feed.PREFIX_GENERATIVE_COVER);
|
||||||
|
}
|
||||||
|
|
||||||
|
static class EmbeddedImageFetcher implements DataFetcher<InputStream> {
|
||||||
|
private static final int[] PALETTES = {0xff78909c, 0xffff6f00, 0xff388e3c,
|
||||||
|
0xff00838f, 0xff7b1fa2, 0xffb71c1c, 0xff2196f3};
|
||||||
|
private final String model;
|
||||||
|
private final int width;
|
||||||
|
private final int height;
|
||||||
|
|
||||||
|
public EmbeddedImageFetcher(String model, int width, int height) {
|
||||||
|
this.model = model;
|
||||||
|
this.width = width;
|
||||||
|
this.height = height;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void loadData(@NonNull Priority priority, @NonNull DataCallback<? super InputStream> callback) {
|
||||||
|
final Bitmap bitmap = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888);
|
||||||
|
final Canvas canvas = new Canvas(bitmap);
|
||||||
|
final Random generator = new Random(model.hashCode());
|
||||||
|
final int lineGridSteps = 4 + generator.nextInt(4);
|
||||||
|
final int slope = width / 4;
|
||||||
|
final float shadowWidth = width * 0.01f;
|
||||||
|
final float lineDistance = ((float) width / (lineGridSteps - 2));
|
||||||
|
final int baseColor = PALETTES[generator.nextInt(PALETTES.length)];
|
||||||
|
|
||||||
|
Paint paint = new Paint();
|
||||||
|
int color = randomShadeOfGrey(generator);
|
||||||
|
paint.setColor(color);
|
||||||
|
paint.setStrokeWidth(lineDistance);
|
||||||
|
paint.setColorFilter(new PorterDuffColorFilter(baseColor, PorterDuff.Mode.MULTIPLY));
|
||||||
|
Paint paintShadow = new Paint();
|
||||||
|
paintShadow.setColor(0xff000000);
|
||||||
|
paintShadow.setStrokeWidth(lineDistance);
|
||||||
|
|
||||||
|
int forcedColorChange = 1 + generator.nextInt(lineGridSteps - 2);
|
||||||
|
for (int i = lineGridSteps - 1; i >= 0; i--) {
|
||||||
|
float linePos = (i - 0.5f) * lineDistance;
|
||||||
|
boolean switchColor = generator.nextFloat() < 0.3f || i == forcedColorChange;
|
||||||
|
if (switchColor) {
|
||||||
|
int newColor = color;
|
||||||
|
while (newColor == color) {
|
||||||
|
newColor = randomShadeOfGrey(generator);
|
||||||
|
}
|
||||||
|
color = newColor;
|
||||||
|
paint.setColor(newColor);
|
||||||
|
canvas.drawLine(linePos + slope + shadowWidth, -slope,
|
||||||
|
linePos - slope + shadowWidth, height + slope, paintShadow);
|
||||||
|
}
|
||||||
|
canvas.drawLine(linePos + slope, -slope,
|
||||||
|
linePos - slope, height + slope, paint);
|
||||||
|
}
|
||||||
|
|
||||||
|
Paint gradientPaint = new Paint();
|
||||||
|
paint.setDither(true);
|
||||||
|
gradientPaint.setShader(new LinearGradient(0, 0, 0, height, 0x00000000, 0x55000000, Shader.TileMode.CLAMP));
|
||||||
|
canvas.drawRect(0, 0, width, height, gradientPaint);
|
||||||
|
|
||||||
|
ByteArrayOutputStream baos = new ByteArrayOutputStream();
|
||||||
|
bitmap.compress(Bitmap.CompressFormat.JPEG, 100, baos);
|
||||||
|
InputStream is = new ByteArrayInputStream(baos.toByteArray());
|
||||||
|
callback.onDataReady(is);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static int randomShadeOfGrey(Random generator) {
|
||||||
|
return 0xff777777 + 0x222222 * generator.nextInt(5);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void cleanup() {
|
||||||
|
// nothing to clean up
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void cancel() {
|
||||||
|
// cannot cancel
|
||||||
|
}
|
||||||
|
|
||||||
|
@NonNull
|
||||||
|
@Override
|
||||||
|
public Class<InputStream> getDataClass() {
|
||||||
|
return InputStream.class;
|
||||||
|
}
|
||||||
|
|
||||||
|
@NonNull
|
||||||
|
@Override
|
||||||
|
public DataSource getDataSource() {
|
||||||
|
return DataSource.LOCAL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -1,5 +1,6 @@
|
|||||||
package de.danoeh.antennapod.core.service.download.handler;
|
package de.danoeh.antennapod.core.service.download.handler;
|
||||||
|
|
||||||
|
import android.text.TextUtils;
|
||||||
import android.util.Log;
|
import android.util.Log;
|
||||||
import de.danoeh.antennapod.model.feed.Feed;
|
import de.danoeh.antennapod.model.feed.Feed;
|
||||||
import de.danoeh.antennapod.model.feed.FeedItem;
|
import de.danoeh.antennapod.model.feed.FeedItem;
|
||||||
@ -48,6 +49,9 @@ public class FeedParserTask implements Callable<FeedHandlerResult> {
|
|||||||
result = feedHandler.parseFeed(feed);
|
result = feedHandler.parseFeed(feed);
|
||||||
Log.d(TAG, feed.getTitle() + " parsed");
|
Log.d(TAG, feed.getTitle() + " parsed");
|
||||||
checkFeedData(feed);
|
checkFeedData(feed);
|
||||||
|
if (TextUtils.isEmpty(feed.getImageUrl())) {
|
||||||
|
feed.setImageUrl(Feed.PREFIX_GENERATIVE_COVER + feed.getDownload_url());
|
||||||
|
}
|
||||||
} catch (SAXException | IOException | ParserConfigurationException e) {
|
} catch (SAXException | IOException | ParserConfigurationException e) {
|
||||||
successful = false;
|
successful = false;
|
||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
|
Binary file not shown.
Before Width: | Height: | Size: 1.2 KiB |
@ -31,7 +31,6 @@ import java.util.List;
|
|||||||
|
|
||||||
import de.danoeh.antennapod.core.ApplicationCallbacks;
|
import de.danoeh.antennapod.core.ApplicationCallbacks;
|
||||||
import de.danoeh.antennapod.core.ClientConfig;
|
import de.danoeh.antennapod.core.ClientConfig;
|
||||||
import de.danoeh.antennapod.core.R;
|
|
||||||
import de.danoeh.antennapod.core.preferences.UserPreferences;
|
import de.danoeh.antennapod.core.preferences.UserPreferences;
|
||||||
import de.danoeh.antennapod.core.storage.DBReader;
|
import de.danoeh.antennapod.core.storage.DBReader;
|
||||||
import de.danoeh.antennapod.core.storage.DBWriter;
|
import de.danoeh.antennapod.core.storage.DBWriter;
|
||||||
@ -41,6 +40,7 @@ import static org.hamcrest.CoreMatchers.endsWith;
|
|||||||
import static org.hamcrest.CoreMatchers.is;
|
import static org.hamcrest.CoreMatchers.is;
|
||||||
import static org.hamcrest.MatcherAssert.assertThat;
|
import static org.hamcrest.MatcherAssert.assertThat;
|
||||||
import static org.hamcrest.Matchers.empty;
|
import static org.hamcrest.Matchers.empty;
|
||||||
|
import static org.hamcrest.Matchers.startsWith;
|
||||||
import static org.junit.Assert.assertEquals;
|
import static org.junit.Assert.assertEquals;
|
||||||
import static org.mockito.Mockito.any;
|
import static org.mockito.Mockito.any;
|
||||||
import static org.mockito.Mockito.mock;
|
import static org.mockito.Mockito.mock;
|
||||||
@ -158,8 +158,7 @@ public class LocalFeedUpdaterTest {
|
|||||||
callUpdateFeed(LOCAL_FEED_DIR1);
|
callUpdateFeed(LOCAL_FEED_DIR1);
|
||||||
|
|
||||||
Feed feedAfter = verifySingleFeedInDatabase();
|
Feed feedAfter = verifySingleFeedInDatabase();
|
||||||
String resourceEntryName = context.getResources().getResourceEntryName(R.raw.local_feed_default_icon);
|
assertThat(feedAfter.getImageUrl(), startsWith(Feed.PREFIX_GENERATIVE_COVER));
|
||||||
assertThat(feedAfter.getImageUrl(), endsWith(resourceEntryName));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -191,17 +190,15 @@ public class LocalFeedUpdaterTest {
|
|||||||
@Test
|
@Test
|
||||||
public void testGetImageUrl_EmptyFolder() {
|
public void testGetImageUrl_EmptyFolder() {
|
||||||
DocumentFile documentFolder = mockDocumentFolder();
|
DocumentFile documentFolder = mockDocumentFolder();
|
||||||
String imageUrl = LocalFeedUpdater.getImageUrl(context, documentFolder);
|
String imageUrl = LocalFeedUpdater.getImageUrl(documentFolder);
|
||||||
String defaultImageName = context.getResources().getResourceEntryName(R.raw.local_feed_default_icon);
|
assertThat(imageUrl, startsWith(Feed.PREFIX_GENERATIVE_COVER));
|
||||||
assertThat(imageUrl, endsWith(defaultImageName));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testGetImageUrl_NoImageButAudioFiles() {
|
public void testGetImageUrl_NoImageButAudioFiles() {
|
||||||
DocumentFile documentFolder = mockDocumentFolder(mockDocumentFile("audio.mp3", "audio/mp3"));
|
DocumentFile documentFolder = mockDocumentFolder(mockDocumentFile("audio.mp3", "audio/mp3"));
|
||||||
String imageUrl = LocalFeedUpdater.getImageUrl(context, documentFolder);
|
String imageUrl = LocalFeedUpdater.getImageUrl(documentFolder);
|
||||||
String defaultImageName = context.getResources().getResourceEntryName(R.raw.local_feed_default_icon);
|
assertThat(imageUrl, startsWith(Feed.PREFIX_GENERATIVE_COVER));
|
||||||
assertThat(imageUrl, endsWith(defaultImageName));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@ -209,7 +206,7 @@ public class LocalFeedUpdaterTest {
|
|||||||
for (String filename : LocalFeedUpdater.PREFERRED_FEED_IMAGE_FILENAMES) {
|
for (String filename : LocalFeedUpdater.PREFERRED_FEED_IMAGE_FILENAMES) {
|
||||||
DocumentFile documentFolder = mockDocumentFolder(mockDocumentFile("audio.mp3", "audio/mp3"),
|
DocumentFile documentFolder = mockDocumentFolder(mockDocumentFile("audio.mp3", "audio/mp3"),
|
||||||
mockDocumentFile(filename, "image/jpeg")); // image MIME type doesn't matter
|
mockDocumentFile(filename, "image/jpeg")); // image MIME type doesn't matter
|
||||||
String imageUrl = LocalFeedUpdater.getImageUrl(context, documentFolder);
|
String imageUrl = LocalFeedUpdater.getImageUrl(documentFolder);
|
||||||
assertThat(imageUrl, endsWith(filename));
|
assertThat(imageUrl, endsWith(filename));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -218,7 +215,7 @@ public class LocalFeedUpdaterTest {
|
|||||||
public void testGetImageUrl_OtherImageFilenameJpg() {
|
public void testGetImageUrl_OtherImageFilenameJpg() {
|
||||||
DocumentFile documentFolder = mockDocumentFolder(mockDocumentFile("audio.mp3", "audio/mp3"),
|
DocumentFile documentFolder = mockDocumentFolder(mockDocumentFile("audio.mp3", "audio/mp3"),
|
||||||
mockDocumentFile("my-image.jpg", "image/jpeg"));
|
mockDocumentFile("my-image.jpg", "image/jpeg"));
|
||||||
String imageUrl = LocalFeedUpdater.getImageUrl(context, documentFolder);
|
String imageUrl = LocalFeedUpdater.getImageUrl(documentFolder);
|
||||||
assertThat(imageUrl, endsWith("my-image.jpg"));
|
assertThat(imageUrl, endsWith("my-image.jpg"));
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -226,7 +223,7 @@ public class LocalFeedUpdaterTest {
|
|||||||
public void testGetImageUrl_OtherImageFilenameJpeg() {
|
public void testGetImageUrl_OtherImageFilenameJpeg() {
|
||||||
DocumentFile documentFolder = mockDocumentFolder(mockDocumentFile("audio.mp3", "audio/mp3"),
|
DocumentFile documentFolder = mockDocumentFolder(mockDocumentFile("audio.mp3", "audio/mp3"),
|
||||||
mockDocumentFile("my-image.jpeg", "image/jpeg"));
|
mockDocumentFile("my-image.jpeg", "image/jpeg"));
|
||||||
String imageUrl = LocalFeedUpdater.getImageUrl(context, documentFolder);
|
String imageUrl = LocalFeedUpdater.getImageUrl(documentFolder);
|
||||||
assertThat(imageUrl, endsWith("my-image.jpeg"));
|
assertThat(imageUrl, endsWith("my-image.jpeg"));
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -234,7 +231,7 @@ public class LocalFeedUpdaterTest {
|
|||||||
public void testGetImageUrl_OtherImageFilenamePng() {
|
public void testGetImageUrl_OtherImageFilenamePng() {
|
||||||
DocumentFile documentFolder = mockDocumentFolder(mockDocumentFile("audio.mp3", "audio/mp3"),
|
DocumentFile documentFolder = mockDocumentFolder(mockDocumentFile("audio.mp3", "audio/mp3"),
|
||||||
mockDocumentFile("my-image.png", "image/png"));
|
mockDocumentFile("my-image.png", "image/png"));
|
||||||
String imageUrl = LocalFeedUpdater.getImageUrl(context, documentFolder);
|
String imageUrl = LocalFeedUpdater.getImageUrl(documentFolder);
|
||||||
assertThat(imageUrl, endsWith("my-image.png"));
|
assertThat(imageUrl, endsWith("my-image.png"));
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -242,9 +239,8 @@ public class LocalFeedUpdaterTest {
|
|||||||
public void testGetImageUrl_OtherImageFilenameUnsupportedMimeType() {
|
public void testGetImageUrl_OtherImageFilenameUnsupportedMimeType() {
|
||||||
DocumentFile documentFolder = mockDocumentFolder(mockDocumentFile("audio.mp3", "audio/mp3"),
|
DocumentFile documentFolder = mockDocumentFolder(mockDocumentFile("audio.mp3", "audio/mp3"),
|
||||||
mockDocumentFile("my-image.svg", "image/svg+xml"));
|
mockDocumentFile("my-image.svg", "image/svg+xml"));
|
||||||
String imageUrl = LocalFeedUpdater.getImageUrl(context, documentFolder);
|
String imageUrl = LocalFeedUpdater.getImageUrl(documentFolder);
|
||||||
String defaultImageName = context.getResources().getResourceEntryName(R.raw.local_feed_default_icon);
|
assertThat(imageUrl, startsWith(Feed.PREFIX_GENERATIVE_COVER));
|
||||||
assertThat(imageUrl, endsWith(defaultImageName));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -19,6 +19,7 @@ public class Feed extends FeedFile {
|
|||||||
public static final String TYPE_RSS2 = "rss";
|
public static final String TYPE_RSS2 = "rss";
|
||||||
public static final String TYPE_ATOM1 = "atom";
|
public static final String TYPE_ATOM1 = "atom";
|
||||||
public static final String PREFIX_LOCAL_FOLDER = "antennapod_local:";
|
public static final String PREFIX_LOCAL_FOLDER = "antennapod_local:";
|
||||||
|
public static final String PREFIX_GENERATIVE_COVER = "antennapod_generative_cover:";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* title as defined by the feed.
|
* title as defined by the feed.
|
||||||
|
Loading…
x
Reference in New Issue
Block a user