mirror of
https://github.com/TeamNewPipe/NewPipe
synced 2024-12-24 09:00:31 +00:00
-Added play queue dropdown to channel info items.
-Added play queue dropdown to playlist info items. -Added Channel Play Queue. -Renamed External Play Queue to Playlist Play Queue. -Modified Playlist Play Queue to allow loading from initial state.
This commit is contained in:
parent
87febf8679
commit
b8a17580c5
@ -1,6 +1,5 @@
|
|||||||
package org.schabi.newpipe.fragments.list.playlist;
|
package org.schabi.newpipe.fragments.list.playlist;
|
||||||
|
|
||||||
import android.content.Intent;
|
|
||||||
import android.os.Build;
|
import android.os.Build;
|
||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
import android.support.annotation.NonNull;
|
import android.support.annotation.NonNull;
|
||||||
@ -24,10 +23,7 @@ import org.schabi.newpipe.extractor.NewPipe;
|
|||||||
import org.schabi.newpipe.extractor.exceptions.ExtractionException;
|
import org.schabi.newpipe.extractor.exceptions.ExtractionException;
|
||||||
import org.schabi.newpipe.extractor.playlist.PlaylistInfo;
|
import org.schabi.newpipe.extractor.playlist.PlaylistInfo;
|
||||||
import org.schabi.newpipe.fragments.list.BaseListInfoFragment;
|
import org.schabi.newpipe.fragments.list.BaseListInfoFragment;
|
||||||
import org.schabi.newpipe.player.BackgroundPlayer;
|
import org.schabi.newpipe.playlist.PlaylistPlayQueue;
|
||||||
import org.schabi.newpipe.player.MainVideoPlayer;
|
|
||||||
import org.schabi.newpipe.player.PopupVideoPlayer;
|
|
||||||
import org.schabi.newpipe.playlist.ExternalPlayQueue;
|
|
||||||
import org.schabi.newpipe.playlist.PlayQueue;
|
import org.schabi.newpipe.playlist.PlayQueue;
|
||||||
import org.schabi.newpipe.report.UserAction;
|
import org.schabi.newpipe.report.UserAction;
|
||||||
import org.schabi.newpipe.util.ExtractorHelper;
|
import org.schabi.newpipe.util.ExtractorHelper;
|
||||||
@ -185,7 +181,7 @@ public class PlaylistFragment extends BaseListInfoFragment<PlaylistInfo> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private PlayQueue getPlayQueue() {
|
private PlayQueue getPlayQueue() {
|
||||||
return new ExternalPlayQueue(
|
return new PlaylistPlayQueue(
|
||||||
currentInfo.service_id,
|
currentInfo.service_id,
|
||||||
currentInfo.url,
|
currentInfo.url,
|
||||||
currentInfo.next_streams_url,
|
currentInfo.next_streams_url,
|
||||||
|
@ -1,7 +1,11 @@
|
|||||||
package org.schabi.newpipe.info_list.holder;
|
package org.schabi.newpipe.info_list.holder;
|
||||||
|
|
||||||
|
import android.content.Context;
|
||||||
|
import android.view.MenuItem;
|
||||||
import android.view.View;
|
import android.view.View;
|
||||||
import android.view.ViewGroup;
|
import android.view.ViewGroup;
|
||||||
|
import android.widget.ImageButton;
|
||||||
|
import android.widget.PopupMenu;
|
||||||
import android.widget.TextView;
|
import android.widget.TextView;
|
||||||
|
|
||||||
import com.nostra13.universalimageloader.core.DisplayImageOptions;
|
import com.nostra13.universalimageloader.core.DisplayImageOptions;
|
||||||
@ -10,7 +14,9 @@ import org.schabi.newpipe.R;
|
|||||||
import org.schabi.newpipe.extractor.InfoItem;
|
import org.schabi.newpipe.extractor.InfoItem;
|
||||||
import org.schabi.newpipe.extractor.channel.ChannelInfoItem;
|
import org.schabi.newpipe.extractor.channel.ChannelInfoItem;
|
||||||
import org.schabi.newpipe.info_list.InfoItemBuilder;
|
import org.schabi.newpipe.info_list.InfoItemBuilder;
|
||||||
|
import org.schabi.newpipe.playlist.ChannelPlayQueue;
|
||||||
import org.schabi.newpipe.util.Localization;
|
import org.schabi.newpipe.util.Localization;
|
||||||
|
import org.schabi.newpipe.util.NavigationHelper;
|
||||||
|
|
||||||
import de.hdodenhof.circleimageview.CircleImageView;
|
import de.hdodenhof.circleimageview.CircleImageView;
|
||||||
|
|
||||||
@ -18,6 +24,7 @@ public class ChannelMiniInfoItemHolder extends InfoItemHolder {
|
|||||||
public final CircleImageView itemThumbnailView;
|
public final CircleImageView itemThumbnailView;
|
||||||
public final TextView itemTitleView;
|
public final TextView itemTitleView;
|
||||||
public final TextView itemAdditionalDetailView;
|
public final TextView itemAdditionalDetailView;
|
||||||
|
public final ImageButton itemActionDropdown;
|
||||||
|
|
||||||
ChannelMiniInfoItemHolder(InfoItemBuilder infoItemBuilder, int layoutId, ViewGroup parent) {
|
ChannelMiniInfoItemHolder(InfoItemBuilder infoItemBuilder, int layoutId, ViewGroup parent) {
|
||||||
super(infoItemBuilder, layoutId, parent);
|
super(infoItemBuilder, layoutId, parent);
|
||||||
@ -25,6 +32,7 @@ public class ChannelMiniInfoItemHolder extends InfoItemHolder {
|
|||||||
itemThumbnailView = itemView.findViewById(R.id.itemThumbnailView);
|
itemThumbnailView = itemView.findViewById(R.id.itemThumbnailView);
|
||||||
itemTitleView = itemView.findViewById(R.id.itemTitleView);
|
itemTitleView = itemView.findViewById(R.id.itemTitleView);
|
||||||
itemAdditionalDetailView = itemView.findViewById(R.id.itemAdditionalDetails);
|
itemAdditionalDetailView = itemView.findViewById(R.id.itemAdditionalDetails);
|
||||||
|
itemActionDropdown = itemView.findViewById(R.id.itemActionDropdown);
|
||||||
}
|
}
|
||||||
|
|
||||||
public ChannelMiniInfoItemHolder(InfoItemBuilder infoItemBuilder, ViewGroup parent) {
|
public ChannelMiniInfoItemHolder(InfoItemBuilder infoItemBuilder, ViewGroup parent) {
|
||||||
@ -50,6 +58,55 @@ public class ChannelMiniInfoItemHolder extends InfoItemHolder {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
enableActionDropdown(item);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void enableActionDropdown(final ChannelInfoItem item) {
|
||||||
|
itemActionDropdown.setVisibility(View.VISIBLE);
|
||||||
|
itemActionDropdown.setOnClickListener(new View.OnClickListener() {
|
||||||
|
@Override
|
||||||
|
public void onClick(View view) {
|
||||||
|
final PopupMenu actionMenu = getStreamDropdown(itemBuilder.getContext(), itemActionDropdown, item);
|
||||||
|
if (itemBuilder.getOnChannelSelectedListener() != null) {
|
||||||
|
itemBuilder.getOnChannelSelectedListener().dropdownClicked(item, actionMenu);
|
||||||
|
}
|
||||||
|
actionMenu.show();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
private PopupMenu getStreamDropdown(final Context context, final View anchor, final ChannelInfoItem infoItem) {
|
||||||
|
PopupMenu actionMenu = new PopupMenu(context, anchor);
|
||||||
|
|
||||||
|
final MenuItem mainPlay = actionMenu.getMenu().add(R.string.play_all);
|
||||||
|
mainPlay.setOnMenuItemClickListener(new MenuItem.OnMenuItemClickListener() {
|
||||||
|
@Override
|
||||||
|
public boolean onMenuItemClick(MenuItem menuItem) {
|
||||||
|
NavigationHelper.playOnMainPlayer(context, new ChannelPlayQueue(infoItem));
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
final MenuItem popupPlay = actionMenu.getMenu().add(R.string.controls_popup_title);
|
||||||
|
popupPlay.setOnMenuItemClickListener(new MenuItem.OnMenuItemClickListener() {
|
||||||
|
@Override
|
||||||
|
public boolean onMenuItemClick(MenuItem menuItem) {
|
||||||
|
NavigationHelper.playOnPopupPlayer(context, new ChannelPlayQueue(infoItem));
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
final MenuItem backgroundPlay = actionMenu.getMenu().add(R.string.controls_background_title);
|
||||||
|
backgroundPlay.setOnMenuItemClickListener(new MenuItem.OnMenuItemClickListener() {
|
||||||
|
@Override
|
||||||
|
public boolean onMenuItemClick(MenuItem menuItem) {
|
||||||
|
NavigationHelper.playOnBackgroundPlayer(context, new ChannelPlayQueue(infoItem));
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
return actionMenu;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected String getDetailLine(final ChannelInfoItem item) {
|
protected String getDetailLine(final ChannelInfoItem item) {
|
||||||
|
@ -1,8 +1,12 @@
|
|||||||
package org.schabi.newpipe.info_list.holder;
|
package org.schabi.newpipe.info_list.holder;
|
||||||
|
|
||||||
|
import android.content.Context;
|
||||||
|
import android.view.MenuItem;
|
||||||
import android.view.View;
|
import android.view.View;
|
||||||
import android.view.ViewGroup;
|
import android.view.ViewGroup;
|
||||||
|
import android.widget.ImageButton;
|
||||||
import android.widget.ImageView;
|
import android.widget.ImageView;
|
||||||
|
import android.widget.PopupMenu;
|
||||||
import android.widget.TextView;
|
import android.widget.TextView;
|
||||||
|
|
||||||
import com.nostra13.universalimageloader.core.DisplayImageOptions;
|
import com.nostra13.universalimageloader.core.DisplayImageOptions;
|
||||||
@ -11,12 +15,15 @@ import org.schabi.newpipe.R;
|
|||||||
import org.schabi.newpipe.extractor.InfoItem;
|
import org.schabi.newpipe.extractor.InfoItem;
|
||||||
import org.schabi.newpipe.extractor.playlist.PlaylistInfoItem;
|
import org.schabi.newpipe.extractor.playlist.PlaylistInfoItem;
|
||||||
import org.schabi.newpipe.info_list.InfoItemBuilder;
|
import org.schabi.newpipe.info_list.InfoItemBuilder;
|
||||||
|
import org.schabi.newpipe.playlist.PlaylistPlayQueue;
|
||||||
|
import org.schabi.newpipe.util.NavigationHelper;
|
||||||
|
|
||||||
public class PlaylistInfoItemHolder extends InfoItemHolder {
|
public class PlaylistInfoItemHolder extends InfoItemHolder {
|
||||||
public final ImageView itemThumbnailView;
|
public final ImageView itemThumbnailView;
|
||||||
public final TextView itemStreamCountView;
|
public final TextView itemStreamCountView;
|
||||||
public final TextView itemTitleView;
|
public final TextView itemTitleView;
|
||||||
public final TextView itemUploaderView;
|
public final TextView itemUploaderView;
|
||||||
|
public final ImageButton itemActionDropdown;
|
||||||
|
|
||||||
public PlaylistInfoItemHolder(InfoItemBuilder infoItemBuilder, ViewGroup parent) {
|
public PlaylistInfoItemHolder(InfoItemBuilder infoItemBuilder, ViewGroup parent) {
|
||||||
super(infoItemBuilder, R.layout.list_playlist_item, parent);
|
super(infoItemBuilder, R.layout.list_playlist_item, parent);
|
||||||
@ -25,6 +32,7 @@ public class PlaylistInfoItemHolder extends InfoItemHolder {
|
|||||||
itemTitleView = itemView.findViewById(R.id.itemTitleView);
|
itemTitleView = itemView.findViewById(R.id.itemTitleView);
|
||||||
itemStreamCountView = itemView.findViewById(R.id.itemStreamCountView);
|
itemStreamCountView = itemView.findViewById(R.id.itemStreamCountView);
|
||||||
itemUploaderView = itemView.findViewById(R.id.itemUploaderView);
|
itemUploaderView = itemView.findViewById(R.id.itemUploaderView);
|
||||||
|
itemActionDropdown = itemView.findViewById(R.id.itemActionDropdown);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -47,8 +55,56 @@ public class PlaylistInfoItemHolder extends InfoItemHolder {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
enableActionDropdown(item);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void enableActionDropdown(final PlaylistInfoItem item) {
|
||||||
|
itemActionDropdown.setVisibility(View.VISIBLE);
|
||||||
|
itemActionDropdown.setOnClickListener(new View.OnClickListener() {
|
||||||
|
@Override
|
||||||
|
public void onClick(View view) {
|
||||||
|
final PopupMenu actionMenu = getStreamDropdown(itemBuilder.getContext(), itemActionDropdown, item);
|
||||||
|
if (itemBuilder.getOnPlaylistSelectedListener() != null) {
|
||||||
|
itemBuilder.getOnPlaylistSelectedListener().dropdownClicked(item, actionMenu);
|
||||||
|
}
|
||||||
|
actionMenu.show();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
private PopupMenu getStreamDropdown(final Context context, final View anchor, final PlaylistInfoItem infoItem) {
|
||||||
|
PopupMenu actionMenu = new PopupMenu(context, anchor);
|
||||||
|
|
||||||
|
final MenuItem mainPlay = actionMenu.getMenu().add(R.string.play_all);
|
||||||
|
mainPlay.setOnMenuItemClickListener(new MenuItem.OnMenuItemClickListener() {
|
||||||
|
@Override
|
||||||
|
public boolean onMenuItemClick(MenuItem menuItem) {
|
||||||
|
NavigationHelper.playOnMainPlayer(context, new PlaylistPlayQueue(infoItem));
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
final MenuItem popupPlay = actionMenu.getMenu().add(R.string.controls_popup_title);
|
||||||
|
popupPlay.setOnMenuItemClickListener(new MenuItem.OnMenuItemClickListener() {
|
||||||
|
@Override
|
||||||
|
public boolean onMenuItemClick(MenuItem menuItem) {
|
||||||
|
NavigationHelper.playOnPopupPlayer(context, new PlaylistPlayQueue(infoItem));
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
final MenuItem backgroundPlay = actionMenu.getMenu().add(R.string.controls_background_title);
|
||||||
|
backgroundPlay.setOnMenuItemClickListener(new MenuItem.OnMenuItemClickListener() {
|
||||||
|
@Override
|
||||||
|
public boolean onMenuItemClick(MenuItem menuItem) {
|
||||||
|
NavigationHelper.playOnBackgroundPlayer(context, new PlaylistPlayQueue(infoItem));
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
return actionMenu;
|
||||||
|
}
|
||||||
/**
|
/**
|
||||||
* Display options for playlist thumbnails
|
* Display options for playlist thumbnails
|
||||||
*/
|
*/
|
||||||
|
@ -2,7 +2,6 @@ package org.schabi.newpipe.info_list.holder;
|
|||||||
|
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.support.v4.content.ContextCompat;
|
import android.support.v4.content.ContextCompat;
|
||||||
import android.view.Menu;
|
|
||||||
import android.view.MenuItem;
|
import android.view.MenuItem;
|
||||||
import android.view.View;
|
import android.view.View;
|
||||||
import android.view.ViewGroup;
|
import android.view.ViewGroup;
|
||||||
@ -10,7 +9,6 @@ import android.widget.ImageButton;
|
|||||||
import android.widget.ImageView;
|
import android.widget.ImageView;
|
||||||
import android.widget.PopupMenu;
|
import android.widget.PopupMenu;
|
||||||
import android.widget.TextView;
|
import android.widget.TextView;
|
||||||
import android.widget.Toast;
|
|
||||||
|
|
||||||
import com.nostra13.universalimageloader.core.DisplayImageOptions;
|
import com.nostra13.universalimageloader.core.DisplayImageOptions;
|
||||||
|
|
||||||
@ -19,9 +17,6 @@ import org.schabi.newpipe.extractor.InfoItem;
|
|||||||
import org.schabi.newpipe.extractor.stream.StreamInfoItem;
|
import org.schabi.newpipe.extractor.stream.StreamInfoItem;
|
||||||
import org.schabi.newpipe.extractor.stream.StreamType;
|
import org.schabi.newpipe.extractor.stream.StreamType;
|
||||||
import org.schabi.newpipe.info_list.InfoItemBuilder;
|
import org.schabi.newpipe.info_list.InfoItemBuilder;
|
||||||
import org.schabi.newpipe.player.BackgroundPlayer;
|
|
||||||
import org.schabi.newpipe.player.PopupVideoPlayer;
|
|
||||||
import org.schabi.newpipe.playlist.PlayQueue;
|
|
||||||
import org.schabi.newpipe.playlist.SinglePlayQueue;
|
import org.schabi.newpipe.playlist.SinglePlayQueue;
|
||||||
import org.schabi.newpipe.util.Localization;
|
import org.schabi.newpipe.util.Localization;
|
||||||
import org.schabi.newpipe.util.NavigationHelper;
|
import org.schabi.newpipe.util.NavigationHelper;
|
||||||
@ -91,11 +86,13 @@ public class StreamMiniInfoItemHolder extends InfoItemHolder {
|
|||||||
case AUDIO_LIVE_STREAM:
|
case AUDIO_LIVE_STREAM:
|
||||||
case NONE:
|
case NONE:
|
||||||
default:
|
default:
|
||||||
|
disableActionDropdown();
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void enableActionDropdown(final StreamInfoItem item) {
|
private void enableActionDropdown(final StreamInfoItem item) {
|
||||||
|
itemActionDropdown.setClickable(true);
|
||||||
itemActionDropdown.setVisibility(View.VISIBLE);
|
itemActionDropdown.setVisibility(View.VISIBLE);
|
||||||
itemActionDropdown.setOnClickListener(new View.OnClickListener() {
|
itemActionDropdown.setOnClickListener(new View.OnClickListener() {
|
||||||
@Override
|
@Override
|
||||||
@ -109,10 +106,34 @@ public class StreamMiniInfoItemHolder extends InfoItemHolder {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void disableActionDropdown() {
|
||||||
|
itemActionDropdown.setVisibility(View.GONE);
|
||||||
|
itemActionDropdown.setClickable(false);
|
||||||
|
itemActionDropdown.setOnClickListener(null);
|
||||||
|
}
|
||||||
|
|
||||||
private PopupMenu getStreamDropdown(final Context context, final View anchor, final StreamInfoItem infoItem) {
|
private PopupMenu getStreamDropdown(final Context context, final View anchor, final StreamInfoItem infoItem) {
|
||||||
PopupMenu actionMenu = new PopupMenu(context, anchor);
|
PopupMenu actionMenu = new PopupMenu(context, anchor);
|
||||||
|
|
||||||
final MenuItem mainPlay = actionMenu.getMenu().add(R.string.play_btn_text);
|
final MenuItem backgroundEnqueue = actionMenu.getMenu().add(R.string.enqueue_on_background);
|
||||||
|
backgroundEnqueue.setOnMenuItemClickListener(new MenuItem.OnMenuItemClickListener() {
|
||||||
|
@Override
|
||||||
|
public boolean onMenuItemClick(MenuItem menuItem) {
|
||||||
|
NavigationHelper.enqueueOnBackgroundPlayer(context, new SinglePlayQueue(infoItem));
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
final MenuItem popupEnqueue = actionMenu.getMenu().add(R.string.enqueue_on_popup);
|
||||||
|
popupEnqueue.setOnMenuItemClickListener(new MenuItem.OnMenuItemClickListener() {
|
||||||
|
@Override
|
||||||
|
public boolean onMenuItemClick(MenuItem menuItem) {
|
||||||
|
NavigationHelper.enqueueOnPopupPlayer(context, new SinglePlayQueue(infoItem));
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
final MenuItem mainPlay = actionMenu.getMenu().add(R.string.play_all);
|
||||||
mainPlay.setOnMenuItemClickListener(new MenuItem.OnMenuItemClickListener() {
|
mainPlay.setOnMenuItemClickListener(new MenuItem.OnMenuItemClickListener() {
|
||||||
@Override
|
@Override
|
||||||
public boolean onMenuItemClick(MenuItem menuItem) {
|
public boolean onMenuItemClick(MenuItem menuItem) {
|
||||||
@ -139,24 +160,6 @@ public class StreamMiniInfoItemHolder extends InfoItemHolder {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
final MenuItem backgroundEnqueue = actionMenu.getMenu().add(R.string.enqueue_on_background);
|
|
||||||
backgroundEnqueue.setOnMenuItemClickListener(new MenuItem.OnMenuItemClickListener() {
|
|
||||||
@Override
|
|
||||||
public boolean onMenuItemClick(MenuItem menuItem) {
|
|
||||||
NavigationHelper.enqueueOnBackgroundPlayer(context, new SinglePlayQueue(infoItem));
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
final MenuItem popupEnqueue = actionMenu.getMenu().add(R.string.enqueue_on_popup);
|
|
||||||
popupEnqueue.setOnMenuItemClickListener(new MenuItem.OnMenuItemClickListener() {
|
|
||||||
@Override
|
|
||||||
public boolean onMenuItemClick(MenuItem menuItem) {
|
|
||||||
NavigationHelper.enqueueOnPopupPlayer(context, new SinglePlayQueue(infoItem));
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
return actionMenu;
|
return actionMenu;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -157,7 +157,7 @@ public class MediaSourceManager {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private void onPlayQueueChanged(final PlayQueueEvent event) {
|
private void onPlayQueueChanged(final PlayQueueEvent event) {
|
||||||
if (playQueue.isEmpty()) {
|
if (playQueue.isEmpty() && playQueue.isComplete()) {
|
||||||
playbackListener.shutdown();
|
playbackListener.shutdown();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,151 @@
|
|||||||
|
package org.schabi.newpipe.playlist;
|
||||||
|
|
||||||
|
import android.util.Log;
|
||||||
|
|
||||||
|
import org.schabi.newpipe.extractor.InfoItem;
|
||||||
|
import org.schabi.newpipe.extractor.ListExtractor;
|
||||||
|
import org.schabi.newpipe.extractor.channel.ChannelInfo;
|
||||||
|
import org.schabi.newpipe.extractor.channel.ChannelInfoItem;
|
||||||
|
import org.schabi.newpipe.extractor.stream.StreamInfoItem;
|
||||||
|
import org.schabi.newpipe.util.ExtractorHelper;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import io.reactivex.SingleObserver;
|
||||||
|
import io.reactivex.android.schedulers.AndroidSchedulers;
|
||||||
|
import io.reactivex.annotations.NonNull;
|
||||||
|
import io.reactivex.disposables.Disposable;
|
||||||
|
import io.reactivex.schedulers.Schedulers;
|
||||||
|
|
||||||
|
public final class ChannelPlayQueue extends PlayQueue {
|
||||||
|
private final String TAG = "ChannelPlayQueue@" + Integer.toHexString(hashCode());
|
||||||
|
|
||||||
|
private boolean isInitial;
|
||||||
|
private boolean isComplete;
|
||||||
|
|
||||||
|
private int serviceId;
|
||||||
|
private String baseUrl;
|
||||||
|
private String nextUrl;
|
||||||
|
|
||||||
|
private transient Disposable fetchReactor;
|
||||||
|
|
||||||
|
public ChannelPlayQueue(final ChannelInfoItem item) {
|
||||||
|
this(item.service_id, item.url, item.url, Collections.<InfoItem>emptyList(), 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
public ChannelPlayQueue(final int serviceId,
|
||||||
|
final String url,
|
||||||
|
final String nextPageUrl,
|
||||||
|
final List<InfoItem> streams,
|
||||||
|
final int index) {
|
||||||
|
super(index, extractChannelItems(streams));
|
||||||
|
|
||||||
|
this.baseUrl = url;
|
||||||
|
this.nextUrl = nextPageUrl;
|
||||||
|
this.serviceId = serviceId;
|
||||||
|
|
||||||
|
this.isInitial = streams.isEmpty();
|
||||||
|
this.isComplete = !isInitial && (nextPageUrl == null || nextPageUrl.isEmpty());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isComplete() {
|
||||||
|
return isComplete;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void fetch() {
|
||||||
|
if (isInitial) {
|
||||||
|
ExtractorHelper.getChannelInfo(this.serviceId, this.baseUrl, false)
|
||||||
|
.subscribeOn(Schedulers.io())
|
||||||
|
.observeOn(AndroidSchedulers.mainThread())
|
||||||
|
.subscribe(getChannelInitialObserver());
|
||||||
|
} else {
|
||||||
|
ExtractorHelper.getMoreChannelItems(this.serviceId, this.baseUrl, this.nextUrl)
|
||||||
|
.subscribeOn(Schedulers.io())
|
||||||
|
.observeOn(AndroidSchedulers.mainThread())
|
||||||
|
.subscribe(getChannelNextItemsObserver());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private SingleObserver<ChannelInfo> getChannelInitialObserver() {
|
||||||
|
return new SingleObserver<ChannelInfo>() {
|
||||||
|
@Override
|
||||||
|
public void onSubscribe(@NonNull Disposable d) {
|
||||||
|
if (isComplete || (fetchReactor != null && !fetchReactor.isDisposed())) {
|
||||||
|
d.dispose();
|
||||||
|
} else {
|
||||||
|
fetchReactor = d;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onSuccess(@NonNull ChannelInfo result) {
|
||||||
|
if (!result.has_more_streams) isComplete = true;
|
||||||
|
nextUrl = result.next_streams_url;
|
||||||
|
|
||||||
|
append(extractChannelItems(result.related_streams));
|
||||||
|
|
||||||
|
isInitial = false;
|
||||||
|
fetchReactor.dispose();
|
||||||
|
fetchReactor = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onError(@NonNull Throwable e) {
|
||||||
|
Log.e(TAG, "Error fetching more playlist, marking playlist as complete.", e);
|
||||||
|
isComplete = true;
|
||||||
|
append(); // Notify change
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
private SingleObserver<ListExtractor.NextItemsResult> getChannelNextItemsObserver() {
|
||||||
|
return new SingleObserver<ListExtractor.NextItemsResult>() {
|
||||||
|
@Override
|
||||||
|
public void onSubscribe(@NonNull Disposable d) {
|
||||||
|
if (isComplete || (fetchReactor != null && !fetchReactor.isDisposed())) {
|
||||||
|
d.dispose();
|
||||||
|
} else {
|
||||||
|
fetchReactor = d;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onSuccess(@NonNull ListExtractor.NextItemsResult result) {
|
||||||
|
if (!result.hasMoreStreams()) isComplete = true;
|
||||||
|
nextUrl = result.nextItemsUrl;
|
||||||
|
|
||||||
|
append(extractChannelItems(result.nextItemsList));
|
||||||
|
|
||||||
|
fetchReactor.dispose();
|
||||||
|
fetchReactor = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onError(@NonNull Throwable e) {
|
||||||
|
Log.e(TAG, "Error fetching more playlist, marking playlist as complete.", e);
|
||||||
|
isComplete = true;
|
||||||
|
append(); // Notify change
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void dispose() {
|
||||||
|
super.dispose();
|
||||||
|
if (fetchReactor != null) fetchReactor.dispose();
|
||||||
|
}
|
||||||
|
|
||||||
|
private static List<PlayQueueItem> extractChannelItems(final List<InfoItem> infos) {
|
||||||
|
List<PlayQueueItem> result = new ArrayList<>();
|
||||||
|
for (final InfoItem stream : infos) {
|
||||||
|
if (stream instanceof StreamInfoItem) {
|
||||||
|
result.add(new PlayQueueItem((StreamInfoItem) stream));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
}
|
@ -4,6 +4,8 @@ import android.util.Log;
|
|||||||
|
|
||||||
import org.schabi.newpipe.extractor.InfoItem;
|
import org.schabi.newpipe.extractor.InfoItem;
|
||||||
import org.schabi.newpipe.extractor.ListExtractor;
|
import org.schabi.newpipe.extractor.ListExtractor;
|
||||||
|
import org.schabi.newpipe.extractor.playlist.PlaylistInfo;
|
||||||
|
import org.schabi.newpipe.extractor.playlist.PlaylistInfoItem;
|
||||||
import org.schabi.newpipe.extractor.stream.StreamInfoItem;
|
import org.schabi.newpipe.extractor.stream.StreamInfoItem;
|
||||||
import org.schabi.newpipe.util.ExtractorHelper;
|
import org.schabi.newpipe.util.ExtractorHelper;
|
||||||
|
|
||||||
@ -17,9 +19,10 @@ import io.reactivex.annotations.NonNull;
|
|||||||
import io.reactivex.disposables.Disposable;
|
import io.reactivex.disposables.Disposable;
|
||||||
import io.reactivex.schedulers.Schedulers;
|
import io.reactivex.schedulers.Schedulers;
|
||||||
|
|
||||||
public final class ExternalPlayQueue extends PlayQueue {
|
public final class PlaylistPlayQueue extends PlayQueue {
|
||||||
private final String TAG = "ExternalPlayQueue@" + Integer.toHexString(hashCode());
|
private final String TAG = "PlaylistPlayQueue@" + Integer.toHexString(hashCode());
|
||||||
|
|
||||||
|
private boolean isInitial;
|
||||||
private boolean isComplete;
|
private boolean isComplete;
|
||||||
|
|
||||||
private int serviceId;
|
private int serviceId;
|
||||||
@ -28,7 +31,11 @@ public final class ExternalPlayQueue extends PlayQueue {
|
|||||||
|
|
||||||
private transient Disposable fetchReactor;
|
private transient Disposable fetchReactor;
|
||||||
|
|
||||||
public ExternalPlayQueue(final int serviceId,
|
public PlaylistPlayQueue(final PlaylistInfoItem item) {
|
||||||
|
this(item.service_id, item.url, item.url, Collections.<InfoItem>emptyList(), 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
public PlaylistPlayQueue(final int serviceId,
|
||||||
final String url,
|
final String url,
|
||||||
final String nextPageUrl,
|
final String nextPageUrl,
|
||||||
final List<InfoItem> streams,
|
final List<InfoItem> streams,
|
||||||
@ -39,7 +46,8 @@ public final class ExternalPlayQueue extends PlayQueue {
|
|||||||
this.nextUrl = nextPageUrl;
|
this.nextUrl = nextPageUrl;
|
||||||
this.serviceId = serviceId;
|
this.serviceId = serviceId;
|
||||||
|
|
||||||
this.isComplete = nextPageUrl == null || nextPageUrl.isEmpty();
|
this.isInitial = streams.isEmpty();
|
||||||
|
this.isComplete = !isInitial && (nextPageUrl == null || nextPageUrl.isEmpty());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -49,13 +57,51 @@ public final class ExternalPlayQueue extends PlayQueue {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void fetch() {
|
public void fetch() {
|
||||||
|
if (isInitial) {
|
||||||
|
ExtractorHelper.getPlaylistInfo(this.serviceId, this.baseUrl, false)
|
||||||
|
.subscribeOn(Schedulers.io())
|
||||||
|
.observeOn(AndroidSchedulers.mainThread())
|
||||||
|
.subscribe(getInitialPlaylistObserver());
|
||||||
|
} else {
|
||||||
ExtractorHelper.getMorePlaylistItems(this.serviceId, this.baseUrl, this.nextUrl)
|
ExtractorHelper.getMorePlaylistItems(this.serviceId, this.baseUrl, this.nextUrl)
|
||||||
.subscribeOn(Schedulers.io())
|
.subscribeOn(Schedulers.io())
|
||||||
.observeOn(AndroidSchedulers.mainThread())
|
.observeOn(AndroidSchedulers.mainThread())
|
||||||
.subscribe(getPlaylistObserver());
|
.subscribe(getPlaylistNextItemsObserver());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private SingleObserver<ListExtractor.NextItemsResult> getPlaylistObserver() {
|
private SingleObserver<PlaylistInfo> getInitialPlaylistObserver() {
|
||||||
|
return new SingleObserver<PlaylistInfo>() {
|
||||||
|
@Override
|
||||||
|
public void onSubscribe(@NonNull Disposable d) {
|
||||||
|
if (isComplete || (fetchReactor != null && !fetchReactor.isDisposed())) {
|
||||||
|
d.dispose();
|
||||||
|
} else {
|
||||||
|
fetchReactor = d;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onSuccess(@NonNull PlaylistInfo result) {
|
||||||
|
if (!result.has_more_streams) isComplete = true;
|
||||||
|
nextUrl = result.next_streams_url;
|
||||||
|
|
||||||
|
append(extractPlaylistItems(result.related_streams));
|
||||||
|
|
||||||
|
fetchReactor.dispose();
|
||||||
|
fetchReactor = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onError(@NonNull Throwable e) {
|
||||||
|
Log.e(TAG, "Error fetching more playlist, marking playlist as complete.", e);
|
||||||
|
isComplete = true;
|
||||||
|
append(); // Notify change
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
private SingleObserver<ListExtractor.NextItemsResult> getPlaylistNextItemsObserver() {
|
||||||
return new SingleObserver<ListExtractor.NextItemsResult>() {
|
return new SingleObserver<ListExtractor.NextItemsResult>() {
|
||||||
@Override
|
@Override
|
||||||
public void onSubscribe(@NonNull Disposable d) {
|
public void onSubscribe(@NonNull Disposable d) {
|
@ -7,7 +7,9 @@
|
|||||||
android:layout_height="@dimen/video_item_search_height"
|
android:layout_height="@dimen/video_item_search_height"
|
||||||
android:background="?attr/selectableItemBackground"
|
android:background="?attr/selectableItemBackground"
|
||||||
android:clickable="true"
|
android:clickable="true"
|
||||||
android:padding="@dimen/video_item_search_padding">
|
android:focusable="true"
|
||||||
|
android:paddingTop="@dimen/video_item_search_padding"
|
||||||
|
android:paddingBottom="@dimen/video_item_search_padding">
|
||||||
|
|
||||||
<de.hdodenhof.circleimageview.CircleImageView
|
<de.hdodenhof.circleimageview.CircleImageView
|
||||||
android:id="@+id/itemThumbnailView"
|
android:id="@+id/itemThumbnailView"
|
||||||
@ -16,18 +18,37 @@
|
|||||||
android:layout_alignParentLeft="true"
|
android:layout_alignParentLeft="true"
|
||||||
android:layout_alignParentStart="true"
|
android:layout_alignParentStart="true"
|
||||||
android:layout_alignParentTop="true"
|
android:layout_alignParentTop="true"
|
||||||
|
android:layout_marginLeft="@dimen/video_item_search_image_right_margin"
|
||||||
android:layout_marginRight="@dimen/video_item_search_image_right_margin"
|
android:layout_marginRight="@dimen/video_item_search_image_right_margin"
|
||||||
android:contentDescription="@string/list_thumbnail_view_description"
|
android:contentDescription="@string/list_thumbnail_view_description"
|
||||||
android:src="@drawable/buddy"
|
android:src="@drawable/buddy"
|
||||||
tools:ignore="RtlHardcoded"/>
|
tools:ignore="RtlHardcoded"/>
|
||||||
|
|
||||||
|
<ImageButton
|
||||||
|
android:id="@+id/itemActionDropdown"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="@dimen/video_item_search_thumbnail_image_height"
|
||||||
|
android:layout_alignParentEnd="true"
|
||||||
|
android:layout_alignParentRight="true"
|
||||||
|
android:layout_alignParentTop="true"
|
||||||
|
android:layout_marginLeft="@dimen/video_item_search_image_right_margin"
|
||||||
|
android:layout_marginStart="@dimen/video_item_search_image_right_margin"
|
||||||
|
android:background="?attr/selectableItemBackground"
|
||||||
|
android:src="?attr/more_vertical"
|
||||||
|
android:visibility="gone"
|
||||||
|
tools:ignore="ContentDescription"
|
||||||
|
tools:visibility="visible" />
|
||||||
|
|
||||||
<TextView
|
<TextView
|
||||||
android:id="@+id/itemTitleView"
|
android:id="@+id/itemTitleView"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout_alignParentTop="true"
|
android:layout_alignParentTop="true"
|
||||||
android:layout_marginBottom="@dimen/video_item_search_image_right_margin"
|
android:layout_marginBottom="@dimen/video_item_search_image_right_margin"
|
||||||
|
android:layout_toLeftOf="@id/itemActionDropdown"
|
||||||
|
android:layout_toStartOf="@id/itemActionDropdown"
|
||||||
android:layout_toRightOf="@+id/itemThumbnailView"
|
android:layout_toRightOf="@+id/itemThumbnailView"
|
||||||
|
android:layout_toEndOf="@+id/itemThumbnailView"
|
||||||
android:ellipsize="end"
|
android:ellipsize="end"
|
||||||
android:lines="1"
|
android:lines="1"
|
||||||
android:textAppearance="?android:attr/textAppearanceLarge"
|
android:textAppearance="?android:attr/textAppearanceLarge"
|
||||||
@ -40,7 +61,10 @@
|
|||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout_above="@+id/itemAdditionalDetails"
|
android:layout_above="@+id/itemAdditionalDetails"
|
||||||
android:layout_marginBottom="@dimen/channel_item_description_to_details_margin"
|
android:layout_marginBottom="@dimen/channel_item_description_to_details_margin"
|
||||||
|
android:layout_toLeftOf="@id/itemActionDropdown"
|
||||||
|
android:layout_toStartOf="@id/itemActionDropdown"
|
||||||
android:layout_toRightOf="@+id/itemThumbnailView"
|
android:layout_toRightOf="@+id/itemThumbnailView"
|
||||||
|
android:layout_toEndOf="@+id/itemThumbnailView"
|
||||||
android:ellipsize="end"
|
android:ellipsize="end"
|
||||||
android:lines="2"
|
android:lines="2"
|
||||||
android:textAppearance="?android:attr/textAppearanceSmall"
|
android:textAppearance="?android:attr/textAppearanceSmall"
|
||||||
@ -52,7 +76,10 @@
|
|||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout_alignParentBottom="true"
|
android:layout_alignParentBottom="true"
|
||||||
|
android:layout_toLeftOf="@id/itemActionDropdown"
|
||||||
|
android:layout_toStartOf="@id/itemActionDropdown"
|
||||||
android:layout_toRightOf="@+id/itemThumbnailView"
|
android:layout_toRightOf="@+id/itemThumbnailView"
|
||||||
|
android:layout_toEndOf="@+id/itemThumbnailView"
|
||||||
android:lines="1"
|
android:lines="1"
|
||||||
android:textAppearance="?android:attr/textAppearanceSmall"
|
android:textAppearance="?android:attr/textAppearanceSmall"
|
||||||
android:textSize="@dimen/video_item_search_upload_date_text_size"
|
android:textSize="@dimen/video_item_search_upload_date_text_size"
|
||||||
|
@ -7,23 +7,43 @@
|
|||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:background="?attr/selectableItemBackground"
|
android:background="?attr/selectableItemBackground"
|
||||||
android:clickable="true"
|
android:clickable="true"
|
||||||
android:padding="@dimen/video_item_search_padding">
|
android:focusable="true"
|
||||||
|
android:paddingTop="@dimen/video_item_search_padding"
|
||||||
|
android:paddingBottom="@dimen/video_item_search_padding">
|
||||||
|
|
||||||
<de.hdodenhof.circleimageview.CircleImageView
|
<de.hdodenhof.circleimageview.CircleImageView
|
||||||
android:id="@+id/itemThumbnailView"
|
android:id="@+id/itemThumbnailView"
|
||||||
android:layout_width="48dp"
|
android:layout_width="48dp"
|
||||||
android:layout_height="42dp"
|
android:layout_height="42dp"
|
||||||
android:layout_centerVertical="true"
|
android:layout_centerVertical="true"
|
||||||
android:layout_marginRight="12dp"
|
android:layout_marginLeft="@dimen/video_item_search_image_right_margin"
|
||||||
|
android:layout_marginRight="@dimen/video_item_search_image_right_margin"
|
||||||
android:contentDescription="@string/list_thumbnail_view_description"
|
android:contentDescription="@string/list_thumbnail_view_description"
|
||||||
android:src="@drawable/buddy_channel_item"
|
android:src="@drawable/buddy_channel_item"
|
||||||
tools:ignore="RtlHardcoded"/>
|
tools:ignore="RtlHardcoded"/>
|
||||||
|
|
||||||
|
<ImageButton
|
||||||
|
android:id="@+id/itemActionDropdown"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="42dp"
|
||||||
|
android:layout_centerVertical="true"
|
||||||
|
android:layout_alignParentRight="true"
|
||||||
|
android:layout_alignParentEnd="true"
|
||||||
|
android:layout_marginLeft="@dimen/video_item_search_image_right_margin"
|
||||||
|
android:layout_marginStart="@dimen/video_item_search_image_right_margin"
|
||||||
|
android:background="?attr/selectableItemBackground"
|
||||||
|
android:src="?attr/more_vertical"
|
||||||
|
android:visibility="gone"
|
||||||
|
tools:visibility="visible"
|
||||||
|
tools:ignore="ContentDescription"/>
|
||||||
|
|
||||||
<TextView
|
<TextView
|
||||||
android:id="@+id/itemTitleView"
|
android:id="@+id/itemTitleView"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout_alignParentTop="true"
|
android:layout_alignParentTop="true"
|
||||||
|
android:layout_toLeftOf="@id/itemActionDropdown"
|
||||||
|
android:layout_toStartOf="@id/itemActionDropdown"
|
||||||
android:layout_marginBottom="2dp"
|
android:layout_marginBottom="2dp"
|
||||||
android:layout_marginTop="3dp"
|
android:layout_marginTop="3dp"
|
||||||
android:layout_toRightOf="@+id/itemThumbnailView"
|
android:layout_toRightOf="@+id/itemThumbnailView"
|
||||||
@ -40,6 +60,8 @@
|
|||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout_below="@+id/itemTitleView"
|
android:layout_below="@+id/itemTitleView"
|
||||||
android:layout_toRightOf="@+id/itemThumbnailView"
|
android:layout_toRightOf="@+id/itemThumbnailView"
|
||||||
|
android:layout_toLeftOf="@id/itemActionDropdown"
|
||||||
|
android:layout_toStartOf="@id/itemActionDropdown"
|
||||||
android:lines="1"
|
android:lines="1"
|
||||||
android:textAppearance="?android:attr/textAppearanceSmall"
|
android:textAppearance="?android:attr/textAppearanceSmall"
|
||||||
android:textSize="@dimen/video_item_search_upload_date_text_size"
|
android:textSize="@dimen/video_item_search_upload_date_text_size"
|
||||||
|
@ -7,7 +7,9 @@
|
|||||||
android:layout_height="@dimen/video_item_search_height"
|
android:layout_height="@dimen/video_item_search_height"
|
||||||
android:background="?attr/selectableItemBackground"
|
android:background="?attr/selectableItemBackground"
|
||||||
android:clickable="true"
|
android:clickable="true"
|
||||||
android:padding="@dimen/video_item_search_padding">
|
android:focusable="true"
|
||||||
|
android:paddingTop="@dimen/video_item_search_padding"
|
||||||
|
android:paddingBottom="@dimen/video_item_search_padding">
|
||||||
|
|
||||||
<ImageView
|
<ImageView
|
||||||
android:id="@+id/itemThumbnailView"
|
android:id="@+id/itemThumbnailView"
|
||||||
@ -16,17 +18,35 @@
|
|||||||
android:layout_alignParentLeft="true"
|
android:layout_alignParentLeft="true"
|
||||||
android:layout_alignParentStart="true"
|
android:layout_alignParentStart="true"
|
||||||
android:layout_alignParentTop="true"
|
android:layout_alignParentTop="true"
|
||||||
|
android:layout_marginLeft="@dimen/video_item_search_image_right_margin"
|
||||||
android:layout_marginRight="@dimen/video_item_search_image_right_margin"
|
android:layout_marginRight="@dimen/video_item_search_image_right_margin"
|
||||||
android:contentDescription="@string/list_thumbnail_view_description"
|
android:contentDescription="@string/list_thumbnail_view_description"
|
||||||
android:scaleType="fitEnd"
|
android:scaleType="fitEnd"
|
||||||
android:src="@drawable/dummy_thumbnail_playlist"
|
android:src="@drawable/dummy_thumbnail_playlist"
|
||||||
tools:ignore="RtlHardcoded"/>
|
tools:ignore="RtlHardcoded"/>
|
||||||
|
|
||||||
|
<ImageButton
|
||||||
|
android:id="@+id/itemActionDropdown"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="match_parent"
|
||||||
|
android:layout_centerVertical="true"
|
||||||
|
android:layout_alignParentRight="true"
|
||||||
|
android:layout_alignParentEnd="true"
|
||||||
|
android:layout_marginLeft="@dimen/video_item_search_image_right_margin"
|
||||||
|
android:layout_marginStart="@dimen/video_item_search_image_right_margin"
|
||||||
|
android:background="?attr/selectableItemBackground"
|
||||||
|
android:src="?attr/more_vertical"
|
||||||
|
android:visibility="gone"
|
||||||
|
tools:visibility="visible"
|
||||||
|
tools:ignore="ContentDescription"/>
|
||||||
|
|
||||||
<TextView
|
<TextView
|
||||||
android:id="@+id/itemStreamCountView"
|
android:id="@+id/itemStreamCountView"
|
||||||
android:layout_width="@dimen/playlist_item_thumbnail_stream_count_width"
|
android:layout_width="@dimen/playlist_item_thumbnail_stream_count_width"
|
||||||
android:layout_height="match_parent"
|
android:layout_height="match_parent"
|
||||||
android:layout_alignBottom="@id/itemThumbnailView"
|
android:layout_alignBottom="@id/itemThumbnailView"
|
||||||
|
android:layout_toLeftOf="@id/itemActionDropdown"
|
||||||
|
android:layout_toStartOf="@id/itemActionDropdown"
|
||||||
android:layout_alignRight="@id/itemThumbnailView"
|
android:layout_alignRight="@id/itemThumbnailView"
|
||||||
android:layout_alignTop="@id/itemThumbnailView"
|
android:layout_alignTop="@id/itemThumbnailView"
|
||||||
android:background="@color/playlist_stream_count_background_color"
|
android:background="@color/playlist_stream_count_background_color"
|
||||||
@ -46,6 +66,8 @@
|
|||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout_alignParentTop="true"
|
android:layout_alignParentTop="true"
|
||||||
|
android:layout_toLeftOf="@id/itemActionDropdown"
|
||||||
|
android:layout_toStartOf="@id/itemActionDropdown"
|
||||||
android:layout_toRightOf="@+id/itemThumbnailView"
|
android:layout_toRightOf="@+id/itemThumbnailView"
|
||||||
android:ellipsize="end"
|
android:ellipsize="end"
|
||||||
android:maxLines="2"
|
android:maxLines="2"
|
||||||
@ -59,6 +81,8 @@
|
|||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout_below="@+id/itemTitleView"
|
android:layout_below="@+id/itemTitleView"
|
||||||
|
android:layout_toLeftOf="@id/itemActionDropdown"
|
||||||
|
android:layout_toStartOf="@id/itemActionDropdown"
|
||||||
android:layout_toRightOf="@+id/itemThumbnailView"
|
android:layout_toRightOf="@+id/itemThumbnailView"
|
||||||
android:lines="1"
|
android:lines="1"
|
||||||
android:textAppearance="?android:attr/textAppearanceSmall"
|
android:textAppearance="?android:attr/textAppearanceSmall"
|
||||||
|
@ -18,7 +18,7 @@
|
|||||||
android:layout_alignParentLeft="true"
|
android:layout_alignParentLeft="true"
|
||||||
android:layout_alignParentStart="true"
|
android:layout_alignParentStart="true"
|
||||||
android:layout_alignParentTop="true"
|
android:layout_alignParentTop="true"
|
||||||
android:layout_marginLeft="@dimen/video_item_search_padding"
|
android:layout_marginLeft="@dimen/video_item_search_image_right_margin"
|
||||||
android:layout_marginRight="@dimen/video_item_search_image_right_margin"
|
android:layout_marginRight="@dimen/video_item_search_image_right_margin"
|
||||||
android:contentDescription="@string/list_thumbnail_view_description"
|
android:contentDescription="@string/list_thumbnail_view_description"
|
||||||
android:scaleType="centerCrop"
|
android:scaleType="centerCrop"
|
||||||
|
@ -51,6 +51,8 @@
|
|||||||
android:layout_centerVertical="true"
|
android:layout_centerVertical="true"
|
||||||
android:layout_alignParentRight="true"
|
android:layout_alignParentRight="true"
|
||||||
android:layout_alignParentEnd="true"
|
android:layout_alignParentEnd="true"
|
||||||
|
android:layout_marginLeft="@dimen/video_item_search_image_right_margin"
|
||||||
|
android:layout_marginStart="@dimen/video_item_search_image_right_margin"
|
||||||
android:background="?attr/selectableItemBackground"
|
android:background="?attr/selectableItemBackground"
|
||||||
android:src="?attr/more_vertical"
|
android:src="?attr/more_vertical"
|
||||||
android:visibility="gone"
|
android:visibility="gone"
|
||||||
|
Loading…
Reference in New Issue
Block a user