2017-09-03 08:04:18 +02:00
|
|
|
package org.schabi.newpipe.fragments.list.channel;
|
|
|
|
|
|
|
|
import android.content.Context;
|
|
|
|
import android.content.Intent;
|
|
|
|
import android.net.Uri;
|
|
|
|
import android.os.Bundle;
|
2019-10-04 14:59:08 +02:00
|
|
|
import androidx.annotation.NonNull;
|
|
|
|
import androidx.annotation.Nullable;
|
|
|
|
import androidx.core.content.ContextCompat;
|
|
|
|
import androidx.appcompat.app.ActionBar;
|
2017-09-03 08:04:18 +02:00
|
|
|
import android.text.TextUtils;
|
|
|
|
import android.util.Log;
|
|
|
|
import android.view.LayoutInflater;
|
|
|
|
import android.view.Menu;
|
|
|
|
import android.view.MenuInflater;
|
|
|
|
import android.view.MenuItem;
|
|
|
|
import android.view.View;
|
|
|
|
import android.view.ViewGroup;
|
|
|
|
import android.widget.Button;
|
|
|
|
import android.widget.ImageView;
|
2017-11-11 23:47:34 +01:00
|
|
|
import android.widget.LinearLayout;
|
2017-09-03 08:04:18 +02:00
|
|
|
import android.widget.TextView;
|
|
|
|
|
|
|
|
import com.jakewharton.rxbinding2.view.RxView;
|
|
|
|
|
|
|
|
import org.schabi.newpipe.R;
|
|
|
|
import org.schabi.newpipe.database.subscription.SubscriptionEntity;
|
2018-03-18 16:37:49 +01:00
|
|
|
import org.schabi.newpipe.extractor.InfoItem;
|
2017-09-03 08:04:18 +02:00
|
|
|
import org.schabi.newpipe.extractor.ListExtractor;
|
|
|
|
import org.schabi.newpipe.extractor.NewPipe;
|
|
|
|
import org.schabi.newpipe.extractor.channel.ChannelInfo;
|
2019-03-09 20:32:25 +01:00
|
|
|
import org.schabi.newpipe.extractor.exceptions.ContentNotAvailableException;
|
2017-09-03 08:04:18 +02:00
|
|
|
import org.schabi.newpipe.extractor.exceptions.ExtractionException;
|
2017-11-11 23:47:34 +01:00
|
|
|
import org.schabi.newpipe.extractor.stream.StreamInfoItem;
|
2017-09-03 08:04:18 +02:00
|
|
|
import org.schabi.newpipe.fragments.list.BaseListInfoFragment;
|
2019-04-28 22:43:54 +02:00
|
|
|
import org.schabi.newpipe.local.subscription.SubscriptionManager;
|
2018-04-21 23:10:01 +02:00
|
|
|
import org.schabi.newpipe.player.playqueue.ChannelPlayQueue;
|
|
|
|
import org.schabi.newpipe.player.playqueue.PlayQueue;
|
2017-09-03 08:04:18 +02:00
|
|
|
import org.schabi.newpipe.report.UserAction;
|
|
|
|
import org.schabi.newpipe.util.AnimationUtils;
|
|
|
|
import org.schabi.newpipe.util.ExtractorHelper;
|
2018-03-16 04:07:20 +01:00
|
|
|
import org.schabi.newpipe.util.ImageDisplayConstants;
|
2017-09-03 08:04:18 +02:00
|
|
|
import org.schabi.newpipe.util.Localization;
|
2017-11-04 19:30:01 +01:00
|
|
|
import org.schabi.newpipe.util.NavigationHelper;
|
2019-04-06 20:17:04 +02:00
|
|
|
import org.schabi.newpipe.util.ShareUtils;
|
2017-09-03 08:04:18 +02:00
|
|
|
|
2018-03-18 16:37:49 +01:00
|
|
|
import java.util.ArrayList;
|
2017-09-03 08:04:18 +02:00
|
|
|
import java.util.List;
|
|
|
|
import java.util.concurrent.TimeUnit;
|
|
|
|
|
|
|
|
import io.reactivex.Observable;
|
|
|
|
import io.reactivex.Single;
|
|
|
|
import io.reactivex.android.schedulers.AndroidSchedulers;
|
|
|
|
import io.reactivex.disposables.CompositeDisposable;
|
|
|
|
import io.reactivex.disposables.Disposable;
|
|
|
|
import io.reactivex.functions.Action;
|
|
|
|
import io.reactivex.functions.Consumer;
|
|
|
|
import io.reactivex.functions.Function;
|
|
|
|
import io.reactivex.schedulers.Schedulers;
|
|
|
|
|
|
|
|
import static org.schabi.newpipe.util.AnimationUtils.animateBackgroundColor;
|
|
|
|
import static org.schabi.newpipe.util.AnimationUtils.animateTextColor;
|
|
|
|
import static org.schabi.newpipe.util.AnimationUtils.animateView;
|
|
|
|
|
|
|
|
public class ChannelFragment extends BaseListInfoFragment<ChannelInfo> {
|
|
|
|
|
2018-08-28 20:02:25 +02:00
|
|
|
private final CompositeDisposable disposables = new CompositeDisposable();
|
2017-09-03 08:04:18 +02:00
|
|
|
private Disposable subscribeButtonMonitor;
|
2019-04-28 22:43:54 +02:00
|
|
|
private SubscriptionManager subscriptionManager;
|
2017-09-03 08:04:18 +02:00
|
|
|
|
|
|
|
/*//////////////////////////////////////////////////////////////////////////
|
|
|
|
// Views
|
|
|
|
//////////////////////////////////////////////////////////////////////////*/
|
|
|
|
|
|
|
|
private View headerRootLayout;
|
|
|
|
private ImageView headerChannelBanner;
|
|
|
|
private ImageView headerAvatarView;
|
|
|
|
private TextView headerTitleView;
|
|
|
|
private TextView headerSubscribersTextView;
|
|
|
|
private Button headerSubscribeButton;
|
2017-11-12 09:16:51 +01:00
|
|
|
private View playlistCtrl;
|
2017-09-03 08:04:18 +02:00
|
|
|
|
2017-11-11 23:47:34 +01:00
|
|
|
private LinearLayout headerPlayAllButton;
|
|
|
|
private LinearLayout headerPopupButton;
|
|
|
|
private LinearLayout headerBackgroundButton;
|
2017-11-04 19:30:01 +01:00
|
|
|
|
2017-09-03 08:04:18 +02:00
|
|
|
private MenuItem menuRssButton;
|
|
|
|
|
2018-07-10 16:26:42 +02:00
|
|
|
public static ChannelFragment getInstance(int serviceId, String url, String name) {
|
2017-09-03 08:04:18 +02:00
|
|
|
ChannelFragment instance = new ChannelFragment();
|
2018-07-10 16:26:42 +02:00
|
|
|
instance.setInitialData(serviceId, url, name);
|
2017-09-03 08:04:18 +02:00
|
|
|
return instance;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*//////////////////////////////////////////////////////////////////////////
|
|
|
|
// LifeCycle
|
|
|
|
//////////////////////////////////////////////////////////////////////////*/
|
|
|
|
|
2017-10-26 20:45:16 +02:00
|
|
|
@Override
|
|
|
|
public void setUserVisibleHint(boolean isVisibleToUser) {
|
|
|
|
super.setUserVisibleHint(isVisibleToUser);
|
2019-11-23 20:04:40 +01:00
|
|
|
if (activity != null
|
2017-10-26 20:45:16 +02:00
|
|
|
&& useAsFrontPage
|
|
|
|
&& isVisibleToUser) {
|
2018-01-30 08:01:57 +01:00
|
|
|
setTitle(currentInfo != null ? currentInfo.getName() : name);
|
2017-10-26 20:45:16 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-09-03 08:04:18 +02:00
|
|
|
@Override
|
|
|
|
public void onAttach(Context context) {
|
|
|
|
super.onAttach(context);
|
2019-04-28 22:43:54 +02:00
|
|
|
subscriptionManager = new SubscriptionManager(activity);
|
2017-09-03 08:04:18 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
@Override
|
2018-03-08 14:39:24 +01:00
|
|
|
public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
|
2017-11-01 16:26:44 +01:00
|
|
|
return inflater.inflate(R.layout.fragment_channel, container, false);
|
2017-09-03 08:04:18 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
@Override
|
|
|
|
public void onDestroy() {
|
|
|
|
super.onDestroy();
|
|
|
|
if (disposables != null) disposables.clear();
|
|
|
|
if (subscribeButtonMonitor != null) subscribeButtonMonitor.dispose();
|
|
|
|
}
|
|
|
|
|
|
|
|
/*//////////////////////////////////////////////////////////////////////////
|
|
|
|
// Init
|
|
|
|
//////////////////////////////////////////////////////////////////////////*/
|
|
|
|
|
|
|
|
protected View getListHeader() {
|
|
|
|
headerRootLayout = activity.getLayoutInflater().inflate(R.layout.channel_header, itemsList, false);
|
|
|
|
headerChannelBanner = headerRootLayout.findViewById(R.id.channel_banner_image);
|
|
|
|
headerAvatarView = headerRootLayout.findViewById(R.id.channel_avatar_view);
|
|
|
|
headerTitleView = headerRootLayout.findViewById(R.id.channel_title_view);
|
|
|
|
headerSubscribersTextView = headerRootLayout.findViewById(R.id.channel_subscriber_view);
|
|
|
|
headerSubscribeButton = headerRootLayout.findViewById(R.id.channel_subscribe_button);
|
2017-11-12 09:16:51 +01:00
|
|
|
playlistCtrl = headerRootLayout.findViewById(R.id.playlist_control);
|
2017-09-28 16:15:09 +02:00
|
|
|
|
2017-11-12 09:16:51 +01:00
|
|
|
|
|
|
|
headerPlayAllButton = headerRootLayout.findViewById(R.id.playlist_ctrl_play_all_button);
|
|
|
|
headerPopupButton = headerRootLayout.findViewById(R.id.playlist_ctrl_play_popup_button);
|
|
|
|
headerBackgroundButton = headerRootLayout.findViewById(R.id.playlist_ctrl_play_bg_button);
|
2017-11-04 19:30:01 +01:00
|
|
|
|
2017-09-03 08:04:18 +02:00
|
|
|
return headerRootLayout;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*//////////////////////////////////////////////////////////////////////////
|
|
|
|
// Menu
|
|
|
|
//////////////////////////////////////////////////////////////////////////*/
|
|
|
|
|
|
|
|
@Override
|
|
|
|
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
|
|
|
|
super.onCreateOptionsMenu(menu, inflater);
|
2017-09-26 18:16:39 +02:00
|
|
|
ActionBar supportActionBar = activity.getSupportActionBar();
|
2019-11-23 20:04:40 +01:00
|
|
|
if (useAsFrontPage && supportActionBar != null) {
|
2017-09-26 18:16:39 +02:00
|
|
|
supportActionBar.setDisplayHomeAsUpEnabled(false);
|
|
|
|
} else {
|
|
|
|
inflater.inflate(R.menu.menu_channel, menu);
|
|
|
|
|
2018-01-29 08:01:06 +01:00
|
|
|
if (DEBUG) Log.d(TAG, "onCreateOptionsMenu() called with: menu = [" + menu +
|
|
|
|
"], inflater = [" + inflater + "]");
|
2017-09-26 18:16:39 +02:00
|
|
|
menuRssButton = menu.findItem(R.id.menu_item_rss);
|
2017-09-03 08:04:18 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-11-01 16:26:44 +01:00
|
|
|
private void openRssFeed() {
|
|
|
|
final ChannelInfo info = currentInfo;
|
2019-11-23 20:04:40 +01:00
|
|
|
if (info != null) {
|
2017-12-08 15:05:08 +01:00
|
|
|
Intent intent = new Intent(Intent.ACTION_VIEW, Uri.parse(info.getFeedUrl()));
|
2017-11-01 16:26:44 +01:00
|
|
|
startActivity(intent);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-09-03 08:04:18 +02:00
|
|
|
@Override
|
|
|
|
public boolean onOptionsItemSelected(MenuItem item) {
|
|
|
|
switch (item.getItemId()) {
|
2020-02-22 10:36:10 +01:00
|
|
|
case R.id.action_settings:
|
|
|
|
NavigationHelper.openSettings(requireContext());
|
|
|
|
break;
|
2017-11-01 16:26:44 +01:00
|
|
|
case R.id.menu_item_rss:
|
|
|
|
openRssFeed();
|
|
|
|
break;
|
|
|
|
case R.id.menu_item_openInBrowser:
|
2019-12-02 21:34:52 +01:00
|
|
|
if (currentInfo != null) {
|
2020-02-22 10:36:10 +01:00
|
|
|
ShareUtils.openUrlInBrowser(requireContext(), currentInfo.getOriginalUrl());
|
2019-12-02 21:34:52 +01:00
|
|
|
}
|
2017-11-01 16:26:44 +01:00
|
|
|
break;
|
2018-01-29 08:01:06 +01:00
|
|
|
case R.id.menu_item_share:
|
2019-12-02 21:34:52 +01:00
|
|
|
if (currentInfo != null) {
|
2020-02-22 10:36:10 +01:00
|
|
|
ShareUtils.shareUrl(requireContext(), name, currentInfo.getOriginalUrl());
|
2019-12-02 21:34:52 +01:00
|
|
|
}
|
2017-11-01 16:26:44 +01:00
|
|
|
break;
|
2017-09-03 08:04:18 +02:00
|
|
|
default:
|
|
|
|
return super.onOptionsItemSelected(item);
|
|
|
|
}
|
2017-11-01 16:26:44 +01:00
|
|
|
return true;
|
2017-09-03 08:04:18 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
/*//////////////////////////////////////////////////////////////////////////
|
|
|
|
// Channel Subscription
|
|
|
|
//////////////////////////////////////////////////////////////////////////*/
|
|
|
|
|
|
|
|
private static final int BUTTON_DEBOUNCE_INTERVAL = 100;
|
|
|
|
|
|
|
|
private void monitorSubscription(final ChannelInfo info) {
|
2018-08-22 16:04:32 +02:00
|
|
|
final Consumer<Throwable> onError = (Throwable throwable) -> {
|
2017-09-03 08:04:18 +02:00
|
|
|
animateView(headerSubscribeButton, false, 100);
|
2018-08-22 16:04:32 +02:00
|
|
|
showSnackBarError(throwable, UserAction.SUBSCRIPTION,
|
|
|
|
NewPipe.getNameOfService(currentInfo.getServiceId()),
|
|
|
|
"Get subscription status",
|
|
|
|
0);
|
2017-09-03 08:04:18 +02:00
|
|
|
};
|
|
|
|
|
2019-04-28 22:43:54 +02:00
|
|
|
final Observable<List<SubscriptionEntity>> observable = subscriptionManager.subscriptionTable()
|
|
|
|
.getSubscriptionFlowable(info.getServiceId(), info.getUrl())
|
2017-09-03 08:04:18 +02:00
|
|
|
.toObservable();
|
|
|
|
|
|
|
|
disposables.add(observable
|
|
|
|
.observeOn(AndroidSchedulers.mainThread())
|
|
|
|
.subscribe(getSubscribeUpdateMonitor(info), onError));
|
|
|
|
|
|
|
|
disposables.add(observable
|
|
|
|
// Some updates are very rapid (when calling the updateSubscription(info), for example)
|
|
|
|
// so only update the UI for the latest emission ("sync" the subscribe button's state)
|
|
|
|
.debounce(100, TimeUnit.MILLISECONDS)
|
|
|
|
.observeOn(AndroidSchedulers.mainThread())
|
2018-08-22 16:04:32 +02:00
|
|
|
.subscribe((List<SubscriptionEntity> subscriptionEntities) ->
|
2019-11-23 20:04:40 +01:00
|
|
|
updateSubscribeButton(!subscriptionEntities.isEmpty())
|
2018-08-22 16:04:32 +02:00
|
|
|
, onError));
|
2017-09-03 08:04:18 +02:00
|
|
|
|
|
|
|
}
|
|
|
|
|
2019-04-28 22:43:54 +02:00
|
|
|
private Function<Object, Object> mapOnSubscribe(final SubscriptionEntity subscription, ChannelInfo info) {
|
2018-08-22 16:04:32 +02:00
|
|
|
return (@NonNull Object o) -> {
|
2019-04-28 22:43:54 +02:00
|
|
|
subscriptionManager.insertSubscription(subscription, info);
|
2018-08-22 16:04:32 +02:00
|
|
|
return o;
|
2017-09-03 08:04:18 +02:00
|
|
|
};
|
|
|
|
}
|
|
|
|
|
|
|
|
private Function<Object, Object> mapOnUnsubscribe(final SubscriptionEntity subscription) {
|
2018-08-22 16:04:32 +02:00
|
|
|
return (@NonNull Object o) -> {
|
2019-04-28 22:43:54 +02:00
|
|
|
subscriptionManager.deleteSubscription(subscription);
|
2018-08-22 16:04:32 +02:00
|
|
|
return o;
|
2017-09-03 08:04:18 +02:00
|
|
|
};
|
|
|
|
}
|
|
|
|
|
|
|
|
private void updateSubscription(final ChannelInfo info) {
|
|
|
|
if (DEBUG) Log.d(TAG, "updateSubscription() called with: info = [" + info + "]");
|
2018-08-22 16:04:32 +02:00
|
|
|
final Action onComplete = () -> {
|
2017-12-08 15:05:08 +01:00
|
|
|
if (DEBUG) Log.d(TAG, "Updated subscription: " + info.getUrl());
|
2017-09-03 08:04:18 +02:00
|
|
|
};
|
|
|
|
|
2018-08-22 16:04:32 +02:00
|
|
|
final Consumer<Throwable> onError = (@NonNull Throwable throwable) ->
|
|
|
|
onUnrecoverableError(throwable,
|
|
|
|
UserAction.SUBSCRIPTION,
|
|
|
|
NewPipe.getNameOfService(info.getServiceId()),
|
|
|
|
"Updating Subscription for " + info.getUrl(),
|
|
|
|
R.string.subscription_update_failed);
|
2017-09-03 08:04:18 +02:00
|
|
|
|
2019-04-28 22:43:54 +02:00
|
|
|
disposables.add(subscriptionManager.updateChannelInfo(info)
|
2017-09-03 08:04:18 +02:00
|
|
|
.subscribeOn(Schedulers.io())
|
|
|
|
.observeOn(AndroidSchedulers.mainThread())
|
|
|
|
.subscribe(onComplete, onError));
|
|
|
|
}
|
|
|
|
|
|
|
|
private Disposable monitorSubscribeButton(final Button subscribeButton, final Function<Object, Object> action) {
|
2018-08-22 16:04:32 +02:00
|
|
|
final Consumer<Object> onNext = (@NonNull Object o) -> {
|
2017-09-03 08:04:18 +02:00
|
|
|
if (DEBUG) Log.d(TAG, "Changed subscription status to this channel!");
|
|
|
|
};
|
|
|
|
|
2018-08-22 16:04:32 +02:00
|
|
|
final Consumer<Throwable> onError = (@NonNull Throwable throwable) ->
|
|
|
|
onUnrecoverableError(throwable,
|
|
|
|
UserAction.SUBSCRIPTION,
|
|
|
|
NewPipe.getNameOfService(currentInfo.getServiceId()),
|
|
|
|
"Subscription Change",
|
|
|
|
R.string.subscription_change_failed);
|
2017-09-03 08:04:18 +02:00
|
|
|
|
|
|
|
/* Emit clicks from main thread unto io thread */
|
|
|
|
return RxView.clicks(subscribeButton)
|
|
|
|
.subscribeOn(AndroidSchedulers.mainThread())
|
|
|
|
.observeOn(Schedulers.io())
|
|
|
|
.debounce(BUTTON_DEBOUNCE_INTERVAL, TimeUnit.MILLISECONDS) // Ignore rapid clicks
|
|
|
|
.map(action)
|
|
|
|
.subscribe(onNext, onError);
|
|
|
|
}
|
|
|
|
|
|
|
|
private Consumer<List<SubscriptionEntity>> getSubscribeUpdateMonitor(final ChannelInfo info) {
|
2018-08-22 16:04:32 +02:00
|
|
|
return (List<SubscriptionEntity> subscriptionEntities) -> {
|
|
|
|
if (DEBUG)
|
2019-04-28 22:43:54 +02:00
|
|
|
Log.d(TAG, "subscriptionManager.subscriptionTable.doOnNext() called with: subscriptionEntities = [" + subscriptionEntities + "]");
|
2018-08-22 16:04:32 +02:00
|
|
|
if (subscribeButtonMonitor != null) subscribeButtonMonitor.dispose();
|
|
|
|
|
|
|
|
if (subscriptionEntities.isEmpty()) {
|
|
|
|
if (DEBUG) Log.d(TAG, "No subscription to this channel!");
|
|
|
|
SubscriptionEntity channel = new SubscriptionEntity();
|
|
|
|
channel.setServiceId(info.getServiceId());
|
|
|
|
channel.setUrl(info.getUrl());
|
|
|
|
channel.setData(info.getName(),
|
|
|
|
info.getAvatarUrl(),
|
|
|
|
info.getDescription(),
|
|
|
|
info.getSubscriberCount());
|
2019-04-28 22:43:54 +02:00
|
|
|
subscribeButtonMonitor = monitorSubscribeButton(headerSubscribeButton, mapOnSubscribe(channel, info));
|
2018-08-22 16:04:32 +02:00
|
|
|
} else {
|
|
|
|
if (DEBUG) Log.d(TAG, "Found subscription to this channel!");
|
|
|
|
final SubscriptionEntity subscription = subscriptionEntities.get(0);
|
|
|
|
subscribeButtonMonitor = monitorSubscribeButton(headerSubscribeButton, mapOnUnsubscribe(subscription));
|
2017-09-03 08:04:18 +02:00
|
|
|
}
|
|
|
|
};
|
|
|
|
}
|
|
|
|
|
|
|
|
private void updateSubscribeButton(boolean isSubscribed) {
|
|
|
|
if (DEBUG) Log.d(TAG, "updateSubscribeButton() called with: isSubscribed = [" + isSubscribed + "]");
|
|
|
|
|
|
|
|
boolean isButtonVisible = headerSubscribeButton.getVisibility() == View.VISIBLE;
|
|
|
|
int backgroundDuration = isButtonVisible ? 300 : 0;
|
|
|
|
int textDuration = isButtonVisible ? 200 : 0;
|
|
|
|
|
|
|
|
int subscribeBackground = ContextCompat.getColor(activity, R.color.subscribe_background_color);
|
|
|
|
int subscribeText = ContextCompat.getColor(activity, R.color.subscribe_text_color);
|
|
|
|
int subscribedBackground = ContextCompat.getColor(activity, R.color.subscribed_background_color);
|
|
|
|
int subscribedText = ContextCompat.getColor(activity, R.color.subscribed_text_color);
|
|
|
|
|
|
|
|
if (!isSubscribed) {
|
|
|
|
headerSubscribeButton.setText(R.string.subscribe_button_title);
|
|
|
|
animateBackgroundColor(headerSubscribeButton, backgroundDuration, subscribedBackground, subscribeBackground);
|
|
|
|
animateTextColor(headerSubscribeButton, textDuration, subscribedText, subscribeText);
|
|
|
|
} else {
|
|
|
|
headerSubscribeButton.setText(R.string.subscribed_button_title);
|
|
|
|
animateBackgroundColor(headerSubscribeButton, backgroundDuration, subscribeBackground, subscribedBackground);
|
|
|
|
animateTextColor(headerSubscribeButton, textDuration, subscribeText, subscribedText);
|
|
|
|
}
|
|
|
|
|
|
|
|
animateView(headerSubscribeButton, AnimationUtils.Type.LIGHT_SCALE_AND_ALPHA, true, 100);
|
|
|
|
}
|
|
|
|
|
|
|
|
/*//////////////////////////////////////////////////////////////////////////
|
|
|
|
// Load and handle
|
|
|
|
//////////////////////////////////////////////////////////////////////////*/
|
|
|
|
|
|
|
|
@Override
|
2018-03-18 16:37:49 +01:00
|
|
|
protected Single<ListExtractor.InfoItemsPage> loadMoreItemsLogic() {
|
2018-07-10 16:26:42 +02:00
|
|
|
return ExtractorHelper.getMoreChannelItems(serviceId, url, currentNextPageUrl);
|
2017-09-03 08:04:18 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
@Override
|
|
|
|
protected Single<ChannelInfo> loadResult(boolean forceLoad) {
|
2018-07-10 16:26:42 +02:00
|
|
|
return ExtractorHelper.getChannelInfo(serviceId, url, forceLoad);
|
2017-09-03 08:04:18 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
/*//////////////////////////////////////////////////////////////////////////
|
|
|
|
// Contract
|
|
|
|
//////////////////////////////////////////////////////////////////////////*/
|
|
|
|
|
|
|
|
@Override
|
|
|
|
public void showLoading() {
|
|
|
|
super.showLoading();
|
|
|
|
|
|
|
|
imageLoader.cancelDisplayTask(headerChannelBanner);
|
|
|
|
imageLoader.cancelDisplayTask(headerAvatarView);
|
|
|
|
animateView(headerSubscribeButton, false, 100);
|
|
|
|
}
|
|
|
|
|
|
|
|
@Override
|
|
|
|
public void handleResult(@NonNull ChannelInfo result) {
|
|
|
|
super.handleResult(result);
|
|
|
|
|
|
|
|
headerRootLayout.setVisibility(View.VISIBLE);
|
2018-03-16 04:07:20 +01:00
|
|
|
imageLoader.displayImage(result.getBannerUrl(), headerChannelBanner,
|
2019-11-23 20:04:40 +01:00
|
|
|
ImageDisplayConstants.DISPLAY_BANNER_OPTIONS);
|
2018-03-16 04:07:20 +01:00
|
|
|
imageLoader.displayImage(result.getAvatarUrl(), headerAvatarView,
|
2019-11-23 20:04:40 +01:00
|
|
|
ImageDisplayConstants.DISPLAY_AVATAR_OPTIONS);
|
2017-09-03 08:04:18 +02:00
|
|
|
|
2018-09-05 04:54:17 +02:00
|
|
|
headerSubscribersTextView.setVisibility(View.VISIBLE);
|
|
|
|
if (result.getSubscriberCount() >= 0) {
|
Multiple localization fixes
With the extractor PR, fixes title & description shown in the wrong language.
Fixed views / spectators counts possibly in the wrong language
Fixed live spectators not showing full count on detail page
Fixed LIVE shown on players, it shows translated instead
Fixed Videos string in search / three dots not available in Weblate
(because it was videos, but there already was a plural string named videos, in Weblate)
Subscriber count is always giving the short count.
We can't get exact number since this YouTube update: https://support.google.com/youtube/thread/6543166
But only short count (B, M, k), so showing full number, eg for 1.9M: 1,900,000, is wrong because the number could be 1,923,490 or 1,897,789…
Added a « sytem default » option to content language and country language selector.
It's the one selected by default (not en-GB anymore then), and correspond to the
language of the system / country of the system
By system I mean phone, tablet, TV…
Fixed russian showing - before time ago (eg 19hrs ago)
This is a workaround fix, I opened an issue on prettytime library repo.
Fixed russian plurals:
other was used instead of many for videos and subscribers
Fixed seek_duration english only
2020-02-14 18:19:35 +01:00
|
|
|
headerSubscribersTextView.setText(Localization.shortSubscriberCount(activity, result.getSubscriberCount()));
|
2018-09-05 04:54:17 +02:00
|
|
|
} else {
|
|
|
|
headerSubscribersTextView.setText(R.string.subscribers_count_not_available);
|
|
|
|
}
|
2017-09-03 08:04:18 +02:00
|
|
|
|
2017-12-08 15:05:08 +01:00
|
|
|
if (menuRssButton != null) menuRssButton.setVisible(!TextUtils.isEmpty(result.getFeedUrl()));
|
2018-01-29 08:01:06 +01:00
|
|
|
|
2017-11-12 09:16:51 +01:00
|
|
|
playlistCtrl.setVisibility(View.VISIBLE);
|
2017-09-03 08:04:18 +02:00
|
|
|
|
2018-03-18 16:37:49 +01:00
|
|
|
if (!result.getErrors().isEmpty()) {
|
|
|
|
showSnackBarError(result.getErrors(), UserAction.REQUESTED_CHANNEL, NewPipe.getNameOfService(result.getServiceId()), result.getUrl(), 0);
|
2017-09-03 08:04:18 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
if (disposables != null) disposables.clear();
|
|
|
|
if (subscribeButtonMonitor != null) subscribeButtonMonitor.dispose();
|
|
|
|
updateSubscription(result);
|
|
|
|
monitorSubscription(result);
|
2017-11-04 19:30:01 +01:00
|
|
|
|
2018-03-18 16:37:49 +01:00
|
|
|
headerPlayAllButton.setOnClickListener(
|
2019-04-13 09:31:32 +02:00
|
|
|
view -> NavigationHelper.playOnMainPlayer(activity, getPlayQueue(), false));
|
2018-03-18 16:37:49 +01:00
|
|
|
headerPopupButton.setOnClickListener(
|
2019-04-13 09:31:32 +02:00
|
|
|
view -> NavigationHelper.playOnPopupPlayer(activity, getPlayQueue(), false));
|
2018-03-18 16:37:49 +01:00
|
|
|
headerBackgroundButton.setOnClickListener(
|
2019-04-13 09:31:32 +02:00
|
|
|
view -> NavigationHelper.playOnBackgroundPlayer(activity, getPlayQueue(), false));
|
2017-11-04 19:30:01 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
private PlayQueue getPlayQueue() {
|
2017-11-11 23:47:34 +01:00
|
|
|
return getPlayQueue(0);
|
|
|
|
}
|
|
|
|
|
|
|
|
private PlayQueue getPlayQueue(final int index) {
|
2018-03-18 16:37:49 +01:00
|
|
|
final List<StreamInfoItem> streamItems = new ArrayList<>();
|
2019-11-23 20:04:40 +01:00
|
|
|
for (InfoItem i : infoListAdapter.getItemsList()) {
|
|
|
|
if (i instanceof StreamInfoItem) {
|
2018-03-18 16:37:49 +01:00
|
|
|
streamItems.add((StreamInfoItem) i);
|
|
|
|
}
|
|
|
|
}
|
2017-11-04 19:30:01 +01:00
|
|
|
return new ChannelPlayQueue(
|
2017-12-08 15:05:08 +01:00
|
|
|
currentInfo.getServiceId(),
|
|
|
|
currentInfo.getUrl(),
|
2018-02-24 22:57:25 +01:00
|
|
|
currentInfo.getNextPageUrl(),
|
2018-03-18 16:37:49 +01:00
|
|
|
streamItems,
|
2017-11-11 23:47:34 +01:00
|
|
|
index
|
2017-11-04 19:30:01 +01:00
|
|
|
);
|
2017-09-03 08:04:18 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
@Override
|
2018-03-18 16:37:49 +01:00
|
|
|
public void handleNextItems(ListExtractor.InfoItemsPage result) {
|
2017-09-03 08:04:18 +02:00
|
|
|
super.handleNextItems(result);
|
|
|
|
|
2017-12-08 15:05:08 +01:00
|
|
|
if (!result.getErrors().isEmpty()) {
|
2018-08-22 16:04:32 +02:00
|
|
|
showSnackBarError(result.getErrors(),
|
|
|
|
UserAction.REQUESTED_CHANNEL,
|
|
|
|
NewPipe.getNameOfService(serviceId),
|
|
|
|
"Get next page of: " + url,
|
|
|
|
R.string.general_error);
|
2017-09-03 08:04:18 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/*//////////////////////////////////////////////////////////////////////////
|
|
|
|
// OnError
|
|
|
|
//////////////////////////////////////////////////////////////////////////*/
|
|
|
|
|
|
|
|
@Override
|
|
|
|
protected boolean onError(Throwable exception) {
|
|
|
|
if (super.onError(exception)) return true;
|
|
|
|
|
2019-11-23 20:04:40 +01:00
|
|
|
if (exception instanceof ContentNotAvailableException) {
|
2019-03-09 20:32:25 +01:00
|
|
|
showError(getString(R.string.content_not_available), false);
|
2019-11-23 20:04:40 +01:00
|
|
|
} else {
|
2019-03-09 20:32:25 +01:00
|
|
|
int errorId = exception instanceof ExtractionException ? R.string.parsing_error : R.string.general_error;
|
|
|
|
onUnrecoverableError(exception,
|
|
|
|
UserAction.REQUESTED_CHANNEL,
|
|
|
|
NewPipe.getNameOfService(serviceId),
|
|
|
|
url,
|
|
|
|
errorId);
|
|
|
|
}
|
2017-09-03 08:04:18 +02:00
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*//////////////////////////////////////////////////////////////////////////
|
|
|
|
// Utils
|
|
|
|
//////////////////////////////////////////////////////////////////////////*/
|
|
|
|
|
|
|
|
@Override
|
|
|
|
public void setTitle(String title) {
|
2018-08-24 11:54:41 +02:00
|
|
|
super.setTitle(title);
|
|
|
|
if (!useAsFrontPage) headerTitleView.setText(title);
|
2017-09-03 08:04:18 +02:00
|
|
|
}
|
|
|
|
}
|