added viewpager. changed from parallaxscrollview to coordinate layout
This commit is contained in:
parent
e4bef056e6
commit
2e9a860aaa
8 changed files with 484 additions and 528 deletions
|
@ -0,0 +1,82 @@
|
||||||
|
package org.schabi.newpipe.fragments.detail;
|
||||||
|
|
||||||
|
import android.support.annotation.Nullable;
|
||||||
|
import android.support.v4.app.Fragment;
|
||||||
|
import android.support.v4.app.FragmentManager;
|
||||||
|
import android.support.v4.app.FragmentPagerAdapter;
|
||||||
|
import android.support.v4.view.PagerAdapter;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
public class TabAdaptor extends FragmentPagerAdapter {
|
||||||
|
|
||||||
|
private final List<Fragment> mFragmentList = new ArrayList<>();
|
||||||
|
private final List<String> mFragmentTitleList = new ArrayList<>();
|
||||||
|
int baseId = 0;
|
||||||
|
|
||||||
|
public TabAdaptor(FragmentManager fm) {
|
||||||
|
super(fm);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Fragment getItem(int position) {
|
||||||
|
return mFragmentList.get(position);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getCount() {
|
||||||
|
return mFragmentList.size();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Nullable
|
||||||
|
@Override
|
||||||
|
public CharSequence getPageTitle(int position) {
|
||||||
|
return mFragmentTitleList.get(position);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public long getItemId(int position) {
|
||||||
|
// give an ID different from position when position has been changed
|
||||||
|
return baseId + position;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void addFragment(Fragment fragment, String title) {
|
||||||
|
mFragmentList.add(fragment);
|
||||||
|
mFragmentTitleList.add(title);
|
||||||
|
notifyDataSetChanged();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void clearAllItems() {
|
||||||
|
mFragmentList.clear();
|
||||||
|
mFragmentTitleList.clear();
|
||||||
|
notifyDataSetChanged();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void removeItem(int position){
|
||||||
|
mFragmentList.remove(position == 0 ? 0 : position - 1);
|
||||||
|
mFragmentTitleList.remove(position == 0 ? 0 : position - 1);
|
||||||
|
notifyDataSetChanged();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void updateItem(int position, Fragment fragment){
|
||||||
|
mFragmentList.set(position, fragment);
|
||||||
|
// shift the ID returned by getItemId outside the range of all previous fragments
|
||||||
|
// https://stackoverflow.com/questions/10396321/remove-fragment-page-from-viewpager-in-android
|
||||||
|
baseId += getCount() + 1;
|
||||||
|
notifyDataSetChanged();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void updateItem(String title, Fragment fragment){
|
||||||
|
int index = mFragmentTitleList.indexOf(title);
|
||||||
|
if(index != -1){
|
||||||
|
updateItem(index, fragment);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getItemPosition(Object object) {
|
||||||
|
if (mFragmentList.contains(object)) return mFragmentList.indexOf(object);
|
||||||
|
else return POSITION_NONE;
|
||||||
|
}
|
||||||
|
}
|
|
@ -13,7 +13,11 @@ import android.support.annotation.DrawableRes;
|
||||||
import android.support.annotation.FloatRange;
|
import android.support.annotation.FloatRange;
|
||||||
import android.support.annotation.NonNull;
|
import android.support.annotation.NonNull;
|
||||||
import android.support.annotation.Nullable;
|
import android.support.annotation.Nullable;
|
||||||
|
import android.support.design.widget.AppBarLayout;
|
||||||
|
import android.support.design.widget.TabLayout;
|
||||||
|
import android.support.v4.app.Fragment;
|
||||||
import android.support.v4.content.ContextCompat;
|
import android.support.v4.content.ContextCompat;
|
||||||
|
import android.support.v4.view.ViewPager;
|
||||||
import android.support.v4.view.animation.FastOutSlowInInterpolator;
|
import android.support.v4.view.animation.FastOutSlowInInterpolator;
|
||||||
import android.support.v7.app.ActionBar;
|
import android.support.v7.app.ActionBar;
|
||||||
import android.support.v7.app.AlertDialog;
|
import android.support.v7.app.AlertDialog;
|
||||||
|
@ -40,11 +44,9 @@ import android.widget.ImageView;
|
||||||
import android.widget.LinearLayout;
|
import android.widget.LinearLayout;
|
||||||
import android.widget.RelativeLayout;
|
import android.widget.RelativeLayout;
|
||||||
import android.widget.Spinner;
|
import android.widget.Spinner;
|
||||||
import android.widget.TabHost;
|
|
||||||
import android.widget.TextView;
|
import android.widget.TextView;
|
||||||
import android.widget.Toast;
|
import android.widget.Toast;
|
||||||
|
|
||||||
import com.nirhart.parallaxscroll.views.ParallaxScrollView;
|
|
||||||
import com.nostra13.universalimageloader.core.assist.FailReason;
|
import com.nostra13.universalimageloader.core.assist.FailReason;
|
||||||
import com.nostra13.universalimageloader.core.listener.ImageLoadingListener;
|
import com.nostra13.universalimageloader.core.listener.ImageLoadingListener;
|
||||||
import com.nostra13.universalimageloader.core.listener.SimpleImageLoadingListener;
|
import com.nostra13.universalimageloader.core.listener.SimpleImageLoadingListener;
|
||||||
|
@ -56,7 +58,6 @@ import org.schabi.newpipe.extractor.InfoItem;
|
||||||
import org.schabi.newpipe.extractor.NewPipe;
|
import org.schabi.newpipe.extractor.NewPipe;
|
||||||
import org.schabi.newpipe.extractor.StreamingService;
|
import org.schabi.newpipe.extractor.StreamingService;
|
||||||
import org.schabi.newpipe.extractor.comments.CommentsInfo;
|
import org.schabi.newpipe.extractor.comments.CommentsInfo;
|
||||||
import org.schabi.newpipe.extractor.comments.CommentsInfoItem;
|
|
||||||
import org.schabi.newpipe.extractor.exceptions.ContentNotAvailableException;
|
import org.schabi.newpipe.extractor.exceptions.ContentNotAvailableException;
|
||||||
import org.schabi.newpipe.extractor.exceptions.ExtractionException;
|
import org.schabi.newpipe.extractor.exceptions.ExtractionException;
|
||||||
import org.schabi.newpipe.extractor.exceptions.ParsingException;
|
import org.schabi.newpipe.extractor.exceptions.ParsingException;
|
||||||
|
@ -69,6 +70,8 @@ import org.schabi.newpipe.extractor.stream.StreamType;
|
||||||
import org.schabi.newpipe.extractor.stream.VideoStream;
|
import org.schabi.newpipe.extractor.stream.VideoStream;
|
||||||
import org.schabi.newpipe.fragments.BackPressable;
|
import org.schabi.newpipe.fragments.BackPressable;
|
||||||
import org.schabi.newpipe.fragments.BaseStateFragment;
|
import org.schabi.newpipe.fragments.BaseStateFragment;
|
||||||
|
import org.schabi.newpipe.fragments.list.comments.CommentsFragment;
|
||||||
|
import org.schabi.newpipe.fragments.list.videos.RelatedVideosFragment;
|
||||||
import org.schabi.newpipe.info_list.InfoItemBuilder;
|
import org.schabi.newpipe.info_list.InfoItemBuilder;
|
||||||
import org.schabi.newpipe.info_list.InfoItemDialog;
|
import org.schabi.newpipe.info_list.InfoItemDialog;
|
||||||
import org.schabi.newpipe.local.dialog.PlaylistAppendDialog;
|
import org.schabi.newpipe.local.dialog.PlaylistAppendDialog;
|
||||||
|
@ -117,13 +120,6 @@ public class VideoDetailFragment
|
||||||
View.OnLongClickListener {
|
View.OnLongClickListener {
|
||||||
public static final String AUTO_PLAY = "auto_play";
|
public static final String AUTO_PLAY = "auto_play";
|
||||||
|
|
||||||
// Amount of videos to show on start
|
|
||||||
private static final int INITIAL_RELATED_VIDEOS = 8;
|
|
||||||
// Amount of comments to show on start
|
|
||||||
public static final int INITIAL_COMMENTS = 8;
|
|
||||||
|
|
||||||
private InfoItemBuilder infoItemBuilder = null;
|
|
||||||
|
|
||||||
private int updateFlags = 0;
|
private int updateFlags = 0;
|
||||||
private static final int RELATED_STREAMS_UPDATE_FLAG = 0x1;
|
private static final int RELATED_STREAMS_UPDATE_FLAG = 0x1;
|
||||||
private static final int RESOLUTIONS_MENU_UPDATE_FLAG = 0x2;
|
private static final int RESOLUTIONS_MENU_UPDATE_FLAG = 0x2;
|
||||||
|
@ -133,8 +129,6 @@ public class VideoDetailFragment
|
||||||
private boolean autoPlayEnabled;
|
private boolean autoPlayEnabled;
|
||||||
private boolean showRelatedStreams;
|
private boolean showRelatedStreams;
|
||||||
private boolean showComments;
|
private boolean showComments;
|
||||||
private boolean isCommentsSupported;
|
|
||||||
private boolean wasRelatedStreamsExpanded = false;
|
|
||||||
|
|
||||||
@State
|
@State
|
||||||
protected int serviceId = Constants.NO_SERVICE_ID;
|
protected int serviceId = Constants.NO_SERVICE_ID;
|
||||||
|
@ -144,7 +138,6 @@ public class VideoDetailFragment
|
||||||
protected String url;
|
protected String url;
|
||||||
|
|
||||||
private StreamInfo currentInfo;
|
private StreamInfo currentInfo;
|
||||||
private CommentsInfo commentsInfo;
|
|
||||||
private Disposable currentWorker;
|
private Disposable currentWorker;
|
||||||
@NonNull
|
@NonNull
|
||||||
private CompositeDisposable disposables = new CompositeDisposable();
|
private CompositeDisposable disposables = new CompositeDisposable();
|
||||||
|
@ -160,7 +153,6 @@ public class VideoDetailFragment
|
||||||
|
|
||||||
private Spinner spinnerToolbar;
|
private Spinner spinnerToolbar;
|
||||||
|
|
||||||
private ParallaxScrollView parallaxScrollRootView;
|
|
||||||
private LinearLayout contentRootLayoutHiding;
|
private LinearLayout contentRootLayoutHiding;
|
||||||
|
|
||||||
private View thumbnailBackgroundButton;
|
private View thumbnailBackgroundButton;
|
||||||
|
@ -193,21 +185,13 @@ public class VideoDetailFragment
|
||||||
private ImageView thumbsDownImageView;
|
private ImageView thumbsDownImageView;
|
||||||
private TextView thumbsDisabledTextView;
|
private TextView thumbsDisabledTextView;
|
||||||
|
|
||||||
private TextView nextStreamTitle;
|
private static final String COMMENTS_TAB_TAG = "COMMENTS";
|
||||||
private LinearLayout relatedStreamRootLayout;
|
private static final String RELATED_TAB_TAG = "NEXT VIDEO";
|
||||||
private LinearLayout relatedStreamsView;
|
|
||||||
private ImageButton relatedStreamExpandButton;
|
|
||||||
|
|
||||||
private LinearLayout commentsRootLayout;
|
|
||||||
private View commentsEmptyStateView;
|
|
||||||
private LinearLayout commentsView;
|
|
||||||
private ImageButton commentsExpandButton;
|
|
||||||
private Disposable commentsDisposable;
|
|
||||||
|
|
||||||
private TabHost tabHost;
|
|
||||||
private static final String COMMENTS_TAB_TAG = "CommentsTab";
|
|
||||||
private static final String RELATED_TAB_TAG = "RelatedTab";
|
|
||||||
|
|
||||||
|
private AppBarLayout appBarLayout;
|
||||||
|
private ViewPager viewPager;
|
||||||
|
private TabAdaptor pageAdapter;
|
||||||
|
private TabLayout tabLayout;
|
||||||
|
|
||||||
|
|
||||||
/*////////////////////////////////////////////////////////////////////////*/
|
/*////////////////////////////////////////////////////////////////////////*/
|
||||||
|
@ -247,7 +231,6 @@ public class VideoDetailFragment
|
||||||
public void onPause() {
|
public void onPause() {
|
||||||
super.onPause();
|
super.onPause();
|
||||||
if (currentWorker != null) currentWorker.dispose();
|
if (currentWorker != null) currentWorker.dispose();
|
||||||
if (commentsDisposable != null) commentsDisposable.dispose();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -256,10 +239,9 @@ public class VideoDetailFragment
|
||||||
|
|
||||||
if (updateFlags != 0) {
|
if (updateFlags != 0) {
|
||||||
if (!isLoading.get() && currentInfo != null) {
|
if (!isLoading.get() && currentInfo != null) {
|
||||||
if ((updateFlags & RELATED_STREAMS_UPDATE_FLAG) != 0)
|
if ((updateFlags & RELATED_STREAMS_UPDATE_FLAG) != 0) startLoading(false);
|
||||||
initRelatedVideos(currentInfo);
|
|
||||||
if ((updateFlags & RESOLUTIONS_MENU_UPDATE_FLAG) != 0) setupActionBar(currentInfo);
|
if ((updateFlags & RESOLUTIONS_MENU_UPDATE_FLAG) != 0) setupActionBar(currentInfo);
|
||||||
if ((updateFlags & COMMENTS_UPDATE_FLAG) != 0) initComments(commentsInfo);
|
if ((updateFlags & COMMENTS_UPDATE_FLAG) != 0) startLoading(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((updateFlags & TOOLBAR_ITEMS_UPDATE_FLAG) != 0
|
if ((updateFlags & TOOLBAR_ITEMS_UPDATE_FLAG) != 0
|
||||||
|
@ -273,8 +255,6 @@ public class VideoDetailFragment
|
||||||
// Check if it was loading when the fragment was stopped/paused,
|
// Check if it was loading when the fragment was stopped/paused,
|
||||||
if (wasLoading.getAndSet(false)) {
|
if (wasLoading.getAndSet(false)) {
|
||||||
selectAndLoadVideo(serviceId, url, name);
|
selectAndLoadVideo(serviceId, url, name);
|
||||||
}else{
|
|
||||||
loadComments(false);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -285,10 +265,8 @@ public class VideoDetailFragment
|
||||||
.unregisterOnSharedPreferenceChangeListener(this);
|
.unregisterOnSharedPreferenceChangeListener(this);
|
||||||
|
|
||||||
if (currentWorker != null) currentWorker.dispose();
|
if (currentWorker != null) currentWorker.dispose();
|
||||||
if (commentsDisposable != null) commentsDisposable.dispose();
|
|
||||||
if (disposables != null) disposables.clear();
|
if (disposables != null) disposables.clear();
|
||||||
currentWorker = null;
|
currentWorker = null;
|
||||||
commentsDisposable = null;
|
|
||||||
disposables = null;
|
disposables = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -339,7 +317,6 @@ public class VideoDetailFragment
|
||||||
|
|
||||||
private static final String INFO_KEY = "info_key";
|
private static final String INFO_KEY = "info_key";
|
||||||
private static final String STACK_KEY = "stack_key";
|
private static final String STACK_KEY = "stack_key";
|
||||||
private static final String WAS_RELATED_EXPANDED_KEY = "was_related_expanded_key";
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onSaveInstanceState(Bundle outState) {
|
public void onSaveInstanceState(Bundle outState) {
|
||||||
|
@ -348,10 +325,6 @@ public class VideoDetailFragment
|
||||||
// Check if the next video label and video is visible,
|
// Check if the next video label and video is visible,
|
||||||
// if it is, include the two elements in the next check
|
// if it is, include the two elements in the next check
|
||||||
int nextCount = currentInfo != null && currentInfo.getNextVideo() != null ? 2 : 0;
|
int nextCount = currentInfo != null && currentInfo.getNextVideo() != null ? 2 : 0;
|
||||||
if (relatedStreamsView != null
|
|
||||||
&& relatedStreamsView.getChildCount() > INITIAL_RELATED_VIDEOS + nextCount) {
|
|
||||||
outState.putSerializable(WAS_RELATED_EXPANDED_KEY, true);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!isLoading.get() && currentInfo != null && isVisible()) {
|
if (!isLoading.get() && currentInfo != null && isVisible()) {
|
||||||
outState.putSerializable(INFO_KEY, currentInfo);
|
outState.putSerializable(INFO_KEY, currentInfo);
|
||||||
|
@ -364,7 +337,6 @@ public class VideoDetailFragment
|
||||||
protected void onRestoreInstanceState(@NonNull Bundle savedState) {
|
protected void onRestoreInstanceState(@NonNull Bundle savedState) {
|
||||||
super.onRestoreInstanceState(savedState);
|
super.onRestoreInstanceState(savedState);
|
||||||
|
|
||||||
wasRelatedStreamsExpanded = savedState.getBoolean(WAS_RELATED_EXPANDED_KEY, false);
|
|
||||||
Serializable serializable = savedState.getSerializable(INFO_KEY);
|
Serializable serializable = savedState.getSerializable(INFO_KEY);
|
||||||
if (serializable instanceof StreamInfo) {
|
if (serializable instanceof StreamInfo) {
|
||||||
//noinspection unchecked
|
//noinspection unchecked
|
||||||
|
@ -432,12 +404,6 @@ public class VideoDetailFragment
|
||||||
case R.id.detail_title_root_layout:
|
case R.id.detail_title_root_layout:
|
||||||
toggleTitleAndDescription();
|
toggleTitleAndDescription();
|
||||||
break;
|
break;
|
||||||
case R.id.detail_related_streams_expand:
|
|
||||||
toggleExpandRelatedVideos(currentInfo);
|
|
||||||
break;
|
|
||||||
case R.id.detail_comments_expand:
|
|
||||||
toggleExpandComments(commentsInfo);
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -472,41 +438,6 @@ public class VideoDetailFragment
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void toggleExpandRelatedVideos(StreamInfo info) {
|
|
||||||
if (DEBUG) Log.d(TAG, "toggleExpandRelatedVideos() called with: info = [" + info + "]");
|
|
||||||
if (!showRelatedStreams) return;
|
|
||||||
|
|
||||||
int nextCount = info.getNextVideo() != null ? 2 : 0;
|
|
||||||
int initialCount = INITIAL_RELATED_VIDEOS + nextCount;
|
|
||||||
|
|
||||||
if (relatedStreamsView.getChildCount() > initialCount) {
|
|
||||||
relatedStreamsView.removeViews(initialCount,
|
|
||||||
relatedStreamsView.getChildCount() - (initialCount));
|
|
||||||
relatedStreamExpandButton.setImageDrawable(ContextCompat.getDrawable(
|
|
||||||
activity, ThemeHelper.resolveResourceIdFromAttr(activity, R.attr.expand)));
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
//Log.d(TAG, "toggleExpandRelatedVideos() called with: info = [" + info + "], from = [" + INITIAL_RELATED_VIDEOS + "]");
|
|
||||||
for (int i = INITIAL_RELATED_VIDEOS; i < info.getRelatedStreams().size(); i++) {
|
|
||||||
InfoItem item = info.getRelatedStreams().get(i);
|
|
||||||
//Log.d(TAG, "i = " + i);
|
|
||||||
relatedStreamsView.addView(infoItemBuilder.buildView(relatedStreamsView, item));
|
|
||||||
}
|
|
||||||
relatedStreamExpandButton.setImageDrawable(
|
|
||||||
ContextCompat.getDrawable(activity,
|
|
||||||
ThemeHelper.resolveResourceIdFromAttr(activity, R.attr.collapse)));
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
private void toggleExpandComments(CommentsInfo info) {
|
|
||||||
if (DEBUG) Log.d(TAG, "toggleExpandComments() called with: info = [" + info + "]");
|
|
||||||
if (!showComments || null == info) return;
|
|
||||||
|
|
||||||
NavigationHelper.openCommentsFragment(getFragmentManager(), serviceId, url, name);
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
/*//////////////////////////////////////////////////////////////////////////
|
/*//////////////////////////////////////////////////////////////////////////
|
||||||
// Init
|
// Init
|
||||||
//////////////////////////////////////////////////////////////////////////*/
|
//////////////////////////////////////////////////////////////////////////*/
|
||||||
|
@ -516,8 +447,6 @@ public class VideoDetailFragment
|
||||||
super.initViews(rootView, savedInstanceState);
|
super.initViews(rootView, savedInstanceState);
|
||||||
spinnerToolbar = activity.findViewById(R.id.toolbar).findViewById(R.id.toolbar_spinner);
|
spinnerToolbar = activity.findViewById(R.id.toolbar).findViewById(R.id.toolbar_spinner);
|
||||||
|
|
||||||
parallaxScrollRootView = rootView.findViewById(R.id.detail_main_content);
|
|
||||||
|
|
||||||
thumbnailBackgroundButton = rootView.findViewById(R.id.detail_thumbnail_root_layout);
|
thumbnailBackgroundButton = rootView.findViewById(R.id.detail_thumbnail_root_layout);
|
||||||
thumbnailImageView = rootView.findViewById(R.id.detail_thumbnail_image_view);
|
thumbnailImageView = rootView.findViewById(R.id.detail_thumbnail_image_view);
|
||||||
thumbnailPlayButton = rootView.findViewById(R.id.detail_thumbnail_play_button);
|
thumbnailPlayButton = rootView.findViewById(R.id.detail_thumbnail_play_button);
|
||||||
|
@ -553,67 +482,21 @@ public class VideoDetailFragment
|
||||||
uploaderTextView = rootView.findViewById(R.id.detail_uploader_text_view);
|
uploaderTextView = rootView.findViewById(R.id.detail_uploader_text_view);
|
||||||
uploaderThumb = rootView.findViewById(R.id.detail_uploader_thumbnail_view);
|
uploaderThumb = rootView.findViewById(R.id.detail_uploader_thumbnail_view);
|
||||||
|
|
||||||
StreamingService service = null;
|
appBarLayout = rootView.findViewById(R.id.appbarlayout);
|
||||||
try {
|
viewPager = rootView.findViewById(R.id.viewpager);
|
||||||
service = NewPipe.getService(serviceId);
|
pageAdapter = new TabAdaptor(getChildFragmentManager());
|
||||||
} catch (ExtractionException e) {
|
viewPager.setAdapter(pageAdapter);
|
||||||
onError(e);
|
tabLayout = rootView.findViewById(R.id.tablayout);
|
||||||
}
|
tabLayout.setupWithViewPager(viewPager);
|
||||||
|
|
||||||
if (service.isCommentsSupported()) {
|
|
||||||
isCommentsSupported = true;
|
|
||||||
initTabs(rootView);
|
|
||||||
}
|
|
||||||
|
|
||||||
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);
|
|
||||||
relatedStreamExpandButton = rootView.findViewById(R.id.detail_related_streams_expand);
|
|
||||||
|
|
||||||
commentsRootLayout = rootView.findViewById(R.id.detail_comments_root_layout);
|
|
||||||
commentsEmptyStateView = rootView.findViewById(R.id.comments_empty_state_view);
|
|
||||||
commentsView = rootView.findViewById(R.id.detail_comments_view);
|
|
||||||
commentsExpandButton = rootView.findViewById(R.id.detail_comments_expand);
|
|
||||||
|
|
||||||
infoItemBuilder = new InfoItemBuilder(activity);
|
|
||||||
setHeightThumbnail();
|
setHeightThumbnail();
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void initTabs(View rootView) {
|
|
||||||
tabHost = (TabHost) rootView.findViewById(R.id.tab_host);
|
|
||||||
tabHost.setup();
|
|
||||||
|
|
||||||
TabHost.TabSpec commentsTab = tabHost.newTabSpec(COMMENTS_TAB_TAG);
|
|
||||||
commentsTab.setContent(R.id.detail_comments_root_layout);
|
|
||||||
commentsTab.setIndicator(getString(R.string.comments));
|
|
||||||
|
|
||||||
TabHost.TabSpec relatedVideosTab = tabHost.newTabSpec(RELATED_TAB_TAG);
|
|
||||||
relatedVideosTab.setContent(R.id.detail_related_streams_root_layout);
|
|
||||||
relatedVideosTab.setIndicator(getString(R.string.next_video_title));
|
|
||||||
|
|
||||||
tabHost.addTab(commentsTab);
|
|
||||||
tabHost.addTab(relatedVideosTab);
|
|
||||||
|
|
||||||
//show comments tab by default
|
|
||||||
tabHost.setCurrentTabByTag(COMMENTS_TAB_TAG);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void initListeners() {
|
protected void initListeners() {
|
||||||
super.initListeners();
|
super.initListeners();
|
||||||
infoItemBuilder.setOnStreamSelectedListener(new OnClickGesture<StreamInfoItem>() {
|
|
||||||
@Override
|
|
||||||
public void selected(StreamInfoItem selectedItem) {
|
|
||||||
selectAndLoadVideo(selectedItem.getServiceId(), selectedItem.getUrl(), selectedItem.getName());
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void held(StreamInfoItem selectedItem) {
|
|
||||||
showStreamDialog(selectedItem);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
videoTitleRoot.setOnClickListener(this);
|
videoTitleRoot.setOnClickListener(this);
|
||||||
uploaderRootLayout.setOnClickListener(this);
|
uploaderRootLayout.setOnClickListener(this);
|
||||||
|
@ -623,8 +506,6 @@ public class VideoDetailFragment
|
||||||
detailControlsAddToPlaylist.setOnClickListener(this);
|
detailControlsAddToPlaylist.setOnClickListener(this);
|
||||||
detailControlsDownload.setOnClickListener(this);
|
detailControlsDownload.setOnClickListener(this);
|
||||||
detailControlsDownload.setOnLongClickListener(this);
|
detailControlsDownload.setOnLongClickListener(this);
|
||||||
relatedStreamExpandButton.setOnClickListener(this);
|
|
||||||
commentsExpandButton.setOnClickListener(this);
|
|
||||||
|
|
||||||
detailControlsBackground.setLongClickable(true);
|
detailControlsBackground.setLongClickable(true);
|
||||||
detailControlsPopup.setLongClickable(true);
|
detailControlsPopup.setLongClickable(true);
|
||||||
|
@ -707,98 +588,6 @@ public class VideoDetailFragment
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void initRelatedVideos(StreamInfo info) {
|
|
||||||
if (relatedStreamsView.getChildCount() > 0) relatedStreamsView.removeAllViews();
|
|
||||||
|
|
||||||
if (info.getNextVideo() != null && showRelatedStreams) {
|
|
||||||
nextStreamTitle.setVisibility(View.VISIBLE);
|
|
||||||
relatedStreamsView.addView(
|
|
||||||
infoItemBuilder.buildView(relatedStreamsView, info.getNextVideo()));
|
|
||||||
relatedStreamsView.addView(getSeparatorView());
|
|
||||||
showRelatedStreamsIfSelected();
|
|
||||||
} else nextStreamTitle.setVisibility(View.GONE);
|
|
||||||
|
|
||||||
if (info.getRelatedStreams() != null
|
|
||||||
&& !info.getRelatedStreams().isEmpty() && showRelatedStreams) {
|
|
||||||
//long first = System.nanoTime(), each;
|
|
||||||
int to = info.getRelatedStreams().size() >= INITIAL_RELATED_VIDEOS
|
|
||||||
? INITIAL_RELATED_VIDEOS
|
|
||||||
: info.getRelatedStreams().size();
|
|
||||||
for (int i = 0; i < to; i++) {
|
|
||||||
InfoItem item = info.getRelatedStreams().get(i);
|
|
||||||
//each = System.nanoTime();
|
|
||||||
relatedStreamsView.addView(infoItemBuilder.buildView(relatedStreamsView, item));
|
|
||||||
//if (DEBUG) Log.d(TAG, "each took " + ((System.nanoTime() - each) / 1000000L) + "ms");
|
|
||||||
}
|
|
||||||
//if (DEBUG) Log.d(TAG, "Total time " + ((System.nanoTime() - first) / 1000000L) + "ms");
|
|
||||||
|
|
||||||
showRelatedStreamsIfSelected();
|
|
||||||
relatedStreamExpandButton.setVisibility(View.VISIBLE);
|
|
||||||
|
|
||||||
relatedStreamExpandButton.setImageDrawable(ContextCompat.getDrawable(
|
|
||||||
activity, ThemeHelper.resolveResourceIdFromAttr(activity, R.attr.expand)));
|
|
||||||
} else {
|
|
||||||
if (info.getNextVideo() == null) relatedStreamRootLayout.setVisibility(View.GONE);
|
|
||||||
relatedStreamExpandButton.setVisibility(View.GONE);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
private void showRelatedStreamsIfSelected() {
|
|
||||||
if (null == tabHost || tabHost.getCurrentTabTag().contentEquals(RELATED_TAB_TAG)) {
|
|
||||||
relatedStreamRootLayout.setVisibility(View.VISIBLE);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void initComments(CommentsInfo info) {
|
|
||||||
clearComments();
|
|
||||||
|
|
||||||
if(null == info || null == info.getRelatedItems() || info.getRelatedItems().size() == 0){
|
|
||||||
commentsEmptyStateView.setVisibility(View.VISIBLE);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
commentsEmptyStateView.setVisibility(View.GONE);
|
|
||||||
|
|
||||||
List<CommentsInfoItem> initialComments = info.getRelatedItems();
|
|
||||||
if (null != info && initialComments != null
|
|
||||||
&& !initialComments.isEmpty() && showComments) {
|
|
||||||
//long first = System.nanoTime(), each;
|
|
||||||
int to = initialComments.size() >= INITIAL_COMMENTS
|
|
||||||
? INITIAL_COMMENTS
|
|
||||||
: initialComments.size();
|
|
||||||
for (int i = 0; i < to; i++) {
|
|
||||||
InfoItem item = initialComments.get(i);
|
|
||||||
//each = System.nanoTime();
|
|
||||||
commentsView.addView(infoItemBuilder.buildView(commentsView, item));
|
|
||||||
//if (DEBUG) Log.d(TAG, "each took " + ((System.nanoTime() - each) / 1000000L) + "ms");
|
|
||||||
}
|
|
||||||
//if (DEBUG) Log.d(TAG, "Total time " + ((System.nanoTime() - first) / 1000000L) + "ms");
|
|
||||||
|
|
||||||
showCommentsIfSelected();
|
|
||||||
if(initialComments.size() > INITIAL_COMMENTS){
|
|
||||||
commentsExpandButton.setVisibility(View.VISIBLE);
|
|
||||||
commentsExpandButton.setImageDrawable(ContextCompat.getDrawable(
|
|
||||||
activity, ThemeHelper.resolveResourceIdFromAttr(activity, R.attr.expand)));
|
|
||||||
}else{
|
|
||||||
commentsExpandButton.setVisibility(View.GONE);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
commentsRootLayout.setVisibility(View.GONE);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
private void showCommentsIfSelected() {
|
|
||||||
if (null == tabHost || tabHost.getCurrentTabTag().contentEquals(COMMENTS_TAB_TAG)) {
|
|
||||||
commentsRootLayout.setVisibility(View.VISIBLE);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void clearComments(){
|
|
||||||
if (commentsView.getChildCount() > 0) commentsView.removeAllViews();
|
|
||||||
commentsExpandButton.setVisibility(View.GONE);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*//////////////////////////////////////////////////////////////////////////
|
/*//////////////////////////////////////////////////////////////////////////
|
||||||
// Menu
|
// Menu
|
||||||
//////////////////////////////////////////////////////////////////////////*/
|
//////////////////////////////////////////////////////////////////////////*/
|
||||||
|
@ -979,23 +768,18 @@ public class VideoDetailFragment
|
||||||
setInitialData(info.getServiceId(), info.getOriginalUrl(), info.getName());
|
setInitialData(info.getServiceId(), info.getOriginalUrl(), info.getName());
|
||||||
pushToStack(serviceId, url, name);
|
pushToStack(serviceId, url, name);
|
||||||
showLoading();
|
showLoading();
|
||||||
|
initTabs();
|
||||||
|
|
||||||
Log.d(TAG, "prepareAndHandleInfo() called parallaxScrollRootView.getScrollY(): "
|
if (scrollToTop) appBarLayout.setExpanded(true, true);
|
||||||
+ parallaxScrollRootView.getScrollY());
|
|
||||||
final boolean greaterThanThreshold = parallaxScrollRootView.getScrollY() > (int)
|
|
||||||
(getResources().getDisplayMetrics().heightPixels * .1f);
|
|
||||||
|
|
||||||
if (scrollToTop) parallaxScrollRootView.smoothScrollTo(0, 0);
|
|
||||||
animateView(contentRootLayoutHiding,
|
animateView(contentRootLayoutHiding,
|
||||||
false,
|
false, 0, 0, () -> {
|
||||||
greaterThanThreshold ? 250 : 0, 0, () -> {
|
|
||||||
handleResult(info);
|
handleResult(info);
|
||||||
showContentWithAnimation(120, 0, .01f);
|
showContentWithAnimation(120, 0, .01f);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
protected void prepareAndLoadInfo() {
|
protected void prepareAndLoadInfo() {
|
||||||
parallaxScrollRootView.smoothScrollTo(0, 0);
|
appBarLayout.setExpanded(true, true);
|
||||||
pushToStack(serviceId, url, name);
|
pushToStack(serviceId, url, name);
|
||||||
startLoading(false);
|
startLoading(false);
|
||||||
}
|
}
|
||||||
|
@ -1004,6 +788,7 @@ public class VideoDetailFragment
|
||||||
public void startLoading(boolean forceLoad) {
|
public void startLoading(boolean forceLoad) {
|
||||||
super.startLoading(forceLoad);
|
super.startLoading(forceLoad);
|
||||||
|
|
||||||
|
initTabs();
|
||||||
currentInfo = null;
|
currentInfo = null;
|
||||||
if (currentWorker != null) currentWorker.dispose();
|
if (currentWorker != null) currentWorker.dispose();
|
||||||
|
|
||||||
|
@ -1020,26 +805,29 @@ public class VideoDetailFragment
|
||||||
onError(throwable);
|
onError(throwable);
|
||||||
});
|
});
|
||||||
|
|
||||||
loadComments(forceLoad);
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void loadComments(boolean forceLoad) {
|
private void initTabs() {
|
||||||
if(isCommentsSupported && showComments){
|
pageAdapter.clearAllItems();
|
||||||
clearComments();
|
|
||||||
commentsInfo = null;
|
|
||||||
if (commentsDisposable != null) commentsDisposable.dispose();
|
|
||||||
|
|
||||||
commentsDisposable = ExtractorHelper.getCommentsInfo(serviceId, url, forceLoad)
|
if(shouldShowComments()){
|
||||||
.subscribeOn(Schedulers.io())
|
pageAdapter.addFragment(CommentsFragment.getInstance(serviceId, url, name), COMMENTS_TAB_TAG);
|
||||||
.observeOn(AndroidSchedulers.mainThread())
|
}
|
||||||
.subscribe((@NonNull CommentsInfo result) -> {
|
|
||||||
commentsInfo = result;
|
if(showRelatedStreams){
|
||||||
showCommentsWithAnimation(120, 0,0);
|
pageAdapter.addFragment(new Fragment(), RELATED_TAB_TAG);
|
||||||
initComments(commentsInfo);
|
}
|
||||||
}, (@NonNull Throwable throwable) -> {
|
|
||||||
onCommentsError(throwable);
|
if(pageAdapter.getCount() < 2){
|
||||||
});
|
tabLayout.setVisibility(View.GONE);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean shouldShowComments() {
|
||||||
|
try {
|
||||||
|
return showComments && NewPipe.getService(serviceId).isCommentsSupported();
|
||||||
|
} catch (ExtractionException e) {
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1230,41 +1018,6 @@ public class VideoDetailFragment
|
||||||
.setInterpolator(new FastOutSlowInInterpolator())
|
.setInterpolator(new FastOutSlowInInterpolator())
|
||||||
.start();
|
.start();
|
||||||
|
|
||||||
if (showRelatedStreams && (null == tabHost || tabHost.getCurrentTabTag().contentEquals(RELATED_TAB_TAG))) {
|
|
||||||
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();
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
private void showCommentsWithAnimation(long duration,
|
|
||||||
long delay,
|
|
||||||
@FloatRange(from = 0.0f, to = 1.0f) float translationPercent) {
|
|
||||||
int translationY = (int) (getResources().getDisplayMetrics().heightPixels *
|
|
||||||
(translationPercent > 0.0f ? translationPercent : .06f));
|
|
||||||
|
|
||||||
if (showComments && (null == tabHost || tabHost.getCurrentTabTag().contentEquals(COMMENTS_TAB_TAG))) {
|
|
||||||
commentsRootLayout.animate().setListener(null).cancel();
|
|
||||||
commentsRootLayout.setAlpha(0f);
|
|
||||||
commentsRootLayout.setTranslationY(translationY);
|
|
||||||
commentsRootLayout.setVisibility(View.VISIBLE);
|
|
||||||
commentsRootLayout.animate()
|
|
||||||
.alpha(1f)
|
|
||||||
.translationY(0)
|
|
||||||
.setStartDelay((long) (duration * .8f) + delay)
|
|
||||||
.setDuration(duration)
|
|
||||||
.setInterpolator(new FastOutSlowInInterpolator())
|
|
||||||
.start();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
protected void setInitialData(int serviceId, String url, String name) {
|
protected void setInitialData(int serviceId, String url, String name) {
|
||||||
|
@ -1324,6 +1077,11 @@ public class VideoDetailFragment
|
||||||
super.handleResult(info);
|
super.handleResult(info);
|
||||||
|
|
||||||
setInitialData(info.getServiceId(), info.getOriginalUrl(), info.getName());
|
setInitialData(info.getServiceId(), info.getOriginalUrl(), info.getName());
|
||||||
|
|
||||||
|
if(showRelatedStreams){
|
||||||
|
pageAdapter.updateItem(RELATED_TAB_TAG, RelatedVideosFragment.getInstance(currentInfo));
|
||||||
|
}
|
||||||
|
|
||||||
pushToStack(serviceId, url, name);
|
pushToStack(serviceId, url, name);
|
||||||
|
|
||||||
animateView(thumbnailPlayButton, true, 200);
|
animateView(thumbnailPlayButton, true, 200);
|
||||||
|
@ -1398,12 +1156,6 @@ public class VideoDetailFragment
|
||||||
animateView(spinnerToolbar, true, 500);
|
animateView(spinnerToolbar, true, 500);
|
||||||
setupActionBar(info);
|
setupActionBar(info);
|
||||||
initThumbnailViews(info);
|
initThumbnailViews(info);
|
||||||
initRelatedVideos(info);
|
|
||||||
|
|
||||||
if (wasRelatedStreamsExpanded) {
|
|
||||||
toggleExpandRelatedVideos(currentInfo);
|
|
||||||
wasRelatedStreamsExpanded = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
setTitleToUrl(info.getServiceId(), info.getUrl(), info.getName());
|
setTitleToUrl(info.getServiceId(), info.getUrl(), info.getName());
|
||||||
setTitleToUrl(info.getServiceId(), info.getOriginalUrl(), info.getName());
|
setTitleToUrl(info.getServiceId(), info.getOriginalUrl(), info.getName());
|
||||||
|
|
|
@ -71,7 +71,6 @@ import static org.schabi.newpipe.util.AnimationUtils.animateView;
|
||||||
public class CommentsFragment extends BaseListInfoFragment<CommentsInfo> {
|
public class CommentsFragment extends BaseListInfoFragment<CommentsInfo> {
|
||||||
|
|
||||||
private CompositeDisposable disposables = new CompositeDisposable();
|
private CompositeDisposable disposables = new CompositeDisposable();
|
||||||
private boolean initialLoad = true;
|
|
||||||
/*//////////////////////////////////////////////////////////////////////////
|
/*//////////////////////////////////////////////////////////////////////////
|
||||||
// Views
|
// Views
|
||||||
//////////////////////////////////////////////////////////////////////////*/
|
//////////////////////////////////////////////////////////////////////////*/
|
||||||
|
@ -94,11 +93,6 @@ public class CommentsFragment extends BaseListInfoFragment<CommentsInfo> {
|
||||||
public void setUserVisibleHint(boolean isVisibleToUser) {
|
public void setUserVisibleHint(boolean isVisibleToUser) {
|
||||||
super.setUserVisibleHint(isVisibleToUser);
|
super.setUserVisibleHint(isVisibleToUser);
|
||||||
mIsVisibleToUser = isVisibleToUser;
|
mIsVisibleToUser = isVisibleToUser;
|
||||||
if(activity != null
|
|
||||||
&& useAsFrontPage
|
|
||||||
&& isVisibleToUser) {
|
|
||||||
setTitle(currentInfo != null ? currentInfo.getName() : name);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -117,15 +111,6 @@ public class CommentsFragment extends BaseListInfoFragment<CommentsInfo> {
|
||||||
if (disposables != null) disposables.clear();
|
if (disposables != null) disposables.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
/*//////////////////////////////////////////////////////////////////////////
|
|
||||||
// Init
|
|
||||||
//////////////////////////////////////////////////////////////////////////*/
|
|
||||||
|
|
||||||
|
|
||||||
/*//////////////////////////////////////////////////////////////////////////
|
|
||||||
// Menu
|
|
||||||
//////////////////////////////////////////////////////////////////////////*/
|
|
||||||
|
|
||||||
|
|
||||||
/*//////////////////////////////////////////////////////////////////////////
|
/*//////////////////////////////////////////////////////////////////////////
|
||||||
// Load and handle
|
// Load and handle
|
||||||
|
@ -153,10 +138,6 @@ public class CommentsFragment extends BaseListInfoFragment<CommentsInfo> {
|
||||||
@Override
|
@Override
|
||||||
public void handleResult(@NonNull CommentsInfo result) {
|
public void handleResult(@NonNull CommentsInfo result) {
|
||||||
super.handleResult(result);
|
super.handleResult(result);
|
||||||
if(initialLoad){
|
|
||||||
itemsList.smoothScrollToPosition(VideoDetailFragment.INITIAL_COMMENTS);
|
|
||||||
initialLoad = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!result.getErrors().isEmpty()) {
|
if (!result.getErrors().isEmpty()) {
|
||||||
showSnackBarError(result.getErrors(), UserAction.REQUESTED_COMMENTS, NewPipe.getNameOfService(result.getServiceId()), result.getUrl(), 0);
|
showSnackBarError(result.getErrors(), UserAction.REQUESTED_COMMENTS, NewPipe.getNameOfService(result.getServiceId()), result.getUrl(), 0);
|
||||||
|
@ -186,12 +167,7 @@ public class CommentsFragment extends BaseListInfoFragment<CommentsInfo> {
|
||||||
protected boolean onError(Throwable exception) {
|
protected boolean onError(Throwable exception) {
|
||||||
if (super.onError(exception)) return true;
|
if (super.onError(exception)) return true;
|
||||||
|
|
||||||
int errorId = exception instanceof ExtractionException ? R.string.parsing_error : R.string.general_error;
|
showSnackBarError(exception, UserAction.REQUESTED_COMMENTS, NewPipe.getNameOfService(serviceId), url, R.string.error_unable_to_load_comments);
|
||||||
onUnrecoverableError(exception,
|
|
||||||
UserAction.REQUESTED_COMMENTS,
|
|
||||||
NewPipe.getNameOfService(serviceId),
|
|
||||||
url,
|
|
||||||
errorId);
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -201,6 +177,11 @@ public class CommentsFragment extends BaseListInfoFragment<CommentsInfo> {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void setTitle(String title) {
|
public void setTitle(String title) {
|
||||||
super.setTitle(title);
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,150 @@
|
||||||
|
package org.schabi.newpipe.fragments.list.videos;
|
||||||
|
|
||||||
|
import android.content.Context;
|
||||||
|
import android.os.Bundle;
|
||||||
|
import android.support.annotation.NonNull;
|
||||||
|
import android.support.annotation.Nullable;
|
||||||
|
import android.view.LayoutInflater;
|
||||||
|
import android.view.Menu;
|
||||||
|
import android.view.MenuInflater;
|
||||||
|
import android.view.View;
|
||||||
|
import android.view.ViewGroup;
|
||||||
|
|
||||||
|
import org.schabi.newpipe.R;
|
||||||
|
import org.schabi.newpipe.extractor.InfoItem;
|
||||||
|
import org.schabi.newpipe.extractor.ListExtractor;
|
||||||
|
import org.schabi.newpipe.extractor.ListInfo;
|
||||||
|
import org.schabi.newpipe.extractor.NewPipe;
|
||||||
|
import org.schabi.newpipe.extractor.comments.CommentsInfo;
|
||||||
|
import org.schabi.newpipe.extractor.exceptions.ExtractionException;
|
||||||
|
import org.schabi.newpipe.extractor.kiosk.KioskInfo;
|
||||||
|
import org.schabi.newpipe.extractor.stream.StreamInfo;
|
||||||
|
import org.schabi.newpipe.extractor.stream.StreamInfoItem;
|
||||||
|
import org.schabi.newpipe.fragments.list.BaseListInfoFragment;
|
||||||
|
import org.schabi.newpipe.report.UserAction;
|
||||||
|
import org.schabi.newpipe.util.ExtractorHelper;
|
||||||
|
import org.schabi.newpipe.util.RelatedStreamInfo;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import io.reactivex.Single;
|
||||||
|
import io.reactivex.disposables.CompositeDisposable;
|
||||||
|
|
||||||
|
public class RelatedVideosFragment extends BaseListInfoFragment<RelatedStreamInfo> {
|
||||||
|
|
||||||
|
private CompositeDisposable disposables = new CompositeDisposable();
|
||||||
|
private RelatedStreamInfo relatedStreamInfo;
|
||||||
|
/*//////////////////////////////////////////////////////////////////////////
|
||||||
|
// Views
|
||||||
|
//////////////////////////////////////////////////////////////////////////*/
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
private boolean mIsVisibleToUser = false;
|
||||||
|
|
||||||
|
public static RelatedVideosFragment getInstance(StreamInfo info) {
|
||||||
|
RelatedVideosFragment instance = new RelatedVideosFragment();
|
||||||
|
instance.setInitialData(info);
|
||||||
|
return instance;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*//////////////////////////////////////////////////////////////////////////
|
||||||
|
// LifeCycle
|
||||||
|
//////////////////////////////////////////////////////////////////////////*/
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setUserVisibleHint(boolean isVisibleToUser) {
|
||||||
|
super.setUserVisibleHint(isVisibleToUser);
|
||||||
|
mIsVisibleToUser = isVisibleToUser;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onAttach(Context context) {
|
||||||
|
super.onAttach(context);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
|
||||||
|
return inflater.inflate(R.layout.fragment_related_streams, container, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onDestroy() {
|
||||||
|
super.onDestroy();
|
||||||
|
if (disposables != null) disposables.clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected Single<ListExtractor.InfoItemsPage> loadMoreItemsLogic() {
|
||||||
|
return Single.fromCallable(() -> ListExtractor.InfoItemsPage.emptyPage());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected Single<RelatedStreamInfo> loadResult(boolean forceLoad) {
|
||||||
|
return Single.fromCallable(() -> relatedStreamInfo);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*//////////////////////////////////////////////////////////////////////////
|
||||||
|
// Contract
|
||||||
|
//////////////////////////////////////////////////////////////////////////*/
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void showLoading() {
|
||||||
|
super.showLoading();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void handleResult(@NonNull RelatedStreamInfo result) {
|
||||||
|
super.handleResult(result);
|
||||||
|
|
||||||
|
if (!result.getErrors().isEmpty()) {
|
||||||
|
showSnackBarError(result.getErrors(), UserAction.REQUESTED_STREAM, NewPipe.getNameOfService(result.getServiceId()), result.getUrl(), 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (disposables != null) disposables.clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void handleNextItems(ListExtractor.InfoItemsPage result) {
|
||||||
|
super.handleNextItems(result);
|
||||||
|
|
||||||
|
if (!result.getErrors().isEmpty()) {
|
||||||
|
showSnackBarError(result.getErrors(),
|
||||||
|
UserAction.REQUESTED_STREAM,
|
||||||
|
NewPipe.getNameOfService(serviceId),
|
||||||
|
"Get next page of: " + url,
|
||||||
|
R.string.general_error);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*//////////////////////////////////////////////////////////////////////////
|
||||||
|
// OnError
|
||||||
|
//////////////////////////////////////////////////////////////////////////*/
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected boolean onError(Throwable exception) {
|
||||||
|
if (super.onError(exception)) return true;
|
||||||
|
|
||||||
|
showSnackBarError(exception, UserAction.REQUESTED_STREAM, NewPipe.getNameOfService(serviceId), url, R.string.general_error);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*//////////////////////////////////////////////////////////////////////////
|
||||||
|
// Utils
|
||||||
|
//////////////////////////////////////////////////////////////////////////*/
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setTitle(String title) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void setInitialData(StreamInfo info) {
|
||||||
|
super.setInitialData(info.getServiceId(), info.getUrl(), info.getName());
|
||||||
|
this.relatedStreamInfo = RelatedStreamInfo.getInfo(info);
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,23 @@
|
||||||
|
package org.schabi.newpipe.util;
|
||||||
|
|
||||||
|
import org.schabi.newpipe.extractor.InfoItem;
|
||||||
|
import org.schabi.newpipe.extractor.ListInfo;
|
||||||
|
import org.schabi.newpipe.extractor.linkhandler.ListLinkHandler;
|
||||||
|
import org.schabi.newpipe.extractor.stream.StreamInfo;
|
||||||
|
|
||||||
|
import java.util.Collections;
|
||||||
|
|
||||||
|
public class RelatedStreamInfo extends ListInfo<InfoItem> {
|
||||||
|
|
||||||
|
|
||||||
|
public RelatedStreamInfo(int serviceId, ListLinkHandler listUrlIdHandler, String name) {
|
||||||
|
super(serviceId, listUrlIdHandler, name);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static RelatedStreamInfo getInfo(StreamInfo info) {
|
||||||
|
ListLinkHandler handler = new ListLinkHandler(info.getOriginalUrl(), info.getUrl(), info.getId(), Collections.emptyList(), null);
|
||||||
|
RelatedStreamInfo relatedStreamInfo = new RelatedStreamInfo(info.getServiceId(), handler, info.getName());
|
||||||
|
relatedStreamInfo.setRelatedItems(info.getRelatedStreams());
|
||||||
|
return relatedStreamInfo;
|
||||||
|
}
|
||||||
|
}
|
|
@ -25,7 +25,7 @@
|
||||||
android:id="@+id/empty_state_view"
|
android:id="@+id/empty_state_view"
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout_centerInParent="true"
|
android:layout_centerHorizontal="true"
|
||||||
android:orientation="vertical"
|
android:orientation="vertical"
|
||||||
android:paddingTop="90dp"
|
android:paddingTop="90dp"
|
||||||
android:visibility="gone"
|
android:visibility="gone"
|
||||||
|
|
70
app/src/main/res/layout/fragment_related_streams.xml
Normal file
70
app/src/main/res/layout/fragment_related_streams.xml
Normal file
|
@ -0,0 +1,70 @@
|
||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<RelativeLayout
|
||||||
|
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
xmlns:tools="http://schemas.android.com/tools"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="match_parent">
|
||||||
|
|
||||||
|
<android.support.v7.widget.RecyclerView
|
||||||
|
android:id="@+id/items_list"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="match_parent"
|
||||||
|
android:scrollbars="vertical"
|
||||||
|
tools:listitem="@layout/list_stream_item"/>
|
||||||
|
|
||||||
|
<ProgressBar
|
||||||
|
android:id="@+id/loading_progress_bar"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_centerInParent="true"
|
||||||
|
android:indeterminate="true"
|
||||||
|
android:visibility="gone"
|
||||||
|
tools:visibility="visible"/>
|
||||||
|
|
||||||
|
<LinearLayout
|
||||||
|
android:id="@+id/empty_state_view"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_centerHorizontal="true"
|
||||||
|
android:orientation="vertical"
|
||||||
|
android:paddingTop="90dp"
|
||||||
|
android:visibility="gone"
|
||||||
|
tools:visibility="visible">
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_gravity="center"
|
||||||
|
android:layout_marginBottom="10dp"
|
||||||
|
android:fontFamily="monospace"
|
||||||
|
android:text="(╯°-°)╯"
|
||||||
|
android:textSize="35sp"
|
||||||
|
tools:ignore="HardcodedText,UnusedAttribute"/>
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_gravity="center"
|
||||||
|
android:text="@string/empty_view_no_videos"
|
||||||
|
android:textSize="24sp"/>
|
||||||
|
|
||||||
|
</LinearLayout>
|
||||||
|
|
||||||
|
<!--ERROR PANEL-->
|
||||||
|
<include
|
||||||
|
android:id="@+id/error_panel"
|
||||||
|
layout="@layout/error_retry"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_centerInParent="true"
|
||||||
|
android:layout_marginTop="50dp"
|
||||||
|
android:visibility="gone"
|
||||||
|
tools:visibility="visible"/>
|
||||||
|
|
||||||
|
<View
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="4dp"
|
||||||
|
android:background="?attr/toolbar_shadow_drawable"
|
||||||
|
android:layout_alignParentTop="true"/>
|
||||||
|
|
||||||
|
</RelativeLayout>
|
|
@ -7,18 +7,20 @@
|
||||||
android:layout_height="match_parent"
|
android:layout_height="match_parent"
|
||||||
android:focusableInTouchMode="true">
|
android:focusableInTouchMode="true">
|
||||||
|
|
||||||
<com.nirhart.parallaxscroll.views.ParallaxScrollView
|
<android.support.design.widget.CoordinatorLayout
|
||||||
android:id="@+id/detail_main_content"
|
android:id="@+id/detail_main_content"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="match_parent"
|
android:layout_height="match_parent">
|
||||||
android:visibility="visible"
|
|
||||||
app:parallax_factor="1.9">
|
|
||||||
|
|
||||||
<!--WRAPPER-->
|
<android.support.design.widget.AppBarLayout
|
||||||
<LinearLayout
|
android:id="@+id/appbarlayout"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content">
|
||||||
|
|
||||||
|
<android.support.design.widget.CollapsingToolbarLayout
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:orientation="vertical">
|
app:layout_scrollFlags="scroll">
|
||||||
|
|
||||||
<!-- THUMBNAIL -->
|
<!-- THUMBNAIL -->
|
||||||
<FrameLayout
|
<FrameLayout
|
||||||
|
@ -28,7 +30,8 @@
|
||||||
android:background="@android:color/black"
|
android:background="@android:color/black"
|
||||||
android:clickable="true"
|
android:clickable="true"
|
||||||
android:focusable="true"
|
android:focusable="true"
|
||||||
android:foreground="?attr/selectableItemBackground">
|
android:foreground="?attr/selectableItemBackground"
|
||||||
|
app:layout_collapseMode="parallax">
|
||||||
|
|
||||||
<ImageView
|
<ImageView
|
||||||
android:id="@+id/detail_thumbnail_image_view"
|
android:id="@+id/detail_thumbnail_image_view"
|
||||||
|
@ -96,12 +99,15 @@
|
||||||
tools:visibility="visible" />
|
tools:visibility="visible" />
|
||||||
</FrameLayout>
|
</FrameLayout>
|
||||||
|
|
||||||
|
</android.support.design.widget.CollapsingToolbarLayout>
|
||||||
|
|
||||||
<!-- CONTENT -->
|
<!-- CONTENT -->
|
||||||
<RelativeLayout
|
<RelativeLayout
|
||||||
android:id="@+id/detail_content_root_layout"
|
android:id="@+id/detail_content_root_layout"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="match_parent"
|
android:layout_height="wrap_content"
|
||||||
android:background="?android:windowBackground">
|
android:background="?android:windowBackground"
|
||||||
|
app:layout_scrollFlags="scroll">
|
||||||
|
|
||||||
<!-- TITLE -->
|
<!-- TITLE -->
|
||||||
<FrameLayout
|
<FrameLayout
|
||||||
|
@ -449,132 +455,24 @@
|
||||||
|
|
||||||
</LinearLayout>
|
</LinearLayout>
|
||||||
|
|
||||||
<TabHost
|
|
||||||
android:id="@+id/tab_host"
|
|
||||||
android:layout_width="fill_parent"
|
|
||||||
android:layout_height="wrap_content">
|
|
||||||
|
|
||||||
<LinearLayout
|
|
||||||
android:layout_width="fill_parent"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:orientation="vertical">
|
|
||||||
|
|
||||||
<TabWidget
|
|
||||||
android:id="@android:id/tabs"
|
|
||||||
android:layout_width="fill_parent"
|
|
||||||
android:layout_height="wrap_content" />
|
|
||||||
|
|
||||||
<FrameLayout
|
|
||||||
android:id="@android:id/tabcontent"
|
|
||||||
android:layout_width="fill_parent"
|
|
||||||
android:layout_height="wrap_content">
|
|
||||||
<!--COMMENTS-->
|
|
||||||
<LinearLayout
|
|
||||||
android:id="@+id/detail_comments_root_layout"
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:layout_gravity="center_horizontal|bottom"
|
|
||||||
android:layout_marginTop="14dp"
|
|
||||||
android:orientation="vertical">
|
|
||||||
|
|
||||||
<LinearLayout
|
|
||||||
android:id="@+id/comments_empty_state_view"
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:layout_centerInParent="true"
|
|
||||||
android:orientation="vertical"
|
|
||||||
android:paddingTop="65dp"
|
|
||||||
android:visibility="gone"
|
|
||||||
tools:visibility="visible">
|
|
||||||
|
|
||||||
<TextView
|
|
||||||
android:layout_width="wrap_content"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:layout_gravity="center"
|
|
||||||
android:layout_marginBottom="10dp"
|
|
||||||
android:fontFamily="monospace"
|
|
||||||
android:text="(╯°-°)╯"
|
|
||||||
android:textSize="35sp"
|
|
||||||
tools:ignore="HardcodedText,UnusedAttribute"/>
|
|
||||||
|
|
||||||
<TextView
|
|
||||||
android:layout_width="wrap_content"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:layout_gravity="center"
|
|
||||||
android:text="@string/empty_view_no_comments"
|
|
||||||
android:textSize="18sp"/>
|
|
||||||
|
|
||||||
</LinearLayout>
|
|
||||||
|
|
||||||
<LinearLayout
|
|
||||||
android:id="@+id/detail_comments_view"
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="match_parent"
|
|
||||||
android:layout_marginTop="2dp"
|
|
||||||
android:orientation="vertical"
|
|
||||||
tools:minHeight="50dp" />
|
|
||||||
|
|
||||||
<ImageButton
|
|
||||||
android:id="@+id/detail_comments_expand"
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:background="?attr/selectableItemBackground"
|
|
||||||
android:paddingBottom="10dp"
|
|
||||||
android:paddingTop="4dp"
|
|
||||||
android:src="?attr/expand"
|
|
||||||
android:textAlignment="center"
|
|
||||||
android:textAllCaps="true"
|
|
||||||
android:visibility="gone"
|
|
||||||
tools:ignore="ContentDescription" />
|
|
||||||
|
|
||||||
</LinearLayout>
|
|
||||||
|
|
||||||
<!--NEXT AND RELATED VIDEOS-->
|
|
||||||
<LinearLayout
|
|
||||||
android:id="@+id/detail_related_streams_root_layout"
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:layout_gravity="center_horizontal|bottom"
|
|
||||||
android:layout_marginTop="14dp"
|
|
||||||
android:orientation="vertical">
|
|
||||||
|
|
||||||
<TextView
|
|
||||||
android:id="@+id/detail_next_stream_title"
|
|
||||||
android:layout_width="wrap_content"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:layout_marginLeft="12dp"
|
|
||||||
android:text="@string/next_video_title"
|
|
||||||
android:textAllCaps="true"
|
|
||||||
android:textAppearance="?android:attr/textAppearanceMedium"
|
|
||||||
android:textSize="@dimen/video_item_detail_next_text_size"
|
|
||||||
tools:ignore="RtlHardcoded" />
|
|
||||||
|
|
||||||
<LinearLayout
|
|
||||||
android:id="@+id/detail_related_streams_view"
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="match_parent"
|
|
||||||
android:layout_marginTop="2dp"
|
|
||||||
android:orientation="vertical"
|
|
||||||
tools:minHeight="50dp" />
|
|
||||||
|
|
||||||
<ImageButton
|
|
||||||
android:id="@+id/detail_related_streams_expand"
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:background="?attr/selectableItemBackground"
|
|
||||||
android:paddingBottom="10dp"
|
|
||||||
android:paddingTop="4dp"
|
|
||||||
android:src="?attr/expand"
|
|
||||||
android:textAlignment="center"
|
|
||||||
android:textAllCaps="true"
|
|
||||||
tools:ignore="ContentDescription" />
|
|
||||||
</LinearLayout>
|
|
||||||
</FrameLayout>
|
|
||||||
</LinearLayout>
|
|
||||||
</TabHost>
|
|
||||||
|
|
||||||
</LinearLayout>
|
</LinearLayout>
|
||||||
</RelativeLayout>
|
</RelativeLayout>
|
||||||
</LinearLayout>
|
|
||||||
</com.nirhart.parallaxscroll.views.ParallaxScrollView>
|
<android.support.design.widget.TabLayout
|
||||||
|
android:id="@+id/tablayout"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="50dp"
|
||||||
|
android:background="?android:windowBackground">
|
||||||
|
|
||||||
|
</android.support.design.widget.TabLayout>
|
||||||
|
|
||||||
|
</android.support.design.widget.AppBarLayout>
|
||||||
|
|
||||||
|
<android.support.v4.view.ViewPager
|
||||||
|
android:id="@+id/viewpager"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="match_parent"
|
||||||
|
app:layout_behavior="@string/appbar_scrolling_view_behavior" />
|
||||||
|
|
||||||
|
</android.support.design.widget.CoordinatorLayout>
|
||||||
</FrameLayout>
|
</FrameLayout>
|
||||||
|
|
Loading…
Reference in a new issue