added viewpager. changed from parallaxscrollview to coordinate layout

This commit is contained in:
Ritvik Saraf 2018-10-02 20:39:16 +05:30
parent e4bef056e6
commit 2e9a860aaa
8 changed files with 484 additions and 528 deletions

View File

@ -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;
}
}

View File

@ -13,7 +13,11 @@ import android.support.annotation.DrawableRes;
import android.support.annotation.FloatRange;
import android.support.annotation.NonNull;
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.view.ViewPager;
import android.support.v4.view.animation.FastOutSlowInInterpolator;
import android.support.v7.app.ActionBar;
import android.support.v7.app.AlertDialog;
@ -40,11 +44,9 @@ import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.RelativeLayout;
import android.widget.Spinner;
import android.widget.TabHost;
import android.widget.TextView;
import android.widget.Toast;
import com.nirhart.parallaxscroll.views.ParallaxScrollView;
import com.nostra13.universalimageloader.core.assist.FailReason;
import com.nostra13.universalimageloader.core.listener.ImageLoadingListener;
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.StreamingService;
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.ExtractionException;
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.fragments.BackPressable;
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.InfoItemDialog;
import org.schabi.newpipe.local.dialog.PlaylistAppendDialog;
@ -117,13 +120,6 @@ public class VideoDetailFragment
View.OnLongClickListener {
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 static final int RELATED_STREAMS_UPDATE_FLAG = 0x1;
private static final int RESOLUTIONS_MENU_UPDATE_FLAG = 0x2;
@ -133,8 +129,6 @@ public class VideoDetailFragment
private boolean autoPlayEnabled;
private boolean showRelatedStreams;
private boolean showComments;
private boolean isCommentsSupported;
private boolean wasRelatedStreamsExpanded = false;
@State
protected int serviceId = Constants.NO_SERVICE_ID;
@ -144,7 +138,6 @@ public class VideoDetailFragment
protected String url;
private StreamInfo currentInfo;
private CommentsInfo commentsInfo;
private Disposable currentWorker;
@NonNull
private CompositeDisposable disposables = new CompositeDisposable();
@ -160,7 +153,6 @@ public class VideoDetailFragment
private Spinner spinnerToolbar;
private ParallaxScrollView parallaxScrollRootView;
private LinearLayout contentRootLayoutHiding;
private View thumbnailBackgroundButton;
@ -193,21 +185,13 @@ public class VideoDetailFragment
private ImageView thumbsDownImageView;
private TextView thumbsDisabledTextView;
private TextView nextStreamTitle;
private LinearLayout relatedStreamRootLayout;
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 static final String COMMENTS_TAB_TAG = "COMMENTS";
private static final String RELATED_TAB_TAG = "NEXT VIDEO";
private AppBarLayout appBarLayout;
private ViewPager viewPager;
private TabAdaptor pageAdapter;
private TabLayout tabLayout;
/*////////////////////////////////////////////////////////////////////////*/
@ -247,7 +231,6 @@ public class VideoDetailFragment
public void onPause() {
super.onPause();
if (currentWorker != null) currentWorker.dispose();
if (commentsDisposable != null) commentsDisposable.dispose();
}
@Override
@ -256,10 +239,9 @@ public class VideoDetailFragment
if (updateFlags != 0) {
if (!isLoading.get() && currentInfo != null) {
if ((updateFlags & RELATED_STREAMS_UPDATE_FLAG) != 0)
initRelatedVideos(currentInfo);
if ((updateFlags & RELATED_STREAMS_UPDATE_FLAG) != 0) startLoading(false);
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
@ -273,8 +255,6 @@ public class VideoDetailFragment
// Check if it was loading when the fragment was stopped/paused,
if (wasLoading.getAndSet(false)) {
selectAndLoadVideo(serviceId, url, name);
}else{
loadComments(false);
}
}
@ -285,10 +265,8 @@ public class VideoDetailFragment
.unregisterOnSharedPreferenceChangeListener(this);
if (currentWorker != null) currentWorker.dispose();
if (commentsDisposable != null) commentsDisposable.dispose();
if (disposables != null) disposables.clear();
currentWorker = null;
commentsDisposable = null;
disposables = null;
}
@ -339,7 +317,6 @@ public class VideoDetailFragment
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) {
@ -348,10 +325,6 @@ public class VideoDetailFragment
// Check if the next video label and video is visible,
// if it is, include the two elements in the next check
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()) {
outState.putSerializable(INFO_KEY, currentInfo);
@ -364,7 +337,6 @@ public class VideoDetailFragment
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
@ -432,12 +404,6 @@ public class VideoDetailFragment
case R.id.detail_title_root_layout:
toggleTitleAndDescription();
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
//////////////////////////////////////////////////////////////////////////*/
@ -516,8 +447,6 @@ public class VideoDetailFragment
super.initViews(rootView, savedInstanceState);
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);
thumbnailImageView = rootView.findViewById(R.id.detail_thumbnail_image_view);
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);
uploaderThumb = rootView.findViewById(R.id.detail_uploader_thumbnail_view);
StreamingService service = null;
try {
service = NewPipe.getService(serviceId);
} catch (ExtractionException e) {
onError(e);
}
appBarLayout = rootView.findViewById(R.id.appbarlayout);
viewPager = rootView.findViewById(R.id.viewpager);
pageAdapter = new TabAdaptor(getChildFragmentManager());
viewPager.setAdapter(pageAdapter);
tabLayout = rootView.findViewById(R.id.tablayout);
tabLayout.setupWithViewPager(viewPager);
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();
}
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
protected void 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);
uploaderRootLayout.setOnClickListener(this);
@ -623,8 +506,6 @@ public class VideoDetailFragment
detailControlsAddToPlaylist.setOnClickListener(this);
detailControlsDownload.setOnClickListener(this);
detailControlsDownload.setOnLongClickListener(this);
relatedStreamExpandButton.setOnClickListener(this);
commentsExpandButton.setOnClickListener(this);
detailControlsBackground.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
//////////////////////////////////////////////////////////////////////////*/
@ -979,23 +768,18 @@ public class VideoDetailFragment
setInitialData(info.getServiceId(), info.getOriginalUrl(), info.getName());
pushToStack(serviceId, url, name);
showLoading();
initTabs();
Log.d(TAG, "prepareAndHandleInfo() called parallaxScrollRootView.getScrollY(): "
+ parallaxScrollRootView.getScrollY());
final boolean greaterThanThreshold = parallaxScrollRootView.getScrollY() > (int)
(getResources().getDisplayMetrics().heightPixels * .1f);
if (scrollToTop) parallaxScrollRootView.smoothScrollTo(0, 0);
if (scrollToTop) appBarLayout.setExpanded(true, true);
animateView(contentRootLayoutHiding,
false,
greaterThanThreshold ? 250 : 0, 0, () -> {
false, 0, 0, () -> {
handleResult(info);
showContentWithAnimation(120, 0, .01f);
});
}
protected void prepareAndLoadInfo() {
parallaxScrollRootView.smoothScrollTo(0, 0);
appBarLayout.setExpanded(true, true);
pushToStack(serviceId, url, name);
startLoading(false);
}
@ -1004,6 +788,7 @@ public class VideoDetailFragment
public void startLoading(boolean forceLoad) {
super.startLoading(forceLoad);
initTabs();
currentInfo = null;
if (currentWorker != null) currentWorker.dispose();
@ -1020,26 +805,29 @@ public class VideoDetailFragment
onError(throwable);
});
loadComments(forceLoad);
}
private void loadComments(boolean forceLoad) {
if(isCommentsSupported && showComments){
clearComments();
commentsInfo = null;
if (commentsDisposable != null) commentsDisposable.dispose();
private void initTabs() {
pageAdapter.clearAllItems();
commentsDisposable = ExtractorHelper.getCommentsInfo(serviceId, url, forceLoad)
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe((@NonNull CommentsInfo result) -> {
commentsInfo = result;
showCommentsWithAnimation(120, 0,0);
initComments(commentsInfo);
}, (@NonNull Throwable throwable) -> {
onCommentsError(throwable);
});
if(shouldShowComments()){
pageAdapter.addFragment(CommentsFragment.getInstance(serviceId, url, name), COMMENTS_TAB_TAG);
}
if(showRelatedStreams){
pageAdapter.addFragment(new Fragment(), RELATED_TAB_TAG);
}
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())
.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) {
@ -1324,6 +1077,11 @@ public class VideoDetailFragment
super.handleResult(info);
setInitialData(info.getServiceId(), info.getOriginalUrl(), info.getName());
if(showRelatedStreams){
pageAdapter.updateItem(RELATED_TAB_TAG, RelatedVideosFragment.getInstance(currentInfo));
}
pushToStack(serviceId, url, name);
animateView(thumbnailPlayButton, true, 200);
@ -1398,12 +1156,6 @@ public class VideoDetailFragment
animateView(spinnerToolbar, true, 500);
setupActionBar(info);
initThumbnailViews(info);
initRelatedVideos(info);
if (wasRelatedStreamsExpanded) {
toggleExpandRelatedVideos(currentInfo);
wasRelatedStreamsExpanded = false;
}
setTitleToUrl(info.getServiceId(), info.getUrl(), info.getName());
setTitleToUrl(info.getServiceId(), info.getOriginalUrl(), info.getName());

View File

@ -71,7 +71,6 @@ import static org.schabi.newpipe.util.AnimationUtils.animateView;
public class CommentsFragment extends BaseListInfoFragment<CommentsInfo> {
private CompositeDisposable disposables = new CompositeDisposable();
private boolean initialLoad = true;
/*//////////////////////////////////////////////////////////////////////////
// Views
//////////////////////////////////////////////////////////////////////////*/
@ -94,11 +93,6 @@ public class CommentsFragment extends BaseListInfoFragment<CommentsInfo> {
public void setUserVisibleHint(boolean isVisibleToUser) {
super.setUserVisibleHint(isVisibleToUser);
mIsVisibleToUser = isVisibleToUser;
if(activity != null
&& useAsFrontPage
&& isVisibleToUser) {
setTitle(currentInfo != null ? currentInfo.getName() : name);
}
}
@Override
@ -117,15 +111,6 @@ public class CommentsFragment extends BaseListInfoFragment<CommentsInfo> {
if (disposables != null) disposables.clear();
}
/*//////////////////////////////////////////////////////////////////////////
// Init
//////////////////////////////////////////////////////////////////////////*/
/*//////////////////////////////////////////////////////////////////////////
// Menu
//////////////////////////////////////////////////////////////////////////*/
/*//////////////////////////////////////////////////////////////////////////
// Load and handle
@ -153,10 +138,6 @@ public class CommentsFragment extends BaseListInfoFragment<CommentsInfo> {
@Override
public void handleResult(@NonNull CommentsInfo result) {
super.handleResult(result);
if(initialLoad){
itemsList.smoothScrollToPosition(VideoDetailFragment.INITIAL_COMMENTS);
initialLoad = false;
}
if (!result.getErrors().isEmpty()) {
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) {
if (super.onError(exception)) return true;
int errorId = exception instanceof ExtractionException ? R.string.parsing_error : R.string.general_error;
onUnrecoverableError(exception,
UserAction.REQUESTED_COMMENTS,
NewPipe.getNameOfService(serviceId),
url,
errorId);
showSnackBarError(exception, UserAction.REQUESTED_COMMENTS, NewPipe.getNameOfService(serviceId), url, R.string.error_unable_to_load_comments);
return true;
}
@ -201,6 +177,11 @@ public class CommentsFragment extends BaseListInfoFragment<CommentsInfo> {
@Override
public void setTitle(String title) {
super.setTitle(title);
return;
}
@Override
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
return;
}
}

View File

@ -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);
}
}

View File

@ -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;
}
}

View File

@ -25,7 +25,7 @@
android:id="@+id/empty_state_view"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerInParent="true"
android:layout_centerHorizontal="true"
android:orientation="vertical"
android:paddingTop="90dp"
android:visibility="gone"

View 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>

View File

@ -7,101 +7,107 @@
android:layout_height="match_parent"
android:focusableInTouchMode="true">
<com.nirhart.parallaxscroll.views.ParallaxScrollView
<android.support.design.widget.CoordinatorLayout
android:id="@+id/detail_main_content"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:visibility="visible"
app:parallax_factor="1.9">
android:layout_height="match_parent">
<!--WRAPPER-->
<LinearLayout
<android.support.design.widget.AppBarLayout
android:id="@+id/appbarlayout"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical">
android:layout_height="wrap_content">
<!-- THUMBNAIL -->
<FrameLayout
android:id="@+id/detail_thumbnail_root_layout"
<android.support.design.widget.CollapsingToolbarLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="@android:color/black"
android:clickable="true"
android:focusable="true"
android:foreground="?attr/selectableItemBackground">
app:layout_scrollFlags="scroll">
<ImageView
android:id="@+id/detail_thumbnail_image_view"
<!-- THUMBNAIL -->
<FrameLayout
android:id="@+id/detail_thumbnail_root_layout"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="@android:color/transparent"
android:contentDescription="@string/detail_thumbnail_view_description"
android:scaleType="fitCenter"
tools:ignore="RtlHardcoded"
tools:layout_height="200dp"
tools:src="@drawable/dummy_thumbnail" />
android:background="@android:color/black"
android:clickable="true"
android:focusable="true"
android:foreground="?attr/selectableItemBackground"
app:layout_collapseMode="parallax">
<ImageView
android:id="@+id/detail_thumbnail_play_button"
android:layout_width="64dp"
android:layout_height="64dp"
android:layout_gravity="center"
android:background="@android:color/transparent"
android:src="@drawable/new_play_arrow"
android:visibility="invisible"
tools:ignore="ContentDescription"
tools:visibility="visible" />
<ImageView
android:id="@+id/detail_thumbnail_image_view"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="@android:color/transparent"
android:contentDescription="@string/detail_thumbnail_view_description"
android:scaleType="fitCenter"
tools:ignore="RtlHardcoded"
tools:layout_height="200dp"
tools:src="@drawable/dummy_thumbnail" />
<TextView
android:id="@+id/touch_append_detail"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:background="#64000000"
android:paddingBottom="10dp"
android:paddingLeft="30dp"
android:paddingRight="30dp"
android:paddingTop="10dp"
android:text="@string/hold_to_append"
android:textColor="@android:color/white"
android:textSize="20sp"
android:textStyle="bold"
android:visibility="gone"
tools:ignore="RtlHardcoded"
tools:visibility="visible" />
<ImageView
android:id="@+id/detail_thumbnail_play_button"
android:layout_width="64dp"
android:layout_height="64dp"
android:layout_gravity="center"
android:background="@android:color/transparent"
android:src="@drawable/new_play_arrow"
android:visibility="invisible"
tools:ignore="ContentDescription"
tools:visibility="visible" />
<TextView
android:id="@+id/detail_duration_view"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="bottom|right"
android:layout_marginBottom="8dp"
android:layout_marginLeft="12dp"
android:layout_marginRight="12dp"
android:layout_marginTop="8dp"
android:alpha=".6"
android:background="#23000000"
android:gravity="center"
android:paddingBottom="2dp"
android:paddingLeft="6dp"
android:paddingRight="6dp"
android:paddingTop="2dp"
android:textAllCaps="true"
android:textColor="@android:color/white"
android:textSize="12sp"
android:textStyle="bold"
android:visibility="gone"
tools:ignore="RtlHardcoded"
tools:text="12:38"
tools:visibility="visible" />
</FrameLayout>
<TextView
android:id="@+id/touch_append_detail"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:background="#64000000"
android:paddingBottom="10dp"
android:paddingLeft="30dp"
android:paddingRight="30dp"
android:paddingTop="10dp"
android:text="@string/hold_to_append"
android:textColor="@android:color/white"
android:textSize="20sp"
android:textStyle="bold"
android:visibility="gone"
tools:ignore="RtlHardcoded"
tools:visibility="visible" />
<TextView
android:id="@+id/detail_duration_view"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="bottom|right"
android:layout_marginBottom="8dp"
android:layout_marginLeft="12dp"
android:layout_marginRight="12dp"
android:layout_marginTop="8dp"
android:alpha=".6"
android:background="#23000000"
android:gravity="center"
android:paddingBottom="2dp"
android:paddingLeft="6dp"
android:paddingRight="6dp"
android:paddingTop="2dp"
android:textAllCaps="true"
android:textColor="@android:color/white"
android:textSize="12sp"
android:textStyle="bold"
android:visibility="gone"
tools:ignore="RtlHardcoded"
tools:text="12:38"
tools:visibility="visible" />
</FrameLayout>
</android.support.design.widget.CollapsingToolbarLayout>
<!-- CONTENT -->
<RelativeLayout
android:id="@+id/detail_content_root_layout"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="?android:windowBackground">
android:layout_height="wrap_content"
android:background="?android:windowBackground"
app:layout_scrollFlags="scroll">
<!-- TITLE -->
<FrameLayout
@ -449,132 +455,24 @@
</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>
</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>