mirror of
https://github.com/AntennaPod/AntennaPod.git
synced 2025-10-29 03:36:21 +00:00
Tags above subscriptions screen (#7954)
This commit is contained in:
parent
acc2638f3b
commit
ad94f2f647
@ -27,10 +27,8 @@ import de.danoeh.antennapod.R;
|
||||
import de.danoeh.antennapod.ui.appstartintent.MainActivityStarter;
|
||||
import de.danoeh.antennapod.ui.common.ThemeSwitcher;
|
||||
import de.danoeh.antennapod.storage.database.DBReader;
|
||||
import de.danoeh.antennapod.storage.database.NavDrawerData;
|
||||
import de.danoeh.antennapod.databinding.SubscriptionSelectionActivityBinding;
|
||||
import de.danoeh.antennapod.model.feed.Feed;
|
||||
import de.danoeh.antennapod.storage.preferences.UserPreferences;
|
||||
import io.reactivex.rxjava3.core.Observable;
|
||||
import io.reactivex.rxjava3.android.schedulers.AndroidSchedulers;
|
||||
import io.reactivex.rxjava3.disposables.Disposable;
|
||||
@ -74,20 +72,6 @@ public class SelectSubscriptionActivity extends AppCompatActivity {
|
||||
|
||||
}
|
||||
|
||||
public List<Feed> getFeedItems(List<NavDrawerData.DrawerItem> items, List<Feed> result) {
|
||||
for (NavDrawerData.DrawerItem item : items) {
|
||||
if (item.type == NavDrawerData.DrawerItem.Type.TAG) {
|
||||
getFeedItems(((NavDrawerData.TagDrawerItem) item).getChildren(), result);
|
||||
} else {
|
||||
Feed feed = ((NavDrawerData.FeedDrawerItem) item).feed;
|
||||
if (!result.contains(feed)) {
|
||||
result.add(feed);
|
||||
}
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
private void addShortcut(Feed feed, Bitmap bitmap) {
|
||||
Intent intent = new Intent(this, MainActivity.class);
|
||||
intent.setAction(Intent.ACTION_MAIN);
|
||||
@ -140,12 +124,7 @@ public class SelectSubscriptionActivity extends AppCompatActivity {
|
||||
if (disposable != null) {
|
||||
disposable.dispose();
|
||||
}
|
||||
disposable = Observable.fromCallable(
|
||||
() -> {
|
||||
NavDrawerData data = DBReader.getNavDrawerData(UserPreferences.getSubscriptionsFilter(),
|
||||
UserPreferences.getFeedOrder(), UserPreferences.getFeedCounterSetting());
|
||||
return getFeedItems(data.items, new ArrayList<>());
|
||||
})
|
||||
disposable = Observable.fromCallable(DBReader::getFeedList)
|
||||
.subscribeOn(Schedulers.io())
|
||||
.observeOn(AndroidSchedulers.mainThread())
|
||||
.subscribe(
|
||||
|
||||
@ -0,0 +1,58 @@
|
||||
package de.danoeh.antennapod.ui.screen.drawer;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import de.danoeh.antennapod.model.feed.Feed;
|
||||
import de.danoeh.antennapod.storage.database.NavDrawerData;
|
||||
|
||||
public class DrawerItem {
|
||||
private final Feed feed;
|
||||
private final NavDrawerData.TagItem tag;
|
||||
private int counter;
|
||||
private final int layer;
|
||||
|
||||
public DrawerItem(@NonNull Feed feed, int counter, int layer) {
|
||||
this.tag = null;
|
||||
this.feed = feed;
|
||||
this.counter = counter;
|
||||
this.layer = layer;
|
||||
}
|
||||
|
||||
public DrawerItem(@NonNull NavDrawerData.TagItem tag) {
|
||||
this.feed = null;
|
||||
this.tag = tag;
|
||||
this.counter = 0;
|
||||
this.layer = 0;
|
||||
}
|
||||
|
||||
public boolean isFeed() {
|
||||
return feed != null;
|
||||
}
|
||||
|
||||
public Feed asFeed() {
|
||||
return feed;
|
||||
}
|
||||
|
||||
public NavDrawerData.TagItem asTag() {
|
||||
return tag;
|
||||
}
|
||||
|
||||
public void setCounter(int counter) {
|
||||
this.counter = counter;
|
||||
}
|
||||
|
||||
public int getCounter() {
|
||||
return counter;
|
||||
}
|
||||
|
||||
public int getLayer() {
|
||||
return layer;
|
||||
}
|
||||
|
||||
public String getTitle() {
|
||||
return isFeed() ? feed.getTitle() : tag.getTitle();
|
||||
}
|
||||
|
||||
public long getId() {
|
||||
return isFeed() ? feed.getId() : tag.getId();
|
||||
}
|
||||
}
|
||||
@ -46,6 +46,7 @@ import org.greenrobot.eventbus.ThreadMode;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
import de.danoeh.antennapod.R;
|
||||
@ -80,8 +81,8 @@ public class NavDrawerFragment extends Fragment implements SharedPreferences.OnS
|
||||
|
||||
private NavDrawerData navDrawerData;
|
||||
private int reclaimableSpace = 0;
|
||||
private List<NavDrawerData.DrawerItem> flatItemList;
|
||||
private NavDrawerData.DrawerItem contextPressedItem = null;
|
||||
private List<DrawerItem> flatItemList;
|
||||
private DrawerItem contextPressedItem = null;
|
||||
private NavListAdapter navAdapter;
|
||||
private Disposable disposable;
|
||||
private ProgressBar progressBar;
|
||||
@ -162,11 +163,12 @@ public class NavDrawerFragment extends Fragment implements SharedPreferences.OnS
|
||||
public void onCreateContextMenu(@NonNull ContextMenu menu, @NonNull View v, ContextMenu.ContextMenuInfo menuInfo) {
|
||||
super.onCreateContextMenu(menu, v, menuInfo);
|
||||
MenuInflater inflater = getActivity().getMenuInflater();
|
||||
menu.setHeaderTitle(contextPressedItem.getTitle());
|
||||
if (contextPressedItem.type == NavDrawerData.DrawerItem.Type.FEED) {
|
||||
if (contextPressedItem.isFeed()) {
|
||||
menu.setHeaderTitle(contextPressedItem.asFeed().getTitle());
|
||||
inflater.inflate(R.menu.nav_feed_context, menu);
|
||||
// episodes are not loaded, so we cannot check if the podcast has new or unplayed ones!
|
||||
} else {
|
||||
menu.setHeaderTitle(contextPressedItem.asTag().getTitle());
|
||||
inflater.inflate(R.menu.nav_folder_context, menu);
|
||||
}
|
||||
MenuItemUtils.setOnClickListeners(menu, this::onContextItemSelected);
|
||||
@ -174,15 +176,15 @@ public class NavDrawerFragment extends Fragment implements SharedPreferences.OnS
|
||||
|
||||
@Override
|
||||
public boolean onContextItemSelected(@NonNull MenuItem item) {
|
||||
NavDrawerData.DrawerItem pressedItem = contextPressedItem;
|
||||
DrawerItem pressedItem = contextPressedItem;
|
||||
contextPressedItem = null;
|
||||
if (pressedItem == null) {
|
||||
return false;
|
||||
}
|
||||
if (pressedItem.type == NavDrawerData.DrawerItem.Type.FEED) {
|
||||
return onFeedContextMenuClicked(((NavDrawerData.FeedDrawerItem) pressedItem).feed, item);
|
||||
if (pressedItem.isFeed()) {
|
||||
return onFeedContextMenuClicked(pressedItem.asFeed(), item);
|
||||
} else {
|
||||
return onTagContextMenuClicked(pressedItem, item);
|
||||
return onTagContextMenuClicked(pressedItem.asTag(), item);
|
||||
}
|
||||
}
|
||||
|
||||
@ -204,7 +206,7 @@ public class NavDrawerFragment extends Fragment implements SharedPreferences.OnS
|
||||
return super.onContextItemSelected(item);
|
||||
}
|
||||
|
||||
private boolean onTagContextMenuClicked(NavDrawerData.DrawerItem drawerItem, MenuItem item) {
|
||||
private boolean onTagContextMenuClicked(NavDrawerData.TagItem drawerItem, MenuItem item) {
|
||||
final int itemId = item.getItemId();
|
||||
if (itemId == R.id.rename_folder_item) {
|
||||
new RenameFeedDialog(getActivity(), drawerItem).show();
|
||||
@ -216,10 +218,8 @@ public class NavDrawerFragment extends Fragment implements SharedPreferences.OnS
|
||||
|
||||
@Override
|
||||
public void onConfirmButtonPressed(DialogInterface dialog) {
|
||||
List<NavDrawerData.DrawerItem> feeds = ((NavDrawerData.TagDrawerItem) drawerItem).getChildren();
|
||||
|
||||
for (NavDrawerData.DrawerItem feed : feeds) {
|
||||
FeedPreferences preferences = ((NavDrawerData.FeedDrawerItem) feed).feed.getPreferences();
|
||||
for (Feed feed : drawerItem.getFeeds()) {
|
||||
FeedPreferences preferences = feed.getPreferences();
|
||||
preferences.getTags().remove(drawerItem.getTitle());
|
||||
DBWriter.setFeedPreferences(preferences);
|
||||
}
|
||||
@ -272,7 +272,7 @@ public class NavDrawerFragment extends Fragment implements SharedPreferences.OnS
|
||||
}
|
||||
|
||||
@Override
|
||||
public NavDrawerData.DrawerItem getItem(int position) {
|
||||
public DrawerItem getItem(int position) {
|
||||
if (flatItemList != null && 0 <= position && position < flatItemList.size()) {
|
||||
return flatItemList.get(position);
|
||||
} else {
|
||||
@ -288,11 +288,11 @@ public class NavDrawerFragment extends Fragment implements SharedPreferences.OnS
|
||||
} else if (StringUtils.isNumeric(lastNavFragment)) { // last fragment was not a list, but a feed
|
||||
long feedId = Long.parseLong(lastNavFragment);
|
||||
if (navDrawerData != null) {
|
||||
NavDrawerData.DrawerItem itemToCheck = flatItemList.get(
|
||||
DrawerItem itemToCheck = flatItemList.get(
|
||||
position - navAdapter.getSubscriptionOffset());
|
||||
if (itemToCheck.type == NavDrawerData.DrawerItem.Type.FEED) {
|
||||
if (itemToCheck.isFeed()) {
|
||||
// When the same feed is displayed multiple times, it should be highlighted multiple times.
|
||||
return ((NavDrawerData.FeedDrawerItem) itemToCheck).feed.getId() == feedId;
|
||||
return itemToCheck.asFeed().getId() == feedId;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -341,15 +341,15 @@ public class NavDrawerFragment extends Fragment implements SharedPreferences.OnS
|
||||
((MainActivity) getActivity()).getBottomSheet().setState(BottomSheetBehavior.STATE_COLLAPSED);
|
||||
} else {
|
||||
int pos = position - navAdapter.getSubscriptionOffset();
|
||||
NavDrawerData.DrawerItem clickedItem = flatItemList.get(pos);
|
||||
DrawerItem clickedItem = flatItemList.get(pos);
|
||||
|
||||
if (clickedItem.type == NavDrawerData.DrawerItem.Type.FEED) {
|
||||
long feedId = ((NavDrawerData.FeedDrawerItem) clickedItem).feed.getId();
|
||||
if (clickedItem.isFeed()) {
|
||||
long feedId = clickedItem.asFeed().getId();
|
||||
((MainActivity) getActivity()).loadFeedFragmentById(feedId, null);
|
||||
((MainActivity) getActivity()).getBottomSheet()
|
||||
.setState(BottomSheetBehavior.STATE_COLLAPSED);
|
||||
} else {
|
||||
NavDrawerData.TagDrawerItem folder = ((NavDrawerData.TagDrawerItem) clickedItem);
|
||||
NavDrawerData.TagItem folder = clickedItem.asTag();
|
||||
if (openFolders.contains(folder.getTitle())) {
|
||||
openFolders.remove(folder.getTitle());
|
||||
} else {
|
||||
@ -361,7 +361,8 @@ public class NavDrawerFragment extends Fragment implements SharedPreferences.OnS
|
||||
.putStringSet(PREF_OPEN_FOLDERS, openFolders)
|
||||
.apply();
|
||||
|
||||
disposable = Observable.fromCallable(() -> makeFlatDrawerData(navDrawerData.items, 0))
|
||||
disposable = Observable.fromCallable(() -> makeFlatDrawerData(navDrawerData.feeds,
|
||||
navDrawerData.tags, navDrawerData.feedCounters))
|
||||
.subscribeOn(Schedulers.computation())
|
||||
.observeOn(AndroidSchedulers.mainThread())
|
||||
.subscribe(
|
||||
@ -409,7 +410,7 @@ public class NavDrawerFragment extends Fragment implements SharedPreferences.OnS
|
||||
NavDrawerData data = DBReader.getNavDrawerData(UserPreferences.getSubscriptionsFilter(),
|
||||
UserPreferences.getFeedOrder(), UserPreferences.getFeedCounterSetting());
|
||||
reclaimableSpace = EpisodeCleanupAlgorithmFactory.build().getReclaimableItems();
|
||||
return new Pair<>(data, makeFlatDrawerData(data.items, 0));
|
||||
return new Pair<>(data, makeFlatDrawerData(data.feeds, data.tags, data.feedCounters));
|
||||
})
|
||||
.subscribeOn(Schedulers.io())
|
||||
.observeOn(AndroidSchedulers.mainThread())
|
||||
@ -425,23 +426,38 @@ public class NavDrawerFragment extends Fragment implements SharedPreferences.OnS
|
||||
});
|
||||
}
|
||||
|
||||
private List<NavDrawerData.DrawerItem> makeFlatDrawerData(List<NavDrawerData.DrawerItem> items, int layer) {
|
||||
List<NavDrawerData.DrawerItem> flatItems = new ArrayList<>();
|
||||
for (NavDrawerData.DrawerItem item : items) {
|
||||
item.setLayer(layer);
|
||||
flatItems.add(item);
|
||||
if (item.type == NavDrawerData.DrawerItem.Type.TAG) {
|
||||
NavDrawerData.TagDrawerItem folder = ((NavDrawerData.TagDrawerItem) item);
|
||||
folder.setOpen(openFolders.contains(folder.getTitle()));
|
||||
if (folder.isOpen()) {
|
||||
flatItems.addAll(makeFlatDrawerData(
|
||||
((NavDrawerData.TagDrawerItem) item).getChildren(), layer + 1));
|
||||
private List<DrawerItem> makeFlatDrawerData(List<Feed> feeds, List<NavDrawerData.TagItem> tags,
|
||||
@Nullable java.util.Map<Long, Integer> feedCounters) {
|
||||
List<DrawerItem> flatItems = new ArrayList<>();
|
||||
for (Feed feed : feeds) {
|
||||
flatItems.add(new DrawerItem(feed, feedCounter(feed, feedCounters), 0));
|
||||
}
|
||||
for (NavDrawerData.TagItem tag : tags) {
|
||||
if (FeedPreferences.TAG_ROOT.equals(tag.getTitle())) {
|
||||
continue;
|
||||
}
|
||||
DrawerItem tagItem = new DrawerItem(tag);
|
||||
flatItems.add(tagItem);
|
||||
int counter = 0;
|
||||
tag.setOpen(openFolders.contains(tag.getTitle()));
|
||||
for (Feed feed : tag.getFeeds()) {
|
||||
counter += feedCounter(feed, feedCounters);
|
||||
if (tag.isOpen()) {
|
||||
flatItems.add(new DrawerItem(feed, feedCounter(feed, feedCounters), 1));
|
||||
}
|
||||
}
|
||||
tagItem.setCounter(counter);
|
||||
}
|
||||
return flatItems;
|
||||
}
|
||||
|
||||
private int feedCounter(Feed feed, Map<Long, Integer> feedCounters) {
|
||||
if (navDrawerData == null || feedCounters == null) {
|
||||
return 0;
|
||||
}
|
||||
return feedCounters.containsKey(feed.getId()) ? feedCounters.get(feed.getId()) : 0;
|
||||
}
|
||||
|
||||
public static void saveLastNavFragment(Context context, String tag) {
|
||||
Log.d(TAG, "saveLastNavFragment(tag: " + tag + ")");
|
||||
SharedPreferences prefs = context.getSharedPreferences(PREF_NAME, Context.MODE_PRIVATE);
|
||||
|
||||
@ -107,7 +107,7 @@ public class NavListAdapter extends RecyclerView.Adapter<NavListAdapter.Holder>
|
||||
public long getItemId(int position) {
|
||||
int viewType = getItemViewType(position);
|
||||
if (viewType == VIEW_TYPE_SUBSCRIPTION) {
|
||||
return itemAccess.getItem(position - getSubscriptionOffset()).id;
|
||||
return itemAccess.getItem(position - getSubscriptionOffset()).getId();
|
||||
} else if (viewType == VIEW_TYPE_NAV) {
|
||||
return -Math.abs((long) fragmentTags.get(position).hashCode()) - 1; // Folder IDs are >0
|
||||
} else {
|
||||
@ -154,12 +154,12 @@ public class NavListAdapter extends RecyclerView.Adapter<NavListAdapter.Holder>
|
||||
bindSectionDivider((DividerHolder) holder);
|
||||
} else {
|
||||
int itemPos = position - getSubscriptionOffset();
|
||||
NavDrawerData.DrawerItem item = itemAccess.getItem(itemPos);
|
||||
DrawerItem item = itemAccess.getItem(itemPos);
|
||||
bindListItem(item, (FeedHolder) holder);
|
||||
if (item.type == NavDrawerData.DrawerItem.Type.FEED) {
|
||||
bindFeedView((NavDrawerData.FeedDrawerItem) item, (FeedHolder) holder);
|
||||
if (item.isFeed()) {
|
||||
bindFeedView(item.asFeed(), (FeedHolder) holder);
|
||||
} else {
|
||||
bindTagView((NavDrawerData.TagDrawerItem) item, (FeedHolder) holder);
|
||||
bindTagView(item.asTag(), (FeedHolder) holder);
|
||||
}
|
||||
holder.itemView.setOnCreateContextMenuListener(itemAccess);
|
||||
}
|
||||
@ -231,7 +231,7 @@ public class NavListAdapter extends RecyclerView.Adapter<NavListAdapter.Holder>
|
||||
}
|
||||
}
|
||||
|
||||
private void bindListItem(NavDrawerData.DrawerItem item, FeedHolder holder) {
|
||||
private void bindListItem(DrawerItem item, FeedHolder holder) {
|
||||
if (item.getCounter() > 0) {
|
||||
holder.count.setVisibility(View.VISIBLE);
|
||||
holder.count.setText(NumberFormat.getInstance().format(item.getCounter()));
|
||||
@ -243,8 +243,7 @@ public class NavListAdapter extends RecyclerView.Adapter<NavListAdapter.Holder>
|
||||
holder.itemView.setPadding(item.getLayer() * padding, 0, 0, 0);
|
||||
}
|
||||
|
||||
private void bindFeedView(NavDrawerData.FeedDrawerItem drawerItem, FeedHolder holder) {
|
||||
Feed feed = drawerItem.feed;
|
||||
private void bindFeedView(Feed feed, FeedHolder holder) {
|
||||
Activity context = activity.get();
|
||||
if (context == null) {
|
||||
return;
|
||||
@ -264,7 +263,7 @@ public class NavListAdapter extends RecyclerView.Adapter<NavListAdapter.Holder>
|
||||
holder.failure.setVisibility(feed.hasLastUpdateFailed() ? View.VISIBLE : View.GONE);
|
||||
}
|
||||
|
||||
private void bindTagView(NavDrawerData.TagDrawerItem tag, FeedHolder holder) {
|
||||
private void bindTagView(NavDrawerData.TagItem tag, FeedHolder holder) {
|
||||
Activity context = activity.get();
|
||||
if (context == null) {
|
||||
return;
|
||||
@ -323,7 +322,7 @@ public class NavListAdapter extends RecyclerView.Adapter<NavListAdapter.Holder>
|
||||
public interface ItemAccess extends View.OnCreateContextMenuListener {
|
||||
int getCount();
|
||||
|
||||
NavDrawerData.DrawerItem getItem(int position);
|
||||
DrawerItem getItem(int position);
|
||||
|
||||
boolean isSelected(int position);
|
||||
|
||||
|
||||
@ -3,8 +3,6 @@ package de.danoeh.antennapod.ui.screen.feed;
|
||||
import android.app.Activity;
|
||||
|
||||
import java.lang.ref.WeakReference;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import android.view.LayoutInflater;
|
||||
import androidx.appcompat.app.AlertDialog;
|
||||
@ -20,16 +18,16 @@ public class RenameFeedDialog {
|
||||
|
||||
private final WeakReference<Activity> activityRef;
|
||||
private Feed feed = null;
|
||||
private NavDrawerData.DrawerItem drawerItem = null;
|
||||
private NavDrawerData.TagItem tag = null;
|
||||
|
||||
public RenameFeedDialog(Activity activity, Feed feed) {
|
||||
this.activityRef = new WeakReference<>(activity);
|
||||
this.feed = feed;
|
||||
}
|
||||
|
||||
public RenameFeedDialog(Activity activity, NavDrawerData.DrawerItem drawerItem) {
|
||||
public RenameFeedDialog(Activity activity, NavDrawerData.TagItem drawerItem) {
|
||||
this.activityRef = new WeakReference<>(activity);
|
||||
this.drawerItem = drawerItem;
|
||||
this.tag = drawerItem;
|
||||
}
|
||||
|
||||
public void show() {
|
||||
@ -39,7 +37,7 @@ public class RenameFeedDialog {
|
||||
}
|
||||
|
||||
final EditTextDialogBinding binding = EditTextDialogBinding.inflate(LayoutInflater.from(activity));
|
||||
String title = feed != null ? feed.getTitle() : drawerItem.getTitle();
|
||||
String title = feed != null ? feed.getTitle() : tag.getTitle();
|
||||
|
||||
binding.textInput.setText(title);
|
||||
AlertDialog dialog = new MaterialAlertDialogBuilder(activity)
|
||||
@ -64,17 +62,11 @@ public class RenameFeedDialog {
|
||||
}
|
||||
|
||||
private void renameTag(String title) {
|
||||
if (NavDrawerData.DrawerItem.Type.TAG == drawerItem.type) {
|
||||
List<FeedPreferences> feedPreferences = new ArrayList<>();
|
||||
for (NavDrawerData.DrawerItem item : ((NavDrawerData.TagDrawerItem) drawerItem).getChildren()) {
|
||||
feedPreferences.add(((NavDrawerData.FeedDrawerItem) item).feed.getPreferences());
|
||||
}
|
||||
|
||||
for (FeedPreferences preferences : feedPreferences) {
|
||||
preferences.getTags().remove(drawerItem.getTitle());
|
||||
preferences.getTags().add(title);
|
||||
DBWriter.setFeedPreferences(preferences);
|
||||
}
|
||||
for (Feed feed : tag.getFeeds()) {
|
||||
FeedPreferences preferences = feed.getPreferences();
|
||||
preferences.getTags().remove(tag.getTitle());
|
||||
preferences.getTags().add(title);
|
||||
DBWriter.setFeedPreferences(preferences);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -7,33 +7,30 @@ import android.util.Log;
|
||||
import android.view.MotionEvent;
|
||||
import android.view.View;
|
||||
import android.widget.ArrayAdapter;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.fragment.app.DialogFragment;
|
||||
import androidx.recyclerview.widget.GridLayoutManager;
|
||||
|
||||
import com.google.android.material.dialog.MaterialAlertDialogBuilder;
|
||||
import de.danoeh.antennapod.R;
|
||||
import de.danoeh.antennapod.databinding.EditTagsDialogBinding;
|
||||
import de.danoeh.antennapod.model.feed.FeedCounter;
|
||||
import de.danoeh.antennapod.model.feed.FeedOrder;
|
||||
import de.danoeh.antennapod.model.feed.FeedPreferences;
|
||||
import de.danoeh.antennapod.storage.database.DBReader;
|
||||
import de.danoeh.antennapod.storage.database.DBWriter;
|
||||
import de.danoeh.antennapod.storage.database.NavDrawerData;
|
||||
import de.danoeh.antennapod.ui.SimpleChipAdapter;
|
||||
import de.danoeh.antennapod.ui.view.ItemOffsetDecoration;
|
||||
import io.reactivex.rxjava3.android.schedulers.AndroidSchedulers;
|
||||
import io.reactivex.rxjava3.core.Observable;
|
||||
import io.reactivex.rxjava3.schedulers.Schedulers;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
import de.danoeh.antennapod.R;
|
||||
import de.danoeh.antennapod.ui.SimpleChipAdapter;
|
||||
import de.danoeh.antennapod.storage.database.DBReader;
|
||||
import de.danoeh.antennapod.storage.database.DBWriter;
|
||||
import de.danoeh.antennapod.storage.database.NavDrawerData;
|
||||
import de.danoeh.antennapod.databinding.EditTagsDialogBinding;
|
||||
import de.danoeh.antennapod.model.feed.FeedCounter;
|
||||
import de.danoeh.antennapod.model.feed.FeedOrder;
|
||||
import de.danoeh.antennapod.model.feed.FeedPreferences;
|
||||
import de.danoeh.antennapod.ui.view.ItemOffsetDecoration;
|
||||
import io.reactivex.rxjava3.core.Observable;
|
||||
import io.reactivex.rxjava3.android.schedulers.AndroidSchedulers;
|
||||
import io.reactivex.rxjava3.schedulers.Schedulers;
|
||||
|
||||
public class TagSettingsDialog extends DialogFragment {
|
||||
public static final String TAG = "TagSettingsDialog";
|
||||
private static final String ARG_FEED_PREFERENCES = "feed_preferences";
|
||||
@ -113,10 +110,9 @@ public class TagSettingsDialog extends DialogFragment {
|
||||
Observable.fromCallable(
|
||||
() -> {
|
||||
NavDrawerData data = DBReader.getNavDrawerData(null, FeedOrder.ALPHABETICAL, FeedCounter.SHOW_NONE);
|
||||
List<NavDrawerData.DrawerItem> items = data.items;
|
||||
List<String> folders = new ArrayList<String>();
|
||||
for (NavDrawerData.DrawerItem item : items) {
|
||||
if (item.type == NavDrawerData.DrawerItem.Type.TAG) {
|
||||
List<String> folders = new ArrayList<>();
|
||||
for (NavDrawerData.TagItem item : data.tags) {
|
||||
if (!FeedPreferences.TAG_ROOT.equals(item.getTitle())) {
|
||||
folders.add(item.getTitle());
|
||||
}
|
||||
}
|
||||
|
||||
@ -11,7 +11,6 @@ import android.view.MenuItem;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.widget.ProgressBar;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.core.util.Pair;
|
||||
import androidx.fragment.app.Fragment;
|
||||
@ -19,43 +18,40 @@ import androidx.recyclerview.widget.GridLayoutManager;
|
||||
import androidx.recyclerview.widget.LinearLayoutManager;
|
||||
import androidx.recyclerview.widget.RecyclerView;
|
||||
import androidx.swiperefreshlayout.widget.SwipeRefreshLayout;
|
||||
|
||||
import com.google.android.material.appbar.MaterialToolbar;
|
||||
import com.google.android.material.floatingactionbutton.FloatingActionButton;
|
||||
|
||||
import de.danoeh.antennapod.model.feed.FeedPreferences;
|
||||
import de.danoeh.antennapod.storage.database.DBWriter;
|
||||
import de.danoeh.antennapod.ui.common.ConfirmationDialog;
|
||||
import de.danoeh.antennapod.ui.screen.AddFeedFragment;
|
||||
import de.danoeh.antennapod.ui.screen.SearchFragment;
|
||||
import de.danoeh.antennapod.net.download.serviceinterface.FeedUpdateManager;
|
||||
import de.danoeh.antennapod.ui.view.FloatingSelectMenu;
|
||||
import org.greenrobot.eventbus.EventBus;
|
||||
import org.greenrobot.eventbus.Subscribe;
|
||||
import org.greenrobot.eventbus.ThreadMode;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
|
||||
import de.danoeh.antennapod.R;
|
||||
import de.danoeh.antennapod.activity.MainActivity;
|
||||
import de.danoeh.antennapod.ui.MenuItemUtils;
|
||||
import de.danoeh.antennapod.storage.database.DBReader;
|
||||
import de.danoeh.antennapod.storage.database.NavDrawerData;
|
||||
import de.danoeh.antennapod.ui.screen.feed.RenameFeedDialog;
|
||||
import de.danoeh.antennapod.event.FeedListUpdateEvent;
|
||||
import de.danoeh.antennapod.event.FeedUpdateRunningEvent;
|
||||
import de.danoeh.antennapod.event.UnreadItemsUpdateEvent;
|
||||
import de.danoeh.antennapod.model.feed.Feed;
|
||||
import de.danoeh.antennapod.model.feed.FeedPreferences;
|
||||
import de.danoeh.antennapod.net.download.serviceinterface.FeedUpdateManager;
|
||||
import de.danoeh.antennapod.storage.database.DBReader;
|
||||
import de.danoeh.antennapod.storage.database.DBWriter;
|
||||
import de.danoeh.antennapod.storage.database.NavDrawerData;
|
||||
import de.danoeh.antennapod.storage.preferences.UserPreferences;
|
||||
import de.danoeh.antennapod.ui.MenuItemUtils;
|
||||
import de.danoeh.antennapod.ui.common.ConfirmationDialog;
|
||||
import de.danoeh.antennapod.ui.screen.AddFeedFragment;
|
||||
import de.danoeh.antennapod.ui.screen.SearchFragment;
|
||||
import de.danoeh.antennapod.ui.screen.feed.RenameFeedDialog;
|
||||
import de.danoeh.antennapod.ui.statistics.StatisticsFragment;
|
||||
import de.danoeh.antennapod.ui.view.EmptyViewHandler;
|
||||
import de.danoeh.antennapod.ui.view.FloatingSelectMenu;
|
||||
import de.danoeh.antennapod.ui.view.ItemOffsetDecoration;
|
||||
import de.danoeh.antennapod.ui.view.LiftOnScrollListener;
|
||||
import io.reactivex.rxjava3.core.Observable;
|
||||
import io.reactivex.rxjava3.android.schedulers.AndroidSchedulers;
|
||||
import io.reactivex.rxjava3.core.Observable;
|
||||
import io.reactivex.rxjava3.disposables.Disposable;
|
||||
import io.reactivex.rxjava3.schedulers.Schedulers;
|
||||
import org.greenrobot.eventbus.EventBus;
|
||||
import org.greenrobot.eventbus.Subscribe;
|
||||
import org.greenrobot.eventbus.ThreadMode;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
|
||||
/**
|
||||
* Fragment for displaying feed subscriptions
|
||||
@ -66,6 +62,7 @@ public class SubscriptionFragment extends Fragment
|
||||
public static final String TAG = "SubscriptionFragment";
|
||||
private static final String PREFS = "SubscriptionFragment";
|
||||
private static final String PREF_NUM_COLUMNS = "columns";
|
||||
private static final String PREF_LAST_TAG = "last_tag";
|
||||
private static final String KEY_UP_ARROW = "up_arrow";
|
||||
private static final String ARGUMENT_FOLDER = "folder";
|
||||
|
||||
@ -79,12 +76,13 @@ public class SubscriptionFragment extends Fragment
|
||||
|
||||
private RecyclerView subscriptionRecycler;
|
||||
private SubscriptionsRecyclerAdapter subscriptionAdapter;
|
||||
private RecyclerView tagsRecycler;
|
||||
private SubscriptionTagAdapter tagAdapter;
|
||||
private EmptyViewHandler emptyView;
|
||||
private View feedsFilteredMsg;
|
||||
private MaterialToolbar toolbar;
|
||||
private SwipeRefreshLayout swipeRefreshLayout;
|
||||
private ProgressBar progressBar;
|
||||
private String displayedFolder = null;
|
||||
private boolean displayUpArrow;
|
||||
|
||||
private Disposable disposable;
|
||||
@ -94,7 +92,7 @@ public class SubscriptionFragment extends Fragment
|
||||
private FloatingActionButton subscriptionAddButton;
|
||||
private FloatingSelectMenu floatingSelectMenu;
|
||||
private RecyclerView.ItemDecoration itemDecoration;
|
||||
private List<NavDrawerData.DrawerItem> listItems;
|
||||
private List<Feed> feeds;
|
||||
|
||||
public static SubscriptionFragment newInstance(String folderTitle) {
|
||||
SubscriptionFragment fragment = new SubscriptionFragment();
|
||||
@ -134,13 +132,6 @@ public class SubscriptionFragment extends Fragment
|
||||
}
|
||||
refreshToolbarState();
|
||||
|
||||
if (getArguments() != null) {
|
||||
displayedFolder = getArguments().getString(ARGUMENT_FOLDER, null);
|
||||
if (displayedFolder != null) {
|
||||
toolbar.setTitle(displayedFolder);
|
||||
}
|
||||
}
|
||||
|
||||
subscriptionRecycler = root.findViewById(R.id.subscriptions_grid);
|
||||
registerForContextMenu(subscriptionRecycler);
|
||||
subscriptionRecycler.addOnScrollListener(new LiftOnScrollListener(root.findViewById(R.id.appbar)));
|
||||
@ -186,6 +177,28 @@ public class SubscriptionFragment extends Fragment
|
||||
return true;
|
||||
});
|
||||
|
||||
tagsRecycler = root.findViewById(R.id.tags_recycler);
|
||||
tagsRecycler.setLayoutManager(new LinearLayoutManager(getContext(), LinearLayoutManager.HORIZONTAL, false));
|
||||
tagsRecycler.addItemDecoration(new ItemOffsetDecoration(getContext(), 4, 0));
|
||||
registerForContextMenu(tagsRecycler);
|
||||
tagAdapter = new SubscriptionTagAdapter(getActivity()) {
|
||||
@Override
|
||||
public void onCreateContextMenu(ContextMenu menu, View v, ContextMenu.ContextMenuInfo menuInfo) {
|
||||
super.onCreateContextMenu(menu, v, menuInfo);
|
||||
MenuItemUtils.setOnClickListeners(menu, SubscriptionFragment.this::onTagContextItemSelected);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onTagClick(NavDrawerData.TagItem tag) {
|
||||
tagAdapter.setSelectedTag(tag.getTitle());
|
||||
loadSubscriptionsAndTags();
|
||||
}
|
||||
};
|
||||
tagAdapter.setSelectedTag(prefs.getString(PREF_LAST_TAG, FeedPreferences.TAG_ROOT));
|
||||
tagsRecycler.setAdapter(tagAdapter);
|
||||
if (getArguments() != null) {
|
||||
tagAdapter.setSelectedTag(getArguments().getString(ARGUMENT_FOLDER, null));
|
||||
}
|
||||
return root;
|
||||
}
|
||||
|
||||
@ -282,13 +295,14 @@ public class SubscriptionFragment extends Fragment
|
||||
public void onStart() {
|
||||
super.onStart();
|
||||
EventBus.getDefault().register(this);
|
||||
loadSubscriptions();
|
||||
loadSubscriptionsAndTags();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onPause() {
|
||||
super.onPause();
|
||||
scrollPosition = getScrollPosition();
|
||||
prefs.edit().putString(PREF_LAST_TAG, tagAdapter.getSelectedTag()).apply();
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -303,44 +317,45 @@ public class SubscriptionFragment extends Fragment
|
||||
}
|
||||
}
|
||||
|
||||
private void loadSubscriptions() {
|
||||
private void loadSubscriptionsAndTags() {
|
||||
if (disposable != null) {
|
||||
disposable.dispose();
|
||||
}
|
||||
emptyView.hide();
|
||||
disposable = Observable.fromCallable(
|
||||
() -> {
|
||||
NavDrawerData data = DBReader.getNavDrawerData(UserPreferences.getSubscriptionsFilter(),
|
||||
UserPreferences.getFeedOrder(), UserPreferences.getFeedCounterSetting());
|
||||
List<NavDrawerData.DrawerItem> items = data.items;
|
||||
for (NavDrawerData.DrawerItem item : items) {
|
||||
if (item.type == NavDrawerData.DrawerItem.Type.TAG
|
||||
&& item.getTitle().equals(displayedFolder)) {
|
||||
return ((NavDrawerData.TagDrawerItem) item).getChildren();
|
||||
}
|
||||
}
|
||||
return items;
|
||||
})
|
||||
() -> DBReader.getNavDrawerData(UserPreferences.getSubscriptionsFilter(),
|
||||
UserPreferences.getFeedOrder(), UserPreferences.getFeedCounterSetting()))
|
||||
.subscribeOn(Schedulers.io())
|
||||
.observeOn(AndroidSchedulers.mainThread())
|
||||
.subscribe(
|
||||
result -> {
|
||||
final boolean firstLoaded = listItems == null || listItems.isEmpty();
|
||||
if (listItems != null && listItems.size() > result.size()) {
|
||||
List<Feed> openedFolderFeeds = result.feeds;
|
||||
for (NavDrawerData.TagItem tag : result.tags) {
|
||||
if (tag.getTitle().equals(tagAdapter.getSelectedTag())) {
|
||||
openedFolderFeeds = tag.getFeeds();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
final boolean firstLoaded = feeds == null || feeds.isEmpty();
|
||||
if (feeds != null && feeds.size() > openedFolderFeeds.size()) {
|
||||
// We have fewer items. This can result in items being selected that are no longer visible.
|
||||
subscriptionAdapter.endSelectMode();
|
||||
}
|
||||
listItems = result;
|
||||
feeds = openedFolderFeeds;
|
||||
progressBar.setVisibility(View.GONE);
|
||||
subscriptionAdapter.setItems(result);
|
||||
subscriptionAdapter.setItems(feeds, result.feedCounters);
|
||||
if (firstLoaded) {
|
||||
restoreScrollPosition(scrollPosition);
|
||||
}
|
||||
emptyView.updateVisibility();
|
||||
if (tagAdapter != null) {
|
||||
tagAdapter.setTags(result.tags);
|
||||
tagsRecycler.setVisibility(result.tags.size() > 1 ? View.VISIBLE : View.GONE);
|
||||
}
|
||||
}, error -> {
|
||||
Log.e(TAG, Log.getStackTraceString(error));
|
||||
});
|
||||
|
||||
updateFilterVisibility();
|
||||
}
|
||||
|
||||
@ -358,75 +373,71 @@ public class SubscriptionFragment extends Fragment
|
||||
return getResources().getInteger(R.integer.subscriptions_default_num_of_columns);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onContextItemSelected(MenuItem item) {
|
||||
NavDrawerData.DrawerItem drawerItem = subscriptionAdapter.getSelectedItem();
|
||||
if (drawerItem == null) {
|
||||
private boolean onTagContextItemSelected(MenuItem item) {
|
||||
NavDrawerData.TagItem selectedTag = tagAdapter.getLongPressedItem();
|
||||
if (selectedTag == null) {
|
||||
return false;
|
||||
}
|
||||
int itemId = item.getItemId();
|
||||
if (drawerItem.type == NavDrawerData.DrawerItem.Type.TAG) {
|
||||
if (itemId == R.id.rename_folder_item) {
|
||||
new RenameFeedDialog(getActivity(), drawerItem).show();
|
||||
return true;
|
||||
} else if (itemId == R.id.delete_folder_item) {
|
||||
ConfirmationDialog dialog = new ConfirmationDialog(
|
||||
getContext(), R.string.delete_tag_label,
|
||||
getString(R.string.delete_tag_confirmation, drawerItem.getTitle())) {
|
||||
if (itemId == R.id.rename_folder_item) {
|
||||
new RenameFeedDialog(getActivity(), selectedTag).show();
|
||||
return true;
|
||||
} else if (itemId == R.id.delete_folder_item) {
|
||||
ConfirmationDialog dialog = new ConfirmationDialog(getContext(), R.string.delete_tag_label,
|
||||
getString(R.string.delete_tag_confirmation, selectedTag.getTitle())) {
|
||||
|
||||
@Override
|
||||
public void onConfirmButtonPressed(DialogInterface dialog) {
|
||||
List<NavDrawerData.DrawerItem> feeds = ((NavDrawerData.TagDrawerItem) drawerItem).getChildren();
|
||||
|
||||
for (NavDrawerData.DrawerItem feed : feeds) {
|
||||
FeedPreferences preferences = ((NavDrawerData.FeedDrawerItem) feed).feed.getPreferences();
|
||||
preferences.getTags().remove(drawerItem.getTitle());
|
||||
DBWriter.setFeedPreferences(preferences);
|
||||
}
|
||||
@Override
|
||||
public void onConfirmButtonPressed(DialogInterface dialog) {
|
||||
tagAdapter.setSelectedTag(FeedPreferences.TAG_ROOT);
|
||||
for (Feed feed : selectedTag.getFeeds()) {
|
||||
FeedPreferences preferences = feed.getPreferences();
|
||||
preferences.getTags().remove(selectedTag.getTitle());
|
||||
DBWriter.setFeedPreferences(preferences);
|
||||
}
|
||||
};
|
||||
dialog.createNewDialog().show();
|
||||
}
|
||||
};
|
||||
dialog.createNewDialog().show();
|
||||
|
||||
return true;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
Feed feed = ((NavDrawerData.FeedDrawerItem) drawerItem).feed;
|
||||
if (itemId == R.id.multi_select) {
|
||||
@Override
|
||||
public boolean onContextItemSelected(@NonNull MenuItem item) {
|
||||
Feed selectedFeed = subscriptionAdapter.getSelectedItem();
|
||||
if (selectedFeed == null) {
|
||||
return false;
|
||||
}
|
||||
if (item.getItemId() == R.id.multi_select) {
|
||||
return subscriptionAdapter.onContextItemSelected(item);
|
||||
}
|
||||
return FeedMenuHandler.onMenuItemClicked(this, item.getItemId(), feed, this::loadSubscriptions);
|
||||
return FeedMenuHandler.onMenuItemClicked(this, item.getItemId(), selectedFeed, this::loadSubscriptionsAndTags);
|
||||
}
|
||||
|
||||
@Subscribe(threadMode = ThreadMode.MAIN)
|
||||
public void onFeedListChanged(FeedListUpdateEvent event) {
|
||||
loadSubscriptions();
|
||||
loadSubscriptionsAndTags();
|
||||
}
|
||||
|
||||
@Subscribe(threadMode = ThreadMode.MAIN)
|
||||
public void onUnreadItemsChanged(UnreadItemsUpdateEvent event) {
|
||||
loadSubscriptions();
|
||||
loadSubscriptionsAndTags();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onEndSelectMode() {
|
||||
floatingSelectMenu.setVisibility(View.GONE);
|
||||
subscriptionAddButton.setVisibility(View.VISIBLE);
|
||||
subscriptionAdapter.setItems(listItems);
|
||||
tagsRecycler.setVisibility(tagAdapter.getItemCount() > 1 ? View.VISIBLE : View.GONE);
|
||||
updateFilterVisibility();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onStartSelectMode() {
|
||||
List<NavDrawerData.DrawerItem> feedsOnly = new ArrayList<>();
|
||||
for (NavDrawerData.DrawerItem item : listItems) {
|
||||
if (item.type == NavDrawerData.DrawerItem.Type.FEED) {
|
||||
feedsOnly.add(item);
|
||||
}
|
||||
}
|
||||
subscriptionAdapter.setItems(feedsOnly);
|
||||
floatingSelectMenu.setVisibility(View.VISIBLE);
|
||||
subscriptionAddButton.setVisibility(View.GONE);
|
||||
tagsRecycler.setVisibility(tagAdapter.getItemCount() > 1 ? View.INVISIBLE : View.GONE);
|
||||
updateFilterVisibility();
|
||||
}
|
||||
|
||||
|
||||
@ -0,0 +1,116 @@
|
||||
package de.danoeh.antennapod.ui.screen.subscriptions;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.os.Build;
|
||||
import android.view.ContextMenu;
|
||||
import android.view.InputDevice;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.MenuInflater;
|
||||
import android.view.MotionEvent;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.recyclerview.widget.RecyclerView;
|
||||
import com.google.android.material.chip.Chip;
|
||||
import de.danoeh.antennapod.R;
|
||||
import de.danoeh.antennapod.model.feed.FeedPreferences;
|
||||
import de.danoeh.antennapod.storage.database.NavDrawerData;
|
||||
|
||||
import java.lang.ref.WeakReference;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
public class SubscriptionTagAdapter extends RecyclerView.Adapter<SubscriptionTagAdapter.TagViewHolder>
|
||||
implements View.OnCreateContextMenuListener {
|
||||
private final WeakReference<Activity> activityRef;
|
||||
private List<NavDrawerData.TagItem> tags = new ArrayList<>();
|
||||
private String selectedTag = null;
|
||||
private NavDrawerData.TagItem longPressedItem = null;
|
||||
|
||||
public SubscriptionTagAdapter(Activity activity) {
|
||||
this.activityRef = new WeakReference<>(activity);
|
||||
}
|
||||
|
||||
public void setTags(List<NavDrawerData.TagItem> tags) {
|
||||
this.tags = tags;
|
||||
notifyDataSetChanged();
|
||||
}
|
||||
|
||||
public void setSelectedTag(String tag) {
|
||||
this.selectedTag = tag;
|
||||
notifyDataSetChanged();
|
||||
}
|
||||
|
||||
public String getSelectedTag() {
|
||||
return selectedTag;
|
||||
}
|
||||
|
||||
@NonNull
|
||||
@Override
|
||||
public TagViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
|
||||
View view = LayoutInflater.from(parent.getContext())
|
||||
.inflate(R.layout.item_tag_chip, parent, false);
|
||||
return new TagViewHolder(view);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onBindViewHolder(@NonNull TagViewHolder holder, int position) {
|
||||
NavDrawerData.TagItem tag = tags.get(position);
|
||||
if (FeedPreferences.TAG_ROOT.equals(tag.getTitle())) {
|
||||
holder.chip.setText(R.string.tag_all);
|
||||
} else {
|
||||
String title = tag.getTitle();
|
||||
if (title.length() > 20) {
|
||||
title = title.substring(0, 19) + "…";
|
||||
}
|
||||
holder.chip.setText(title);
|
||||
}
|
||||
holder.chip.setChecked(tag.getTitle().equals(selectedTag));
|
||||
holder.chip.setOnClickListener(v -> onTagClick(tag));
|
||||
holder.chip.setOnTouchListener((v, e) -> {
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
|
||||
if (e.isFromSource(InputDevice.SOURCE_MOUSE)
|
||||
&& e.getButtonState() == MotionEvent.BUTTON_SECONDARY) {
|
||||
longPressedItem = tag;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
});
|
||||
holder.chip.setOnLongClickListener(v -> {
|
||||
longPressedItem = tag;
|
||||
return false;
|
||||
});
|
||||
holder.chip.setOnCreateContextMenuListener(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getItemCount() {
|
||||
return tags != null ? tags.size() : 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onCreateContextMenu(ContextMenu menu, View v, ContextMenu.ContextMenuInfo menuInfo) {
|
||||
if (longPressedItem == null || FeedPreferences.TAG_ROOT.equals(longPressedItem.getTitle())) {
|
||||
return;
|
||||
}
|
||||
MenuInflater inflater = activityRef.get().getMenuInflater();
|
||||
inflater.inflate(R.menu.nav_folder_context, menu);
|
||||
menu.setHeaderTitle(longPressedItem.getTitle());
|
||||
}
|
||||
|
||||
protected void onTagClick(NavDrawerData.TagItem tag) {
|
||||
}
|
||||
|
||||
public NavDrawerData.TagItem getLongPressedItem() {
|
||||
return longPressedItem;
|
||||
}
|
||||
|
||||
public static class TagViewHolder extends RecyclerView.ViewHolder {
|
||||
public final Chip chip;
|
||||
|
||||
public TagViewHolder(@NonNull View itemView) {
|
||||
super(itemView);
|
||||
chip = itemView.findViewById(R.id.tag_chip);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -13,7 +13,6 @@ import androidx.cardview.widget.CardView;
|
||||
import androidx.recyclerview.widget.RecyclerView;
|
||||
import de.danoeh.antennapod.R;
|
||||
import de.danoeh.antennapod.model.feed.Feed;
|
||||
import de.danoeh.antennapod.storage.database.NavDrawerData;
|
||||
import de.danoeh.antennapod.storage.preferences.UserPreferences;
|
||||
import de.danoeh.antennapod.ui.CoverLoader;
|
||||
import de.danoeh.antennapod.ui.common.ThemeUtils;
|
||||
@ -45,35 +44,28 @@ public class SubscriptionViewHolder extends RecyclerView.ViewHolder {
|
||||
this.mainActivityRef = new WeakReference<>(mainActivity);
|
||||
}
|
||||
|
||||
public void bind(NavDrawerData.DrawerItem drawerItem, int columnCount) {
|
||||
public void bind(Feed feed, int columnCount, int counter) {
|
||||
if (selectView != null) {
|
||||
Drawable drawable = AppCompatResources.getDrawable(selectView.getContext(),
|
||||
R.drawable.ic_checkbox_background);
|
||||
selectView.setBackground(drawable); // Setting this in XML crashes API <= 21
|
||||
}
|
||||
title.setText(drawerItem.getTitle());
|
||||
fallbackTitle.setText(drawerItem.getTitle());
|
||||
coverImage.setContentDescription(drawerItem.getTitle());
|
||||
if (drawerItem.getCounter() > 0) {
|
||||
count.setText(NumberFormat.getInstance().format(drawerItem.getCounter()));
|
||||
title.setText(feed.getTitle());
|
||||
fallbackTitle.setText(feed.getTitle());
|
||||
coverImage.setContentDescription(feed.getTitle());
|
||||
if (counter > 0) {
|
||||
count.setText(NumberFormat.getInstance().format(counter));
|
||||
count.setVisibility(View.VISIBLE);
|
||||
} else {
|
||||
count.setVisibility(View.GONE);
|
||||
}
|
||||
|
||||
CoverLoader coverLoader = new CoverLoader();
|
||||
boolean textAndImageCombined;
|
||||
if (drawerItem.type == NavDrawerData.DrawerItem.Type.FEED) {
|
||||
Feed feed = ((NavDrawerData.FeedDrawerItem) drawerItem).feed;
|
||||
textAndImageCombined = feed.isLocalFeed() && feed.getImageUrl() != null
|
||||
&& feed.getImageUrl().startsWith(Feed.PREFIX_GENERATIVE_COVER);
|
||||
coverLoader.withUri(feed.getImageUrl());
|
||||
errorIcon.setVisibility(feed.hasLastUpdateFailed() ? View.VISIBLE : View.GONE);
|
||||
} else {
|
||||
textAndImageCombined = true;
|
||||
coverLoader.withResource(R.drawable.ic_tag);
|
||||
errorIcon.setVisibility(View.GONE);
|
||||
}
|
||||
boolean textAndImageCombined = feed.isLocalFeed() && feed.getImageUrl() != null
|
||||
&& feed.getImageUrl().startsWith(Feed.PREFIX_GENERATIVE_COVER);
|
||||
coverLoader.withUri(feed.getImageUrl());
|
||||
errorIcon.setVisibility(feed.hasLastUpdateFailed() ? View.VISIBLE : View.GONE);
|
||||
|
||||
if (UserPreferences.shouldShowSubscriptionTitle() || columnCount == 1) {
|
||||
// No need for fallback title when already showing title
|
||||
fallbackTitle.setVisibility(View.GONE);
|
||||
|
||||
@ -18,7 +18,6 @@ import androidx.recyclerview.widget.RecyclerView;
|
||||
import de.danoeh.antennapod.R;
|
||||
import de.danoeh.antennapod.activity.MainActivity;
|
||||
import de.danoeh.antennapod.model.feed.Feed;
|
||||
import de.danoeh.antennapod.storage.database.NavDrawerData;
|
||||
import de.danoeh.antennapod.storage.preferences.UserPreferences;
|
||||
import de.danoeh.antennapod.ui.SelectableAdapter;
|
||||
import de.danoeh.antennapod.ui.common.ThemeUtils;
|
||||
@ -27,6 +26,7 @@ import de.danoeh.antennapod.ui.screen.feed.FeedItemlistFragment;
|
||||
import java.lang.ref.WeakReference;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* Adapter for subscriptions
|
||||
@ -34,8 +34,9 @@ import java.util.List;
|
||||
public class SubscriptionsRecyclerAdapter extends SelectableAdapter<SubscriptionViewHolder>
|
||||
implements View.OnCreateContextMenuListener {
|
||||
private final WeakReference<MainActivity> mainActivityRef;
|
||||
private List<NavDrawerData.DrawerItem> listItems;
|
||||
private NavDrawerData.DrawerItem selectedItem = null;
|
||||
private List<Feed> listItems;
|
||||
private Map<Long, Integer> feedCounters;
|
||||
private Feed selectedItem = null;
|
||||
int longPressedPosition = 0; // used to init actionMode
|
||||
private int columnCount = 3;
|
||||
|
||||
@ -43,6 +44,7 @@ public class SubscriptionsRecyclerAdapter extends SelectableAdapter<Subscription
|
||||
super(mainActivity);
|
||||
this.mainActivityRef = new WeakReference<>(mainActivity);
|
||||
this.listItems = new ArrayList<>();
|
||||
this.feedCounters = Map.of();
|
||||
setHasStableIds(true);
|
||||
}
|
||||
|
||||
@ -54,7 +56,7 @@ public class SubscriptionsRecyclerAdapter extends SelectableAdapter<Subscription
|
||||
return listItems.get(position);
|
||||
}
|
||||
|
||||
public NavDrawerData.DrawerItem getSelectedItem() {
|
||||
public Feed getSelectedItem() {
|
||||
return selectedItem;
|
||||
}
|
||||
|
||||
@ -75,16 +77,13 @@ public class SubscriptionsRecyclerAdapter extends SelectableAdapter<Subscription
|
||||
|
||||
@Override
|
||||
public void onBindViewHolder(@NonNull SubscriptionViewHolder holder, int position) {
|
||||
NavDrawerData.DrawerItem drawerItem = listItems.get(position);
|
||||
boolean isFeed = drawerItem.type == NavDrawerData.DrawerItem.Type.FEED;
|
||||
holder.bind(drawerItem, columnCount);
|
||||
Feed feed = listItems.get(position);
|
||||
holder.bind(feed, columnCount, feedCounters.containsKey(feed.getId()) ? feedCounters.get(feed.getId()) : 0);
|
||||
holder.itemView.setOnCreateContextMenuListener(this);
|
||||
if (inActionMode()) {
|
||||
if (holder.selectView != null) {
|
||||
if (isFeed) {
|
||||
holder.selectCheckbox.setVisibility(View.VISIBLE);
|
||||
}
|
||||
holder.selectView.setVisibility(isFeed ? View.VISIBLE : View.GONE);
|
||||
holder.selectCheckbox.setVisibility(View.VISIBLE);
|
||||
holder.selectView.setVisibility(View.VISIBLE);
|
||||
holder.selectCheckbox.setChecked((isSelected(position)));
|
||||
holder.selectCheckbox.setOnCheckedChangeListener((buttonView, isChecked)
|
||||
-> setSelected(holder.getBindingAdapterPosition(), isChecked));
|
||||
@ -106,10 +105,8 @@ public class SubscriptionsRecyclerAdapter extends SelectableAdapter<Subscription
|
||||
|
||||
holder.itemView.setOnLongClickListener(v -> {
|
||||
if (!inActionMode()) {
|
||||
if (isFeed) {
|
||||
longPressedPosition = holder.getBindingAdapterPosition();
|
||||
}
|
||||
selectedItem = drawerItem;
|
||||
longPressedPosition = holder.getBindingAdapterPosition();
|
||||
selectedItem = feed;
|
||||
}
|
||||
return false;
|
||||
});
|
||||
@ -119,27 +116,19 @@ public class SubscriptionsRecyclerAdapter extends SelectableAdapter<Subscription
|
||||
if (e.isFromSource(InputDevice.SOURCE_MOUSE)
|
||||
&& e.getButtonState() == MotionEvent.BUTTON_SECONDARY) {
|
||||
if (!inActionMode()) {
|
||||
if (isFeed) {
|
||||
longPressedPosition = holder.getBindingAdapterPosition();
|
||||
}
|
||||
selectedItem = drawerItem;
|
||||
longPressedPosition = holder.getBindingAdapterPosition();
|
||||
selectedItem = feed;
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
});
|
||||
holder.itemView.setOnClickListener(v -> {
|
||||
if (isFeed) {
|
||||
if (inActionMode()) {
|
||||
setSelected(holder.getBindingAdapterPosition(), !isSelected(holder.getBindingAdapterPosition()));
|
||||
notifyItemChanged(holder.getBindingAdapterPosition());
|
||||
} else {
|
||||
Fragment fragment = FeedItemlistFragment
|
||||
.newInstance(((NavDrawerData.FeedDrawerItem) drawerItem).feed.getId());
|
||||
mainActivityRef.get().loadChildFragment(fragment);
|
||||
}
|
||||
} else if (!inActionMode()) {
|
||||
Fragment fragment = SubscriptionFragment.newInstance(drawerItem.getTitle());
|
||||
if (inActionMode()) {
|
||||
setSelected(holder.getBindingAdapterPosition(), !isSelected(holder.getBindingAdapterPosition()));
|
||||
notifyItemChanged(holder.getBindingAdapterPosition());
|
||||
} else {
|
||||
Fragment fragment = FeedItemlistFragment.newInstance(feed.getId());
|
||||
mainActivityRef.get().loadChildFragment(fragment);
|
||||
}
|
||||
});
|
||||
@ -156,7 +145,7 @@ public class SubscriptionsRecyclerAdapter extends SelectableAdapter<Subscription
|
||||
if (position >= listItems.size()) {
|
||||
return RecyclerView.NO_ID; // Dummy views
|
||||
}
|
||||
return listItems.get(position).id;
|
||||
return listItems.get(position).getId();
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -165,12 +154,8 @@ public class SubscriptionsRecyclerAdapter extends SelectableAdapter<Subscription
|
||||
return;
|
||||
}
|
||||
MenuInflater inflater = mainActivityRef.get().getMenuInflater();
|
||||
if (selectedItem.type == NavDrawerData.DrawerItem.Type.FEED) {
|
||||
inflater.inflate(R.menu.nav_feed_context, menu);
|
||||
menu.findItem(R.id.multi_select).setVisible(true);
|
||||
} else {
|
||||
inflater.inflate(R.menu.nav_folder_context, menu);
|
||||
}
|
||||
inflater.inflate(R.menu.nav_feed_context, menu);
|
||||
menu.findItem(R.id.multi_select).setVisible(true);
|
||||
menu.setHeaderTitle(selectedItem.getTitle());
|
||||
}
|
||||
|
||||
@ -186,29 +171,18 @@ public class SubscriptionsRecyclerAdapter extends SelectableAdapter<Subscription
|
||||
List<Feed> items = new ArrayList<>();
|
||||
for (int i = 0; i < getItemCount(); i++) {
|
||||
if (isSelected(i)) {
|
||||
NavDrawerData.DrawerItem drawerItem = listItems.get(i);
|
||||
if (drawerItem.type == NavDrawerData.DrawerItem.Type.FEED) {
|
||||
Feed feed = ((NavDrawerData.FeedDrawerItem) drawerItem).feed;
|
||||
items.add(feed);
|
||||
}
|
||||
items.add(listItems.get(i));
|
||||
}
|
||||
}
|
||||
return items;
|
||||
}
|
||||
|
||||
public void setItems(List<NavDrawerData.DrawerItem> listItems) {
|
||||
public void setItems(List<Feed> listItems, Map<Long, Integer> feedCounters) {
|
||||
this.listItems = listItems;
|
||||
this.feedCounters = feedCounters;
|
||||
notifyDataSetChanged();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setSelected(int pos, boolean selected) {
|
||||
NavDrawerData.DrawerItem drawerItem = listItems.get(pos);
|
||||
if (drawerItem.type == NavDrawerData.DrawerItem.Type.FEED) {
|
||||
super.setSelected(pos, selected);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getItemViewType(int position) {
|
||||
if (columnCount == 1) {
|
||||
|
||||
@ -6,19 +6,24 @@ import android.view.View;
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.recyclerview.widget.RecyclerView;
|
||||
|
||||
/**
|
||||
* Source: https://stackoverflow.com/a/30794046
|
||||
*/
|
||||
public class ItemOffsetDecoration extends RecyclerView.ItemDecoration {
|
||||
private final int itemOffset;
|
||||
private final int itemOffsetHorizontal;
|
||||
private final int itemOffsetVertical;
|
||||
|
||||
public ItemOffsetDecoration(@NonNull Context context, int itemOffsetDp) {
|
||||
itemOffset = (int) (itemOffsetDp * context.getResources().getDisplayMetrics().density);
|
||||
itemOffsetHorizontal = (int) (itemOffsetDp * context.getResources().getDisplayMetrics().density);
|
||||
itemOffsetVertical = (int) (itemOffsetDp * context.getResources().getDisplayMetrics().density);
|
||||
}
|
||||
|
||||
public ItemOffsetDecoration(@NonNull Context context, int itemOffsetHorizontalDp, int itemOffsetVerticalDp) {
|
||||
itemOffsetHorizontal = (int) (itemOffsetHorizontalDp * context.getResources().getDisplayMetrics().density);
|
||||
itemOffsetVertical = (int) (itemOffsetVerticalDp * context.getResources().getDisplayMetrics().density);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void getItemOffsets(Rect outRect, View view, RecyclerView parent, RecyclerView.State state) {
|
||||
public void getItemOffsets(@NonNull Rect outRect, @NonNull View view, @NonNull RecyclerView parent,
|
||||
@NonNull RecyclerView.State state) {
|
||||
super.getItemOffsets(outRect, view, parent, state);
|
||||
outRect.set(itemOffset, itemOffset, itemOffset, itemOffset);
|
||||
outRect.set(itemOffsetHorizontal, itemOffsetVertical, itemOffsetHorizontal, itemOffsetVertical);
|
||||
}
|
||||
}
|
||||
|
||||
@ -20,15 +20,32 @@
|
||||
app:navigationContentDescription="@string/toolbar_back_button_content_description"
|
||||
app:navigationIcon="?homeAsUpIndicator" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/feeds_filtered_message"
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:paddingHorizontal="16dp"
|
||||
android:paddingVertical="4dp"
|
||||
android:layout_marginTop="-16dp"
|
||||
android:background="?android:attr/selectableItemBackground"
|
||||
android:text="@string/filtered_label" />
|
||||
android:orientation="vertical">
|
||||
|
||||
<androidx.recyclerview.widget.RecyclerView
|
||||
android:id="@+id/tags_recycler"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:paddingHorizontal="12dp"
|
||||
android:clipToPadding="false"
|
||||
android:visibility="visible"
|
||||
tools:orientation="horizontal"
|
||||
tools:listitem="@layout/item_tag_chip" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/feeds_filtered_message"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:paddingHorizontal="16dp"
|
||||
android:paddingVertical="4dp"
|
||||
android:background="?android:attr/selectableItemBackground"
|
||||
android:text="@string/filtered_label" />
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
</com.google.android.material.appbar.AppBarLayout>
|
||||
|
||||
|
||||
9
app/src/main/res/layout/item_tag_chip.xml
Normal file
9
app/src/main/res/layout/item_tag_chip.xml
Normal file
@ -0,0 +1,9 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<com.google.android.material.chip.Chip
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:id="@+id/tag_chip"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:checkable="true"
|
||||
android:longClickable="true"
|
||||
style="@style/Widget.Material3.Chip.Filter" />
|
||||
@ -343,7 +343,7 @@ public class DbReaderTest {
|
||||
DbTestUtils.saveFeedlist(numFeeds, numItems, true);
|
||||
NavDrawerData navDrawerData = DBReader.getNavDrawerData(
|
||||
UserPreferences.getSubscriptionsFilter(), FeedOrder.COUNTER, FeedCounter.SHOW_NEW);
|
||||
assertEquals(numFeeds, navDrawerData.items.size());
|
||||
assertEquals(numFeeds, navDrawerData.feeds.size());
|
||||
assertEquals(0, navDrawerData.numNewItems);
|
||||
assertEquals(0, navDrawerData.queueSize);
|
||||
}
|
||||
@ -373,7 +373,7 @@ public class DbReaderTest {
|
||||
|
||||
NavDrawerData navDrawerData = DBReader.getNavDrawerData(
|
||||
UserPreferences.getSubscriptionsFilter(), FeedOrder.COUNTER, FeedCounter.SHOW_NEW);
|
||||
assertEquals(numFeeds, navDrawerData.items.size());
|
||||
assertEquals(numFeeds, navDrawerData.feeds.size());
|
||||
assertEquals(numNew, navDrawerData.numNewItems);
|
||||
assertEquals(numQueue, navDrawerData.queueSize);
|
||||
}
|
||||
|
||||
@ -21,7 +21,6 @@ import de.danoeh.antennapod.model.feed.FeedItem;
|
||||
import de.danoeh.antennapod.model.feed.FeedItemFilter;
|
||||
import de.danoeh.antennapod.model.feed.FeedMedia;
|
||||
import de.danoeh.antennapod.model.feed.FeedOrder;
|
||||
import de.danoeh.antennapod.model.feed.FeedPreferences;
|
||||
import de.danoeh.antennapod.model.feed.SortOrder;
|
||||
import de.danoeh.antennapod.model.feed.SubscriptionsFilter;
|
||||
import de.danoeh.antennapod.model.download.DownloadResult;
|
||||
@ -737,32 +736,21 @@ public final class DBReader {
|
||||
final int numNewItems = getTotalEpisodeCount(new FeedItemFilter(FeedItemFilter.NEW));
|
||||
final int numDownloadedItems = getTotalEpisodeCount(new FeedItemFilter(FeedItemFilter.DOWNLOADED));
|
||||
|
||||
List<NavDrawerData.DrawerItem> items = new ArrayList<>();
|
||||
Map<String, NavDrawerData.TagDrawerItem> folders = new HashMap<>();
|
||||
Map<String, NavDrawerData.TagItem> tags = new HashMap<>();
|
||||
for (Feed feed : feeds) {
|
||||
for (String tag : feed.getPreferences().getTags()) {
|
||||
if (!tags.containsKey(tag)) {
|
||||
tags.put(tag, new NavDrawerData.TagItem(tag));
|
||||
}
|
||||
int counter = feedCounters.containsKey(feed.getId()) ? feedCounters.get(feed.getId()) : 0;
|
||||
NavDrawerData.FeedDrawerItem drawerItem = new NavDrawerData.FeedDrawerItem(feed, feed.getId(), counter);
|
||||
if (FeedPreferences.TAG_ROOT.equals(tag)) {
|
||||
items.add(drawerItem);
|
||||
continue;
|
||||
}
|
||||
NavDrawerData.TagDrawerItem folder;
|
||||
if (folders.containsKey(tag)) {
|
||||
folder = folders.get(tag);
|
||||
} else {
|
||||
folder = new NavDrawerData.TagDrawerItem(tag);
|
||||
folders.put(tag, folder);
|
||||
}
|
||||
drawerItem.id |= folder.id;
|
||||
folder.getChildren().add(drawerItem);
|
||||
tags.get(tag).addFeed(feed, counter);
|
||||
}
|
||||
}
|
||||
List<NavDrawerData.TagDrawerItem> foldersSorted = new ArrayList<>(folders.values());
|
||||
Collections.sort(foldersSorted, (o1, o2) -> o1.getTitle().compareToIgnoreCase(o2.getTitle()));
|
||||
items.addAll(foldersSorted);
|
||||
List<NavDrawerData.TagItem> tagsSorted = new ArrayList<>(tags.values());
|
||||
Collections.sort(tagsSorted, (o1, o2) -> o1.getTitle().compareToIgnoreCase(o2.getTitle()));
|
||||
|
||||
NavDrawerData result = new NavDrawerData(items, queueSize, numNewItems, numDownloadedItems, feedCounters);
|
||||
NavDrawerData result = new NavDrawerData(feeds, tagsSorted,
|
||||
queueSize, numNewItems, numDownloadedItems, feedCounters);
|
||||
adapter.close();
|
||||
return result;
|
||||
}
|
||||
|
||||
@ -7,60 +7,38 @@ import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
public class NavDrawerData {
|
||||
public final List<DrawerItem> items;
|
||||
public final List<Feed> feeds;
|
||||
public final List<TagItem> tags;
|
||||
public final int queueSize;
|
||||
public final int numNewItems;
|
||||
public final int numDownloadedItems;
|
||||
public final Map<Long, Integer> feedCounters;
|
||||
|
||||
public NavDrawerData(List<DrawerItem> feeds,
|
||||
public NavDrawerData(List<Feed> feeds,
|
||||
List<TagItem> tags,
|
||||
int queueSize,
|
||||
int numNewItems,
|
||||
int numDownloadedItems,
|
||||
Map<Long, Integer> feedIndicatorValues) {
|
||||
this.items = feeds;
|
||||
this.feeds = feeds;
|
||||
this.tags = tags;
|
||||
this.queueSize = queueSize;
|
||||
this.numNewItems = numNewItems;
|
||||
this.numDownloadedItems = numDownloadedItems;
|
||||
this.feedCounters = feedIndicatorValues;
|
||||
}
|
||||
|
||||
public abstract static class DrawerItem {
|
||||
public enum Type {
|
||||
TAG, FEED
|
||||
}
|
||||
|
||||
public final Type type;
|
||||
private int layer;
|
||||
public long id;
|
||||
|
||||
public DrawerItem(Type type, long id) {
|
||||
this.type = type;
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
public int getLayer() {
|
||||
return layer;
|
||||
}
|
||||
|
||||
public void setLayer(int layer) {
|
||||
this.layer = layer;
|
||||
}
|
||||
|
||||
public abstract String getTitle();
|
||||
|
||||
public abstract int getCounter();
|
||||
}
|
||||
|
||||
public static class TagDrawerItem extends DrawerItem {
|
||||
private final List<DrawerItem> children = new ArrayList<>();
|
||||
public static class TagItem {
|
||||
private final String name;
|
||||
private boolean isOpen;
|
||||
private List<Feed> feeds = new ArrayList<>();
|
||||
private int counter = 0;
|
||||
private boolean isOpen = false;
|
||||
private long id;
|
||||
|
||||
public TagDrawerItem(String name) {
|
||||
// Keep IDs >0 but make room for many feeds
|
||||
super(DrawerItem.Type.TAG, Math.abs((long) name.hashCode()) << 20);
|
||||
public TagItem(String name) {
|
||||
this.name = name;
|
||||
// Keep IDs >0 but make room for many feeds
|
||||
this.id = (Math.abs((long) name.hashCode()) << 20);
|
||||
}
|
||||
|
||||
public String getTitle() {
|
||||
@ -75,35 +53,21 @@ public class NavDrawerData {
|
||||
isOpen = open;
|
||||
}
|
||||
|
||||
public List<DrawerItem> getChildren() {
|
||||
return children;
|
||||
}
|
||||
|
||||
public int getCounter() {
|
||||
int sum = 0;
|
||||
for (DrawerItem item : children) {
|
||||
sum += item.getCounter();
|
||||
}
|
||||
return sum;
|
||||
}
|
||||
}
|
||||
|
||||
public static class FeedDrawerItem extends DrawerItem {
|
||||
public final Feed feed;
|
||||
public final int counter;
|
||||
|
||||
public FeedDrawerItem(Feed feed, long id, int counter) {
|
||||
super(DrawerItem.Type.FEED, id);
|
||||
this.feed = feed;
|
||||
this.counter = counter;
|
||||
}
|
||||
|
||||
public String getTitle() {
|
||||
return feed.getTitle();
|
||||
public List<Feed> getFeeds() {
|
||||
return feeds;
|
||||
}
|
||||
|
||||
public int getCounter() {
|
||||
return counter;
|
||||
}
|
||||
|
||||
public void addFeed(Feed feed, int feedCounter) {
|
||||
counter += feedCounter;
|
||||
feeds.add(feed);
|
||||
}
|
||||
|
||||
public long getId() {
|
||||
return id;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -761,7 +761,8 @@
|
||||
<string name="authentication_descr">Change your username and password for this podcast and its episodes</string>
|
||||
<string name="feed_tags_label">Tags</string>
|
||||
<string name="feed_tags_summary">Change the tags of this podcast to help organize your subscriptions</string>
|
||||
<string name="feed_folders_include_root">Show this podcast in main list</string>
|
||||
<string name="feed_folders_include_root">Show this podcast in \"all\" tag</string>
|
||||
<string name="tag_all">All</string>
|
||||
<string name="multi_feed_common_tags_info">Only common tags from all selected subscriptions are shown. Other tags stay unaffected.</string>
|
||||
<string name="auto_download_inbox_category">Automatically download episodes from the inbox</string>
|
||||
<string name="episode_filters_label">Episode filter</string>
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user