1
0
mirror of https://github.com/TeamNewPipe/NewPipe synced 2024-12-23 08:30:44 +00:00

Merge remote-tracking branch 'upstream/master'

Conflicts:
	app/src/main/java/org/schabi/newpipe/VideoItemDetailFragment.java -- still used class-based passing
	app/src/main/java/org/schabi/newpipe/VideoItemListActivity.java -- just some whitespace
This commit is contained in:
Adam Howard 2015-11-02 21:29:43 +00:00
commit c32c267889
15 changed files with 226 additions and 69 deletions

View File

@ -2,7 +2,7 @@
[![Translation Status](https://hosted.weblate.org/widgets/NewPipe/-/svg-badge.svg)](https://hosted.weblate.org/engage/NewPipe/) [![Translation Status](https://hosted.weblate.org/widgets/NewPipe/-/svg-badge.svg)](https://hosted.weblate.org/engage/NewPipe/)
[![NewPipe](https://f-droid.org/repo/icons/org.schabi.newpipe.4.png)](http://dasochan.nl/newpipe/) [![NewPipe](https://f-droid.org/repo/icons/org.schabi.newpipe.5.png)](http://dasochan.nl/newpipe/)
NewPipe: A free lightweight Youtube frontend for Android. NewPipe: A free lightweight Youtube frontend for Android.
[![F-Droid](https://f-droid.org/wiki/images/0/06/F-Droid-button_get-it-on.png)](https://f-droid.org/repository/browse/?fdfilter=newpipe&fdid=org.schabi.newpipe) [![F-Droid](https://f-droid.org/wiki/images/0/06/F-Droid-button_get-it-on.png)](https://f-droid.org/repository/browse/?fdfilter=newpipe&fdid=org.schabi.newpipe)
@ -21,10 +21,10 @@ NewPipe does not use any Google framework libraries, or the YouTube API. It only
* Download videos (working, but it could be better) * Download videos (working, but it could be better)
* Download audio only (working but, but it could be better) * Download audio only (working but, but it could be better)
* Open a video in Kodi * Open a video in Kodi
* Show Next/Related videos
## Coming Features ## Coming Features
* Shows Next/Related videos
* Improved Downloading * Improved Downloading
* Bookmarks * Bookmarks
* View history * View history

View File

@ -23,7 +23,7 @@ dependencies {
compile fileTree(include: ['*.jar'], dir: 'libs') compile fileTree(include: ['*.jar'], dir: 'libs')
compile 'com.android.support:appcompat-v7:23.1.0' compile 'com.android.support:appcompat-v7:23.1.0'
compile 'com.android.support:support-v4:23.1.0' compile 'com.android.support:support-v4:23.1.0'
compile 'com.android.support:design:23.1.0'
compile 'org.jsoup:jsoup:1.8.3' compile 'org.jsoup:jsoup:1.8.3'
compile 'org.mozilla:rhino:1.7.7' compile 'org.mozilla:rhino:1.7.7'
compile 'com.android.support:design:23.1.0'
} }

View File

@ -69,6 +69,7 @@ public class ActionBarHandler {
public void setStreams(VideoInfo.VideoStream[] videoStreams, VideoInfo.AudioStream[] audioStreams) { public void setStreams(VideoInfo.VideoStream[] videoStreams, VideoInfo.AudioStream[] audioStreams) {
this.videoStreams = videoStreams; this.videoStreams = videoStreams;
selectedStream = 0; selectedStream = 0;
defaultPreferences = PreferenceManager.getDefaultSharedPreferences(activity);
String[] itemArray = new String[videoStreams.length]; String[] itemArray = new String[videoStreams.length];
String defaultResolution = defaultPreferences String defaultResolution = defaultPreferences
.getString(activity.getString(R.string.defaultResolutionPreference), .getString(activity.getString(R.string.defaultResolutionPreference),
@ -93,7 +94,7 @@ public class ActionBarHandler {
// set audioStream // set audioStream
audioStream = null; audioStream = null;
String preferedFormat = PreferenceManager.getDefaultSharedPreferences(activity) String preferedFormat = defaultPreferences
.getString(activity.getString(R.string.defaultAudioFormatPreference), "webm"); .getString(activity.getString(R.string.defaultAudioFormatPreference), "webm");
if(preferedFormat.equals("webm")) { if(preferedFormat.equals("webm")) {
for(VideoInfo.AudioStream s : audioStreams) { for(VideoInfo.AudioStream s : audioStreams) {

View File

@ -143,6 +143,6 @@ public class VideoInfo {
public VideoStream[] videoStreams = null; public VideoStream[] videoStreams = null;
public AudioStream[] audioStreams = null; public AudioStream[] audioStreams = null;
public VideoInfoItem nextVideo = null; public VideoInfoItem nextVideo = null;
public Vector<VideoInfoItem> relatedVideos = null; public VideoInfoItem[] relatedVideos = null;
public int videoAvailableStatus = VIDEO_AVAILABLE; public int videoAvailableStatus = VIDEO_AVAILABLE;
} }

View File

@ -1,6 +1,8 @@
package org.schabi.newpipe; package org.schabi.newpipe;
import android.graphics.Bitmap; import android.graphics.Bitmap;
import android.os.Parcel;
import android.os.Parcelable;
/** /**
* Created by Christian Schabesberger on 26.08.15. * Created by Christian Schabesberger on 26.08.15.
@ -22,7 +24,7 @@ import android.graphics.Bitmap;
* along with NewPipe. If not, see <http://www.gnu.org/licenses/>. * along with NewPipe. If not, see <http://www.gnu.org/licenses/>.
*/ */
public class VideoInfoItem { public class VideoInfoItem implements Parcelable {
public String id = ""; public String id = "";
public String title = ""; public String title = "";
public String uploader = ""; public String uploader = "";
@ -32,4 +34,51 @@ public class VideoInfoItem {
public String webpage_url = ""; public String webpage_url = "";
public String upload_date = ""; public String upload_date = "";
public String view_count = ""; public String view_count = "";
protected VideoInfoItem(Parcel in) {
id = in.readString();
title = in.readString();
uploader = in.readString();
duration = in.readString();
thumbnail_url = in.readString();
thumbnail = (Bitmap) in.readValue(Bitmap.class.getClassLoader());
webpage_url = in.readString();
upload_date = in.readString();
view_count = in.readString();
}
public VideoInfoItem() {
}
@Override
public int describeContents() {
return 0;
}
@Override
public void writeToParcel(Parcel dest, int flags) {
dest.writeString(id);
dest.writeString(title);
dest.writeString(uploader);
dest.writeString(duration);
dest.writeString(thumbnail_url);
dest.writeValue(thumbnail);
dest.writeString(webpage_url);
dest.writeString(upload_date);
dest.writeString(view_count);
}
@SuppressWarnings("unused")
public static final Parcelable.Creator<VideoInfoItem> CREATOR = new Parcelable.Creator<VideoInfoItem>() {
@Override
public VideoInfoItem createFromParcel(Parcel in) {
return new VideoInfoItem(in);
}
@Override
public VideoInfoItem[] newArray(int size) {
return new VideoInfoItem[size];
}
};
} }

View File

@ -38,7 +38,6 @@ public class VideoItemDetailActivity extends AppCompatActivity {
private String videoUrl; private String videoUrl;
private int currentStreamingService = -1; private int currentStreamingService = -1;
private Menu menu = null;
protected void onCreate(Bundle savedInstanceState) { protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState); super.onCreate(savedInstanceState);

View File

@ -81,6 +81,7 @@ public class VideoItemDetailFragment extends Fragment {
private Handler h = new Handler(); private Handler h = new Handler();
private Extractor extractor; private Extractor extractor;
private String videoUrl; private String videoUrl;
public ExtractorRunnable(String videoUrl, Extractor extractor, VideoItemDetailFragment f) { public ExtractorRunnable(String videoUrl, Extractor extractor, VideoItemDetailFragment f) {
this.extractor = extractor; this.extractor = extractor;
this.videoUrl = videoUrl; this.videoUrl = videoUrl;
@ -95,18 +96,21 @@ public class VideoItemDetailFragment extends Fragment {
BitmapFactory.decodeStream( BitmapFactory.decodeStream(
new URL(videoInfo.thumbnail_url) new URL(videoInfo.thumbnail_url)
.openConnection() .openConnection()
.getInputStream()), SetThumbnailRunnable.VIDEO_THUMBNAIL)); .getInputStream()),
SetThumbnailRunnable.VIDEO_THUMBNAIL));
h.post(new SetThumbnailRunnable( h.post(new SetThumbnailRunnable(
BitmapFactory.decodeStream( BitmapFactory.decodeStream(
new URL(videoInfo.uploader_thumbnail_url) new URL(videoInfo.uploader_thumbnail_url)
.openConnection() .openConnection()
.getInputStream()), SetThumbnailRunnable.CHANNEL_THUMBNAIL)); .getInputStream()),
SetThumbnailRunnable.CHANNEL_THUMBNAIL));
if(showNextVideoItem) { if(showNextVideoItem) {
h.post(new SetThumbnailRunnable( h.post(new SetThumbnailRunnable(
BitmapFactory.decodeStream( BitmapFactory.decodeStream(
new URL(videoInfo.nextVideo.thumbnail_url) new URL(videoInfo.nextVideo.thumbnail_url)
.openConnection() .openConnection()
.getInputStream()), SetThumbnailRunnable.NEXT_VIDEO_THUMBNAIL)); .getInputStream()),
SetThumbnailRunnable.NEXT_VIDEO_THUMBNAIL));
} }
} }
} catch (Exception e) { } catch (Exception e) {
@ -175,29 +179,28 @@ public class VideoItemDetailFragment extends Fragment {
} }
public void updateInfo(VideoInfo info) { public void updateInfo(VideoInfo info) {
Activity a = getActivity();
currentVideoInfo = info; currentVideoInfo = info;
try { try {
VideoInfoItemViewCreator videoItemViewCreator = VideoInfoItemViewCreator videoItemViewCreator =
new VideoInfoItemViewCreator(LayoutInflater.from(getActivity())); new VideoInfoItemViewCreator(LayoutInflater.from(getActivity()));
ScrollView contentMainView = (ScrollView) a.findViewById(R.id.detailMainContent); ScrollView contentMainView = (ScrollView) activity.findViewById(R.id.detailMainContent);
ProgressBar progressBar = (ProgressBar) a.findViewById(R.id.detailProgressBar); ProgressBar progressBar = (ProgressBar) activity.findViewById(R.id.detailProgressBar);
TextView videoTitleView = (TextView) a.findViewById(R.id.detailVideoTitleView); TextView videoTitleView = (TextView) activity.findViewById(R.id.detailVideoTitleView);
TextView uploaderView = (TextView) a.findViewById(R.id.detailUploaderView); TextView uploaderView = (TextView) activity.findViewById(R.id.detailUploaderView);
TextView viewCountView = (TextView) a.findViewById(R.id.detailViewCountView); TextView viewCountView = (TextView) activity.findViewById(R.id.detailViewCountView);
TextView thumbsUpView = (TextView) a.findViewById(R.id.detailThumbsUpCountView); TextView thumbsUpView = (TextView) activity.findViewById(R.id.detailThumbsUpCountView);
TextView thumbsDownView = (TextView) a.findViewById(R.id.detailThumbsDownCountView); TextView thumbsDownView = (TextView) activity.findViewById(R.id.detailThumbsDownCountView);
TextView uploadDateView = (TextView) a.findViewById(R.id.detailUploadDateView); TextView uploadDateView = (TextView) activity.findViewById(R.id.detailUploadDateView);
TextView descriptionView = (TextView) a.findViewById(R.id.detailDescriptionView); TextView descriptionView = (TextView) activity.findViewById(R.id.detailDescriptionView);
ImageView thumbnailView = (ImageView) a.findViewById(R.id.detailThumbnailView); ImageView thumbnailView = (ImageView) activity.findViewById(R.id.detailThumbnailView);
FrameLayout nextVideoFrame = (FrameLayout) a.findViewById(R.id.detailNextVideoFrame); FrameLayout nextVideoFrame = (FrameLayout) activity.findViewById(R.id.detailNextVideoFrame);
RelativeLayout nextVideoRootFrame = RelativeLayout nextVideoRootFrame =
(RelativeLayout) a.findViewById(R.id.detailNextVideoRootLayout); (RelativeLayout) activity.findViewById(R.id.detailNextVideoRootLayout);
View nextVideoView = videoItemViewCreator View nextVideoView = videoItemViewCreator
.getViewByVideoInfoItem(null, nextVideoFrame, info.nextVideo); .getViewByVideoInfoItem(null, nextVideoFrame, info.nextVideo);
nextVideoFrame.addView(nextVideoView); nextVideoFrame.addView(nextVideoView);
Button nextVideoButton = (Button) a.findViewById(R.id.detailNextVideoButton); Button nextVideoButton = (Button) activity.findViewById(R.id.detailNextVideoButton);
contentMainView.setVisibility(View.VISIBLE); contentMainView.setVisibility(View.VISIBLE);
progressBar.setVisibility(View.GONE); progressBar.setVisibility(View.GONE);
@ -209,10 +212,12 @@ public class VideoItemDetailFragment extends Fragment {
case VideoInfo.VIDEO_AVAILABLE: { case VideoInfo.VIDEO_AVAILABLE: {
videoTitleView.setText(info.title); videoTitleView.setText(info.title);
uploaderView.setText(info.uploader); uploaderView.setText(info.uploader);
viewCountView.setText(info.view_count + " " + a.getString(R.string.viewSufix)); viewCountView.setText(info.view_count
+ " " + activity.getString(R.string.viewSufix));
thumbsUpView.setText(info.like_count); thumbsUpView.setText(info.like_count);
thumbsDownView.setText(info.dislike_count); thumbsDownView.setText(info.dislike_count);
uploadDateView.setText(a.getString(R.string.uploadDatePrefix) + " " + info.upload_date); uploadDateView.setText(
activity.getString(R.string.uploadDatePrefix) + " " + info.upload_date);
descriptionView.setText(Html.fromHtml(info.description)); descriptionView.setText(Html.fromHtml(info.description));
descriptionView.setMovementMethod(LinkMovementMethod.getInstance()); descriptionView.setMovementMethod(LinkMovementMethod.getInstance());
@ -235,9 +240,12 @@ public class VideoItemDetailFragment extends Fragment {
nextVideoButton.setOnClickListener(new View.OnClickListener() { nextVideoButton.setOnClickListener(new View.OnClickListener() {
@Override @Override
public void onClick(View v) { public void onClick(View v) {
Intent detailIntent = new Intent(getActivity(), VideoItemDetailActivity.class); Intent detailIntent =
detailIntent.putExtra(VideoItemDetailFragment.ARG_ITEM_ID, currentVideoInfo.nextVideo.id); new Intent(getActivity(), VideoItemDetailActivity.class);
detailIntent.putExtra(VideoItemDetailFragment.VIDEO_URL, currentVideoInfo.nextVideo.webpage_url); detailIntent.putExtra(
VideoItemDetailFragment.ARG_ITEM_ID, currentVideoInfo.nextVideo.id);
detailIntent.putExtra(
VideoItemDetailFragment.VIDEO_URL, currentVideoInfo.nextVideo.webpage_url);
//todo: make id dynamic the following line is crap //todo: make id dynamic the following line is crap
detailIntent.putExtra(VideoItemDetailFragment.STREAMING_SERVICE, 0); detailIntent.putExtra(VideoItemDetailFragment.STREAMING_SERVICE, 0);
startActivity(detailIntent); startActivity(detailIntent);
@ -245,10 +253,12 @@ public class VideoItemDetailFragment extends Fragment {
}); });
break; break;
case VideoInfo.VIDEO_UNAVAILABLE_GEMA: case VideoInfo.VIDEO_UNAVAILABLE_GEMA:
thumbnailView.setImageBitmap(BitmapFactory.decodeResource(getResources(), R.drawable.gruese_die_gema_unangebracht)); thumbnailView.setImageBitmap(BitmapFactory.decodeResource(
getResources(), R.drawable.gruese_die_gema_unangebracht));
break; break;
case VideoInfo.VIDEO_UNAVAILABLE: case VideoInfo.VIDEO_UNAVAILABLE:
thumbnailView.setImageBitmap(BitmapFactory.decodeResource(getResources(), R.drawable.not_available_monkey)); thumbnailView.setImageBitmap(BitmapFactory.decodeResource(
getResources(), R.drawable.not_available_monkey));
break; break;
default: default:
Log.e(TAG, "Video Available Status not known."); Log.e(TAG, "Video Available Status not known.");
@ -303,15 +313,19 @@ public class VideoItemDetailFragment extends Fragment {
@Override @Override
public void onActivityCreated(Bundle savedInstanceBundle) { public void onActivityCreated(Bundle savedInstanceBundle) {
super.onActivityCreated(savedInstanceBundle); super.onActivityCreated(savedInstanceBundle);
FloatingActionButton playVideoButton = (FloatingActionButton) getActivity().findViewById(R.id.playVideoButton); FloatingActionButton playVideoButton =
(FloatingActionButton) getActivity().findViewById(R.id.playVideoButton);
// Sometimes when this fragment is not visible it still gets initiated
// then we must not try to access objects of this fragment.
// Otherwise the applications would crash.
if(playVideoButton != null) { if(playVideoButton != null) {
try { try {
StreamingService streamingService = ServiceList.getService( StreamingService streamingService = ServiceList.getService(
getArguments().getInt(STREAMING_SERVICE)); getArguments().getInt(STREAMING_SERVICE));
extractorThread = new Thread(new ExtractorRunnable( extractorThread = new Thread(new ExtractorRunnable(
getArguments().getString(VIDEO_URL), streamingService.getExtractorInstance(), this)); getArguments().getString(VIDEO_URL), streamingService.getExtractorInstance(), this));
autoPlayEnabled = getArguments().getBoolean(AUTO_PLAY); autoPlayEnabled = getArguments().getBoolean(AUTO_PLAY);
extractorThread.start(); extractorThread.start();
} catch (Exception e) { } catch (Exception e) {
@ -320,13 +334,15 @@ public class VideoItemDetailFragment extends Fragment {
if (PreferenceManager.getDefaultSharedPreferences(getActivity()) if (PreferenceManager.getDefaultSharedPreferences(getActivity())
.getBoolean(getString(R.string.leftHandLayout), false) && checkIfLandscape()) { .getBoolean(getString(R.string.leftHandLayout), false) && checkIfLandscape()) {
RelativeLayout.LayoutParams oldLayout = (RelativeLayout.LayoutParams) playVideoButton.getLayoutParams(); RelativeLayout.LayoutParams oldLayout =
(RelativeLayout.LayoutParams) playVideoButton.getLayoutParams();
RelativeLayout.LayoutParams layoutParams = new RelativeLayout.LayoutParams( RelativeLayout.LayoutParams layoutParams = new RelativeLayout.LayoutParams(
RelativeLayout.LayoutParams.WRAP_CONTENT, RelativeLayout.LayoutParams.WRAP_CONTENT,
RelativeLayout.LayoutParams.WRAP_CONTENT); RelativeLayout.LayoutParams.WRAP_CONTENT);
layoutParams.addRule(RelativeLayout.ALIGN_PARENT_BOTTOM); layoutParams.addRule(RelativeLayout.ALIGN_PARENT_BOTTOM);
layoutParams.addRule(RelativeLayout.ALIGN_PARENT_LEFT); layoutParams.addRule(RelativeLayout.ALIGN_PARENT_LEFT);
layoutParams.setMargins(oldLayout.leftMargin, oldLayout.topMargin, oldLayout.rightMargin, oldLayout.bottomMargin); layoutParams.setMargins(oldLayout.leftMargin, oldLayout.topMargin,
oldLayout.rightMargin, oldLayout.bottomMargin);
playVideoButton.setLayoutParams(layoutParams); playVideoButton.setLayoutParams(layoutParams);
} }
@ -336,6 +352,16 @@ public class VideoItemDetailFragment extends Fragment {
actionBarHandler.playVideo(); actionBarHandler.playVideo();
} }
}); });
Button similarVideosButton = (Button) activity.findViewById(R.id.detailShowSimilarButton);
similarVideosButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Intent intent = new Intent(activity, VideoItemListActivity.class);
intent.putExtra(VideoItemListActivity.VIDEO_INFO_ITEMS, currentVideoInfo.relatedVideos);
activity.startActivity(intent);
}
});
} }
} }

View File

@ -3,8 +3,12 @@ package org.schabi.newpipe;
import android.content.Context; import android.content.Context;
import android.content.Intent; import android.content.Intent;
import android.os.Bundle; import android.os.Bundle;
import android.os.Parcel;
import android.os.Parcelable;
import android.support.v4.app.NavUtils;
import android.support.v7.app.AppCompatActivity; import android.support.v7.app.AppCompatActivity;
import android.support.v7.widget.SearchView; import android.support.v7.widget.SearchView;
import android.util.Log;
import android.view.Menu; import android.view.Menu;
import android.view.MenuInflater; import android.view.MenuInflater;
import android.view.MenuItem; import android.view.MenuItem;
@ -12,6 +16,8 @@ import android.view.View;
import android.view.inputmethod.InputMethodManager; import android.view.inputmethod.InputMethodManager;
import android.widget.ImageView; import android.widget.ImageView;
import java.util.Arrays;
/** /**
* Copyright (C) Christian Schabesberger 2015 <chris.schabesberger@mailbox.org> * Copyright (C) Christian Schabesberger 2015 <chris.schabesberger@mailbox.org>
* VideoItemListActivity.java is part of NewPipe. * VideoItemListActivity.java is part of NewPipe.
@ -34,9 +40,19 @@ public class VideoItemListActivity extends AppCompatActivity
implements VideoItemListFragment.Callbacks { implements VideoItemListFragment.Callbacks {
private static final String TAG = VideoItemListFragment.class.toString(); private static final String TAG = VideoItemListFragment.class.toString();
// arguments to give to this activity
public static final String VIDEO_INFO_ITEMS = "video_info_items";
// savedInstanceBundle arguments
private static final String QUERY = "query"; private static final String QUERY = "query";
private static final String STREAMING_SERVICE = "streaming_service"; private static final String STREAMING_SERVICE = "streaming_service";
// activity modes
private static final int SEARCH_MODE = 0;
private static final int PRESENT_VIDEOS_MODE = 1;
private int mode = SEARCH_MODE;
private int currentStreamingServiceId = -1; private int currentStreamingServiceId = -1;
private String searchQuery = ""; private String searchQuery = "";
@ -95,7 +111,22 @@ public class VideoItemListActivity extends AppCompatActivity
.findFragmentById(R.id.videoitem_list); .findFragmentById(R.id.videoitem_list);
listFragment.setStreamingService(ServiceList.getService(currentStreamingServiceId)); listFragment.setStreamingService(ServiceList.getService(currentStreamingServiceId));
if(savedInstanceState != null) { Bundle arguments = getIntent().getExtras();
if(arguments != null) {
Parcelable[] p = arguments.getParcelableArray(VIDEO_INFO_ITEMS);
if(p != null) {
mode = PRESENT_VIDEOS_MODE;
getSupportActionBar().setDisplayHomeAsUpEnabled(true);
//todo: make this more efficient
listFragment.present(Arrays.copyOf(p, p.length, VideoInfoItem[].class));
}
}
if(savedInstanceState != null
&& mode != PRESENT_VIDEOS_MODE) {
searchQuery = savedInstanceState.getString(QUERY); searchQuery = savedInstanceState.getString(QUERY);
currentStreamingServiceId = savedInstanceState.getInt(STREAMING_SERVICE); currentStreamingServiceId = savedInstanceState.getInt(STREAMING_SERVICE);
if(!searchQuery.isEmpty()) { if(!searchQuery.isEmpty()) {
@ -118,15 +149,18 @@ public class VideoItemListActivity extends AppCompatActivity
.setActivateOnItemClick(true); .setActivateOnItemClick(true);
SearchView searchView = (SearchView)findViewById(R.id.searchViewTablet); SearchView searchView = (SearchView)findViewById(R.id.searchViewTablet);
// Somehow the seticonifiedbydefault property set by the layout xml is not working on if(mode != PRESENT_VIDEOS_MODE) {
// the support version on SearchView, so it needs to be set programmatically. // Somehow the seticonifiedbydefault property set by the layout xml is not working on
searchView.setIconifiedByDefault(false); // the support version on SearchView, so it needs to be set programmatically.
searchView.setIconified(false); searchView.setIconifiedByDefault(false);
searchView.setOnQueryTextListener(new SearchVideoQueryListener()); searchView.setIconified(false);
searchView.setOnQueryTextListener(new SearchVideoQueryListener());
} else {
searchView.setVisibility(View.GONE);
}
} }
SettingsActivity.initSettings(this); SettingsActivity.initSettings(this);
} }
/** /**
@ -176,7 +210,8 @@ public class VideoItemListActivity extends AppCompatActivity
super.onCreateOptionsMenu(menu); super.onCreateOptionsMenu(menu);
this.menu = menu; this.menu = menu;
MenuInflater inflater = getMenuInflater(); MenuInflater inflater = getMenuInflater();
if(findViewById(R.id.videoitem_detail_container) == null) { if(mode != PRESENT_VIDEOS_MODE &&
findViewById(R.id.videoitem_detail_container) == null) {
inflater.inflate(R.menu.videoitem_list, menu); inflater.inflate(R.menu.videoitem_list, menu);
MenuItem searchItem = menu.findItem(R.id.action_search); MenuItem searchItem = menu.findItem(R.id.action_search);
SearchView searchView = (SearchView) searchItem.getActionView(); SearchView searchView = (SearchView) searchItem.getActionView();
@ -196,14 +231,23 @@ public class VideoItemListActivity extends AppCompatActivity
@Override @Override
public boolean onOptionsItemSelected(MenuItem item) { public boolean onOptionsItemSelected(MenuItem item) {
int id = item.getItemId(); int id = item.getItemId();
if(id == R.id.action_settings) {
Intent intent = new Intent(this, SettingsActivity.class); switch(id) {
startActivity(intent); case android.R.id.home: {
} else { Intent intent = new Intent(this, VideoItemListActivity.class);
return videoFragment.onOptionsItemSelected(item) || intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
NavUtils.navigateUpTo(this, intent);
return true;
}
case R.id.action_settings: {
Intent intent = new Intent(this, SettingsActivity.class);
startActivity(intent);
return true;
}
default:
return videoFragment.onOptionsItemSelected(item) ||
super.onOptionsItemSelected(item); super.onOptionsItemSelected(item);
} }
return true;
} }
@Override @Override

View File

@ -13,6 +13,7 @@ import android.widget.ListView;
import android.widget.Toast; import android.widget.Toast;
import java.net.URL; import java.net.URL;
import java.util.Arrays;
import java.util.Vector; import java.util.Vector;
@ -41,6 +42,11 @@ public class VideoItemListFragment extends ListFragment {
private StreamingService streamingService = null; private StreamingService streamingService = null;
private VideoListAdapter videoListAdapter; private VideoListAdapter videoListAdapter;
// activity modes
private static final int SEARCH_MODE = 0;
private static final int PRESENT_VIDEOS_MODE = 1;
private int mode = SEARCH_MODE;
private String query = ""; private String query = "";
private int lastPage = 0; private int lastPage = 0;
@ -50,6 +56,7 @@ public class VideoItemListFragment extends ListFragment {
private LoadThumbsRunnable loadThumbsRunnable = null; private LoadThumbsRunnable loadThumbsRunnable = null;
// used to track down if results posted by threads ar still valid // used to track down if results posted by threads ar still valid
private int currentRequestId = -1; private int currentRequestId = -1;
private ListView list;
private class ResultRunnable implements Runnable { private class ResultRunnable implements Runnable {
private SearchEngine.Result result; private SearchEngine.Result result;
@ -154,7 +161,18 @@ public class VideoItemListFragment extends ListFragment {
} }
} }
public void present(VideoInfoItem[] videoList) {
mode = PRESENT_VIDEOS_MODE;
setListShown(true);
getListView().smoothScrollToPosition(0);
// inefficient like hell i know (welcome to the world of java)
//todo: make this more efficient
updateList(new Vector<>(Arrays.asList(videoList)));
}
public void search(String query) { public void search(String query) {
mode = SEARCH_MODE;
this.query = query; this.query = query;
this.lastPage = 1; this.lastPage = 1;
videoListAdapter.clearVideoList(); videoListAdapter.clearVideoList();
@ -261,6 +279,7 @@ public class VideoItemListFragment extends ListFragment {
@Override @Override
public void onViewCreated(View view, Bundle savedInstanceState) { public void onViewCreated(View view, Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState); super.onViewCreated(view, savedInstanceState);
list = getListView();
videoListAdapter = new VideoListAdapter(getActivity(), this); videoListAdapter = new VideoListAdapter(getActivity(), this);
setListAdapter(videoListAdapter); setListAdapter(videoListAdapter);
@ -272,8 +291,6 @@ public class VideoItemListFragment extends ListFragment {
} }
getListView().setOnScrollListener(new AbsListView.OnScrollListener() { getListView().setOnScrollListener(new AbsListView.OnScrollListener() {
private static final float OVERSCROLL_THRESHOLD_IN_PIXELS = 100;
private float downY;
long lastScrollDate = 0; long lastScrollDate = 0;
@Override @Override
@ -282,8 +299,8 @@ public class VideoItemListFragment extends ListFragment {
@Override @Override
public void onScroll(AbsListView view, int firstVisibleItem, int visibleItemCount, int totalItemCount) { public void onScroll(AbsListView view, int firstVisibleItem, int visibleItemCount, int totalItemCount) {
ListView list = getListView(); if (mode != PRESENT_VIDEOS_MODE
if (list.getChildAt(0) != null && list.getChildAt(0) != null
&& list.getLastVisiblePosition() == list.getAdapter().getCount() - 1 && list.getLastVisiblePosition() == list.getAdapter().getCount() - 1
&& list.getChildAt(list.getChildCount() - 1).getBottom() <= list.getHeight()) { && list.getChildAt(list.getChildCount() - 1).getBottom() <= list.getHeight()) {
long time = System.currentTimeMillis(); long time = System.currentTimeMillis();

View File

@ -233,10 +233,8 @@ public class YoutubeExtractor implements Extractor {
resolveResolutionString(itag))); resolveResolutionString(itag)));
} }
} }
videoInfo.videoStreams = new VideoInfo.VideoStream[videoStreams.size()]; videoInfo.videoStreams =
for(int i = 0; i < videoStreams.size(); i++) { videoStreams.toArray(new VideoInfo.VideoStream[videoStreams.size()]);
videoInfo.videoStreams[i] = videoStreams.get(i);
}
} catch (Exception e) { } catch (Exception e) {
e.printStackTrace(); e.printStackTrace();
@ -310,15 +308,15 @@ public class YoutubeExtractor implements Extractor {
int i = 0; int i = 0;
// related videos // related videos
videoInfo.relatedVideos = new Vector<>(); Vector<VideoInfoItem> relatedVideos = new Vector<>();
for(Element li : doc.select("ul[id=\"watch-related\"]").first().children()) { for(Element li : doc.select("ul[id=\"watch-related\"]").first().children()) {
// first check if we have a playlist. If so leave them out // first check if we have a playlist. If so leave them out
if(li.select("a[class*=\"content-link\"]").first() != null) { if(li.select("a[class*=\"content-link\"]").first() != null) {
videoInfo.relatedVideos.add(extractVideoInfoItem(li)); relatedVideos.add(extractVideoInfoItem(li));
i++; i++;
} }
} }
videoInfo.relatedVideos = relatedVideos.toArray(new VideoInfoItem[relatedVideos.size()]);
return videoInfo; return videoInfo;
} }
@ -390,11 +388,7 @@ public class YoutubeExtractor implements Extractor {
} catch(Exception e) { } catch(Exception e) {
e.printStackTrace(); e.printStackTrace();
} }
VideoInfo.AudioStream[] output = new VideoInfo.AudioStream[audioStreams.size()]; return audioStreams.toArray(new VideoInfo.AudioStream[audioStreams.size()]);
for(int i = 0; i < output.length; i++) {
output[i] = audioStreams.get(i);
}
return output;
} }
private VideoInfoItem extractVideoInfoItem(Element li) { private VideoInfoItem extractVideoInfoItem(Element li) {

View File

@ -188,10 +188,18 @@
android:layout_alignParentLeft="true" /> android:layout_alignParentLeft="true" />
</RelativeLayout> </RelativeLayout>
<Button android:id="@+id/detailShowSimilarButton"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginLeft="6dp"
android:layout_marginRight="6dp"
android:layout_below="@id/detailNextVideoRootLayout"
android:text="@string/showSimilarVideosButtonText"/>
<View <View
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="90dp" android:layout_height="90dp"
android:layout_below="@id/detailNextVideoRootLayout"/> android:layout_below="@id/detailShowSimilarButton"/>
</RelativeLayout> </RelativeLayout>
</ScrollView> </ScrollView>

View File

@ -188,10 +188,18 @@
android:layout_alignParentLeft="true" /> android:layout_alignParentLeft="true" />
</RelativeLayout> </RelativeLayout>
<Button android:id="@+id/detailShowSimilarButton"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginLeft="6dp"
android:layout_marginRight="6dp"
android:layout_below="@id/detailNextVideoRootLayout"
android:text="@string/showSimilarVideosButtonText"/>
<View <View
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="90dp" android:layout_height="90dp"
android:layout_below="@id/detailNextVideoRootLayout"/> android:layout_below="@id/detailShowSimilarButton"/>
</RelativeLayout> </RelativeLayout>
</ScrollView> </ScrollView>

View File

@ -185,13 +185,22 @@
android:layout_alignParentLeft="true" /> android:layout_alignParentLeft="true" />
</RelativeLayout> </RelativeLayout>
<Button android:id="@+id/detailShowSimilarButton"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginLeft="6dp"
android:layout_marginRight="6dp"
android:layout_below="@id/detailNextVideoRootLayout"
android:text="@string/showSimilarVideosButtonText"/>
<View <View
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="90dp" android:layout_height="90dp"
android:layout_below="@id/detailNextVideoRootLayout"/> android:layout_below="@id/detailShowSimilarButton"/>
</RelativeLayout> </RelativeLayout>
</ScrollView> </ScrollView>
<android.support.design.widget.FloatingActionButton <android.support.design.widget.FloatingActionButton
android:id="@+id/playVideoButton" android:id="@+id/playVideoButton"
android:layout_alignParentBottom="true" android:layout_alignParentBottom="true"

View File

@ -48,4 +48,5 @@
<string name="nextVideoTitle">Nächstes Video</string> <string name="nextVideoTitle">Nächstes Video</string>
<string name="showNextVideoTitle">Zeige \"Nächstes Video\" Auswahl.</string> <string name="showNextVideoTitle">Zeige \"Nächstes Video\" Auswahl.</string>
<string name="urlNotSupportedText">Url wird nicht unterstützt.</string> <string name="urlNotSupportedText">Url wird nicht unterstützt.</string>
<string name="showSimilarVideosButtonText">Ähnliche Videos</string>
</resources> </resources>

View File

@ -48,4 +48,5 @@
<string name="nextVideoTitle">Next Video</string> <string name="nextVideoTitle">Next Video</string>
<string name="showNextVideoTitle">Show \"Next video\" item.</string> <string name="showNextVideoTitle">Show \"Next video\" item.</string>
<string name="urlNotSupportedText">Url not Supported.</string> <string name="urlNotSupportedText">Url not Supported.</string>
<string name="showSimilarVideosButtonText">Similar Videos</string>
</resources> </resources>