diff --git a/README.md b/README.md
index b24ed14af..a11084c4e 100644
--- a/README.md
+++ b/README.md
@@ -18,7 +18,6 @@ Project status:
[](screenshots/screenshot_3.png)
[](screenshots/screenshot_4.png)
[](screenshots/screenshot_5.png)
-[](screenshots/screenshot_6.png)
## Description
diff --git a/app/build.gradle b/app/build.gradle
index 67b7e5326..05cdbb2f6 100644
--- a/app/build.gradle
+++ b/app/build.gradle
@@ -2,7 +2,7 @@ apply plugin: 'com.android.application'
android {
compileSdkVersion 23
- buildToolsVersion "23.0.2"
+ buildToolsVersion '23.0.2'
defaultConfig {
applicationId "org.schabi.newpipe"
@@ -24,6 +24,10 @@ android {
// but continue the build even when errors are found:
abortOnError false
}
+ compileOptions {
+ sourceCompatibility JavaVersion.VERSION_1_7
+ targetCompatibility JavaVersion.VERSION_1_7
+ }
}
dependencies {
@@ -31,9 +35,11 @@ dependencies {
compile 'com.android.support:appcompat-v7:23.1.1'
compile 'com.android.support:support-v4:23.1.1'
compile 'com.android.support:design:23.1.1'
- compile 'com.android.support:cardview-v7:23.1.1'
compile 'com.android.support:recyclerview-v7:23.1.1'
compile 'org.jsoup:jsoup:1.8.3'
compile 'org.mozilla:rhino:1.7.7'
compile 'info.guardianproject.netcipher:netcipher:1.2'
+ compile 'de.hdodenhof:circleimageview:2.0.0'
+ compile 'com.nostra13.universalimageloader:universal-image-loader:1.9.5'
+ compile 'com.github.nirhart:parallaxscroll:1.0'
}
diff --git a/app/src/androidTest/java/org/schabi/newpipe/services/youtube/YoutubeVideoExtractorDefaultTest.java b/app/src/androidTest/java/org/schabi/newpipe/services/youtube/YoutubeVideoExtractorDefaultTest.java
index b63e390c2..19246b54c 100644
--- a/app/src/androidTest/java/org/schabi/newpipe/services/youtube/YoutubeVideoExtractorDefaultTest.java
+++ b/app/src/androidTest/java/org/schabi/newpipe/services/youtube/YoutubeVideoExtractorDefaultTest.java
@@ -1,6 +1,7 @@
package org.schabi.newpipe.services.youtube;
import android.test.AndroidTestCase;
+import android.util.Log;
import org.schabi.newpipe.Downloader;
import org.schabi.newpipe.crawler.CrawlingException;
diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml
index 2f2ec061b..e30920404 100644
--- a/app/src/main/AndroidManifest.xml
+++ b/app/src/main/AndroidManifest.xml
@@ -16,7 +16,8 @@
tools:ignore="AllowBackup">
+ android:label="@string/app_name"
+ android:configChanges="orientation|screenSize">
@@ -26,7 +27,9 @@
+ android:theme="@style/AppTheme"
+ android:configChanges="orientation|screenSize"
+ android:screenOrientation="portrait">
diff --git a/app/src/main/java/org/schabi/newpipe/ActionBarHandler.java b/app/src/main/java/org/schabi/newpipe/ActionBarHandler.java
index a5e7c8cff..b3451cbaf 100644
--- a/app/src/main/java/org/schabi/newpipe/ActionBarHandler.java
+++ b/app/src/main/java/org/schabi/newpipe/ActionBarHandler.java
@@ -15,6 +15,7 @@ import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
import android.widget.ArrayAdapter;
+import android.widget.Toast;
import org.schabi.newpipe.crawler.MediaFormat;
import org.schabi.newpipe.crawler.VideoInfo;
@@ -24,7 +25,7 @@ import java.util.List;
/**
* Created by Christian Schabesberger on 18.08.15.
*
- * Copyright (C) Christian Schabesberger 2016
+ * Copyright (C) Christian Schabesberger 2015
* DetailsMenuHandler.java is part of NewPipe.
*
* NewPipe is free software: you can redistribute it and/or modify
@@ -86,7 +87,7 @@ class ActionBarHandler {
serviceId = id;
}
- public void setSetVideoThumbnail(Bitmap bitmap) {
+ public void setVideoThumbnail(Bitmap bitmap) {
videoThumbnail = bitmap;
}
@@ -327,7 +328,6 @@ class ActionBarHandler {
}
public void playAudio() {
-
boolean externalAudioPlayer = PreferenceManager.getDefaultSharedPreferences(activity)
.getBoolean(activity.getString(R.string.use_external_audio_player_key), false);
Intent intent;
diff --git a/app/src/main/java/org/schabi/newpipe/App.java b/app/src/main/java/org/schabi/newpipe/App.java
index d842e3f0a..1e51b6a34 100644
--- a/app/src/main/java/org/schabi/newpipe/App.java
+++ b/app/src/main/java/org/schabi/newpipe/App.java
@@ -5,6 +5,9 @@ import android.content.Context;
import android.content.SharedPreferences;
import android.preference.PreferenceManager;
+import com.nostra13.universalimageloader.core.ImageLoader;
+import com.nostra13.universalimageloader.core.ImageLoaderConfiguration;
+
import info.guardianproject.netcipher.NetCipher;
import info.guardianproject.netcipher.proxy.OrbotHelper;
@@ -34,6 +37,10 @@ public class App extends Application {
public void onCreate() {
super.onCreate();
+ // Initialize image loader
+ ImageLoaderConfiguration config = new ImageLoaderConfiguration.Builder(this).build();
+ ImageLoader.getInstance().init(config);
+
SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(this);
if(prefs.getBoolean(getString(R.string.use_tor_key), false)) {
OrbotHelper.requestStartTor(this);
diff --git a/app/src/main/java/org/schabi/newpipe/BackgroundPlayer.java b/app/src/main/java/org/schabi/newpipe/BackgroundPlayer.java
index cf0f88d05..7223928fe 100644
--- a/app/src/main/java/org/schabi/newpipe/BackgroundPlayer.java
+++ b/app/src/main/java/org/schabi/newpipe/BackgroundPlayer.java
@@ -53,7 +53,7 @@ public class BackgroundPlayer extends Service /*implements MediaPlayer.OnPrepare
public static final String TITLE = "title";
public static final String WEB_URL = "web_url";
public static final String SERVICE_ID = "service_id";
- public static final String CHANNEL_NAME="channel_name";
+ public static final String CHANNEL_NAME = "channel_name";
private volatile String webUrl = "";
private volatile int serviceId = -1;
@@ -117,6 +117,7 @@ public class BackgroundPlayer extends Service /*implements MediaPlayer.OnPrepare
private WifiManager.WifiLock wifiLock;
private Bitmap videoThumbnail = null;
private NotificationCompat.Builder noteBuilder;
+ private Notification note;
public PlayerThread(String src, String title, BackgroundPlayer owner) {
this.source = src;
@@ -174,7 +175,7 @@ public class BackgroundPlayer extends Service /*implements MediaPlayer.OnPrepare
filter.addAction(ACTION_STOP);
registerReceiver(broadcastReceiver, filter);
- Notification note = buildNotification();
+ note = buildNotification();
startForeground(noteID, note);
@@ -204,11 +205,21 @@ public class BackgroundPlayer extends Service /*implements MediaPlayer.OnPrepare
if(action.equals(ACTION_PLAYPAUSE)) {
if(mediaPlayer.isPlaying()) {
mediaPlayer.pause();
+ note.contentView.setImageViewResource(R.id.backgroundPlayPause, R.drawable.ic_play_circle_filled_white_24dp);
+ if(android.os.Build.VERSION.SDK_INT >=16){
+ note.bigContentView.setImageViewResource(R.id.backgroundPlayPause, R.drawable.ic_play_circle_filled_white_24dp);
+ }
+ noteMgr.notify(noteID, note);
}
else {
//reacquire CPU lock after auto-releasing it on pause
mediaPlayer.setWakeMode(getApplicationContext(), PowerManager.PARTIAL_WAKE_LOCK);
mediaPlayer.start();
+ note.contentView.setImageViewResource(R.id.backgroundPlayPause, R.drawable.ic_pause_white_24dp);
+ if(android.os.Build.VERSION.SDK_INT >=16){
+ note.bigContentView.setImageViewResource(R.id.backgroundPlayPause, R.drawable.ic_pause_white_24dp);
+ }
+ noteMgr.notify(noteID, note);
}
}
else if(action.equals(ACTION_STOP)) {
diff --git a/app/src/main/java/org/schabi/newpipe/VideoInfoItemViewCreator.java b/app/src/main/java/org/schabi/newpipe/VideoInfoItemViewCreator.java
index e254af02d..07f631146 100644
--- a/app/src/main/java/org/schabi/newpipe/VideoInfoItemViewCreator.java
+++ b/app/src/main/java/org/schabi/newpipe/VideoInfoItemViewCreator.java
@@ -8,6 +8,8 @@ import android.widget.ImageView;
import android.widget.TextView;
import org.schabi.newpipe.crawler.VideoPreviewInfo;
+import com.nostra13.universalimageloader.core.DisplayImageOptions;
+import com.nostra13.universalimageloader.core.ImageLoader;
/**
* Created by Christian Schabesberger on 24.10.15.
@@ -31,6 +33,8 @@ import org.schabi.newpipe.crawler.VideoPreviewInfo;
class VideoInfoItemViewCreator {
private final LayoutInflater inflater;
+ private ImageLoader imageLoader = ImageLoader.getInstance();
+ private DisplayImageOptions displayImageOptions = new DisplayImageOptions.Builder().cacheInMemory(true).build();
public VideoInfoItemViewCreator(LayoutInflater inflater) {
this.inflater = inflater;
@@ -46,6 +50,7 @@ class VideoInfoItemViewCreator {
holder.itemUploaderView = (TextView) convertView.findViewById(R.id.itemUploaderView);
holder.itemDurationView = (TextView) convertView.findViewById(R.id.itemDurationView);
holder.itemUploadDateView = (TextView) convertView.findViewById(R.id.itemUploadDateView);
+ holder.itemViewCountView = (TextView) convertView.findViewById(R.id.itemViewCountView);
convertView.setTag(holder);
} else {
holder = (ViewHolder) convertView.getTag();
@@ -59,18 +64,31 @@ class VideoInfoItemViewCreator {
holder.itemVideoTitleView.setText(info.title);
holder.itemUploaderView.setText(info.uploader);
holder.itemDurationView.setText(info.duration);
+ holder.itemViewCountView.setText(shortViewCount(info.view_count));
if(!info.upload_date.isEmpty()) {
- holder.itemUploadDateView.setText(info.upload_date);
- } else {
- holder.itemUploadDateView.setText(Localization.localizeViewCount(info.view_count, context));
+ holder.itemUploadDateView.setText(info.upload_date+" • ");
}
+ imageLoader.displayImage(info.thumbnail_url, holder.itemThumbnailView, displayImageOptions);
+
return convertView;
}
private class ViewHolder {
public ImageView itemThumbnailView;
- public TextView itemVideoTitleView, itemUploaderView, itemDurationView, itemUploadDateView;
+ public TextView itemVideoTitleView, itemUploaderView, itemDurationView, itemUploadDateView, itemViewCountView;
+ }
+
+ private String shortViewCount(Long view_count){
+ if(view_count >= 1000000000){
+ return Long.toString(view_count/1000000000)+"B views";
+ }else if(view_count>=1000000){
+ return Long.toString(view_count/1000000)+"M views";
+ }else if(view_count>=1000){
+ return Long.toString(view_count/1000)+"K views";
+ }else {
+ return Long.toString(view_count)+" views";
+ }
}
}
diff --git a/app/src/main/java/org/schabi/newpipe/VideoItemDetailFragment.java b/app/src/main/java/org/schabi/newpipe/VideoItemDetailFragment.java
index daa7719c0..ed87235c5 100644
--- a/app/src/main/java/org/schabi/newpipe/VideoItemDetailFragment.java
+++ b/app/src/main/java/org/schabi/newpipe/VideoItemDetailFragment.java
@@ -2,7 +2,7 @@ package org.schabi.newpipe;
import android.app.Activity;
import android.content.Intent;
-import android.content.res.Resources;
+import android.content.res.TypedArray;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Point;
@@ -20,11 +20,13 @@ import android.util.Log;
import android.view.LayoutInflater;
import android.view.Menu;
import android.view.MenuInflater;
+import android.view.MotionEvent;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Button;
import android.widget.FrameLayout;
import android.widget.ImageView;
+import android.widget.LinearLayout;
import android.widget.ProgressBar;
import android.widget.RelativeLayout;
import android.widget.TextView;
@@ -32,16 +34,19 @@ import android.view.MenuItem;
import android.widget.Toast;
import java.io.IOException;
-import java.net.URL;
-import java.nio.charset.MalformedInputException;
+
+import com.nostra13.universalimageloader.core.DisplayImageOptions;
+import com.nostra13.universalimageloader.core.ImageLoader;
+import com.nostra13.universalimageloader.core.assist.FailReason;
+import com.nostra13.universalimageloader.core.listener.ImageLoadingListener;
+
import java.util.ArrayList;
import java.util.Vector;
-import org.schabi.newpipe.crawler.CrawlingException;
import org.schabi.newpipe.crawler.ParsingException;
+import org.schabi.newpipe.crawler.ServiceList;
import org.schabi.newpipe.crawler.VideoPreviewInfo;
import org.schabi.newpipe.crawler.VideoExtractor;
-import org.schabi.newpipe.crawler.ServiceList;
import org.schabi.newpipe.crawler.StreamingService;
import org.schabi.newpipe.crawler.VideoInfo;
import org.schabi.newpipe.crawler.services.youtube.YoutubeVideoExtractor;
@@ -91,6 +96,12 @@ public class VideoItemDetailFragment extends Fragment {
private FloatingActionButton playVideoButton;
private final Point initialThumbnailPos = new Point(0, 0);
+
+ private ImageLoader imageLoader = ImageLoader.getInstance();
+ private DisplayImageOptions displayImageOptions =
+ new DisplayImageOptions.Builder().cacheInMemory(true).build();
+
+
public interface OnInvokeCreateOptionsMenuListener {
void createOptionsMenu();
}
@@ -113,31 +124,8 @@ public class VideoItemDetailFragment extends Fragment {
try {
videoExtractor = service.getExtractorInstance(videoUrl, new Downloader());
VideoInfo videoInfo = VideoInfo.getVideoInfo(videoExtractor, new Downloader());
+
h.post(new VideoResultReturnedRunnable(videoInfo));
- h.post(new SetThumbnailRunnable(
- //todo: make bitmaps not bypass tor
- BitmapFactory.decodeStream(
- new URL(videoInfo.thumbnail_url)
- .openConnection()
- .getInputStream()),
- SetThumbnailRunnable.VIDEO_THUMBNAIL));
- h.post(new SetThumbnailRunnable(
- BitmapFactory.decodeStream(
- new URL(videoInfo.uploader_thumbnail_url)
- .openConnection()
- .getInputStream()),
- SetThumbnailRunnable.CHANNEL_THUMBNAIL));
- if (showNextVideoItem) {
- h.post(new SetThumbnailRunnable(
- BitmapFactory.decodeStream(
- new URL(videoInfo.nextVideo.thumbnail_url)
- .openConnection()
- .getInputStream()),
- SetThumbnailRunnable.NEXT_VIDEO_THUMBNAIL));
- }
- } catch (MalformedInputException e) {
- postNewErrorToast(h, R.string.could_not_load_thumbnails);
- e.printStackTrace();
} catch (IOException e) {
postNewErrorToast(h, R.string.network_error);
e.printStackTrace();
@@ -186,52 +174,22 @@ public class VideoItemDetailFragment extends Fragment {
}
}
- private class SetThumbnailRunnable implements Runnable {
- public static final int VIDEO_THUMBNAIL = 1;
- public static final int CHANNEL_THUMBNAIL = 2;
- public static final int NEXT_VIDEO_THUMBNAIL = 3;
- private final Bitmap thumbnail;
- private final int thumbnailId;
- public SetThumbnailRunnable(Bitmap thumbnail, int id) {
- this.thumbnail = thumbnail;
- this.thumbnailId = id;
- }
+ private class ThumbnailLoadingListener implements ImageLoadingListener {
@Override
- public void run() {
- updateThumbnail(thumbnail, thumbnailId);
+ public void onLoadingStarted(String imageUri, View view) {}
+
+ @Override
+ public void onLoadingFailed(String imageUri, View view, FailReason failReason) {
+ Toast.makeText(VideoItemDetailFragment.this.getActivity(),
+ R.string.could_not_load_thumbnails, Toast.LENGTH_LONG).show();
+ failReason.getCause().printStackTrace();
}
- }
- private void updateThumbnail(Bitmap thumbnail, int id) {
- Activity a = getActivity();
- ImageView thumbnailView;
- try {
- switch (id) {
- case SetThumbnailRunnable.VIDEO_THUMBNAIL:
- thumbnailView = (ImageView) a.findViewById(R.id.detailThumbnailView);
- actionBarHandler.setSetVideoThumbnail(thumbnail);
- break;
- case SetThumbnailRunnable.CHANNEL_THUMBNAIL:
- thumbnailView = (ImageView) a.findViewById(R.id.detailUploaderThumbnailView);
- break;
- case SetThumbnailRunnable.NEXT_VIDEO_THUMBNAIL:
- FrameLayout nextVideoFrame = (FrameLayout) a.findViewById(R.id.detailNextVideoFrame);
- thumbnailView = (ImageView) nextVideoFrame.findViewById(R.id.itemThumbnailView);
- currentVideoInfo.nextVideo.thumbnail = thumbnail;
- break;
- default:
- Log.d(TAG, "Error: Thumbnail id not known");
- return;
- }
+ @Override
+ public void onLoadingComplete(String imageUri, View view, Bitmap loadedImage) {}
- if (thumbnailView != null) {
- thumbnailView.setImageBitmap(thumbnail);
- }
-
- } catch (java.lang.NullPointerException e) {
- // Not good program design, I know. :/
- Log.w(TAG, "updateThumbnail(): Fragment closed before thread ended work");
- }
+ @Override
+ public void onLoadingCancelled(String imageUri, View view) {}
}
private void updateInfo(VideoInfo info) {
@@ -241,36 +199,62 @@ public class VideoItemDetailFragment extends Fragment {
VideoInfoItemViewCreator videoItemViewCreator =
new VideoInfoItemViewCreator(LayoutInflater.from(getActivity()));
- RelativeLayout textContentLayout = (RelativeLayout) activity.findViewById(R.id.detailTextContentLayout);
- TextView videoTitleView = (TextView) activity.findViewById(R.id.detailVideoTitleView);
+ RelativeLayout textContentLayout =
+ (RelativeLayout) activity.findViewById(R.id.detailTextContentLayout);
+ final TextView videoTitleView =
+ (TextView) activity.findViewById(R.id.detailVideoTitleView);
TextView uploaderView = (TextView) activity.findViewById(R.id.detailUploaderView);
TextView viewCountView = (TextView) activity.findViewById(R.id.detailViewCountView);
TextView thumbsUpView = (TextView) activity.findViewById(R.id.detailThumbsUpCountView);
- TextView thumbsDownView = (TextView) activity.findViewById(R.id.detailThumbsDownCountView);
+ TextView thumbsDownView =
+ (TextView) activity.findViewById(R.id.detailThumbsDownCountView);
TextView uploadDateView = (TextView) activity.findViewById(R.id.detailUploadDateView);
TextView descriptionView = (TextView) activity.findViewById(R.id.detailDescriptionView);
- FrameLayout nextVideoFrame = (FrameLayout) activity.findViewById(R.id.detailNextVideoFrame);
+ FrameLayout nextVideoFrame =
+ (FrameLayout) activity.findViewById(R.id.detailNextVideoFrame);
RelativeLayout nextVideoRootFrame =
(RelativeLayout) activity.findViewById(R.id.detailNextVideoRootLayout);
-
- progressBar.setVisibility(View.GONE);
-
-
+ Button nextVideoButton = (Button) activity.findViewById(R.id.detailNextVideoButton);
+ TextView similarTitle = (TextView) activity.findViewById(R.id.detailSimilarTitle);
+ View topView = activity.findViewById(R.id.detailTopView);
View nextVideoView = videoItemViewCreator
.getViewFromVideoInfoItem(null, nextVideoFrame, info.nextVideo, getContext());
+
+ progressBar.setVisibility(View.GONE);
nextVideoFrame.addView(nextVideoView);
-
- Button nextVideoButton = (Button) activity.findViewById(R.id.detailNextVideoButton);
- Button similarVideosButton = (Button) activity.findViewById(R.id.detailShowSimilarButton);
+ initThumbnailViews(info, nextVideoFrame);
textContentLayout.setVisibility(View.VISIBLE);
playVideoButton.setVisibility(View.VISIBLE);
if (!showNextVideoItem) {
nextVideoRootFrame.setVisibility(View.GONE);
- similarVideosButton.setVisibility(View.GONE);
+ similarTitle.setVisibility(View.GONE);
}
+ videoTitleView.setText(info.title);
+
+ topView.setOnTouchListener(new View.OnTouchListener() {
+ @Override
+ public boolean onTouch(View v, MotionEvent event) {
+ if (event.getAction() == android.view.MotionEvent.ACTION_UP) {
+ ImageView arrow = (ImageView) activity.findViewById(R.id.toggleDescriptionView);
+ View extra = activity.findViewById(R.id.detailExtraView);
+ if (extra.getVisibility() == View.VISIBLE) {
+ extra.setVisibility(View.GONE);
+ arrow.setImageResource(R.drawable.arrow_down);
+ } else {
+ extra.setVisibility(View.VISIBLE);
+ arrow.setImageResource(R.drawable.arrow_up);
+ }
+ }
+ return true;
+ }
+ });
+
+ uploaderView.setText(info.uploader);
+ actionBarHandler.setChannelName(info.uploader);
+
videoTitleView.setText(info.title);
uploaderView.setText(info.uploader);
actionBarHandler.setChannelName(info.uploader);
@@ -314,12 +298,13 @@ public class VideoItemDetailFragment extends Fragment {
VideoItemDetailFragment.ARG_ITEM_ID, currentVideoInfo.nextVideo.id); */
detailIntent.putExtra(
VideoItemDetailFragment.VIDEO_URL, currentVideoInfo.nextVideo.webpage_url);
-
detailIntent.putExtra(VideoItemDetailFragment.STREAMING_SERVICE, streamingServiceId);
startActivity(detailIntent);
}
});
+ textContentLayout.setVisibility(View.VISIBLE);
+ initSimilarVideos(videoItemViewCreator);
if(autoPlayEnabled) {
actionBarHandler.playVideo();
@@ -330,6 +315,76 @@ public class VideoItemDetailFragment extends Fragment {
}
}
+ private void initThumbnailViews(VideoInfo info, View nextVideoFrame) {
+ ImageView videoThumbnailView = (ImageView) activity.findViewById(R.id.detailThumbnailView);
+ ImageView uploaderThumb
+ = (ImageView) activity.findViewById(R.id.detailUploaderThumbnailView);
+ ImageView nextVideoThumb =
+ (ImageView) nextVideoFrame.findViewById(R.id.itemThumbnailView);
+
+ imageLoader.displayImage(info.thumbnail_url, videoThumbnailView,
+ displayImageOptions, new ImageLoadingListener() {
+ @Override
+ public void onLoadingStarted(String imageUri, View view) {}
+
+ @Override
+ public void onLoadingFailed(String imageUri, View view, FailReason failReason) {
+ Toast.makeText(VideoItemDetailFragment.this.getActivity(),
+ R.string.could_not_load_thumbnails, Toast.LENGTH_LONG).show();
+ failReason.getCause().printStackTrace();
+ }
+
+ @Override
+ public void onLoadingComplete(String imageUri, View view, Bitmap loadedImage) {
+ actionBarHandler.setVideoThumbnail(loadedImage);
+ }
+
+ @Override
+ public void onLoadingCancelled(String imageUri, View view) {}
+ });
+ imageLoader.displayImage(info.uploader_thumbnail_url,
+ uploaderThumb, displayImageOptions, new ThumbnailLoadingListener());
+ imageLoader.displayImage(info.nextVideo.thumbnail_url,
+ nextVideoThumb, displayImageOptions, new ThumbnailLoadingListener());
+ }
+
+ private void initSimilarVideos(VideoInfoItemViewCreator videoItemViewCreator) {
+ LinearLayout similarLayout = (LinearLayout) activity.findViewById(R.id.similarVideosView);
+ ArrayList similar = new ArrayList<>(currentVideoInfo.relatedVideos);
+ for (final VideoPreviewInfo item : similar) {
+ View similarView = videoItemViewCreator
+ .getViewFromVideoInfoItem(null, similarLayout, item, getContext());
+
+ similarView.setClickable(true);
+ similarView.setFocusable(true);
+ int[] attrs = new int[]{R.attr.selectableItemBackground};
+ TypedArray typedArray = activity.obtainStyledAttributes(attrs);
+ int backgroundResource = typedArray.getResourceId(0, 0);
+ similarView.setBackgroundResource(backgroundResource);
+ typedArray.recycle();
+
+ similarView.setOnTouchListener(new View.OnTouchListener() {
+ @Override
+ public boolean onTouch(View v, MotionEvent event) {
+ if (event.getAction() == MotionEvent.ACTION_UP) {
+ Intent detailIntent = new Intent(activity, VideoItemDetailActivity.class);
+ detailIntent.putExtra(VideoItemDetailFragment.VIDEO_URL, item.webpage_url);
+ detailIntent.putExtra(
+ VideoItemDetailFragment.STREAMING_SERVICE, streamingServiceId);
+ startActivity(detailIntent);
+ return true;
+ }
+ return false;
+ }
+ });
+
+ similarLayout.addView(similarView);
+ ImageView rthumb = (ImageView)similarView.findViewById(R.id.itemThumbnailView);
+ imageLoader.displayImage(item.thumbnail_url, rthumb,
+ displayImageOptions, new ThumbnailLoadingListener());
+ }
+ }
+
private void onErrorBlockedByGema() {
Button backgroundButton = (Button)
activity.findViewById(R.id.detailVideoThumbnailWindowBackgroundButton);
@@ -438,21 +493,6 @@ public class VideoItemDetailFragment extends Fragment {
}
});
- 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);
- //todo: find more elegant way to do this - converting from List to ArrayList sucks
- ArrayList toParcel = new ArrayList<>(currentVideoInfo.relatedVideos);
- //why oh why does the parcelable array put method have to be so damn specific
- // about the class of its argument?
- //why not a List extends Parcelable>?
- intent.putParcelableArrayListExtra(VideoItemListActivity.VIDEO_INFO_ITEMS, toParcel);
- activity.startActivity(intent);
- }
- });
-
// todo: Fix this workaround (probably with a better design), so that older android
// versions don't have problems rendering the thumbnail right.
if(Build.VERSION.SDK_INT >= 18) {
@@ -461,7 +501,8 @@ public class VideoItemDetailFragment extends Fragment {
// This is used to synchronize the thumbnailWindowButton and the playVideoButton
// inside the ScrollView with the actual size of the thumbnail.
@Override
- public void onLayoutChange(View v, int left, int top, int right, int bottom, int oldLeft, int oldTop, int oldRight, int oldBottom) {
+ public void onLayoutChange(View v, int left, int top, int right, int bottom,
+ int oldLeft, int oldTop, int oldRight, int oldBottom) {
RelativeLayout.LayoutParams newWindowLayoutParams =
(RelativeLayout.LayoutParams) thumbnailWindowLayout.getLayoutParams();
newWindowLayoutParams.height = bottom - top;
diff --git a/app/src/main/java/org/schabi/newpipe/VideoItemListFragment.java b/app/src/main/java/org/schabi/newpipe/VideoItemListFragment.java
index 479a4820d..cf8a5a08c 100644
--- a/app/src/main/java/org/schabi/newpipe/VideoItemListFragment.java
+++ b/app/src/main/java/org/schabi/newpipe/VideoItemListFragment.java
@@ -61,8 +61,6 @@ public class VideoItemListFragment extends ListFragment {
private Thread searchThread = null;
private SearchRunnable searchRunnable = null;
- private Thread loadThumbsThread = null;
- private LoadThumbsRunnable loadThumbsRunnable = null;
// used to track down if results posted by threads ar still valid
private int currentRequestId = -1;
private ListView list;
@@ -130,7 +128,8 @@ public class VideoItemListFragment extends ListFragment {
}
}
}
-
+/*
+<<<
private class LoadThumbsRunnable implements Runnable {
private final Vector thumbnailUrlList = new Vector<>();
private final Vector downloadedList;
@@ -187,6 +186,9 @@ public class VideoItemListFragment extends ListFragment {
}
}
+=======
+>>>>>>> 6d1b4652fc98e5c2d5e19b0f98ba38a731137a70
+*/
public void present(List videoList) {
mode = PRESENT_VIDEOS_MODE;
setListShown(true);
@@ -246,10 +248,6 @@ public class VideoItemListFragment extends ListFragment {
try {
videoListAdapter.addVideoList(list);
terminateThreads();
- loadThumbsRunnable = new LoadThumbsRunnable(videoListAdapter.getVideoList(),
- videoListAdapter.getDownloadedThumbnailList(), currentRequestId);
- loadThumbsThread = new Thread(loadThumbsRunnable);
- loadThumbsThread.start();
} catch(java.lang.IllegalStateException e) {
Log.w(TAG, "Trying to set value while activity doesn't exist anymore.");
} catch(Exception e) {
@@ -260,14 +258,6 @@ public class VideoItemListFragment extends ListFragment {
}
private void terminateThreads() {
- if(loadThumbsRunnable != null && loadThumbsRunnable.isRunning()) {
- loadThumbsRunnable.terminate();
- try {
- loadThumbsThread.join();
- } catch(Exception e) {
- e.printStackTrace();
- }
- }
if(searchThread != null) {
searchRunnable.terminate();
// No need to join, since we don't really terminate the thread. We just demand
diff --git a/app/src/main/java/org/schabi/newpipe/VideoListAdapter.java b/app/src/main/java/org/schabi/newpipe/VideoListAdapter.java
index 54ff763f0..7077810ad 100644
--- a/app/src/main/java/org/schabi/newpipe/VideoListAdapter.java
+++ b/app/src/main/java/org/schabi/newpipe/VideoListAdapter.java
@@ -1,7 +1,6 @@
package org.schabi.newpipe;
import android.content.Context;
-import android.graphics.Bitmap;
import android.support.v4.content.ContextCompat;
import android.view.LayoutInflater;
import android.view.View;
@@ -38,7 +37,6 @@ class VideoListAdapter extends BaseAdapter {
private final Context context;
private final VideoInfoItemViewCreator viewCreator;
private Vector videoList = new Vector<>();
- private Vector downloadedThumbnailList = new Vector<>();
private final ListView listView;
public VideoListAdapter(Context context, VideoItemListFragment videoListFragment) {
@@ -51,15 +49,11 @@ class VideoListAdapter extends BaseAdapter {
public void addVideoList(List videos) {
videoList.addAll(videos);
- for(int i = 0; i < videos.size(); i++) {
- downloadedThumbnailList.add(false);
- }
notifyDataSetChanged();
}
public void clearVideoList() {
videoList = new Vector<>();
- downloadedThumbnailList = new Vector<>();
notifyDataSetChanged();
}
@@ -67,20 +61,6 @@ class VideoListAdapter extends BaseAdapter {
return videoList;
}
- public void updateDownloadedThumbnailList(int index) {
- downloadedThumbnailList.set(index, true);
- }
-
- public Vector getDownloadedThumbnailList() {
- return downloadedThumbnailList;
- }
-
- public void setThumbnail(int index, Bitmap thumbnail) {
- videoList.get(index).thumbnail = thumbnail;
- downloadedThumbnailList.set(index, true);
- notifyDataSetChanged();
- }
-
@Override
public int getCount() {
return videoList.size();
diff --git a/app/src/main/java/org/schabi/newpipe/crawler/services/youtube/YoutubeSearchEngine.java b/app/src/main/java/org/schabi/newpipe/crawler/services/youtube/YoutubeSearchEngine.java
index a6d4857c1..dca9caa26 100644
--- a/app/src/main/java/org/schabi/newpipe/crawler/services/youtube/YoutubeSearchEngine.java
+++ b/app/src/main/java/org/schabi/newpipe/crawler/services/youtube/YoutubeSearchEngine.java
@@ -122,6 +122,15 @@ public class YoutubeSearchEngine implements SearchEngine {
resultItem.upload_date = item.select("div[class=\"yt-lockup-meta\"]").first()
.select("li").first()
.text();
+
+ //todo: test against view_count
+ String viewCountInfo = item.select("div[class=\"yt-lockup-meta\"]").first()
+ .select("li").get(1)
+ .text();
+ viewCountInfo = viewCountInfo.substring(0, viewCountInfo.indexOf(' '));
+ viewCountInfo = viewCountInfo.replaceAll("[,.]", "");
+ resultItem.view_count = Long.parseLong(viewCountInfo);
+
Element te = item.select("div[class=\"yt-thumb video-thumb\"]").first()
.select("img").first();
resultItem.thumbnail_url = te.attr("abs:src");
diff --git a/app/src/main/res/drawable-nodpi/arrow_down.png b/app/src/main/res/drawable-nodpi/arrow_down.png
new file mode 100644
index 000000000..f968ab32b
Binary files /dev/null and b/app/src/main/res/drawable-nodpi/arrow_down.png differ
diff --git a/app/src/main/res/drawable-nodpi/arrow_up.png b/app/src/main/res/drawable-nodpi/arrow_up.png
new file mode 100644
index 000000000..e5081691a
Binary files /dev/null and b/app/src/main/res/drawable-nodpi/arrow_up.png differ
diff --git a/app/src/main/res/layout-v18/fragment_videoitem_detail.xml b/app/src/main/res/layout-v18/fragment_videoitem_detail.xml
deleted file mode 100644
index cbb5652ca..000000000
--- a/app/src/main/res/layout-v18/fragment_videoitem_detail.xml
+++ /dev/null
@@ -1,219 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/app/src/main/res/layout-v21/fragment_videoitem_detail.xml b/app/src/main/res/layout-v21/fragment_videoitem_detail.xml
deleted file mode 100644
index b7919dbe8..000000000
--- a/app/src/main/res/layout-v21/fragment_videoitem_detail.xml
+++ /dev/null
@@ -1,221 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/app/src/main/res/layout/fragment_videoitem_detail.xml b/app/src/main/res/layout/fragment_videoitem_detail.xml
index 611a5aa14..1695bf441 100644
--- a/app/src/main/res/layout/fragment_videoitem_detail.xml
+++ b/app/src/main/res/layout/fragment_videoitem_detail.xml
@@ -10,11 +10,12 @@
android:layout_height="match_parent"
android:id="@+id/videoitem_detail">
-
+ android:background="@color/light_background_color"
+ android:visibility="gone">
-
+ android:id="@+id/detailTopView">
-
+
-
+
+
+
+ android:textAppearance="?android:attr/textAppearanceLarge"
+ android:layout_marginLeft="12dp"
+ android:layout_marginStart="12dp"
+ android:text="10,069,948 views"
+ android:layout_below="@id/detailTopView"
+ android:layout_alignParentLeft="true"
+ android:layout_alignParentStart="true"
+ android:layout_marginTop="5dp" />
-
+
+
+
+
+
+
+ android:layout_marginTop="5dp">
+
-
+
-
+
+
+
+
+
+ android:layout_below="@+id/linearLayout"
+ android:id="@+id/detailUploaderWrapView"
+ android:layout_marginTop="12dp">
-
+
-
+
-
+
+
+
+ android:layout_height="match_parent"
+ android:layout_gravity="center_horizontal|bottom"
+ android:layout_below="@+id/detailUploaderWrapView"
+ android:layout_centerHorizontal="true"
+ android:layout_marginTop="10dp">
-
+ android:textAllCaps="true" />
+
+
-
-
+
\ No newline at end of file
diff --git a/app/src/main/res/layout/paginate_footer.xml b/app/src/main/res/layout/paginate_footer.xml
index b3757c1af..8459a3887 100644
--- a/app/src/main/res/layout/paginate_footer.xml
+++ b/app/src/main/res/layout/paginate_footer.xml
@@ -5,16 +5,11 @@
android:gravity="center_horizontal"
android:orientation="vertical">
-
-
+ android:gravity="center"
+ android:paddingBottom="10dp"/>
\ No newline at end of file
diff --git a/app/src/main/res/layout/player_notification.xml b/app/src/main/res/layout/player_notification.xml
index 463ce18a3..4d874a3bd 100644
--- a/app/src/main/res/layout/player_notification.xml
+++ b/app/src/main/res/layout/player_notification.xml
@@ -51,7 +51,7 @@
android:background="#00ffffff"
android:clickable="true"
android:scaleType="fitXY"
- android:src="@drawable/ic_play_arrow_white_48dp" />
+ android:src="@drawable/ic_pause_white_24dp" />
-
-
+ android:scaleType="fitXY"
+ android:src="@drawable/ic_pause_white_24dp"
+ android:layout_alignParentTop="true"
+ android:layout_centerHorizontal="true" />
+
\ No newline at end of file
diff --git a/app/src/main/res/layout/video_item.xml b/app/src/main/res/layout/video_item.xml
index cff3a4224..8ab554543 100644
--- a/app/src/main/res/layout/video_item.xml
+++ b/app/src/main/res/layout/video_item.xml
@@ -1,29 +1,15 @@
-
-
+ android:layout_margin="12dp">
-
-
+ android:layout_height="wrap_content">
+
+
+
+
+
+
+
-
\ No newline at end of file
diff --git a/app/src/main/res/values/dimens.xml b/app/src/main/res/values/dimens.xml
index 97df6e82b..0eb887da1 100644
--- a/app/src/main/res/values/dimens.xml
+++ b/app/src/main/res/values/dimens.xml
@@ -11,21 +11,17 @@
140dp
85dp
- 3dp
- 6dp
- 6dp
6dp
1sp
5sp
2sp
- 4dp
- 18sp
+ 20sp
14sp
- 12sp
+ 14sp
14sp
14sp
14sp
@@ -33,11 +29,10 @@
16sp
200dp
- 80dp
+ 50dp
18sp
18sp
- 6sp
6sp
20dp
diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml
index 91afd974c..0e95a3231 100644
--- a/app/src/main/res/values/strings.xml
+++ b/app/src/main/res/values/strings.xml
@@ -67,7 +67,7 @@
Play
Error
Network error
- Could not load Thumbnails
+ Could not load all Thumbnails
Could not decrypt video url signature.
Could not parse website.
Content not available.
diff --git a/screenshots/screenshot_1.png b/screenshots/screenshot_1.png
index 32edfa9ee..b8d6554b8 100644
Binary files a/screenshots/screenshot_1.png and b/screenshots/screenshot_1.png differ
diff --git a/screenshots/screenshot_2.png b/screenshots/screenshot_2.png
index bce324736..2068224f6 100644
Binary files a/screenshots/screenshot_2.png and b/screenshots/screenshot_2.png differ
diff --git a/screenshots/screenshot_3.png b/screenshots/screenshot_3.png
index 8277daa6d..09cf2b8d4 100644
Binary files a/screenshots/screenshot_3.png and b/screenshots/screenshot_3.png differ
diff --git a/screenshots/screenshot_4.png b/screenshots/screenshot_4.png
index 94f676dff..bfc14cce1 100644
Binary files a/screenshots/screenshot_4.png and b/screenshots/screenshot_4.png differ
diff --git a/screenshots/screenshot_5.png b/screenshots/screenshot_5.png
index 5b33a4f46..d4a0a3599 100644
Binary files a/screenshots/screenshot_5.png and b/screenshots/screenshot_5.png differ
diff --git a/screenshots/screenshot_6.png b/screenshots/screenshot_6.png
deleted file mode 100644
index fd796c0cf..000000000
Binary files a/screenshots/screenshot_6.png and /dev/null differ