-Added play buttons to channel fragment similar to playlist fragment.
-Fixed abstract info play queue reloading the same initial page. -Fixed OOB on get item for abstract play queue.
This commit is contained in:
parent
b883f313ba
commit
7700cff5e5
6 changed files with 191 additions and 77 deletions
|
@ -3,6 +3,7 @@ package org.schabi.newpipe.fragments.list.channel;
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.content.Intent;
|
import android.content.Intent;
|
||||||
import android.net.Uri;
|
import android.net.Uri;
|
||||||
|
import android.os.Build;
|
||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
import android.support.annotation.NonNull;
|
import android.support.annotation.NonNull;
|
||||||
import android.support.annotation.Nullable;
|
import android.support.annotation.Nullable;
|
||||||
|
@ -10,6 +11,7 @@ import android.support.v4.content.ContextCompat;
|
||||||
import android.support.v7.app.ActionBar;
|
import android.support.v7.app.ActionBar;
|
||||||
import android.text.TextUtils;
|
import android.text.TextUtils;
|
||||||
import android.util.Log;
|
import android.util.Log;
|
||||||
|
import android.view.Gravity;
|
||||||
import android.view.LayoutInflater;
|
import android.view.LayoutInflater;
|
||||||
import android.view.Menu;
|
import android.view.Menu;
|
||||||
import android.view.MenuInflater;
|
import android.view.MenuInflater;
|
||||||
|
@ -19,6 +21,7 @@ import android.view.ViewGroup;
|
||||||
import android.widget.Button;
|
import android.widget.Button;
|
||||||
import android.widget.ImageView;
|
import android.widget.ImageView;
|
||||||
import android.widget.TextView;
|
import android.widget.TextView;
|
||||||
|
import android.widget.Toast;
|
||||||
|
|
||||||
import com.jakewharton.rxbinding2.view.RxView;
|
import com.jakewharton.rxbinding2.view.RxView;
|
||||||
|
|
||||||
|
@ -30,10 +33,14 @@ import org.schabi.newpipe.extractor.channel.ChannelInfo;
|
||||||
import org.schabi.newpipe.extractor.exceptions.ExtractionException;
|
import org.schabi.newpipe.extractor.exceptions.ExtractionException;
|
||||||
import org.schabi.newpipe.fragments.list.BaseListInfoFragment;
|
import org.schabi.newpipe.fragments.list.BaseListInfoFragment;
|
||||||
import org.schabi.newpipe.fragments.subscription.SubscriptionService;
|
import org.schabi.newpipe.fragments.subscription.SubscriptionService;
|
||||||
|
import org.schabi.newpipe.playlist.ChannelPlayQueue;
|
||||||
|
import org.schabi.newpipe.playlist.PlayQueue;
|
||||||
import org.schabi.newpipe.report.UserAction;
|
import org.schabi.newpipe.report.UserAction;
|
||||||
import org.schabi.newpipe.util.AnimationUtils;
|
import org.schabi.newpipe.util.AnimationUtils;
|
||||||
import org.schabi.newpipe.util.ExtractorHelper;
|
import org.schabi.newpipe.util.ExtractorHelper;
|
||||||
import org.schabi.newpipe.util.Localization;
|
import org.schabi.newpipe.util.Localization;
|
||||||
|
import org.schabi.newpipe.util.NavigationHelper;
|
||||||
|
import org.schabi.newpipe.util.PermissionHelper;
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.concurrent.TimeUnit;
|
import java.util.concurrent.TimeUnit;
|
||||||
|
@ -69,6 +76,10 @@ public class ChannelFragment extends BaseListInfoFragment<ChannelInfo> {
|
||||||
private TextView headerSubscribersTextView;
|
private TextView headerSubscribersTextView;
|
||||||
private Button headerSubscribeButton;
|
private Button headerSubscribeButton;
|
||||||
|
|
||||||
|
private Button headerPlayAllButton;
|
||||||
|
private Button headerPopupButton;
|
||||||
|
private Button headerBackgroundButton;
|
||||||
|
|
||||||
private MenuItem menuRssButton;
|
private MenuItem menuRssButton;
|
||||||
|
|
||||||
public static ChannelFragment getInstance(int serviceId, String url, String name) {
|
public static ChannelFragment getInstance(int serviceId, String url, String name) {
|
||||||
|
@ -125,6 +136,10 @@ public class ChannelFragment extends BaseListInfoFragment<ChannelInfo> {
|
||||||
headerSubscribersTextView = headerRootLayout.findViewById(R.id.channel_subscriber_view);
|
headerSubscribersTextView = headerRootLayout.findViewById(R.id.channel_subscriber_view);
|
||||||
headerSubscribeButton = headerRootLayout.findViewById(R.id.channel_subscribe_button);
|
headerSubscribeButton = headerRootLayout.findViewById(R.id.channel_subscribe_button);
|
||||||
|
|
||||||
|
headerPlayAllButton = headerRootLayout.findViewById(R.id.playlist_play_all_button);
|
||||||
|
headerPopupButton = headerRootLayout.findViewById(R.id.playlist_play_popup_button);
|
||||||
|
headerBackgroundButton = headerRootLayout.findViewById(R.id.playlist_play_bg_button);
|
||||||
|
|
||||||
return headerRootLayout;
|
return headerRootLayout;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -391,6 +406,42 @@ public class ChannelFragment extends BaseListInfoFragment<ChannelInfo> {
|
||||||
if (subscribeButtonMonitor != null) subscribeButtonMonitor.dispose();
|
if (subscribeButtonMonitor != null) subscribeButtonMonitor.dispose();
|
||||||
updateSubscription(result);
|
updateSubscription(result);
|
||||||
monitorSubscription(result);
|
monitorSubscription(result);
|
||||||
|
|
||||||
|
headerPlayAllButton.setOnClickListener(new View.OnClickListener() {
|
||||||
|
@Override
|
||||||
|
public void onClick(View view) {
|
||||||
|
NavigationHelper.playOnMainPlayer(activity, getPlayQueue());
|
||||||
|
}
|
||||||
|
});
|
||||||
|
headerPopupButton.setOnClickListener(new View.OnClickListener() {
|
||||||
|
@Override
|
||||||
|
public void onClick(View view) {
|
||||||
|
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M && !PermissionHelper.checkSystemAlertWindowPermission(activity)) {
|
||||||
|
Toast toast = Toast.makeText(activity, R.string.msg_popup_permission, Toast.LENGTH_LONG);
|
||||||
|
TextView messageView = toast.getView().findViewById(android.R.id.message);
|
||||||
|
if (messageView != null) messageView.setGravity(Gravity.CENTER);
|
||||||
|
toast.show();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
NavigationHelper.playOnPopupPlayer(activity, getPlayQueue());
|
||||||
|
}
|
||||||
|
});
|
||||||
|
headerBackgroundButton.setOnClickListener(new View.OnClickListener() {
|
||||||
|
@Override
|
||||||
|
public void onClick(View view) {
|
||||||
|
NavigationHelper.playOnBackgroundPlayer(activity, getPlayQueue());
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
private PlayQueue getPlayQueue() {
|
||||||
|
return new ChannelPlayQueue(
|
||||||
|
currentInfo.service_id,
|
||||||
|
currentInfo.url,
|
||||||
|
currentInfo.next_streams_url,
|
||||||
|
infoListAdapter.getItemsList(),
|
||||||
|
0
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
|
@ -26,7 +26,7 @@ abstract class AbstractInfoPlayQueue<T extends ListInfo, U extends InfoItem> ext
|
||||||
transient Disposable fetchReactor;
|
transient Disposable fetchReactor;
|
||||||
|
|
||||||
AbstractInfoPlayQueue(final U item) {
|
AbstractInfoPlayQueue(final U item) {
|
||||||
this(item.service_id, item.url, item.url, Collections.<InfoItem>emptyList(), 0);
|
this(item.service_id, item.url, null, Collections.<InfoItem>emptyList(), 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
AbstractInfoPlayQueue(final int serviceId,
|
AbstractInfoPlayQueue(final int serviceId,
|
||||||
|
@ -55,7 +55,7 @@ abstract class AbstractInfoPlayQueue<T extends ListInfo, U extends InfoItem> ext
|
||||||
return new SingleObserver<T>() {
|
return new SingleObserver<T>() {
|
||||||
@Override
|
@Override
|
||||||
public void onSubscribe(@NonNull Disposable d) {
|
public void onSubscribe(@NonNull Disposable d) {
|
||||||
if (isComplete || (fetchReactor != null && !fetchReactor.isDisposed())) {
|
if (isComplete || !isInitial || (fetchReactor != null && !fetchReactor.isDisposed())) {
|
||||||
d.dispose();
|
d.dispose();
|
||||||
} else {
|
} else {
|
||||||
fetchReactor = d;
|
fetchReactor = d;
|
||||||
|
@ -64,6 +64,7 @@ abstract class AbstractInfoPlayQueue<T extends ListInfo, U extends InfoItem> ext
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onSuccess(@NonNull T result) {
|
public void onSuccess(@NonNull T result) {
|
||||||
|
isInitial = false;
|
||||||
if (!result.has_more_streams) isComplete = true;
|
if (!result.has_more_streams) isComplete = true;
|
||||||
nextUrl = result.next_streams_url;
|
nextUrl = result.next_streams_url;
|
||||||
|
|
||||||
|
@ -86,7 +87,7 @@ abstract class AbstractInfoPlayQueue<T extends ListInfo, U extends InfoItem> ext
|
||||||
return new SingleObserver<ListExtractor.NextItemsResult>() {
|
return new SingleObserver<ListExtractor.NextItemsResult>() {
|
||||||
@Override
|
@Override
|
||||||
public void onSubscribe(@NonNull Disposable d) {
|
public void onSubscribe(@NonNull Disposable d) {
|
||||||
if (isComplete || (fetchReactor != null && !fetchReactor.isDisposed())) {
|
if (isComplete || isInitial || (fetchReactor != null && !fetchReactor.isDisposed())) {
|
||||||
d.dispose();
|
d.dispose();
|
||||||
} else {
|
} else {
|
||||||
fetchReactor = d;
|
fetchReactor = d;
|
||||||
|
|
|
@ -16,10 +16,10 @@ public final class ChannelPlayQueue extends AbstractInfoPlayQueue<ChannelInfo, C
|
||||||
}
|
}
|
||||||
|
|
||||||
public ChannelPlayQueue(final int serviceId,
|
public ChannelPlayQueue(final int serviceId,
|
||||||
final String url,
|
final String url,
|
||||||
final String nextPageUrl,
|
final String nextPageUrl,
|
||||||
final List<InfoItem> streams,
|
final List<InfoItem> streams,
|
||||||
final int index) {
|
final int index) {
|
||||||
super(serviceId, url, nextPageUrl, streams, index);
|
super(serviceId, url, nextPageUrl, streams, index);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -123,7 +123,7 @@ public abstract class PlayQueue implements Serializable {
|
||||||
* May throw {@link IndexOutOfBoundsException}.
|
* May throw {@link IndexOutOfBoundsException}.
|
||||||
* */
|
* */
|
||||||
public PlayQueueItem getItem(int index) {
|
public PlayQueueItem getItem(int index) {
|
||||||
if (index >= streams.size() || streams.get(index) == null) return null;
|
if (index < 0 || index >= streams.size() || streams.get(index) == null) return null;
|
||||||
return streams.get(index);
|
return streams.get(index);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -16,10 +16,10 @@ public final class PlaylistPlayQueue extends AbstractInfoPlayQueue<PlaylistInfo,
|
||||||
}
|
}
|
||||||
|
|
||||||
public PlaylistPlayQueue(final int serviceId,
|
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,
|
||||||
final int index) {
|
final int index) {
|
||||||
super(serviceId, url, nextPageUrl, streams, index);
|
super(serviceId, url, nextPageUrl, streams, index);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -5,76 +5,138 @@
|
||||||
xmlns:tools="http://schemas.android.com/tools"
|
xmlns:tools="http://schemas.android.com/tools"
|
||||||
android:id="@+id/channel_header_layout"
|
android:id="@+id/channel_header_layout"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content">
|
||||||
android:layout_marginBottom="12dp">
|
|
||||||
|
|
||||||
<ImageView
|
<RelativeLayout
|
||||||
android:id="@+id/channel_banner_image"
|
android:id="@+id/channel_metadata"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="70dp"
|
android:layout_height="wrap_content">
|
||||||
android:background="@android:color/black"
|
|
||||||
android:fitsSystemWindows="true"
|
|
||||||
android:scaleType="centerCrop"
|
|
||||||
android:src="@drawable/channel_banner"
|
|
||||||
tools:ignore="ContentDescription"/>
|
|
||||||
|
|
||||||
<de.hdodenhof.circleimageview.CircleImageView
|
<ImageView
|
||||||
android:id="@+id/channel_avatar_view"
|
android:id="@+id/channel_banner_image"
|
||||||
android:layout_width="@dimen/channel_avatar_size"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="@dimen/channel_avatar_size"
|
android:layout_height="70dp"
|
||||||
android:layout_alignTop="@id/channel_banner_image"
|
android:background="@android:color/black"
|
||||||
android:layout_marginLeft="8dp"
|
android:fitsSystemWindows="true"
|
||||||
android:layout_marginTop="50dp"
|
android:scaleType="centerCrop"
|
||||||
android:src="@drawable/buddy"
|
android:src="@drawable/channel_banner"
|
||||||
app:civ_border_color="#ffffff"
|
tools:ignore="ContentDescription"/>
|
||||||
app:civ_border_width="2dp"
|
|
||||||
tools:ignore="RtlHardcoded"/>
|
|
||||||
|
|
||||||
<TextView
|
<de.hdodenhof.circleimageview.CircleImageView
|
||||||
android:id="@+id/channel_title_view"
|
android:id="@+id/channel_avatar_view"
|
||||||
|
android:layout_width="@dimen/channel_avatar_size"
|
||||||
|
android:layout_height="@dimen/channel_avatar_size"
|
||||||
|
android:layout_alignTop="@id/channel_banner_image"
|
||||||
|
android:layout_marginLeft="8dp"
|
||||||
|
android:layout_marginTop="50dp"
|
||||||
|
android:src="@drawable/buddy"
|
||||||
|
app:civ_border_color="#ffffff"
|
||||||
|
app:civ_border_width="2dp"
|
||||||
|
tools:ignore="RtlHardcoded"/>
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/channel_title_view"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_below="@id/channel_banner_image"
|
||||||
|
android:layout_marginLeft="8dp"
|
||||||
|
android:layout_marginRight="8dp"
|
||||||
|
android:layout_marginTop="6dp"
|
||||||
|
android:layout_toLeftOf="@+id/channel_subscribe_button"
|
||||||
|
android:layout_toRightOf="@+id/channel_avatar_view"
|
||||||
|
android:ellipsize="end"
|
||||||
|
android:lines="1"
|
||||||
|
android:textAppearance="?android:attr/textAppearanceLarge"
|
||||||
|
android:textSize="@dimen/video_item_detail_title_text_size"
|
||||||
|
tools:ignore="RtlHardcoded"
|
||||||
|
tools:text="Lorem ipsum dolor"/>
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/channel_subscriber_view"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_alignLeft="@+id/channel_title_view"
|
||||||
|
android:layout_alignRight="@+id/channel_title_view"
|
||||||
|
android:layout_below="@+id/channel_title_view"
|
||||||
|
android:ellipsize="end"
|
||||||
|
android:gravity="left|center"
|
||||||
|
android:lines="1"
|
||||||
|
android:textSize="@dimen/channel_subscribers_text_size"
|
||||||
|
android:visibility="gone"
|
||||||
|
tools:ignore="RtlHardcoded"
|
||||||
|
tools:text="123,141,411 subscribers"
|
||||||
|
tools:visibility="visible"/>
|
||||||
|
|
||||||
|
<android.support.v7.widget.AppCompatButton
|
||||||
|
android:id="@+id/channel_subscribe_button"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_alignParentRight="true"
|
||||||
|
android:layout_below="@+id/channel_banner_image"
|
||||||
|
android:layout_gravity="center_vertical|right"
|
||||||
|
android:layout_marginRight="2dp"
|
||||||
|
android:text="@string/subscribe_button_title"
|
||||||
|
android:textSize="@dimen/channel_rss_title_size"
|
||||||
|
android:theme="@style/RedButton"
|
||||||
|
android:visibility="gone"
|
||||||
|
tools:ignore="RtlHardcoded"
|
||||||
|
tools:visibility="visible"/>
|
||||||
|
</RelativeLayout>
|
||||||
|
|
||||||
|
<RelativeLayout
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout_below="@id/channel_banner_image"
|
android:id="@+id/play_control"
|
||||||
android:layout_marginLeft="8dp"
|
|
||||||
android:layout_marginRight="8dp"
|
|
||||||
android:layout_marginTop="6dp"
|
|
||||||
android:layout_toLeftOf="@+id/channel_subscribe_button"
|
|
||||||
android:layout_toRightOf="@+id/channel_avatar_view"
|
|
||||||
android:ellipsize="end"
|
|
||||||
android:lines="1"
|
|
||||||
android:textAppearance="?android:attr/textAppearanceLarge"
|
|
||||||
android:textSize="@dimen/video_item_detail_title_text_size"
|
|
||||||
tools:ignore="RtlHardcoded"
|
|
||||||
tools:text="Lorem ipsum dolor"/>
|
|
||||||
|
|
||||||
<TextView
|
|
||||||
android:id="@+id/channel_subscriber_view"
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:layout_alignLeft="@+id/channel_title_view"
|
|
||||||
android:layout_alignRight="@+id/channel_title_view"
|
|
||||||
android:layout_below="@+id/channel_title_view"
|
|
||||||
android:ellipsize="end"
|
|
||||||
android:gravity="left|center"
|
|
||||||
android:lines="1"
|
|
||||||
android:textSize="@dimen/channel_subscribers_text_size"
|
|
||||||
android:visibility="gone"
|
|
||||||
tools:ignore="RtlHardcoded"
|
|
||||||
tools:text="123,141,411 subscribers"
|
|
||||||
tools:visibility="visible"/>
|
|
||||||
|
|
||||||
<android.support.v7.widget.AppCompatButton
|
|
||||||
android:id="@+id/channel_subscribe_button"
|
|
||||||
android:layout_width="wrap_content"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:layout_alignParentRight="true"
|
|
||||||
android:layout_below="@+id/channel_banner_image"
|
|
||||||
android:layout_gravity="center_vertical|right"
|
|
||||||
android:layout_marginRight="2dp"
|
android:layout_marginRight="2dp"
|
||||||
android:text="@string/subscribe_button_title"
|
android:layout_marginEnd="2dp"
|
||||||
android:textSize="@dimen/channel_rss_title_size"
|
android:layout_below="@+id/channel_metadata">
|
||||||
android:theme="@style/RedButton"
|
|
||||||
android:visibility="gone"
|
<Button
|
||||||
tools:ignore="RtlHardcoded"
|
android:id="@+id/playlist_play_bg_button"
|
||||||
tools:visibility="visible"/>
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_gravity="center_vertical|right"
|
||||||
|
android:layout_marginRight="2dp"
|
||||||
|
android:layout_toLeftOf="@+id/playlist_play_all_button"
|
||||||
|
android:layout_toStartOf="@+id/playlist_play_all_button"
|
||||||
|
android:text="@string/controls_background_title"
|
||||||
|
android:textSize="@dimen/channel_rss_title_size"
|
||||||
|
android:textColor="?attr/colorAccent"
|
||||||
|
android:theme="@style/RedButton"
|
||||||
|
android:drawableLeft="?attr/audio"
|
||||||
|
android:drawablePadding="4dp"
|
||||||
|
tools:ignore="RtlHardcoded"
|
||||||
|
tools:visibility="visible" />
|
||||||
|
|
||||||
|
<Button
|
||||||
|
android:id="@+id/playlist_play_all_button"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_gravity="center_vertical|right"
|
||||||
|
android:layout_marginRight="2dp"
|
||||||
|
android:layout_toLeftOf="@+id/playlist_play_popup_button"
|
||||||
|
android:layout_toStartOf="@+id/playlist_play_popup_button"
|
||||||
|
android:text="@string/play_all"
|
||||||
|
android:textSize="@dimen/channel_rss_title_size"
|
||||||
|
android:textColor="?attr/colorAccent"
|
||||||
|
android:theme="@style/RedButton"
|
||||||
|
tools:ignore="RtlHardcoded"
|
||||||
|
tools:visibility="visible"/>
|
||||||
|
|
||||||
|
<Button
|
||||||
|
android:id="@+id/playlist_play_popup_button"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_gravity="center_vertical|right"
|
||||||
|
android:layout_alignParentRight="true"
|
||||||
|
android:text="@string/controls_popup_title"
|
||||||
|
android:textSize="@dimen/channel_rss_title_size"
|
||||||
|
android:textColor="?attr/colorAccent"
|
||||||
|
android:theme="@style/RedButton"
|
||||||
|
android:drawableLeft="?attr/popup"
|
||||||
|
android:drawablePadding="4dp"
|
||||||
|
tools:ignore="RtlHardcoded"
|
||||||
|
tools:visibility="visible" />
|
||||||
|
</RelativeLayout>
|
||||||
|
|
||||||
</RelativeLayout>
|
</RelativeLayout>
|
Loading…
Reference in a new issue