Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add preference to show subscription title #5538

Merged
merged 3 commits into from Dec 1, 2021
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
1 change: 1 addition & 0 deletions app/build.gradle
Expand Up @@ -131,6 +131,7 @@ dependencies {
implementation 'androidx.viewpager2:viewpager2:1.1.0-beta01'
implementation "androidx.work:work-runtime:$workManagerVersion"
implementation "com.google.android.material:material:$googleMaterialVersion"
implementation 'androidx.palette:palette:1.0.0'

implementation "org.apache.commons:commons-lang3:$commonslangVersion"
implementation "commons-io:commons-io:$commonsioVersion"
Expand Down
41 changes: 32 additions & 9 deletions app/src/main/java/de/danoeh/antennapod/adapter/CoverLoader.java
Expand Up @@ -3,6 +3,9 @@
import android.graphics.drawable.Drawable;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.core.graphics.ColorUtils;
import androidx.palette.graphics.Palette;

import android.view.View;
import android.widget.ImageView;
import android.widget.TextView;
Expand All @@ -19,6 +22,9 @@
import de.danoeh.antennapod.R;
import de.danoeh.antennapod.activity.MainActivity;
import de.danoeh.antennapod.core.glide.ApGlideSettings;
import de.danoeh.antennapod.core.glide.PaletteBitmap;
import de.danoeh.antennapod.core.preferences.UserPreferences;
import de.danoeh.antennapod.ui.common.ThemeUtils;

public class CoverLoader {
private int resource = 0;
Expand Down Expand Up @@ -77,7 +83,7 @@ public void load() {
if (resource != 0) {
Glide.with(activity).clear(coverTarget);
imgvCover.setImageResource(resource);
CoverTarget.setPlaceholderVisibility(txtvPlaceholder, textAndImageCombined);
CoverTarget.setPlaceholderVisibility(txtvPlaceholder, textAndImageCombined, null);
return;
}

Expand All @@ -86,20 +92,22 @@ public void load() {
.fitCenter()
.dontAnimate();

RequestBuilder<Drawable> builder = Glide.with(activity)
RequestBuilder<PaletteBitmap> builder = Glide.with(activity)
.as(PaletteBitmap.class)
.load(uri)
.apply(options);

if (fallbackUri != null && txtvPlaceholder != null && imgvCover != null) {
builder = builder.error(Glide.with(activity)
.as(PaletteBitmap.class)
.load(fallbackUri)
.apply(options));
}

builder.into(coverTarget);
}

static class CoverTarget extends CustomViewTarget<ImageView, Drawable> {
static class CoverTarget extends CustomViewTarget<ImageView, PaletteBitmap> {
private final WeakReference<TextView> placeholder;
private final WeakReference<ImageView> cover;
private boolean textAndImageCombined;
Expand All @@ -120,23 +128,38 @@ public void onLoadFailed(Drawable errorDrawable) {
}

@Override
public void onResourceReady(@NonNull Drawable resource, @Nullable Transition<? super Drawable> transition) {
setPlaceholderVisibility(placeholder.get(), textAndImageCombined);
public void onResourceReady(@NonNull PaletteBitmap resource,
@Nullable Transition<? super PaletteBitmap> transition) {
ImageView ivCover = cover.get();
ivCover.setImageDrawable(resource);
ivCover.setImageBitmap(resource.bitmap);
setPlaceholderVisibility(placeholder.get(), textAndImageCombined, resource.palette);
}

@Override
protected void onResourceCleared(@Nullable Drawable placeholder) {
ImageView ivCover = cover.get();
ivCover.setImageDrawable(placeholder);
setPlaceholderVisibility(this.placeholder.get(), textAndImageCombined, null);
}

static void setPlaceholderVisibility(TextView placeholder, boolean textAndImageCombined) {
static void setPlaceholderVisibility(TextView placeholder, boolean textAndImageCombined, Palette palette) {
boolean showTitle = UserPreferences.shouldShowSubscriptionTitle();
if (placeholder != null) {
if (textAndImageCombined) {
if (textAndImageCombined || showTitle) {
int bgColor = placeholder.getContext().getResources().getColor(R.color.feed_text_bg);
placeholder.setBackgroundColor(bgColor);
if (palette == null || !showTitle) {
placeholder.setBackgroundColor(bgColor);
placeholder.setTextColor(ThemeUtils.getColorFromAttr(placeholder.getContext(),
android.R.attr.textColorPrimary));
return;
}
int dominantColor = palette.getDominantColor(bgColor);
int textColor = placeholder.getContext().getResources().getColor(R.color.white);
if (ColorUtils.calculateLuminance(dominantColor) > 0.5) {
textColor = placeholder.getContext().getResources().getColor(R.color.black);
}
placeholder.setTextColor(textColor);
placeholder.setBackgroundColor(dominantColor);
} else {
placeholder.setVisibility(View.INVISIBLE);
}
Expand Down
Expand Up @@ -12,6 +12,7 @@
import android.widget.CheckBox;
import android.widget.FrameLayout;
import android.widget.ImageView;
import android.widget.RelativeLayout;
import android.widget.TextView;

import androidx.annotation.NonNull;
Expand All @@ -29,6 +30,7 @@
import de.danoeh.antennapod.R;
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.storage.NavDrawerData;
import de.danoeh.antennapod.fragment.FeedItemlistFragment;
import de.danoeh.antennapod.fragment.SubscriptionFragment;
Expand All @@ -40,6 +42,8 @@
*/
public class SubscriptionsRecyclerAdapter extends SelectableAdapter<SubscriptionsRecyclerAdapter.SubscriptionViewHolder>
implements View.OnCreateContextMenuListener {
private static final int COVER_WITH_TITLE = 1;

private final WeakReference<MainActivity> mainActivityRef;
private List<NavDrawerData.DrawerItem> listItems;
private Feed selectedFeed = null;
Expand All @@ -64,6 +68,23 @@ public Feed getSelectedFeed() {
@Override
public SubscriptionViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
View itemView = LayoutInflater.from(mainActivityRef.get()).inflate(R.layout.subscription_item, parent, false);
TextView feedTitle = itemView.findViewById(R.id.txtvTitle);
RelativeLayout.LayoutParams params = (RelativeLayout.LayoutParams) feedTitle.getLayoutParams();
int topAndBottomItemId = R.id.imgvCover;
int belowItemId = 0;

if (viewType == COVER_WITH_TITLE) {
topAndBottomItemId = 0;
belowItemId = R.id.imgvCover;
feedTitle.setBackgroundColor(feedTitle.getContext().getResources().getColor(R.color.feed_text_bg));
int padding = (int) convertDpToPixel(feedTitle.getContext(), 6);
feedTitle.setPadding(padding, padding, padding, padding);
}
params.addRule(RelativeLayout.BELOW, belowItemId);
params.addRule(RelativeLayout.ALIGN_TOP, topAndBottomItemId);
params.addRule(RelativeLayout.ALIGN_BOTTOM, topAndBottomItemId);
feedTitle.setLayoutParams(params);
feedTitle.setSingleLine(viewType == COVER_WITH_TITLE);
return new SubscriptionViewHolder(itemView);
}

Expand Down Expand Up @@ -171,6 +192,11 @@ public void setSelected(int pos, boolean selected) {
}
}

@Override
public int getItemViewType(int position) {
return UserPreferences.shouldShowSubscriptionTitle() ? COVER_WITH_TITLE : 0;
}

public class SubscriptionViewHolder extends RecyclerView.ViewHolder {
private final TextView feedTitle;
private final ImageView imageView;
Expand Down
5 changes: 5 additions & 0 deletions app/src/main/res/xml/preferences_user_interface.xml
Expand Up @@ -44,6 +44,11 @@
android:title="@string/pref_filter_feed_title"
android:key="prefSubscriptionsFilter"
android:summary="@string/pref_filter_feed_sum" />
<SwitchPreferenceCompat
android:title="@string/pref_show_subscription_title"
android:key="prefSubscriptionTitle"
android:summary="@string/pref_show_subscription_title_summary"
android:defaultValue="false" />
</PreferenceCategory>
<PreferenceCategory android:title="@string/external_elements">
<SwitchPreferenceCompat
Expand Down
1 change: 1 addition & 0 deletions core/build.gradle
Expand Up @@ -40,6 +40,7 @@ dependencies {
implementation "androidx.preference:preference:$preferenceVersion"
implementation "androidx.work:work-runtime:$workManagerVersion"
implementation "com.google.android.material:material:$googleMaterialVersion"
implementation 'androidx.palette:palette:1.0.0'

implementation "org.apache.commons:commons-lang3:$commonslangVersion"
implementation "commons-io:commons-io:$commonsioVersion"
Expand Down
Expand Up @@ -2,6 +2,7 @@

import android.annotation.SuppressLint;
import android.content.Context;
import android.graphics.Bitmap;
import android.util.Log;

import androidx.annotation.NonNull;
Expand Down Expand Up @@ -45,5 +46,6 @@ public void registerComponents(@NonNull Context context, @NonNull Glide glide, @
registry.append(String.class, InputStream.class, new NoHttpStringLoader.StreamFactory());

registry.append(EmbeddedChapterImage.class, ByteBuffer.class, new ChapterImageModelLoader.Factory());
registry.register(Bitmap.class, PaletteBitmap.class, new PaletteBitmapTranscoder());
}
}
@@ -0,0 +1,16 @@
package de.danoeh.antennapod.core.glide;

import android.graphics.Bitmap;

import androidx.annotation.NonNull;
import androidx.palette.graphics.Palette;

public class PaletteBitmap {
public final Palette palette;
public final Bitmap bitmap;

public PaletteBitmap(@NonNull Bitmap bitmap, Palette palette) {
this.bitmap = bitmap;
this.palette = palette;
}
}
@@ -0,0 +1,33 @@
package de.danoeh.antennapod.core.glide;

import androidx.annotation.NonNull;

import com.bumptech.glide.load.engine.Resource;
import com.bumptech.glide.util.Util;

public class PaletteBitmapResource implements Resource<PaletteBitmap> {
private final PaletteBitmap paletteBitmap;

public PaletteBitmapResource(@NonNull PaletteBitmap paletteBitmap) {
this.paletteBitmap = paletteBitmap;
}

@NonNull
@Override
public Class<PaletteBitmap> getResourceClass() {
return PaletteBitmap.class;
}

@NonNull
@Override public PaletteBitmap get() {
vbh marked this conversation as resolved.
Show resolved Hide resolved
return paletteBitmap;
}

@Override public int getSize() {
vbh marked this conversation as resolved.
Show resolved Hide resolved
return Util.getBitmapByteSize(paletteBitmap.bitmap);
}

@Override public void recycle() {
vbh marked this conversation as resolved.
Show resolved Hide resolved
paletteBitmap.bitmap.recycle();
}
}
@@ -0,0 +1,28 @@
package de.danoeh.antennapod.core.glide;

import android.graphics.Bitmap;

import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.palette.graphics.Palette;

import com.bumptech.glide.load.Options;
import com.bumptech.glide.load.engine.Resource;
import com.bumptech.glide.load.resource.transcode.ResourceTranscoder;

import de.danoeh.antennapod.core.preferences.UserPreferences;

public class PaletteBitmapTranscoder implements ResourceTranscoder<Bitmap, PaletteBitmap> {

@Nullable
@Override
public Resource<PaletteBitmap> transcode(@NonNull Resource<Bitmap> toTranscode, @NonNull Options options) {
Bitmap bitmap = toTranscode.get();
Palette palette = null;
if (UserPreferences.shouldShowSubscriptionTitle()) {
palette = new Palette.Builder(bitmap).generate();
}
PaletteBitmap result = new PaletteBitmap(bitmap, palette);
return new PaletteBitmapResource(result);
}
}
Expand Up @@ -69,6 +69,7 @@ private UserPreferences(){}
public static final String PREF_BACK_BUTTON_BEHAVIOR = "prefBackButtonBehavior";
private static final String PREF_BACK_BUTTON_GO_TO_PAGE = "prefBackButtonGoToPage";
public static final String PREF_FILTER_FEED = "prefSubscriptionsFilter";
public static final String PREF_SUBSCRIPTION_TITLE = "prefSubscriptionTitle";

public static final String PREF_QUEUE_KEEP_SORTED = "prefQueueKeepSorted";
public static final String PREF_QUEUE_KEEP_SORTED_ORDER = "prefQueueKeepSortedOrder";
Expand Down Expand Up @@ -1090,4 +1091,13 @@ public static void resetUsageCountingDate() {
public static void unsetUsageCountingDate() {
setUsageCountingDateMillis(-1);
}

public static boolean shouldShowSubscriptionTitle() {
return prefs.getBoolean(PREF_SUBSCRIPTION_TITLE, false);
}

public static void setSubscriptionTitleSetting(boolean showTitle) {
prefs.edit().putBoolean(PREF_SUBSCRIPTION_TITLE, showTitle).apply();
}

}
2 changes: 2 additions & 0 deletions core/src/main/res/values/strings.xml
Expand Up @@ -542,6 +542,8 @@
<string name="new_episode_notification_disabled">Notification disabled</string>
<string name="pref_feed_settings_dialog_msg">This setting is unique to each podcast. You can change it by opening the podcast page.</string>
<string name="pref_contribute">Contribute</string>
<string name="pref_show_subscription_title">Show Subscription Title</string>
<string name="pref_show_subscription_title_summary">Display the subscription title below the cover image.</string>

<!-- About screen -->
<string name="about_pref">About</string>
Expand Down
Expand Up @@ -5,6 +5,7 @@
import androidx.annotation.ColorInt;
import android.util.TypedValue;
import androidx.annotation.DrawableRes;
import androidx.core.content.ContextCompat;

public class ThemeUtils {
private ThemeUtils() {
Expand All @@ -14,6 +15,9 @@ private ThemeUtils() {
public static @ColorInt int getColorFromAttr(Context context, @AttrRes int attr) {
TypedValue typedValue = new TypedValue();
context.getTheme().resolveAttribute(attr, typedValue, true);
if (typedValue.resourceId != 0) {
return ContextCompat.getColor(context, typedValue.resourceId);
}
return typedValue.data;
}

Expand Down