Use dummy items instead of loading progress bar

This commit is contained in:
ByteHamster 2022-08-28 16:52:29 +02:00
parent 4c88a1aa69
commit c42ed1d187
14 changed files with 256 additions and 365 deletions

View File

@ -52,6 +52,7 @@ public class SubscriptionsRecyclerAdapter extends SelectableAdapter<Subscription
private List<NavDrawerData.DrawerItem> listItems; private List<NavDrawerData.DrawerItem> listItems;
private NavDrawerData.DrawerItem selectedItem = null; private NavDrawerData.DrawerItem selectedItem = null;
int longPressedPosition = 0; // used to init actionMode int longPressedPosition = 0; // used to init actionMode
private int dummyViews = 0;
public SubscriptionsRecyclerAdapter(MainActivity mainActivity) { public SubscriptionsRecyclerAdapter(MainActivity mainActivity) {
super(mainActivity); super(mainActivity);
@ -95,6 +96,11 @@ public class SubscriptionsRecyclerAdapter extends SelectableAdapter<Subscription
@Override @Override
public void onBindViewHolder(@NonNull SubscriptionViewHolder holder, int position) { public void onBindViewHolder(@NonNull SubscriptionViewHolder holder, int position) {
if (position >= listItems.size()) {
holder.selectView.setVisibility(View.GONE);
holder.bindDummy();
return;
}
NavDrawerData.DrawerItem drawerItem = listItems.get(position); NavDrawerData.DrawerItem drawerItem = listItems.get(position);
boolean isFeed = drawerItem.type == NavDrawerData.DrawerItem.Type.FEED; boolean isFeed = drawerItem.type == NavDrawerData.DrawerItem.Type.FEED;
holder.bind(drawerItem); holder.bind(drawerItem);
@ -157,11 +163,14 @@ public class SubscriptionsRecyclerAdapter extends SelectableAdapter<Subscription
@Override @Override
public int getItemCount() { public int getItemCount() {
return listItems.size(); return listItems.size() + dummyViews;
} }
@Override @Override
public long getItemId(int position) { public long getItemId(int position) {
if (position >= listItems.size()) {
return RecyclerView.NO_ID; // Dummy views
}
return listItems.get(position).id; return listItems.get(position).id;
} }
@ -202,6 +211,10 @@ public class SubscriptionsRecyclerAdapter extends SelectableAdapter<Subscription
return items; return items;
} }
public void setDummyViews(int dummyViews) {
this.dummyViews = dummyViews;
}
public void setItems(List<NavDrawerData.DrawerItem> listItems) { public void setItems(List<NavDrawerData.DrawerItem> listItems) {
this.listItems = listItems; this.listItems = listItems;
} }
@ -270,6 +283,17 @@ public class SubscriptionsRecyclerAdapter extends SelectableAdapter<Subscription
.load(); .load();
} }
} }
public void bindDummy() {
feedTitle.setText("███████");
feedTitle.setVisibility(View.VISIBLE);
count.setVisibility(View.GONE);
new CoverLoader(mainActivityRef.get())
.withResource(android.R.color.transparent)
.withPlaceholderView(feedTitle, false)
.withCoverView(imageView)
.load();
}
} }
public static float convertDpToPixel(Context context, float dp) { public static float convertDpToPixel(Context context, float dp) {

View File

@ -1,5 +1,6 @@
package de.danoeh.antennapod.fragment; package de.danoeh.antennapod.fragment;
import android.content.Context;
import android.os.Bundle; import android.os.Bundle;
import android.util.Log; import android.util.Log;
import android.view.ContextMenu; import android.view.ContextMenu;
@ -7,7 +8,6 @@ import android.view.LayoutInflater;
import android.view.MenuItem; import android.view.MenuItem;
import android.view.View; import android.view.View;
import android.view.ViewGroup; import android.view.ViewGroup;
import android.widget.ProgressBar;
import androidx.annotation.NonNull; import androidx.annotation.NonNull;
import androidx.annotation.Nullable; import androidx.annotation.Nullable;
import androidx.appcompat.widget.Toolbar; import androidx.appcompat.widget.Toolbar;
@ -46,6 +46,7 @@ import org.greenrobot.eventbus.ThreadMode;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Arrays; import java.util.Arrays;
import java.util.Collections;
import java.util.List; import java.util.List;
/** /**
@ -56,12 +57,12 @@ public class CompletedDownloadsFragment extends Fragment
public static final String TAG = "DownloadsFragment"; public static final String TAG = "DownloadsFragment";
public static final String ARG_SHOW_LOGS = "show_logs"; public static final String ARG_SHOW_LOGS = "show_logs";
private static final String KEY_UP_ARROW = "up_arrow"; private static final String KEY_UP_ARROW = "up_arrow";
private static final String PREF_PREVIOUS_EPISODE_COUNT = "episodeCount";
private long[] runningDownloads = new long[0]; private long[] runningDownloads = new long[0];
private List<FeedItem> items = new ArrayList<>(); private List<FeedItem> items = new ArrayList<>();
private CompletedDownloadsListAdapter adapter; private CompletedDownloadsListAdapter adapter;
private EpisodeItemListRecyclerView recyclerView; private EpisodeItemListRecyclerView recyclerView;
private ProgressBar progressBar;
private Disposable disposable; private Disposable disposable;
private EmptyViewHandler emptyView; private EmptyViewHandler emptyView;
private boolean displayUpArrow; private boolean displayUpArrow;
@ -91,11 +92,12 @@ public class CompletedDownloadsFragment extends Fragment
recyclerView.setRecycledViewPool(((MainActivity) getActivity()).getRecycledViewPool()); recyclerView.setRecycledViewPool(((MainActivity) getActivity()).getRecycledViewPool());
adapter = new CompletedDownloadsListAdapter((MainActivity) getActivity()); adapter = new CompletedDownloadsListAdapter((MainActivity) getActivity());
adapter.setOnSelectModeListener(this); adapter.setOnSelectModeListener(this);
int previousEpisodesCount = getContext().getSharedPreferences(TAG, Context.MODE_PRIVATE)
.getInt(PREF_PREVIOUS_EPISODE_COUNT, 5);
adapter.setDummyViews(Math.max(1, previousEpisodesCount));
recyclerView.setAdapter(adapter); recyclerView.setAdapter(adapter);
swipeActions = new SwipeActions(this, TAG).attachTo(recyclerView); swipeActions = new SwipeActions(this, TAG).attachTo(recyclerView);
swipeActions.setFilter(new FeedItemFilter(FeedItemFilter.DOWNLOADED)); swipeActions.setFilter(new FeedItemFilter(FeedItemFilter.DOWNLOADED));
progressBar = root.findViewById(R.id.progLoading);
progressBar.setVisibility(View.VISIBLE);
speedDialView = root.findViewById(R.id.fabSD); speedDialView = root.findViewById(R.id.fabSD);
speedDialView.setOverlayLayout(root.findViewById(R.id.fabSDOverlay)); speedDialView.setOverlayLayout(root.findViewById(R.id.fabSDOverlay));
@ -159,6 +161,9 @@ public class CompletedDownloadsFragment extends Fragment
if (disposable != null) { if (disposable != null) {
disposable.dispose(); disposable.dispose();
} }
getContext().getSharedPreferences(TAG, Context.MODE_PRIVATE).edit()
.putInt(PREF_PREVIOUS_EPISODE_COUNT, adapter.getItemCount())
.apply();
} }
@Override @Override
@ -291,11 +296,16 @@ public class CompletedDownloadsFragment extends Fragment
}) })
.subscribeOn(Schedulers.io()) .subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread()) .observeOn(AndroidSchedulers.mainThread())
.subscribe(result -> { .subscribe(
items = result; result -> {
adapter.updateItems(result); items = result;
progressBar.setVisibility(View.GONE); adapter.setDummyViews(0);
}, error -> Log.e(TAG, Log.getStackTraceString(error))); adapter.updateItems(result);
}, error -> {
adapter.setDummyViews(0);
adapter.updateItems(Collections.emptyList());
Log.e(TAG, Log.getStackTraceString(error));
});
} }
@Override @Override

View File

@ -1,5 +1,6 @@
package de.danoeh.antennapod.fragment; package de.danoeh.antennapod.fragment;
import android.content.Context;
import android.content.DialogInterface; import android.content.DialogInterface;
import android.os.Bundle; import android.os.Bundle;
import android.os.Handler; import android.os.Handler;
@ -11,7 +12,6 @@ import android.view.LayoutInflater;
import android.view.MenuItem; import android.view.MenuItem;
import android.view.View; import android.view.View;
import android.view.ViewGroup; import android.view.ViewGroup;
import android.widget.ProgressBar;
import android.widget.TextView; import android.widget.TextView;
import androidx.annotation.NonNull; import androidx.annotation.NonNull;
import androidx.appcompat.widget.Toolbar; import androidx.appcompat.widget.Toolbar;
@ -56,6 +56,7 @@ import org.greenrobot.eventbus.Subscribe;
import org.greenrobot.eventbus.ThreadMode; import org.greenrobot.eventbus.ThreadMode;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Collections;
import java.util.List; import java.util.List;
/** /**
@ -65,16 +66,15 @@ public abstract class EpisodesListFragment extends Fragment
implements EpisodeItemListAdapter.OnSelectModeListener, Toolbar.OnMenuItemClickListener { implements EpisodeItemListAdapter.OnSelectModeListener, Toolbar.OnMenuItemClickListener {
public static final String TAG = "EpisodesListFragment"; public static final String TAG = "EpisodesListFragment";
private static final String KEY_UP_ARROW = "up_arrow"; private static final String KEY_UP_ARROW = "up_arrow";
private static final String PREF_PREVIOUS_EPISODE_COUNT = "episodeCount";
protected static final int EPISODES_PER_PAGE = 150; protected static final int EPISODES_PER_PAGE = 150;
protected int page = 1; protected int page = 1;
protected boolean isLoadingMore = false; protected boolean isLoadingMore = false;
protected boolean hasMoreItems = true; protected boolean hasMoreItems = false;
private boolean displayUpArrow; private boolean displayUpArrow;
EpisodeItemListRecyclerView recyclerView; EpisodeItemListRecyclerView recyclerView;
EpisodeItemListAdapter listAdapter; EpisodeItemListAdapter listAdapter;
ProgressBar progLoading;
View loadingMoreView;
EmptyViewHandler emptyView; EmptyViewHandler emptyView;
SpeedDialView speedDialView; SpeedDialView speedDialView;
Toolbar toolbar; Toolbar toolbar;
@ -113,6 +113,9 @@ public abstract class EpisodesListFragment extends Fragment
if (disposable != null) { if (disposable != null) {
disposable.dispose(); disposable.dispose();
} }
getContext().getSharedPreferences(getPrefName(), Context.MODE_PRIVATE).edit()
.putInt(PREF_PREVIOUS_EPISODE_COUNT, episodes.size())
.apply();
} }
@Override @Override
@ -187,17 +190,28 @@ public abstract class EpisodesListFragment extends Fragment
getResources().getInteger(R.integer.swipe_to_refresh_duration_in_ms)); getResources().getInteger(R.integer.swipe_to_refresh_duration_in_ms));
}); });
progLoading = root.findViewById(R.id.progLoading); listAdapter = new EpisodeItemListAdapter((MainActivity) getActivity()) {
progLoading.setVisibility(View.VISIBLE); @Override
loadingMoreView = root.findViewById(R.id.loadingMore); public void onCreateContextMenu(ContextMenu menu, View v, ContextMenu.ContextMenuInfo menuInfo) {
super.onCreateContextMenu(menu, v, menuInfo);
if (!inActionMode()) {
menu.findItem(R.id.multi_select).setVisible(true);
}
MenuItemUtils.setOnClickListeners(menu, EpisodesListFragment.this::onContextItemSelected);
}
};
listAdapter.setOnSelectModeListener(this);
int previousEpisodesCount = getContext().getSharedPreferences(getPrefName(), Context.MODE_PRIVATE)
.getInt(PREF_PREVIOUS_EPISODE_COUNT, 5);
listAdapter.setDummyViews(Math.max(1, previousEpisodesCount));
recyclerView.setAdapter(listAdapter);
emptyView = new EmptyViewHandler(getContext()); emptyView = new EmptyViewHandler(getContext());
emptyView.attachToRecyclerView(recyclerView); emptyView.attachToRecyclerView(recyclerView);
emptyView.setIcon(R.drawable.ic_feed); emptyView.setIcon(R.drawable.ic_feed);
emptyView.setTitle(R.string.no_all_episodes_head_label); emptyView.setTitle(R.string.no_all_episodes_head_label);
emptyView.setMessage(R.string.no_all_episodes_label); emptyView.setMessage(R.string.no_all_episodes_label);
emptyView.updateAdapter(listAdapter);
createRecycleAdapter(recyclerView, emptyView);
emptyView.hide(); emptyView.hide();
speedDialView = root.findViewById(R.id.fabSD); speedDialView = root.findViewById(R.id.fabSD);
@ -286,68 +300,36 @@ public abstract class EpisodesListFragment extends Fragment
disposable.dispose(); disposable.dispose();
} }
isLoadingMore = true; isLoadingMore = true;
loadingMoreView.setVisibility(View.VISIBLE); listAdapter.setDummyViews(1);
listAdapter.notifyItemInserted(listAdapter.getItemCount() - 1);
disposable = Observable.fromCallable(() -> loadMoreData(page)) disposable = Observable.fromCallable(() -> loadMoreData(page))
.subscribeOn(Schedulers.io()) .subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread()) .observeOn(AndroidSchedulers.mainThread())
.subscribe(data -> { .subscribe(
if (data.size() < EPISODES_PER_PAGE) { data -> {
hasMoreItems = false; if (data.size() < EPISODES_PER_PAGE) {
} hasMoreItems = false;
episodes.addAll(data); }
updateAdapterWithNewItems(); episodes.addAll(data);
if (listAdapter.shouldSelectLazyLoadedItems()) { listAdapter.setDummyViews(0);
listAdapter.setSelected(episodes.size() - data.size(), episodes.size(), true); listAdapter.updateItems(episodes);
} if (listAdapter.shouldSelectLazyLoadedItems()) {
}, error -> Log.e(TAG, Log.getStackTraceString(error)), listAdapter.setSelected(episodes.size() - data.size(), episodes.size(), true);
() -> { }
recyclerView.post(() -> isLoadingMore = false); // Make sure to not always load 2 pages at once }, error -> {
progLoading.setVisibility(View.GONE); listAdapter.setDummyViews(0);
loadingMoreView.setVisibility(View.GONE); listAdapter.updateItems(Collections.emptyList());
}); Log.e(TAG, Log.getStackTraceString(error));
} }, () -> {
// Make sure to not always load 2 pages at once
protected void updateAdapterWithNewItems() { recyclerView.post(() -> isLoadingMore = false);
boolean restoreScrollPosition = listAdapter.getItemCount() == 0; });
if (episodes.size() == 0) {
createRecycleAdapter(recyclerView, emptyView);
} else {
listAdapter.updateItems(episodes);
}
if (restoreScrollPosition) {
recyclerView.restoreScrollPosition(getPrefName());
}
}
/**
* Currently, we need to recreate the list adapter in order to be able to undo last item via the
* snackbar. See #3084 for details.
*/
private void createRecycleAdapter(RecyclerView recyclerView, EmptyViewHandler emptyViewHandler) {
MainActivity mainActivity = (MainActivity) getActivity();
listAdapter = new EpisodeItemListAdapter(mainActivity) {
@Override
public void onCreateContextMenu(ContextMenu menu, View v, ContextMenu.ContextMenuInfo menuInfo) {
super.onCreateContextMenu(menu, v, menuInfo);
if (!inActionMode()) {
menu.findItem(R.id.multi_select).setVisible(true);
}
MenuItemUtils.setOnClickListeners(menu, EpisodesListFragment.this::onContextItemSelected);
}
};
listAdapter.setOnSelectModeListener(this);
listAdapter.updateItems(episodes);
recyclerView.setAdapter(listAdapter);
emptyViewHandler.updateAdapter(listAdapter);
} }
@Override @Override
public void onDestroyView() { public void onDestroyView() {
super.onDestroyView(); super.onDestroyView();
if (listAdapter != null) { listAdapter.endSelectMode();
listAdapter.endSelectMode();
}
listAdapter = null;
} }
@Override @Override
@ -380,13 +362,11 @@ public abstract class EpisodesListFragment extends Fragment
@Subscribe(threadMode = ThreadMode.MAIN) @Subscribe(threadMode = ThreadMode.MAIN)
public void onEventMainThread(PlaybackPositionEvent event) { public void onEventMainThread(PlaybackPositionEvent event) {
if (listAdapter != null) { for (int i = 0; i < listAdapter.getItemCount(); i++) {
for (int i = 0; i < listAdapter.getItemCount(); i++) { EpisodeItemViewHolder holder = (EpisodeItemViewHolder) recyclerView.findViewHolderForAdapterPosition(i);
EpisodeItemViewHolder holder = (EpisodeItemViewHolder) recyclerView.findViewHolderForAdapterPosition(i); if (holder != null && holder.isCurrentlyPlayingItem()) {
if (holder != null && holder.isCurrentlyPlayingItem()) { holder.notifyPlaybackPositionUpdated(event);
holder.notifyPlaybackPositionUpdated(event); break;
break;
}
} }
} }
} }
@ -445,16 +425,20 @@ public abstract class EpisodesListFragment extends Fragment
disposable = Observable.fromCallable(() -> new Pair<>(loadData(), loadTotalItemCount())) disposable = Observable.fromCallable(() -> new Pair<>(loadData(), loadTotalItemCount()))
.subscribeOn(Schedulers.io()) .subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread()) .observeOn(AndroidSchedulers.mainThread())
.subscribe(data -> { .subscribe(
progLoading.setVisibility(View.GONE); data -> {
loadingMoreView.setVisibility(View.GONE); episodes = data.first;
hasMoreItems = true; hasMoreItems = !(page == 1 && episodes.size() < EPISODES_PER_PAGE);
episodes = data.first; listAdapter.setDummyViews(0);
listAdapter.notifyDataSetChanged(); listAdapter.updateItems(episodes);
listAdapter.setTotalNumberOfItems(data.second); listAdapter.setTotalNumberOfItems(data.second);
updateAdapterWithNewItems(); recyclerView.restoreScrollPosition(getPrefName());
updateToolbar(); updateToolbar();
}, error -> Log.e(TAG, Log.getStackTraceString(error))); }, error -> {
listAdapter.setDummyViews(0);
listAdapter.updateItems(Collections.emptyList());
Log.e(TAG, Log.getStackTraceString(error));
});
} }
@NonNull @NonNull

