2017-04-09 19:34:00 +02:00
|
|
|
package org.schabi.newpipe.fragments.detail;
|
2015-09-04 02:15:03 +02:00
|
|
|
|
2017-04-09 19:34:00 +02:00
|
|
|
import android.app.Activity;
|
2017-10-30 21:15:06 +01:00
|
|
|
import android.content.Context;
|
2015-09-04 02:15:03 +02:00
|
|
|
import android.content.Intent;
|
2017-03-31 20:15:26 +02:00
|
|
|
import android.content.SharedPreferences;
|
|
|
|
import android.net.Uri;
|
|
|
|
import android.os.Build;
|
2015-09-04 02:15:03 +02:00
|
|
|
import android.os.Bundle;
|
2017-03-31 20:15:26 +02:00
|
|
|
import android.preference.PreferenceManager;
|
2019-10-04 14:59:08 +02:00
|
|
|
import androidx.annotation.DrawableRes;
|
|
|
|
import androidx.annotation.NonNull;
|
|
|
|
import androidx.annotation.Nullable;
|
|
|
|
import com.google.android.material.appbar.AppBarLayout;
|
|
|
|
import com.google.android.material.tabs.TabLayout;
|
|
|
|
import androidx.fragment.app.Fragment;
|
|
|
|
import androidx.core.content.ContextCompat;
|
|
|
|
import androidx.viewpager.widget.ViewPager;
|
|
|
|
import androidx.appcompat.app.ActionBar;
|
|
|
|
import androidx.appcompat.app.AppCompatActivity;
|
2017-03-31 20:15:26 +02:00
|
|
|
import android.text.Html;
|
2017-06-15 16:26:48 +02:00
|
|
|
import android.text.Spanned;
|
2017-04-26 21:32:04 +02:00
|
|
|
import android.text.TextUtils;
|
2017-03-31 20:15:26 +02:00
|
|
|
import android.text.method.LinkMovementMethod;
|
2017-07-19 10:26:26 +02:00
|
|
|
import android.text.util.Linkify;
|
2017-09-03 08:04:18 +02:00
|
|
|
import android.util.DisplayMetrics;
|
2015-11-29 13:06:27 +01:00
|
|
|
import android.util.Log;
|
2017-04-09 19:34:00 +02:00
|
|
|
import android.view.LayoutInflater;
|
2017-03-31 20:15:26 +02:00
|
|
|
import android.view.Menu;
|
2017-04-09 19:34:00 +02:00
|
|
|
import android.view.MenuInflater;
|
2015-09-04 02:15:03 +02:00
|
|
|
import android.view.MenuItem;
|
2017-10-14 23:09:49 +02:00
|
|
|
import android.view.MotionEvent;
|
2017-03-31 20:15:26 +02:00
|
|
|
import android.view.View;
|
|
|
|
import android.view.ViewGroup;
|
2018-02-16 12:18:15 +01:00
|
|
|
import android.widget.AdapterView;
|
2017-06-15 16:26:48 +02:00
|
|
|
import android.widget.FrameLayout;
|
2017-03-31 20:15:26 +02:00
|
|
|
import android.widget.ImageView;
|
|
|
|
import android.widget.LinearLayout;
|
|
|
|
import android.widget.RelativeLayout;
|
2017-04-26 21:32:04 +02:00
|
|
|
import android.widget.Spinner;
|
2017-03-31 20:15:26 +02:00
|
|
|
import android.widget.TextView;
|
|
|
|
import android.widget.Toast;
|
2015-09-04 02:15:03 +02:00
|
|
|
|
2017-03-31 20:15:26 +02:00
|
|
|
import com.nostra13.universalimageloader.core.assist.FailReason;
|
2018-03-23 02:11:59 +01:00
|
|
|
import com.nostra13.universalimageloader.core.listener.ImageLoadingListener;
|
2017-03-31 20:15:26 +02:00
|
|
|
import com.nostra13.universalimageloader.core.listener.SimpleImageLoadingListener;
|
|
|
|
|
2016-08-02 21:17:54 +02:00
|
|
|
import org.schabi.newpipe.R;
|
2017-03-31 20:15:26 +02:00
|
|
|
import org.schabi.newpipe.ReCaptchaActivity;
|
|
|
|
import org.schabi.newpipe.download.DownloadDialog;
|
2017-06-17 13:43:09 +02:00
|
|
|
import org.schabi.newpipe.extractor.InfoItem;
|
2017-03-31 20:15:26 +02:00
|
|
|
import org.schabi.newpipe.extractor.NewPipe;
|
2018-12-23 22:07:27 +01:00
|
|
|
import org.schabi.newpipe.extractor.ServiceList;
|
2018-09-23 03:32:19 +02:00
|
|
|
import org.schabi.newpipe.extractor.exceptions.ExtractionException;
|
2017-09-03 08:04:18 +02:00
|
|
|
import org.schabi.newpipe.extractor.exceptions.ParsingException;
|
2018-07-08 17:46:21 +02:00
|
|
|
import org.schabi.newpipe.extractor.services.youtube.extractors.YoutubeStreamExtractor;
|
2017-09-03 08:04:18 +02:00
|
|
|
import org.schabi.newpipe.extractor.stream.AudioStream;
|
2020-02-06 23:54:36 +01:00
|
|
|
import org.schabi.newpipe.extractor.stream.Description;
|
2018-06-19 03:27:30 +02:00
|
|
|
import org.schabi.newpipe.extractor.stream.Stream;
|
2017-09-03 08:04:18 +02:00
|
|
|
import org.schabi.newpipe.extractor.stream.StreamInfo;
|
2018-02-26 00:10:11 +01:00
|
|
|
import org.schabi.newpipe.extractor.stream.StreamType;
|
2017-09-03 08:04:18 +02:00
|
|
|
import org.schabi.newpipe.extractor.stream.VideoStream;
|
|
|
|
import org.schabi.newpipe.fragments.BackPressable;
|
|
|
|
import org.schabi.newpipe.fragments.BaseStateFragment;
|
2019-03-03 13:50:15 +01:00
|
|
|
import org.schabi.newpipe.fragments.EmptyFragment;
|
2018-10-02 17:09:16 +02:00
|
|
|
import org.schabi.newpipe.fragments.list.comments.CommentsFragment;
|
|
|
|
import org.schabi.newpipe.fragments.list.videos.RelatedVideosFragment;
|
2018-09-03 01:22:59 +02:00
|
|
|
import org.schabi.newpipe.local.dialog.PlaylistAppendDialog;
|
|
|
|
import org.schabi.newpipe.local.history.HistoryRecordManager;
|
2017-04-17 06:19:53 +02:00
|
|
|
import org.schabi.newpipe.player.MainVideoPlayer;
|
2017-03-31 20:15:26 +02:00
|
|
|
import org.schabi.newpipe.player.PopupVideoPlayer;
|
2018-04-21 23:10:01 +02:00
|
|
|
import org.schabi.newpipe.player.playqueue.PlayQueue;
|
|
|
|
import org.schabi.newpipe.player.playqueue.SinglePlayQueue;
|
2018-09-03 01:22:59 +02:00
|
|
|
import org.schabi.newpipe.report.ErrorActivity;
|
2017-06-28 07:27:32 +02:00
|
|
|
import org.schabi.newpipe.report.UserAction;
|
2017-10-08 21:04:37 +02:00
|
|
|
import org.schabi.newpipe.util.Constants;
|
2017-09-03 08:04:18 +02:00
|
|
|
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.InfoCache;
|
2019-04-25 20:47:39 +02:00
|
|
|
import org.schabi.newpipe.util.KoreUtil;
|
2017-09-03 08:04:18 +02:00
|
|
|
import org.schabi.newpipe.util.ListHelper;
|
2017-05-08 15:33:26 +02:00
|
|
|
import org.schabi.newpipe.util.Localization;
|
2017-04-09 19:34:00 +02:00
|
|
|
import org.schabi.newpipe.util.NavigationHelper;
|
2017-03-31 20:15:26 +02:00
|
|
|
import org.schabi.newpipe.util.PermissionHelper;
|
2019-04-06 20:17:04 +02:00
|
|
|
import org.schabi.newpipe.util.ShareUtils;
|
2018-09-03 01:22:59 +02:00
|
|
|
import org.schabi.newpipe.util.StreamItemAdapter;
|
|
|
|
import org.schabi.newpipe.util.StreamItemAdapter.StreamSizeWrapper;
|
2019-04-13 09:31:32 +02:00
|
|
|
import org.schabi.newpipe.views.AnimatedProgressBar;
|
2015-11-17 00:32:00 +01:00
|
|
|
|
2017-04-09 19:34:00 +02:00
|
|
|
import java.io.Serializable;
|
2017-09-03 08:04:18 +02:00
|
|
|
import java.util.Collection;
|
|
|
|
import java.util.LinkedList;
|
2018-04-08 13:08:19 +02:00
|
|
|
import java.util.List;
|
2019-04-13 09:31:32 +02:00
|
|
|
import java.util.concurrent.TimeUnit;
|
2017-09-03 08:04:18 +02:00
|
|
|
|
|
|
|
import icepick.State;
|
2020-02-08 09:56:37 +01:00
|
|
|
import io.noties.markwon.Markwon;
|
|
|
|
import io.noties.markwon.linkify.LinkifyPlugin;
|
2017-09-03 08:04:18 +02:00
|
|
|
import io.reactivex.Single;
|
|
|
|
import io.reactivex.android.schedulers.AndroidSchedulers;
|
|
|
|
import io.reactivex.disposables.CompositeDisposable;
|
|
|
|
import io.reactivex.disposables.Disposable;
|
|
|
|
import io.reactivex.schedulers.Schedulers;
|
2017-04-09 19:34:00 +02:00
|
|
|
|
2019-02-15 20:53:26 +01:00
|
|
|
import static org.schabi.newpipe.extractor.StreamingService.ServiceInfo.MediaCapability.COMMENTS;
|
2017-05-08 15:33:26 +02:00
|
|
|
import static org.schabi.newpipe.util.AnimationUtils.animateView;
|
|
|
|
|
2018-02-16 11:31:25 +01:00
|
|
|
public class VideoDetailFragment
|
|
|
|
extends BaseStateFragment<StreamInfo>
|
|
|
|
implements BackPressable,
|
|
|
|
SharedPreferences.OnSharedPreferenceChangeListener,
|
|
|
|
View.OnClickListener,
|
|
|
|
View.OnLongClickListener {
|
2017-09-03 08:04:18 +02:00
|
|
|
public static final String AUTO_PLAY = "auto_play";
|
2017-03-31 20:15:26 +02:00
|
|
|
|
2017-09-03 08:04:18 +02:00
|
|
|
private int updateFlags = 0;
|
2017-04-12 08:07:15 +02:00
|
|
|
private static final int RELATED_STREAMS_UPDATE_FLAG = 0x1;
|
|
|
|
private static final int RESOLUTIONS_MENU_UPDATE_FLAG = 0x2;
|
2017-05-09 03:23:27 +02:00
|
|
|
private static final int TOOLBAR_ITEMS_UPDATE_FLAG = 0x4;
|
2019-04-13 09:31:32 +02:00
|
|
|
private static final int COMMENTS_UPDATE_FLAG = 0x8;
|
2017-03-31 20:15:26 +02:00
|
|
|
|
|
|
|
private boolean autoPlayEnabled;
|
|
|
|
private boolean showRelatedStreams;
|
2018-09-03 01:22:59 +02:00
|
|
|
private boolean showComments;
|
2019-03-24 02:01:28 +01:00
|
|
|
private String selectedTabTag;
|
2017-03-31 20:15:26 +02:00
|
|
|
|
2018-09-03 01:22:59 +02:00
|
|
|
@State
|
|
|
|
protected int serviceId = Constants.NO_SERVICE_ID;
|
|
|
|
@State
|
|
|
|
protected String name;
|
|
|
|
@State
|
|
|
|
protected String url;
|
2017-09-03 08:04:18 +02:00
|
|
|
|
|
|
|
private StreamInfo currentInfo;
|
|
|
|
private Disposable currentWorker;
|
2018-09-03 01:22:59 +02:00
|
|
|
@NonNull
|
|
|
|
private CompositeDisposable disposables = new CompositeDisposable();
|
2019-04-13 09:31:32 +02:00
|
|
|
@Nullable
|
|
|
|
private Disposable positionSubscriber = null;
|
2017-06-28 03:39:33 +02:00
|
|
|
|
2018-04-08 13:08:19 +02:00
|
|
|
private List<VideoStream> sortedVideoStreams;
|
|
|
|
private int selectedVideoStreamIndex = -1;
|
2018-02-16 12:18:15 +01:00
|
|
|
|
2017-03-31 20:15:26 +02:00
|
|
|
/*//////////////////////////////////////////////////////////////////////////
|
|
|
|
// Views
|
|
|
|
//////////////////////////////////////////////////////////////////////////*/
|
2018-03-10 17:16:51 +01:00
|
|
|
|
2018-02-16 12:18:15 +01:00
|
|
|
private Menu menu;
|
2017-03-31 20:15:26 +02:00
|
|
|
|
2017-04-26 21:32:04 +02:00
|
|
|
private Spinner spinnerToolbar;
|
2017-03-31 20:15:26 +02:00
|
|
|
|
2017-06-15 16:26:48 +02:00
|
|
|
private LinearLayout contentRootLayoutHiding;
|
2017-03-31 20:15:26 +02:00
|
|
|
|
2017-06-15 16:26:48 +02:00
|
|
|
private View thumbnailBackgroundButton;
|
2017-03-31 20:15:26 +02:00
|
|
|
private ImageView thumbnailImageView;
|
|
|
|
private ImageView thumbnailPlayButton;
|
2019-04-13 09:31:32 +02:00
|
|
|
private AnimatedProgressBar positionView;
|
2015-09-04 02:15:03 +02:00
|
|
|
|
2017-03-31 20:15:26 +02:00
|
|
|
private View videoTitleRoot;
|
|
|
|
private TextView videoTitleTextView;
|
|
|
|
private ImageView videoTitleToggleArrow;
|
|
|
|
private TextView videoCountView;
|
|
|
|
|
2017-04-26 21:32:04 +02:00
|
|
|
private TextView detailControlsBackground;
|
|
|
|
private TextView detailControlsPopup;
|
2018-01-17 23:32:09 +01:00
|
|
|
private TextView detailControlsAddToPlaylist;
|
2018-02-11 21:34:32 +01:00
|
|
|
private TextView detailControlsDownload;
|
2017-10-14 23:09:49 +02:00
|
|
|
private TextView appendControlsDetail;
|
2018-03-10 17:16:51 +01:00
|
|
|
private TextView detailDurationView;
|
2019-04-13 09:31:32 +02:00
|
|
|
private TextView detailPositionView;
|
2017-04-26 21:32:04 +02:00
|
|
|
|
2017-06-15 16:26:48 +02:00
|
|
|
private LinearLayout videoDescriptionRootLayout;
|
2017-03-31 20:15:26 +02:00
|
|
|
private TextView videoUploadDateView;
|
|
|
|
private TextView videoDescriptionView;
|
|
|
|
|
2017-04-28 05:58:50 +02:00
|
|
|
private View uploaderRootLayout;
|
2017-03-31 20:15:26 +02:00
|
|
|
private TextView uploaderTextView;
|
|
|
|
private ImageView uploaderThumb;
|
|
|
|
|
|
|
|
private TextView thumbsUpTextView;
|
|
|
|
private ImageView thumbsUpImageView;
|
|
|
|
private TextView thumbsDownTextView;
|
|
|
|
private ImageView thumbsDownImageView;
|
|
|
|
private TextView thumbsDisabledTextView;
|
|
|
|
|
2018-10-02 17:09:16 +02:00
|
|
|
private static final String COMMENTS_TAB_TAG = "COMMENTS";
|
|
|
|
private static final String RELATED_TAB_TAG = "NEXT VIDEO";
|
2019-03-03 13:50:15 +01:00
|
|
|
private static final String EMPTY_TAB_TAG = "EMPTY TAB";
|
2018-09-03 01:22:59 +02:00
|
|
|
|
2018-10-02 17:09:16 +02:00
|
|
|
private AppBarLayout appBarLayout;
|
|
|
|
private ViewPager viewPager;
|
|
|
|
private TabAdaptor pageAdapter;
|
|
|
|
private TabLayout tabLayout;
|
2018-12-08 22:51:55 +01:00
|
|
|
private FrameLayout relatedStreamsLayout;
|
2018-09-03 01:22:59 +02:00
|
|
|
|
2018-02-16 12:18:15 +01:00
|
|
|
|
2017-04-09 19:34:00 +02:00
|
|
|
/*////////////////////////////////////////////////////////////////////////*/
|
|
|
|
|
2017-09-03 08:04:18 +02:00
|
|
|
public static VideoDetailFragment getInstance(int serviceId, String videoUrl, String name) {
|
|
|
|
VideoDetailFragment instance = new VideoDetailFragment();
|
|
|
|
instance.setInitialData(serviceId, videoUrl, name);
|
2017-04-09 19:34:00 +02:00
|
|
|
return instance;
|
|
|
|
}
|
|
|
|
|
2017-03-31 20:15:26 +02:00
|
|
|
/*//////////////////////////////////////////////////////////////////////////
|
2017-04-09 19:34:00 +02:00
|
|
|
// Fragment's Lifecycle
|
2017-03-31 20:15:26 +02:00
|
|
|
//////////////////////////////////////////////////////////////////////////*/
|
|
|
|
|
|
|
|
@Override
|
2018-09-03 01:22:59 +02:00
|
|
|
public void
|
|
|
|
onCreate(Bundle savedInstanceState) {
|
2015-09-04 02:15:03 +02:00
|
|
|
super.onCreate(savedInstanceState);
|
2017-09-03 08:04:18 +02:00
|
|
|
setHasOptionsMenu(true);
|
2017-03-31 20:15:26 +02:00
|
|
|
|
2018-02-16 11:31:25 +01:00
|
|
|
showRelatedStreams = PreferenceManager.getDefaultSharedPreferences(activity)
|
|
|
|
.getBoolean(getString(R.string.show_next_video_key), true);
|
2018-09-03 01:22:59 +02:00
|
|
|
|
|
|
|
showComments = PreferenceManager.getDefaultSharedPreferences(activity)
|
2018-10-02 17:26:14 +02:00
|
|
|
.getBoolean(getString(R.string.show_comments_key), true);
|
2018-09-03 01:22:59 +02:00
|
|
|
|
2019-03-24 02:01:28 +01:00
|
|
|
selectedTabTag = PreferenceManager.getDefaultSharedPreferences(activity)
|
|
|
|
.getString(getString(R.string.stream_info_selected_tab_key), COMMENTS_TAB_TAG);
|
|
|
|
|
2018-02-16 11:31:25 +01:00
|
|
|
PreferenceManager.getDefaultSharedPreferences(activity)
|
|
|
|
.registerOnSharedPreferenceChangeListener(this);
|
2017-04-09 19:34:00 +02:00
|
|
|
}
|
2015-09-04 02:15:03 +02:00
|
|
|
|
2017-04-09 19:34:00 +02:00
|
|
|
@Override
|
2018-04-06 09:35:44 +02:00
|
|
|
public View onCreateView(@NonNull LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
|
2017-04-09 19:34:00 +02:00
|
|
|
return inflater.inflate(R.layout.fragment_video_detail, container, false);
|
|
|
|
}
|
2017-03-31 20:15:26 +02:00
|
|
|
|
2017-04-09 19:34:00 +02:00
|
|
|
@Override
|
2017-09-03 08:04:18 +02:00
|
|
|
public void onPause() {
|
|
|
|
super.onPause();
|
|
|
|
if (currentWorker != null) currentWorker.dispose();
|
2019-03-24 02:01:28 +01:00
|
|
|
PreferenceManager.getDefaultSharedPreferences(getContext())
|
|
|
|
.edit()
|
|
|
|
.putString(getString(R.string.stream_info_selected_tab_key), pageAdapter.getItemTitle(viewPager.getCurrentItem()))
|
|
|
|
.apply();
|
2017-08-12 06:50:25 +02:00
|
|
|
}
|
|
|
|
|
2017-04-26 21:32:04 +02:00
|
|
|
@Override
|
|
|
|
public void onResume() {
|
|
|
|
super.onResume();
|
|
|
|
|
|
|
|
if (updateFlags != 0) {
|
2017-09-03 08:04:18 +02:00
|
|
|
if (!isLoading.get() && currentInfo != null) {
|
2018-10-02 17:09:16 +02:00
|
|
|
if ((updateFlags & RELATED_STREAMS_UPDATE_FLAG) != 0) startLoading(false);
|
2018-02-16 12:18:15 +01:00
|
|
|
if ((updateFlags & RESOLUTIONS_MENU_UPDATE_FLAG) != 0) setupActionBar(currentInfo);
|
2018-10-02 17:09:16 +02:00
|
|
|
if ((updateFlags & COMMENTS_UPDATE_FLAG) != 0) startLoading(false);
|
2017-04-26 21:32:04 +02:00
|
|
|
}
|
2017-05-09 03:23:27 +02:00
|
|
|
|
2018-02-16 11:31:25 +01:00
|
|
|
if ((updateFlags & TOOLBAR_ITEMS_UPDATE_FLAG) != 0
|
2018-02-16 12:18:15 +01:00
|
|
|
&& menu != null) {
|
|
|
|
updateMenuItemVisibility();
|
2018-02-16 11:31:25 +01:00
|
|
|
}
|
2018-09-03 01:22:59 +02:00
|
|
|
|
2017-04-26 21:32:04 +02:00
|
|
|
updateFlags = 0;
|
|
|
|
}
|
|
|
|
|
2017-09-03 08:04:18 +02:00
|
|
|
// Check if it was loading when the fragment was stopped/paused,
|
|
|
|
if (wasLoading.getAndSet(false)) {
|
|
|
|
selectAndLoadVideo(serviceId, url, name);
|
2019-04-13 09:31:32 +02:00
|
|
|
} else if (currentInfo != null) {
|
|
|
|
updateProgressInfo(currentInfo);
|
2017-09-03 08:04:18 +02:00
|
|
|
}
|
2017-04-26 21:32:04 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
@Override
|
|
|
|
public void onDestroy() {
|
|
|
|
super.onDestroy();
|
2018-02-16 11:31:25 +01:00
|
|
|
PreferenceManager.getDefaultSharedPreferences(activity)
|
|
|
|
.unregisterOnSharedPreferenceChangeListener(this);
|
2017-09-03 08:04:18 +02:00
|
|
|
|
2019-04-13 09:31:32 +02:00
|
|
|
if (positionSubscriber != null) positionSubscriber.dispose();
|
2017-09-03 08:04:18 +02:00
|
|
|
if (currentWorker != null) currentWorker.dispose();
|
|
|
|
if (disposables != null) disposables.clear();
|
2019-04-13 09:31:32 +02:00
|
|
|
positionSubscriber = null;
|
2017-09-03 08:04:18 +02:00
|
|
|
currentWorker = null;
|
|
|
|
disposables = null;
|
2017-03-31 20:15:26 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
@Override
|
2017-04-09 19:34:00 +02:00
|
|
|
public void onDestroyView() {
|
2017-04-26 21:32:04 +02:00
|
|
|
if (DEBUG) Log.d(TAG, "onDestroyView() called");
|
|
|
|
spinnerToolbar.setOnItemSelectedListener(null);
|
2017-09-03 08:04:18 +02:00
|
|
|
spinnerToolbar.setAdapter(null);
|
2017-04-26 21:32:04 +02:00
|
|
|
super.onDestroyView();
|
2017-04-09 19:34:00 +02:00
|
|
|
}
|
|
|
|
|
2017-03-31 20:15:26 +02:00
|
|
|
@Override
|
|
|
|
public void onActivityResult(int requestCode, int resultCode, Intent data) {
|
|
|
|
super.onActivityResult(requestCode, resultCode, data);
|
|
|
|
switch (requestCode) {
|
|
|
|
case ReCaptchaActivity.RECAPTCHA_REQUEST:
|
2017-04-09 19:34:00 +02:00
|
|
|
if (resultCode == Activity.RESULT_OK) {
|
2017-09-03 08:04:18 +02:00
|
|
|
NavigationHelper.openVideoDetailFragment(getFragmentManager(), serviceId, url, name);
|
2017-03-31 20:15:26 +02:00
|
|
|
} else Log.e(TAG, "ReCaptcha failed");
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
Log.e(TAG, "Request code from activity not supported [" + requestCode + "]");
|
|
|
|
break;
|
|
|
|
}
|
2015-10-29 17:56:35 +01:00
|
|
|
}
|
|
|
|
|
2016-01-01 23:04:29 +01:00
|
|
|
@Override
|
2017-03-31 20:15:26 +02:00
|
|
|
public void onSharedPreferenceChanged(SharedPreferences sharedPreferences, String key) {
|
|
|
|
if (key.equals(getString(R.string.show_next_video_key))) {
|
|
|
|
showRelatedStreams = sharedPreferences.getBoolean(key, true);
|
2017-04-12 08:07:15 +02:00
|
|
|
updateFlags |= RELATED_STREAMS_UPDATE_FLAG;
|
2017-09-03 08:04:18 +02:00
|
|
|
} else if (key.equals(getString(R.string.default_video_format_key))
|
2017-04-12 08:07:15 +02:00
|
|
|
|| key.equals(getString(R.string.default_resolution_key))
|
2017-05-15 05:57:57 +02:00
|
|
|
|| key.equals(getString(R.string.show_higher_resolutions_key))
|
|
|
|
|| key.equals(getString(R.string.use_external_video_player_key))) {
|
2017-04-12 08:07:15 +02:00
|
|
|
updateFlags |= RESOLUTIONS_MENU_UPDATE_FLAG;
|
2017-05-09 03:23:27 +02:00
|
|
|
} else if (key.equals(getString(R.string.show_play_with_kodi_key))) {
|
|
|
|
updateFlags |= TOOLBAR_ITEMS_UPDATE_FLAG;
|
2018-10-02 17:26:14 +02:00
|
|
|
} else if (key.equals(getString(R.string.show_comments_key))) {
|
2018-09-03 01:22:59 +02:00
|
|
|
showComments = sharedPreferences.getBoolean(key, true);
|
|
|
|
updateFlags |= COMMENTS_UPDATE_FLAG;
|
2017-03-31 20:15:26 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-09-03 08:04:18 +02:00
|
|
|
/*//////////////////////////////////////////////////////////////////////////
|
|
|
|
// State Saving
|
|
|
|
//////////////////////////////////////////////////////////////////////////*/
|
|
|
|
|
|
|
|
private static final String INFO_KEY = "info_key";
|
|
|
|
private static final String STACK_KEY = "stack_key";
|
|
|
|
|
|
|
|
@Override
|
|
|
|
public void onSaveInstanceState(Bundle outState) {
|
|
|
|
super.onSaveInstanceState(outState);
|
|
|
|
|
|
|
|
// Check if the next video label and video is visible,
|
|
|
|
// if it is, include the two elements in the next check
|
2017-12-08 15:05:08 +01:00
|
|
|
int nextCount = currentInfo != null && currentInfo.getNextVideo() != null ? 2 : 0;
|
2017-09-03 08:04:18 +02:00
|
|
|
|
|
|
|
if (!isLoading.get() && currentInfo != null && isVisible()) {
|
2018-09-19 01:43:55 +02:00
|
|
|
outState.putSerializable(INFO_KEY, currentInfo);
|
2017-09-03 08:04:18 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
outState.putSerializable(STACK_KEY, stack);
|
|
|
|
}
|
|
|
|
|
|
|
|
@Override
|
|
|
|
protected void onRestoreInstanceState(@NonNull Bundle savedState) {
|
|
|
|
super.onRestoreInstanceState(savedState);
|
|
|
|
|
|
|
|
Serializable serializable = savedState.getSerializable(INFO_KEY);
|
|
|
|
if (serializable instanceof StreamInfo) {
|
|
|
|
//noinspection unchecked
|
|
|
|
currentInfo = (StreamInfo) serializable;
|
2018-09-23 03:32:19 +02:00
|
|
|
InfoCache.getInstance().putInfo(serviceId, url, currentInfo, InfoItem.InfoType.STREAM);
|
2017-09-03 08:04:18 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
serializable = savedState.getSerializable(STACK_KEY);
|
|
|
|
if (serializable instanceof Collection) {
|
|
|
|
//noinspection unchecked
|
|
|
|
stack.addAll((Collection<? extends StackItem>) serializable);
|
|
|
|
}
|
2018-09-23 03:32:19 +02:00
|
|
|
|
2017-09-03 08:04:18 +02:00
|
|
|
}
|
|
|
|
|
2017-04-26 21:32:04 +02:00
|
|
|
/*//////////////////////////////////////////////////////////////////////////
|
|
|
|
// OnClick
|
|
|
|
//////////////////////////////////////////////////////////////////////////*/
|
|
|
|
|
|
|
|
@Override
|
|
|
|
public void onClick(View v) {
|
2017-09-03 08:04:18 +02:00
|
|
|
if (isLoading.get() || currentInfo == null) return;
|
2017-04-26 21:32:04 +02:00
|
|
|
|
|
|
|
switch (v.getId()) {
|
|
|
|
case R.id.detail_controls_background:
|
2017-10-13 02:02:07 +02:00
|
|
|
openBackgroundPlayer(false);
|
2017-04-26 21:32:04 +02:00
|
|
|
break;
|
|
|
|
case R.id.detail_controls_popup:
|
2017-10-13 02:02:07 +02:00
|
|
|
openPopupPlayer(false);
|
2017-04-26 21:32:04 +02:00
|
|
|
break;
|
2018-01-17 23:32:09 +01:00
|
|
|
case R.id.detail_controls_playlist_append:
|
|
|
|
if (getFragmentManager() != null && currentInfo != null) {
|
2018-01-22 04:32:49 +01:00
|
|
|
PlaylistAppendDialog.fromStreamInfo(currentInfo)
|
|
|
|
.show(getFragmentManager(), TAG);
|
2018-01-17 23:32:09 +01:00
|
|
|
}
|
|
|
|
break;
|
2018-02-11 21:34:32 +01:00
|
|
|
case R.id.detail_controls_download:
|
2019-08-15 04:00:11 +02:00
|
|
|
if (PermissionHelper.checkStoragePermissions(activity,
|
|
|
|
PermissionHelper.DOWNLOAD_DIALOG_REQUEST_CODE)) {
|
|
|
|
this.openDownloadDialog();
|
|
|
|
}
|
2018-02-11 21:34:32 +01:00
|
|
|
break;
|
2017-06-15 16:26:48 +02:00
|
|
|
case R.id.detail_uploader_root_layout:
|
2017-12-08 15:05:08 +01:00
|
|
|
if (TextUtils.isEmpty(currentInfo.getUploaderUrl())) {
|
2017-06-15 16:26:48 +02:00
|
|
|
Log.w(TAG, "Can't open channel because we got no channel URL");
|
|
|
|
} else {
|
2018-07-08 17:46:21 +02:00
|
|
|
try {
|
2018-09-23 20:12:23 +02:00
|
|
|
NavigationHelper.openChannelFragment(
|
|
|
|
getFragmentManager(),
|
|
|
|
currentInfo.getServiceId(),
|
|
|
|
currentInfo.getUploaderUrl(),
|
|
|
|
currentInfo.getUploaderName());
|
2018-07-08 17:46:21 +02:00
|
|
|
} catch (Exception e) {
|
|
|
|
ErrorActivity.reportUiError((AppCompatActivity) getActivity(), e);
|
2018-09-23 20:12:23 +02:00
|
|
|
}
|
2017-06-15 16:26:48 +02:00
|
|
|
}
|
2017-04-26 21:32:04 +02:00
|
|
|
break;
|
2017-06-15 16:26:48 +02:00
|
|
|
case R.id.detail_thumbnail_root_layout:
|
2018-03-18 16:37:49 +01:00
|
|
|
if (currentInfo.getVideoStreams().isEmpty()
|
|
|
|
&& currentInfo.getVideoOnlyStreams().isEmpty()) {
|
2017-11-11 13:18:26 +01:00
|
|
|
openBackgroundPlayer(false);
|
2017-09-14 10:49:39 +02:00
|
|
|
} else {
|
|
|
|
openVideoPlayer();
|
|
|
|
}
|
2017-04-26 21:32:04 +02:00
|
|
|
break;
|
|
|
|
case R.id.detail_title_root_layout:
|
|
|
|
toggleTitleAndDescription();
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-10-13 02:02:07 +02:00
|
|
|
@Override
|
|
|
|
public boolean onLongClick(View v) {
|
|
|
|
if (isLoading.get() || currentInfo == null) return false;
|
|
|
|
|
|
|
|
switch (v.getId()) {
|
|
|
|
case R.id.detail_controls_background:
|
|
|
|
openBackgroundPlayer(true);
|
|
|
|
break;
|
|
|
|
case R.id.detail_controls_popup:
|
|
|
|
openPopupPlayer(true);
|
|
|
|
break;
|
2018-04-08 21:53:15 +02:00
|
|
|
case R.id.detail_controls_download:
|
|
|
|
NavigationHelper.openDownloads(getActivity());
|
|
|
|
break;
|
2017-10-13 02:02:07 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2017-04-26 21:32:04 +02:00
|
|
|
private void toggleTitleAndDescription() {
|
2018-12-08 22:51:55 +01:00
|
|
|
if (videoDescriptionRootLayout.getVisibility() == View.VISIBLE) {
|
|
|
|
videoTitleTextView.setMaxLines(1);
|
|
|
|
videoDescriptionRootLayout.setVisibility(View.GONE);
|
|
|
|
videoTitleToggleArrow.setImageResource(R.drawable.arrow_down);
|
|
|
|
} else {
|
|
|
|
videoTitleTextView.setMaxLines(10);
|
|
|
|
videoDescriptionRootLayout.setVisibility(View.VISIBLE);
|
|
|
|
videoTitleToggleArrow.setImageResource(R.drawable.arrow_up);
|
2017-04-26 21:32:04 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-03-31 20:15:26 +02:00
|
|
|
/*//////////////////////////////////////////////////////////////////////////
|
|
|
|
// Init
|
|
|
|
//////////////////////////////////////////////////////////////////////////*/
|
|
|
|
|
2017-09-03 08:04:18 +02:00
|
|
|
@Override
|
2017-04-26 21:32:04 +02:00
|
|
|
protected void initViews(View rootView, Bundle savedInstanceState) {
|
|
|
|
super.initViews(rootView, savedInstanceState);
|
2018-03-10 17:16:51 +01:00
|
|
|
spinnerToolbar = activity.findViewById(R.id.toolbar).findViewById(R.id.toolbar_spinner);
|
2017-03-31 20:15:26 +02:00
|
|
|
|
2017-06-15 16:26:48 +02:00
|
|
|
thumbnailBackgroundButton = rootView.findViewById(R.id.detail_thumbnail_root_layout);
|
2017-09-03 08:04:18 +02:00
|
|
|
thumbnailImageView = rootView.findViewById(R.id.detail_thumbnail_image_view);
|
|
|
|
thumbnailPlayButton = rootView.findViewById(R.id.detail_thumbnail_play_button);
|
2017-03-31 20:15:26 +02:00
|
|
|
|
2017-09-03 08:04:18 +02:00
|
|
|
contentRootLayoutHiding = rootView.findViewById(R.id.detail_content_root_hiding);
|
2017-03-31 20:15:26 +02:00
|
|
|
|
2017-04-09 19:34:00 +02:00
|
|
|
videoTitleRoot = rootView.findViewById(R.id.detail_title_root_layout);
|
2017-09-03 08:04:18 +02:00
|
|
|
videoTitleTextView = rootView.findViewById(R.id.detail_video_title_view);
|
|
|
|
videoTitleToggleArrow = rootView.findViewById(R.id.detail_toggle_description_view);
|
|
|
|
videoCountView = rootView.findViewById(R.id.detail_view_count_view);
|
2019-04-13 09:31:32 +02:00
|
|
|
positionView = rootView.findViewById(R.id.position_view);
|
2017-03-31 20:15:26 +02:00
|
|
|
|
2017-09-03 08:04:18 +02:00
|
|
|
detailControlsBackground = rootView.findViewById(R.id.detail_controls_background);
|
|
|
|
detailControlsPopup = rootView.findViewById(R.id.detail_controls_popup);
|
2018-01-17 23:32:09 +01:00
|
|
|
detailControlsAddToPlaylist = rootView.findViewById(R.id.detail_controls_playlist_append);
|
2018-02-11 21:34:32 +01:00
|
|
|
detailControlsDownload = rootView.findViewById(R.id.detail_controls_download);
|
2017-10-14 23:09:49 +02:00
|
|
|
appendControlsDetail = rootView.findViewById(R.id.touch_append_detail);
|
2018-03-10 17:16:51 +01:00
|
|
|
detailDurationView = rootView.findViewById(R.id.detail_duration_view);
|
2019-04-13 09:31:32 +02:00
|
|
|
detailPositionView = rootView.findViewById(R.id.detail_position_view);
|
2017-04-26 21:32:04 +02:00
|
|
|
|
2017-09-03 08:04:18 +02:00
|
|
|
videoDescriptionRootLayout = rootView.findViewById(R.id.detail_description_root_layout);
|
|
|
|
videoUploadDateView = rootView.findViewById(R.id.detail_upload_date_view);
|
|
|
|
videoDescriptionView = rootView.findViewById(R.id.detail_description_view);
|
|
|
|
videoDescriptionView.setMovementMethod(LinkMovementMethod.getInstance());
|
2017-03-31 20:15:26 +02:00
|
|
|
|
2017-09-03 08:04:18 +02:00
|
|
|
thumbsUpTextView = rootView.findViewById(R.id.detail_thumbs_up_count_view);
|
|
|
|
thumbsUpImageView = rootView.findViewById(R.id.detail_thumbs_up_img_view);
|
|
|
|
thumbsDownTextView = rootView.findViewById(R.id.detail_thumbs_down_count_view);
|
|
|
|
thumbsDownImageView = rootView.findViewById(R.id.detail_thumbs_down_img_view);
|
|
|
|
thumbsDisabledTextView = rootView.findViewById(R.id.detail_thumbs_disabled_view);
|
2017-03-31 20:15:26 +02:00
|
|
|
|
2017-04-28 05:58:50 +02:00
|
|
|
uploaderRootLayout = rootView.findViewById(R.id.detail_uploader_root_layout);
|
2017-09-03 08:04:18 +02:00
|
|
|
uploaderTextView = rootView.findViewById(R.id.detail_uploader_text_view);
|
|
|
|
uploaderThumb = rootView.findViewById(R.id.detail_uploader_thumbnail_view);
|
2017-03-31 20:15:26 +02:00
|
|
|
|
2018-10-02 17:09:16 +02:00
|
|
|
appBarLayout = rootView.findViewById(R.id.appbarlayout);
|
|
|
|
viewPager = rootView.findViewById(R.id.viewpager);
|
|
|
|
pageAdapter = new TabAdaptor(getChildFragmentManager());
|
|
|
|
viewPager.setAdapter(pageAdapter);
|
|
|
|
tabLayout = rootView.findViewById(R.id.tablayout);
|
|
|
|
tabLayout.setupWithViewPager(viewPager);
|
2018-09-23 03:32:19 +02:00
|
|
|
|
2018-12-08 22:51:55 +01:00
|
|
|
relatedStreamsLayout = rootView.findViewById(R.id.relatedStreamsLayout);
|
|
|
|
|
2018-09-23 03:32:19 +02:00
|
|
|
setHeightThumbnail();
|
|
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
2017-09-03 08:04:18 +02:00
|
|
|
@Override
|
2017-04-26 21:32:04 +02:00
|
|
|
protected void initListeners() {
|
|
|
|
super.initListeners();
|
2017-03-31 20:15:26 +02:00
|
|
|
|
2017-04-26 21:32:04 +02:00
|
|
|
videoTitleRoot.setOnClickListener(this);
|
2017-06-15 16:26:48 +02:00
|
|
|
uploaderRootLayout.setOnClickListener(this);
|
2017-04-26 21:32:04 +02:00
|
|
|
thumbnailBackgroundButton.setOnClickListener(this);
|
|
|
|
detailControlsBackground.setOnClickListener(this);
|
|
|
|
detailControlsPopup.setOnClickListener(this);
|
2018-01-17 23:32:09 +01:00
|
|
|
detailControlsAddToPlaylist.setOnClickListener(this);
|
2018-02-11 21:34:32 +01:00
|
|
|
detailControlsDownload.setOnClickListener(this);
|
2018-04-08 21:53:15 +02:00
|
|
|
detailControlsDownload.setOnLongClickListener(this);
|
2017-10-13 02:02:07 +02:00
|
|
|
|
|
|
|
detailControlsBackground.setLongClickable(true);
|
|
|
|
detailControlsPopup.setLongClickable(true);
|
|
|
|
detailControlsBackground.setOnLongClickListener(this);
|
|
|
|
detailControlsPopup.setOnLongClickListener(this);
|
2017-10-14 23:09:49 +02:00
|
|
|
detailControlsBackground.setOnTouchListener(getOnControlsTouchListener());
|
|
|
|
detailControlsPopup.setOnTouchListener(getOnControlsTouchListener());
|
|
|
|
}
|
|
|
|
|
|
|
|
private View.OnTouchListener getOnControlsTouchListener() {
|
2018-02-11 21:34:32 +01:00
|
|
|
return (View view, MotionEvent motionEvent) -> {
|
2018-02-16 11:31:25 +01:00
|
|
|
if (!PreferenceManager.getDefaultSharedPreferences(activity)
|
|
|
|
.getBoolean(getString(R.string.show_hold_to_append_key), true)) {
|
|
|
|
return false;
|
|
|
|
}
|
2018-02-11 21:34:32 +01:00
|
|
|
|
|
|
|
if (motionEvent.getAction() == MotionEvent.ACTION_DOWN) {
|
2018-02-12 00:43:12 +01:00
|
|
|
animateView(appendControlsDetail, true, 250, 0, () ->
|
|
|
|
animateView(appendControlsDetail, false, 1500, 1000));
|
2017-10-14 23:09:49 +02:00
|
|
|
}
|
2018-02-11 21:34:32 +01:00
|
|
|
return false;
|
2017-10-14 23:09:49 +02:00
|
|
|
};
|
2017-03-31 20:15:26 +02:00
|
|
|
}
|
|
|
|
|
2018-03-23 02:11:59 +01:00
|
|
|
private void initThumbnailViews(@NonNull StreamInfo info) {
|
2017-09-03 08:04:18 +02:00
|
|
|
thumbnailImageView.setImageResource(R.drawable.dummy_thumbnail_dark);
|
2017-12-08 15:05:08 +01:00
|
|
|
if (!TextUtils.isEmpty(info.getThumbnailUrl())) {
|
2018-03-23 02:11:59 +01:00
|
|
|
final String infoServiceName = NewPipe.getNameOfService(info.getServiceId());
|
|
|
|
final ImageLoadingListener onFailListener = new SimpleImageLoadingListener() {
|
2017-04-26 21:32:04 +02:00
|
|
|
@Override
|
|
|
|
public void onLoadingFailed(String imageUri, View view, FailReason failReason) {
|
2018-03-23 02:11:59 +01:00
|
|
|
showSnackBarError(failReason.getCause(), UserAction.LOAD_IMAGE,
|
|
|
|
infoServiceName, imageUri, R.string.could_not_load_thumbnails);
|
2017-04-26 21:32:04 +02:00
|
|
|
}
|
2018-03-23 02:11:59 +01:00
|
|
|
};
|
|
|
|
|
|
|
|
imageLoader.displayImage(info.getThumbnailUrl(), thumbnailImageView,
|
|
|
|
ImageDisplayConstants.DISPLAY_THUMBNAIL_OPTIONS, onFailListener);
|
2017-09-03 08:04:18 +02:00
|
|
|
}
|
2018-02-16 11:31:25 +01:00
|
|
|
|
2017-12-22 16:53:43 +01:00
|
|
|
if (!TextUtils.isEmpty(info.getUploaderAvatarUrl())) {
|
2018-03-16 04:07:20 +01:00
|
|
|
imageLoader.displayImage(info.getUploaderAvatarUrl(), uploaderThumb,
|
|
|
|
ImageDisplayConstants.DISPLAY_AVATAR_OPTIONS);
|
2017-03-31 20:15:26 +02:00
|
|
|
}
|
2016-01-01 23:04:29 +01:00
|
|
|
}
|
|
|
|
|
2017-03-31 20:15:26 +02:00
|
|
|
|
|
|
|
/*//////////////////////////////////////////////////////////////////////////
|
|
|
|
// Menu
|
|
|
|
//////////////////////////////////////////////////////////////////////////*/
|
|
|
|
|
2015-10-29 17:56:35 +01:00
|
|
|
@Override
|
2017-04-09 19:34:00 +02:00
|
|
|
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
|
2018-02-16 12:18:15 +01:00
|
|
|
this.menu = menu;
|
|
|
|
|
|
|
|
// CAUTION set item properties programmatically otherwise it would not be accepted by
|
|
|
|
// appcompat itemsinflater.inflate(R.menu.videoitem_detail, menu);
|
|
|
|
|
|
|
|
inflater.inflate(R.menu.video_detail_menu, menu);
|
|
|
|
|
|
|
|
updateMenuItemVisibility();
|
|
|
|
|
2017-04-09 19:34:00 +02:00
|
|
|
ActionBar supportActionBar = activity.getSupportActionBar();
|
|
|
|
if (supportActionBar != null) {
|
|
|
|
supportActionBar.setDisplayHomeAsUpEnabled(true);
|
|
|
|
supportActionBar.setDisplayShowTitleEnabled(false);
|
|
|
|
}
|
2015-09-04 02:15:03 +02:00
|
|
|
}
|
|
|
|
|
2018-02-16 12:18:15 +01:00
|
|
|
private void updateMenuItemVisibility() {
|
|
|
|
|
|
|
|
// show kodi if set in settings
|
|
|
|
menu.findItem(R.id.action_play_with_kodi).setVisible(
|
|
|
|
PreferenceManager.getDefaultSharedPreferences(activity).getBoolean(
|
|
|
|
activity.getString(R.string.show_play_with_kodi_key), false));
|
|
|
|
}
|
|
|
|
|
2015-09-04 02:15:03 +02:00
|
|
|
@Override
|
|
|
|
public boolean onOptionsItemSelected(MenuItem item) {
|
2020-02-22 10:36:10 +01:00
|
|
|
int id = item.getItemId();
|
|
|
|
if (id == R.id.action_settings) {
|
|
|
|
NavigationHelper.openSettings(requireContext());
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2018-09-03 01:22:59 +02:00
|
|
|
if (isLoading.get()) {
|
2020-02-22 10:36:10 +01:00
|
|
|
// if still loading, block menu buttons related to video info
|
2018-02-16 12:18:15 +01:00
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
switch (id) {
|
|
|
|
case R.id.menu_item_share: {
|
2018-04-06 09:35:44 +02:00
|
|
|
if (currentInfo != null) {
|
2020-02-22 10:36:10 +01:00
|
|
|
ShareUtils.shareUrl(requireContext(), currentInfo.getName(), currentInfo.getOriginalUrl());
|
2018-02-16 12:18:15 +01:00
|
|
|
}
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
case R.id.menu_item_openInBrowser: {
|
2018-04-06 09:35:44 +02:00
|
|
|
if (currentInfo != null) {
|
2020-02-22 10:36:10 +01:00
|
|
|
ShareUtils.openUrlInBrowser(requireContext(), currentInfo.getOriginalUrl());
|
2018-04-06 09:35:44 +02:00
|
|
|
}
|
2018-02-16 12:18:15 +01:00
|
|
|
return true;
|
|
|
|
}
|
|
|
|
case R.id.action_play_with_kodi:
|
|
|
|
try {
|
|
|
|
NavigationHelper.playWithKore(activity, Uri.parse(
|
|
|
|
url.replace("https", "http")));
|
|
|
|
} catch (Exception e) {
|
2018-09-03 01:22:59 +02:00
|
|
|
if (DEBUG) Log.i(TAG, "Failed to start kore", e);
|
2019-04-25 20:47:39 +02:00
|
|
|
KoreUtil.showInstallKoreDialog(activity);
|
2018-02-16 12:18:15 +01:00
|
|
|
}
|
|
|
|
return true;
|
|
|
|
default:
|
|
|
|
return super.onOptionsItemSelected(item);
|
|
|
|
}
|
2017-03-31 20:15:26 +02:00
|
|
|
}
|
|
|
|
|
2018-02-16 12:18:15 +01:00
|
|
|
private void setupActionBarOnError(final String url) {
|
|
|
|
if (DEBUG) Log.d(TAG, "setupActionBarHandlerOnError() called with: url = [" + url + "]");
|
|
|
|
Log.e("-----", "missing code");
|
|
|
|
}
|
|
|
|
|
|
|
|
private void setupActionBar(final StreamInfo info) {
|
2017-09-03 08:04:18 +02:00
|
|
|
if (DEBUG) Log.d(TAG, "setupActionBarHandler() called with: info = [" + info + "]");
|
2018-02-16 12:18:15 +01:00
|
|
|
boolean isExternalPlayerEnabled = PreferenceManager.getDefaultSharedPreferences(activity)
|
|
|
|
.getBoolean(activity.getString(R.string.use_external_video_player_key), false);
|
2018-04-08 13:08:19 +02:00
|
|
|
|
2019-01-31 13:24:02 +01:00
|
|
|
sortedVideoStreams = ListHelper.getSortedStreamVideosList(
|
|
|
|
activity,
|
|
|
|
info.getVideoStreams(),
|
|
|
|
info.getVideoOnlyStreams(),
|
|
|
|
false);
|
2018-04-08 13:08:19 +02:00
|
|
|
selectedVideoStreamIndex = ListHelper.getDefaultResolutionIndex(activity, sortedVideoStreams);
|
|
|
|
|
2019-01-31 13:24:02 +01:00
|
|
|
final StreamItemAdapter<VideoStream, Stream> streamsAdapter =
|
|
|
|
new StreamItemAdapter<>(activity,
|
|
|
|
new StreamSizeWrapper<>(sortedVideoStreams, activity), isExternalPlayerEnabled);
|
2018-04-08 13:08:19 +02:00
|
|
|
spinnerToolbar.setAdapter(streamsAdapter);
|
|
|
|
spinnerToolbar.setSelection(selectedVideoStreamIndex);
|
2018-02-16 12:18:15 +01:00
|
|
|
spinnerToolbar.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
|
|
|
|
@Override
|
|
|
|
public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
|
2018-04-08 13:08:19 +02:00
|
|
|
selectedVideoStreamIndex = position;
|
2018-02-16 12:18:15 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
@Override
|
|
|
|
public void onNothingSelected(AdapterView<?> parent) {
|
2017-03-31 20:15:26 +02:00
|
|
|
}
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
2017-04-09 19:34:00 +02:00
|
|
|
/*//////////////////////////////////////////////////////////////////////////
|
|
|
|
// OwnStack
|
|
|
|
//////////////////////////////////////////////////////////////////////////*/
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Stack that contains the "navigation history".<br>
|
|
|
|
* The peek is the current video.
|
|
|
|
*/
|
2018-08-28 20:02:25 +02:00
|
|
|
protected final LinkedList<StackItem> stack = new LinkedList<>();
|
2017-04-09 19:34:00 +02:00
|
|
|
|
2017-09-03 08:04:18 +02:00
|
|
|
public void pushToStack(int serviceId, String videoUrl, String name) {
|
|
|
|
if (DEBUG) {
|
2019-01-31 13:24:02 +01:00
|
|
|
Log.d(TAG, "pushToStack() called with: serviceId = ["
|
|
|
|
+ serviceId + "], videoUrl = [" + videoUrl + "], name = [" + name + "]");
|
2017-09-03 08:04:18 +02:00
|
|
|
}
|
2017-04-09 19:34:00 +02:00
|
|
|
|
2019-01-31 13:24:02 +01:00
|
|
|
if (stack.size() > 0
|
|
|
|
&& stack.peek().getServiceId() == serviceId
|
|
|
|
&& stack.peek().getUrl().equals(videoUrl)) {
|
|
|
|
Log.d(TAG, "pushToStack() called with: serviceId == peek.serviceId = ["
|
|
|
|
+ serviceId + "], videoUrl == peek.getUrl = [" + videoUrl + "]");
|
2017-09-03 08:04:18 +02:00
|
|
|
return;
|
|
|
|
} else {
|
|
|
|
Log.d(TAG, "pushToStack() wasn't equal");
|
2017-04-09 19:34:00 +02:00
|
|
|
}
|
2017-09-03 08:04:18 +02:00
|
|
|
|
|
|
|
stack.push(new StackItem(serviceId, videoUrl, name));
|
2017-04-09 19:34:00 +02:00
|
|
|
}
|
|
|
|
|
2017-09-03 08:04:18 +02:00
|
|
|
public void setTitleToUrl(int serviceId, String videoUrl, String name) {
|
|
|
|
if (name != null && !name.isEmpty()) {
|
2017-04-26 21:32:04 +02:00
|
|
|
for (StackItem stackItem : stack) {
|
2018-02-16 11:31:25 +01:00
|
|
|
if (stack.peek().getServiceId() == serviceId
|
|
|
|
&& stackItem.getUrl().equals(videoUrl)) {
|
|
|
|
stackItem.setTitle(name);
|
|
|
|
}
|
2017-04-26 21:32:04 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-09-03 08:04:18 +02:00
|
|
|
@Override
|
|
|
|
public boolean onBackPressed() {
|
|
|
|
if (DEBUG) Log.d(TAG, "onBackPressed() called");
|
2017-04-09 19:34:00 +02:00
|
|
|
// That means that we are on the start of the stack,
|
|
|
|
// return false to let the MainActivity handle the onBack
|
2017-09-03 08:04:18 +02:00
|
|
|
if (stack.size() <= 1) return false;
|
2017-04-09 19:34:00 +02:00
|
|
|
// Remove top
|
|
|
|
stack.pop();
|
2017-09-03 08:04:18 +02:00
|
|
|
// Get stack item from the new top
|
2017-04-09 19:34:00 +02:00
|
|
|
StackItem peek = stack.peek();
|
2017-04-26 21:32:04 +02:00
|
|
|
|
2019-01-31 13:24:02 +01:00
|
|
|
selectAndLoadVideo(peek.getServiceId(),
|
|
|
|
peek.getUrl(),
|
|
|
|
!TextUtils.isEmpty(peek.getTitle())
|
|
|
|
? peek.getTitle()
|
|
|
|
: "");
|
2017-04-09 19:34:00 +02:00
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2017-03-31 20:15:26 +02:00
|
|
|
/*//////////////////////////////////////////////////////////////////////////
|
2017-09-03 08:04:18 +02:00
|
|
|
// Info loading and handling
|
2017-03-31 20:15:26 +02:00
|
|
|
//////////////////////////////////////////////////////////////////////////*/
|
|
|
|
|
2017-09-03 08:04:18 +02:00
|
|
|
@Override
|
|
|
|
protected void doInitialLoadLogic() {
|
|
|
|
if (currentInfo == null) prepareAndLoadInfo();
|
|
|
|
else prepareAndHandleInfo(currentInfo, false);
|
2017-03-31 20:15:26 +02:00
|
|
|
}
|
|
|
|
|
2017-09-03 08:04:18 +02:00
|
|
|
public void selectAndLoadVideo(int serviceId, String videoUrl, String name) {
|
|
|
|
setInitialData(serviceId, videoUrl, name);
|
|
|
|
prepareAndLoadInfo();
|
2017-04-09 19:34:00 +02:00
|
|
|
}
|
|
|
|
|
2017-09-03 08:04:18 +02:00
|
|
|
public void prepareAndHandleInfo(final StreamInfo info, boolean scrollToTop) {
|
2019-01-31 13:24:02 +01:00
|
|
|
if (DEBUG) Log.d(TAG, "prepareAndHandleInfo() called with: info = ["
|
|
|
|
+ info + "], scrollToTop = [" + scrollToTop + "]");
|
2017-04-28 05:58:50 +02:00
|
|
|
|
2019-01-31 13:24:02 +01:00
|
|
|
setInitialData(info.getServiceId(), info.getUrl(), info.getName());
|
2017-09-03 08:04:18 +02:00
|
|
|
pushToStack(serviceId, url, name);
|
|
|
|
showLoading();
|
2018-10-02 17:09:16 +02:00
|
|
|
initTabs();
|
2017-04-26 21:32:04 +02:00
|
|
|
|
2018-10-02 17:09:16 +02:00
|
|
|
if (scrollToTop) appBarLayout.setExpanded(true, true);
|
2018-12-19 06:28:59 +01:00
|
|
|
handleResult(info);
|
|
|
|
showContent();
|
|
|
|
|
2017-04-09 19:34:00 +02:00
|
|
|
}
|
2017-03-31 20:15:26 +02:00
|
|
|
|
2017-09-03 08:04:18 +02:00
|
|
|
protected void prepareAndLoadInfo() {
|
2018-10-02 17:09:16 +02:00
|
|
|
appBarLayout.setExpanded(true, true);
|
2017-09-03 08:04:18 +02:00
|
|
|
pushToStack(serviceId, url, name);
|
|
|
|
startLoading(false);
|
|
|
|
}
|
2017-04-28 05:58:50 +02:00
|
|
|
|
2017-09-03 08:04:18 +02:00
|
|
|
@Override
|
|
|
|
public void startLoading(boolean forceLoad) {
|
|
|
|
super.startLoading(forceLoad);
|
|
|
|
|
2018-10-02 17:09:16 +02:00
|
|
|
initTabs();
|
2017-09-03 08:04:18 +02:00
|
|
|
currentInfo = null;
|
|
|
|
if (currentWorker != null) currentWorker.dispose();
|
|
|
|
|
|
|
|
currentWorker = ExtractorHelper.getStreamInfo(serviceId, url, forceLoad)
|
|
|
|
.subscribeOn(Schedulers.io())
|
|
|
|
.observeOn(AndroidSchedulers.mainThread())
|
2018-02-11 21:34:32 +01:00
|
|
|
.subscribe((@NonNull StreamInfo result) -> {
|
|
|
|
isLoading.set(false);
|
|
|
|
currentInfo = result;
|
|
|
|
handleResult(result);
|
2018-12-19 06:28:59 +01:00
|
|
|
showContent();
|
2018-02-11 21:34:32 +01:00
|
|
|
}, (@NonNull Throwable throwable) -> {
|
|
|
|
isLoading.set(false);
|
|
|
|
onError(throwable);
|
2017-09-03 08:04:18 +02:00
|
|
|
});
|
2018-09-23 03:32:19 +02:00
|
|
|
|
2018-10-02 17:09:16 +02:00
|
|
|
}
|
2018-09-23 03:32:19 +02:00
|
|
|
|
2018-10-02 17:09:16 +02:00
|
|
|
private void initTabs() {
|
2019-03-24 02:01:28 +01:00
|
|
|
if (pageAdapter.getCount() != 0) {
|
|
|
|
selectedTabTag = pageAdapter.getItemTitle(viewPager.getCurrentItem());
|
|
|
|
}
|
2018-10-02 17:09:16 +02:00
|
|
|
pageAdapter.clearAllItems();
|
|
|
|
|
|
|
|
if(shouldShowComments()){
|
|
|
|
pageAdapter.addFragment(CommentsFragment.getInstance(serviceId, url, name), COMMENTS_TAB_TAG);
|
|
|
|
}
|
|
|
|
|
2018-12-08 22:51:55 +01:00
|
|
|
if(showRelatedStreams && null == relatedStreamsLayout){
|
2018-10-02 17:26:14 +02:00
|
|
|
//temp empty fragment. will be updated in handleResult
|
2018-10-02 17:09:16 +02:00
|
|
|
pageAdapter.addFragment(new Fragment(), RELATED_TAB_TAG);
|
|
|
|
}
|
|
|
|
|
2019-03-03 13:50:15 +01:00
|
|
|
if(pageAdapter.getCount() == 0){
|
|
|
|
pageAdapter.addFragment(new EmptyFragment(), EMPTY_TAB_TAG);
|
|
|
|
}
|
|
|
|
|
2018-10-02 18:00:11 +02:00
|
|
|
pageAdapter.notifyDataSetUpdate();
|
|
|
|
|
2018-10-02 17:09:16 +02:00
|
|
|
if(pageAdapter.getCount() < 2){
|
|
|
|
tabLayout.setVisibility(View.GONE);
|
2018-10-02 17:26:14 +02:00
|
|
|
}else{
|
2019-03-24 02:01:28 +01:00
|
|
|
int position = pageAdapter.getItemPositionByTitle(selectedTabTag);
|
|
|
|
if(position != -1) viewPager.setCurrentItem(position);
|
2018-10-02 17:26:14 +02:00
|
|
|
tabLayout.setVisibility(View.VISIBLE);
|
2018-10-02 17:09:16 +02:00
|
|
|
}
|
2018-09-23 03:32:19 +02:00
|
|
|
}
|
|
|
|
|
2018-10-02 17:09:16 +02:00
|
|
|
private boolean shouldShowComments() {
|
|
|
|
try {
|
2019-02-15 20:53:26 +01:00
|
|
|
return showComments && NewPipe.getService(serviceId)
|
|
|
|
.getServiceInfo()
|
|
|
|
.getMediaCapabilities()
|
|
|
|
.contains(COMMENTS);
|
2018-10-02 17:09:16 +02:00
|
|
|
} catch (ExtractionException e) {
|
|
|
|
return false;
|
2018-09-23 03:32:19 +02:00
|
|
|
}
|
2017-09-03 08:04:18 +02:00
|
|
|
}
|
2017-04-28 05:58:50 +02:00
|
|
|
|
2017-09-03 08:04:18 +02:00
|
|
|
/*//////////////////////////////////////////////////////////////////////////
|
|
|
|
// Play Utils
|
|
|
|
//////////////////////////////////////////////////////////////////////////*/
|
2017-04-09 19:34:00 +02:00
|
|
|
|
2017-10-13 02:02:07 +02:00
|
|
|
private void openBackgroundPlayer(final boolean append) {
|
2018-02-16 11:31:25 +01:00
|
|
|
AudioStream audioStream = currentInfo.getAudioStreams()
|
|
|
|
.get(ListHelper.getDefaultAudioFormat(activity, currentInfo.getAudioStreams()));
|
2017-03-31 20:15:26 +02:00
|
|
|
|
2017-09-03 08:04:18 +02:00
|
|
|
boolean useExternalAudioPlayer = PreferenceManager.getDefaultSharedPreferences(activity)
|
|
|
|
.getBoolean(activity.getString(R.string.use_external_audio_player_key), false);
|
2017-04-28 05:58:50 +02:00
|
|
|
|
2017-09-03 08:04:18 +02:00
|
|
|
if (!useExternalAudioPlayer && android.os.Build.VERSION.SDK_INT >= 16) {
|
2017-10-13 02:02:07 +02:00
|
|
|
openNormalBackgroundPlayer(append);
|
2017-04-26 21:32:04 +02:00
|
|
|
} else {
|
2018-06-19 03:27:30 +02:00
|
|
|
startOnExternalPlayer(activity, currentInfo, audioStream);
|
2017-04-26 21:32:04 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-10-13 02:02:07 +02:00
|
|
|
private void openPopupPlayer(final boolean append) {
|
2018-01-04 07:53:31 +01:00
|
|
|
if (!PermissionHelper.isPopupEnabled(activity)) {
|
|
|
|
PermissionHelper.showPopupEnablementToast(activity);
|
2017-09-03 08:04:18 +02:00
|
|
|
return;
|
|
|
|
}
|
2017-04-26 21:32:04 +02:00
|
|
|
|
2017-11-02 06:33:13 +01:00
|
|
|
final PlayQueue itemQueue = new SinglePlayQueue(currentInfo);
|
2017-10-13 02:02:07 +02:00
|
|
|
if (append) {
|
2019-04-13 09:31:32 +02:00
|
|
|
NavigationHelper.enqueueOnPopupPlayer(activity, itemQueue, false);
|
2017-10-13 02:02:07 +02:00
|
|
|
} else {
|
2017-11-02 20:30:26 +01:00
|
|
|
Toast.makeText(activity, R.string.popup_playing_toast, Toast.LENGTH_SHORT).show();
|
|
|
|
final Intent intent = NavigationHelper.getPlayerIntent(
|
2019-04-13 09:31:32 +02:00
|
|
|
activity, PopupVideoPlayer.class, itemQueue, getSelectedVideoStream().resolution, true
|
2017-11-02 20:30:26 +01:00
|
|
|
);
|
|
|
|
activity.startService(intent);
|
2017-10-13 02:02:07 +02:00
|
|
|
}
|
2017-09-03 08:04:18 +02:00
|
|
|
}
|
2017-04-26 21:32:04 +02:00
|
|
|
|
2017-09-03 08:04:18 +02:00
|
|
|
private void openVideoPlayer() {
|
|
|
|
VideoStream selectedVideoStream = getSelectedVideoStream();
|
2017-04-26 21:32:04 +02:00
|
|
|
|
2018-02-16 11:31:25 +01:00
|
|
|
if (PreferenceManager.getDefaultSharedPreferences(activity)
|
|
|
|
.getBoolean(this.getString(R.string.use_external_video_player_key), false)) {
|
2018-06-19 03:27:30 +02:00
|
|
|
startOnExternalPlayer(activity, currentInfo, selectedVideoStream);
|
2017-04-26 21:32:04 +02:00
|
|
|
} else {
|
2018-11-13 17:27:47 +01:00
|
|
|
openNormalPlayer();
|
2017-04-26 21:32:04 +02:00
|
|
|
}
|
2017-09-03 08:04:18 +02:00
|
|
|
}
|
2017-04-26 21:32:04 +02:00
|
|
|
|
2017-10-13 02:02:07 +02:00
|
|
|
private void openNormalBackgroundPlayer(final boolean append) {
|
2017-11-02 06:33:13 +01:00
|
|
|
final PlayQueue itemQueue = new SinglePlayQueue(currentInfo);
|
2017-10-14 06:07:19 +02:00
|
|
|
if (append) {
|
2019-04-13 09:31:32 +02:00
|
|
|
NavigationHelper.enqueueOnBackgroundPlayer(activity, itemQueue, false);
|
2017-10-14 06:07:19 +02:00
|
|
|
} else {
|
2019-04-13 09:31:32 +02:00
|
|
|
NavigationHelper.playOnBackgroundPlayer(activity, itemQueue, true);
|
2017-10-14 06:07:19 +02:00
|
|
|
}
|
2017-09-03 08:04:18 +02:00
|
|
|
}
|
2017-04-26 21:32:04 +02:00
|
|
|
|
2018-11-13 17:27:47 +01:00
|
|
|
private void openNormalPlayer() {
|
2017-11-02 20:30:26 +01:00
|
|
|
Intent mIntent;
|
2018-11-13 17:27:47 +01:00
|
|
|
final PlayQueue playQueue = new SinglePlayQueue(currentInfo);
|
|
|
|
mIntent = NavigationHelper.getPlayerIntent(activity,
|
|
|
|
MainVideoPlayer.class,
|
|
|
|
playQueue,
|
2019-04-13 09:31:32 +02:00
|
|
|
getSelectedVideoStream().getResolution(), true);
|
2017-11-02 20:30:26 +01:00
|
|
|
startActivity(mIntent);
|
2017-06-15 16:26:48 +02:00
|
|
|
}
|
2017-06-28 03:39:33 +02:00
|
|
|
|
2017-09-03 08:04:18 +02:00
|
|
|
/*//////////////////////////////////////////////////////////////////////////
|
|
|
|
// Utils
|
|
|
|
//////////////////////////////////////////////////////////////////////////*/
|
|
|
|
|
|
|
|
public void setAutoplay(boolean autoplay) {
|
|
|
|
this.autoPlayEnabled = autoplay;
|
2017-03-31 20:15:26 +02:00
|
|
|
}
|
|
|
|
|
2018-06-19 03:27:30 +02:00
|
|
|
private void startOnExternalPlayer(@NonNull final Context context,
|
|
|
|
@NonNull final StreamInfo info,
|
|
|
|
@NonNull final Stream selectedStream) {
|
|
|
|
NavigationHelper.playOnExternalPlayer(context, currentInfo.getName(),
|
|
|
|
currentInfo.getUploaderName(), selectedStream);
|
|
|
|
|
|
|
|
final HistoryRecordManager recordManager = new HistoryRecordManager(requireContext());
|
|
|
|
disposables.add(recordManager.onViewed(info).onErrorComplete()
|
|
|
|
.subscribe(
|
|
|
|
ignored -> {/* successful */},
|
|
|
|
error -> Log.e(TAG, "Register view failure: ", error)
|
|
|
|
));
|
|
|
|
}
|
|
|
|
|
2018-04-08 13:08:19 +02:00
|
|
|
@Nullable
|
2017-08-12 06:50:25 +02:00
|
|
|
private VideoStream getSelectedVideoStream() {
|
2018-04-08 13:08:19 +02:00
|
|
|
return sortedVideoStreams != null ? sortedVideoStreams.get(selectedVideoStreamIndex) : null;
|
2017-08-12 06:50:25 +02:00
|
|
|
}
|
|
|
|
|
2020-02-06 23:54:36 +01:00
|
|
|
private void prepareDescription(Description description) {
|
|
|
|
if (TextUtils.isEmpty(description.getContent()) || description == Description.emptyDescription) {
|
2017-09-03 08:04:18 +02:00
|
|
|
return;
|
2017-08-12 06:50:25 +02:00
|
|
|
}
|
2017-03-31 20:15:26 +02:00
|
|
|
|
2020-02-06 23:54:36 +01:00
|
|
|
if (description.getType() == Description.HTML) {
|
|
|
|
disposables.add(Single.just(description.getContent())
|
|
|
|
.map((@io.reactivex.annotations.NonNull String descriptionText) -> {
|
2020-02-02 16:54:09 +01:00
|
|
|
Spanned parsedDescription;
|
|
|
|
if (Build.VERSION.SDK_INT >= 24) {
|
2020-02-06 23:54:36 +01:00
|
|
|
parsedDescription = Html.fromHtml(descriptionText, 0);
|
2020-02-02 16:54:09 +01:00
|
|
|
} else {
|
|
|
|
//noinspection deprecation
|
2020-02-06 23:54:36 +01:00
|
|
|
parsedDescription = Html.fromHtml(descriptionText);
|
2020-02-02 16:54:09 +01:00
|
|
|
}
|
|
|
|
return parsedDescription;
|
|
|
|
})
|
|
|
|
.subscribeOn(Schedulers.computation())
|
|
|
|
.observeOn(AndroidSchedulers.mainThread())
|
|
|
|
.subscribe((@io.reactivex.annotations.NonNull Spanned spanned) -> {
|
|
|
|
videoDescriptionView.setText(spanned);
|
|
|
|
videoDescriptionView.setVisibility(View.VISIBLE);
|
|
|
|
}));
|
2020-02-06 23:54:36 +01:00
|
|
|
} else if (description.getType() == Description.MARKDOWN) {
|
2020-02-08 09:56:37 +01:00
|
|
|
final Markwon markwon = Markwon.builder(getContext())
|
|
|
|
.usePlugin(LinkifyPlugin.create())
|
|
|
|
.build();
|
|
|
|
markwon.setMarkdown(videoDescriptionView, description.getContent());
|
2020-02-06 23:54:36 +01:00
|
|
|
videoDescriptionView.setVisibility(View.VISIBLE);
|
|
|
|
} else {
|
|
|
|
//== Description.PLAIN_TEXT
|
2020-02-08 09:56:37 +01:00
|
|
|
videoDescriptionView.setAutoLinkMask(Linkify.WEB_URLS);
|
2020-02-06 23:54:36 +01:00
|
|
|
videoDescriptionView.setText(description.getContent(), TextView.BufferType.SPANNABLE);
|
|
|
|
videoDescriptionView.setVisibility(View.VISIBLE);
|
2020-02-02 16:54:09 +01:00
|
|
|
}
|
2017-03-31 20:15:26 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
private void setHeightThumbnail() {
|
2017-09-03 08:04:18 +02:00
|
|
|
final DisplayMetrics metrics = getResources().getDisplayMetrics();
|
|
|
|
boolean isPortrait = metrics.heightPixels > metrics.widthPixels;
|
2018-02-16 11:31:25 +01:00
|
|
|
int height = isPortrait
|
|
|
|
? (int) (metrics.widthPixels / (16.0f / 9.0f))
|
|
|
|
: (int) (metrics.heightPixels / 2f);
|
|
|
|
thumbnailImageView.setLayoutParams(
|
|
|
|
new FrameLayout.LayoutParams(RelativeLayout.LayoutParams.MATCH_PARENT, height));
|
2017-03-31 20:15:26 +02:00
|
|
|
thumbnailImageView.setMinimumHeight(height);
|
|
|
|
}
|
|
|
|
|
2018-12-19 06:28:59 +01:00
|
|
|
private void showContent() {
|
2019-08-07 12:00:47 +02:00
|
|
|
contentRootLayoutHiding.setVisibility(View.VISIBLE);
|
2017-04-28 05:58:50 +02:00
|
|
|
}
|
2017-03-31 20:15:26 +02:00
|
|
|
|
2017-09-03 08:04:18 +02:00
|
|
|
protected void setInitialData(int serviceId, String url, String name) {
|
|
|
|
this.serviceId = serviceId;
|
|
|
|
this.url = url;
|
|
|
|
this.name = !TextUtils.isEmpty(name) ? name : "";
|
|
|
|
}
|
|
|
|
|
2017-04-26 21:32:04 +02:00
|
|
|
private void setErrorImage(final int imageResource) {
|
|
|
|
if (thumbnailImageView == null || activity == null) return;
|
2017-09-03 08:04:18 +02:00
|
|
|
|
2017-04-26 21:32:04 +02:00
|
|
|
thumbnailImageView.setImageDrawable(ContextCompat.getDrawable(activity, imageResource));
|
2018-02-16 11:31:25 +01:00
|
|
|
animateView(thumbnailImageView, false, 0, 0,
|
|
|
|
() -> animateView(thumbnailImageView, true, 500));
|
2017-04-26 21:32:04 +02:00
|
|
|
}
|
2017-03-31 20:15:26 +02:00
|
|
|
|
2017-04-26 21:32:04 +02:00
|
|
|
@Override
|
2017-09-03 08:04:18 +02:00
|
|
|
public void showError(String message, boolean showRetryButton) {
|
|
|
|
showError(message, showRetryButton, R.drawable.not_available_monkey);
|
|
|
|
}
|
2017-03-31 20:15:26 +02:00
|
|
|
|
2017-09-03 08:04:18 +02:00
|
|
|
protected void showError(String message, boolean showRetryButton, @DrawableRes int imageError) {
|
|
|
|
super.showError(message, showRetryButton);
|
|
|
|
setErrorImage(imageError);
|
2017-04-26 21:32:04 +02:00
|
|
|
}
|
2017-03-31 20:15:26 +02:00
|
|
|
|
2017-06-28 03:39:33 +02:00
|
|
|
/*//////////////////////////////////////////////////////////////////////////
|
2017-09-03 08:04:18 +02:00
|
|
|
// Contract
|
2017-06-28 03:39:33 +02:00
|
|
|
//////////////////////////////////////////////////////////////////////////*/
|
|
|
|
|
2017-04-26 21:32:04 +02:00
|
|
|
@Override
|
2017-09-03 08:04:18 +02:00
|
|
|
public void showLoading() {
|
2019-08-07 12:00:47 +02:00
|
|
|
|
2017-09-03 08:04:18 +02:00
|
|
|
super.showLoading();
|
2017-04-09 19:34:00 +02:00
|
|
|
|
2019-08-07 12:00:47 +02:00
|
|
|
//if data is already cached, transition from VISIBLE -> INVISIBLE -> VISIBLE is not required
|
|
|
|
if(!ExtractorHelper.isCached(serviceId, url, InfoItem.InfoType.STREAM)){
|
|
|
|
contentRootLayoutHiding.setVisibility(View.INVISIBLE);
|
|
|
|
}
|
|
|
|
|
2017-09-03 08:04:18 +02:00
|
|
|
animateView(spinnerToolbar, false, 200);
|
|
|
|
animateView(thumbnailPlayButton, false, 50);
|
2018-03-10 17:16:51 +01:00
|
|
|
animateView(detailDurationView, false, 100);
|
2019-04-13 09:31:32 +02:00
|
|
|
animateView(detailPositionView, false, 100);
|
|
|
|
animateView(positionView, false, 50);
|
2017-03-31 20:15:26 +02:00
|
|
|
|
2017-09-03 08:04:18 +02:00
|
|
|
videoTitleTextView.setText(name != null ? name : "");
|
|
|
|
videoTitleTextView.setMaxLines(1);
|
|
|
|
animateView(videoTitleTextView, true, 0);
|
2017-04-26 21:32:04 +02:00
|
|
|
|
2017-09-03 08:04:18 +02:00
|
|
|
videoDescriptionRootLayout.setVisibility(View.GONE);
|
2018-12-08 22:51:55 +01:00
|
|
|
videoTitleToggleArrow.setImageResource(R.drawable.arrow_down);
|
|
|
|
videoTitleToggleArrow.setVisibility(View.GONE);
|
2017-09-03 08:04:18 +02:00
|
|
|
videoTitleRoot.setClickable(false);
|
2017-03-31 20:15:26 +02:00
|
|
|
|
2018-12-08 22:51:55 +01:00
|
|
|
if(relatedStreamsLayout != null){
|
|
|
|
if(showRelatedStreams){
|
|
|
|
relatedStreamsLayout.setVisibility(View.INVISIBLE);
|
|
|
|
}else{
|
|
|
|
relatedStreamsLayout.setVisibility(View.GONE);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-09-03 08:04:18 +02:00
|
|
|
imageLoader.cancelDisplayTask(thumbnailImageView);
|
|
|
|
imageLoader.cancelDisplayTask(uploaderThumb);
|
|
|
|
thumbnailImageView.setImageBitmap(null);
|
|
|
|
uploaderThumb.setImageBitmap(null);
|
2017-03-31 20:15:26 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
@Override
|
2017-09-03 08:04:18 +02:00
|
|
|
public void handleResult(@NonNull StreamInfo info) {
|
|
|
|
super.handleResult(info);
|
2017-04-26 21:32:04 +02:00
|
|
|
|
2018-04-06 09:35:44 +02:00
|
|
|
setInitialData(info.getServiceId(), info.getOriginalUrl(), info.getName());
|
2018-10-02 17:09:16 +02:00
|
|
|
|
|
|
|
if(showRelatedStreams){
|
2018-12-08 22:51:55 +01:00
|
|
|
if(null == relatedStreamsLayout){ //phone
|
|
|
|
pageAdapter.updateItem(RELATED_TAB_TAG, RelatedVideosFragment.getInstance(currentInfo));
|
|
|
|
pageAdapter.notifyDataSetUpdate();
|
|
|
|
}else{ //tablet
|
|
|
|
getChildFragmentManager().beginTransaction()
|
|
|
|
.replace(R.id.relatedStreamsLayout, RelatedVideosFragment.getInstance(currentInfo))
|
|
|
|
.commitNow();
|
|
|
|
relatedStreamsLayout.setVisibility(View.VISIBLE);
|
|
|
|
}
|
2018-10-02 17:09:16 +02:00
|
|
|
}
|
|
|
|
|
2019-01-31 13:24:02 +01:00
|
|
|
//pushToStack(serviceId, url, name);
|
2017-04-26 21:32:04 +02:00
|
|
|
|
2017-09-03 08:04:18 +02:00
|
|
|
animateView(thumbnailPlayButton, true, 200);
|
|
|
|
videoTitleTextView.setText(name);
|
2017-03-31 20:15:26 +02:00
|
|
|
|
2017-12-08 15:05:08 +01:00
|
|
|
if (!TextUtils.isEmpty(info.getUploaderName())) {
|
|
|
|
uploaderTextView.setText(info.getUploaderName());
|
|
|
|
uploaderTextView.setVisibility(View.VISIBLE);
|
2018-01-29 08:01:06 +01:00
|
|
|
uploaderTextView.setSelected(true);
|
2017-12-08 15:05:08 +01:00
|
|
|
} else {
|
|
|
|
uploaderTextView.setVisibility(View.GONE);
|
|
|
|
}
|
2017-09-03 08:04:18 +02:00
|
|
|
uploaderThumb.setImageDrawable(ContextCompat.getDrawable(activity, R.drawable.buddy));
|
2017-03-31 20:15:26 +02:00
|
|
|
|
2017-12-08 15:05:08 +01:00
|
|
|
if (info.getViewCount() >= 0) {
|
2019-10-28 03:37:36 +01:00
|
|
|
if (info.getStreamType().equals(StreamType.AUDIO_LIVE_STREAM)) {
|
|
|
|
videoCountView.setText(Localization.listeningCount(activity, info.getViewCount()));
|
|
|
|
} else if (info.getStreamType().equals(StreamType.LIVE_STREAM)) {
|
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
|
|
|
videoCountView.setText(Localization.localizeWatchingCount(activity, info.getViewCount()));
|
2019-10-28 03:37:36 +01:00
|
|
|
} else {
|
|
|
|
videoCountView.setText(Localization.localizeViewCount(activity, info.getViewCount()));
|
|
|
|
}
|
2017-12-08 15:05:08 +01:00
|
|
|
videoCountView.setVisibility(View.VISIBLE);
|
|
|
|
} else {
|
|
|
|
videoCountView.setVisibility(View.GONE);
|
|
|
|
}
|
2017-03-31 20:15:26 +02:00
|
|
|
|
2017-12-08 15:05:08 +01:00
|
|
|
if (info.getDislikeCount() == -1 && info.getLikeCount() == -1) {
|
2017-09-03 08:04:18 +02:00
|
|
|
thumbsDownImageView.setVisibility(View.VISIBLE);
|
|
|
|
thumbsUpImageView.setVisibility(View.VISIBLE);
|
|
|
|
thumbsUpTextView.setVisibility(View.GONE);
|
|
|
|
thumbsDownTextView.setVisibility(View.GONE);
|
2017-04-12 08:07:15 +02:00
|
|
|
|
2017-09-03 08:04:18 +02:00
|
|
|
thumbsDisabledTextView.setVisibility(View.VISIBLE);
|
|
|
|
} else {
|
2017-12-08 15:05:08 +01:00
|
|
|
if (info.getDislikeCount() >= 0) {
|
|
|
|
thumbsDownTextView.setText(Localization.shortCount(activity, info.getDislikeCount()));
|
|
|
|
thumbsDownTextView.setVisibility(View.VISIBLE);
|
|
|
|
thumbsDownImageView.setVisibility(View.VISIBLE);
|
|
|
|
} else {
|
|
|
|
thumbsDownTextView.setVisibility(View.GONE);
|
|
|
|
thumbsDownImageView.setVisibility(View.GONE);
|
|
|
|
}
|
2017-06-28 03:39:33 +02:00
|
|
|
|
2017-12-08 15:05:08 +01:00
|
|
|
if (info.getLikeCount() >= 0) {
|
|
|
|
thumbsUpTextView.setText(Localization.shortCount(activity, info.getLikeCount()));
|
|
|
|
thumbsUpTextView.setVisibility(View.VISIBLE);
|
|
|
|
thumbsUpImageView.setVisibility(View.VISIBLE);
|
|
|
|
} else {
|
|
|
|
thumbsUpTextView.setVisibility(View.GONE);
|
|
|
|
thumbsUpImageView.setVisibility(View.GONE);
|
|
|
|
}
|
2017-09-03 08:04:18 +02:00
|
|
|
thumbsDisabledTextView.setVisibility(View.GONE);
|
|
|
|
}
|
2017-06-15 16:26:48 +02:00
|
|
|
|
2018-03-10 17:16:51 +01:00
|
|
|
if (info.getDuration() > 0) {
|
|
|
|
detailDurationView.setText(Localization.getDurationString(info.getDuration()));
|
2019-01-31 13:24:02 +01:00
|
|
|
detailDurationView.setBackgroundColor(
|
|
|
|
ContextCompat.getColor(activity, R.color.duration_background_color));
|
2018-03-10 17:16:51 +01:00
|
|
|
animateView(detailDurationView, true, 100);
|
|
|
|
} else if (info.getStreamType() == StreamType.LIVE_STREAM) {
|
|
|
|
detailDurationView.setText(R.string.duration_live);
|
2019-01-31 13:24:02 +01:00
|
|
|
detailDurationView.setBackgroundColor(
|
|
|
|
ContextCompat.getColor(activity, R.color.live_duration_background_color));
|
2018-03-10 17:16:51 +01:00
|
|
|
animateView(detailDurationView, true, 100);
|
|
|
|
} else {
|
|
|
|
detailDurationView.setVisibility(View.GONE);
|
|
|
|
}
|
|
|
|
|
2017-09-03 08:04:18 +02:00
|
|
|
videoDescriptionView.setVisibility(View.GONE);
|
2018-12-08 22:51:55 +01:00
|
|
|
videoTitleRoot.setClickable(true);
|
|
|
|
videoTitleToggleArrow.setVisibility(View.VISIBLE);
|
|
|
|
videoTitleToggleArrow.setImageResource(R.drawable.arrow_down);
|
|
|
|
videoDescriptionRootLayout.setVisibility(View.GONE);
|
2019-10-28 03:35:51 +01:00
|
|
|
|
|
|
|
if (info.getUploadDate() != null) {
|
|
|
|
videoUploadDateView.setText(Localization.localizeUploadDate(activity, info.getUploadDate().date().getTime()));
|
|
|
|
videoUploadDateView.setVisibility(View.VISIBLE);
|
|
|
|
} else {
|
|
|
|
videoUploadDateView.setText(null);
|
|
|
|
videoUploadDateView.setVisibility(View.GONE);
|
2017-06-15 16:26:48 +02:00
|
|
|
}
|
2019-10-28 03:35:51 +01:00
|
|
|
|
2020-02-06 23:54:36 +01:00
|
|
|
prepareDescription(info.getDescription());
|
2019-04-13 09:31:32 +02:00
|
|
|
updateProgressInfo(info);
|
2017-06-15 16:26:48 +02:00
|
|
|
|
2017-09-03 08:04:18 +02:00
|
|
|
animateView(spinnerToolbar, true, 500);
|
2018-02-16 12:18:15 +01:00
|
|
|
setupActionBar(info);
|
2017-09-03 08:04:18 +02:00
|
|
|
initThumbnailViews(info);
|
2018-04-06 09:35:44 +02:00
|
|
|
|
2017-12-08 15:05:08 +01:00
|
|
|
setTitleToUrl(info.getServiceId(), info.getUrl(), info.getName());
|
2018-04-06 09:35:44 +02:00
|
|
|
setTitleToUrl(info.getServiceId(), info.getOriginalUrl(), info.getName());
|
2017-06-15 16:26:48 +02:00
|
|
|
|
2017-12-08 15:05:08 +01:00
|
|
|
if (!info.getErrors().isEmpty()) {
|
2018-02-16 11:31:25 +01:00
|
|
|
showSnackBarError(info.getErrors(),
|
|
|
|
UserAction.REQUESTED_STREAM,
|
|
|
|
NewPipe.getNameOfService(info.getServiceId()),
|
|
|
|
info.getUrl(),
|
|
|
|
0);
|
2017-06-15 16:26:48 +02:00
|
|
|
}
|
|
|
|
|
2018-02-26 00:10:11 +01:00
|
|
|
switch (info.getStreamType()) {
|
|
|
|
case LIVE_STREAM:
|
|
|
|
case AUDIO_LIVE_STREAM:
|
|
|
|
detailControlsDownload.setVisibility(View.GONE);
|
|
|
|
spinnerToolbar.setVisibility(View.GONE);
|
|
|
|
break;
|
|
|
|
default:
|
2018-08-21 17:43:39 +02:00
|
|
|
if(info.getAudioStreams().isEmpty()) detailControlsBackground.setVisibility(View.GONE);
|
2018-03-18 16:37:49 +01:00
|
|
|
if (!info.getVideoStreams().isEmpty()
|
|
|
|
|| !info.getVideoOnlyStreams().isEmpty()) break;
|
2018-02-26 00:10:11 +01:00
|
|
|
|
|
|
|
detailControlsPopup.setVisibility(View.GONE);
|
|
|
|
spinnerToolbar.setVisibility(View.GONE);
|
|
|
|
thumbnailPlayButton.setImageResource(R.drawable.ic_headset_white_24dp);
|
|
|
|
break;
|
2017-09-14 10:49:39 +02:00
|
|
|
}
|
|
|
|
|
2017-09-03 08:04:18 +02:00
|
|
|
if (autoPlayEnabled) {
|
|
|
|
openVideoPlayer();
|
|
|
|
// Only auto play in the first open
|
|
|
|
autoPlayEnabled = false;
|
2017-06-15 16:26:48 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-04-07 19:32:02 +02:00
|
|
|
|
|
|
|
public void openDownloadDialog() {
|
2018-04-08 18:49:27 +02:00
|
|
|
try {
|
|
|
|
DownloadDialog downloadDialog = DownloadDialog.newInstance(currentInfo);
|
|
|
|
downloadDialog.setVideoStreams(sortedVideoStreams);
|
|
|
|
downloadDialog.setAudioStreams(currentInfo.getAudioStreams());
|
|
|
|
downloadDialog.setSelectedVideoStream(selectedVideoStreamIndex);
|
2018-09-23 20:12:23 +02:00
|
|
|
downloadDialog.setSubtitleStreams(currentInfo.getSubtitles());
|
2018-04-08 18:49:27 +02:00
|
|
|
|
2019-06-14 17:19:50 +02:00
|
|
|
downloadDialog.show(getActivity().getSupportFragmentManager(), "downloadDialog");
|
2018-04-08 18:49:27 +02:00
|
|
|
} catch (Exception e) {
|
2018-12-23 22:07:27 +01:00
|
|
|
ErrorActivity.ErrorInfo info = ErrorActivity.ErrorInfo.make(UserAction.UI_ERROR,
|
|
|
|
ServiceList.all()
|
|
|
|
.get(currentInfo
|
|
|
|
.getServiceId())
|
|
|
|
.getServiceInfo()
|
|
|
|
.getName(), "",
|
|
|
|
R.string.could_not_setup_download_menu);
|
|
|
|
|
|
|
|
ErrorActivity.reportError(getActivity(),
|
|
|
|
e,
|
|
|
|
getActivity().getClass(),
|
|
|
|
getActivity().findViewById(android.R.id.content), info);
|
2018-04-08 18:49:27 +02:00
|
|
|
}
|
2018-04-07 19:32:02 +02:00
|
|
|
}
|
|
|
|
|
2017-09-03 08:04:18 +02:00
|
|
|
/*//////////////////////////////////////////////////////////////////////////
|
|
|
|
// Stream Results
|
|
|
|
//////////////////////////////////////////////////////////////////////////*/
|
|
|
|
|
|
|
|
@Override
|
|
|
|
protected boolean onError(Throwable exception) {
|
|
|
|
if (super.onError(exception)) return true;
|
|
|
|
|
2020-03-27 03:58:01 +01:00
|
|
|
int errorId = exception instanceof YoutubeStreamExtractor.DecryptException ? R.string.youtube_signature_decryption_error
|
|
|
|
: exception instanceof ExtractionException ? R.string.parsing_error
|
|
|
|
: R.string.general_error;
|
|
|
|
|
|
|
|
onUnrecoverableError(exception, UserAction.REQUESTED_STREAM,
|
|
|
|
NewPipe.getNameOfService(serviceId), url, errorId);
|
2017-09-03 08:04:18 +02:00
|
|
|
|
|
|
|
return true;
|
2017-06-15 16:26:48 +02:00
|
|
|
}
|
2017-08-12 06:50:25 +02:00
|
|
|
|
2019-04-13 09:31:32 +02:00
|
|
|
private void updateProgressInfo(@NonNull final StreamInfo info) {
|
|
|
|
if (positionSubscriber != null) {
|
|
|
|
positionSubscriber.dispose();
|
|
|
|
}
|
|
|
|
final SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(activity);
|
|
|
|
final boolean playbackResumeEnabled =
|
|
|
|
prefs.getBoolean(activity.getString(R.string.enable_watch_history_key), true)
|
|
|
|
&& prefs.getBoolean(activity.getString(R.string.enable_playback_resume_key), true);
|
2019-12-16 08:36:04 +01:00
|
|
|
|
2019-04-13 09:31:32 +02:00
|
|
|
if (!playbackResumeEnabled || info.getDuration() <= 0) {
|
|
|
|
positionView.setVisibility(View.INVISIBLE);
|
|
|
|
detailPositionView.setVisibility(View.GONE);
|
2019-12-16 08:36:04 +01:00
|
|
|
|
|
|
|
// TODO: Remove this check when separation of concerns is done.
|
|
|
|
// (live streams weren't getting updated because they are mixed)
|
|
|
|
if (!info.getStreamType().equals(StreamType.LIVE_STREAM) &&
|
|
|
|
!info.getStreamType().equals(StreamType.AUDIO_LIVE_STREAM)) {
|
|
|
|
return;
|
|
|
|
}
|
2019-04-13 09:31:32 +02:00
|
|
|
}
|
|
|
|
final HistoryRecordManager recordManager = new HistoryRecordManager(requireContext());
|
2019-12-16 08:36:04 +01:00
|
|
|
|
|
|
|
// TODO: Separate concerns when updating database data.
|
|
|
|
// (move the updating part to when the loading happens)
|
2019-04-13 09:31:32 +02:00
|
|
|
positionSubscriber = recordManager.loadStreamState(info)
|
|
|
|
.subscribeOn(Schedulers.io())
|
|
|
|
.onErrorComplete()
|
|
|
|
.observeOn(AndroidSchedulers.mainThread())
|
|
|
|
.subscribe(state -> {
|
|
|
|
final int seconds = (int) TimeUnit.MILLISECONDS.toSeconds(state.getProgressTime());
|
|
|
|
positionView.setMax((int) info.getDuration());
|
2019-04-27 21:27:08 +02:00
|
|
|
positionView.setProgressAnimated(seconds);
|
2019-04-13 09:31:32 +02:00
|
|
|
detailPositionView.setText(Localization.getDurationString(seconds));
|
|
|
|
animateView(positionView, true, 500);
|
|
|
|
animateView(detailPositionView, true, 500);
|
|
|
|
}, e -> {
|
|
|
|
if (DEBUG) e.printStackTrace();
|
|
|
|
}, () -> {
|
|
|
|
animateView(positionView, false, 500);
|
|
|
|
animateView(detailPositionView, false, 500);
|
|
|
|
});
|
2017-08-12 06:50:25 +02:00
|
|
|
}
|
2018-11-20 23:10:50 +01:00
|
|
|
}
|