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;
|
2017-03-31 20:15:26 +02:00
|
|
|
import android.content.DialogInterface;
|
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;
|
2017-09-03 08:04:18 +02:00
|
|
|
import android.support.annotation.DrawableRes;
|
2017-04-28 05:58:50 +02:00
|
|
|
import android.support.annotation.FloatRange;
|
2017-04-26 21:32:04 +02:00
|
|
|
import android.support.annotation.NonNull;
|
2017-03-31 20:15:26 +02:00
|
|
|
import android.support.v4.content.ContextCompat;
|
2017-12-08 15:05:08 +01:00
|
|
|
import android.support.v4.text.TextUtilsCompat;
|
2017-04-28 05:58:50 +02:00
|
|
|
import android.support.v4.view.animation.FastOutSlowInInterpolator;
|
2017-04-09 19:34:00 +02:00
|
|
|
import android.support.v7.app.ActionBar;
|
2017-03-31 20:15:26 +02:00
|
|
|
import android.support.v7.app.AlertDialog;
|
|
|
|
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-03-31 20:15:26 +02:00
|
|
|
import android.util.TypedValue;
|
2017-05-01 07:23:50 +02:00
|
|
|
import android.view.Gravity;
|
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;
|
2017-06-15 16:26:48 +02:00
|
|
|
import android.widget.FrameLayout;
|
2017-04-26 21:32:04 +02:00
|
|
|
import android.widget.ImageButton;
|
2017-03-31 20:15:26 +02:00
|
|
|
import android.widget.ImageView;
|
|
|
|
import android.widget.LinearLayout;
|
2017-11-02 06:33:13 +01:00
|
|
|
import android.widget.PopupMenu;
|
2017-03-31 20:15:26 +02:00
|
|
|
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.nirhart.parallaxscroll.views.ParallaxScrollView;
|
|
|
|
import com.nostra13.universalimageloader.core.assist.FailReason;
|
|
|
|
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.MediaFormat;
|
|
|
|
import org.schabi.newpipe.extractor.NewPipe;
|
2017-09-03 08:04:18 +02:00
|
|
|
import org.schabi.newpipe.extractor.exceptions.ContentNotAvailableException;
|
|
|
|
import org.schabi.newpipe.extractor.exceptions.ParsingException;
|
|
|
|
import org.schabi.newpipe.extractor.services.youtube.YoutubeStreamExtractor;
|
|
|
|
import org.schabi.newpipe.extractor.stream.AudioStream;
|
|
|
|
import org.schabi.newpipe.extractor.stream.StreamInfo;
|
|
|
|
import org.schabi.newpipe.extractor.stream.StreamInfoItem;
|
|
|
|
import org.schabi.newpipe.extractor.stream.VideoStream;
|
|
|
|
import org.schabi.newpipe.fragments.BackPressable;
|
|
|
|
import org.schabi.newpipe.fragments.BaseStateFragment;
|
|
|
|
import org.schabi.newpipe.history.HistoryListener;
|
2017-03-31 20:15:26 +02:00
|
|
|
import org.schabi.newpipe.info_list.InfoItemBuilder;
|
2017-11-11 23:47:34 +01:00
|
|
|
import org.schabi.newpipe.info_list.InfoItemDialog;
|
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;
|
2017-11-02 20:30:26 +01:00
|
|
|
import org.schabi.newpipe.player.helper.PlayerHelper;
|
2017-09-03 08:04:18 +02:00
|
|
|
import org.schabi.newpipe.player.old.PlayVideoActivity;
|
2017-09-25 05:14:58 +02:00
|
|
|
import org.schabi.newpipe.playlist.PlayQueue;
|
|
|
|
import org.schabi.newpipe.playlist.SinglePlayQueue;
|
2017-02-18 21:59:48 +01: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;
|
|
|
|
import org.schabi.newpipe.util.InfoCache;
|
|
|
|
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;
|
2015-11-17 00:32:00 +01:00
|
|
|
|
2017-04-09 19:34:00 +02:00
|
|
|
import java.io.Serializable;
|
2017-03-31 20:15:26 +02:00
|
|
|
import java.util.ArrayList;
|
2017-09-03 08:04:18 +02:00
|
|
|
import java.util.Collection;
|
|
|
|
import java.util.LinkedList;
|
|
|
|
|
|
|
|
import icepick.State;
|
|
|
|
import io.reactivex.Single;
|
|
|
|
import io.reactivex.android.schedulers.AndroidSchedulers;
|
|
|
|
import io.reactivex.disposables.CompositeDisposable;
|
|
|
|
import io.reactivex.disposables.Disposable;
|
|
|
|
import io.reactivex.functions.Consumer;
|
|
|
|
import io.reactivex.functions.Function;
|
|
|
|
import io.reactivex.schedulers.Schedulers;
|
2017-04-09 19:34:00 +02:00
|
|
|
|
2017-05-08 15:33:26 +02:00
|
|
|
import static org.schabi.newpipe.util.AnimationUtils.animateView;
|
|
|
|
|
2017-10-13 02:02:07 +02: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-04-26 21:32:04 +02:00
|
|
|
// Amount of videos to show on start
|
|
|
|
private static final int INITIAL_RELATED_VIDEOS = 8;
|
|
|
|
|
2017-03-31 20:15:26 +02:00
|
|
|
private ActionBarHandler actionBarHandler;
|
2017-09-03 08:04:18 +02:00
|
|
|
private ArrayList<VideoStream> sortedStreamVideosList;
|
2017-03-31 20:15:26 +02:00
|
|
|
|
2017-06-17 13:43:09 +02:00
|
|
|
private InfoItemBuilder infoItemBuilder = null;
|
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;
|
2017-03-31 20:15:26 +02:00
|
|
|
|
|
|
|
private boolean autoPlayEnabled;
|
|
|
|
private boolean showRelatedStreams;
|
2017-04-26 21:32:04 +02:00
|
|
|
private boolean wasRelatedStreamsExpanded = false;
|
2017-03-31 20:15:26 +02:00
|
|
|
|
2017-09-03 08:04:18 +02:00
|
|
|
@State
|
2017-10-08 21:04:37 +02:00
|
|
|
protected int serviceId = Constants.NO_SERVICE_ID;
|
2017-09-03 08:04:18 +02:00
|
|
|
@State
|
|
|
|
protected String name;
|
|
|
|
@State
|
|
|
|
protected String url;
|
|
|
|
|
|
|
|
private StreamInfo currentInfo;
|
|
|
|
private Disposable currentWorker;
|
|
|
|
private CompositeDisposable disposables = new CompositeDisposable();
|
2017-06-28 03:39:33 +02:00
|
|
|
|
2017-03-31 20:15:26 +02:00
|
|
|
/*//////////////////////////////////////////////////////////////////////////
|
|
|
|
// Views
|
|
|
|
//////////////////////////////////////////////////////////////////////////*/
|
|
|
|
|
2017-04-26 21:32:04 +02:00
|
|
|
private Spinner spinnerToolbar;
|
2017-03-31 20:15:26 +02:00
|
|
|
|
|
|
|
private ParallaxScrollView parallaxScrollRootView;
|
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;
|
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;
|
2017-10-14 23:09:49 +02:00
|
|
|
private TextView appendControlsDetail;
|
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;
|
|
|
|
|
|
|
|
private TextView nextStreamTitle;
|
2017-06-15 16:26:48 +02:00
|
|
|
private LinearLayout relatedStreamRootLayout;
|
2017-06-17 13:43:09 +02:00
|
|
|
private LinearLayout relatedStreamsView;
|
2017-04-26 21:32:04 +02:00
|
|
|
private ImageButton relatedStreamExpandButton;
|
2017-03-31 20:15:26 +02: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
|
|
|
|
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
|
|
|
|
2017-04-09 19:34:00 +02:00
|
|
|
showRelatedStreams = PreferenceManager.getDefaultSharedPreferences(activity).getBoolean(getString(R.string.show_next_video_key), true);
|
|
|
|
PreferenceManager.getDefaultSharedPreferences(activity).registerOnSharedPreferenceChangeListener(this);
|
|
|
|
}
|
2015-09-04 02:15:03 +02:00
|
|
|
|
2017-04-09 19:34:00 +02:00
|
|
|
@Override
|
|
|
|
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
|
|
|
|
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();
|
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) {
|
|
|
|
if ((updateFlags & RELATED_STREAMS_UPDATE_FLAG) != 0) initRelatedVideos(currentInfo);
|
|
|
|
if ((updateFlags & RESOLUTIONS_MENU_UPDATE_FLAG) != 0) setupActionBarHandler(currentInfo);
|
2017-04-26 21:32:04 +02:00
|
|
|
}
|
2017-05-09 03:23:27 +02:00
|
|
|
|
|
|
|
if ((updateFlags & TOOLBAR_ITEMS_UPDATE_FLAG) != 0 && actionBarHandler != null) actionBarHandler.updateItemsVisibility();
|
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);
|
|
|
|
}
|
2017-04-26 21:32:04 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
@Override
|
|
|
|
public void onDestroy() {
|
|
|
|
super.onDestroy();
|
|
|
|
PreferenceManager.getDefaultSharedPreferences(activity).unregisterOnSharedPreferenceChangeListener(this);
|
2017-09-03 08:04:18 +02:00
|
|
|
|
|
|
|
if (currentWorker != null) currentWorker.dispose();
|
|
|
|
if (disposables != null) disposables.clear();
|
|
|
|
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;
|
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";
|
|
|
|
private static final String WAS_RELATED_EXPANDED_KEY = "was_related_expanded_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 (relatedStreamsView != null && relatedStreamsView.getChildCount() > INITIAL_RELATED_VIDEOS + nextCount) {
|
|
|
|
outState.putSerializable(WAS_RELATED_EXPANDED_KEY, true);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!isLoading.get() && currentInfo != null && isVisible()) {
|
|
|
|
outState.putSerializable(INFO_KEY, currentInfo);
|
|
|
|
}
|
|
|
|
|
|
|
|
outState.putSerializable(STACK_KEY, stack);
|
|
|
|
}
|
|
|
|
|
|
|
|
@Override
|
|
|
|
protected void onRestoreInstanceState(@NonNull Bundle savedState) {
|
|
|
|
super.onRestoreInstanceState(savedState);
|
|
|
|
|
|
|
|
wasRelatedStreamsExpanded = savedState.getBoolean(WAS_RELATED_EXPANDED_KEY, false);
|
|
|
|
Serializable serializable = savedState.getSerializable(INFO_KEY);
|
|
|
|
if (serializable instanceof StreamInfo) {
|
|
|
|
//noinspection unchecked
|
|
|
|
currentInfo = (StreamInfo) serializable;
|
|
|
|
InfoCache.getInstance().putInfo(currentInfo);
|
|
|
|
}
|
|
|
|
|
|
|
|
serializable = savedState.getSerializable(STACK_KEY);
|
|
|
|
if (serializable instanceof Collection) {
|
|
|
|
//noinspection unchecked
|
|
|
|
stack.addAll((Collection<? extends StackItem>) serializable);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
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;
|
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 {
|
2017-12-08 15:05:08 +01:00
|
|
|
NavigationHelper.openChannelFragment(
|
|
|
|
getFragmentManager(),
|
|
|
|
currentInfo.getServiceId(),
|
|
|
|
currentInfo.getUploaderUrl(),
|
|
|
|
currentInfo.getUploaderName());
|
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:
|
2017-09-03 08:04:18 +02:00
|
|
|
openVideoPlayer();
|
2017-04-26 21:32:04 +02:00
|
|
|
break;
|
|
|
|
case R.id.detail_title_root_layout:
|
|
|
|
toggleTitleAndDescription();
|
|
|
|
break;
|
|
|
|
case R.id.detail_related_streams_expand:
|
2017-09-03 08:04:18 +02:00
|
|
|
toggleExpandRelatedVideos(currentInfo);
|
2017-04-26 21:32:04 +02:00
|
|
|
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;
|
|
|
|
}
|
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2017-04-26 21:32:04 +02:00
|
|
|
private void toggleTitleAndDescription() {
|
|
|
|
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);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
private void toggleExpandRelatedVideos(StreamInfo info) {
|
|
|
|
if (DEBUG) Log.d(TAG, "toggleExpandRelatedVideos() called with: info = [" + info + "]");
|
|
|
|
if (!showRelatedStreams) return;
|
|
|
|
|
2017-12-08 15:05:08 +01:00
|
|
|
int nextCount = info.getNextVideo() != null ? 2 : 0;
|
2017-04-26 21:32:04 +02:00
|
|
|
int initialCount = INITIAL_RELATED_VIDEOS + nextCount;
|
|
|
|
|
2017-06-17 13:43:09 +02:00
|
|
|
if (relatedStreamsView.getChildCount() > initialCount) {
|
|
|
|
relatedStreamsView.removeViews(initialCount, relatedStreamsView.getChildCount() - (initialCount));
|
2017-09-03 08:04:18 +02:00
|
|
|
relatedStreamExpandButton.setImageDrawable(ContextCompat.getDrawable(activity, resolveResourceIdFromAttr(R.attr.expand)));
|
2017-06-17 13:43:09 +02:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
//Log.d(TAG, "toggleExpandRelatedVideos() called with: info = [" + info + "], from = [" + INITIAL_RELATED_VIDEOS + "]");
|
2017-12-08 15:05:08 +01:00
|
|
|
for (int i = INITIAL_RELATED_VIDEOS; i < info.getRelatedStreams().size(); i++) {
|
|
|
|
InfoItem item = info.getRelatedStreams().get(i);
|
2017-06-17 13:43:09 +02:00
|
|
|
//Log.d(TAG, "i = " + i);
|
|
|
|
relatedStreamsView.addView(infoItemBuilder.buildView(relatedStreamsView, item));
|
2017-04-26 21:32:04 +02:00
|
|
|
}
|
2017-09-03 08:04:18 +02:00
|
|
|
relatedStreamExpandButton.setImageDrawable(ContextCompat.getDrawable(activity, resolveResourceIdFromAttr(R.attr.collapse)));
|
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);
|
|
|
|
|
2017-09-03 08:04:18 +02:00
|
|
|
spinnerToolbar = activity.findViewById(R.id.toolbar).findViewById(R.id.toolbar_spinner);
|
2017-03-31 20:15:26 +02:00
|
|
|
|
2017-09-03 08:04:18 +02:00
|
|
|
parallaxScrollRootView = rootView.findViewById(R.id.detail_main_content);
|
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);
|
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);
|
2017-10-14 23:09:49 +02:00
|
|
|
appendControlsDetail = rootView.findViewById(R.id.touch_append_detail);
|
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());
|
|
|
|
videoDescriptionView.setAutoLinkMask(Linkify.WEB_URLS);
|
2017-03-31 20:15:26 +02:00
|
|
|
|
2017-09-03 08:04:18 +02:00
|
|
|
//thumbsRootLayout = rootView.findViewById(R.id.detail_thumbs_root_layout);
|
|
|
|
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
|
|
|
|
2017-09-03 08:04:18 +02:00
|
|
|
relatedStreamRootLayout = rootView.findViewById(R.id.detail_related_streams_root_layout);
|
|
|
|
nextStreamTitle = rootView.findViewById(R.id.detail_next_stream_title);
|
|
|
|
relatedStreamsView = rootView.findViewById(R.id.detail_related_streams_view);
|
2017-06-15 16:26:48 +02:00
|
|
|
|
2017-09-03 08:04:18 +02:00
|
|
|
relatedStreamExpandButton = rootView.findViewById(R.id.detail_related_streams_expand);
|
2017-03-31 20:15:26 +02:00
|
|
|
|
2017-04-09 19:34:00 +02:00
|
|
|
actionBarHandler = new ActionBarHandler(activity);
|
2017-06-17 13:43:09 +02:00
|
|
|
infoItemBuilder = new InfoItemBuilder(activity);
|
2017-03-31 20:15:26 +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-09-03 08:04:18 +02:00
|
|
|
infoItemBuilder.setOnStreamSelectedListener(new InfoItemBuilder.OnInfoItemSelectedListener<StreamInfoItem>() {
|
2017-03-31 20:15:26 +02:00
|
|
|
@Override
|
2017-09-03 08:04:18 +02:00
|
|
|
public void selected(StreamInfoItem selectedItem) {
|
2017-12-08 15:05:08 +01:00
|
|
|
selectAndLoadVideo(selectedItem.getServiceId(), selectedItem.getUrl(), selectedItem.getName());
|
2017-03-31 20:15:26 +02:00
|
|
|
}
|
2017-11-11 23:47:34 +01:00
|
|
|
|
|
|
|
@Override
|
|
|
|
public void held(StreamInfoItem selectedItem) {
|
|
|
|
showStreamDialog(selectedItem);
|
|
|
|
}
|
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);
|
|
|
|
relatedStreamExpandButton.setOnClickListener(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());
|
|
|
|
}
|
|
|
|
|
2017-11-11 23:47:34 +01:00
|
|
|
private void showStreamDialog(final StreamInfoItem item) {
|
|
|
|
final Context context = getContext();
|
2017-11-14 06:13:52 +01:00
|
|
|
if (context == null || context.getResources() == null || getActivity() == null) return;
|
|
|
|
|
2017-11-11 23:47:34 +01:00
|
|
|
final String[] commands = new String[]{
|
|
|
|
context.getResources().getString(R.string.enqueue_on_background),
|
|
|
|
context.getResources().getString(R.string.enqueue_on_popup)
|
|
|
|
};
|
|
|
|
|
|
|
|
final DialogInterface.OnClickListener actions = new DialogInterface.OnClickListener() {
|
|
|
|
@Override
|
|
|
|
public void onClick(DialogInterface dialogInterface, int i) {
|
|
|
|
switch (i) {
|
|
|
|
case 0:
|
|
|
|
NavigationHelper.enqueueOnBackgroundPlayer(context, new SinglePlayQueue(item));
|
|
|
|
break;
|
|
|
|
case 1:
|
|
|
|
NavigationHelper.enqueueOnPopupPlayer(context, new SinglePlayQueue(item));
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
new InfoItemDialog(getActivity(), item, commands, actions).show();
|
|
|
|
}
|
|
|
|
|
2017-10-14 23:09:49 +02:00
|
|
|
private View.OnTouchListener getOnControlsTouchListener() {
|
|
|
|
return new View.OnTouchListener() {
|
|
|
|
@Override
|
|
|
|
public boolean onTouch(View view, MotionEvent motionEvent) {
|
2017-10-17 03:59:59 +02:00
|
|
|
if (!PreferenceManager.getDefaultSharedPreferences(activity).getBoolean(getString(R.string.show_hold_to_append_key), true)) return false;
|
|
|
|
|
2017-10-14 23:09:49 +02:00
|
|
|
if (motionEvent.getAction() == MotionEvent.ACTION_DOWN) {
|
2017-10-31 04:58:02 +01:00
|
|
|
animateView(appendControlsDetail, true, 250, 0, new Runnable() {
|
|
|
|
@Override
|
|
|
|
public void run() {
|
|
|
|
animateView(appendControlsDetail, false, 1500, 1000);
|
|
|
|
}
|
|
|
|
});
|
2017-10-14 23:09:49 +02:00
|
|
|
}
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
};
|
2017-03-31 20:15:26 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
private void initThumbnailViews(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())) {
|
|
|
|
imageLoader.displayImage(info.getThumbnailUrl(), thumbnailImageView, DISPLAY_THUMBNAIL_OPTIONS, new SimpleImageLoadingListener() {
|
2017-04-26 21:32:04 +02:00
|
|
|
@Override
|
|
|
|
public void onLoadingFailed(String imageUri, View view, FailReason failReason) {
|
2017-12-08 15:05:08 +01:00
|
|
|
ErrorActivity.reportError(activity, failReason.getCause(), null, activity.findViewById(android.R.id.content), ErrorActivity.ErrorInfo.make(UserAction.LOAD_IMAGE, NewPipe.getNameOfService(currentInfo.getServiceId()), imageUri, R.string.could_not_load_thumbnails));
|
2017-04-26 21:32:04 +02:00
|
|
|
}
|
|
|
|
});
|
2017-09-03 08:04:18 +02:00
|
|
|
}
|
2017-03-31 20:15:26 +02:00
|
|
|
|
2017-12-08 15:05:08 +01:00
|
|
|
if (TextUtils.isEmpty(info.getUploaderAvatarUrl())) {
|
|
|
|
imageLoader.displayImage(info.getUploaderAvatarUrl(), uploaderThumb, 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
|
|
|
private void initRelatedVideos(StreamInfo info) {
|
2017-06-17 13:43:09 +02:00
|
|
|
if (relatedStreamsView.getChildCount() > 0) relatedStreamsView.removeAllViews();
|
2017-03-31 20:15:26 +02:00
|
|
|
|
2017-12-08 15:05:08 +01:00
|
|
|
if (info.getNextVideo() != null && showRelatedStreams) {
|
2017-03-31 20:15:26 +02:00
|
|
|
nextStreamTitle.setVisibility(View.VISIBLE);
|
2017-12-08 15:05:08 +01:00
|
|
|
relatedStreamsView.addView(infoItemBuilder.buildView(relatedStreamsView, info.getNextVideo()));
|
2017-06-17 13:43:09 +02:00
|
|
|
relatedStreamsView.addView(getSeparatorView());
|
2017-04-09 19:34:00 +02:00
|
|
|
relatedStreamRootLayout.setVisibility(View.VISIBLE);
|
2017-03-31 20:15:26 +02:00
|
|
|
} else nextStreamTitle.setVisibility(View.GONE);
|
|
|
|
|
|
|
|
if (info.related_streams != null && !info.related_streams.isEmpty() && showRelatedStreams) {
|
2017-04-26 21:32:04 +02:00
|
|
|
//long first = System.nanoTime(), each;
|
2017-12-08 15:05:08 +01:00
|
|
|
int to = info.getRelatedStreams().size() >= INITIAL_RELATED_VIDEOS ? INITIAL_RELATED_VIDEOS : info.getRelatedStreams().size();
|
2017-06-17 13:43:09 +02:00
|
|
|
for (int i = 0; i < to; i++) {
|
2017-12-08 15:05:08 +01:00
|
|
|
InfoItem item = info.getRelatedStreams().get(i);
|
2017-06-17 13:43:09 +02:00
|
|
|
//each = System.nanoTime();
|
|
|
|
relatedStreamsView.addView(infoItemBuilder.buildView(relatedStreamsView, item));
|
|
|
|
//if (DEBUG) Log.d(TAG, "each took " + ((System.nanoTime() - each) / 1000000L) + "ms");
|
|
|
|
}
|
2017-04-26 21:32:04 +02:00
|
|
|
//if (DEBUG) Log.d(TAG, "Total time " + ((System.nanoTime() - first) / 1000000L) + "ms");
|
|
|
|
|
2017-04-09 19:34:00 +02:00
|
|
|
relatedStreamRootLayout.setVisibility(View.VISIBLE);
|
2017-04-26 21:32:04 +02:00
|
|
|
relatedStreamExpandButton.setVisibility(View.VISIBLE);
|
|
|
|
|
2017-09-03 08:04:18 +02:00
|
|
|
relatedStreamExpandButton.setImageDrawable(ContextCompat.getDrawable(activity, resolveResourceIdFromAttr(R.attr.expand)));
|
2017-04-26 21:32:04 +02:00
|
|
|
} else {
|
2017-12-08 15:05:08 +01:00
|
|
|
if (info.getNextVideo() == null) relatedStreamRootLayout.setVisibility(View.GONE);
|
2017-04-26 21:32:04 +02:00
|
|
|
relatedStreamExpandButton.setVisibility(View.GONE);
|
|
|
|
}
|
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) {
|
|
|
|
actionBarHandler.setupMenu(menu, inflater);
|
|
|
|
ActionBar supportActionBar = activity.getSupportActionBar();
|
|
|
|
if (supportActionBar != null) {
|
|
|
|
supportActionBar.setDisplayHomeAsUpEnabled(true);
|
|
|
|
supportActionBar.setDisplayShowTitleEnabled(false);
|
|
|
|
}
|
2015-09-04 02:15:03 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
@Override
|
|
|
|
public boolean onOptionsItemSelected(MenuItem item) {
|
2017-09-03 08:04:18 +02:00
|
|
|
return (!isLoading.get() && actionBarHandler.onItemSelected(item)) || super.onOptionsItemSelected(item);
|
2017-03-31 20:15:26 +02:00
|
|
|
}
|
|
|
|
|
2017-10-30 21:15:06 +01:00
|
|
|
private static void showInstallKoreDialog(final Context context) {
|
|
|
|
final AlertDialog.Builder builder = new AlertDialog.Builder(context);
|
|
|
|
builder.setMessage(R.string.kore_not_found)
|
|
|
|
.setPositiveButton(R.string.install, new DialogInterface.OnClickListener() {
|
|
|
|
@Override
|
|
|
|
public void onClick(DialogInterface dialog, int which) {
|
|
|
|
NavigationHelper.installKore(context);
|
|
|
|
}
|
|
|
|
})
|
|
|
|
.setNegativeButton(R.string.cancel, new DialogInterface.OnClickListener() {
|
|
|
|
@Override
|
|
|
|
public void onClick(DialogInterface dialog, int which) {
|
|
|
|
|
|
|
|
}
|
|
|
|
});
|
|
|
|
builder.create().show();
|
|
|
|
}
|
|
|
|
|
2017-03-31 20:15:26 +02:00
|
|
|
private void setupActionBarHandler(final StreamInfo info) {
|
2017-09-03 08:04:18 +02:00
|
|
|
if (DEBUG) Log.d(TAG, "setupActionBarHandler() called with: info = [" + info + "]");
|
2017-12-08 15:05:08 +01:00
|
|
|
sortedStreamVideosList = new ArrayList<>(ListHelper.getSortedStreamVideosList(activity, info.getVideoStreams(), info.getVideoOnlyStreams(), false));
|
2017-04-26 21:32:04 +02:00
|
|
|
actionBarHandler.setupStreamList(sortedStreamVideosList, spinnerToolbar);
|
2017-03-31 20:15:26 +02:00
|
|
|
actionBarHandler.setOnShareListener(new ActionBarHandler.OnActionListener() {
|
|
|
|
@Override
|
|
|
|
public void onActionSelected(int selectedStreamId) {
|
|
|
|
Intent intent = new Intent();
|
|
|
|
intent.setAction(Intent.ACTION_SEND);
|
2017-12-08 15:05:08 +01:00
|
|
|
intent.putExtra(Intent.EXTRA_TEXT, info.getUrl());
|
2017-03-31 20:15:26 +02:00
|
|
|
intent.setType("text/plain");
|
2017-04-09 19:34:00 +02:00
|
|
|
startActivity(Intent.createChooser(intent, activity.getString(R.string.share_dialog_title)));
|
2017-03-31 20:15:26 +02:00
|
|
|
}
|
|
|
|
});
|
|
|
|
|
|
|
|
actionBarHandler.setOnOpenInBrowserListener(new ActionBarHandler.OnActionListener() {
|
|
|
|
@Override
|
|
|
|
public void onActionSelected(int selectedStreamId) {
|
|
|
|
Intent intent = new Intent();
|
|
|
|
intent.setAction(Intent.ACTION_VIEW);
|
2017-12-08 15:05:08 +01:00
|
|
|
intent.setData(Uri.parse(info.getUrl()));
|
2017-04-09 19:34:00 +02:00
|
|
|
startActivity(Intent.createChooser(intent, activity.getString(R.string.choose_browser)));
|
2017-03-31 20:15:26 +02:00
|
|
|
}
|
|
|
|
});
|
|
|
|
|
|
|
|
actionBarHandler.setOnPlayWithKodiListener(new ActionBarHandler.OnActionListener() {
|
|
|
|
@Override
|
|
|
|
public void onActionSelected(int selectedStreamId) {
|
|
|
|
try {
|
2017-12-08 15:05:08 +01:00
|
|
|
NavigationHelper.playWithKore(activity, Uri.parse(info.getUrl().replace("https", "http")));
|
2017-10-30 21:31:59 +01:00
|
|
|
if(activity instanceof HistoryListener) {
|
|
|
|
((HistoryListener) activity).onVideoPlayed(info, null);
|
|
|
|
}
|
2017-03-31 20:15:26 +02:00
|
|
|
} catch (Exception e) {
|
2017-10-30 21:15:06 +01:00
|
|
|
if(DEBUG) Log.i(TAG, "Failed to start kore", e);
|
|
|
|
showInstallKoreDialog(activity);
|
2017-03-31 20:15:26 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
});
|
|
|
|
|
|
|
|
actionBarHandler.setOnDownloadListener(new ActionBarHandler.OnActionListener() {
|
|
|
|
@Override
|
|
|
|
public void onActionSelected(int selectedStreamId) {
|
2017-09-03 08:04:18 +02:00
|
|
|
if (!PermissionHelper.checkStoragePermissions(activity)) {
|
2017-03-31 20:15:26 +02:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
try {
|
2017-05-15 05:57:57 +02:00
|
|
|
DownloadDialog downloadDialog = DownloadDialog.newInstance(info, sortedStreamVideosList, selectedStreamId);
|
2017-04-09 19:34:00 +02:00
|
|
|
downloadDialog.show(activity.getSupportFragmentManager(), "downloadDialog");
|
2017-03-31 20:15:26 +02:00
|
|
|
} catch (Exception e) {
|
2017-05-15 05:57:57 +02:00
|
|
|
Toast.makeText(activity, R.string.could_not_setup_download_menu, Toast.LENGTH_LONG).show();
|
2017-03-31 20:15:26 +02:00
|
|
|
e.printStackTrace();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
2017-04-09 19:34:00 +02:00
|
|
|
/*//////////////////////////////////////////////////////////////////////////
|
|
|
|
// OwnStack
|
|
|
|
//////////////////////////////////////////////////////////////////////////*/
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Stack that contains the "navigation history".<br>
|
|
|
|
* The peek is the current video.
|
|
|
|
*/
|
2017-09-03 08:04:18 +02:00
|
|
|
protected LinkedList<StackItem> stack = new LinkedList<>();
|
2017-04-09 19:34:00 +02:00
|
|
|
|
|
|
|
public void clearHistory() {
|
|
|
|
stack.clear();
|
|
|
|
}
|
|
|
|
|
2017-09-03 08:04:18 +02:00
|
|
|
public void pushToStack(int serviceId, String videoUrl, String name) {
|
|
|
|
if (DEBUG) {
|
|
|
|
Log.d(TAG, "pushToStack() called with: serviceId = [" + serviceId + "], videoUrl = [" + videoUrl + "], name = [" + name + "]");
|
|
|
|
}
|
2017-04-09 19:34:00 +02:00
|
|
|
|
2017-09-03 08:04:18 +02: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 + "]");
|
|
|
|
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) {
|
2017-09-03 08:04:18 +02: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
|
|
|
|
2017-09-03 08:04:18 +02: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) {
|
|
|
|
if (DEBUG) Log.d(TAG, "prepareAndHandleInfo() called with: info = [" + info + "], scrollToTop = [" + scrollToTop + "]");
|
2017-04-28 05:58:50 +02:00
|
|
|
|
2017-12-08 15:05:08 +01:00
|
|
|
setInitialData(info.getServiceId(), info.getUrl(), info.getName());
|
2017-09-03 08:04:18 +02:00
|
|
|
pushToStack(serviceId, url, name);
|
|
|
|
showLoading();
|
2017-04-26 21:32:04 +02:00
|
|
|
|
2017-09-03 08:04:18 +02:00
|
|
|
Log.d(TAG, "prepareAndHandleInfo() called parallaxScrollRootView.getScrollY(): " + parallaxScrollRootView.getScrollY());
|
|
|
|
final boolean greaterThanThreshold = parallaxScrollRootView.getScrollY() > (int)
|
|
|
|
(getResources().getDisplayMetrics().heightPixels * .1f);
|
2017-04-28 05:58:50 +02:00
|
|
|
|
2017-09-03 08:04:18 +02:00
|
|
|
if (scrollToTop) parallaxScrollRootView.smoothScrollTo(0, 0);
|
|
|
|
animateView(contentRootLayoutHiding, false, greaterThanThreshold ? 250 : 0, 0, new Runnable() {
|
|
|
|
@Override
|
|
|
|
public void run() {
|
|
|
|
handleResult(info);
|
|
|
|
showContentWithAnimation(120, 0, .01f);
|
|
|
|
}
|
|
|
|
});
|
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() {
|
|
|
|
parallaxScrollRootView.smoothScrollTo(0, 0);
|
|
|
|
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);
|
|
|
|
|
|
|
|
currentInfo = null;
|
|
|
|
if (currentWorker != null) currentWorker.dispose();
|
|
|
|
|
|
|
|
currentWorker = ExtractorHelper.getStreamInfo(serviceId, url, forceLoad)
|
|
|
|
.subscribeOn(Schedulers.io())
|
|
|
|
.observeOn(AndroidSchedulers.mainThread())
|
|
|
|
.subscribe(new Consumer<StreamInfo>() {
|
|
|
|
@Override
|
|
|
|
public void accept(@NonNull StreamInfo result) throws Exception {
|
|
|
|
isLoading.set(false);
|
|
|
|
currentInfo = result;
|
|
|
|
showContentWithAnimation(120, 0, 0);
|
|
|
|
handleResult(result);
|
|
|
|
}
|
|
|
|
}, new Consumer<Throwable>() {
|
|
|
|
@Override
|
|
|
|
public void accept(@NonNull Throwable throwable) throws Exception {
|
|
|
|
isLoading.set(false);
|
|
|
|
onError(throwable);
|
|
|
|
}
|
|
|
|
});
|
|
|
|
}
|
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) {
|
2017-12-08 15:05:08 +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
|
|
|
if (activity instanceof HistoryListener) {
|
|
|
|
((HistoryListener) activity).onAudioPlayed(currentInfo, audioStream);
|
|
|
|
}
|
2017-04-28 05:58:50 +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 {
|
2017-09-03 08:04:18 +02:00
|
|
|
openExternalBackgroundPlayer(audioStream);
|
2017-04-26 21:32:04 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-10-13 02:02:07 +02:00
|
|
|
private void openPopupPlayer(final boolean append) {
|
2017-09-03 08:04:18 +02:00
|
|
|
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M && !PermissionHelper.checkSystemAlertWindowPermission(activity)) {
|
|
|
|
Toast toast = Toast.makeText(activity, R.string.msg_popup_permission, Toast.LENGTH_LONG);
|
|
|
|
TextView messageView = toast.getView().findViewById(android.R.id.message);
|
|
|
|
if (messageView != null) messageView.setGravity(Gravity.CENTER);
|
|
|
|
toast.show();
|
|
|
|
return;
|
|
|
|
}
|
2017-04-26 21:32:04 +02:00
|
|
|
|
2017-09-03 08:04:18 +02:00
|
|
|
if (activity instanceof HistoryListener) {
|
|
|
|
((HistoryListener) activity).onVideoPlayed(currentInfo, getSelectedVideoStream());
|
|
|
|
}
|
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) {
|
2017-11-02 06:33:13 +01:00
|
|
|
NavigationHelper.enqueueOnPopupPlayer(activity, itemQueue);
|
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(
|
|
|
|
activity, PopupVideoPlayer.class, itemQueue, getSelectedVideoStream().resolution
|
|
|
|
);
|
|
|
|
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
|
|
|
|
2017-09-03 08:04:18 +02:00
|
|
|
if (activity instanceof HistoryListener) {
|
|
|
|
((HistoryListener) activity).onVideoPlayed(currentInfo, selectedVideoStream);
|
|
|
|
}
|
2017-04-26 21:32:04 +02:00
|
|
|
|
2017-09-03 08:04:18 +02:00
|
|
|
if (PreferenceManager.getDefaultSharedPreferences(activity).getBoolean(this.getString(R.string.use_external_video_player_key), false)) {
|
|
|
|
openExternalVideoPlayer(selectedVideoStream);
|
2017-04-26 21:32:04 +02:00
|
|
|
} else {
|
2017-09-03 08:04:18 +02:00
|
|
|
openNormalPlayer(selectedVideoStream);
|
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) {
|
2017-11-02 06:33:13 +01:00
|
|
|
NavigationHelper.enqueueOnBackgroundPlayer(activity, itemQueue);
|
2017-10-14 06:07:19 +02:00
|
|
|
} else {
|
2017-11-02 06:33:13 +01:00
|
|
|
NavigationHelper.playOnBackgroundPlayer(activity, itemQueue);
|
2017-10-14 06:07:19 +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 openExternalBackgroundPlayer(AudioStream audioStream) {
|
|
|
|
Intent intent;
|
|
|
|
intent = new Intent();
|
|
|
|
try {
|
|
|
|
intent.setAction(Intent.ACTION_VIEW);
|
2017-12-08 15:05:08 +01:00
|
|
|
intent.setDataAndType(Uri.parse(audioStream.getUrl()), audioStream.getFormat().getMimeType());
|
|
|
|
intent.putExtra(Intent.EXTRA_TITLE, currentInfo.getName());
|
|
|
|
intent.putExtra("title", currentInfo.getName());
|
2017-09-03 08:04:18 +02:00
|
|
|
activity.startActivity(intent);
|
|
|
|
} catch (Exception e) {
|
|
|
|
e.printStackTrace();
|
|
|
|
AlertDialog.Builder builder = new AlertDialog.Builder(activity);
|
|
|
|
builder.setMessage(R.string.no_player_found)
|
|
|
|
.setPositiveButton(R.string.install, new DialogInterface.OnClickListener() {
|
|
|
|
@Override
|
|
|
|
public void onClick(DialogInterface dialog, int which) {
|
|
|
|
Intent intent = new Intent();
|
|
|
|
intent.setAction(Intent.ACTION_VIEW);
|
|
|
|
intent.setData(Uri.parse(activity.getString(R.string.fdroid_vlc_url)));
|
|
|
|
activity.startActivity(intent);
|
|
|
|
}
|
|
|
|
})
|
|
|
|
.setNegativeButton(R.string.cancel, new DialogInterface.OnClickListener() {
|
|
|
|
@Override
|
|
|
|
public void onClick(DialogInterface dialog, int which) {
|
|
|
|
Log.i(TAG, "You unlocked a secret unicorn.");
|
|
|
|
}
|
|
|
|
});
|
|
|
|
builder.create().show();
|
|
|
|
Log.e(TAG, "Either no Streaming player for audio was installed, or something important crashed:");
|
|
|
|
e.printStackTrace();
|
2017-06-27 12:44:20 +02:00
|
|
|
}
|
2017-09-03 08:04:18 +02:00
|
|
|
}
|
2017-06-28 03:39:33 +02:00
|
|
|
|
2017-09-03 08:04:18 +02:00
|
|
|
private void openNormalPlayer(VideoStream selectedVideoStream) {
|
2017-11-02 20:30:26 +01:00
|
|
|
Intent mIntent;
|
|
|
|
boolean useOldPlayer = PlayerHelper.isUsingOldPlayer(activity) || (Build.VERSION.SDK_INT < 16);
|
2017-09-03 08:04:18 +02:00
|
|
|
if (!useOldPlayer) {
|
|
|
|
// ExoPlayer
|
2017-11-02 20:30:26 +01:00
|
|
|
final PlayQueue playQueue = new SinglePlayQueue(currentInfo);
|
2017-12-08 15:05:08 +01:00
|
|
|
mIntent = NavigationHelper.getPlayerIntent(activity, MainVideoPlayer.class, playQueue, getSelectedVideoStream().getResolution());
|
2017-09-03 08:04:18 +02:00
|
|
|
} else {
|
|
|
|
// Internal Player
|
2017-11-02 20:30:26 +01:00
|
|
|
mIntent = new Intent(activity, PlayVideoActivity.class)
|
2017-12-08 15:05:08 +01:00
|
|
|
.putExtra(PlayVideoActivity.VIDEO_TITLE, currentInfo.getName())
|
|
|
|
.putExtra(PlayVideoActivity.STREAM_URL, selectedVideoStream.getUrl())
|
|
|
|
.putExtra(PlayVideoActivity.VIDEO_URL, currentInfo.getUrl())
|
|
|
|
.putExtra(PlayVideoActivity.START_POSITION, currentInfo.getStartPosition());
|
2017-06-28 03:39:33 +02:00
|
|
|
}
|
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
|
|
|
private void openExternalVideoPlayer(VideoStream selectedVideoStream) {
|
|
|
|
// External Player
|
|
|
|
Intent intent = new Intent();
|
|
|
|
try {
|
|
|
|
intent.setAction(Intent.ACTION_VIEW)
|
2017-12-08 15:05:08 +01:00
|
|
|
.setDataAndType(Uri.parse(selectedVideoStream.getUrl()), selectedVideoStream.getFormat().getMimeType())
|
|
|
|
.putExtra(Intent.EXTRA_TITLE, currentInfo.getName())
|
|
|
|
.putExtra("title", currentInfo.getName());
|
2017-09-03 08:04:18 +02:00
|
|
|
this.startActivity(intent);
|
|
|
|
} catch (Exception e) {
|
|
|
|
e.printStackTrace();
|
|
|
|
AlertDialog.Builder builder = new AlertDialog.Builder(activity);
|
|
|
|
builder.setMessage(R.string.no_player_found)
|
|
|
|
.setPositiveButton(R.string.install, new DialogInterface.OnClickListener() {
|
|
|
|
@Override
|
|
|
|
public void onClick(DialogInterface dialog, int which) {
|
|
|
|
Intent intent = new Intent()
|
|
|
|
.setAction(Intent.ACTION_VIEW)
|
|
|
|
.setData(Uri.parse(getString(R.string.fdroid_vlc_url)));
|
|
|
|
startActivity(intent);
|
|
|
|
}
|
|
|
|
})
|
|
|
|
.setNegativeButton(R.string.cancel, null);
|
|
|
|
builder.create().show();
|
2017-06-15 16:26:48 +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
|
|
|
}
|
|
|
|
|
2017-08-12 06:50:25 +02:00
|
|
|
private VideoStream getSelectedVideoStream() {
|
|
|
|
return sortedStreamVideosList.get(actionBarHandler.getSelectedVideoStream());
|
|
|
|
}
|
|
|
|
|
2017-09-03 08:04:18 +02:00
|
|
|
private void prepareDescription(final String descriptionHtml) {
|
|
|
|
if (TextUtils.isEmpty(descriptionHtml)) {
|
|
|
|
return;
|
2017-08-12 06:50:25 +02:00
|
|
|
}
|
2017-03-31 20:15:26 +02:00
|
|
|
|
2017-09-03 08:04:18 +02:00
|
|
|
disposables.add(Single.just(descriptionHtml)
|
|
|
|
.map(new Function<String, Spanned>() {
|
|
|
|
@Override
|
|
|
|
public Spanned apply(@io.reactivex.annotations.NonNull String description) throws Exception {
|
|
|
|
Spanned parsedDescription;
|
|
|
|
if (Build.VERSION.SDK_INT >= 24) {
|
|
|
|
parsedDescription = Html.fromHtml(description, 0);
|
|
|
|
} else {
|
|
|
|
//noinspection deprecation
|
|
|
|
parsedDescription = Html.fromHtml(description);
|
|
|
|
}
|
|
|
|
return parsedDescription;
|
|
|
|
}
|
|
|
|
})
|
|
|
|
.subscribeOn(Schedulers.computation())
|
|
|
|
.observeOn(AndroidSchedulers.mainThread())
|
|
|
|
.subscribe(new Consumer<Spanned>() {
|
|
|
|
@Override
|
|
|
|
public void accept(@io.reactivex.annotations.NonNull Spanned spanned) throws Exception {
|
|
|
|
videoDescriptionView.setText(spanned);
|
|
|
|
videoDescriptionView.setVisibility(View.VISIBLE);
|
|
|
|
}
|
|
|
|
}));
|
2017-03-31 20:15:26 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
private View getSeparatorView() {
|
2017-04-09 19:34:00 +02:00
|
|
|
View separator = new View(activity);
|
2017-03-31 20:15:26 +02:00
|
|
|
LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, 1);
|
|
|
|
int m8 = (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 8, getResources().getDisplayMetrics());
|
|
|
|
int m5 = (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 5, getResources().getDisplayMetrics());
|
|
|
|
params.setMargins(m8, m5, m8, m5);
|
|
|
|
separator.setLayoutParams(params);
|
|
|
|
|
|
|
|
TypedValue typedValue = new TypedValue();
|
2017-09-03 08:04:18 +02:00
|
|
|
activity.getTheme().resolveAttribute(R.attr.separator_color, typedValue, true);
|
2017-03-31 20:15:26 +02:00
|
|
|
separator.setBackgroundColor(typedValue.data);
|
2017-04-26 21:32:04 +02:00
|
|
|
|
2017-03-31 20:15:26 +02:00
|
|
|
return separator;
|
|
|
|
}
|
|
|
|
|
|
|
|
private void setHeightThumbnail() {
|
2017-09-03 08:04:18 +02:00
|
|
|
final DisplayMetrics metrics = getResources().getDisplayMetrics();
|
|
|
|
boolean isPortrait = metrics.heightPixels > metrics.widthPixels;
|
|
|
|
int height = isPortrait ? (int) (metrics.widthPixels / (16.0f / 9.0f)) : (int) (metrics.heightPixels / 2f);
|
2017-03-31 20:15:26 +02:00
|
|
|
thumbnailImageView.setScaleType(isPortrait ? ImageView.ScaleType.CENTER_CROP : ImageView.ScaleType.FIT_CENTER);
|
2017-06-15 16:26:48 +02:00
|
|
|
thumbnailImageView.setLayoutParams(new FrameLayout.LayoutParams(RelativeLayout.LayoutParams.MATCH_PARENT, height));
|
2017-03-31 20:15:26 +02:00
|
|
|
thumbnailImageView.setMinimumHeight(height);
|
|
|
|
}
|
|
|
|
|
2017-04-28 05:58:50 +02:00
|
|
|
private void showContentWithAnimation(long duration, long delay, @FloatRange(from = 0.0f, to = 1.0f) float translationPercent) {
|
|
|
|
int translationY = (int) (getResources().getDisplayMetrics().heightPixels *
|
2017-09-03 08:04:18 +02:00
|
|
|
(translationPercent > 0.0f ? translationPercent : .06f));
|
2017-04-28 05:58:50 +02:00
|
|
|
|
|
|
|
contentRootLayoutHiding.animate().setListener(null).cancel();
|
|
|
|
contentRootLayoutHiding.setAlpha(0f);
|
|
|
|
contentRootLayoutHiding.setTranslationY(translationY);
|
|
|
|
contentRootLayoutHiding.setVisibility(View.VISIBLE);
|
|
|
|
contentRootLayoutHiding.animate().alpha(1f).translationY(0)
|
|
|
|
.setStartDelay(delay).setDuration(duration).setInterpolator(new FastOutSlowInInterpolator()).start();
|
|
|
|
|
|
|
|
uploaderRootLayout.animate().setListener(null).cancel();
|
|
|
|
uploaderRootLayout.setAlpha(0f);
|
|
|
|
uploaderRootLayout.setTranslationY(translationY);
|
|
|
|
uploaderRootLayout.setVisibility(View.VISIBLE);
|
|
|
|
uploaderRootLayout.animate().alpha(1f).translationY(0)
|
|
|
|
.setStartDelay((long) (duration * .5f) + delay).setDuration(duration).setInterpolator(new FastOutSlowInInterpolator()).start();
|
|
|
|
|
|
|
|
if (showRelatedStreams) {
|
|
|
|
relatedStreamRootLayout.animate().setListener(null).cancel();
|
|
|
|
relatedStreamRootLayout.setAlpha(0f);
|
|
|
|
relatedStreamRootLayout.setTranslationY(translationY);
|
|
|
|
relatedStreamRootLayout.setVisibility(View.VISIBLE);
|
|
|
|
relatedStreamRootLayout.animate().alpha(1f).translationY(0)
|
|
|
|
.setStartDelay((long) (duration * .8f) + delay).setDuration(duration).setInterpolator(new FastOutSlowInInterpolator()).start();
|
|
|
|
}
|
|
|
|
}
|
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));
|
2017-05-08 15:33:26 +02:00
|
|
|
animateView(thumbnailImageView, false, 0, 0, new Runnable() {
|
2017-04-26 21:32:04 +02:00
|
|
|
@Override
|
|
|
|
public void run() {
|
|
|
|
animateView(thumbnailImageView, true, 500);
|
|
|
|
}
|
|
|
|
});
|
|
|
|
}
|
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() {
|
|
|
|
super.showLoading();
|
2017-04-09 19:34:00 +02:00
|
|
|
|
2017-09-03 08:04:18 +02:00
|
|
|
animateView(contentRootLayoutHiding, false, 200);
|
|
|
|
animateView(spinnerToolbar, false, 200);
|
|
|
|
animateView(thumbnailPlayButton, 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);
|
|
|
|
videoTitleToggleArrow.setImageResource(R.drawable.arrow_down);
|
|
|
|
videoTitleToggleArrow.setVisibility(View.GONE);
|
|
|
|
videoTitleRoot.setClickable(false);
|
2017-03-31 20:15:26 +02:00
|
|
|
|
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
|
|
|
|
2017-12-08 15:05:08 +01:00
|
|
|
setInitialData(info.getServiceId(), info.getUrl(), info.getName());
|
2017-09-03 08:04:18 +02: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);
|
|
|
|
} 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) {
|
|
|
|
videoCountView.setText(Localization.localizeViewCount(activity, info.getViewCount()));
|
|
|
|
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
|
|
|
|
2017-09-03 08:04:18 +02:00
|
|
|
videoTitleRoot.setClickable(true);
|
|
|
|
videoTitleToggleArrow.setVisibility(View.VISIBLE);
|
|
|
|
videoTitleToggleArrow.setImageResource(R.drawable.arrow_down);
|
|
|
|
videoDescriptionView.setVisibility(View.GONE);
|
|
|
|
videoDescriptionRootLayout.setVisibility(View.GONE);
|
2017-12-08 15:05:08 +01:00
|
|
|
if (!TextUtils.isEmpty(info.getUploadDate())) {
|
|
|
|
videoUploadDateView.setText(Localization.localizeDate(activity, info.getUploadDate()));
|
2017-06-15 16:26:48 +02:00
|
|
|
}
|
2017-12-08 15:05:08 +01:00
|
|
|
prepareDescription(info.getDescription());
|
2017-06-15 16:26:48 +02:00
|
|
|
|
2017-09-03 08:04:18 +02:00
|
|
|
animateView(spinnerToolbar, true, 500);
|
|
|
|
setupActionBarHandler(info);
|
|
|
|
initThumbnailViews(info);
|
|
|
|
initRelatedVideos(info);
|
|
|
|
if (wasRelatedStreamsExpanded) {
|
|
|
|
toggleExpandRelatedVideos(currentInfo);
|
|
|
|
wasRelatedStreamsExpanded = false;
|
2017-06-15 16:26:48 +02:00
|
|
|
}
|
2017-12-08 15:05:08 +01:00
|
|
|
setTitleToUrl(info.getServiceId(), info.getUrl(), info.getName());
|
2017-06-15 16:26:48 +02:00
|
|
|
|
2017-12-08 15:05:08 +01:00
|
|
|
if (!info.getErrors().isEmpty()) {
|
|
|
|
showSnackBarError(info.getErrors(), UserAction.REQUESTED_STREAM, NewPipe.getNameOfService(info.getServiceId()), info.getUrl(), 0);
|
2017-06-15 16:26:48 +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
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-09-03 08:04:18 +02:00
|
|
|
/*//////////////////////////////////////////////////////////////////////////
|
|
|
|
// Stream Results
|
|
|
|
//////////////////////////////////////////////////////////////////////////*/
|
|
|
|
|
|
|
|
@Override
|
|
|
|
protected boolean onError(Throwable exception) {
|
|
|
|
if (super.onError(exception)) return true;
|
|
|
|
|
|
|
|
if (exception instanceof YoutubeStreamExtractor.GemaException) {
|
|
|
|
onBlockedByGemaError();
|
|
|
|
} else if (exception instanceof YoutubeStreamExtractor.LiveStreamException) {
|
|
|
|
showError(getString(R.string.live_streams_not_supported), false);
|
|
|
|
} else if (exception instanceof ContentNotAvailableException) {
|
|
|
|
showError(getString(R.string.content_not_available), false);
|
|
|
|
} else {
|
|
|
|
int errorId = exception instanceof YoutubeStreamExtractor.DecryptException ? R.string.youtube_signature_decryption_error :
|
|
|
|
exception instanceof ParsingException ? R.string.parsing_error : R.string.general_error;
|
|
|
|
onUnrecoverableError(exception, UserAction.REQUESTED_STREAM, NewPipe.getNameOfService(serviceId), url, errorId);
|
2017-06-15 16:26:48 +02:00
|
|
|
}
|
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
|
|
|
|
2017-09-03 08:04:18 +02:00
|
|
|
public void onBlockedByGemaError() {
|
|
|
|
thumbnailBackgroundButton.setOnClickListener(new View.OnClickListener() {
|
|
|
|
@Override
|
|
|
|
public void onClick(View v) {
|
|
|
|
Intent intent = new Intent();
|
|
|
|
intent.setAction(Intent.ACTION_VIEW);
|
|
|
|
intent.setData(Uri.parse(getString(R.string.c3s_url)));
|
|
|
|
startActivity(intent);
|
|
|
|
}
|
|
|
|
});
|
|
|
|
|
|
|
|
showError(getString(R.string.blocked_by_gema), false, R.drawable.gruese_die_gema);
|
2017-08-12 06:50:25 +02:00
|
|
|
}
|
2017-09-03 08:04:18 +02:00
|
|
|
}
|