View File

@ -74,6 +74,7 @@ import org.greenrobot.eventbus.EventBus;
import org.greenrobot.eventbus.Subscribe; import org.greenrobot.eventbus.Subscribe;
import org.greenrobot.eventbus.ThreadMode; import org.greenrobot.eventbus.ThreadMode;
import java.util.Collections;
import java.util.List; import java.util.List;
/** /**
@ -142,7 +143,12 @@ public class FeedItemlistFragment extends Fragment implements AdapterView.OnItem
updateToolbar(); updateToolbar();
viewBinding.recyclerView.setRecycledViewPool(((MainActivity) getActivity()).getRecycledViewPool()); viewBinding.recyclerView.setRecycledViewPool(((MainActivity) getActivity()).getRecycledViewPool());
viewBinding.progLoading.setVisibility(View.VISIBLE); adapter = new FeedItemListAdapter((MainActivity) getActivity());
adapter.setOnSelectModeListener(this);
adapter.setDummyViews(10);
viewBinding.recyclerView.setAdapter(adapter);
swipeActions = new SwipeActions(this, TAG).attachTo(viewBinding.recyclerView);
ToolbarIconTintManager iconTintManager = new ToolbarIconTintManager( ToolbarIconTintManager iconTintManager = new ToolbarIconTintManager(
getContext(), viewBinding.toolbar, viewBinding.collapsingToolbar) { getContext(), viewBinding.toolbar, viewBinding.collapsingToolbar) {
@Override @Override
@ -221,10 +227,7 @@ public class FeedItemlistFragment extends Fragment implements AdapterView.OnItem
if (disposable != null) { if (disposable != null) {
disposable.dispose(); disposable.dispose();
} }
if (adapter != null) { adapter.endSelectMode();
adapter.endSelectMode();
}
adapter = null;
} }
@Override @Override
@ -294,9 +297,6 @@ public class FeedItemlistFragment extends Fragment implements AdapterView.OnItem
@Override @Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) { public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
if (adapter == null) {
return;
}
MainActivity activity = (MainActivity) getActivity(); MainActivity activity = (MainActivity) getActivity();
long[] ids = FeedItemUtil.getIds(feed.getItems()); long[] ids = FeedItemUtil.getIds(feed.getItems());
activity.loadChildFragment(ItemPagerFragment.newInstance(ids, position)); activity.loadChildFragment(ItemPagerFragment.newInstance(ids, position));
@ -315,9 +315,6 @@ public class FeedItemlistFragment extends Fragment implements AdapterView.OnItem
Log.d(TAG, "onEventMainThread() called with: " + "event = [" + event + "]"); Log.d(TAG, "onEventMainThread() called with: " + "event = [" + event + "]");
if (feed == null || feed.getItems() == null) { if (feed == null || feed.getItems() == null) {
return; return;
} else if (adapter == null) {
loadItems();
return;
} }
for (int i = 0, size = event.items.size(); i < size; i++) { for (int i = 0, size = event.items.size(); i < size; i++) {
FeedItem item = event.items.get(i); FeedItem item = event.items.get(i);
@ -335,7 +332,7 @@ public class FeedItemlistFragment extends Fragment implements AdapterView.OnItem
Log.d(TAG, "onEventMainThread() called with: " + "event = [" + event + "]"); Log.d(TAG, "onEventMainThread() called with: " + "event = [" + event + "]");
DownloaderUpdate update = event.update; DownloaderUpdate update = event.update;
updateToolbar(); updateToolbar();
if (adapter != null && update.mediaIds.length > 0 && feed != null) { if (update.mediaIds.length > 0 && feed != null) {
for (long mediaId : update.mediaIds) { for (long mediaId : update.mediaIds) {
int pos = FeedItemUtil.indexOfItemWithMediaId(feed.getItems(), mediaId); int pos = FeedItemUtil.indexOfItemWithMediaId(feed.getItems(), mediaId);
if (pos >= 0) { if (pos >= 0) {
@ -347,14 +344,12 @@ public class FeedItemlistFragment extends Fragment implements AdapterView.OnItem
@Subscribe(threadMode = ThreadMode.MAIN) @Subscribe(threadMode = ThreadMode.MAIN)
public void onEventMainThread(PlaybackPositionEvent event) { public void onEventMainThread(PlaybackPositionEvent event) {
if (adapter != null) { for (int i = 0; i < adapter.getItemCount(); i++) {
for (int i = 0; i < adapter.getItemCount(); i++) { EpisodeItemViewHolder holder = (EpisodeItemViewHolder)
EpisodeItemViewHolder holder = (EpisodeItemViewHolder) viewBinding.recyclerView.findViewHolderForAdapterPosition(i);
viewBinding.recyclerView.findViewHolderForAdapterPosition(i); if (holder != null && holder.isCurrentlyPlayingItem()) {
if (holder != null && holder.isCurrentlyPlayingItem()) { holder.notifyPlaybackPositionUpdated(event);
holder.notifyPlaybackPositionUpdated(event); break;
break;
}
} }
} }
} }
@ -417,28 +412,6 @@ public class FeedItemlistFragment extends Fragment implements AdapterView.OnItem
nextPageLoader.setLoadingState(DownloadService.isDownloadingFeeds()); nextPageLoader.setLoadingState(DownloadService.isDownloadingFeeds());
} }
private void displayList() {
if (getView() == null) {
Log.e(TAG, "Required root view is not yet created. Stop binding data to UI.");
return;
}
if (adapter == null) {
viewBinding.recyclerView.setAdapter(null);
adapter = new FeedItemListAdapter((MainActivity) getActivity());
adapter.setOnSelectModeListener(this);
viewBinding.recyclerView.setAdapter(adapter);
swipeActions = new SwipeActions(this, TAG).attachTo(viewBinding.recyclerView);
}
viewBinding.progLoading.setVisibility(View.GONE);
if (feed != null) {
adapter.updateItems(feed.getItems());
swipeActions.setFilter(feed.getItemFilter());
}
updateToolbar();
updateSyncProgressBarVisibility();
}
private void refreshHeaderView() { private void refreshHeaderView() {
setupHeaderView(); setupHeaderView();
if (viewBinding == null || feed == null) { if (viewBinding == null || feed == null) {
@ -557,12 +530,19 @@ public class FeedItemlistFragment extends Fragment implements AdapterView.OnItem
.subscribe( .subscribe(
result -> { result -> {
feed = result; feed = result;
swipeActions.setFilter(feed.getItemFilter());
refreshHeaderView(); refreshHeaderView();
displayList(); adapter.setDummyViews(0);
adapter.updateItems(feed.getItems());
updateToolbar();
updateSyncProgressBarVisibility();
}, error -> { }, error -> {
feed = null; feed = null;
refreshHeaderView(); refreshHeaderView();
displayList(); adapter.setDummyViews(0);
adapter.updateItems(Collections.emptyList());
updateToolbar();
updateSyncProgressBarVisibility();
Log.e(TAG, Log.getStackTraceString(error)); Log.e(TAG, Log.getStackTraceString(error));
}); });
} }

View File

@ -14,7 +14,6 @@ import android.view.MenuItem;
import android.view.View; import android.view.View;
import android.view.ViewGroup; import android.view.ViewGroup;
import android.widget.CheckBox; import android.widget.CheckBox;
import android.widget.ProgressBar;
import android.widget.TextView; import android.widget.TextView;
import androidx.annotation.NonNull; import androidx.annotation.NonNull;
import androidx.appcompat.app.AlertDialog; import androidx.appcompat.app.AlertDialog;
@ -24,10 +23,8 @@ import androidx.recyclerview.widget.ItemTouchHelper;
import androidx.recyclerview.widget.RecyclerView; import androidx.recyclerview.widget.RecyclerView;
import androidx.recyclerview.widget.SimpleItemAnimator; import androidx.recyclerview.widget.SimpleItemAnimator;
import androidx.swiperefreshlayout.widget.SwipeRefreshLayout; import androidx.swiperefreshlayout.widget.SwipeRefreshLayout;
import com.google.android.material.snackbar.Snackbar; import com.google.android.material.snackbar.Snackbar;
import com.leinardi.android.speeddial.SpeedDialView; import com.leinardi.android.speeddial.SpeedDialView;
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.adapter.EpisodeItemListAdapter; import de.danoeh.antennapod.adapter.EpisodeItemListAdapter;
@ -35,26 +32,26 @@ import de.danoeh.antennapod.adapter.QueueRecyclerAdapter;
import de.danoeh.antennapod.core.dialog.ConfirmationDialog; import de.danoeh.antennapod.core.dialog.ConfirmationDialog;
import de.danoeh.antennapod.core.event.DownloadEvent; import de.danoeh.antennapod.core.event.DownloadEvent;
import de.danoeh.antennapod.core.event.DownloaderUpdate; import de.danoeh.antennapod.core.event.DownloaderUpdate;
import de.danoeh.antennapod.event.FeedItemEvent;
import de.danoeh.antennapod.event.playback.PlaybackPositionEvent;
import de.danoeh.antennapod.event.PlayerStatusEvent;
import de.danoeh.antennapod.event.QueueEvent;
import de.danoeh.antennapod.event.UnreadItemsUpdateEvent;
import de.danoeh.antennapod.core.menuhandler.MenuItemUtils;
import de.danoeh.antennapod.fragment.actions.EpisodeMultiSelectActionHandler;
import de.danoeh.antennapod.fragment.swipeactions.SwipeActions;
import de.danoeh.antennapod.model.feed.FeedItem;
import de.danoeh.antennapod.core.feed.util.PlaybackSpeedUtils; import de.danoeh.antennapod.core.feed.util.PlaybackSpeedUtils;
import de.danoeh.antennapod.core.menuhandler.MenuItemUtils;
import de.danoeh.antennapod.core.preferences.UserPreferences; import de.danoeh.antennapod.core.preferences.UserPreferences;
import de.danoeh.antennapod.core.service.download.DownloadService; import de.danoeh.antennapod.core.service.download.DownloadService;
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;
import de.danoeh.antennapod.core.util.Converter; import de.danoeh.antennapod.core.util.Converter;
import de.danoeh.antennapod.core.util.FeedItemUtil; import de.danoeh.antennapod.core.util.FeedItemUtil;
import de.danoeh.antennapod.core.util.download.AutoUpdateManager;
import de.danoeh.antennapod.event.FeedItemEvent;
import de.danoeh.antennapod.event.PlayerStatusEvent;
import de.danoeh.antennapod.event.QueueEvent;
import de.danoeh.antennapod.event.UnreadItemsUpdateEvent;
import de.danoeh.antennapod.event.playback.PlaybackPositionEvent;
import de.danoeh.antennapod.fragment.actions.EpisodeMultiSelectActionHandler;
import de.danoeh.antennapod.fragment.swipeactions.SwipeActions;
import de.danoeh.antennapod.menuhandler.FeedItemMenuHandler;
import de.danoeh.antennapod.model.feed.FeedItem;
import de.danoeh.antennapod.model.feed.FeedItemFilter; import de.danoeh.antennapod.model.feed.FeedItemFilter;
import de.danoeh.antennapod.model.feed.SortOrder; import de.danoeh.antennapod.model.feed.SortOrder;
import de.danoeh.antennapod.core.util.download.AutoUpdateManager;
import de.danoeh.antennapod.menuhandler.FeedItemMenuHandler;
import de.danoeh.antennapod.view.EmptyViewHandler; import de.danoeh.antennapod.view.EmptyViewHandler;
import de.danoeh.antennapod.view.EpisodeItemListRecyclerView; import de.danoeh.antennapod.view.EpisodeItemListRecyclerView;
import de.danoeh.antennapod.view.viewholder.EpisodeItemViewHolder; import de.danoeh.antennapod.view.viewholder.EpisodeItemViewHolder;
@ -81,7 +78,6 @@ public class QueueFragment extends Fragment implements Toolbar.OnMenuItemClickLi
private EpisodeItemListRecyclerView recyclerView; private EpisodeItemListRecyclerView recyclerView;
private QueueRecyclerAdapter recyclerAdapter; private QueueRecyclerAdapter recyclerAdapter;
private EmptyViewHandler emptyView; private EmptyViewHandler emptyView;
private ProgressBar progLoading;
private Toolbar toolbar; private Toolbar toolbar;
private boolean displayUpArrow; private boolean displayUpArrow;
@ -89,6 +85,7 @@ public class QueueFragment extends Fragment implements Toolbar.OnMenuItemClickLi
private static final String PREFS = "QueueFragment"; private static final String PREFS = "QueueFragment";
private static final String PREF_SHOW_LOCK_WARNING = "show_lock_warning"; private static final String PREF_SHOW_LOCK_WARNING = "show_lock_warning";
private static final String PREF_PREVIOUS_EPISODE_COUNT = "episodeCount";
private Disposable disposable; private Disposable disposable;
private SwipeActions swipeActions; private SwipeActions swipeActions;
@ -107,7 +104,7 @@ public class QueueFragment extends Fragment implements Toolbar.OnMenuItemClickLi
public void onStart() { public void onStart() {
super.onStart(); super.onStart();
if (queue != null) { if (queue != null) {
onFragmentLoaded(true); recyclerView.restoreScrollPosition(QueueFragment.TAG);
} }
loadItems(true); loadItems(true);
EventBus.getDefault().register(this); EventBus.getDefault().register(this);
@ -126,6 +123,7 @@ public class QueueFragment extends Fragment implements Toolbar.OnMenuItemClickLi
if (disposable != null) { if (disposable != null) {
disposable.dispose(); disposable.dispose();
} }
prefs.edit().putInt(PREF_PREVIOUS_EPISODE_COUNT, queue.size()).apply();
} }
@Subscribe(threadMode = ThreadMode.MAIN) @Subscribe(threadMode = ThreadMode.MAIN)
@ -161,7 +159,7 @@ public class QueueFragment extends Fragment implements Toolbar.OnMenuItemClickLi
return; return;
} }
recyclerView.saveScrollPosition(QueueFragment.TAG); recyclerView.saveScrollPosition(QueueFragment.TAG);
onFragmentLoaded(false); refreshInfoBar();
} }
@Subscribe(threadMode = ThreadMode.MAIN) @Subscribe(threadMode = ThreadMode.MAIN)
@ -456,6 +454,17 @@ public class QueueFragment extends Fragment implements Toolbar.OnMenuItemClickLi
recyclerView.setRecycledViewPool(((MainActivity) getActivity()).getRecycledViewPool()); recyclerView.setRecycledViewPool(((MainActivity) getActivity()).getRecycledViewPool());
registerForContextMenu(recyclerView); registerForContextMenu(recyclerView);
recyclerAdapter = new QueueRecyclerAdapter((MainActivity) getActivity(), swipeActions) {
@Override
public void onCreateContextMenu(ContextMenu menu, View v, ContextMenu.ContextMenuInfo menuInfo) {
super.onCreateContextMenu(menu, v, menuInfo);
MenuItemUtils.setOnClickListeners(menu, QueueFragment.this::onContextItemSelected);
}
};
recyclerAdapter.setOnSelectModeListener(this);
recyclerAdapter.setDummyViews(Math.max(1, prefs.getInt(PREF_PREVIOUS_EPISODE_COUNT, 5)));
recyclerView.setAdapter(recyclerAdapter);
SwipeRefreshLayout swipeRefreshLayout = root.findViewById(R.id.swipeRefresh); SwipeRefreshLayout swipeRefreshLayout = root.findViewById(R.id.swipeRefresh);
swipeRefreshLayout.setDistanceToTriggerSync(getResources().getInteger(R.integer.swipe_refresh_distance)); swipeRefreshLayout.setDistanceToTriggerSync(getResources().getInteger(R.integer.swipe_refresh_distance));
swipeRefreshLayout.setOnRefreshListener(() -> { swipeRefreshLayout.setOnRefreshListener(() -> {
@ -473,9 +482,7 @@ public class QueueFragment extends Fragment implements Toolbar.OnMenuItemClickLi
emptyView.setIcon(R.drawable.ic_playlist_play); emptyView.setIcon(R.drawable.ic_playlist_play);
emptyView.setTitle(R.string.no_items_header_label); emptyView.setTitle(R.string.no_items_header_label);
emptyView.setMessage(R.string.no_items_label); emptyView.setMessage(R.string.no_items_label);
emptyView.updateAdapter(recyclerAdapter);
progLoading = root.findViewById(R.id.progLoading);
progLoading.setVisibility(View.VISIBLE);
speedDialView = root.findViewById(R.id.fabSD); speedDialView = root.findViewById(R.id.fabSD);
speedDialView.setOverlayLayout(root.findViewById(R.id.fabSDOverlay)); speedDialView.setOverlayLayout(root.findViewById(R.id.fabSDOverlay));
@ -513,38 +520,6 @@ public class QueueFragment extends Fragment implements Toolbar.OnMenuItemClickLi
super.onSaveInstanceState(outState); super.onSaveInstanceState(outState);
} }
private void onFragmentLoaded(final boolean restoreScrollPosition) {
if (queue != null) {
if (recyclerAdapter == null) {
MainActivity activity = (MainActivity) getActivity();
recyclerAdapter = new QueueRecyclerAdapter(activity, swipeActions) {
@Override
public void onCreateContextMenu(ContextMenu menu, View v, ContextMenu.ContextMenuInfo menuInfo) {
super.onCreateContextMenu(menu, v, menuInfo);
MenuItemUtils.setOnClickListeners(menu, QueueFragment.this::onContextItemSelected);
}
};
recyclerAdapter.setOnSelectModeListener(this);
recyclerView.setAdapter(recyclerAdapter);
emptyView.updateAdapter(recyclerAdapter);
}
recyclerAdapter.updateItems(queue);
} else {
recyclerAdapter = null;
emptyView.updateAdapter(null);
}
if (restoreScrollPosition) {
recyclerView.restoreScrollPosition(QueueFragment.TAG);
}
// we need to refresh the options menu because it sometimes
// needs data that may have just been loaded.
refreshToolbarState();
refreshInfoBar();
}
private void refreshInfoBar() { private void refreshInfoBar() {
String info = String.format(Locale.getDefault(), "%d%s", String info = String.format(Locale.getDefault(), "%d%s",
queue.size(), getString(R.string.episodes_suffix)); queue.size(), getString(R.string.episodes_suffix));
@ -574,18 +549,18 @@ public class QueueFragment extends Fragment implements Toolbar.OnMenuItemClickLi
} }
if (queue == null) { if (queue == null) {
emptyView.hide(); emptyView.hide();
progLoading.setVisibility(View.VISIBLE);
} }
disposable = Observable.fromCallable(DBReader::getQueue) disposable = Observable.fromCallable(DBReader::getQueue)
.subscribeOn(Schedulers.io()) .subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread()) .observeOn(AndroidSchedulers.mainThread())
.subscribe(items -> { .subscribe(items -> {
progLoading.setVisibility(View.GONE);
queue = items; queue = items;
onFragmentLoaded(restoreScrollPosition); recyclerAdapter.setDummyViews(0);
if (recyclerAdapter != null) { recyclerAdapter.updateItems(queue);
recyclerAdapter.notifyDataSetChanged(); if (restoreScrollPosition) {
recyclerView.restoreScrollPosition(QueueFragment.TAG);
} }
refreshInfoBar();
}, error -> Log.e(TAG, Log.getStackTraceString(error))); }, error -> Log.e(TAG, Log.getStackTraceString(error)));
} }

View File

@ -3,6 +3,7 @@ package de.danoeh.antennapod.fragment;
import android.content.Intent; import android.content.Intent;
import android.content.SharedPreferences; import android.content.SharedPreferences;
import android.os.Bundle; import android.os.Bundle;
import android.text.TextUtils;
import android.util.DisplayMetrics; import android.util.DisplayMetrics;
import androidx.fragment.app.Fragment; import androidx.fragment.app.Fragment;
@ -14,7 +15,6 @@ import android.widget.AdapterView;
import android.widget.Button; import android.widget.Button;
import android.widget.GridView; import android.widget.GridView;
import android.widget.LinearLayout; import android.widget.LinearLayout;
import android.widget.ProgressBar;
import android.widget.TextView; import android.widget.TextView;
import de.danoeh.antennapod.net.discovery.ItunesTopListLoader; import de.danoeh.antennapod.net.discovery.ItunesTopListLoader;
@ -41,7 +41,6 @@ public class QuickFeedDiscoveryFragment extends Fragment implements AdapterView.
private static final String TAG = "FeedDiscoveryFragment"; private static final String TAG = "FeedDiscoveryFragment";
private static final int NUM_SUGGESTIONS = 12; private static final int NUM_SUGGESTIONS = 12;
private ProgressBar progressBar;
private Disposable disposable; private Disposable disposable;
private FeedDiscoverAdapter adapter; private FeedDiscoverAdapter adapter;
private GridView discoverGridLayout; private GridView discoverGridLayout;
@ -59,7 +58,6 @@ public class QuickFeedDiscoveryFragment extends Fragment implements AdapterView.
((MainActivity) getActivity()).loadChildFragment(new DiscoveryFragment())); ((MainActivity) getActivity()).loadChildFragment(new DiscoveryFragment()));
discoverGridLayout = root.findViewById(R.id.discover_grid); discoverGridLayout = root.findViewById(R.id.discover_grid);
progressBar = root.findViewById(R.id.discover_progress_bar);
errorView = root.findViewById(R.id.discover_error); errorView = root.findViewById(R.id.discover_error);
errorTextView = root.findViewById(R.id.discover_error_txtV); errorTextView = root.findViewById(R.id.discover_error_txtV);
errorRetry = root.findViewById(R.id.discover_error_retry_btn); errorRetry = root.findViewById(R.id.discover_error_retry_btn);
@ -108,8 +106,6 @@ public class QuickFeedDiscoveryFragment extends Fragment implements AdapterView.
} }
private void loadToplist() { private void loadToplist() {
progressBar.setVisibility(View.VISIBLE);
discoverGridLayout.setVisibility(View.INVISIBLE);
errorView.setVisibility(View.GONE); errorView.setVisibility(View.GONE);
errorRetry.setVisibility(View.INVISIBLE); errorRetry.setVisibility(View.INVISIBLE);
poweredByTextView.setVisibility(View.VISIBLE); poweredByTextView.setVisibility(View.VISIBLE);
@ -121,7 +117,6 @@ public class QuickFeedDiscoveryFragment extends Fragment implements AdapterView.
if (countryCode.equals(ItunesTopListLoader.DISCOVER_HIDE_FAKE_COUNTRY_CODE)) { if (countryCode.equals(ItunesTopListLoader.DISCOVER_HIDE_FAKE_COUNTRY_CODE)) {
errorTextView.setText(R.string.discover_is_hidden); errorTextView.setText(R.string.discover_is_hidden);
errorView.setVisibility(View.VISIBLE); errorView.setVisibility(View.VISIBLE);
progressBar.setVisibility(View.GONE);
discoverGridLayout.setVisibility(View.GONE); discoverGridLayout.setVisibility(View.GONE);
errorRetry.setVisibility(View.GONE); errorRetry.setVisibility(View.GONE);
poweredByTextView.setVisibility(View.GONE); poweredByTextView.setVisibility(View.GONE);
@ -132,20 +127,18 @@ public class QuickFeedDiscoveryFragment extends Fragment implements AdapterView.
.subscribe( .subscribe(
podcasts -> { podcasts -> {
errorView.setVisibility(View.GONE); errorView.setVisibility(View.GONE);
progressBar.setVisibility(View.GONE);
discoverGridLayout.setVisibility(View.VISIBLE);
if (podcasts.size() == 0) { if (podcasts.size() == 0) {
errorTextView.setText(getResources().getText(R.string.search_status_no_results)); errorTextView.setText(getResources().getText(R.string.search_status_no_results));
errorView.setVisibility(View.VISIBLE); errorView.setVisibility(View.VISIBLE);
discoverGridLayout.setVisibility(View.INVISIBLE); discoverGridLayout.setVisibility(View.INVISIBLE);
} else { } else {
discoverGridLayout.setVisibility(View.VISIBLE);
adapter.updateData(podcasts); adapter.updateData(podcasts);
} }
}, error -> { }, error -> {
Log.e(TAG, Log.getStackTraceString(error)); Log.e(TAG, Log.getStackTraceString(error));
errorTextView.setText(error.getLocalizedMessage()); errorTextView.setText(error.getLocalizedMessage());
errorView.setVisibility(View.VISIBLE); errorView.setVisibility(View.VISIBLE);
progressBar.setVisibility(View.GONE);
discoverGridLayout.setVisibility(View.INVISIBLE); discoverGridLayout.setVisibility(View.INVISIBLE);
errorRetry.setVisibility(View.VISIBLE); errorRetry.setVisibility(View.VISIBLE);
}); });
@ -154,7 +147,7 @@ public class QuickFeedDiscoveryFragment extends Fragment implements AdapterView.
@Override @Override
public void onItemClick(AdapterView<?> parent, final View view, int position, long id) { public void onItemClick(AdapterView<?> parent, final View view, int position, long id) {
PodcastSearchResult podcast = adapter.getItem(position); PodcastSearchResult podcast = adapter.getItem(position);
if (podcast.feedUrl == null) { if (TextUtils.isEmpty(podcast.feedUrl)) {
return; return;
} }
Intent intent = new Intent(getActivity(), OnlineFeedViewActivity.class); Intent intent = new Intent(getActivity(), OnlineFeedViewActivity.class);

View File

@ -13,7 +13,6 @@ import android.view.LayoutInflater;
import android.view.MenuItem; import android.view.MenuItem;
import android.view.View; import android.view.View;
import android.view.ViewGroup; import android.view.ViewGroup;
import android.widget.ProgressBar;
import android.widget.TextView; import android.widget.TextView;
import androidx.annotation.NonNull; import androidx.annotation.NonNull;
@ -75,6 +74,7 @@ public class SubscriptionFragment extends Fragment
public static final String TAG = "SubscriptionFragment"; public static final String TAG = "SubscriptionFragment";
private static final String PREFS = "SubscriptionFragment"; private static final String PREFS = "SubscriptionFragment";
private static final String PREF_NUM_COLUMNS = "columns"; private static final String PREF_NUM_COLUMNS = "columns";
private static final String PREF_PREVIOUS_EPISODE_COUNT = "episodeCount";
private static final String KEY_UP_ARROW = "up_arrow"; private static final String KEY_UP_ARROW = "up_arrow";
private static final String ARGUMENT_FOLDER = "folder"; private static final String ARGUMENT_FOLDER = "folder";
@ -88,7 +88,6 @@ public class SubscriptionFragment extends Fragment
private RecyclerView subscriptionRecycler; private RecyclerView subscriptionRecycler;
private SubscriptionsRecyclerAdapter subscriptionAdapter; private SubscriptionsRecyclerAdapter subscriptionAdapter;
private FloatingActionButton subscriptionAddButton; private FloatingActionButton subscriptionAddButton;
private ProgressBar progressBar;
private EmptyViewHandler emptyView; private EmptyViewHandler emptyView;
private TextView feedsFilteredMsg; private TextView feedsFilteredMsg;
private Toolbar toolbar; private Toolbar toolbar;
@ -153,8 +152,24 @@ public class SubscriptionFragment extends Fragment
setColumnNumber(prefs.getInt(PREF_NUM_COLUMNS, getDefaultNumOfColumns())); setColumnNumber(prefs.getInt(PREF_NUM_COLUMNS, getDefaultNumOfColumns()));
subscriptionRecycler.addItemDecoration(new SubscriptionsRecyclerAdapter.GridDividerItemDecorator()); subscriptionRecycler.addItemDecoration(new SubscriptionsRecyclerAdapter.GridDividerItemDecorator());
registerForContextMenu(subscriptionRecycler); registerForContextMenu(subscriptionRecycler);
subscriptionAdapter = new SubscriptionsRecyclerAdapter((MainActivity) getActivity()) {
@Override
public void onCreateContextMenu(ContextMenu menu, View v, ContextMenu.ContextMenuInfo menuInfo) {
super.onCreateContextMenu(menu, v, menuInfo);
MenuItemUtils.setOnClickListeners(menu, SubscriptionFragment.this::onContextItemSelected);
}
};
subscriptionAdapter.setOnSelectModeListener(this);
subscriptionAdapter.setDummyViews(Math.max(1, prefs.getInt(PREF_PREVIOUS_EPISODE_COUNT, 5)));
subscriptionRecycler.setAdapter(subscriptionAdapter);
setupEmptyView();
subscriptionAddButton = root.findViewById(R.id.subscriptions_add); subscriptionAddButton = root.findViewById(R.id.subscriptions_add);
progressBar = root.findViewById(R.id.progLoading); subscriptionAddButton.setOnClickListener(view -> {
if (getActivity() instanceof MainActivity) {
((MainActivity) getActivity()).loadChildFragment(new AddFeedFragment());
}
});
feedsFilteredMsg = root.findViewById(R.id.feeds_filtered_message); feedsFilteredMsg = root.findViewById(R.id.feeds_filtered_message);
feedsFilteredMsg.setOnClickListener((l) -> SubscriptionsFilterDialog.showDialog(requireContext())); feedsFilteredMsg.setOnClickListener((l) -> SubscriptionsFilterDialog.showDialog(requireContext()));
@ -253,26 +268,6 @@ public class SubscriptionFragment extends Fragment
emptyView.attachToRecyclerView(subscriptionRecycler); emptyView.attachToRecyclerView(subscriptionRecycler);
} }
@Override
public void onViewCreated(@NonNull View v, Bundle savedInstanceState) {
super.onViewCreated(v, savedInstanceState);
subscriptionAdapter = new SubscriptionsRecyclerAdapter((MainActivity) getActivity()) {
@Override
public void onCreateContextMenu(ContextMenu menu, View v, ContextMenu.ContextMenuInfo menuInfo) {
super.onCreateContextMenu(menu, v, menuInfo);
MenuItemUtils.setOnClickListeners(menu, SubscriptionFragment.this::onContextItemSelected);
}
};
subscriptionAdapter.setOnSelectModeListener(this);
subscriptionRecycler.setAdapter(subscriptionAdapter);
setupEmptyView();
subscriptionAddButton.setOnClickListener(view -> {
if (getActivity() instanceof MainActivity) {
((MainActivity) getActivity()).loadChildFragment(new AddFeedFragment());
}
});
}
@Override @Override
public void onStart() { public void onStart() {
super.onStart(); super.onStart();
@ -287,6 +282,7 @@ public class SubscriptionFragment extends Fragment
if (disposable != null) { if (disposable != null) {
disposable.dispose(); disposable.dispose();
} }
prefs.edit().putInt(PREF_PREVIOUS_EPISODE_COUNT, subscriptionAdapter.getItemCount()).apply();
if (subscriptionAdapter != null) { if (subscriptionAdapter != null) {
subscriptionAdapter.endSelectMode(); subscriptionAdapter.endSelectMode();
@ -319,13 +315,12 @@ public class SubscriptionFragment extends Fragment
subscriptionAdapter.endSelectMode(); subscriptionAdapter.endSelectMode();
} }
listItems = result; listItems = result;
subscriptionAdapter.setDummyViews(0);
subscriptionAdapter.setItems(result); subscriptionAdapter.setItems(result);
subscriptionAdapter.notifyDataSetChanged(); subscriptionAdapter.notifyDataSetChanged();
emptyView.updateVisibility(); emptyView.updateVisibility();
progressBar.setVisibility(View.GONE); // Keep hidden to avoid flickering while refreshing
}, error -> { }, error -> {
Log.e(TAG, Log.getStackTraceString(error)); Log.e(TAG, Log.getStackTraceString(error));
progressBar.setVisibility(View.GONE);
}); });
if (UserPreferences.getSubscriptionsFilter().isEnabled()) { if (UserPreferences.getSubscriptionsFilter().isEnabled()) {

View File

@ -220,6 +220,7 @@ public class EpisodeItemViewHolder extends RecyclerView.ViewHolder {
.withPlaceholderView(placeholder) .withPlaceholderView(placeholder)
.withCoverView(cover) .withCoverView(cover)
.load(); .load();
hideSeparatorIfNecessary();
} }
private void updateDuration(PlaybackPositionEvent event) { private void updateDuration(PlaybackPositionEvent event) {

View File

@ -32,8 +32,7 @@
android:id="@+id/swipeRefresh" android:id="@+id/swipeRefresh"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="match_parent" android:layout_height="match_parent"
android:layout_below="@+id/txtvInformation" android:layout_below="@+id/txtvInformation">
android:layout_above="@id/loadingMore">
<de.danoeh.antennapod.view.EpisodeItemListRecyclerView <de.danoeh.antennapod.view.EpisodeItemListRecyclerView
android:id="@android:id/list" android:id="@android:id/list"
@ -49,45 +48,6 @@
</androidx.swiperefreshlayout.widget.SwipeRefreshLayout> </androidx.swiperefreshlayout.widget.SwipeRefreshLayout>
<ProgressBar
android:id="@+id/progLoading"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:gravity="center"
android:indeterminateOnly="true"
android:visibility="gone"
android:layout_centerInParent="true"
tools:background="@android:color/holo_red_light" />
<LinearLayout
android:id="@+id/loadingMore"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true"
android:orientation="horizontal"
android:paddingLeft="16dp"
android:paddingRight="16dp"
android:paddingTop="4dp"
android:paddingBottom="4dp"
android:visibility="gone"
android:gravity="center">
<ProgressBar
android:layout_width="16dp"
android:layout_height="16dp"
android:gravity="center_horizontal"
android:indeterminateOnly="true"
tools:background="@android:color/holo_red_light" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginLeft="4dp"
android:layout_marginStart="4dp"
android:text="@string/loading_more" />
</LinearLayout>
<include <include
layout="@layout/multi_select_speed_dial" /> layout="@layout/multi_select_speed_dial" />

View File

@ -61,14 +61,6 @@
</androidx.swiperefreshlayout.widget.SwipeRefreshLayout> </androidx.swiperefreshlayout.widget.SwipeRefreshLayout>
<ProgressBar
android:id="@+id/progLoading"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:indeterminateOnly="true"
android:visibility="gone" />
<include <include
android:id="@+id/more_content" android:id="@+id/more_content"
android:layout_width="match_parent" android:layout_width="match_parent"

View File

@ -49,14 +49,6 @@
</androidx.swiperefreshlayout.widget.SwipeRefreshLayout> </androidx.swiperefreshlayout.widget.SwipeRefreshLayout>
<ProgressBar
android:id="@+id/progLoading"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerInParent="true"
android:indeterminateOnly="true"
android:visibility="visible" />
<com.google.android.material.floatingactionbutton.FloatingActionButton <com.google.android.material.floatingactionbutton.FloatingActionButton
android:id="@+id/subscriptions_add" android:id="@+id/subscriptions_add"
android:layout_width="56dp" android:layout_width="56dp"

View File

@ -49,14 +49,6 @@
</androidx.swiperefreshlayout.widget.SwipeRefreshLayout> </androidx.swiperefreshlayout.widget.SwipeRefreshLayout>
<ProgressBar
android:id="@+id/progLoading"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerInParent="true"
android:indeterminateOnly="true"
android:visibility="gone" />
<include <include
layout="@layout/multi_select_speed_dial" /> layout="@layout/multi_select_speed_dial" />

View File

@ -1,98 +1,92 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<LinearLayout <LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android" xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent" xmlns:tools="http://schemas.android.com/tools"
android:layout_height="wrap_content" android:layout_width="match_parent"
xmlns:tools="http://schemas.android.com/tools" android:layout_height="wrap_content"
android:orientation="vertical"> android:orientation="vertical">
<LinearLayout <LinearLayout
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:orientation="horizontal"> android:orientation="horizontal">
<TextView <TextView
android:layout_width="0dip" android:layout_width="0dip"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:text="@string/discover" android:text="@string/discover"
android:textSize="18sp" android:textSize="18sp"
android:layout_marginBottom="8dp" android:layout_marginBottom="8dp"
android:layout_weight="1" android:layout_weight="1"
android:textColor="?android:attr/textColorPrimary"/> android:textColor="?android:attr/textColorPrimary" />
<Button <Button
android:layout_width="wrap_content" android:id="@+id/discover_more"
android:layout_height="wrap_content" android:layout_width="wrap_content"
android:minHeight="48dp" android:layout_height="wrap_content"
android:minWidth="0dp" android:minHeight="48dp"
android:text="@string/discover_more" android:minWidth="0dp"
style="@style/Widget.MaterialComponents.Button.TextButton" android:text="@string/discover_more"
android:id="@+id/discover_more"/> style="@style/Widget.MaterialComponents.Button.TextButton" />
</LinearLayout> </LinearLayout>
<RelativeLayout <RelativeLayout
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content"> android:layout_height="wrap_content">
<de.danoeh.antennapod.ui.common.WrappingGridView <de.danoeh.antennapod.ui.common.WrappingGridView
android:id="@+id/discover_grid" android:id="@+id/discover_grid"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:numColumns="4" android:numColumns="4"
app:layout_columnWeight="1" android:scrollbars="none"
app:layout_rowWeight="1" android:layout_marginTop="8dp"
android:scrollbars="none" android:layout_centerInParent="true"
android:layout_marginTop="8dp" android:layout_gravity="center_horizontal"
android:layout_centerInParent="true" app:layout_columnWeight="1"
android:layout_gravity="center_horizontal"/> app:layout_rowWeight="1" />
<ProgressBar
android:id="@+id/discover_progress_bar"
style="?android:attr/progressBarStyle"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:layout_centerInParent="true"
android:layout_marginTop="30dp"/>
<LinearLayout <LinearLayout
android:id="@+id/discover_error" android:id="@+id/discover_error"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_centerInParent="true" android:layout_centerInParent="true"
android:gravity="center" android:gravity="center"
android:orientation="vertical"> android:orientation="vertical">
<TextView <TextView
android:id="@+id/discover_error_txtV" android:id="@+id/discover_error_txtV"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:gravity="center" android:gravity="center"
android:layout_margin="16dp" android:layout_margin="16dp"
android:textSize="@dimen/text_size_small" android:textSize="@dimen/text_size_small"
tools:text="Error message" tools:text="Error message"
tools:background="@android:color/holo_red_light" /> tools:background="@android:color/holo_red_light" />
<Button <Button
android:id="@+id/discover_error_retry_btn" android:id="@+id/discover_error_retry_btn"
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_margin="16dp" android:layout_margin="16dp"
android:text="@string/retry_label" android:text="@string/retry_label"
tools:background="@android:color/holo_red_light" /> tools:background="@android:color/holo_red_light" />
</LinearLayout> </LinearLayout>
</RelativeLayout> </RelativeLayout>
<TextView <TextView
android:id="@+id/discover_powered_by_itunes" android:id="@+id/discover_powered_by_itunes"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:textColor="?android:attr/textColorTertiary" android:textColor="?android:attr/textColorTertiary"
android:text="@string/discover_powered_by_itunes" android:text="@string/discover_powered_by_itunes"
android:textSize="12sp" android:textSize="12sp"
android:layout_gravity="right|end" android:layout_gravity="right|end"
android:paddingHorizontal="4dp" android:paddingHorizontal="4dp"
android:textAlignment="textEnd"/> android:textAlignment="textEnd" />
</LinearLayout> </LinearLayout>

View File

@ -146,7 +146,6 @@
<item quantity="one">%d episode</item> <item quantity="one">%d episode</item>
<item quantity="other">%d episodes</item> <item quantity="other">%d episodes</item>
</plurals> </plurals>
<string name="loading_more">Loading more…</string>
<string name="episode_notification">Episode Notifications</string> <string name="episode_notification">Episode Notifications</string>
<string name="episode_notification_summary">Show a notification when a new episode is released.</string> <string name="episode_notification_summary">Show a notification when a new episode is released.</string>
<plurals name="new_episode_notification_message"> <plurals name="new_episode_notification_message">