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? - 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 @@ - - - - - - - - - - - - - - - - -