Thumbnails used in NewPipe are small (list/grid) mode. This PR facilitates full width thumbnails and dubbed as card mode.
This commit is contained in:
parent
c47d1af5e3
commit
7924bb5b6b
24 changed files with 601 additions and 69 deletions
|
|
@ -26,6 +26,7 @@ import org.schabi.newpipe.extractor.stream.StreamInfoItem;
|
|||
import org.schabi.newpipe.fragments.BaseStateFragment;
|
||||
import org.schabi.newpipe.fragments.OnScrollBelowItemsListener;
|
||||
import org.schabi.newpipe.info_list.InfoListAdapter;
|
||||
import org.schabi.newpipe.info_list.ItemViewMode;
|
||||
import org.schabi.newpipe.info_list.dialog.InfoItemDialog;
|
||||
import org.schabi.newpipe.util.NavigationHelper;
|
||||
import org.schabi.newpipe.util.OnClickGesture;
|
||||
|
|
@ -91,11 +92,7 @@ public abstract class BaseListFragment<I, N> extends BaseStateFragment<I>
|
|||
|
||||
if (updateFlags != 0) {
|
||||
if ((updateFlags & LIST_MODE_UPDATE_FLAG) != 0) {
|
||||
final boolean useGrid = isGridLayout();
|
||||
itemsList.setLayoutManager(useGrid
|
||||
? getGridLayoutManager() : getListLayoutManager());
|
||||
infoListAdapter.setUseGridVariant(useGrid);
|
||||
infoListAdapter.notifyDataSetChanged();
|
||||
refreshItemViewMode();
|
||||
}
|
||||
updateFlags = 0;
|
||||
}
|
||||
|
|
@ -221,15 +218,23 @@ public abstract class BaseListFragment<I, N> extends BaseStateFragment<I>
|
|||
return lm;
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates the item view mode based on user preference.
|
||||
*/
|
||||
private void refreshItemViewMode() {
|
||||
final ItemViewMode itemViewMode = getItemViewMode();
|
||||
itemsList.setLayoutManager((itemViewMode == ItemViewMode.GRID)
|
||||
? getGridLayoutManager() : getListLayoutManager());
|
||||
infoListAdapter.setItemViewMode(itemViewMode);
|
||||
infoListAdapter.notifyDataSetChanged();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void initViews(final View rootView, final Bundle savedInstanceState) {
|
||||
super.initViews(rootView, savedInstanceState);
|
||||
|
||||
final boolean useGrid = isGridLayout();
|
||||
itemsList = rootView.findViewById(R.id.items_list);
|
||||
itemsList.setLayoutManager(useGrid ? getGridLayoutManager() : getListLayoutManager());
|
||||
|
||||
infoListAdapter.setUseGridVariant(useGrid);
|
||||
refreshItemViewMode();
|
||||
|
||||
final Supplier<View> listHeaderSupplier = getListHeaderSupplier();
|
||||
if (listHeaderSupplier != null) {
|
||||
|
|
@ -474,7 +479,11 @@ public abstract class BaseListFragment<I, N> extends BaseStateFragment<I>
|
|||
}
|
||||
}
|
||||
|
||||
protected boolean isGridLayout() {
|
||||
return ThemeHelper.shouldUseGridLayout(activity);
|
||||
/**
|
||||
* Returns preferred item view mode.
|
||||
* @return ItemViewMode
|
||||
*/
|
||||
protected ItemViewMode getItemViewMode() {
|
||||
return ThemeHelper.getItemViewMode(requireContext());
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -17,6 +17,7 @@ import org.schabi.newpipe.extractor.ListExtractor;
|
|||
import org.schabi.newpipe.extractor.comments.CommentsInfo;
|
||||
import org.schabi.newpipe.extractor.comments.CommentsInfoItem;
|
||||
import org.schabi.newpipe.fragments.list.BaseListInfoFragment;
|
||||
import org.schabi.newpipe.info_list.ItemViewMode;
|
||||
import org.schabi.newpipe.ktx.ViewUtils;
|
||||
import org.schabi.newpipe.util.ExtractorHelper;
|
||||
|
||||
|
|
@ -106,7 +107,7 @@ public class CommentsFragment extends BaseListInfoFragment<CommentsInfoItem, Com
|
|||
@NonNull final MenuInflater inflater) { }
|
||||
|
||||
@Override
|
||||
protected boolean isGridLayout() {
|
||||
return false;
|
||||
protected ItemViewMode getItemViewMode() {
|
||||
return ItemViewMode.LIST;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -132,6 +132,8 @@ public class PlaylistFragment extends BaseListInfoFragment<StreamInfoItem, Playl
|
|||
protected void initViews(final View rootView, final Bundle savedInstanceState) {
|
||||
super.initViews(rootView, savedInstanceState);
|
||||
|
||||
// Is mini variant still relevant?
|
||||
// Only the remote playlist screen uses it now
|
||||
infoListAdapter.setUseMiniVariant(true);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -19,6 +19,7 @@ import org.schabi.newpipe.extractor.InfoItem;
|
|||
import org.schabi.newpipe.extractor.ListExtractor;
|
||||
import org.schabi.newpipe.extractor.stream.StreamInfo;
|
||||
import org.schabi.newpipe.fragments.list.BaseListInfoFragment;
|
||||
import org.schabi.newpipe.info_list.ItemViewMode;
|
||||
import org.schabi.newpipe.ktx.ViewUtils;
|
||||
import org.schabi.newpipe.util.RelatedItemInfo;
|
||||
|
||||
|
|
@ -167,7 +168,12 @@ public class RelatedItemsFragment extends BaseListInfoFragment<InfoItem, Related
|
|||
}
|
||||
|
||||
@Override
|
||||
protected boolean isGridLayout() {
|
||||
return false;
|
||||
protected ItemViewMode getItemViewMode() {
|
||||
ItemViewMode mode = super.getItemViewMode();
|
||||
// Only list mode is supported. Either List or card will be used.
|
||||
if (mode != ItemViewMode.LIST && mode != ItemViewMode.CARD) {
|
||||
mode = ItemViewMode.LIST;
|
||||
}
|
||||
return mode;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -23,9 +23,11 @@ import org.schabi.newpipe.info_list.holder.ChannelMiniInfoItemHolder;
|
|||
import org.schabi.newpipe.info_list.holder.CommentsInfoItemHolder;
|
||||
import org.schabi.newpipe.info_list.holder.CommentsMiniInfoItemHolder;
|
||||
import org.schabi.newpipe.info_list.holder.InfoItemHolder;
|
||||
import org.schabi.newpipe.info_list.holder.PlaylistCardInfoItemHolder;
|
||||
import org.schabi.newpipe.info_list.holder.PlaylistGridInfoItemHolder;
|
||||
import org.schabi.newpipe.info_list.holder.PlaylistInfoItemHolder;
|
||||
import org.schabi.newpipe.info_list.holder.PlaylistMiniInfoItemHolder;
|
||||
import org.schabi.newpipe.info_list.holder.StreamCardInfoItemHolder;
|
||||
import org.schabi.newpipe.info_list.holder.StreamGridInfoItemHolder;
|
||||
import org.schabi.newpipe.info_list.holder.StreamInfoItemHolder;
|
||||
import org.schabi.newpipe.info_list.holder.StreamMiniInfoItemHolder;
|
||||
|
|
@ -67,12 +69,14 @@ public class InfoListAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolde
|
|||
private static final int MINI_STREAM_HOLDER_TYPE = 0x100;
|
||||
private static final int STREAM_HOLDER_TYPE = 0x101;
|
||||
private static final int GRID_STREAM_HOLDER_TYPE = 0x102;
|
||||
private static final int CARD_STREAM_HOLDER_TYPE = 0x103;
|
||||
private static final int MINI_CHANNEL_HOLDER_TYPE = 0x200;
|
||||
private static final int CHANNEL_HOLDER_TYPE = 0x201;
|
||||
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;
|
||||
private static final int GRID_PLAYLIST_HOLDER_TYPE = 0x302;
|
||||
private static final int CARD_PLAYLIST_HOLDER_TYPE = 0x303;
|
||||
private static final int MINI_COMMENT_HOLDER_TYPE = 0x400;
|
||||
private static final int COMMENT_HOLDER_TYPE = 0x401;
|
||||
|
||||
|
|
@ -82,9 +86,10 @@ public class InfoListAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolde
|
|||
private final HistoryRecordManager recordManager;
|
||||
|
||||
private boolean useMiniVariant = false;
|
||||
private boolean useGridVariant = false;
|
||||
private boolean showFooter = false;
|
||||
|
||||
private ItemViewMode itemMode = ItemViewMode.LIST;
|
||||
|
||||
private Supplier<View> headerSupplier = null;
|
||||
|
||||
public InfoListAdapter(final Context context) {
|
||||
|
|
@ -114,8 +119,8 @@ public class InfoListAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolde
|
|||
this.useMiniVariant = useMiniVariant;
|
||||
}
|
||||
|
||||
public void setUseGridVariant(final boolean useGridVariant) {
|
||||
this.useGridVariant = useGridVariant;
|
||||
public void setItemViewMode(final ItemViewMode itemViewMode) {
|
||||
this.itemMode = itemViewMode;
|
||||
}
|
||||
|
||||
public void addInfoItemList(@Nullable final List<? extends InfoItem> data) {
|
||||
|
|
@ -234,14 +239,33 @@ public class InfoListAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolde
|
|||
final InfoItem item = infoItemList.get(position);
|
||||
switch (item.getInfoType()) {
|
||||
case STREAM:
|
||||
return useGridVariant ? GRID_STREAM_HOLDER_TYPE : useMiniVariant
|
||||
? MINI_STREAM_HOLDER_TYPE : STREAM_HOLDER_TYPE;
|
||||
if (itemMode == ItemViewMode.CARD) {
|
||||
return CARD_STREAM_HOLDER_TYPE;
|
||||
} else if (itemMode == ItemViewMode.GRID) {
|
||||
return GRID_STREAM_HOLDER_TYPE;
|
||||
} else if (useMiniVariant) {
|
||||
return MINI_STREAM_HOLDER_TYPE;
|
||||
} else {
|
||||
return STREAM_HOLDER_TYPE;
|
||||
}
|
||||
case CHANNEL:
|
||||
return useGridVariant ? GRID_CHANNEL_HOLDER_TYPE : useMiniVariant
|
||||
? MINI_CHANNEL_HOLDER_TYPE : CHANNEL_HOLDER_TYPE;
|
||||
if (itemMode == ItemViewMode.GRID) {
|
||||
return GRID_CHANNEL_HOLDER_TYPE;
|
||||
} else if (useMiniVariant) {
|
||||
return MINI_CHANNEL_HOLDER_TYPE;
|
||||
} else {
|
||||
return CHANNEL_HOLDER_TYPE;
|
||||
}
|
||||
case PLAYLIST:
|
||||
return useGridVariant ? GRID_PLAYLIST_HOLDER_TYPE : useMiniVariant
|
||||
? MINI_PLAYLIST_HOLDER_TYPE : PLAYLIST_HOLDER_TYPE;
|
||||
if (itemMode == ItemViewMode.CARD) {
|
||||
return CARD_PLAYLIST_HOLDER_TYPE;
|
||||
} else if (itemMode == ItemViewMode.GRID) {
|
||||
return GRID_PLAYLIST_HOLDER_TYPE;
|
||||
} else if (useMiniVariant) {
|
||||
return MINI_PLAYLIST_HOLDER_TYPE;
|
||||
} else {
|
||||
return PLAYLIST_HOLDER_TYPE;
|
||||
}
|
||||
case COMMENT:
|
||||
return useMiniVariant ? MINI_COMMENT_HOLDER_TYPE : COMMENT_HOLDER_TYPE;
|
||||
default:
|
||||
|
|
@ -274,6 +298,8 @@ public class InfoListAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolde
|
|||
return new StreamInfoItemHolder(infoItemBuilder, parent);
|
||||
case GRID_STREAM_HOLDER_TYPE:
|
||||
return new StreamGridInfoItemHolder(infoItemBuilder, parent);
|
||||
case CARD_STREAM_HOLDER_TYPE:
|
||||
return new StreamCardInfoItemHolder(infoItemBuilder, parent);
|
||||
case MINI_CHANNEL_HOLDER_TYPE:
|
||||
return new ChannelMiniInfoItemHolder(infoItemBuilder, parent);
|
||||
case CHANNEL_HOLDER_TYPE:
|
||||
|
|
@ -286,6 +312,8 @@ public class InfoListAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolde
|
|||
return new PlaylistInfoItemHolder(infoItemBuilder, parent);
|
||||
case GRID_PLAYLIST_HOLDER_TYPE:
|
||||
return new PlaylistGridInfoItemHolder(infoItemBuilder, parent);
|
||||
case CARD_PLAYLIST_HOLDER_TYPE:
|
||||
return new PlaylistCardInfoItemHolder(infoItemBuilder, parent);
|
||||
case MINI_COMMENT_HOLDER_TYPE:
|
||||
return new CommentsMiniInfoItemHolder(infoItemBuilder, parent);
|
||||
case COMMENT_HOLDER_TYPE:
|
||||
|
|
|
|||
|
|
@ -0,0 +1,23 @@
|
|||
package org.schabi.newpipe.info_list;
|
||||
|
||||
/**
|
||||
* Item view mode for streams & playlist listing screens.
|
||||
*/
|
||||
public enum ItemViewMode {
|
||||
/**
|
||||
* Default mode.
|
||||
*/
|
||||
AUTO,
|
||||
/**
|
||||
* Full width list item with thumb on the left and two line title & uploader in right.
|
||||
*/
|
||||
LIST,
|
||||
/**
|
||||
* Grid mode places two cards per row.
|
||||
*/
|
||||
GRID,
|
||||
/**
|
||||
* A full width card in phone - portrait.
|
||||
*/
|
||||
CARD
|
||||
}
|
||||
|
|
@ -0,0 +1,17 @@
|
|||
package org.schabi.newpipe.info_list.holder;
|
||||
|
||||
import android.view.ViewGroup;
|
||||
|
||||
import org.schabi.newpipe.R;
|
||||
import org.schabi.newpipe.info_list.InfoItemBuilder;
|
||||
|
||||
/**
|
||||
* Playlist card layout.
|
||||
*/
|
||||
public class PlaylistCardInfoItemHolder extends PlaylistMiniInfoItemHolder {
|
||||
|
||||
public PlaylistCardInfoItemHolder(final InfoItemBuilder infoItemBuilder,
|
||||
final ViewGroup parent) {
|
||||
super(infoItemBuilder, R.layout.list_playlist_card_item, parent);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,16 @@
|
|||
package org.schabi.newpipe.info_list.holder;
|
||||
|
||||
import android.view.ViewGroup;
|
||||
|
||||
import org.schabi.newpipe.R;
|
||||
import org.schabi.newpipe.info_list.InfoItemBuilder;
|
||||
|
||||
/**
|
||||
* Card layout for stream.
|
||||
*/
|
||||
public class StreamCardInfoItemHolder extends StreamInfoItemHolder {
|
||||
|
||||
public StreamCardInfoItemHolder(final InfoItemBuilder infoItemBuilder, final ViewGroup parent) {
|
||||
super(infoItemBuilder, R.layout.list_stream_card_item, parent);
|
||||
}
|
||||
}
|
||||
|
|
@ -22,10 +22,11 @@ import org.schabi.newpipe.R;
|
|||
import org.schabi.newpipe.databinding.PignateFooterBinding;
|
||||
import org.schabi.newpipe.fragments.BaseStateFragment;
|
||||
import org.schabi.newpipe.fragments.list.ListViewContract;
|
||||
import org.schabi.newpipe.info_list.ItemViewMode;
|
||||
|
||||
import static org.schabi.newpipe.ktx.ViewUtils.animate;
|
||||
import static org.schabi.newpipe.ktx.ViewUtils.animateHideRecyclerViewAllowingScrolling;
|
||||
import static org.schabi.newpipe.util.ThemeHelper.shouldUseGridLayout;
|
||||
import static org.schabi.newpipe.util.ThemeHelper.getItemViewMode;
|
||||
|
||||
/**
|
||||
* This fragment is design to be used with persistent data such as
|
||||
|
|
@ -77,16 +78,23 @@ public abstract class BaseLocalListFragment<I, N> extends BaseStateFragment<I>
|
|||
super.onResume();
|
||||
if (updateFlags != 0) {
|
||||
if ((updateFlags & LIST_MODE_UPDATE_FLAG) != 0) {
|
||||
final boolean useGrid = shouldUseGridLayout(requireContext());
|
||||
itemsList.setLayoutManager(
|
||||
useGrid ? getGridLayoutManager() : getListLayoutManager());
|
||||
itemListAdapter.setUseGridVariant(useGrid);
|
||||
itemListAdapter.notifyDataSetChanged();
|
||||
refreshItemViewMode();
|
||||
}
|
||||
updateFlags = 0;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates the item view mode based on user preference.
|
||||
*/
|
||||
private void refreshItemViewMode() {
|
||||
final ItemViewMode itemViewMode = getItemViewMode(requireContext());
|
||||
itemsList.setLayoutManager((itemViewMode == ItemViewMode.GRID)
|
||||
? getGridLayoutManager() : getListLayoutManager());
|
||||
itemListAdapter.setItemViewMode(itemViewMode);
|
||||
itemListAdapter.notifyDataSetChanged();
|
||||
}
|
||||
|
||||
/*//////////////////////////////////////////////////////////////////////////
|
||||
// Lifecycle - View
|
||||
//////////////////////////////////////////////////////////////////////////*/
|
||||
|
|
@ -120,11 +128,9 @@ public abstract class BaseLocalListFragment<I, N> extends BaseStateFragment<I>
|
|||
|
||||
itemListAdapter = new LocalItemListAdapter(activity);
|
||||
|
||||
final boolean useGrid = shouldUseGridLayout(requireContext());
|
||||
itemsList = rootView.findViewById(R.id.items_list);
|
||||
itemsList.setLayoutManager(useGrid ? getGridLayoutManager() : getListLayoutManager());
|
||||
refreshItemViewMode();
|
||||
|
||||
itemListAdapter.setUseGridVariant(useGrid);
|
||||
headerRootBinding = getListHeader();
|
||||
if (headerRootBinding != null) {
|
||||
itemListAdapter.setHeader(headerRootBinding.getRoot());
|
||||
|
|
|
|||
|
|
@ -12,14 +12,19 @@ import androidx.recyclerview.widget.RecyclerView;
|
|||
|
||||
import org.schabi.newpipe.database.LocalItem;
|
||||
import org.schabi.newpipe.database.stream.model.StreamStateEntity;
|
||||
import org.schabi.newpipe.info_list.ItemViewMode;
|
||||
import org.schabi.newpipe.local.history.HistoryRecordManager;
|
||||
import org.schabi.newpipe.local.holder.LocalItemHolder;
|
||||
import org.schabi.newpipe.local.holder.LocalPlaylistCardItemHolder;
|
||||
import org.schabi.newpipe.local.holder.LocalPlaylistGridItemHolder;
|
||||
import org.schabi.newpipe.local.holder.LocalPlaylistItemHolder;
|
||||
import org.schabi.newpipe.local.holder.LocalPlaylistStreamCardItemHolder;
|
||||
import org.schabi.newpipe.local.holder.LocalPlaylistStreamGridItemHolder;
|
||||
import org.schabi.newpipe.local.holder.LocalPlaylistStreamItemHolder;
|
||||
import org.schabi.newpipe.local.holder.LocalStatisticStreamCardItemHolder;
|
||||
import org.schabi.newpipe.local.holder.LocalStatisticStreamGridItemHolder;
|
||||
import org.schabi.newpipe.local.holder.LocalStatisticStreamItemHolder;
|
||||
import org.schabi.newpipe.local.holder.RemotePlaylistCardItemHolder;
|
||||
import org.schabi.newpipe.local.holder.RemotePlaylistGridItemHolder;
|
||||
import org.schabi.newpipe.local.holder.RemotePlaylistItemHolder;
|
||||
import org.schabi.newpipe.util.FallbackViewHolder;
|
||||
|
|
@ -61,11 +66,17 @@ public class LocalItemListAdapter extends RecyclerView.Adapter<RecyclerView.View
|
|||
private static final int STREAM_STATISTICS_HOLDER_TYPE = 0x1000;
|
||||
private static final int STREAM_PLAYLIST_HOLDER_TYPE = 0x1001;
|
||||
private static final int STREAM_STATISTICS_GRID_HOLDER_TYPE = 0x1002;
|
||||
private static final int STREAM_STATISTICS_CARD_HOLDER_TYPE = 0x1003;
|
||||
private static final int STREAM_PLAYLIST_GRID_HOLDER_TYPE = 0x1004;
|
||||
private static final int STREAM_PLAYLIST_CARD_HOLDER_TYPE = 0x1005;
|
||||
|
||||
private static final int LOCAL_PLAYLIST_HOLDER_TYPE = 0x2000;
|
||||
private static final int REMOTE_PLAYLIST_HOLDER_TYPE = 0x2001;
|
||||
private static final int LOCAL_PLAYLIST_GRID_HOLDER_TYPE = 0x2002;
|
||||
private static final int REMOTE_PLAYLIST_GRID_HOLDER_TYPE = 0x2004;
|
||||
private static final int LOCAL_PLAYLIST_GRID_HOLDER_TYPE = 0x2001;
|
||||
private static final int LOCAL_PLAYLIST_CARD_HOLDER_TYPE = 0x2002;
|
||||
|
||||
private static final int REMOTE_PLAYLIST_HOLDER_TYPE = 0x3000;
|
||||
private static final int REMOTE_PLAYLIST_GRID_HOLDER_TYPE = 0x3001;
|
||||
private static final int REMOTE_PLAYLIST_CARD_HOLDER_TYPE = 0x3002;
|
||||
|
||||
private final LocalItemBuilder localItemBuilder;
|
||||
private final ArrayList<LocalItem> localItems;
|
||||
|
|
@ -73,9 +84,9 @@ public class LocalItemListAdapter extends RecyclerView.Adapter<RecyclerView.View
|
|||
private final DateTimeFormatter dateTimeFormatter;
|
||||
|
||||
private boolean showFooter = false;
|
||||
private boolean useGridVariant = false;
|
||||
private View header = null;
|
||||
private View footer = null;
|
||||
private ItemViewMode itemViewMode = ItemViewMode.LIST;
|
||||
|
||||
public LocalItemListAdapter(final Context context) {
|
||||
recordManager = new HistoryRecordManager(context);
|
||||
|
|
@ -165,8 +176,8 @@ public class LocalItemListAdapter extends RecyclerView.Adapter<RecyclerView.View
|
|||
notifyDataSetChanged();
|
||||
}
|
||||
|
||||
public void setUseGridVariant(final boolean useGridVariant) {
|
||||
this.useGridVariant = useGridVariant;
|
||||
public void setItemViewMode(final ItemViewMode itemViewMode) {
|
||||
this.itemViewMode = itemViewMode;
|
||||
}
|
||||
|
||||
public void setHeader(final View header) {
|
||||
|
|
@ -244,21 +255,39 @@ public class LocalItemListAdapter extends RecyclerView.Adapter<RecyclerView.View
|
|||
return FOOTER_TYPE;
|
||||
}
|
||||
final LocalItem item = localItems.get(position);
|
||||
|
||||
switch (item.getLocalItemType()) {
|
||||
case PLAYLIST_LOCAL_ITEM:
|
||||
return useGridVariant
|
||||
? LOCAL_PLAYLIST_GRID_HOLDER_TYPE : LOCAL_PLAYLIST_HOLDER_TYPE;
|
||||
if (itemViewMode == ItemViewMode.CARD) {
|
||||
return LOCAL_PLAYLIST_CARD_HOLDER_TYPE;
|
||||
} else if (itemViewMode == ItemViewMode.GRID) {
|
||||
return LOCAL_PLAYLIST_GRID_HOLDER_TYPE;
|
||||
} else {
|
||||
return LOCAL_PLAYLIST_HOLDER_TYPE;
|
||||
}
|
||||
case PLAYLIST_REMOTE_ITEM:
|
||||
return useGridVariant
|
||||
? REMOTE_PLAYLIST_GRID_HOLDER_TYPE : REMOTE_PLAYLIST_HOLDER_TYPE;
|
||||
|
||||
if (itemViewMode == ItemViewMode.CARD) {
|
||||
return REMOTE_PLAYLIST_CARD_HOLDER_TYPE;
|
||||
} else if (itemViewMode == ItemViewMode.GRID) {
|
||||
return REMOTE_PLAYLIST_GRID_HOLDER_TYPE;
|
||||
} else {
|
||||
return REMOTE_PLAYLIST_HOLDER_TYPE;
|
||||
}
|
||||
case PLAYLIST_STREAM_ITEM:
|
||||
return useGridVariant
|
||||
? STREAM_PLAYLIST_GRID_HOLDER_TYPE : STREAM_PLAYLIST_HOLDER_TYPE;
|
||||
if (itemViewMode == ItemViewMode.CARD) {
|
||||
return STREAM_PLAYLIST_CARD_HOLDER_TYPE;
|
||||
} else if (itemViewMode == ItemViewMode.GRID) {
|
||||
return STREAM_PLAYLIST_GRID_HOLDER_TYPE;
|
||||
} else {
|
||||
return STREAM_PLAYLIST_HOLDER_TYPE;
|
||||
}
|
||||
case STATISTIC_STREAM_ITEM:
|
||||
return useGridVariant
|
||||
? STREAM_STATISTICS_GRID_HOLDER_TYPE : STREAM_STATISTICS_HOLDER_TYPE;
|
||||
if (itemViewMode == ItemViewMode.CARD) {
|
||||
return STREAM_STATISTICS_CARD_HOLDER_TYPE;
|
||||
} else if (itemViewMode == ItemViewMode.GRID) {
|
||||
return STREAM_STATISTICS_GRID_HOLDER_TYPE;
|
||||
} else {
|
||||
return STREAM_STATISTICS_HOLDER_TYPE;
|
||||
}
|
||||
default:
|
||||
Log.e(TAG, "No holder type has been considered for item: ["
|
||||
+ item.getLocalItemType() + "]");
|
||||
|
|
@ -283,18 +312,26 @@ public class LocalItemListAdapter extends RecyclerView.Adapter<RecyclerView.View
|
|||
return new LocalPlaylistItemHolder(localItemBuilder, parent);
|
||||
case LOCAL_PLAYLIST_GRID_HOLDER_TYPE:
|
||||
return new LocalPlaylistGridItemHolder(localItemBuilder, parent);
|
||||
case LOCAL_PLAYLIST_CARD_HOLDER_TYPE:
|
||||
return new LocalPlaylistCardItemHolder(localItemBuilder, parent);
|
||||
case REMOTE_PLAYLIST_HOLDER_TYPE:
|
||||
return new RemotePlaylistItemHolder(localItemBuilder, parent);
|
||||
case REMOTE_PLAYLIST_GRID_HOLDER_TYPE:
|
||||
return new RemotePlaylistGridItemHolder(localItemBuilder, parent);
|
||||
case REMOTE_PLAYLIST_CARD_HOLDER_TYPE:
|
||||
return new RemotePlaylistCardItemHolder(localItemBuilder, parent);
|
||||
case STREAM_PLAYLIST_HOLDER_TYPE:
|
||||
return new LocalPlaylistStreamItemHolder(localItemBuilder, parent);
|
||||
case STREAM_PLAYLIST_GRID_HOLDER_TYPE:
|
||||
return new LocalPlaylistStreamGridItemHolder(localItemBuilder, parent);
|
||||
case STREAM_PLAYLIST_CARD_HOLDER_TYPE:
|
||||
return new LocalPlaylistStreamCardItemHolder(localItemBuilder, parent);
|
||||
case STREAM_STATISTICS_HOLDER_TYPE:
|
||||
return new LocalStatisticStreamItemHolder(localItemBuilder, parent);
|
||||
case STREAM_STATISTICS_GRID_HOLDER_TYPE:
|
||||
return new LocalStatisticStreamGridItemHolder(localItemBuilder, parent);
|
||||
case STREAM_STATISTICS_CARD_HOLDER_TYPE:
|
||||
return new LocalStatisticStreamCardItemHolder(localItemBuilder, parent);
|
||||
default:
|
||||
Log.e(TAG, "No view type has been considered for holder: [" + type + "]");
|
||||
return new FallbackViewHolder(new View(parent.getContext()));
|
||||
|
|
|
|||
|
|
@ -69,6 +69,7 @@ import org.schabi.newpipe.extractor.exceptions.ContentNotAvailableException
|
|||
import org.schabi.newpipe.extractor.stream.StreamInfoItem
|
||||
import org.schabi.newpipe.extractor.utils.Utils.isNullOrEmpty
|
||||
import org.schabi.newpipe.fragments.BaseStateFragment
|
||||
import org.schabi.newpipe.info_list.ItemViewMode
|
||||
import org.schabi.newpipe.info_list.dialog.InfoItemDialog
|
||||
import org.schabi.newpipe.ktx.animate
|
||||
import org.schabi.newpipe.ktx.animateHideRecyclerViewAllowingScrolling
|
||||
|
|
@ -80,6 +81,7 @@ import org.schabi.newpipe.util.DeviceUtils
|
|||
import org.schabi.newpipe.util.Localization
|
||||
import org.schabi.newpipe.util.NavigationHelper
|
||||
import org.schabi.newpipe.util.ThemeHelper.getGridSpanCountStreams
|
||||
import org.schabi.newpipe.util.ThemeHelper.getItemViewMode
|
||||
import org.schabi.newpipe.util.ThemeHelper.resolveDrawable
|
||||
import org.schabi.newpipe.util.ThemeHelper.shouldUseGridLayout
|
||||
import java.time.OffsetDateTime
|
||||
|
|
@ -416,11 +418,10 @@ class FeedFragment : BaseStateFragment<FeedState>() {
|
|||
|
||||
@SuppressLint("StringFormatMatches")
|
||||
private fun handleLoadedState(loadedState: FeedState.LoadedState) {
|
||||
|
||||
val itemVersion = if (shouldUseGridLayout(context)) {
|
||||
StreamItem.ItemVersion.GRID
|
||||
} else {
|
||||
StreamItem.ItemVersion.NORMAL
|
||||
val itemVersion = when (getItemViewMode(requireContext())) {
|
||||
ItemViewMode.GRID -> StreamItem.ItemVersion.GRID
|
||||
ItemViewMode.CARD -> StreamItem.ItemVersion.CARD
|
||||
else -> StreamItem.ItemVersion.NORMAL
|
||||
}
|
||||
loadedState.items.forEach { it.itemVersion = itemVersion }
|
||||
|
||||
|
|
|
|||
|
|
@ -42,12 +42,13 @@ data class StreamItem(
|
|||
|
||||
override fun getId(): Long = stream.uid
|
||||
|
||||
enum class ItemVersion { NORMAL, MINI, GRID }
|
||||
enum class ItemVersion { NORMAL, MINI, GRID, CARD }
|
||||
|
||||
override fun getLayout(): Int = when (itemVersion) {
|
||||
ItemVersion.NORMAL -> R.layout.list_stream_item
|
||||
ItemVersion.MINI -> R.layout.list_stream_mini_item
|
||||
ItemVersion.GRID -> R.layout.list_stream_grid_item
|
||||
ItemVersion.CARD -> R.layout.list_stream_card_item
|
||||
}
|
||||
|
||||
override fun initializeViewBinding(view: View) = ListStreamItemBinding.bind(view)
|
||||
|
|
|
|||
|
|
@ -0,0 +1,17 @@
|
|||
package org.schabi.newpipe.local.holder;
|
||||
|
||||
import android.view.ViewGroup;
|
||||
|
||||
import org.schabi.newpipe.R;
|
||||
import org.schabi.newpipe.local.LocalItemBuilder;
|
||||
|
||||
/**
|
||||
* Playlist card layout.
|
||||
*/
|
||||
public class LocalPlaylistCardItemHolder extends LocalPlaylistItemHolder {
|
||||
|
||||
public LocalPlaylistCardItemHolder(final LocalItemBuilder infoItemBuilder,
|
||||
final ViewGroup parent) {
|
||||
super(infoItemBuilder, R.layout.list_playlist_card_item, parent);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,17 @@
|
|||
package org.schabi.newpipe.local.holder;
|
||||
|
||||
import android.view.ViewGroup;
|
||||
|
||||
import org.schabi.newpipe.R;
|
||||
import org.schabi.newpipe.local.LocalItemBuilder;
|
||||
|
||||
/**
|
||||
* Local playlist stream UI. This also includes a handle to rearrange the videos.
|
||||
*/
|
||||
public class LocalPlaylistStreamCardItemHolder extends LocalPlaylistStreamItemHolder {
|
||||
|
||||
public LocalPlaylistStreamCardItemHolder(final LocalItemBuilder infoItemBuilder,
|
||||
final ViewGroup parent) {
|
||||
super(infoItemBuilder, R.layout.list_stream_playlist_card_item, parent);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,13 @@
|
|||
package org.schabi.newpipe.local.holder;
|
||||
|
||||
import android.view.ViewGroup;
|
||||
|
||||
import org.schabi.newpipe.R;
|
||||
import org.schabi.newpipe.local.LocalItemBuilder;
|
||||
|
||||
public class LocalStatisticStreamCardItemHolder extends LocalStatisticStreamItemHolder {
|
||||
public LocalStatisticStreamCardItemHolder(final LocalItemBuilder infoItemBuilder,
|
||||
final ViewGroup parent) {
|
||||
super(infoItemBuilder, R.layout.list_stream_card_item, parent);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,17 @@
|
|||
package org.schabi.newpipe.local.holder;
|
||||
|
||||
import android.view.ViewGroup;
|
||||
|
||||
import org.schabi.newpipe.R;
|
||||
import org.schabi.newpipe.local.LocalItemBuilder;
|
||||
|
||||
/**
|
||||
* Playlist card UI for list item.
|
||||
*/
|
||||
public class RemotePlaylistCardItemHolder extends RemotePlaylistItemHolder {
|
||||
|
||||
public RemotePlaylistCardItemHolder(final LocalItemBuilder infoItemBuilder,
|
||||
final ViewGroup parent) {
|
||||
super(infoItemBuilder, R.layout.list_playlist_card_item, parent);
|
||||
}
|
||||
}
|
||||
|
|
@ -41,6 +41,7 @@ import org.schabi.newpipe.R;
|
|||
import org.schabi.newpipe.extractor.NewPipe;
|
||||
import org.schabi.newpipe.extractor.StreamingService;
|
||||
import org.schabi.newpipe.extractor.exceptions.ExtractionException;
|
||||
import org.schabi.newpipe.info_list.ItemViewMode;
|
||||
|
||||
public final class ThemeHelper {
|
||||
private ThemeHelper() {
|
||||
|
|
@ -332,7 +333,6 @@ public final class ThemeHelper {
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Returns whether the grid layout or the list layout should be used. If the user set "auto"
|
||||
* mode in settings, decides based on screen orientation (landscape) and size.
|
||||
|
|
@ -341,19 +341,8 @@ public final class ThemeHelper {
|
|||
* @return true:use grid layout, false:use list layout
|
||||
*/
|
||||
public static boolean shouldUseGridLayout(final Context context) {
|
||||
final String listMode = PreferenceManager.getDefaultSharedPreferences(context)
|
||||
.getString(context.getString(R.string.list_view_mode_key),
|
||||
context.getString(R.string.list_view_mode_value));
|
||||
|
||||
if (listMode.equals(context.getString(R.string.list_view_mode_list_key))) {
|
||||
return false;
|
||||
} else if (listMode.equals(context.getString(R.string.list_view_mode_grid_key))) {
|
||||
return true;
|
||||
} else /* listMode.equals("auto") */ {
|
||||
final Configuration configuration = context.getResources().getConfiguration();
|
||||
return configuration.orientation == Configuration.ORIENTATION_LANDSCAPE
|
||||
&& configuration.isLayoutSizeAtLeast(Configuration.SCREENLAYOUT_SIZE_LARGE);
|
||||
}
|
||||
final ItemViewMode mode = getItemViewMode(context);
|
||||
return mode == ItemViewMode.GRID;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -367,6 +356,36 @@ public final class ThemeHelper {
|
|||
context.getResources().getDimensionPixelSize(R.dimen.channel_item_grid_min_width));
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns item view mode.
|
||||
* @param context to read preference and parse string
|
||||
* @return Returns one of ItemViewMode
|
||||
*/
|
||||
public static ItemViewMode getItemViewMode(final Context context) {
|
||||
final String listMode = PreferenceManager.getDefaultSharedPreferences(context)
|
||||
.getString(context.getString(R.string.list_view_mode_key),
|
||||
context.getString(R.string.list_view_mode_value));
|
||||
final ItemViewMode result;
|
||||
if (listMode.equals(context.getString(R.string.list_view_mode_list_key))) {
|
||||
result = ItemViewMode.LIST;
|
||||
} else if (listMode.equals(context.getString(R.string.list_view_mode_grid_key))) {
|
||||
result = ItemViewMode.GRID;
|
||||
} else if (listMode.equals(context.getString(R.string.list_view_mode_card_key))) {
|
||||
result = ItemViewMode.CARD;
|
||||
} else {
|
||||
// Auto mode - evaluate whether to use Grid based on screen real estate.
|
||||
final Configuration configuration = context.getResources().getConfiguration();
|
||||
final boolean useGrid = configuration.orientation == Configuration.ORIENTATION_LANDSCAPE
|
||||
&& configuration.isLayoutSizeAtLeast(Configuration.SCREENLAYOUT_SIZE_LARGE);
|
||||
if (useGrid) {
|
||||
result = ItemViewMode.GRID;
|
||||
} else {
|
||||
result = ItemViewMode.LIST;
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Calculates the number of grid stream info items that can fit horizontally on the screen. The
|
||||
* width of a grid stream info item is obtained from the thumbnail width plus the right and left
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue