Merge pull request #12996 from whistlingwoods/reapply-local-list-header-fix-by-j-haldane
This commit is contained in:
commit
4ff958eef5
4 changed files with 37 additions and 29 deletions
|
|
@ -28,6 +28,8 @@ import static org.schabi.newpipe.ktx.ViewUtils.animate;
|
||||||
import static org.schabi.newpipe.ktx.ViewUtils.animateHideRecyclerViewAllowingScrolling;
|
import static org.schabi.newpipe.ktx.ViewUtils.animateHideRecyclerViewAllowingScrolling;
|
||||||
import static org.schabi.newpipe.util.ThemeHelper.getItemViewMode;
|
import static org.schabi.newpipe.util.ThemeHelper.getItemViewMode;
|
||||||
|
|
||||||
|
import java.util.function.Supplier;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This fragment is design to be used with persistent data such as
|
* This fragment is design to be used with persistent data such as
|
||||||
* {@link org.schabi.newpipe.database.LocalItem}, and does not cache the data contained
|
* {@link org.schabi.newpipe.database.LocalItem}, and does not cache the data contained
|
||||||
|
|
@ -100,7 +102,7 @@ public abstract class BaseLocalListFragment<I, N> extends BaseStateFragment<I>
|
||||||
//////////////////////////////////////////////////////////////////////////*/
|
//////////////////////////////////////////////////////////////////////////*/
|
||||||
|
|
||||||
@Nullable
|
@Nullable
|
||||||
protected ViewBinding getListHeader() {
|
protected Supplier<View> getListHeaderSupplier() {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -131,9 +133,9 @@ public abstract class BaseLocalListFragment<I, N> extends BaseStateFragment<I>
|
||||||
itemsList = rootView.findViewById(R.id.items_list);
|
itemsList = rootView.findViewById(R.id.items_list);
|
||||||
refreshItemViewMode();
|
refreshItemViewMode();
|
||||||
|
|
||||||
headerRootBinding = getListHeader();
|
final Supplier<View> listHeaderSupplier = getListHeaderSupplier();
|
||||||
if (headerRootBinding != null) {
|
if (listHeaderSupplier != null) {
|
||||||
itemListAdapter.setHeader(headerRootBinding.getRoot());
|
itemListAdapter.setHeaderSupplier(listHeaderSupplier);
|
||||||
}
|
}
|
||||||
footerRootBinding = getListFooter();
|
footerRootBinding = getListFooter();
|
||||||
itemListAdapter.setFooter(footerRootBinding.getRoot());
|
itemListAdapter.setFooter(footerRootBinding.getRoot());
|
||||||
|
|
|
||||||
|
|
@ -37,6 +37,7 @@ import java.time.format.DateTimeFormatter;
|
||||||
import java.time.format.FormatStyle;
|
import java.time.format.FormatStyle;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import java.util.function.Supplier;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Created by Christian Schabesberger on 01.08.16.
|
* Created by Christian Schabesberger on 01.08.16.
|
||||||
|
|
@ -88,7 +89,7 @@ public class LocalItemListAdapter extends RecyclerView.Adapter<RecyclerView.View
|
||||||
private final DateTimeFormatter dateTimeFormatter;
|
private final DateTimeFormatter dateTimeFormatter;
|
||||||
|
|
||||||
private boolean showFooter = false;
|
private boolean showFooter = false;
|
||||||
private View header = null;
|
private Supplier<View> headerSupplier = null;
|
||||||
private View footer = null;
|
private View footer = null;
|
||||||
private ItemViewMode itemViewMode = ItemViewMode.LIST;
|
private ItemViewMode itemViewMode = ItemViewMode.LIST;
|
||||||
private boolean useItemHandle = false;
|
private boolean useItemHandle = false;
|
||||||
|
|
@ -97,6 +98,7 @@ public class LocalItemListAdapter extends RecyclerView.Adapter<RecyclerView.View
|
||||||
recordManager = new HistoryRecordManager(context);
|
recordManager = new HistoryRecordManager(context);
|
||||||
localItemBuilder = new LocalItemBuilder(context);
|
localItemBuilder = new LocalItemBuilder(context);
|
||||||
localItems = new ArrayList<>();
|
localItems = new ArrayList<>();
|
||||||
|
|
||||||
dateTimeFormatter = DateTimeFormatter.ofLocalizedDate(FormatStyle.SHORT)
|
dateTimeFormatter = DateTimeFormatter.ofLocalizedDate(FormatStyle.SHORT)
|
||||||
.withLocale(Localization.getPreferredLocale(context));
|
.withLocale(Localization.getPreferredLocale(context));
|
||||||
}
|
}
|
||||||
|
|
@ -124,7 +126,7 @@ public class LocalItemListAdapter extends RecyclerView.Adapter<RecyclerView.View
|
||||||
if (DEBUG) {
|
if (DEBUG) {
|
||||||
Log.d(TAG, "addItems() after > offsetStart = " + offsetStart + ", "
|
Log.d(TAG, "addItems() after > offsetStart = " + offsetStart + ", "
|
||||||
+ "localItems.size() = " + localItems.size() + ", "
|
+ "localItems.size() = " + localItems.size() + ", "
|
||||||
+ "header = " + header + ", footer = " + footer + ", "
|
+ "header = " + hasHeader() + ", footer = " + footer + ", "
|
||||||
+ "showFooter = " + showFooter);
|
+ "showFooter = " + showFooter);
|
||||||
}
|
}
|
||||||
notifyItemRangeInserted(offsetStart, data.size());
|
notifyItemRangeInserted(offsetStart, data.size());
|
||||||
|
|
@ -144,7 +146,7 @@ public class LocalItemListAdapter extends RecyclerView.Adapter<RecyclerView.View
|
||||||
final int index = localItems.indexOf(data);
|
final int index = localItems.indexOf(data);
|
||||||
if (index != -1) {
|
if (index != -1) {
|
||||||
localItems.remove(index);
|
localItems.remove(index);
|
||||||
notifyItemRemoved(index + (header != null ? 1 : 0));
|
notifyItemRemoved(index + (hasHeader() ? 1 : 0));
|
||||||
} else {
|
} else {
|
||||||
// this happens when
|
// this happens when
|
||||||
// 1) removeItem is called on infoItemDuplicate as in showStreamItemDialog of
|
// 1) removeItem is called on infoItemDuplicate as in showStreamItemDialog of
|
||||||
|
|
@ -189,9 +191,9 @@ public class LocalItemListAdapter extends RecyclerView.Adapter<RecyclerView.View
|
||||||
this.useItemHandle = useItemHandle;
|
this.useItemHandle = useItemHandle;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setHeader(final View header) {
|
public void setHeaderSupplier(@Nullable final Supplier<View> headerSupplier) {
|
||||||
final boolean changed = header != this.header;
|
final boolean changed = headerSupplier != this.headerSupplier;
|
||||||
this.header = header;
|
this.headerSupplier = headerSupplier;
|
||||||
if (changed) {
|
if (changed) {
|
||||||
notifyDataSetChanged();
|
notifyDataSetChanged();
|
||||||
}
|
}
|
||||||
|
|
@ -201,6 +203,10 @@ public class LocalItemListAdapter extends RecyclerView.Adapter<RecyclerView.View
|
||||||
this.footer = view;
|
this.footer = view;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected boolean hasHeader() {
|
||||||
|
return this.headerSupplier != null;
|
||||||
|
}
|
||||||
|
|
||||||
public void showFooter(final boolean show) {
|
public void showFooter(final boolean show) {
|
||||||
if (DEBUG) {
|
if (DEBUG) {
|
||||||
Log.d(TAG, "showFooter() called with: show = [" + show + "]");
|
Log.d(TAG, "showFooter() called with: show = [" + show + "]");
|
||||||
|
|
@ -218,11 +224,11 @@ public class LocalItemListAdapter extends RecyclerView.Adapter<RecyclerView.View
|
||||||
}
|
}
|
||||||
|
|
||||||
private int adapterOffsetWithoutHeader(final int offset) {
|
private int adapterOffsetWithoutHeader(final int offset) {
|
||||||
return offset - (header != null ? 1 : 0);
|
return offset - (hasHeader() ? 1 : 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
private int sizeConsideringHeader() {
|
private int sizeConsideringHeader() {
|
||||||
return localItems.size() + (header != null ? 1 : 0);
|
return localItems.size() + (hasHeader() ? 1 : 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
public ArrayList<LocalItem> getItemsList() {
|
public ArrayList<LocalItem> getItemsList() {
|
||||||
|
|
@ -232,7 +238,7 @@ public class LocalItemListAdapter extends RecyclerView.Adapter<RecyclerView.View
|
||||||
@Override
|
@Override
|
||||||
public int getItemCount() {
|
public int getItemCount() {
|
||||||
int count = localItems.size();
|
int count = localItems.size();
|
||||||
if (header != null) {
|
if (hasHeader()) {
|
||||||
count++;
|
count++;
|
||||||
}
|
}
|
||||||
if (footer != null && showFooter) {
|
if (footer != null && showFooter) {
|
||||||
|
|
@ -242,7 +248,7 @@ public class LocalItemListAdapter extends RecyclerView.Adapter<RecyclerView.View
|
||||||
if (DEBUG) {
|
if (DEBUG) {
|
||||||
Log.d(TAG, "getItemCount() called, count = " + count + ", "
|
Log.d(TAG, "getItemCount() called, count = " + count + ", "
|
||||||
+ "localItems.size() = " + localItems.size() + ", "
|
+ "localItems.size() = " + localItems.size() + ", "
|
||||||
+ "header = " + header + ", footer = " + footer + ", "
|
+ "header = " + hasHeader() + ", footer = " + footer + ", "
|
||||||
+ "showFooter = " + showFooter);
|
+ "showFooter = " + showFooter);
|
||||||
}
|
}
|
||||||
return count;
|
return count;
|
||||||
|
|
@ -255,9 +261,9 @@ public class LocalItemListAdapter extends RecyclerView.Adapter<RecyclerView.View
|
||||||
Log.d(TAG, "getItemViewType() called with: position = [" + position + "]");
|
Log.d(TAG, "getItemViewType() called with: position = [" + position + "]");
|
||||||
}
|
}
|
||||||
|
|
||||||
if (header != null && position == 0) {
|
if (hasHeader() && position == 0) {
|
||||||
return HEADER_TYPE;
|
return HEADER_TYPE;
|
||||||
} else if (header != null) {
|
} else if (hasHeader()) {
|
||||||
position--;
|
position--;
|
||||||
}
|
}
|
||||||
if (footer != null && position == localItems.size() && showFooter) {
|
if (footer != null && position == localItems.size() && showFooter) {
|
||||||
|
|
@ -318,7 +324,7 @@ public class LocalItemListAdapter extends RecyclerView.Adapter<RecyclerView.View
|
||||||
}
|
}
|
||||||
switch (type) {
|
switch (type) {
|
||||||
case HEADER_TYPE:
|
case HEADER_TYPE:
|
||||||
return new HeaderFooterHolder(header);
|
return new HeaderFooterHolder(headerSupplier.get());
|
||||||
case FOOTER_TYPE:
|
case FOOTER_TYPE:
|
||||||
return new HeaderFooterHolder(footer);
|
return new HeaderFooterHolder(footer);
|
||||||
case LOCAL_PLAYLIST_HOLDER_TYPE:
|
case LOCAL_PLAYLIST_HOLDER_TYPE:
|
||||||
|
|
@ -366,14 +372,14 @@ public class LocalItemListAdapter extends RecyclerView.Adapter<RecyclerView.View
|
||||||
|
|
||||||
if (holder instanceof LocalItemHolder) {
|
if (holder instanceof LocalItemHolder) {
|
||||||
// If header isn't null, offset the items by -1
|
// If header isn't null, offset the items by -1
|
||||||
if (header != null) {
|
if (hasHeader()) {
|
||||||
position--;
|
position--;
|
||||||
}
|
}
|
||||||
|
|
||||||
((LocalItemHolder) holder)
|
((LocalItemHolder) holder)
|
||||||
.updateFromItem(localItems.get(position), recordManager, dateTimeFormatter);
|
.updateFromItem(localItems.get(position), recordManager, dateTimeFormatter);
|
||||||
} else if (holder instanceof HeaderFooterHolder && position == 0 && header != null) {
|
} else if (holder instanceof HeaderFooterHolder && position == 0 && hasHeader()) {
|
||||||
((HeaderFooterHolder) holder).view = header;
|
((HeaderFooterHolder) holder).view = headerSupplier.get();
|
||||||
} else if (holder instanceof HeaderFooterHolder && position == sizeConsideringHeader()
|
} else if (holder instanceof HeaderFooterHolder && position == sizeConsideringHeader()
|
||||||
&& footer != null && showFooter) {
|
&& footer != null && showFooter) {
|
||||||
((HeaderFooterHolder) holder).view = footer;
|
((HeaderFooterHolder) holder).view = footer;
|
||||||
|
|
@ -387,10 +393,10 @@ public class LocalItemListAdapter extends RecyclerView.Adapter<RecyclerView.View
|
||||||
for (final Object payload : payloads) {
|
for (final Object payload : payloads) {
|
||||||
if (payload instanceof StreamStateEntity) {
|
if (payload instanceof StreamStateEntity) {
|
||||||
((LocalItemHolder) holder).updateState(localItems
|
((LocalItemHolder) holder).updateState(localItems
|
||||||
.get(header == null ? position : position - 1), recordManager);
|
.get(hasHeader() ? position - 1 : position), recordManager);
|
||||||
} else if (payload instanceof Boolean) {
|
} else if (payload instanceof Boolean) {
|
||||||
((LocalItemHolder) holder).updateState(localItems
|
((LocalItemHolder) holder).updateState(localItems
|
||||||
.get(header == null ? position : position - 1), recordManager);
|
.get(hasHeader() ? position - 1 : position), recordManager);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
|
|
||||||
|
|
@ -13,7 +13,6 @@ import android.widget.Toast;
|
||||||
|
|
||||||
import androidx.annotation.NonNull;
|
import androidx.annotation.NonNull;
|
||||||
import androidx.annotation.Nullable;
|
import androidx.annotation.Nullable;
|
||||||
import androidx.viewbinding.ViewBinding;
|
|
||||||
|
|
||||||
import com.evernote.android.state.State;
|
import com.evernote.android.state.State;
|
||||||
import com.google.android.material.snackbar.Snackbar;
|
import com.google.android.material.snackbar.Snackbar;
|
||||||
|
|
@ -45,6 +44,7 @@ import java.util.Collections;
|
||||||
import java.util.Comparator;
|
import java.util.Comparator;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Objects;
|
import java.util.Objects;
|
||||||
|
import java.util.function.Supplier;
|
||||||
|
|
||||||
import io.reactivex.rxjava3.android.schedulers.AndroidSchedulers;
|
import io.reactivex.rxjava3.android.schedulers.AndroidSchedulers;
|
||||||
import io.reactivex.rxjava3.disposables.CompositeDisposable;
|
import io.reactivex.rxjava3.disposables.CompositeDisposable;
|
||||||
|
|
@ -126,12 +126,12 @@ public class StatisticsPlaylistFragment
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected ViewBinding getListHeader() {
|
protected Supplier<View> getListHeaderSupplier() {
|
||||||
headerBinding = StatisticPlaylistControlBinding.inflate(activity.getLayoutInflater(),
|
headerBinding = StatisticPlaylistControlBinding.inflate(activity.getLayoutInflater(),
|
||||||
itemsList, false);
|
itemsList, false);
|
||||||
playlistControlBinding = headerBinding.playlistControl;
|
playlistControlBinding = headerBinding.playlistControl;
|
||||||
|
|
||||||
return headerBinding;
|
return headerBinding::getRoot;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
|
||||||
|
|
@ -29,7 +29,6 @@ import androidx.annotation.Nullable;
|
||||||
import androidx.appcompat.app.AlertDialog;
|
import androidx.appcompat.app.AlertDialog;
|
||||||
import androidx.recyclerview.widget.ItemTouchHelper;
|
import androidx.recyclerview.widget.ItemTouchHelper;
|
||||||
import androidx.recyclerview.widget.RecyclerView;
|
import androidx.recyclerview.widget.RecyclerView;
|
||||||
import androidx.viewbinding.ViewBinding;
|
|
||||||
|
|
||||||
import com.evernote.android.state.State;
|
import com.evernote.android.state.State;
|
||||||
import org.reactivestreams.Subscriber;
|
import org.reactivestreams.Subscriber;
|
||||||
|
|
@ -67,6 +66,7 @@ import java.util.ArrayList;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.concurrent.atomic.AtomicBoolean;
|
import java.util.concurrent.atomic.AtomicBoolean;
|
||||||
|
import java.util.function.Supplier;
|
||||||
import java.util.stream.Collectors;
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
import io.reactivex.rxjava3.android.schedulers.AndroidSchedulers;
|
import io.reactivex.rxjava3.android.schedulers.AndroidSchedulers;
|
||||||
|
|
@ -158,14 +158,14 @@ public class LocalPlaylistFragment extends BaseLocalListFragment<List<PlaylistSt
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected ViewBinding getListHeader() {
|
protected Supplier<View> getListHeaderSupplier() {
|
||||||
headerBinding = LocalPlaylistHeaderBinding.inflate(activity.getLayoutInflater(), itemsList,
|
headerBinding = LocalPlaylistHeaderBinding.inflate(activity.getLayoutInflater(), itemsList,
|
||||||
false);
|
false);
|
||||||
playlistControlBinding = headerBinding.playlistControl;
|
playlistControlBinding = headerBinding.playlistControl;
|
||||||
|
|
||||||
headerBinding.playlistTitleView.setSelected(true);
|
headerBinding.playlistTitleView.setSelected(true);
|
||||||
|
|
||||||
return headerBinding;
|
return headerBinding::getRoot;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue