NewPipe-app-android/app/src/main/java/org/schabi/newpipe/info_list/InfoListAdapter.java

339 lines
13 KiB
Java
Raw Normal View History

2016-08-03 00:54:03 +02:00
package org.schabi.newpipe.info_list;
2016-08-02 00:58:52 +02:00
import android.content.Context;
import android.util.Log;
import android.view.View;
import android.view.ViewGroup;
2019-10-04 14:59:08 +02:00
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.recyclerview.widget.GridLayoutManager;
import androidx.recyclerview.widget.RecyclerView;
2016-08-02 00:58:52 +02:00
import org.schabi.newpipe.database.stream.model.StreamStateEntity;
import org.schabi.newpipe.extractor.InfoItem;
import org.schabi.newpipe.extractor.channel.ChannelInfoItem;
2018-09-03 01:22:59 +02:00
import org.schabi.newpipe.extractor.comments.CommentsInfoItem;
import org.schabi.newpipe.extractor.playlist.PlaylistInfoItem;
import org.schabi.newpipe.extractor.stream.StreamInfoItem;
import org.schabi.newpipe.info_list.holder.ChannelGridInfoItemHolder;
import org.schabi.newpipe.info_list.holder.ChannelInfoItemHolder;
import org.schabi.newpipe.info_list.holder.ChannelMiniInfoItemHolder;
2018-09-23 03:32:19 +02:00
import org.schabi.newpipe.info_list.holder.CommentsInfoItemHolder;
import org.schabi.newpipe.info_list.holder.CommentsMiniInfoItemHolder;
import org.schabi.newpipe.info_list.holder.InfoItemHolder;
2018-08-22 09:14:01 +02:00
import org.schabi.newpipe.info_list.holder.PlaylistGridInfoItemHolder;
import org.schabi.newpipe.info_list.holder.PlaylistInfoItemHolder;
import org.schabi.newpipe.info_list.holder.PlaylistMiniInfoItemHolder;
2018-08-22 09:14:01 +02:00
import org.schabi.newpipe.info_list.holder.StreamGridInfoItemHolder;
import org.schabi.newpipe.info_list.holder.StreamInfoItemHolder;
import org.schabi.newpipe.info_list.holder.StreamMiniInfoItemHolder;
import org.schabi.newpipe.local.history.HistoryRecordManager;
2018-05-06 10:14:24 +02:00
import org.schabi.newpipe.util.FallbackViewHolder;
import org.schabi.newpipe.util.OnClickGesture;
2016-08-02 00:58:52 +02:00
import java.util.ArrayList;
2016-08-02 00:58:52 +02:00
import java.util.List;
/*
2016-09-12 00:33:11 +02:00
* Created by Christian Schabesberger on 01.08.16.
*
* Copyright (C) Christian Schabesberger 2016 <chris.schabesberger@mailbox.org>
* InfoListAdapter.java is part of NewPipe.
*
* NewPipe is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* NewPipe is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with NewPipe. If not, see <http://www.gnu.org/licenses/>.
2016-08-02 00:58:52 +02:00
*/
2016-09-12 00:33:11 +02:00
public class InfoListAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> {
private static final String TAG = InfoListAdapter.class.getSimpleName();
private static final boolean DEBUG = false;
private static final int HEADER_TYPE = 0;
private static final int FOOTER_TYPE = 1;
private static final int MINI_STREAM_HOLDER_TYPE = 0x100;
private static final int STREAM_HOLDER_TYPE = 0x101;
2018-08-22 09:14:01 +02:00
private static final int GRID_STREAM_HOLDER_TYPE = 0x102;
private static final int MINI_CHANNEL_HOLDER_TYPE = 0x200;
private static final int CHANNEL_HOLDER_TYPE = 0x201;
2018-08-22 09:14:01 +02:00
private static final int GRID_CHANNEL_HOLDER_TYPE = 0x202;
private static final int MINI_PLAYLIST_HOLDER_TYPE = 0x300;
private static final int PLAYLIST_HOLDER_TYPE = 0x301;
2018-08-22 09:14:01 +02:00
private static final int GRID_PLAYLIST_HOLDER_TYPE = 0x302;
2018-09-23 03:32:19 +02:00
private static final int MINI_COMMENT_HOLDER_TYPE = 0x400;
private static final int COMMENT_HOLDER_TYPE = 0x401;
2016-08-02 00:58:52 +02:00
private final InfoItemBuilder infoItemBuilder;
private final ArrayList<InfoItem> infoItemList;
private final HistoryRecordManager recordManager;
private boolean useMiniVariant = false;
2018-08-22 09:14:01 +02:00
private boolean useGridVariant = false;
private boolean showFooter = false;
2017-02-27 15:58:09 +01:00
private View header = null;
private View footer = null;
2017-02-27 15:58:09 +01:00
public InfoListAdapter(final Context context) {
this.recordManager = new HistoryRecordManager(context);
infoItemBuilder = new InfoItemBuilder(context);
2017-06-18 15:43:11 +02:00
infoItemList = new ArrayList<>();
2016-08-02 00:58:52 +02:00
}
public void setOnStreamSelectedListener(final OnClickGesture<StreamInfoItem> listener) {
infoItemBuilder.setOnStreamSelectedListener(listener);
}
public void setOnChannelSelectedListener(final OnClickGesture<ChannelInfoItem> listener) {
infoItemBuilder.setOnChannelSelectedListener(listener);
2017-02-15 12:59:36 +01:00
}
public void setOnPlaylistSelectedListener(final OnClickGesture<PlaylistInfoItem> listener) {
infoItemBuilder.setOnPlaylistSelectedListener(listener);
}
public void setOnCommentsSelectedListener(final OnClickGesture<CommentsInfoItem> listener) {
2018-09-03 01:22:59 +02:00
infoItemBuilder.setOnCommentsSelectedListener(listener);
}
public void setUseMiniVariant(final boolean useMiniVariant) {
this.useMiniVariant = useMiniVariant;
2016-08-02 20:59:53 +02:00
}
public void setUseGridVariant(final boolean useGridVariant) {
2018-08-22 09:14:01 +02:00
this.useGridVariant = useGridVariant;
}
public void addInfoItemList(@Nullable final List<? extends InfoItem> data) {
if (data == null) {
return;
2019-04-27 20:23:52 +02:00
}
if (DEBUG) {
Log.d(TAG, "addInfoItemList() before > infoItemList.size() = "
+ infoItemList.size() + ", data.size() = " + data.size());
}
2020-08-16 10:24:58 +02:00
final int offsetStart = sizeConsideringHeaderOffset();
2019-04-27 20:23:52 +02:00
infoItemList.addAll(data);
if (DEBUG) {
Log.d(TAG, "addInfoItemList() after > offsetStart = " + offsetStart + ", "
+ "infoItemList.size() = " + infoItemList.size() + ", "
+ "header = " + header + ", footer = " + footer + ", "
+ "showFooter = " + showFooter);
}
2019-04-27 20:23:52 +02:00
notifyItemRangeInserted(offsetStart, data.size());
2019-04-27 20:23:52 +02:00
if (footer != null && showFooter) {
2020-08-16 10:24:58 +02:00
final int footerNow = sizeConsideringHeaderOffset();
2019-04-27 20:23:52 +02:00
notifyItemMoved(offsetStart, footerNow);
if (DEBUG) {
Log.d(TAG, "addInfoItemList() footer from " + offsetStart
+ " to " + footerNow);
}
}
2016-08-02 18:38:05 +02:00
}
public void clearStreamItemList() {
if (infoItemList.isEmpty()) {
return;
}
2017-02-13 00:55:05 +01:00
infoItemList.clear();
2016-08-02 18:38:05 +02:00
notifyDataSetChanged();
}
public void setHeader(final View header) {
2020-08-16 10:24:58 +02:00
final boolean changed = header != this.header;
2017-02-27 15:58:09 +01:00
this.header = header;
if (changed) {
notifyDataSetChanged();
}
}
public void setFooter(final View view) {
this.footer = view;
}
public void showFooter(final boolean show) {
if (DEBUG) {
Log.d(TAG, "showFooter() called with: show = [" + show + "]");
}
if (show == showFooter) {
return;
}
showFooter = show;
if (show) {
notifyItemInserted(sizeConsideringHeaderOffset());
} else {
notifyItemRemoved(sizeConsideringHeaderOffset());
}
}
private int sizeConsideringHeaderOffset() {
2020-08-16 10:24:58 +02:00
final int i = infoItemList.size() + (header != null ? 1 : 0);
if (DEBUG) {
Log.d(TAG, "sizeConsideringHeaderOffset() called → " + i);
}
return i;
2017-02-27 15:58:09 +01:00
}
public List<InfoItem> getItemsList() {
return infoItemList;
}
2016-08-02 00:58:52 +02:00
@Override
public int getItemCount() {
int count = infoItemList.size();
if (header != null) {
count++;
}
if (footer != null && showFooter) {
count++;
}
if (DEBUG) {
Log.d(TAG, "getItemCount() called with: "
+ "count = " + count + ", infoItemList.size() = " + infoItemList.size() + ", "
+ "header = " + header + ", footer = " + footer + ", "
+ "showFooter = " + showFooter);
}
return count;
2016-08-02 00:58:52 +02:00
}
@SuppressWarnings("FinalParameters")
2016-08-02 00:58:52 +02:00
@Override
2017-02-15 15:21:36 +01:00
public int getItemViewType(int position) {
if (DEBUG) {
Log.d(TAG, "getItemViewType() called with: position = [" + position + "]");
}
if (header != null && position == 0) {
return HEADER_TYPE;
} else if (header != null) {
2017-02-27 15:58:09 +01:00
position--;
}
if (footer != null && position == infoItemList.size() && showFooter) {
return FOOTER_TYPE;
}
final InfoItem item = infoItemList.get(position);
switch (item.getInfoType()) {
2017-02-13 00:55:05 +01:00
case STREAM:
return useGridVariant ? GRID_STREAM_HOLDER_TYPE : useMiniVariant
? MINI_STREAM_HOLDER_TYPE : STREAM_HOLDER_TYPE;
case CHANNEL:
return useGridVariant ? GRID_CHANNEL_HOLDER_TYPE : useMiniVariant
? MINI_CHANNEL_HOLDER_TYPE : CHANNEL_HOLDER_TYPE;
case PLAYLIST:
return useGridVariant ? GRID_PLAYLIST_HOLDER_TYPE : useMiniVariant
? MINI_PLAYLIST_HOLDER_TYPE : PLAYLIST_HOLDER_TYPE;
2018-09-23 03:32:19 +02:00
case COMMENT:
return useMiniVariant ? MINI_COMMENT_HOLDER_TYPE : COMMENT_HOLDER_TYPE;
2017-02-15 15:21:36 +01:00
default:
return -1;
}
}
2019-04-27 20:23:52 +02:00
@NonNull
2017-02-15 15:21:36 +01:00
@Override
public RecyclerView.ViewHolder onCreateViewHolder(@NonNull final ViewGroup parent,
final int type) {
if (DEBUG) {
Log.d(TAG, "onCreateViewHolder() called with: "
+ "parent = [" + parent + "], type = [" + type + "]");
}
switch (type) {
case HEADER_TYPE:
return new HFHolder(header);
case FOOTER_TYPE:
return new HFHolder(footer);
case MINI_STREAM_HOLDER_TYPE:
return new StreamMiniInfoItemHolder(infoItemBuilder, parent);
case STREAM_HOLDER_TYPE:
return new StreamInfoItemHolder(infoItemBuilder, parent);
2018-08-22 09:14:01 +02:00
case GRID_STREAM_HOLDER_TYPE:
return new StreamGridInfoItemHolder(infoItemBuilder, parent);
case MINI_CHANNEL_HOLDER_TYPE:
return new ChannelMiniInfoItemHolder(infoItemBuilder, parent);
case CHANNEL_HOLDER_TYPE:
return new ChannelInfoItemHolder(infoItemBuilder, parent);
2018-08-22 09:14:01 +02:00
case GRID_CHANNEL_HOLDER_TYPE:
return new ChannelGridInfoItemHolder(infoItemBuilder, parent);
case MINI_PLAYLIST_HOLDER_TYPE:
return new PlaylistMiniInfoItemHolder(infoItemBuilder, parent);
case PLAYLIST_HOLDER_TYPE:
return new PlaylistInfoItemHolder(infoItemBuilder, parent);
2018-08-22 09:14:01 +02:00
case GRID_PLAYLIST_HOLDER_TYPE:
return new PlaylistGridInfoItemHolder(infoItemBuilder, parent);
2018-09-23 03:32:19 +02:00
case MINI_COMMENT_HOLDER_TYPE:
return new CommentsMiniInfoItemHolder(infoItemBuilder, parent);
case COMMENT_HOLDER_TYPE:
return new CommentsInfoItemHolder(infoItemBuilder, parent);
2017-02-13 00:55:05 +01:00
default:
2018-05-06 10:14:24 +02:00
return new FallbackViewHolder(new View(parent.getContext()));
2017-02-13 00:55:05 +01:00
}
2016-08-02 00:58:52 +02:00
}
@SuppressWarnings("FinalParameters")
2016-08-02 00:58:52 +02:00
@Override
public void onBindViewHolder(@NonNull final RecyclerView.ViewHolder holder, int position) {
if (DEBUG) {
Log.d(TAG, "onBindViewHolder() called with: "
+ "holder = [" + holder.getClass().getSimpleName() + "], "
+ "position = [" + position + "]");
}
if (holder instanceof InfoItemHolder) {
// If header isn't null, offset the items by -1
if (header != null) {
position--;
}
((InfoItemHolder) holder).updateFromItem(infoItemList.get(position), recordManager);
2017-02-27 15:58:09 +01:00
}
2016-08-02 00:58:52 +02:00
}
2018-08-22 09:14:01 +02:00
2019-04-27 21:27:08 +02:00
@Override
public void onBindViewHolder(@NonNull final RecyclerView.ViewHolder holder,
final int position,
@NonNull final List<Object> payloads) {
if (payloads.isEmpty() || !(holder instanceof InfoItemHolder)) {
2019-04-27 21:27:08 +02:00
onBindViewHolder(holder, position);
return;
}
for (final Object payload : payloads) {
if (payload instanceof StreamStateEntity || payload instanceof Boolean) {
((InfoItemHolder) holder).updateState(infoItemList
.get(header == null ? position : position - 1), recordManager);
}
2019-04-27 21:27:08 +02:00
}
}
2018-08-22 09:14:01 +02:00
public GridLayoutManager.SpanSizeLookup getSpanSizeLookup(final int spanCount) {
return new GridLayoutManager.SpanSizeLookup() {
@Override
public int getSpanSize(final int position) {
2018-08-22 09:14:01 +02:00
final int type = getItemViewType(position);
return type == HEADER_TYPE || type == FOOTER_TYPE ? spanCount : 1;
}
};
}
2020-11-19 00:02:33 +01:00
public static class HFHolder extends RecyclerView.ViewHolder {
HFHolder(final View v) {
super(v);
}
}
2016-08-02 00:58:52 +02:00
}