Merge remote-tracking branch 'origin/master'
This commit is contained in:
commit
11541310d6
|
@ -5,7 +5,7 @@ READ THIS GUIDELINES CAREFULLY BEFORE CONTRIBUTING.
|
|||
|
||||
## Crash reporting
|
||||
|
||||
Do not report crashes in the GitHub issue tracker. NewPipe has an automated crash report system that will ask you to send a report if a crash occures.
|
||||
Do not report crashes in the GitHub issue tracker. NewPipe has an automated crash report system that will ask you to send a report if a crash occurs.
|
||||
|
||||
## Issue reporting/feature request
|
||||
|
||||
|
|
|
@ -10,6 +10,8 @@ android {
|
|||
targetSdkVersion 25
|
||||
versionCode 35
|
||||
versionName "0.9.8"
|
||||
|
||||
testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
|
||||
}
|
||||
buildTypes {
|
||||
release {
|
||||
|
@ -31,6 +33,11 @@ android {
|
|||
}
|
||||
|
||||
dependencies {
|
||||
androidTestCompile('com.android.support.test.espresso:espresso-core:2.2.2') {
|
||||
exclude module: 'support-annotations'
|
||||
}
|
||||
|
||||
|
||||
testCompile 'junit:junit:4.12'
|
||||
testCompile 'org.mockito:mockito-core:1.10.19'
|
||||
testCompile 'org.json:json:20160810'
|
||||
|
|
|
@ -0,0 +1,37 @@
|
|||
package org.schabi.newpipe.report;
|
||||
|
||||
import android.os.Parcel;
|
||||
import android.support.test.filters.LargeTest;
|
||||
import android.support.test.runner.AndroidJUnit4;
|
||||
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.schabi.newpipe.R;
|
||||
import org.schabi.newpipe.report.ErrorActivity.ErrorInfo;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
|
||||
/**
|
||||
* Instrumented tests for {@link ErrorInfo}
|
||||
*/
|
||||
@RunWith(AndroidJUnit4.class)
|
||||
@LargeTest
|
||||
public class ErrorInfoTest {
|
||||
|
||||
@Test
|
||||
public void errorInfo_testParcelable() {
|
||||
ErrorInfo info = ErrorInfo.make(UserAction.USER_REPORT, "youtube", "request", R.string.general_error);
|
||||
// Obtain a Parcel object and write the parcelable object to it:
|
||||
Parcel parcel = Parcel.obtain();
|
||||
info.writeToParcel(parcel, 0);
|
||||
parcel.setDataPosition(0);
|
||||
ErrorInfo infoFromParcel = ErrorInfo.CREATOR.createFromParcel(parcel);
|
||||
|
||||
assertEquals(UserAction.USER_REPORT, infoFromParcel.userAction);
|
||||
assertEquals("youtube", infoFromParcel.serviceName);
|
||||
assertEquals("request", infoFromParcel.request);
|
||||
assertEquals(R.string.general_error, infoFromParcel.message);
|
||||
|
||||
parcel.recycle();
|
||||
}
|
||||
}
|
|
@ -14,6 +14,7 @@ import org.acra.sender.ReportSenderFactory;
|
|||
import org.schabi.newpipe.extractor.NewPipe;
|
||||
import org.schabi.newpipe.report.AcraReportSenderFactory;
|
||||
import org.schabi.newpipe.report.ErrorActivity;
|
||||
import org.schabi.newpipe.report.UserAction;
|
||||
import org.schabi.newpipe.settings.SettingsActivity;
|
||||
import org.schabi.newpipe.util.ThemeHelper;
|
||||
|
||||
|
@ -59,7 +60,7 @@ public class App extends Application {
|
|||
} catch(ACRAConfigurationException ace) {
|
||||
ace.printStackTrace();
|
||||
ErrorActivity.reportError(this, ace, null, null,
|
||||
ErrorActivity.ErrorInfo.make(ErrorActivity.SEARCHED,"none",
|
||||
ErrorActivity.ErrorInfo.make(UserAction.SEARCHED,"none",
|
||||
"Could not initialize ACRA crash report", R.string.app_ui_crash));
|
||||
}
|
||||
|
||||
|
|
|
@ -9,6 +9,7 @@ import com.nostra13.universalimageloader.core.listener.ImageLoadingListener;
|
|||
|
||||
import org.schabi.newpipe.extractor.NewPipe;
|
||||
import org.schabi.newpipe.report.ErrorActivity;
|
||||
import org.schabi.newpipe.report.UserAction;
|
||||
|
||||
/**
|
||||
* Created by Christian Schabesberger on 01.08.16.
|
||||
|
@ -49,7 +50,7 @@ public class ImageErrorLoadingListener implements ImageLoadingListener {
|
|||
public void onLoadingFailed(String imageUri, View view, FailReason failReason) {
|
||||
ErrorActivity.reportError(context,
|
||||
failReason.getCause(), null, rootView,
|
||||
ErrorActivity.ErrorInfo.make(ErrorActivity.LOAD_IMAGE,
|
||||
ErrorActivity.ErrorInfo.make(UserAction.LOAD_IMAGE,
|
||||
NewPipe.getNameOfService(serviceId), imageUri,
|
||||
R.string.could_not_load_image));
|
||||
}
|
||||
|
|
|
@ -35,7 +35,6 @@ import us.shandian.giga.service.DownloadManagerService;
|
|||
import us.shandian.giga.ui.fragment.AllMissionsFragment;
|
||||
import us.shandian.giga.ui.fragment.MissionsFragment;
|
||||
import us.shandian.giga.util.CrashHandler;
|
||||
import us.shandian.giga.util.Utility;
|
||||
|
||||
public class DownloadActivity extends AppCompatActivity implements AdapterView.OnItemClickListener {
|
||||
|
||||
|
@ -125,11 +124,11 @@ public class DownloadActivity extends AppCompatActivity implements AdapterView.O
|
|||
// Create the view
|
||||
LayoutInflater inflater = (LayoutInflater) getSystemService(Context.LAYOUT_INFLATER_SERVICE);
|
||||
View v = inflater.inflate(R.layout.dialog_url, null);
|
||||
final EditText name = Utility.findViewById(v, R.id.file_name);
|
||||
final TextView tCount = Utility.findViewById(v, R.id.threads_count);
|
||||
final SeekBar threads = Utility.findViewById(v, R.id.threads);
|
||||
final Toolbar toolbar = Utility.findViewById(v, R.id.toolbar);
|
||||
final RadioButton audioButton = (RadioButton) Utility.findViewById(v, R.id.audio_button);
|
||||
final EditText name = (EditText) v.findViewById(R.id.file_name);
|
||||
final TextView tCount = (TextView) v.findViewById(R.id.threads_count);
|
||||
final SeekBar threads = (SeekBar) v.findViewById(R.id.threads);
|
||||
final Toolbar toolbar = (Toolbar) v.findViewById(R.id.toolbar);
|
||||
final RadioButton audioButton = (RadioButton) v.findViewById(R.id.audio_button);
|
||||
|
||||
|
||||
threads.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() {
|
||||
|
|
|
@ -253,7 +253,7 @@ public class DownloadDialog extends DialogFragment implements RadioGroup.OnCheck
|
|||
}
|
||||
|
||||
/**
|
||||
* #143 #44 #42 #22: make shure that the filename does not contain illegal chars.
|
||||
* #143 #44 #42 #22: make sure that the filename does not contain illegal chars.
|
||||
* This should fix some of the "cannot download" problems.
|
||||
*/
|
||||
private String createFileName(String fileName) {
|
||||
|
|
|
@ -26,6 +26,7 @@ import org.schabi.newpipe.R;
|
|||
import org.schabi.newpipe.extractor.InfoItem;
|
||||
import org.schabi.newpipe.extractor.channel.ChannelInfo;
|
||||
import org.schabi.newpipe.fragments.BaseFragment;
|
||||
import org.schabi.newpipe.fragments.search.OnScrollBelowItemsListener;
|
||||
import org.schabi.newpipe.info_list.InfoItemBuilder;
|
||||
import org.schabi.newpipe.info_list.InfoListAdapter;
|
||||
import org.schabi.newpipe.util.Constants;
|
||||
|
@ -213,7 +214,7 @@ public class ChannelFragment extends BaseFragment implements ChannelExtractorWor
|
|||
|
||||
channelVideosList.setLayoutManager(new LinearLayoutManager(activity));
|
||||
if (infoListAdapter == null) {
|
||||
infoListAdapter = new InfoListAdapter(activity, rootView);
|
||||
infoListAdapter = new InfoListAdapter(activity);
|
||||
if (savedInstanceState != null) {
|
||||
//noinspection unchecked
|
||||
ArrayList<InfoItem> serializable = (ArrayList<InfoItem>) savedInstanceState.getSerializable(INFO_LIST_KEY);
|
||||
|
@ -245,25 +246,14 @@ public class ChannelFragment extends BaseFragment implements ChannelExtractorWor
|
|||
});
|
||||
|
||||
channelVideosList.clearOnScrollListeners();
|
||||
channelVideosList.addOnScrollListener(new RecyclerView.OnScrollListener() {
|
||||
channelVideosList.addOnScrollListener(new OnScrollBelowItemsListener() {
|
||||
@Override
|
||||
public void onScrolled(RecyclerView recyclerView, int dx, int dy) {
|
||||
int pastVisiblesItems, visibleItemCount, totalItemCount;
|
||||
super.onScrolled(recyclerView, dx, dy);
|
||||
//check for scroll down
|
||||
if (dy > 0) {
|
||||
LinearLayoutManager layoutManager = (LinearLayoutManager) channelVideosList.getLayoutManager();
|
||||
|
||||
visibleItemCount = layoutManager.getChildCount();
|
||||
totalItemCount = layoutManager.getItemCount();
|
||||
pastVisiblesItems = layoutManager.findFirstVisibleItemPosition();
|
||||
|
||||
if ((visibleItemCount + pastVisiblesItems) >= totalItemCount && (currentChannelWorker == null || !currentChannelWorker.isRunning()) && hasNextPage && !isLoading.get()) {
|
||||
public void onScrolledDown(RecyclerView recyclerView) {
|
||||
if ((currentChannelWorker == null || !currentChannelWorker.isRunning()) && hasNextPage && !isLoading.get()) {
|
||||
pageNumber++;
|
||||
loadMoreVideos();
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
headerRssButton.setOnClickListener(new View.OnClickListener() {
|
||||
|
|
|
@ -67,12 +67,12 @@ class ActionBarHandler {
|
|||
|
||||
public void setupStreamList(final List<VideoStream> videoStreams, Spinner toolbarSpinner) {
|
||||
if (activity == null) return;
|
||||
selectedVideoStream = 0;
|
||||
|
||||
int defaultResolutionIndex = Utils.getDefaultResolution(activity, videoStreams);
|
||||
selectedVideoStream = Utils.getDefaultResolution(activity, videoStreams);
|
||||
|
||||
boolean isExternalPlayerEnabled = PreferenceManager.getDefaultSharedPreferences(activity).getBoolean(activity.getString(R.string.use_external_video_player_key), false);
|
||||
toolbarSpinner.setAdapter(new SpinnerToolbarAdapter(activity, videoStreams, isExternalPlayerEnabled));
|
||||
toolbarSpinner.setSelection(defaultResolutionIndex);
|
||||
toolbarSpinner.setSelection(selectedVideoStream);
|
||||
toolbarSpinner.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
|
||||
@Override
|
||||
public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
|
||||
|
|
|
@ -1,12 +1,17 @@
|
|||
package org.schabi.newpipe.fragments.detail;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.content.Context;
|
||||
import android.content.DialogInterface;
|
||||
import android.content.Intent;
|
||||
import android.content.SharedPreferences;
|
||||
import android.net.Uri;
|
||||
import android.os.Build;
|
||||
import android.os.Bundle;
|
||||
import android.os.Handler;
|
||||
import android.os.HandlerThread;
|
||||
import android.os.Looper;
|
||||
import android.os.Message;
|
||||
import android.preference.PreferenceManager;
|
||||
import android.support.annotation.FloatRange;
|
||||
import android.support.annotation.NonNull;
|
||||
|
@ -15,6 +20,7 @@ import android.support.v4.view.animation.FastOutSlowInInterpolator;
|
|||
import android.support.v7.app.ActionBar;
|
||||
import android.support.v7.app.AlertDialog;
|
||||
import android.text.Html;
|
||||
import android.text.Spanned;
|
||||
import android.text.TextUtils;
|
||||
import android.text.method.LinkMovementMethod;
|
||||
import android.util.Log;
|
||||
|
@ -26,7 +32,7 @@ import android.view.MenuInflater;
|
|||
import android.view.MenuItem;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.widget.Button;
|
||||
import android.widget.FrameLayout;
|
||||
import android.widget.ImageButton;
|
||||
import android.widget.ImageView;
|
||||
import android.widget.LinearLayout;
|
||||
|
@ -55,6 +61,7 @@ import org.schabi.newpipe.player.MainVideoPlayer;
|
|||
import org.schabi.newpipe.player.PlayVideoActivity;
|
||||
import org.schabi.newpipe.player.PopupVideoPlayer;
|
||||
import org.schabi.newpipe.report.ErrorActivity;
|
||||
import org.schabi.newpipe.report.UserAction;
|
||||
import org.schabi.newpipe.util.Constants;
|
||||
import org.schabi.newpipe.util.Localization;
|
||||
import org.schabi.newpipe.util.NavigationHelper;
|
||||
|
@ -105,6 +112,10 @@ public class VideoDetailFragment extends BaseFragment implements StreamExtractor
|
|||
private boolean showRelatedStreams;
|
||||
private boolean wasRelatedStreamsExpanded = false;
|
||||
|
||||
private Handler uiHandler;
|
||||
private Handler backgroundHandler;
|
||||
private HandlerThread backgroundHandlerThread;
|
||||
|
||||
/*//////////////////////////////////////////////////////////////////////////
|
||||
// Views
|
||||
//////////////////////////////////////////////////////////////////////////*/
|
||||
|
@ -112,9 +123,9 @@ public class VideoDetailFragment extends BaseFragment implements StreamExtractor
|
|||
private Spinner spinnerToolbar;
|
||||
|
||||
private ParallaxScrollView parallaxScrollRootView;
|
||||
private RelativeLayout contentRootLayoutHiding;
|
||||
private LinearLayout contentRootLayoutHiding;
|
||||
|
||||
private Button thumbnailBackgroundButton;
|
||||
private View thumbnailBackgroundButton;
|
||||
private ImageView thumbnailImageView;
|
||||
private ImageView thumbnailPlayButton;
|
||||
|
||||
|
@ -126,12 +137,11 @@ public class VideoDetailFragment extends BaseFragment implements StreamExtractor
|
|||
private TextView detailControlsBackground;
|
||||
private TextView detailControlsPopup;
|
||||
|
||||
private RelativeLayout videoDescriptionRootLayout;
|
||||
private LinearLayout videoDescriptionRootLayout;
|
||||
private TextView videoUploadDateView;
|
||||
private TextView videoDescriptionView;
|
||||
|
||||
private View uploaderRootLayout;
|
||||
private Button uploaderButton;
|
||||
private TextView uploaderTextView;
|
||||
private ImageView uploaderThumb;
|
||||
|
||||
|
@ -142,7 +152,7 @@ public class VideoDetailFragment extends BaseFragment implements StreamExtractor
|
|||
private TextView thumbsDisabledTextView;
|
||||
|
||||
private TextView nextStreamTitle;
|
||||
private RelativeLayout relatedStreamRootLayout;
|
||||
private LinearLayout relatedStreamRootLayout;
|
||||
private LinearLayout relatedStreamsView;
|
||||
private ImageButton relatedStreamExpandButton;
|
||||
|
||||
|
@ -194,6 +204,16 @@ public class VideoDetailFragment extends BaseFragment implements StreamExtractor
|
|||
thousand = getString(R.string.short_thousand);
|
||||
million = getString(R.string.short_million);
|
||||
billion = getString(R.string.short_billion);
|
||||
|
||||
if (uiHandler == null) {
|
||||
uiHandler = new Handler(Looper.getMainLooper(), new UICallback());
|
||||
}
|
||||
if (backgroundHandler == null) {
|
||||
HandlerThread handlerThread = new HandlerThread("VideoDetailFragment-BG");
|
||||
handlerThread.start();
|
||||
backgroundHandlerThread = handlerThread;
|
||||
backgroundHandler = new Handler(handlerThread.getLooper(), new BackgroundCallback(uiHandler, getContext()));
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -241,6 +261,11 @@ public class VideoDetailFragment extends BaseFragment implements StreamExtractor
|
|||
@Override
|
||||
public void onDestroy() {
|
||||
super.onDestroy();
|
||||
if (backgroundHandlerThread != null) {
|
||||
backgroundHandlerThread.quit();
|
||||
}
|
||||
backgroundHandlerThread = null;
|
||||
backgroundHandler = null;
|
||||
PreferenceManager.getDefaultSharedPreferences(activity).unregisterOnSharedPreferenceChangeListener(this);
|
||||
}
|
||||
|
||||
|
@ -272,7 +297,7 @@ public class VideoDetailFragment extends BaseFragment implements StreamExtractor
|
|||
videoUploadDateView = null;
|
||||
videoDescriptionView = null;
|
||||
|
||||
uploaderButton = null;
|
||||
uploaderRootLayout = null;
|
||||
uploaderTextView = null;
|
||||
uploaderThumb = null;
|
||||
|
||||
|
@ -353,10 +378,14 @@ public class VideoDetailFragment extends BaseFragment implements StreamExtractor
|
|||
case R.id.detail_controls_popup:
|
||||
openInPopup();
|
||||
break;
|
||||
case R.id.detail_uploader_button:
|
||||
case R.id.detail_uploader_root_layout:
|
||||
if (currentStreamInfo.channel_url == null || currentStreamInfo.channel_url.isEmpty()) {
|
||||
Log.w(TAG, "Can't open channel because we got no channel URL");
|
||||
} else {
|
||||
NavigationHelper.openChannelFragment(getFragmentManager(), currentStreamInfo.service_id, currentStreamInfo.channel_url, currentStreamInfo.uploader);
|
||||
}
|
||||
break;
|
||||
case R.id.detail_thumbnail_background_button:
|
||||
case R.id.detail_thumbnail_root_layout:
|
||||
playVideo(currentStreamInfo);
|
||||
break;
|
||||
case R.id.detail_title_root_layout:
|
||||
|
@ -484,12 +513,11 @@ public class VideoDetailFragment extends BaseFragment implements StreamExtractor
|
|||
|
||||
parallaxScrollRootView = (ParallaxScrollView) rootView.findViewById(R.id.detail_main_content);
|
||||
|
||||
//thumbnailRootLayout = (RelativeLayout) rootView.findViewById(R.id.detail_thumbnail_root_layout);
|
||||
thumbnailBackgroundButton = (Button) rootView.findViewById(R.id.detail_thumbnail_background_button);
|
||||
thumbnailBackgroundButton = rootView.findViewById(R.id.detail_thumbnail_root_layout);
|
||||
thumbnailImageView = (ImageView) rootView.findViewById(R.id.detail_thumbnail_image_view);
|
||||
thumbnailPlayButton = (ImageView) rootView.findViewById(R.id.detail_thumbnail_play_button);
|
||||
|
||||
contentRootLayoutHiding = (RelativeLayout) rootView.findViewById(R.id.detail_content_root_hiding);
|
||||
contentRootLayoutHiding = (LinearLayout) rootView.findViewById(R.id.detail_content_root_hiding);
|
||||
|
||||
videoTitleRoot = rootView.findViewById(R.id.detail_title_root_layout);
|
||||
videoTitleTextView = (TextView) rootView.findViewById(R.id.detail_video_title_view);
|
||||
|
@ -499,7 +527,7 @@ public class VideoDetailFragment extends BaseFragment implements StreamExtractor
|
|||
detailControlsBackground = (TextView) rootView.findViewById(R.id.detail_controls_background);
|
||||
detailControlsPopup = (TextView) rootView.findViewById(R.id.detail_controls_popup);
|
||||
|
||||
videoDescriptionRootLayout = (RelativeLayout) rootView.findViewById(R.id.detail_description_root_layout);
|
||||
videoDescriptionRootLayout = (LinearLayout) rootView.findViewById(R.id.detail_description_root_layout);
|
||||
videoUploadDateView = (TextView) rootView.findViewById(R.id.detail_upload_date_view);
|
||||
videoDescriptionView = (TextView) rootView.findViewById(R.id.detail_description_view);
|
||||
|
||||
|
@ -511,19 +539,19 @@ public class VideoDetailFragment extends BaseFragment implements StreamExtractor
|
|||
thumbsDisabledTextView = (TextView) rootView.findViewById(R.id.detail_thumbs_disabled_view);
|
||||
|
||||
uploaderRootLayout = rootView.findViewById(R.id.detail_uploader_root_layout);
|
||||
uploaderButton = (Button) rootView.findViewById(R.id.detail_uploader_button);
|
||||
uploaderTextView = (TextView) rootView.findViewById(R.id.detail_uploader_text_view);
|
||||
uploaderThumb = (ImageView) rootView.findViewById(R.id.detail_uploader_thumbnail_view);
|
||||
|
||||
relatedStreamRootLayout = (RelativeLayout) rootView.findViewById(R.id.detail_related_streams_root_layout);
|
||||
relatedStreamRootLayout = (LinearLayout) rootView.findViewById(R.id.detail_related_streams_root_layout);
|
||||
nextStreamTitle = (TextView) rootView.findViewById(R.id.detail_next_stream_title);
|
||||
relatedStreamsView = (LinearLayout) rootView.findViewById(R.id.detail_related_streams_view);
|
||||
|
||||
relatedStreamExpandButton = ((ImageButton) rootView.findViewById(R.id.detail_related_streams_expand));
|
||||
|
||||
actionBarHandler = new ActionBarHandler(activity);
|
||||
videoDescriptionView.setMovementMethod(LinkMovementMethod.getInstance());
|
||||
|
||||
infoItemBuilder = new InfoItemBuilder(activity, rootView.findViewById(android.R.id.content));
|
||||
infoItemBuilder = new InfoItemBuilder(activity);
|
||||
|
||||
setHeightThumbnail();
|
||||
}
|
||||
|
@ -539,7 +567,7 @@ public class VideoDetailFragment extends BaseFragment implements StreamExtractor
|
|||
});
|
||||
|
||||
videoTitleRoot.setOnClickListener(this);
|
||||
uploaderButton.setOnClickListener(this);
|
||||
uploaderRootLayout.setOnClickListener(this);
|
||||
thumbnailBackgroundButton.setOnClickListener(this);
|
||||
detailControlsBackground.setOnClickListener(this);
|
||||
detailControlsPopup.setOnClickListener(this);
|
||||
|
@ -551,7 +579,7 @@ public class VideoDetailFragment extends BaseFragment implements StreamExtractor
|
|||
imageLoader.displayImage(info.thumbnail_url, thumbnailImageView, displayImageOptions, new SimpleImageLoadingListener() {
|
||||
@Override
|
||||
public void onLoadingFailed(String imageUri, View view, FailReason failReason) {
|
||||
ErrorActivity.reportError(activity, failReason.getCause(), null, activity.findViewById(android.R.id.content), ErrorActivity.ErrorInfo.make(ErrorActivity.LOAD_IMAGE, NewPipe.getNameOfService(currentStreamInfo.service_id), imageUri, R.string.could_not_load_thumbnails));
|
||||
ErrorActivity.reportError(activity, failReason.getCause(), null, activity.findViewById(android.R.id.content), ErrorActivity.ErrorInfo.make(UserAction.LOAD_IMAGE, NewPipe.getNameOfService(currentStreamInfo.service_id), imageUri, R.string.could_not_load_thumbnails));
|
||||
}
|
||||
});
|
||||
} else thumbnailImageView.setImageResource(R.drawable.dummy_thumbnail_dark);
|
||||
|
@ -739,8 +767,17 @@ public class VideoDetailFragment extends BaseFragment implements StreamExtractor
|
|||
// Get url from the new top
|
||||
StackItem peek = stack.peek();
|
||||
|
||||
if (peek.getInfo() != null) selectAndHandleInfo(peek.getInfo());
|
||||
else selectAndLoadVideo(0, peek.getUrl(), !TextUtils.isEmpty(peek.getTitle()) ? peek.getTitle() : "");
|
||||
if (peek.getInfo() != null) {
|
||||
final StreamInfo streamInfo = peek.getInfo();
|
||||
getActivity().runOnUiThread(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
selectAndHandleInfo(streamInfo);
|
||||
}
|
||||
});
|
||||
} else {
|
||||
selectAndLoadVideo(0, peek.getUrl(), !TextUtils.isEmpty(peek.getTitle()) ? peek.getTitle() : "");
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -848,7 +885,7 @@ public class VideoDetailFragment extends BaseFragment implements StreamExtractor
|
|||
}
|
||||
}
|
||||
|
||||
private void handleStreamInfo(@NonNull StreamInfo info, boolean fromNetwork) {
|
||||
private void handleStreamInfo(@NonNull final StreamInfo info, boolean fromNetwork) {
|
||||
if (DEBUG) Log.d(TAG, "handleStreamInfo() called with: info = [" + info + "]");
|
||||
currentStreamInfo = info;
|
||||
selectVideo(info.service_id, info.webpage_url, info.title);
|
||||
|
@ -862,7 +899,6 @@ public class VideoDetailFragment extends BaseFragment implements StreamExtractor
|
|||
|
||||
if (!TextUtils.isEmpty(info.uploader)) uploaderTextView.setText(info.uploader);
|
||||
uploaderTextView.setVisibility(!TextUtils.isEmpty(info.uploader) ? View.VISIBLE : View.GONE);
|
||||
uploaderButton.setVisibility(!TextUtils.isEmpty(info.channel_url) ? View.VISIBLE : View.GONE);
|
||||
uploaderThumb.setImageDrawable(ContextCompat.getDrawable(activity, R.drawable.buddy));
|
||||
|
||||
if (info.view_count >= 0) videoCountView.setText(Localization.localizeViewCount(info.view_count, activity));
|
||||
|
@ -887,14 +923,8 @@ public class VideoDetailFragment extends BaseFragment implements StreamExtractor
|
|||
thumbsUpImageView.setVisibility(info.like_count >= 0 ? View.VISIBLE : View.GONE);
|
||||
}
|
||||
|
||||
if (!TextUtils.isEmpty(info.upload_date)) videoUploadDateView.setText(Localization.localizeDate(info.upload_date, activity));
|
||||
videoUploadDateView.setVisibility(!TextUtils.isEmpty(info.upload_date) ? View.VISIBLE : View.GONE);
|
||||
|
||||
if (!TextUtils.isEmpty(info.description)) { //noinspection deprecation
|
||||
videoDescriptionView.setText(Build.VERSION.SDK_INT >= 24 ? Html.fromHtml(info.description, 0) : Html.fromHtml(info.description));
|
||||
}
|
||||
videoDescriptionView.setVisibility(!TextUtils.isEmpty(info.description) ? View.VISIBLE : View.GONE);
|
||||
|
||||
videoDescriptionView.setVisibility(View.GONE);
|
||||
videoDescriptionRootLayout.setVisibility(View.GONE);
|
||||
videoTitleToggleArrow.setImageResource(R.drawable.arrow_down);
|
||||
videoTitleToggleArrow.setVisibility(View.VISIBLE);
|
||||
|
@ -908,9 +938,32 @@ public class VideoDetailFragment extends BaseFragment implements StreamExtractor
|
|||
toggleExpandRelatedVideos(currentStreamInfo);
|
||||
wasRelatedStreamsExpanded = false;
|
||||
}
|
||||
|
||||
setTitleToUrl(info.webpage_url, info.title);
|
||||
setStreamInfoToUrl(info.webpage_url, info);
|
||||
|
||||
prepareDescription(info.description);
|
||||
prepareUploadDate(info.upload_date);
|
||||
|
||||
if (autoPlayEnabled) {
|
||||
playVideo(info);
|
||||
// Only auto play in the first open
|
||||
autoPlayEnabled = false;
|
||||
}
|
||||
}
|
||||
|
||||
private void prepareUploadDate(final String uploadDate) {
|
||||
// Hide until date is prepared or forever if no date is supplied
|
||||
videoUploadDateView.setVisibility(View.GONE);
|
||||
if (!TextUtils.isEmpty(uploadDate)) {
|
||||
backgroundHandler.sendMessage(Message.obtain(backgroundHandler, BackgroundCallback.MESSAGE_UPLOADER_DATE, uploadDate));
|
||||
}
|
||||
}
|
||||
|
||||
private void prepareDescription(final String descriptionHtml) {
|
||||
// Send the unparsed description to the handler as a message
|
||||
if (!TextUtils.isEmpty(descriptionHtml)) {
|
||||
backgroundHandler.sendMessage(Message.obtain(backgroundHandler, BackgroundCallback.MESSAGE_DESCRIPTION, descriptionHtml));
|
||||
}
|
||||
}
|
||||
|
||||
public void playVideo(StreamInfo info) {
|
||||
|
@ -987,10 +1040,8 @@ public class VideoDetailFragment extends BaseFragment implements StreamExtractor
|
|||
int height = isPortrait ? (int) (getResources().getDisplayMetrics().widthPixels / (16.0f / 9.0f))
|
||||
: (int) (getResources().getDisplayMetrics().heightPixels / 2f);
|
||||
thumbnailImageView.setScaleType(isPortrait ? ImageView.ScaleType.CENTER_CROP : ImageView.ScaleType.FIT_CENTER);
|
||||
thumbnailImageView.setLayoutParams(new RelativeLayout.LayoutParams(RelativeLayout.LayoutParams.MATCH_PARENT, height));
|
||||
thumbnailImageView.setLayoutParams(new FrameLayout.LayoutParams(RelativeLayout.LayoutParams.MATCH_PARENT, height));
|
||||
thumbnailImageView.setMinimumHeight(height);
|
||||
thumbnailBackgroundButton.setLayoutParams(new RelativeLayout.LayoutParams(RelativeLayout.LayoutParams.MATCH_PARENT, height));
|
||||
thumbnailBackgroundButton.setMinimumHeight(height);
|
||||
}
|
||||
|
||||
public String getShortCount(Long viewCount) {
|
||||
|
@ -1032,9 +1083,6 @@ public class VideoDetailFragment extends BaseFragment implements StreamExtractor
|
|||
.setStartDelay((long) (duration * .8f) + delay).setDuration(duration).setInterpolator(new FastOutSlowInInterpolator()).start();
|
||||
}
|
||||
}
|
||||
/*//////////////////////////////////////////////////////////////////////////
|
||||
// OnStreamInfoReceivedListener callbacks
|
||||
//////////////////////////////////////////////////////////////////////////*/
|
||||
|
||||
private void setErrorImage(final int imageResource) {
|
||||
if (thumbnailImageView == null || activity == null) return;
|
||||
|
@ -1055,6 +1103,10 @@ public class VideoDetailFragment extends BaseFragment implements StreamExtractor
|
|||
currentStreamInfo = null;
|
||||
}
|
||||
|
||||
/*//////////////////////////////////////////////////////////////////////////
|
||||
// OnStreamInfoReceivedListener callbacks
|
||||
//////////////////////////////////////////////////////////////////////////*/
|
||||
|
||||
@Override
|
||||
public void onReceive(StreamInfo info) {
|
||||
if (DEBUG) Log.d(TAG, "onReceive() called with: info = [" + info + "]");
|
||||
|
@ -1062,15 +1114,8 @@ public class VideoDetailFragment extends BaseFragment implements StreamExtractor
|
|||
|
||||
handleStreamInfo(info, true);
|
||||
showContentWithAnimation(300, 0, 0);
|
||||
|
||||
animateView(loadingProgressBar, false, 200);
|
||||
|
||||
if (autoPlayEnabled) {
|
||||
playVideo(info);
|
||||
// Only auto play in the first open
|
||||
autoPlayEnabled = false;
|
||||
}
|
||||
|
||||
StreamInfoCache.getInstance().putInfo(info);
|
||||
isLoading.set(false);
|
||||
|
||||
|
@ -1126,4 +1171,69 @@ public class VideoDetailFragment extends BaseFragment implements StreamExtractor
|
|||
public void onUnrecoverableError(Exception exception) {
|
||||
activity.finish();
|
||||
}
|
||||
|
||||
/*//////////////////////////////////////////////////////////////////////////
|
||||
// Background handling
|
||||
//////////////////////////////////////////////////////////////////////////*/
|
||||
|
||||
private static class BackgroundCallback implements Handler.Callback {
|
||||
private static final int MESSAGE_DESCRIPTION = 1;
|
||||
public static final int MESSAGE_UPLOADER_DATE = 2;
|
||||
private final Handler uiHandler;
|
||||
private final Context context;
|
||||
|
||||
BackgroundCallback(Handler uiHandler, Context context) {
|
||||
this.uiHandler = uiHandler;
|
||||
this.context = context;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean handleMessage(Message msg) {
|
||||
switch (msg.what) {
|
||||
case MESSAGE_DESCRIPTION:
|
||||
handleDescription((String) msg.obj);
|
||||
return true;
|
||||
case MESSAGE_UPLOADER_DATE:
|
||||
handleUploadDate((String) msg.obj);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private void handleUploadDate(String uploadDate) {
|
||||
String localizedDate = Localization.localizeDate(uploadDate, context);
|
||||
uiHandler.sendMessage(Message.obtain(uiHandler, MESSAGE_UPLOADER_DATE, localizedDate));
|
||||
}
|
||||
|
||||
private void handleDescription(String description) {
|
||||
Spanned parsedDescription;
|
||||
if (TextUtils.isEmpty(description)) {
|
||||
return;
|
||||
}
|
||||
if (Build.VERSION.SDK_INT >= 24) {
|
||||
parsedDescription = Html.fromHtml(description, 0);
|
||||
} else {
|
||||
//noinspection deprecation
|
||||
parsedDescription = Html.fromHtml(description);
|
||||
}
|
||||
uiHandler.sendMessage(Message.obtain(uiHandler, MESSAGE_DESCRIPTION, parsedDescription));
|
||||
}
|
||||
}
|
||||
|
||||
private class UICallback implements Handler.Callback {
|
||||
@Override
|
||||
public boolean handleMessage(Message msg) {
|
||||
switch (msg.what) {
|
||||
case BackgroundCallback.MESSAGE_DESCRIPTION:
|
||||
videoDescriptionView.setText((Spanned) msg.obj);
|
||||
videoDescriptionView.setVisibility(View.VISIBLE);
|
||||
return true;
|
||||
case BackgroundCallback.MESSAGE_UPLOADER_DATE:
|
||||
videoUploadDateView.setText((String) msg.obj);
|
||||
videoUploadDateView.setVisibility(View.VISIBLE);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,33 @@
|
|||
package org.schabi.newpipe.fragments.search;
|
||||
|
||||
import android.support.v7.widget.LinearLayoutManager;
|
||||
import android.support.v7.widget.RecyclerView;
|
||||
|
||||
/**
|
||||
* Recycler view scroll listener which calls the method {@link #onScrolledDown(RecyclerView)}
|
||||
* if the view is scrolled below the last item.
|
||||
*/
|
||||
public abstract class OnScrollBelowItemsListener extends RecyclerView.OnScrollListener {
|
||||
|
||||
@Override
|
||||
public void onScrolled(RecyclerView recyclerView, int dx, int dy) {
|
||||
super.onScrolled(recyclerView, dx, dy);
|
||||
//check for scroll down
|
||||
if (dy > 0) {
|
||||
int pastVisibleItems, visibleItemCount, totalItemCount;
|
||||
LinearLayoutManager layoutManager = (LinearLayoutManager) recyclerView.getLayoutManager();
|
||||
visibleItemCount = recyclerView.getLayoutManager().getChildCount();
|
||||
totalItemCount = recyclerView.getLayoutManager().getItemCount();
|
||||
pastVisibleItems = layoutManager.findFirstVisibleItemPosition();
|
||||
if ((visibleItemCount + pastVisibleItems) >= totalItemCount) {
|
||||
onScrolledDown(recyclerView);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Called when the recycler view is scrolled below the last item.
|
||||
* @param recyclerView the recycler view
|
||||
*/
|
||||
public abstract void onScrolledDown(RecyclerView recyclerView);
|
||||
}
|
|
@ -212,7 +212,7 @@ public class SearchFragment extends BaseFragment implements SuggestionWorker.OnS
|
|||
resultRecyclerView.setLayoutManager(new LinearLayoutManager(activity));
|
||||
|
||||
if (infoListAdapter == null) {
|
||||
infoListAdapter = new InfoListAdapter(getActivity(), getActivity().findViewById(android.R.id.content));
|
||||
infoListAdapter = new InfoListAdapter(getActivity());
|
||||
if (savedInstanceState != null) {
|
||||
//noinspection unchecked
|
||||
ArrayList<InfoItem> serializable = (ArrayList<InfoItem>) savedInstanceState.getSerializable(INFO_LIST_KEY);
|
||||
|
@ -242,19 +242,10 @@ public class SearchFragment extends BaseFragment implements SuggestionWorker.OnS
|
|||
protected void initListeners() {
|
||||
super.initListeners();
|
||||
resultRecyclerView.clearOnScrollListeners();
|
||||
resultRecyclerView.addOnScrollListener(new RecyclerView.OnScrollListener() {
|
||||
resultRecyclerView.addOnScrollListener(new OnScrollBelowItemsListener() {
|
||||
@Override
|
||||
public void onScrolled(RecyclerView recyclerView, int dx, int dy) {
|
||||
int pastVisiblesItems, visibleItemCount, totalItemCount;
|
||||
super.onScrolled(recyclerView, dx, dy);
|
||||
//check for scroll down
|
||||
if (dy > 0) {
|
||||
LinearLayoutManager layoutManager = (LinearLayoutManager) resultRecyclerView.getLayoutManager();
|
||||
visibleItemCount = resultRecyclerView.getLayoutManager().getChildCount();
|
||||
totalItemCount = resultRecyclerView.getLayoutManager().getItemCount();
|
||||
pastVisiblesItems = layoutManager.findFirstVisibleItemPosition();
|
||||
|
||||
if ((visibleItemCount + pastVisiblesItems) >= totalItemCount && !isLoading.get()) {
|
||||
public void onScrolledDown(RecyclerView recyclerView) {
|
||||
if(!isLoading.get()) {
|
||||
pageNumber++;
|
||||
recyclerView.post(new Runnable() {
|
||||
@Override
|
||||
|
@ -265,10 +256,10 @@ public class SearchFragment extends BaseFragment implements SuggestionWorker.OnS
|
|||
search(searchQuery, pageNumber);
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
protected void reloadContent() {
|
||||
if (DEBUG) Log.d(TAG, "reloadContent() called");
|
||||
|
|
|
@ -31,8 +31,7 @@ import de.hdodenhof.circleimageview.CircleImageView;
|
|||
public class ChannelInfoItemHolder extends InfoItemHolder {
|
||||
public final CircleImageView itemThumbnailView;
|
||||
public final TextView itemChannelTitleView;
|
||||
public final TextView itemSubscriberCountView;
|
||||
public final TextView itemVideoCountView;
|
||||
public final TextView itemAdditionalDetailView;
|
||||
public final TextView itemChannelDescriptionView;
|
||||
|
||||
public final View itemRoot;
|
||||
|
@ -42,8 +41,7 @@ public class ChannelInfoItemHolder extends InfoItemHolder {
|
|||
itemRoot = v.findViewById(R.id.itemRoot);
|
||||
itemThumbnailView = (CircleImageView) v.findViewById(R.id.itemThumbnailView);
|
||||
itemChannelTitleView = (TextView) v.findViewById(R.id.itemChannelTitleView);
|
||||
itemSubscriberCountView = (TextView) v.findViewById(R.id.itemSubscriberCountView);
|
||||
itemVideoCountView = (TextView) v.findViewById(R.id.itemVideoCountView);
|
||||
itemAdditionalDetailView = (TextView) v.findViewById(R.id.itemAdditionalDetails);
|
||||
itemChannelDescriptionView = (TextView) v.findViewById(R.id.itemChannelDescriptionView);
|
||||
}
|
||||
|
||||
|
|
|
@ -17,6 +17,8 @@ import org.schabi.newpipe.extractor.InfoItem;
|
|||
import org.schabi.newpipe.extractor.channel.ChannelInfoItem;
|
||||
import org.schabi.newpipe.extractor.stream_info.StreamInfoItem;
|
||||
|
||||
import java.util.Locale;
|
||||
|
||||
/**
|
||||
* Created by Christian Schabesberger on 26.09.16.
|
||||
* <p>
|
||||
|
@ -54,18 +56,35 @@ public class InfoItemBuilder {
|
|||
void selected(int serviceId, String url, String title);
|
||||
}
|
||||
|
||||
private Context mContext = null;
|
||||
private LayoutInflater inflater;
|
||||
private View rootView = null;
|
||||
private ImageLoader imageLoader = ImageLoader.getInstance();
|
||||
private DisplayImageOptions displayImageOptions =
|
||||
new DisplayImageOptions.Builder().cacheInMemory(true).build();
|
||||
|
||||
/** Base display options */
|
||||
private static final DisplayImageOptions DISPLAY_IMAGE_OPTIONS =
|
||||
new DisplayImageOptions.Builder()
|
||||
.cacheInMemory(true)
|
||||
.build();
|
||||
|
||||
/** Display options for stream thumbnails */
|
||||
private static final DisplayImageOptions DISPLAY_STREAM_THUMBNAIL_OPTIONS =
|
||||
new DisplayImageOptions.Builder()
|
||||
.cloneFrom(DISPLAY_IMAGE_OPTIONS)
|
||||
.showImageOnFail(R.drawable.dummy_thumbnail)
|
||||
.showImageForEmptyUri(R.drawable.dummy_thumbnail)
|
||||
.showImageOnLoading(R.drawable.dummy_thumbnail)
|
||||
.build();
|
||||
|
||||
/** Display options for channel thumbnails */
|
||||
private static final DisplayImageOptions DISPLAY_CHANNEL_THUMBNAIL_OPTIONS =
|
||||
new DisplayImageOptions.Builder()
|
||||
.cloneFrom(DISPLAY_IMAGE_OPTIONS)
|
||||
.showImageOnLoading(R.drawable.buddy_channel_item)
|
||||
.showImageForEmptyUri(R.drawable.buddy_channel_item)
|
||||
.showImageOnFail(R.drawable.buddy_channel_item)
|
||||
.build();
|
||||
private OnInfoItemSelectedListener onStreamInfoItemSelectedListener;
|
||||
private OnInfoItemSelectedListener onChannelInfoItemSelectedListener;
|
||||
|
||||
public InfoItemBuilder(Context context, View rootView) {
|
||||
mContext = context;
|
||||
this.rootView = rootView;
|
||||
public InfoItemBuilder(Context context) {
|
||||
viewsS = context.getString(R.string.views);
|
||||
videosS = context.getString(R.string.videos);
|
||||
subsS = context.getString(R.string.subscriber);
|
||||
|
@ -73,7 +92,6 @@ public class InfoItemBuilder {
|
|||
thousand = context.getString(R.string.short_thousand);
|
||||
million = context.getString(R.string.short_million);
|
||||
billion = context.getString(R.string.short_billion);
|
||||
inflater = LayoutInflater.from(context);
|
||||
}
|
||||
|
||||
public void setOnStreamInfoItemSelectedListener(
|
||||
|
@ -107,6 +125,7 @@ public class InfoItemBuilder {
|
|||
public View buildView(ViewGroup parent, final InfoItem info) {
|
||||
View itemView = null;
|
||||
InfoItemHolder holder = null;
|
||||
LayoutInflater inflater = LayoutInflater.from(parent.getContext());
|
||||
switch (info.infoType()) {
|
||||
case STREAM:
|
||||
//long start = System.nanoTime();
|
||||
|
@ -127,6 +146,22 @@ public class InfoItemBuilder {
|
|||
return itemView;
|
||||
}
|
||||
|
||||
|
||||
private String getStreamInfoDetailLine(final StreamInfoItem info) {
|
||||
String viewsAndDate = "";
|
||||
if(info.view_count >= 0) {
|
||||
viewsAndDate = shortViewCount(info.view_count);
|
||||
}
|
||||
if(!TextUtils.isEmpty(info.upload_date)) {
|
||||
if(viewsAndDate.isEmpty()) {
|
||||
viewsAndDate = info.upload_date;
|
||||
} else {
|
||||
viewsAndDate += " • " + info.upload_date;
|
||||
}
|
||||
}
|
||||
return viewsAndDate;
|
||||
}
|
||||
|
||||
private void buildStreamInfoItem(StreamInfoItemHolder holder, final StreamInfoItem info) {
|
||||
if (info.infoType() != InfoItem.InfoType.STREAM) {
|
||||
Log.e("InfoItemBuilder", "Info type not yet supported");
|
||||
|
@ -146,47 +181,60 @@ public class InfoItemBuilder {
|
|||
holder.itemDurationView.setVisibility(View.GONE);
|
||||
}
|
||||
}
|
||||
if (info.view_count >= 0) {
|
||||
holder.itemViewCountView.setText(shortViewCount(info.view_count));
|
||||
} else {
|
||||
holder.itemViewCountView.setVisibility(View.GONE);
|
||||
}
|
||||
if (!TextUtils.isEmpty(info.upload_date)) holder.itemUploadDateView.setText(info.upload_date + " • ");
|
||||
|
||||
holder.itemThumbnailView.setImageResource(R.drawable.dummy_thumbnail);
|
||||
if (!TextUtils.isEmpty(info.thumbnail_url)) {
|
||||
holder.itemAdditionalDetails.setText(getStreamInfoDetailLine(info));
|
||||
|
||||
// Default thumbnail is shown on error, while loading and if the url is empty
|
||||
imageLoader.displayImage(info.thumbnail_url,
|
||||
holder.itemThumbnailView, displayImageOptions,
|
||||
new ImageErrorLoadingListener(mContext, rootView, info.service_id));
|
||||
}
|
||||
holder.itemThumbnailView,
|
||||
DISPLAY_STREAM_THUMBNAIL_OPTIONS,
|
||||
new ImageErrorLoadingListener(holder.itemRoot.getContext(), holder.itemRoot.getRootView(), info.service_id));
|
||||
|
||||
|
||||
holder.itemRoot.setOnClickListener(new View.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View view) {
|
||||
if(onStreamInfoItemSelectedListener != null) {
|
||||
onStreamInfoItemSelectedListener.selected(info.service_id, info.webpage_url, info.getTitle());
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private String getChannelInfoDetailLine(final ChannelInfoItem info) {
|
||||
String details = "";
|
||||
if(info.subscriberCount >= 0) {
|
||||
details = shortSubscriber(info.subscriberCount);
|
||||
}
|
||||
if(info.videoAmount >= 0) {
|
||||
String formattedVideoAmount = info.videoAmount + " " + videosS;
|
||||
if(!details.isEmpty()) {
|
||||
details += " • " + formattedVideoAmount;
|
||||
} else {
|
||||
details = formattedVideoAmount;
|
||||
}
|
||||
}
|
||||
return details;
|
||||
}
|
||||
|
||||
private void buildChannelInfoItem(ChannelInfoItemHolder holder, final ChannelInfoItem info) {
|
||||
if (!TextUtils.isEmpty(info.getTitle())) holder.itemChannelTitleView.setText(info.getTitle());
|
||||
holder.itemSubscriberCountView.setText(shortSubscriber(info.subscriberCount) + " • ");
|
||||
holder.itemVideoCountView.setText(info.videoAmount + " " + videosS);
|
||||
holder.itemAdditionalDetailView.setText(getChannelInfoDetailLine(info));
|
||||
if (!TextUtils.isEmpty(info.description)) holder.itemChannelDescriptionView.setText(info.description);
|
||||
|
||||
holder.itemThumbnailView.setImageResource(R.drawable.buddy_channel_item);
|
||||
if (!TextUtils.isEmpty(info.thumbnailUrl)) {
|
||||
imageLoader.displayImage(info.thumbnailUrl,
|
||||
holder.itemThumbnailView,
|
||||
displayImageOptions,
|
||||
new ImageErrorLoadingListener(mContext, rootView, info.serviceId));
|
||||
}
|
||||
DISPLAY_CHANNEL_THUMBNAIL_OPTIONS,
|
||||
new ImageErrorLoadingListener(holder.itemRoot.getContext(), holder.itemRoot.getRootView(), info.serviceId));
|
||||
|
||||
|
||||
holder.itemRoot.setOnClickListener(new View.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View view) {
|
||||
if(onStreamInfoItemSelectedListener != null) {
|
||||
onChannelInfoItemSelectedListener.selected(info.serviceId, info.getLink(), info.channelName);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -218,7 +266,10 @@ public class InfoItemBuilder {
|
|||
}
|
||||
|
||||
public static String getDurationString(int duration) {
|
||||
String output = "";
|
||||
if(duration < 0) {
|
||||
duration = 0;
|
||||
}
|
||||
String output;
|
||||
int days = duration / (24 * 60 * 60); /* greater than a day */
|
||||
duration %= (24 * 60 * 60);
|
||||
int hours = duration / (60 * 60); /* greater than an hour */
|
||||
|
@ -228,46 +279,12 @@ public class InfoItemBuilder {
|
|||
|
||||
//handle days
|
||||
if (days > 0) {
|
||||
output = Integer.toString(days) + ":";
|
||||
}
|
||||
// handle hours
|
||||
if (hours > 0 || !output.isEmpty()) {
|
||||
if (hours > 0) {
|
||||
if (hours >= 10 || output.isEmpty()) {
|
||||
output += Integer.toString(hours);
|
||||
output = String.format(Locale.US, "%d:%02d:%02d:%02d", days, hours, minutes, seconds);
|
||||
} else if(hours > 0) {
|
||||
output = String.format(Locale.US, "%d:%02d:%02d", hours, minutes, seconds);
|
||||
} else {
|
||||
output += "0" + Integer.toString(hours);
|
||||
output = String.format(Locale.US, "%d:%02d", minutes, seconds);
|
||||
}
|
||||
} else {
|
||||
output += "00";
|
||||
}
|
||||
output += ":";
|
||||
}
|
||||
//handle minutes
|
||||
if (minutes > 0 || !output.isEmpty()) {
|
||||
if (minutes > 0) {
|
||||
if (minutes >= 10 || output.isEmpty()) {
|
||||
output += Integer.toString(minutes);
|
||||
} else {
|
||||
output += "0" + Integer.toString(minutes);
|
||||
}
|
||||
} else {
|
||||
output += "00";
|
||||
}
|
||||
output += ":";
|
||||
}
|
||||
|
||||
//handle seconds
|
||||
if (output.isEmpty()) {
|
||||
output += "0:";
|
||||
}
|
||||
|
||||
if (seconds >= 10) {
|
||||
output += Integer.toString(seconds);
|
||||
} else {
|
||||
output += "0" + Integer.toString(seconds);
|
||||
}
|
||||
|
||||
return output;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -55,8 +55,8 @@ public class InfoListAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolde
|
|||
notifyDataSetChanged();
|
||||
}
|
||||
|
||||
public InfoListAdapter(Activity a, View rootView) {
|
||||
infoItemBuilder = new InfoItemBuilder(a, rootView);
|
||||
public InfoListAdapter(Activity a) {
|
||||
infoItemBuilder = new InfoItemBuilder(a);
|
||||
infoItemList = new ArrayList<>();
|
||||
}
|
||||
|
||||
|
@ -78,6 +78,9 @@ public class InfoListAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolde
|
|||
}
|
||||
|
||||
public void clearStreamItemList() {
|
||||
if(infoItemList.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
infoItemList.clear();
|
||||
notifyDataSetChanged();
|
||||
}
|
||||
|
@ -152,7 +155,7 @@ public class InfoListAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolde
|
|||
|
||||
@Override
|
||||
public void onBindViewHolder(RecyclerView.ViewHolder holder, int i) {
|
||||
//god damen f*** ANDROID SH**
|
||||
//god damn f*** ANDROID SH**
|
||||
if(holder instanceof InfoItemHolder) {
|
||||
if(header != null) {
|
||||
i--;
|
||||
|
|
|
@ -33,8 +33,7 @@ public class StreamInfoItemHolder extends InfoItemHolder {
|
|||
public final TextView itemVideoTitleView,
|
||||
itemUploaderView,
|
||||
itemDurationView,
|
||||
itemUploadDateView,
|
||||
itemViewCountView;
|
||||
itemAdditionalDetails;
|
||||
public final View itemRoot;
|
||||
|
||||
public StreamInfoItemHolder(View v) {
|
||||
|
@ -44,8 +43,7 @@ public class StreamInfoItemHolder extends InfoItemHolder {
|
|||
itemVideoTitleView = (TextView) v.findViewById(R.id.itemVideoTitleView);
|
||||
itemUploaderView = (TextView) v.findViewById(R.id.itemUploaderView);
|
||||
itemDurationView = (TextView) v.findViewById(R.id.itemDurationView);
|
||||
itemUploadDateView = (TextView) v.findViewById(R.id.itemUploadDateView);
|
||||
itemViewCountView = (TextView) v.findViewById(R.id.itemViewCountView);
|
||||
itemAdditionalDetails = (TextView) v.findViewById(R.id.itemAdditionalDetails);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
package org.schabi.newpipe.report;
|
||||
|
||||
import android.content.Context;
|
||||
import android.support.annotation.NonNull;
|
||||
|
||||
import org.acra.collector.CrashReportData;
|
||||
import org.acra.sender.ReportSender;
|
||||
|
@ -30,9 +31,9 @@ import org.schabi.newpipe.R;
|
|||
public class AcraReportSender implements ReportSender {
|
||||
|
||||
@Override
|
||||
public void send(Context context, CrashReportData report) throws ReportSenderException {
|
||||
public void send(@NonNull Context context, @NonNull CrashReportData report) throws ReportSenderException {
|
||||
ErrorActivity.reportError(context, report,
|
||||
ErrorActivity.ErrorInfo.make(ErrorActivity.UI_ERROR,"none",
|
||||
ErrorActivity.ErrorInfo.make(UserAction.UI_ERROR,"none",
|
||||
"App crash, UI failure", R.string.app_ui_crash));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
package org.schabi.newpipe.report;
|
||||
|
||||
import android.content.Context;
|
||||
import android.support.annotation.NonNull;
|
||||
|
||||
import org.acra.config.ACRAConfiguration;
|
||||
import org.acra.sender.ReportSender;
|
||||
|
@ -28,7 +29,8 @@ import org.schabi.newpipe.report.AcraReportSender;
|
|||
*/
|
||||
|
||||
public class AcraReportSenderFactory implements ReportSenderFactory {
|
||||
public ReportSender create(Context context, ACRAConfiguration config) {
|
||||
@NonNull
|
||||
public ReportSender create(@NonNull Context context, @NonNull ACRAConfiguration config) {
|
||||
return new AcraReportSender();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -11,6 +11,8 @@ import android.os.Handler;
|
|||
import android.os.Parcel;
|
||||
import android.os.Parcelable;
|
||||
import android.preference.PreferenceManager;
|
||||
import android.support.annotation.Nullable;
|
||||
import android.support.annotation.StringRes;
|
||||
import android.support.design.widget.Snackbar;
|
||||
import android.support.v4.app.NavUtils;
|
||||
import android.support.v7.app.ActionBar;
|
||||
|
@ -71,24 +73,7 @@ public class ErrorActivity extends AppCompatActivity {
|
|||
// BUNDLE TAGS
|
||||
public static final String ERROR_INFO = "error_info";
|
||||
public static final String ERROR_LIST = "error_list";
|
||||
// MESSAGE ID
|
||||
public static final int SEARCHED = 0;
|
||||
public static final int REQUESTED_STREAM = 1;
|
||||
public static final int GET_SUGGESTIONS = 2;
|
||||
public static final int SOMETHING_ELSE = 3;
|
||||
public static final int USER_REPORT = 4;
|
||||
public static final int LOAD_IMAGE = 5;
|
||||
public static final int UI_ERROR = 6;
|
||||
public static final int REQUESTED_CHANNEL = 7;
|
||||
// MESSAGE STRING
|
||||
public static final String SEARCHED_STRING = "searched";
|
||||
public static final String REQUESTED_STREAM_STRING = "requested stream";
|
||||
public static final String GET_SUGGESTIONS_STRING = "get suggestions";
|
||||
public static final String SOMETHING_ELSE_STRING = "something";
|
||||
public static final String USER_REPORT_STRING = "user report";
|
||||
public static final String LOAD_IMAGE_STRING = "load image";
|
||||
public static final String UI_ERROR_STRING = "ui error";
|
||||
public static final String REQUESTED_CHANNEL_STRING = "requested channel";
|
||||
|
||||
public static final String ERROR_EMAIL_ADDRESS = "crashreport@newpipe.schabi.org";
|
||||
public static final String ERROR_EMAIL_SUBJECT = "Exception in NewPipe " + BuildConfig.VERSION_NAME;
|
||||
Thread globIpRangeThread;
|
||||
|
@ -105,11 +90,11 @@ public class ErrorActivity extends AppCompatActivity {
|
|||
private TextView errorMessageView;
|
||||
|
||||
public static void reportUiError(final AppCompatActivity activity, final Throwable el) {
|
||||
reportError(activity, el, activity.getClass(), null, ErrorInfo.make(UI_ERROR, "none", "", R.string.app_ui_crash));
|
||||
reportError(activity, el, activity.getClass(), null, ErrorInfo.make(UserAction.UI_ERROR, "none", "", R.string.app_ui_crash));
|
||||
}
|
||||
|
||||
public static void reportError(final Context context, final List<Throwable> el,
|
||||
final Class returnAcitivty, View rootView, final ErrorInfo errorInfo) {
|
||||
final Class returnActivity, View rootView, final ErrorInfo errorInfo) {
|
||||
|
||||
if (rootView != null) {
|
||||
Snackbar.make(rootView, R.string.error_snackbar_message, Snackbar.LENGTH_LONG)
|
||||
|
@ -118,7 +103,7 @@ public class ErrorActivity extends AppCompatActivity {
|
|||
@Override
|
||||
public void onClick(View v) {
|
||||
ActivityCommunicator ac = ActivityCommunicator.getCommunicator();
|
||||
ac.returnActivity = returnAcitivty;
|
||||
ac.returnActivity = returnActivity;
|
||||
Intent intent = new Intent(context, ErrorActivity.class);
|
||||
intent.putExtra(ERROR_INFO, errorInfo);
|
||||
intent.putExtra(ERROR_LIST, elToSl(el));
|
||||
|
@ -128,7 +113,7 @@ public class ErrorActivity extends AppCompatActivity {
|
|||
}).show();
|
||||
} else {
|
||||
ActivityCommunicator ac = ActivityCommunicator.getCommunicator();
|
||||
ac.returnActivity = returnAcitivty;
|
||||
ac.returnActivity = returnActivity;
|
||||
Intent intent = new Intent(context, ErrorActivity.class);
|
||||
intent.putExtra(ERROR_INFO, errorInfo);
|
||||
intent.putExtra(ERROR_LIST, elToSl(el));
|
||||
|
@ -138,34 +123,34 @@ public class ErrorActivity extends AppCompatActivity {
|
|||
}
|
||||
|
||||
public static void reportError(final Context context, final Throwable e,
|
||||
final Class returnAcitivty, View rootView, final ErrorInfo errorInfo) {
|
||||
final Class returnActivity, View rootView, final ErrorInfo errorInfo) {
|
||||
List<Throwable> el = null;
|
||||
if(e != null) {
|
||||
el = new Vector<>();
|
||||
el.add(e);
|
||||
}
|
||||
reportError(context, el, returnAcitivty, rootView, errorInfo);
|
||||
reportError(context, el, returnActivity, rootView, errorInfo);
|
||||
}
|
||||
|
||||
// async call
|
||||
public static void reportError(Handler handler, final Context context, final Throwable e,
|
||||
final Class returnAcitivty, final View rootView, final ErrorInfo errorInfo) {
|
||||
final Class returnActivity, final View rootView, final ErrorInfo errorInfo) {
|
||||
|
||||
List<Throwable> el = null;
|
||||
if(e != null) {
|
||||
el = new Vector<>();
|
||||
el.add(e);
|
||||
}
|
||||
reportError(handler, context, el, returnAcitivty, rootView, errorInfo);
|
||||
reportError(handler, context, el, returnActivity, rootView, errorInfo);
|
||||
}
|
||||
|
||||
// async call
|
||||
public static void reportError(Handler handler, final Context context, final List<Throwable> el,
|
||||
final Class returnAcitivty, final View rootView, final ErrorInfo errorInfo) {
|
||||
final Class returnActivity, final View rootView, final ErrorInfo errorInfo) {
|
||||
handler.post(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
reportError(context, el, returnAcitivty, rootView, errorInfo);
|
||||
reportError(context, el, returnActivity, rootView, errorInfo);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
@ -232,7 +217,7 @@ public class ErrorActivity extends AppCompatActivity {
|
|||
errorInfo = intent.getParcelableExtra(ERROR_INFO);
|
||||
errorList = intent.getStringArrayExtra(ERROR_LIST);
|
||||
|
||||
//importand add gurumeditaion
|
||||
// important add guru meditation
|
||||
addGuruMeditaion();
|
||||
currentTimeStamp = getCurrentTimeStamp();
|
||||
|
||||
|
@ -250,7 +235,7 @@ public class ErrorActivity extends AppCompatActivity {
|
|||
});
|
||||
reportButton.setEnabled(false);
|
||||
|
||||
globIpRangeThread = new Thread(new IpRagneRequester());
|
||||
globIpRangeThread = new Thread(new IpRangeRequester());
|
||||
globIpRangeThread.start();
|
||||
|
||||
// normal bugreport
|
||||
|
@ -308,17 +293,30 @@ public class ErrorActivity extends AppCompatActivity {
|
|||
return text;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the checked activity.
|
||||
* @param returnActivity the activity to return to
|
||||
* @return the casted return activity or null
|
||||
*/
|
||||
@Nullable
|
||||
static Class<? extends Activity> getReturnActivity(Class<?> returnActivity) {
|
||||
Class<? extends Activity> checkedReturnActivity = null;
|
||||
if (returnActivity != null){
|
||||
if (Activity.class.isAssignableFrom(returnActivity)) {
|
||||
checkedReturnActivity = returnActivity.asSubclass(Activity.class);
|
||||
} else {
|
||||
checkedReturnActivity = MainActivity.class;
|
||||
}
|
||||
}
|
||||
return checkedReturnActivity;
|
||||
}
|
||||
|
||||
private void goToReturnActivity() {
|
||||
if (returnActivity == null) {
|
||||
Class<? extends Activity> checkedReturnActivity = getReturnActivity(returnActivity);
|
||||
if (checkedReturnActivity == null) {
|
||||
super.onBackPressed();
|
||||
} else {
|
||||
Intent intent;
|
||||
if (returnActivity != null &&
|
||||
returnActivity.isAssignableFrom(Activity.class)) {
|
||||
intent = new Intent(this, returnActivity);
|
||||
} else {
|
||||
intent = new Intent(this, MainActivity.class);
|
||||
}
|
||||
Intent intent = new Intent(this, checkedReturnActivity);
|
||||
intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
|
||||
NavUtils.navigateUpTo(this, intent);
|
||||
}
|
||||
|
@ -376,26 +374,11 @@ public class ErrorActivity extends AppCompatActivity {
|
|||
return "";
|
||||
}
|
||||
|
||||
private String getUserActionString(int userAction) {
|
||||
switch (userAction) {
|
||||
case REQUESTED_STREAM:
|
||||
return REQUESTED_STREAM_STRING;
|
||||
case SEARCHED:
|
||||
return SEARCHED_STRING;
|
||||
case GET_SUGGESTIONS:
|
||||
return GET_SUGGESTIONS_STRING;
|
||||
case SOMETHING_ELSE:
|
||||
return SOMETHING_ELSE_STRING;
|
||||
case USER_REPORT:
|
||||
return USER_REPORT_STRING;
|
||||
case LOAD_IMAGE:
|
||||
return LOAD_IMAGE_STRING;
|
||||
case UI_ERROR:
|
||||
return UI_ERROR_STRING;
|
||||
case REQUESTED_CHANNEL:
|
||||
return REQUESTED_CHANNEL_STRING;
|
||||
default:
|
||||
private String getUserActionString(UserAction userAction) {
|
||||
if(userAction == null) {
|
||||
return "Your description is in another castle.";
|
||||
} else {
|
||||
return userAction.getMessage();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -444,28 +427,28 @@ public class ErrorActivity extends AppCompatActivity {
|
|||
return new ErrorInfo[size];
|
||||
}
|
||||
};
|
||||
public int userAction;
|
||||
public String request;
|
||||
public String serviceName;
|
||||
public int message;
|
||||
final public UserAction userAction;
|
||||
final public String request;
|
||||
final public String serviceName;
|
||||
@StringRes
|
||||
final public int message;
|
||||
|
||||
public ErrorInfo() {
|
||||
private ErrorInfo(UserAction userAction, String serviceName, String request, @StringRes int message) {
|
||||
this.userAction = userAction;
|
||||
this.serviceName = serviceName;
|
||||
this.request = request;
|
||||
this.message = message;
|
||||
}
|
||||
|
||||
protected ErrorInfo(Parcel in) {
|
||||
this.userAction = in.readInt();
|
||||
this.userAction = UserAction.valueOf(in.readString());
|
||||
this.request = in.readString();
|
||||
this.serviceName = in.readString();
|
||||
this.message = in.readInt();
|
||||
}
|
||||
|
||||
public static ErrorInfo make(int userAction, String serviceName, String request, int message) {
|
||||
ErrorInfo info = new ErrorInfo();
|
||||
info.userAction = userAction;
|
||||
info.serviceName = serviceName;
|
||||
info.request = request;
|
||||
info.message = message;
|
||||
return info;
|
||||
public static ErrorInfo make(UserAction userAction, String serviceName, String request, @StringRes int message) {
|
||||
return new ErrorInfo(userAction, serviceName, request, message);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -475,14 +458,14 @@ public class ErrorActivity extends AppCompatActivity {
|
|||
|
||||
@Override
|
||||
public void writeToParcel(Parcel dest, int flags) {
|
||||
dest.writeInt(this.userAction);
|
||||
dest.writeString(this.userAction.name());
|
||||
dest.writeString(this.request);
|
||||
dest.writeString(this.serviceName);
|
||||
dest.writeInt(this.message);
|
||||
}
|
||||
}
|
||||
|
||||
private class IpRagneRequester implements Runnable {
|
||||
private class IpRangeRequester implements Runnable {
|
||||
Handler h = new Handler();
|
||||
public void run() {
|
||||
String ipRange = "none";
|
||||
|
@ -493,17 +476,16 @@ public class ErrorActivity extends AppCompatActivity {
|
|||
ipRange = Parser.matchGroup1("([0-9]*\\.[0-9]*\\.)[0-9]*\\.[0-9]*", ip)
|
||||
+ "0.0";
|
||||
} catch(Throwable e) {
|
||||
Log.d(TAG, "Error while error: could not get iprange");
|
||||
e.printStackTrace();
|
||||
Log.w(TAG, "Error while error: could not get iprange", e);
|
||||
} finally {
|
||||
h.post(new IpRageReturnRunnable(ipRange));
|
||||
h.post(new IpRangeReturnRunnable(ipRange));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private class IpRageReturnRunnable implements Runnable {
|
||||
private class IpRangeReturnRunnable implements Runnable {
|
||||
String ipRange;
|
||||
public IpRageReturnRunnable(String ipRange) {
|
||||
public IpRangeReturnRunnable(String ipRange) {
|
||||
this.ipRange = ipRange;
|
||||
}
|
||||
public void run() {
|
||||
|
|
|
@ -0,0 +1,26 @@
|
|||
package org.schabi.newpipe.report;
|
||||
|
||||
/**
|
||||
* The user actions that can cause an error.
|
||||
*/
|
||||
public enum UserAction {
|
||||
SEARCHED("searched"),
|
||||
REQUESTED_STREAM("requested stream"),
|
||||
GET_SUGGESTIONS("get suggestions"),
|
||||
SOMETHING_ELSE("something"),
|
||||
USER_REPORT("user report"),
|
||||
LOAD_IMAGE("load image"),
|
||||
UI_ERROR("ui error"),
|
||||
REQUESTED_CHANNEL("requested channel");
|
||||
|
||||
|
||||
private final String message;
|
||||
|
||||
UserAction(String message) {
|
||||
this.message = message;
|
||||
}
|
||||
|
||||
public String getMessage() {
|
||||
return message;
|
||||
}
|
||||
}
|
|
@ -72,9 +72,7 @@ public class NewPipeSettings {
|
|||
public static String getVideoDownloadPath(Context context) {
|
||||
SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(context);
|
||||
final String key = context.getString(R.string.download_path_key);
|
||||
String downloadPath = prefs.getString(key, Environment.DIRECTORY_MOVIES);
|
||||
|
||||
return downloadPath;
|
||||
return prefs.getString(key, Environment.DIRECTORY_MOVIES);
|
||||
}
|
||||
|
||||
public static File getAudioDownloadFolder(Context context) {
|
||||
|
@ -84,9 +82,7 @@ public class NewPipeSettings {
|
|||
public static String getAudioDownloadPath(Context context) {
|
||||
SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(context);
|
||||
final String key = context.getString(R.string.download_path_audio_key);
|
||||
String downloadPath = prefs.getString(key, Environment.DIRECTORY_MUSIC);
|
||||
|
||||
return downloadPath;
|
||||
return prefs.getString(key, Environment.DIRECTORY_MUSIC);
|
||||
}
|
||||
|
||||
private static File getFolder(Context context, int keyID, String defaultDirectoryName) {
|
||||
|
|
|
@ -77,14 +77,14 @@ public class NavigationHelper {
|
|||
public static void openMainFragment(FragmentManager fragmentManager) {
|
||||
ImageLoader.getInstance().clearMemoryCache();
|
||||
fragmentManager.beginTransaction()
|
||||
.setCustomAnimations(android.R.anim.fade_in, android.R.anim.fade_out, android.R.anim.fade_in, android.R.anim.fade_out)
|
||||
.setCustomAnimations(R.anim.custom_fade_in, R.anim.custom_fade_out, R.anim.custom_fade_in, R.anim.custom_fade_out)
|
||||
.replace(R.id.fragment_holder, new MainFragment())
|
||||
.commit();
|
||||
}
|
||||
|
||||
public static void openSearchFragment(FragmentManager fragmentManager, int serviceId, String query) {
|
||||
fragmentManager.beginTransaction()
|
||||
.setCustomAnimations(android.R.anim.fade_in, android.R.anim.fade_out, android.R.anim.fade_in, android.R.anim.fade_out)
|
||||
.setCustomAnimations(R.anim.custom_fade_in, R.anim.custom_fade_out, R.anim.custom_fade_in, R.anim.custom_fade_out)
|
||||
.replace(R.id.fragment_holder, SearchFragment.getInstance(serviceId, query))
|
||||
.addToBackStack(null)
|
||||
.commit();
|
||||
|
@ -109,7 +109,7 @@ public class NavigationHelper {
|
|||
instance.setAutoplay(autoPlay);
|
||||
|
||||
fragmentManager.beginTransaction()
|
||||
.setCustomAnimations(android.R.anim.fade_in, android.R.anim.fade_out, android.R.anim.fade_in, android.R.anim.fade_out)
|
||||
.setCustomAnimations(R.anim.custom_fade_in, R.anim.custom_fade_out, R.anim.custom_fade_in, R.anim.custom_fade_out)
|
||||
.replace(R.id.fragment_holder, instance)
|
||||
.addToBackStack(null)
|
||||
.commit();
|
||||
|
@ -118,7 +118,7 @@ public class NavigationHelper {
|
|||
public static void openChannelFragment(FragmentManager fragmentManager, int serviceId, String url, String name) {
|
||||
if (name == null) name = "";
|
||||
fragmentManager.beginTransaction()
|
||||
.setCustomAnimations(android.R.anim.fade_in, android.R.anim.fade_out, android.R.anim.fade_in, android.R.anim.fade_out)
|
||||
.setCustomAnimations(R.anim.custom_fade_in, R.anim.custom_fade_out, R.anim.custom_fade_in, R.anim.custom_fade_out)
|
||||
.replace(R.id.fragment_holder, ChannelFragment.getInstance(serviceId, url, name))
|
||||
.addToBackStack(null)
|
||||
.commit();
|
||||
|
|
|
@ -12,6 +12,8 @@ import org.schabi.newpipe.report.ErrorActivity;
|
|||
|
||||
import java.io.IOException;
|
||||
|
||||
import static org.schabi.newpipe.report.UserAction.REQUESTED_CHANNEL;
|
||||
|
||||
/**
|
||||
* Extract {@link ChannelInfo} with {@link ChannelExtractor} from the given url of the given service
|
||||
*
|
||||
|
@ -67,7 +69,7 @@ public class ChannelExtractorWorker extends ExtractorWorker {
|
|||
ChannelExtractor extractor = getService().getChannelExtractorInstance(url, pageNumber);
|
||||
channelInfo = ChannelInfo.getInfo(extractor);
|
||||
|
||||
if (!channelInfo.errors.isEmpty()) handleErrorsDuringExtraction(channelInfo.errors, ErrorActivity.REQUESTED_CHANNEL);
|
||||
if (!channelInfo.errors.isEmpty()) handleErrorsDuringExtraction(channelInfo.errors, REQUESTED_CHANNEL);
|
||||
|
||||
if (callback != null && channelInfo != null && !isInterrupted()) getHandler().post(new Runnable() {
|
||||
@Override
|
||||
|
@ -93,7 +95,7 @@ public class ChannelExtractorWorker extends ExtractorWorker {
|
|||
}
|
||||
});
|
||||
} else if (exception instanceof ParsingException || exception instanceof ExtractionException) {
|
||||
ErrorActivity.reportError(getHandler(), getContext(), exception, MainActivity.class, null, ErrorActivity.ErrorInfo.make(ErrorActivity.REQUESTED_CHANNEL, getServiceName(), url, R.string.parsing_error));
|
||||
ErrorActivity.reportError(getHandler(), getContext(), exception, MainActivity.class, null, ErrorActivity.ErrorInfo.make(REQUESTED_CHANNEL, getServiceName(), url, R.string.parsing_error));
|
||||
getHandler().post(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
|
@ -101,7 +103,7 @@ public class ChannelExtractorWorker extends ExtractorWorker {
|
|||
}
|
||||
});
|
||||
} else {
|
||||
ErrorActivity.reportError(getHandler(), getContext(), exception, MainActivity.class, null, ErrorActivity.ErrorInfo.make(ErrorActivity.REQUESTED_CHANNEL, getServiceName(), url, R.string.general_error));
|
||||
ErrorActivity.reportError(getHandler(), getContext(), exception, MainActivity.class, null, ErrorActivity.ErrorInfo.make(REQUESTED_CHANNEL, getServiceName(), url, R.string.general_error));
|
||||
getHandler().post(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
|
|
|
@ -6,6 +6,7 @@ import android.util.Log;
|
|||
import android.view.View;
|
||||
|
||||
import org.schabi.newpipe.report.ErrorActivity;
|
||||
import org.schabi.newpipe.report.UserAction;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
|
@ -59,14 +60,14 @@ public abstract class ExtractorWorker extends AbstractWorker {
|
|||
* @param errorUserAction what action was the user performing during the error.
|
||||
* (One of the {@link ErrorActivity}.REQUEST_* error (message) ids)
|
||||
*/
|
||||
protected void handleErrorsDuringExtraction(List<Throwable> errorsList, int errorUserAction){
|
||||
protected void handleErrorsDuringExtraction(List<Throwable> errorsList, UserAction errorUserAction){
|
||||
String errorString = "<error id>";
|
||||
switch (errorUserAction) {
|
||||
case ErrorActivity.REQUESTED_STREAM:
|
||||
errorString= ErrorActivity.REQUESTED_STREAM_STRING;
|
||||
case REQUESTED_STREAM:
|
||||
errorString= errorUserAction.getMessage();
|
||||
break;
|
||||
case ErrorActivity.REQUESTED_CHANNEL:
|
||||
errorString= ErrorActivity.REQUESTED_CHANNEL_STRING;
|
||||
case REQUESTED_CHANNEL:
|
||||
errorString= errorUserAction.getMessage();
|
||||
break;
|
||||
}
|
||||
|
||||
|
|
|
@ -13,10 +13,13 @@ import org.schabi.newpipe.extractor.exceptions.ReCaptchaException;
|
|||
import org.schabi.newpipe.extractor.search.SearchEngine;
|
||||
import org.schabi.newpipe.extractor.search.SearchResult;
|
||||
import org.schabi.newpipe.report.ErrorActivity;
|
||||
import org.schabi.newpipe.report.UserAction;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.EnumSet;
|
||||
|
||||
import static org.schabi.newpipe.report.UserAction.*;
|
||||
|
||||
/**
|
||||
* Return list of results based on a query
|
||||
*
|
||||
|
@ -106,7 +109,7 @@ public class SearchWorker extends AbstractWorker {
|
|||
});
|
||||
} else if (exception instanceof ExtractionException) {
|
||||
View rootView = getContext() instanceof Activity ? ((Activity) getContext()).findViewById(android.R.id.content) : null;
|
||||
ErrorActivity.reportError(getHandler(), getContext(), exception, null, rootView, ErrorActivity.ErrorInfo.make(ErrorActivity.SEARCHED, getServiceName(), query, R.string.parsing_error));
|
||||
ErrorActivity.reportError(getHandler(), getContext(), exception, null, rootView, ErrorActivity.ErrorInfo.make(SEARCHED, getServiceName(), query, R.string.parsing_error));
|
||||
getHandler().post(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
|
@ -115,7 +118,7 @@ public class SearchWorker extends AbstractWorker {
|
|||
});
|
||||
} else {
|
||||
View rootView = getContext() instanceof Activity ? ((Activity) getContext()).findViewById(android.R.id.content) : null;
|
||||
ErrorActivity.reportError(getHandler(), getContext(), exception, null, rootView, ErrorActivity.ErrorInfo.make(ErrorActivity.SEARCHED, getServiceName(), query, R.string.general_error));
|
||||
ErrorActivity.reportError(getHandler(), getContext(), exception, null, rootView, ErrorActivity.ErrorInfo.make(SEARCHED, getServiceName(), query, R.string.general_error));
|
||||
getHandler().post(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
|
|
|
@ -10,9 +10,12 @@ import org.schabi.newpipe.extractor.services.youtube.YoutubeStreamExtractor;
|
|||
import org.schabi.newpipe.extractor.stream_info.StreamExtractor;
|
||||
import org.schabi.newpipe.extractor.stream_info.StreamInfo;
|
||||
import org.schabi.newpipe.report.ErrorActivity;
|
||||
import org.schabi.newpipe.report.UserAction;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
import static org.schabi.newpipe.report.UserAction.*;
|
||||
|
||||
/**
|
||||
* Extract {@link StreamInfo} with {@link StreamExtractor} from the given url of the given service
|
||||
*
|
||||
|
@ -66,7 +69,7 @@ public class StreamExtractorWorker extends ExtractorWorker {
|
|||
StreamExtractor streamExtractor = getService().getExtractorInstance(url);
|
||||
streamInfo = StreamInfo.getVideoInfo(streamExtractor);
|
||||
|
||||
if (streamInfo != null && !streamInfo.errors.isEmpty()) handleErrorsDuringExtraction(streamInfo.errors, ErrorActivity.REQUESTED_STREAM);
|
||||
if (streamInfo != null && !streamInfo.errors.isEmpty()) handleErrorsDuringExtraction(streamInfo.errors, REQUESTED_STREAM);
|
||||
|
||||
if (callback != null && getHandler() != null && streamInfo != null && !isInterrupted()) getHandler().post(new Runnable() {
|
||||
@Override
|
||||
|
@ -121,7 +124,7 @@ public class StreamExtractorWorker extends ExtractorWorker {
|
|||
});
|
||||
} else if (exception instanceof YoutubeStreamExtractor.DecryptException) {
|
||||
// custom service related exceptions
|
||||
ErrorActivity.reportError(getHandler(), getContext(), exception, MainActivity.class, null, ErrorActivity.ErrorInfo.make(ErrorActivity.REQUESTED_STREAM, getServiceName(), url, R.string.youtube_signature_decryption_error));
|
||||
ErrorActivity.reportError(getHandler(), getContext(), exception, MainActivity.class, null, ErrorActivity.ErrorInfo.make(REQUESTED_STREAM, getServiceName(), url, R.string.youtube_signature_decryption_error));
|
||||
getHandler().post(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
|
@ -131,9 +134,9 @@ public class StreamExtractorWorker extends ExtractorWorker {
|
|||
} else if (exception instanceof StreamInfo.StreamExctractException) {
|
||||
if (!streamInfo.errors.isEmpty()) {
|
||||
// !!! if this case ever kicks in someone gets kicked out !!!
|
||||
ErrorActivity.reportError(getHandler(), getContext(), exception, MainActivity.class, null, ErrorActivity.ErrorInfo.make(ErrorActivity.REQUESTED_STREAM, getServiceName(), url, R.string.could_not_get_stream));
|
||||
ErrorActivity.reportError(getHandler(), getContext(), exception, MainActivity.class, null, ErrorActivity.ErrorInfo.make(REQUESTED_STREAM, getServiceName(), url, R.string.could_not_get_stream));
|
||||
} else {
|
||||
ErrorActivity.reportError(getHandler(), getContext(), streamInfo.errors, MainActivity.class, null, ErrorActivity.ErrorInfo.make(ErrorActivity.REQUESTED_STREAM, getServiceName(), url, R.string.could_not_get_stream));
|
||||
ErrorActivity.reportError(getHandler(), getContext(), streamInfo.errors, MainActivity.class, null, ErrorActivity.ErrorInfo.make(REQUESTED_STREAM, getServiceName(), url, R.string.could_not_get_stream));
|
||||
}
|
||||
|
||||
getHandler().post(new Runnable() {
|
||||
|
@ -143,7 +146,7 @@ public class StreamExtractorWorker extends ExtractorWorker {
|
|||
}
|
||||
});
|
||||
} else if (exception instanceof ParsingException) {
|
||||
ErrorActivity.reportError(getHandler(), getContext(), exception, MainActivity.class, null, ErrorActivity.ErrorInfo.make(ErrorActivity.REQUESTED_STREAM, getServiceName(), url, R.string.parsing_error));
|
||||
ErrorActivity.reportError(getHandler(), getContext(), exception, MainActivity.class, null, ErrorActivity.ErrorInfo.make(REQUESTED_STREAM, getServiceName(), url, R.string.parsing_error));
|
||||
getHandler().post(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
|
@ -151,7 +154,7 @@ public class StreamExtractorWorker extends ExtractorWorker {
|
|||
}
|
||||
});
|
||||
} else {
|
||||
ErrorActivity.reportError(getHandler(), getContext(), exception, MainActivity.class, null, ErrorActivity.ErrorInfo.make(ErrorActivity.REQUESTED_STREAM, getServiceName(), url, R.string.general_error));
|
||||
ErrorActivity.reportError(getHandler(), getContext(), exception, MainActivity.class, null, ErrorActivity.ErrorInfo.make(REQUESTED_STREAM, getServiceName(), url, R.string.general_error));
|
||||
getHandler().post(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
|
|
|
@ -11,10 +11,13 @@ import org.schabi.newpipe.R;
|
|||
import org.schabi.newpipe.extractor.SuggestionExtractor;
|
||||
import org.schabi.newpipe.extractor.exceptions.ExtractionException;
|
||||
import org.schabi.newpipe.report.ErrorActivity;
|
||||
import org.schabi.newpipe.report.UserAction;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.List;
|
||||
|
||||
import static org.schabi.newpipe.report.UserAction.*;
|
||||
|
||||
/**
|
||||
* Worker that get suggestions based on the query
|
||||
*
|
||||
|
@ -79,7 +82,7 @@ public class SuggestionWorker extends AbstractWorker {
|
|||
|
||||
if (exception instanceof ExtractionException) {
|
||||
View rootView = getContext() instanceof Activity ? ((Activity) getContext()).findViewById(android.R.id.content) : null;
|
||||
ErrorActivity.reportError(getHandler(), getContext(), exception, null, rootView, ErrorActivity.ErrorInfo.make(ErrorActivity.GET_SUGGESTIONS, getServiceName(), query, R.string.parsing_error));
|
||||
ErrorActivity.reportError(getHandler(), getContext(), exception, null, rootView, ErrorActivity.ErrorInfo.make(GET_SUGGESTIONS, getServiceName(), query, R.string.parsing_error));
|
||||
getHandler().post(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
|
@ -95,7 +98,7 @@ public class SuggestionWorker extends AbstractWorker {
|
|||
});
|
||||
} else {
|
||||
View rootView = getContext() instanceof Activity ? ((Activity) getContext()).findViewById(android.R.id.content) : null;
|
||||
ErrorActivity.reportError(getHandler(), getContext(), exception, null, rootView, ErrorActivity.ErrorInfo.make(ErrorActivity.GET_SUGGESTIONS, getServiceName(), query, R.string.general_error));
|
||||
ErrorActivity.reportError(getHandler(), getContext(), exception, null, rootView, ErrorActivity.ErrorInfo.make(GET_SUGGESTIONS, getServiceName(), query, R.string.general_error));
|
||||
getHandler().post(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
|
|
|
@ -9,12 +9,14 @@ public interface DownloadDataSource {
|
|||
|
||||
/**
|
||||
* Load all missions
|
||||
*
|
||||
* @return a list of download missions
|
||||
*/
|
||||
List<DownloadMission> loadMissions();
|
||||
|
||||
/**
|
||||
* Add a downlaod mission to the storage
|
||||
* Add a download mission to the storage
|
||||
*
|
||||
* @param downloadMission the download mission to add
|
||||
* @return the identifier of the mission
|
||||
*/
|
||||
|
@ -22,6 +24,7 @@ public interface DownloadDataSource {
|
|||
|
||||
/**
|
||||
* Update a download mission which exists in the storage
|
||||
*
|
||||
* @param downloadMission the download mission to update
|
||||
* @throws IllegalArgumentException if the mission was not added to storage
|
||||
*/
|
||||
|
@ -30,6 +33,7 @@ public interface DownloadDataSource {
|
|||
|
||||
/**
|
||||
* Delete a download mission
|
||||
*
|
||||
* @param downloadMission the mission to delete
|
||||
*/
|
||||
void deleteMission(DownloadMission downloadMission);
|
||||
|
|
|
@ -1,11 +1,11 @@
|
|||
package us.shandian.giga.get;
|
||||
|
||||
public interface DownloadManager
|
||||
{
|
||||
public interface DownloadManager {
|
||||
int BLOCK_SIZE = 512 * 1024;
|
||||
|
||||
/**
|
||||
* Start a new download mission
|
||||
*
|
||||
* @param url the url to download
|
||||
* @param location the location
|
||||
* @param name the name of the file to create
|
||||
|
@ -16,24 +16,28 @@ public interface DownloadManager
|
|||
|
||||
/**
|
||||
* Resume the execution of a download mission.
|
||||
*
|
||||
* @param id the identifier of the mission to resume.
|
||||
*/
|
||||
void resumeMission(int id);
|
||||
|
||||
/**
|
||||
* Pause the execution of a download mission.
|
||||
*
|
||||
* @param id the identifier of the mission to pause.
|
||||
*/
|
||||
void pauseMission(int id);
|
||||
|
||||
/**
|
||||
* Deletes the mission from the downloaded list but keeps the downloaded file.
|
||||
*
|
||||
* @param id The mission identifier
|
||||
*/
|
||||
void deleteMission(int id);
|
||||
|
||||
/**
|
||||
* Get the download mission by its identifier
|
||||
*
|
||||
* @param id the identifier of the download mission
|
||||
* @return the download mission or null if the mission doesn't exist
|
||||
*/
|
||||
|
@ -41,6 +45,7 @@ public interface DownloadManager
|
|||
|
||||
/**
|
||||
* Get the number of download missions.
|
||||
*
|
||||
* @return the number of download missions.
|
||||
*/
|
||||
int getCount();
|
||||
|
|
|
@ -18,10 +18,10 @@ import java.util.Comparator;
|
|||
import java.util.List;
|
||||
|
||||
import us.shandian.giga.util.Utility;
|
||||
|
||||
import static org.schabi.newpipe.BuildConfig.DEBUG;
|
||||
|
||||
public class DownloadManagerImpl implements DownloadManager
|
||||
{
|
||||
public class DownloadManagerImpl implements DownloadManager {
|
||||
private static final String TAG = DownloadManagerImpl.class.getSimpleName();
|
||||
private final DownloadDataSource mDownloadDataSource;
|
||||
|
||||
|
@ -29,6 +29,7 @@ public class DownloadManagerImpl implements DownloadManager
|
|||
|
||||
/**
|
||||
* Create a new instance
|
||||
*
|
||||
* @param searchLocations the directories to search for unfinished downloads
|
||||
* @param downloadDataSource the data source for finished downloads
|
||||
*/
|
||||
|
@ -205,11 +206,14 @@ public class DownloadManagerImpl implements DownloadManager
|
|||
|
||||
/**
|
||||
* Get a mission by its location and name
|
||||
*
|
||||
* @param location the location
|
||||
* @param name the name
|
||||
* @return the mission or null if no such mission exists
|
||||
*/
|
||||
private @Nullable DownloadMission getMissionByLocation(String location, String name) {
|
||||
private
|
||||
@Nullable
|
||||
DownloadMission getMissionByLocation(String location, String name) {
|
||||
for (DownloadMission mission : mMissions) {
|
||||
if (location.equals(mission.location) && name.equals(mission.name)) {
|
||||
return mission;
|
||||
|
@ -220,7 +224,7 @@ public class DownloadManagerImpl implements DownloadManager
|
|||
|
||||
/**
|
||||
* Splits the filename into name and extension
|
||||
*
|
||||
* <p>
|
||||
* Dots are ignored if they appear: not at all, at the beginning of the file,
|
||||
* at the end of the file
|
||||
*
|
||||
|
@ -238,8 +242,9 @@ public class DownloadManagerImpl implements DownloadManager
|
|||
|
||||
/**
|
||||
* Generates a unique file name.
|
||||
*
|
||||
* <p>
|
||||
* e.g. "myname (1).txt" if the name "myname.txt" exists.
|
||||
*
|
||||
* @param location the location (to check for existing files)
|
||||
* @param name the name of the file
|
||||
* @return the unique file name
|
||||
|
|
|
@ -18,15 +18,16 @@ import us.shandian.giga.util.Utility;
|
|||
|
||||
import static org.schabi.newpipe.BuildConfig.DEBUG;
|
||||
|
||||
public class DownloadMission
|
||||
{
|
||||
public class DownloadMission {
|
||||
private static final String TAG = DownloadMission.class.getSimpleName();
|
||||
|
||||
public interface MissionListener {
|
||||
HashMap<MissionListener, Handler> handlerStore = new HashMap<>();
|
||||
|
||||
void onProgressUpdate(DownloadMission downloadMission, long done, long total);
|
||||
|
||||
void onFinish(DownloadMission downloadMission);
|
||||
|
||||
void onError(DownloadMission downloadMission, int errCode);
|
||||
}
|
||||
|
||||
|
@ -104,6 +105,7 @@ public class DownloadMission
|
|||
|
||||
/**
|
||||
* Check if a block is reserved
|
||||
*
|
||||
* @param block the block identifier
|
||||
* @return true if the block is reserved and false if otherwise
|
||||
*/
|
||||
|
@ -121,6 +123,7 @@ public class DownloadMission
|
|||
|
||||
/**
|
||||
* Set the download position of the file
|
||||
*
|
||||
* @param threadId the identifier of the thread
|
||||
* @param position the download position of the thread
|
||||
*/
|
||||
|
@ -130,6 +133,7 @@ public class DownloadMission
|
|||
|
||||
/**
|
||||
* Get the position of a thread
|
||||
*
|
||||
* @param threadId the identifier of the thread
|
||||
* @return the position for the thread
|
||||
*/
|
||||
|
@ -234,8 +238,7 @@ public class DownloadMission
|
|||
for (Iterator<WeakReference<MissionListener>> iterator = mListeners.iterator();
|
||||
iterator.hasNext(); ) {
|
||||
WeakReference<MissionListener> weakRef = iterator.next();
|
||||
if (listener!=null && listener == weakRef.get())
|
||||
{
|
||||
if (listener != null && listener == weakRef.get()) {
|
||||
iterator.remove();
|
||||
}
|
||||
}
|
||||
|
@ -315,6 +318,7 @@ public class DownloadMission
|
|||
|
||||
/**
|
||||
* Get the path of the meta file
|
||||
*
|
||||
* @return the path to the meta file
|
||||
*/
|
||||
private String getMetaFilename() {
|
||||
|
|
|
@ -13,8 +13,7 @@ import static org.schabi.newpipe.BuildConfig.DEBUG;
|
|||
* Runnable to download blocks of a file until the file is completely downloaded,
|
||||
* an error occurs or the process is stopped.
|
||||
*/
|
||||
public class DownloadRunnable implements Runnable
|
||||
{
|
||||
public class DownloadRunnable implements Runnable {
|
||||
private static final String TAG = DownloadRunnable.class.getSimpleName();
|
||||
|
||||
private final DownloadMission mMission;
|
||||
|
|
|
@ -6,8 +6,7 @@ import java.net.HttpURLConnection;
|
|||
import java.net.URL;
|
||||
|
||||
// Single-threaded fallback mode
|
||||
public class DownloadRunnableFallback implements Runnable
|
||||
{
|
||||
public class DownloadRunnableFallback implements Runnable {
|
||||
private final DownloadMission mMission;
|
||||
//private int mId;
|
||||
|
||||
|
|
|
@ -64,6 +64,7 @@ public class DownloadMissionSQLiteHelper extends SQLiteOpenHelper {
|
|||
|
||||
/**
|
||||
* Returns all values of the download mission as ContentValues.
|
||||
*
|
||||
* @param downloadMission the download mission
|
||||
* @return the content values
|
||||
*/
|
||||
|
|
|
@ -6,7 +6,6 @@ import android.app.PendingIntent;
|
|||
import android.app.Service;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.content.ServiceConnection;
|
||||
import android.graphics.drawable.BitmapDrawable;
|
||||
import android.graphics.drawable.Drawable;
|
||||
import android.net.Uri;
|
||||
|
@ -16,6 +15,7 @@ import android.os.HandlerThread;
|
|||
import android.os.IBinder;
|
||||
import android.os.Message;
|
||||
import android.support.v4.app.NotificationCompat.Builder;
|
||||
import android.support.v4.content.ContextCompat;
|
||||
import android.support.v4.content.PermissionChecker;
|
||||
import android.util.Log;
|
||||
import android.widget.Toast;
|
||||
|
@ -34,8 +34,7 @@ import us.shandian.giga.get.sqlite.SQLiteDownloadDataSource;
|
|||
|
||||
import static org.schabi.newpipe.BuildConfig.DEBUG;
|
||||
|
||||
public class DownloadManagerService extends Service
|
||||
{
|
||||
public class DownloadManagerService extends Service {
|
||||
|
||||
private static final String TAG = DownloadManagerService.class.getSimpleName();
|
||||
|
||||
|
@ -58,7 +57,6 @@ public class DownloadManagerService extends Service
|
|||
private DownloadDataSource mDataSource;
|
||||
|
||||
|
||||
|
||||
private MissionListener missionListener = new MissionListener();
|
||||
|
||||
|
||||
|
@ -95,7 +93,7 @@ public class DownloadManagerService extends Service
|
|||
i.setAction(Intent.ACTION_MAIN);
|
||||
i.setClass(this, DownloadActivity.class);
|
||||
|
||||
Drawable icon = this.getResources().getDrawable(R.mipmap.ic_launcher);
|
||||
Drawable icon = ContextCompat.getDrawable(this, R.mipmap.ic_launcher);
|
||||
|
||||
Builder builder = new Builder(this)
|
||||
.setContentIntent(PendingIntent.getActivity(this, 0, i, 0))
|
||||
|
@ -227,7 +225,7 @@ public class DownloadManagerService extends Service
|
|||
}
|
||||
|
||||
|
||||
class MissionListener implements DownloadMission.MissionListener {
|
||||
private class MissionListener implements DownloadMission.MissionListener {
|
||||
@Override
|
||||
public void onProgressUpdate(DownloadMission downloadMission, long done, long total) {
|
||||
long now = System.currentTimeMillis();
|
||||
|
|
|
@ -7,6 +7,8 @@ import android.net.Uri;
|
|||
import android.os.AsyncTask;
|
||||
import android.os.Build;
|
||||
import android.support.v4.content.FileProvider;
|
||||
import android.support.v4.view.ViewCompat;
|
||||
import android.support.v7.widget.RecyclerView;
|
||||
import android.util.Log;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.Menu;
|
||||
|
@ -18,14 +20,13 @@ import android.widget.ImageView;
|
|||
import android.widget.PopupMenu;
|
||||
import android.widget.TextView;
|
||||
|
||||
import android.support.v7.widget.RecyclerView;
|
||||
import org.schabi.newpipe.R;
|
||||
|
||||
import java.io.File;
|
||||
import java.util.HashMap;
|
||||
import java.util.Locale;
|
||||
import java.util.Map;
|
||||
|
||||
import org.schabi.newpipe.R;
|
||||
import us.shandian.giga.get.DownloadManager;
|
||||
import us.shandian.giga.get.DownloadMission;
|
||||
import us.shandian.giga.service.DownloadManagerService;
|
||||
|
@ -35,8 +36,7 @@ import us.shandian.giga.util.Utility;
|
|||
import static android.content.Intent.FLAG_GRANT_PREFIX_URI_PERMISSION;
|
||||
import static android.content.Intent.FLAG_GRANT_READ_URI_PERMISSION;
|
||||
|
||||
public class MissionAdapter extends RecyclerView.Adapter<MissionAdapter.ViewHolder>
|
||||
{
|
||||
public class MissionAdapter extends RecyclerView.Adapter<MissionAdapter.ViewHolder> {
|
||||
private static final Map<Integer, String> ALGORITHMS = new HashMap<>();
|
||||
private static final String TAG = "MissionAdapter";
|
||||
|
||||
|
@ -108,7 +108,7 @@ public class MissionAdapter extends RecyclerView.Adapter<MissionAdapter.ViewHold
|
|||
h.size.setText(Utility.formatBytes(ms.length));
|
||||
|
||||
h.progress = new ProgressDrawable(mContext, Utility.getBackgroundForFileType(type), Utility.getForegroundForFileType(type));
|
||||
h.bkg.setBackgroundDrawable(h.progress);
|
||||
ViewCompat.setBackground(h.bkg, h.progress);
|
||||
|
||||
h.observer = new MissionObserver(this, h);
|
||||
ms.addListener(h.observer);
|
||||
|
@ -285,33 +285,6 @@ public class MissionAdapter extends RecyclerView.Adapter<MissionAdapter.ViewHold
|
|||
mContext.startActivity(intent);
|
||||
}
|
||||
|
||||
private class ChecksumTask extends AsyncTask<String, Void, String> {
|
||||
ProgressDialog prog;
|
||||
|
||||
@Override
|
||||
protected void onPreExecute() {
|
||||
super.onPreExecute();
|
||||
|
||||
// Create dialog
|
||||
prog = new ProgressDialog(mContext);
|
||||
prog.setCancelable(false);
|
||||
prog.setMessage(mContext.getString(R.string.msg_wait));
|
||||
prog.show();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String doInBackground(String... params) {
|
||||
return Utility.checksum(params[0], params[1]);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onPostExecute(String result) {
|
||||
super.onPostExecute(result);
|
||||
prog.dismiss();
|
||||
Utility.copyToClipboard(mContext, result);
|
||||
}
|
||||
}
|
||||
|
||||
static class ViewHolder extends RecyclerView.ViewHolder {
|
||||
public DownloadMission mission;
|
||||
public int position;
|
||||
|
@ -332,12 +305,12 @@ public class MissionAdapter extends RecyclerView.Adapter<MissionAdapter.ViewHold
|
|||
public ViewHolder(View v) {
|
||||
super(v);
|
||||
|
||||
status = Utility.findViewById(v, R.id.item_status);
|
||||
icon = Utility.findViewById(v, R.id.item_icon);
|
||||
name = Utility.findViewById(v, R.id.item_name);
|
||||
size = Utility.findViewById(v, R.id.item_size);
|
||||
bkg = Utility.findViewById(v, R.id.item_bkg);
|
||||
menu = Utility.findViewById(v, R.id.item_more);
|
||||
status = (TextView) v.findViewById(R.id.item_status);
|
||||
icon = (ImageView) v.findViewById(R.id.item_icon);
|
||||
name = (TextView) v.findViewById(R.id.item_name);
|
||||
size = (TextView) v.findViewById(R.id.item_size);
|
||||
bkg = v.findViewById(R.id.item_bkg);
|
||||
menu = (ImageView) v.findViewById(R.id.item_more);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -372,4 +345,31 @@ public class MissionAdapter extends RecyclerView.Adapter<MissionAdapter.ViewHold
|
|||
}
|
||||
|
||||
}
|
||||
|
||||
private class ChecksumTask extends AsyncTask<String, Void, String> {
|
||||
ProgressDialog prog;
|
||||
|
||||
@Override
|
||||
protected void onPreExecute() {
|
||||
super.onPreExecute();
|
||||
|
||||
// Create dialog
|
||||
prog = new ProgressDialog(mContext);
|
||||
prog.setCancelable(false);
|
||||
prog.setMessage(mContext.getString(R.string.msg_wait));
|
||||
prog.show();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String doInBackground(String... params) {
|
||||
return Utility.checksum(params[0], params[1]);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onPostExecute(String result) {
|
||||
super.onPostExecute(result);
|
||||
prog.dismiss();
|
||||
Utility.copyToClipboard(mContext, result);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -6,14 +6,16 @@ import android.graphics.ColorFilter;
|
|||
import android.graphics.Paint;
|
||||
import android.graphics.PixelFormat;
|
||||
import android.graphics.drawable.Drawable;
|
||||
import android.support.annotation.ColorRes;
|
||||
import android.support.annotation.NonNull;
|
||||
import android.support.v4.content.ContextCompat;
|
||||
|
||||
public class ProgressDrawable extends Drawable
|
||||
{
|
||||
public class ProgressDrawable extends Drawable {
|
||||
private float mProgress;
|
||||
private int mBackgroundColor, mForegroundColor;
|
||||
|
||||
public ProgressDrawable(Context context, int background, int foreground) {
|
||||
this(context.getResources().getColor(background), context.getResources().getColor(foreground));
|
||||
public ProgressDrawable(Context context, @ColorRes int background, @ColorRes int foreground) {
|
||||
this(ContextCompat.getColor(context, background), ContextCompat.getColor(context, foreground));
|
||||
}
|
||||
|
||||
public ProgressDrawable(int background, int foreground) {
|
||||
|
@ -27,7 +29,7 @@ public class ProgressDrawable extends Drawable
|
|||
}
|
||||
|
||||
@Override
|
||||
public void draw(Canvas canvas) {
|
||||
public void draw(@NonNull Canvas canvas) {
|
||||
int width = canvas.getWidth();
|
||||
int height = canvas.getHeight();
|
||||
|
||||
|
|
|
@ -1,15 +1,12 @@
|
|||
package us.shandian.giga.ui.common;
|
||||
|
||||
import android.os.Bundle;
|
||||
|
||||
import android.support.v7.app.ActionBarActivity;
|
||||
import android.support.v7.widget.Toolbar;
|
||||
|
||||
import org.schabi.newpipe.R;
|
||||
import us.shandian.giga.util.Utility;
|
||||
|
||||
public abstract class ToolbarActivity extends ActionBarActivity
|
||||
{
|
||||
public abstract class ToolbarActivity extends ActionBarActivity {
|
||||
protected Toolbar mToolbar;
|
||||
|
||||
@Override
|
||||
|
@ -17,7 +14,7 @@ public abstract class ToolbarActivity extends ActionBarActivity
|
|||
super.onCreate(savedInstanceState);
|
||||
setContentView(getLayoutResource());
|
||||
|
||||
mToolbar = Utility.findViewById(this, R.id.toolbar);
|
||||
mToolbar = (Toolbar) this.findViewById(R.id.toolbar);
|
||||
|
||||
setSupportActionBar(mToolbar);
|
||||
}
|
||||
|
|
|
@ -3,8 +3,7 @@ package us.shandian.giga.ui.fragment;
|
|||
import us.shandian.giga.get.DownloadManager;
|
||||
import us.shandian.giga.service.DownloadManagerService;
|
||||
|
||||
public class AllMissionsFragment extends MissionsFragment
|
||||
{
|
||||
public class AllMissionsFragment extends MissionsFragment {
|
||||
|
||||
@Override
|
||||
protected DownloadManager setupDownloadManager(DownloadManagerService.DMBinder binder) {
|
||||
|
|
|
@ -23,10 +23,8 @@ import org.schabi.newpipe.R;
|
|||
import us.shandian.giga.get.DownloadManager;
|
||||
import us.shandian.giga.service.DownloadManagerService;
|
||||
import us.shandian.giga.ui.adapter.MissionAdapter;
|
||||
import us.shandian.giga.util.Utility;
|
||||
|
||||
public abstract class MissionsFragment extends Fragment
|
||||
{
|
||||
public abstract class MissionsFragment extends Fragment {
|
||||
private DownloadManager mManager;
|
||||
private DownloadManagerService.DMBinder mBinder;
|
||||
|
||||
|
@ -70,7 +68,7 @@ public abstract class MissionsFragment extends Fragment
|
|||
getActivity().bindService(i, mConnection, Context.BIND_AUTO_CREATE);
|
||||
|
||||
// Views
|
||||
mList = Utility.findViewById(v, R.id.mission_recycler);
|
||||
mList = (RecyclerView) v.findViewById(R.id.mission_recycler);
|
||||
|
||||
// Init
|
||||
mGridManager = new GridLayoutManager(getActivity(), 2);
|
||||
|
@ -82,7 +80,9 @@ public abstract class MissionsFragment extends Fragment
|
|||
return v;
|
||||
}
|
||||
|
||||
/** Added in API level 23. */
|
||||
/**
|
||||
* Added in API level 23.
|
||||
*/
|
||||
@Override
|
||||
public void onAttach(Context activity) {
|
||||
super.onAttach(activity);
|
||||
|
@ -93,8 +93,10 @@ public abstract class MissionsFragment extends Fragment
|
|||
mActivity = activity;
|
||||
}
|
||||
|
||||
/** deprecated in API level 23,
|
||||
* but must remain to allow compatibility with api<23 */
|
||||
/**
|
||||
* deprecated in API level 23,
|
||||
* but must remain to allow compatibility with api<23
|
||||
*/
|
||||
@Override
|
||||
public void onAttach(Activity activity) {
|
||||
super.onAttach(activity);
|
||||
|
|
|
@ -9,8 +9,7 @@ import java.io.File;
|
|||
import java.io.PrintWriter;
|
||||
|
||||
//todo: replace this by using the internal crash handler of newpipe
|
||||
public class CrashHandler implements Thread.UncaughtExceptionHandler
|
||||
{
|
||||
public class CrashHandler implements Thread.UncaughtExceptionHandler {
|
||||
public static final String CRASH_DIR = Environment.getExternalStorageDirectory().getPath() + "/GigaCrash/";
|
||||
public static final String CRASH_LOG = CRASH_DIR + "last_crash.log";
|
||||
public static final String CRASH_TAG = CRASH_DIR + ".crashed";
|
||||
|
|
|
@ -1,32 +1,27 @@
|
|||
package us.shandian.giga.util;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.content.ClipboardManager;
|
||||
import android.content.ClipData;
|
||||
import android.content.ClipboardManager;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.view.View;
|
||||
import android.support.annotation.ColorRes;
|
||||
import android.support.annotation.DrawableRes;
|
||||
import android.support.annotation.Nullable;
|
||||
import android.widget.Toast;
|
||||
|
||||
import org.schabi.newpipe.R;
|
||||
|
||||
import java.io.BufferedInputStream;
|
||||
import java.io.File;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.FileNotFoundException;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.security.MessageDigest;
|
||||
import java.security.NoSuchAlgorithmException;
|
||||
|
||||
import org.schabi.newpipe.settings.NewPipeSettings;
|
||||
import org.schabi.newpipe.R;
|
||||
public class Utility {
|
||||
|
||||
import com.nononsenseapps.filepicker.FilePickerActivity;
|
||||
import com.nononsenseapps.filepicker.AbstractFilePickerFragment;
|
||||
|
||||
public class Utility
|
||||
{
|
||||
|
||||
public static enum FileType {
|
||||
public enum FileType {
|
||||
VIDEO,
|
||||
MUSIC,
|
||||
UNKNOWN
|
||||
|
@ -109,30 +104,25 @@ public class Utility
|
|||
}
|
||||
}
|
||||
|
||||
public static <T> T findViewById(View v, int id) {
|
||||
return (T) v.findViewById(id);
|
||||
}
|
||||
|
||||
public static <T> T findViewById(Activity activity, int id) {
|
||||
return (T) activity.findViewById(id);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public static String getFileExt(String url) {
|
||||
if (url.indexOf("?")>-1) {
|
||||
url = url.substring(0,url.indexOf("?"));
|
||||
int index;
|
||||
if ((index = url.indexOf("?")) > -1) {
|
||||
url = url.substring(0, index);
|
||||
}
|
||||
if (url.lastIndexOf(".") == -1) {
|
||||
|
||||
index = url.lastIndexOf(".");
|
||||
if (index == -1) {
|
||||
return null;
|
||||
} else {
|
||||
String ext = url.substring(url.lastIndexOf(".") );
|
||||
if (ext.indexOf("%")>-1) {
|
||||
ext = ext.substring(0,ext.indexOf("%"));
|
||||
String ext = url.substring(index);
|
||||
if ((index = ext.indexOf("%")) > -1) {
|
||||
ext = ext.substring(0, index);
|
||||
}
|
||||
if (ext.indexOf("/")>-1) {
|
||||
ext = ext.substring(0,ext.indexOf("/"));
|
||||
if ((index = ext.indexOf("/")) > -1) {
|
||||
ext = ext.substring(0, index);
|
||||
}
|
||||
return ext.toLowerCase();
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -147,16 +137,7 @@ public class Utility
|
|||
}
|
||||
}
|
||||
|
||||
public static Boolean isMusicFile(String file)
|
||||
{
|
||||
return Utility.getFileType(file) == FileType.MUSIC;
|
||||
}
|
||||
|
||||
public static Boolean isVideoFile(String file)
|
||||
{
|
||||
return Utility.getFileType(file) == FileType.VIDEO;
|
||||
}
|
||||
|
||||
@ColorRes
|
||||
public static int getBackgroundForFileType(FileType type) {
|
||||
switch (type) {
|
||||
case MUSIC:
|
||||
|
@ -168,6 +149,7 @@ public class Utility
|
|||
}
|
||||
}
|
||||
|
||||
@ColorRes
|
||||
public static int getForegroundForFileType(FileType type) {
|
||||
switch (type) {
|
||||
case MUSIC:
|
||||
|
@ -179,6 +161,7 @@ public class Utility
|
|||
}
|
||||
}
|
||||
|
||||
@DrawableRes
|
||||
public static int getIconForFileType(FileType type) {
|
||||
switch (type) {
|
||||
case MUSIC:
|
||||
|
@ -190,24 +173,6 @@ public class Utility
|
|||
}
|
||||
}
|
||||
|
||||
public static boolean isDirectoryAvailble(String path) {
|
||||
File dir = new File(path);
|
||||
return dir.exists() && dir.isDirectory();
|
||||
}
|
||||
|
||||
public static boolean isDownloadDirectoryAvailble(Context context) {
|
||||
return isDirectoryAvailble(NewPipeSettings.getVideoDownloadPath(context));
|
||||
}
|
||||
|
||||
public static void showDirectoryChooser(Activity activity) {
|
||||
Intent i = new Intent(activity, FilePickerActivity.class);
|
||||
i.setAction(Intent.ACTION_GET_CONTENT);
|
||||
i.putExtra(FilePickerActivity.EXTRA_ALLOW_MULTIPLE, false);
|
||||
i.putExtra(FilePickerActivity.EXTRA_ALLOW_CREATE_DIR, true);
|
||||
i.putExtra(FilePickerActivity.EXTRA_MODE, AbstractFilePickerFragment.MODE_DIR);
|
||||
activity.startActivityForResult(i, 233);
|
||||
}
|
||||
|
||||
public static void copyToClipboard(Context context, String str) {
|
||||
ClipboardManager cm = (ClipboardManager) context.getSystemService(Context.CLIPBOARD_SERVICE);
|
||||
cm.setPrimaryClip(ClipData.newPlainText("text", str));
|
||||
|
|
|
@ -0,0 +1,6 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<alpha xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:duration="200"
|
||||
android:fromAlpha="0.0"
|
||||
android:interpolator="@android:interpolator/accelerate_decelerate"
|
||||
android:toAlpha="1.0"/>
|
|
@ -0,0 +1,6 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<alpha xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:duration="200"
|
||||
android:fromAlpha="1.0"
|
||||
android:interpolator="@android:interpolator/accelerate_decelerate"
|
||||
android:toAlpha="0.0"/>
|
|
@ -1,5 +1,5 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<RelativeLayout
|
||||
<FrameLayout
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:layout_width="match_parent"
|
||||
|
@ -15,4 +15,4 @@
|
|||
|
||||
<include layout="@layout/toolbar_layout"/>
|
||||
|
||||
</RelativeLayout>
|
||||
</FrameLayout>
|
||||
|
|
|
@ -4,11 +4,10 @@
|
|||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:id="@+id/itemRoot"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_height="@dimen/video_item_search_height"
|
||||
android:background="?attr/selectableItemBackground"
|
||||
android:clickable="true"
|
||||
android:orientation="vertical"
|
||||
android:padding="12dp">
|
||||
android:padding="@dimen/video_item_search_padding">
|
||||
|
||||
<de.hdodenhof.circleimageview.CircleImageView
|
||||
android:id="@+id/itemThumbnailView"
|
||||
|
@ -22,55 +21,43 @@
|
|||
android:src="@drawable/buddy_channel_item"
|
||||
tools:ignore="RtlHardcoded"/>
|
||||
|
||||
<RelativeLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="@dimen/video_item_search_thumbnail_image_height"
|
||||
android:layout_toRightOf="@id/itemThumbnailView"
|
||||
android:orientation="vertical"
|
||||
tools:ignore="RtlHardcoded">
|
||||
|
||||
<TextView
|
||||
android:id="@+id/itemChannelTitleView"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_alignParentTop="true"
|
||||
android:layout_toRightOf="@id/itemThumbnailView"
|
||||
android:layout_marginBottom="@dimen/video_item_search_image_right_margin"
|
||||
android:ellipsize="end"
|
||||
android:maxLines="1"
|
||||
android:lines="1"
|
||||
android:textAppearance="?android:attr/textAppearanceLarge"
|
||||
android:textSize="@dimen/channel_item_detail_title_text_size"
|
||||
android:textSize="@dimen/video_item_search_title_text_size"
|
||||
tools:text="Channel Title, Lorem ipsum"/>
|
||||
|
||||
<TextView
|
||||
android:id="@+id/itemAdditionalDetails"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_alignParentBottom="true"
|
||||
android:layout_toRightOf="@id/itemThumbnailView"
|
||||
android:lines="1"
|
||||
android:textAppearance="?android:attr/textAppearanceSmall"
|
||||
android:textSize="@dimen/video_item_search_upload_date_text_size"
|
||||
tools:text="10M subscribers • 1000 videos"/>
|
||||
|
||||
|
||||
<TextView
|
||||
android:id="@+id/itemChannelDescriptionView"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_above="@+id/itemSubscriberCountView"
|
||||
android:layout_below="@+id/itemChannelTitleView"
|
||||
android:layout_above="@id/itemAdditionalDetails"
|
||||
android:layout_marginBottom="@dimen/video_item_detail_description_to_details_margin"
|
||||
android:layout_toRightOf="@id/itemThumbnailView"
|
||||
android:ellipsize="end"
|
||||
android:maxLines="2"
|
||||
android:lines="2"
|
||||
android:textAppearance="?android:attr/textAppearanceSmall"
|
||||
android:textSize="@dimen/video_item_search_uploader_text_size"
|
||||
tools:text="Channel description, Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nunc tristique vitae sem vitae blanditLorem ipsum dolor sit amet, consectetur adipiscing elit. Nunc tristique vitae sem vitae blanditLorem ipsum dolor sit amet, consectetur adipiscing elit. Nunc tristique vitae sem vitae blandit"/>
|
||||
|
||||
<TextView
|
||||
android:id="@+id/itemSubscriberCountView"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_alignParentBottom="true"
|
||||
android:maxLines="1"
|
||||
android:textAppearance="?android:attr/textAppearanceSmall"
|
||||
android:textSize="@dimen/video_item_search_upload_date_text_size"
|
||||
tools:text="10M subscribers • "/>
|
||||
|
||||
<TextView
|
||||
android:id="@+id/itemVideoCountView"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_alignParentBottom="true"
|
||||
android:layout_toRightOf="@+id/itemSubscriberCountView"
|
||||
android:maxLines="1"
|
||||
android:textAppearance="?android:attr/textAppearanceSmall"
|
||||
android:textSize="@dimen/video_item_search_upload_date_text_size"
|
||||
tools:text="1000 videos"/>
|
||||
</RelativeLayout>
|
||||
</RelativeLayout>
|
||||
|
|
|
@ -1,17 +1,17 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<RelativeLayout
|
||||
<LinearLayout
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:padding="16dp"
|
||||
android:gravity="center_horizontal"
|
||||
android:orientation="vertical">
|
||||
|
||||
<TextView
|
||||
android:id="@+id/error_message_view"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_centerHorizontal="true"
|
||||
android:text="@string/general_error"
|
||||
android:gravity="center"
|
||||
android:textSize="16sp"
|
||||
|
@ -22,8 +22,6 @@
|
|||
android:id="@+id/error_button_retry"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_below="@+id/error_message_view"
|
||||
android:layout_centerHorizontal="true"
|
||||
android:layout_margin="8dp"
|
||||
android:text="@string/retry"
|
||||
android:textAlignment="center"
|
||||
|
@ -32,4 +30,4 @@
|
|||
android:textSize="16sp"
|
||||
android:theme="@style/RedButton"/>
|
||||
|
||||
</RelativeLayout>
|
||||
</LinearLayout>
|
|
@ -1,9 +1,9 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<RelativeLayout
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent">
|
||||
android:layout_height="match_parent"
|
||||
tools:context=".fragments.channel.ChannelFragment">
|
||||
|
||||
<android.support.v7.widget.RecyclerView
|
||||
android:id="@+id/channel_streams_view"
|
||||
|
@ -13,24 +13,9 @@
|
|||
android:scrollbars="vertical"
|
||||
tools:listitem="@layout/stream_item" />
|
||||
|
||||
<ProgressBar
|
||||
android:id="@+id/loading_progress_bar"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_centerInParent="true"
|
||||
android:indeterminate="true"
|
||||
android:visibility="gone"
|
||||
tools:visibility="visible"/>
|
||||
|
||||
<!--ERROR PANEL-->
|
||||
<include
|
||||
android:id="@+id/error_panel"
|
||||
layout="@layout/error_retry"
|
||||
android:layout_width="wrap_content"
|
||||
layout="@layout/loading_error_retry"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_centerInParent="true"
|
||||
android:layout_marginTop="50dp"
|
||||
android:visibility="gone"
|
||||
tools:visibility="visible"/>
|
||||
|
||||
</RelativeLayout>
|
||||
android:layout_gravity="center" />
|
||||
</FrameLayout>
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<RelativeLayout
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:layout_width="match_parent"
|
||||
|
@ -16,24 +15,9 @@
|
|||
app:layoutManager="LinearLayoutManager"
|
||||
tools:listitem="@layout/stream_item" />
|
||||
|
||||
<ProgressBar
|
||||
android:id="@+id/loading_progress_bar"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_centerInParent="true"
|
||||
android:indeterminate="true"
|
||||
android:visibility="gone"
|
||||
tools:visibility="visible"/>
|
||||
|
||||
<!--ERROR PANEL-->
|
||||
<include
|
||||
android:id="@+id/error_panel"
|
||||
layout="@layout/error_retry"
|
||||
android:layout_width="wrap_content"
|
||||
layout="@layout/loading_error_retry"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_centerHorizontal="true"
|
||||
android:layout_marginTop="50dp"
|
||||
android:visibility="gone"
|
||||
tools:visibility="visible"/>
|
||||
|
||||
</RelativeLayout>
|
||||
android:layout_gravity="center_vertical" />
|
||||
</FrameLayout>
|
|
@ -1,6 +1,5 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<RelativeLayout
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:id="@+id/video_item_detail"
|
||||
|
@ -16,24 +15,24 @@
|
|||
app:parallax_factor="1.9">
|
||||
|
||||
<!--WRAPPER-->
|
||||
<RelativeLayout
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content">
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="vertical">
|
||||
|
||||
<!-- THUMBNAIL -->
|
||||
<RelativeLayout
|
||||
<FrameLayout
|
||||
android:id="@+id/detail_thumbnail_root_layout"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:background="@android:color/black">
|
||||
android:background="@android:color/black"
|
||||
android:clickable="true"
|
||||
android:foreground="?attr/selectableItemBackground">
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/detail_thumbnail_image_view"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_alignParentLeft="true"
|
||||
android:layout_alignParentRight="true"
|
||||
android:layout_alignParentTop="true"
|
||||
android:background="@android:color/transparent"
|
||||
android:contentDescription="@string/detail_thumbnail_view_description"
|
||||
android:scaleType="centerCrop"
|
||||
|
@ -45,52 +44,42 @@
|
|||
android:id="@+id/detail_thumbnail_play_button"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_centerInParent="true"
|
||||
android:layout_gravity="center"
|
||||
android:background="@android:color/transparent"
|
||||
android:src="@drawable/new_play_arrow"
|
||||
android:visibility="invisible"
|
||||
tools:ignore="ContentDescription"
|
||||
tools:visibility="visible" />
|
||||
|
||||
<Button
|
||||
android:id="@+id/detail_thumbnail_background_button"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:background="?attr/selectableItemBackground"/>
|
||||
|
||||
</RelativeLayout>
|
||||
</FrameLayout>
|
||||
|
||||
<!-- CONTENT -->
|
||||
<RelativeLayout
|
||||
<LinearLayout
|
||||
android:id="@+id/detail_content_root_layout"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_below="@+id/detail_thumbnail_root_layout"
|
||||
android:background="?android:windowBackground">
|
||||
android:background="?android:windowBackground"
|
||||
android:orientation="vertical">
|
||||
|
||||
<!-- TITLE -->
|
||||
<RelativeLayout
|
||||
<FrameLayout
|
||||
android:id="@+id/detail_title_root_layout"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:background="?attr/selectableItemBackground"
|
||||
android:clickable="true"
|
||||
android:paddingLeft="12dp"
|
||||
android:paddingRight="12dp"
|
||||
android:paddingTop="12dp">
|
||||
android:paddingRight="12dp">
|
||||
|
||||
<TextView
|
||||
android:id="@+id/detail_video_title_view"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_alignParentLeft="true"
|
||||
android:layout_centerVertical="true"
|
||||
android:layout_toLeftOf="@+id/detail_toggle_description_view"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_marginRight="20dp"
|
||||
android:ellipsize="end"
|
||||
android:gravity="center_vertical"
|
||||
android:maxLines="1"
|
||||
android:paddingBottom="2dp"
|
||||
android:paddingTop="6dp"
|
||||
android:paddingBottom="8dp"
|
||||
android:paddingTop="12dp"
|
||||
android:textAppearance="?android:attr/textAppearanceLarge"
|
||||
android:textSize="@dimen/video_item_detail_title_text_size"
|
||||
tools:ignore="RtlHardcoded"
|
||||
|
@ -100,21 +89,18 @@
|
|||
android:id="@+id/detail_toggle_description_view"
|
||||
android:layout_width="15dp"
|
||||
android:layout_height="15dp"
|
||||
android:layout_alignParentRight="true"
|
||||
android:layout_alignParentTop="true"
|
||||
android:layout_gravity="center_vertical|right"
|
||||
android:layout_marginLeft="5dp"
|
||||
android:layout_marginTop="6dp"
|
||||
android:src="@drawable/arrow_down"
|
||||
tools:ignore="ContentDescription,RtlHardcoded" />
|
||||
|
||||
</RelativeLayout>
|
||||
|
||||
</FrameLayout>
|
||||
<!--HIDING ROOT-->
|
||||
<RelativeLayout
|
||||
<LinearLayout
|
||||
android:id="@+id/detail_content_root_hiding"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_below="@+id/detail_title_root_layout"
|
||||
android:orientation="vertical"
|
||||
android:visibility="gone"
|
||||
tools:visibility="visible">
|
||||
|
||||
|
@ -122,56 +108,44 @@
|
|||
<RelativeLayout
|
||||
android:id="@+id/detail_root"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_height="55dp"
|
||||
android:layout_marginLeft="12dp"
|
||||
android:layout_marginRight="12dp"
|
||||
android:layout_marginTop="6dp"
|
||||
android:baselineAligned="false"
|
||||
android:orientation="horizontal"
|
||||
android:paddingTop="6dp">
|
||||
android:orientation="horizontal">
|
||||
|
||||
<!-- VIEW & THUMBS -->
|
||||
<LinearLayout
|
||||
android:id="@+id/detail_views_thumbs_root"
|
||||
<TextView
|
||||
android:id="@+id/detail_view_count_view"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_alignParentLeft="true"
|
||||
android:layout_centerHorizontal="true"
|
||||
android:orientation="vertical"
|
||||
android:paddingTop="6dp"
|
||||
tools:ignore="RtlHardcoded">
|
||||
|
||||
<TextView
|
||||
android:id="@+id/detail_view_count_view"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="left"
|
||||
android:layout_marginBottom="6dp"
|
||||
android:layout_marginTop="6dp"
|
||||
android:lines="1"
|
||||
android:textAppearance="?android:attr/textAppearanceLarge"
|
||||
android:textSize="@dimen/video_item_detail_views_text_size"
|
||||
tools:ignore="RtlHardcoded"
|
||||
tools:text="2,816,821,505 views" />
|
||||
|
||||
<LinearLayout
|
||||
android:id="@+id/detail_thumbs_root_layout"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="left"
|
||||
android:gravity="center_vertical"
|
||||
android:minHeight="30dp"
|
||||
android:orientation="horizontal">
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/detail_thumbs_up_img_view"
|
||||
android:layout_width="@dimen/video_item_detail_like_image_width"
|
||||
android:layout_height="@dimen/video_item_detail_like_image_height"
|
||||
android:layout_below="@id/detail_view_count_view"
|
||||
android:contentDescription="@string/detail_likes_img_view_description"
|
||||
android:src="?attr/thumbs_up" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/detail_thumbs_up_count_view"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_height="@dimen/video_item_detail_like_image_height"
|
||||
android:layout_below="@id/detail_view_count_view"
|
||||
android:layout_marginLeft="@dimen/video_item_detail_like_margin"
|
||||
android:layout_toRightOf="@id/detail_thumbs_up_img_view"
|
||||
android:gravity="left|center_vertical"
|
||||
android:lines="1"
|
||||
android:textAppearance="?android:attr/textAppearanceMedium"
|
||||
android:textSize="@dimen/video_item_detail_likes_text_size"
|
||||
tools:ignore="RtlHardcoded"
|
||||
|
@ -181,7 +155,9 @@
|
|||
android:id="@+id/detail_thumbs_down_img_view"
|
||||
android:layout_width="@dimen/video_item_detail_like_image_width"
|
||||
android:layout_height="@dimen/video_item_detail_like_image_height"
|
||||
android:layout_below="@id/detail_view_count_view"
|
||||
android:layout_marginLeft="15dp"
|
||||
android:layout_toRightOf="@id/detail_thumbs_up_count_view"
|
||||
android:contentDescription="@string/detail_dislikes_img_view_description"
|
||||
android:src="?attr/thumbs_down"
|
||||
tools:ignore="RtlHardcoded" />
|
||||
|
@ -189,9 +165,12 @@
|
|||
<TextView
|
||||
android:id="@+id/detail_thumbs_down_count_view"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_height="@dimen/video_item_detail_like_image_height"
|
||||
android:layout_below="@id/detail_view_count_view"
|
||||
android:layout_marginLeft="@dimen/video_item_detail_like_margin"
|
||||
android:layout_toRightOf="@id/detail_thumbs_down_img_view"
|
||||
android:gravity="left|center_vertical"
|
||||
android:lines="1"
|
||||
android:textAppearance="?android:attr/textAppearanceMedium"
|
||||
android:textSize="@dimen/video_item_detail_likes_text_size"
|
||||
tools:ignore="RtlHardcoded"
|
||||
|
@ -201,6 +180,7 @@
|
|||
android:id="@+id/detail_thumbs_disabled_view"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_below="@id/detail_view_count_view"
|
||||
android:layout_marginLeft="15dp"
|
||||
android:gravity="left|center_vertical"
|
||||
android:text="@string/disabled"
|
||||
|
@ -209,38 +189,14 @@
|
|||
android:textStyle="bold"
|
||||
android:visibility="gone"
|
||||
tools:ignore="RtlHardcoded" />
|
||||
</LinearLayout>
|
||||
</LinearLayout>
|
||||
|
||||
<!-- CONTROLS -->
|
||||
<LinearLayout
|
||||
android:id="@+id/detail_controls_root"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_alignParentRight="true"
|
||||
android:layout_centerHorizontal="true"
|
||||
android:orientation="horizontal"
|
||||
tools:ignore="RtlHardcoded">
|
||||
|
||||
<TextView
|
||||
android:id="@+id/detail_controls_background"
|
||||
android:layout_width="80dp"
|
||||
android:layout_height="55dp"
|
||||
android:layout_gravity="center_vertical"
|
||||
android:background="?attr/selectableItemBackgroundBorderless"
|
||||
android:clickable="true"
|
||||
android:contentDescription="@string/play_audio"
|
||||
android:drawableTop="?attr/audio"
|
||||
android:gravity="center"
|
||||
android:paddingBottom="6dp"
|
||||
android:paddingTop="6dp"
|
||||
android:text="@string/controls_background_title"
|
||||
android:textSize="12sp"/>
|
||||
|
||||
<TextView
|
||||
android:id="@+id/detail_controls_popup"
|
||||
android:layout_width="80dp"
|
||||
android:layout_height="55dp"
|
||||
android:layout_alignParentRight="true"
|
||||
android:layout_alignParentTop="true"
|
||||
android:layout_gravity="center_vertical"
|
||||
android:background="?attr/selectableItemBackgroundBorderless"
|
||||
android:clickable="true"
|
||||
|
@ -252,68 +208,57 @@
|
|||
android:text="@string/controls_popup_title"
|
||||
android:textSize="12sp" />
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
<TextView
|
||||
android:id="@+id/detail_controls_background"
|
||||
android:layout_width="80dp"
|
||||
android:layout_height="55dp"
|
||||
android:layout_alignParentTop="true"
|
||||
android:layout_gravity="center_vertical"
|
||||
android:layout_toLeftOf="@id/detail_controls_popup"
|
||||
android:background="?attr/selectableItemBackgroundBorderless"
|
||||
android:clickable="true"
|
||||
android:contentDescription="@string/play_audio"
|
||||
android:drawableTop="?attr/audio"
|
||||
android:gravity="center"
|
||||
android:paddingBottom="6dp"
|
||||
android:paddingTop="6dp"
|
||||
android:text="@string/controls_background_title"
|
||||
android:textSize="12sp" />
|
||||
</RelativeLayout>
|
||||
|
||||
<!--UPLOADER-->
|
||||
<FrameLayout
|
||||
<LinearLayout
|
||||
android:id="@+id/detail_uploader_root_layout"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_below="@+id/detail_root">
|
||||
|
||||
<RelativeLayout
|
||||
android:id="@+id/detail_uploader_layout"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginBottom="8dp"
|
||||
android:layout_marginLeft="12dp"
|
||||
android:layout_marginRight="12dp"
|
||||
android:layout_marginTop="8dp">
|
||||
android:background="?attr/selectableItemBackground"
|
||||
android:gravity="center_vertical"
|
||||
android:orientation="horizontal"
|
||||
android:paddingBottom="8dp"
|
||||
android:paddingLeft="12dp"
|
||||
android:paddingRight="12dp"
|
||||
android:paddingTop="8dp">
|
||||
|
||||
|
||||
<de.hdodenhof.circleimageview.CircleImageView
|
||||
android:id="@+id/detail_uploader_thumbnail_view"
|
||||
android:layout_width="@dimen/video_item_detail_uploader_image_size"
|
||||
android:layout_height="@dimen/video_item_detail_uploader_image_size"
|
||||
android:layout_alignParentLeft="true"
|
||||
android:contentDescription="@string/detail_uploader_thumbnail_view_description"
|
||||
android:src="@drawable/buddy"
|
||||
tools:ignore="RtlHardcoded" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/detail_uploader_text_view"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_centerVertical="true"
|
||||
android:layout_marginLeft="15dp"
|
||||
android:layout_toEndOf="@+id/detail_uploader_thumbnail_view"
|
||||
android:layout_toRightOf="@+id/detail_uploader_thumbnail_view"
|
||||
android:textAppearance="?android:attr/textAppearanceLarge"
|
||||
android:textSize="@dimen/video_item_detail_uploader_text_size"
|
||||
android:textStyle="bold"
|
||||
tools:ignore="RtlHardcoded"
|
||||
tools:text="Uploader" />
|
||||
|
||||
|
||||
</RelativeLayout>
|
||||
|
||||
<View
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="1px"
|
||||
android:layout_gravity="bottom"
|
||||
android:layout_marginLeft="8dp"
|
||||
android:layout_marginRight="8dp"
|
||||
android:background="?attr/separatorColor"/>
|
||||
|
||||
<Button
|
||||
android:id="@+id/detail_uploader_button"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:background="?attr/selectableItemBackground"
|
||||
tools:visibility="gone"/>
|
||||
|
||||
<!--<Button
|
||||
android:id="@+id/detail_uploader_subscribe"
|
||||
android:layout_width="wrap_content"
|
||||
|
@ -326,15 +271,22 @@
|
|||
android:drawableLeft="@drawable/ic_rss_feed_white_24dp"
|
||||
tools:ignore="RtlHardcoded"
|
||||
android:visibility="gone"/>-->
|
||||
</FrameLayout>
|
||||
</LinearLayout>
|
||||
|
||||
<View
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="1px"
|
||||
android:layout_marginLeft="8dp"
|
||||
android:layout_marginRight="8dp"
|
||||
android:background="?attr/separatorColor" />
|
||||
|
||||
<!--DESCRIPTIONS-->
|
||||
<RelativeLayout
|
||||
<LinearLayout
|
||||
android:id="@+id/detail_description_root_layout"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_below="@id/detail_uploader_root_layout"
|
||||
android:layout_marginTop="5dp"
|
||||
android:orientation="vertical"
|
||||
android:visibility="gone"
|
||||
tools:visibility="visible">
|
||||
|
||||
|
@ -347,13 +299,12 @@
|
|||
android:textAppearance="?android:attr/textAppearanceMedium"
|
||||
android:textSize="@dimen/video_item_detail_upload_date_text_size"
|
||||
android:textStyle="bold"
|
||||
tools:text="Upload date"/>
|
||||
tools:text="Published on Oct 2, 2009" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/detail_description_view"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_below="@+id/detail_upload_date_view"
|
||||
android:layout_marginBottom="8dp"
|
||||
android:layout_marginLeft="12dp"
|
||||
android:layout_marginRight="12dp"
|
||||
|
@ -365,28 +316,25 @@
|
|||
<View
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="1px"
|
||||
android:layout_alignParentBottom="true"
|
||||
android:layout_marginLeft="8dp"
|
||||
android:layout_marginRight="8dp"
|
||||
android:background="?attr/separatorColor" />
|
||||
|
||||
</RelativeLayout>
|
||||
</LinearLayout>
|
||||
|
||||
<!--NEXT AND RELATED VIDEOS-->
|
||||
<RelativeLayout
|
||||
<LinearLayout
|
||||
android:id="@+id/detail_related_streams_root_layout"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_below="@+id/detail_description_root_layout"
|
||||
android:layout_centerHorizontal="true"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="center_horizontal|bottom"
|
||||
android:layout_marginTop="14dp">
|
||||
android:layout_marginTop="14dp"
|
||||
android:orientation="vertical">
|
||||
|
||||
<TextView
|
||||
android:id="@+id/detail_next_stream_title"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_alignParentLeft="true"
|
||||
android:layout_marginLeft="12dp"
|
||||
android:text="@string/next_video_title"
|
||||
android:textAllCaps="true"
|
||||
|
@ -398,7 +346,6 @@
|
|||
android:id="@+id/detail_related_streams_view"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_below="@id/detail_next_stream_title"
|
||||
android:layout_marginTop="2dp"
|
||||
android:orientation="vertical"
|
||||
tools:minHeight="50dp" />
|
||||
|
@ -407,7 +354,6 @@
|
|||
android:id="@+id/detail_related_streams_expand"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_below="@id/detail_related_streams_view"
|
||||
android:background="?attr/selectableItemBackground"
|
||||
android:paddingBottom="10dp"
|
||||
android:paddingTop="4dp"
|
||||
|
@ -415,38 +361,12 @@
|
|||
android:textAlignment="center"
|
||||
android:textAllCaps="true"
|
||||
tools:ignore="ContentDescription" />
|
||||
</LinearLayout>
|
||||
</LinearLayout>
|
||||
|
||||
|
||||
</RelativeLayout>
|
||||
|
||||
</RelativeLayout>
|
||||
|
||||
<!-- LOADING BAR -->
|
||||
<ProgressBar
|
||||
android:id="@+id/loading_progress_bar"
|
||||
style="@style/Widget.AppCompat.ProgressBar"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_below="@+id/detail_title_root_layout"
|
||||
android:layout_centerHorizontal="true"
|
||||
android:layout_marginTop="15dp"
|
||||
android:indeterminate="true"
|
||||
android:visibility="gone"
|
||||
tools:visibility="visible"/>
|
||||
|
||||
<!--ERROR PANEL-->
|
||||
<include
|
||||
android:id="@+id/error_panel"
|
||||
layout="@layout/error_retry"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_below="@+id/detail_title_root_layout"
|
||||
android:layout_centerHorizontal="true"
|
||||
android:layout_marginTop="@dimen/video_item_detail_error_panel_margin"
|
||||
android:visibility="gone"
|
||||
tools:visibility="visible"/>
|
||||
|
||||
</RelativeLayout>
|
||||
</RelativeLayout>
|
||||
<!-- LOADING BAR, ERROR & RETRY -->
|
||||
<include layout="@layout/loading_error_retry" />
|
||||
</LinearLayout>
|
||||
</LinearLayout>
|
||||
</com.nirhart.parallaxscroll.views.ParallaxScrollView>
|
||||
</RelativeLayout>
|
||||
</FrameLayout>
|
||||
|
|
|
@ -0,0 +1,26 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:padding="15dp">
|
||||
|
||||
<ProgressBar
|
||||
android:id="@+id/loading_progress_bar"
|
||||
style="@style/Widget.AppCompat.ProgressBar"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:indeterminate="true"
|
||||
android:visibility="gone"
|
||||
tools:visibility="visible" />
|
||||
|
||||
<!--ERROR PANEL-->
|
||||
<include
|
||||
android:id="@+id/error_panel"
|
||||
layout="@layout/error_retry"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="@dimen/video_item_detail_error_panel_margin"
|
||||
android:visibility="gone"
|
||||
tools:visibility="visible" />
|
||||
</FrameLayout>
|
|
@ -4,11 +4,10 @@
|
|||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:id="@+id/itemRoot"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_height="@dimen/video_item_search_height"
|
||||
android:background="?attr/selectableItemBackground"
|
||||
android:clickable="true"
|
||||
android:orientation="vertical"
|
||||
android:padding="12dp">
|
||||
android:padding="@dimen/video_item_search_padding">
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/itemThumbnailView"
|
||||
|
@ -42,20 +41,15 @@
|
|||
tools:ignore="RtlHardcoded"
|
||||
tools:text="1:09:10"/>
|
||||
|
||||
<RelativeLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="@dimen/video_item_search_thumbnail_image_height"
|
||||
android:layout_toRightOf="@id/itemThumbnailView"
|
||||
android:orientation="vertical"
|
||||
tools:ignore="RtlHardcoded">
|
||||
|
||||
<TextView
|
||||
android:id="@+id/itemVideoTitleView"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_above="@+id/itemUploaderView"
|
||||
android:layout_alignParentTop="true"
|
||||
android:layout_toRightOf="@id/itemThumbnailView"
|
||||
android:ellipsize="end"
|
||||
android:lines="2"
|
||||
android:maxLines="2"
|
||||
android:textAppearance="?android:attr/textAppearanceLarge"
|
||||
android:textSize="@dimen/video_item_search_title_text_size"
|
||||
|
@ -65,32 +59,22 @@
|
|||
android:id="@+id/itemUploaderView"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_above="@+id/itemUploadDateView"
|
||||
android:maxLines="1"
|
||||
android:layout_above="@id/itemAdditionalDetails"
|
||||
android:layout_toRightOf="@id/itemThumbnailView"
|
||||
android:lines="1"
|
||||
android:layout_marginBottom="@dimen/video_item_detail_description_to_details_margin"
|
||||
android:textAppearance="?android:attr/textAppearanceSmall"
|
||||
android:textSize="@dimen/video_item_search_uploader_text_size"
|
||||
tools:text="Uploader"/>
|
||||
|
||||
|
||||
<TextView
|
||||
android:id="@+id/itemUploadDateView"
|
||||
android:layout_width="wrap_content"
|
||||
android:id="@+id/itemAdditionalDetails"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_alignParentBottom="true"
|
||||
android:maxLines="1"
|
||||
android:layout_toRightOf="@id/itemThumbnailView"
|
||||
android:lines="1"
|
||||
android:textAppearance="?android:attr/textAppearanceSmall"
|
||||
android:textSize="@dimen/video_item_search_upload_date_text_size"
|
||||
tools:text="2 years ago • "/>
|
||||
|
||||
<TextView
|
||||
android:id="@+id/itemViewCountView"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_alignParentBottom="true"
|
||||
android:layout_toRightOf="@+id/itemUploadDateView"
|
||||
android:maxLines="1"
|
||||
android:textAppearance="?android:attr/textAppearanceSmall"
|
||||
android:textSize="@dimen/video_item_search_upload_date_text_size"
|
||||
tools:text="10M views"/>
|
||||
</RelativeLayout>
|
||||
tools:text="2 years ago • 10M views"/>
|
||||
</RelativeLayout>
|
|
@ -37,7 +37,7 @@
|
|||
android:layout_gravity="right|center_vertical"
|
||||
tools:ignore="RtlHardcoded">
|
||||
|
||||
<FrameLayout
|
||||
<View
|
||||
android:layout_width="28dp"
|
||||
android:layout_height="28dp"
|
||||
android:layout_gravity="center"
|
||||
|
|
|
@ -12,6 +12,8 @@
|
|||
<!-- 16 / 9 ratio-->
|
||||
<dimen name="video_item_search_thumbnail_image_width">142dp</dimen>
|
||||
<dimen name="video_item_search_thumbnail_image_height">80dp</dimen>
|
||||
<!-- Calculated: 2*video_item_search_padding + video_item_search_thumbnail_image_height -->
|
||||
<dimen name="video_item_search_height">104dp</dimen>
|
||||
<!-- Paddings & Margins -->
|
||||
<dimen name="video_item_search_image_right_margin">10dp</dimen>
|
||||
<dimen name="video_item_search_duration_vertical_padding">1sp</dimen>
|
||||
|
|
|
@ -11,11 +11,15 @@
|
|||
<!-- 16 / 9 ratio-->
|
||||
<dimen name="video_item_search_thumbnail_image_width">124dp</dimen>
|
||||
<dimen name="video_item_search_thumbnail_image_height">70dp</dimen>
|
||||
<!-- Calculated: 2*video_item_search_padding + video_item_search_thumbnail_image_height -->
|
||||
<dimen name="video_item_search_height">94dp</dimen>
|
||||
<!-- Paddings & Margins -->
|
||||
<dimen name="video_item_search_padding">12dp</dimen>
|
||||
<dimen name="video_item_search_image_right_margin">6dp</dimen>
|
||||
<dimen name="video_item_search_duration_vertical_padding">1sp</dimen>
|
||||
<dimen name="video_item_search_duration_horizontal_padding">5sp</dimen>
|
||||
<dimen name="video_item_search_duration_margin">2sp</dimen>
|
||||
<dimen name="video_item_detail_description_to_details_margin">4dp</dimen>
|
||||
<!-- Miscellaneous -->
|
||||
<dimen name="popup_default_width">180dp</dimen>
|
||||
<dimen name="popup_minimum_width">120dp</dimen>
|
||||
|
|
|
@ -0,0 +1,38 @@
|
|||
package org.schabi.newpipe.report;
|
||||
|
||||
import android.app.Activity;
|
||||
|
||||
import org.junit.Test;
|
||||
import org.schabi.newpipe.MainActivity;
|
||||
import org.schabi.newpipe.RouterActivity;
|
||||
import org.schabi.newpipe.fragments.detail.VideoDetailFragment;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertNull;
|
||||
|
||||
/**
|
||||
* Unit tests for {@link ErrorActivity}
|
||||
*/
|
||||
public class ErrorActivityTest {
|
||||
@Test
|
||||
public void getReturnActivity() throws Exception {
|
||||
Class<? extends Activity> returnActivity;
|
||||
returnActivity = ErrorActivity.getReturnActivity(MainActivity.class);
|
||||
assertEquals(MainActivity.class, returnActivity);
|
||||
|
||||
returnActivity = ErrorActivity.getReturnActivity(RouterActivity.class);
|
||||
assertEquals(RouterActivity.class, returnActivity);
|
||||
|
||||
returnActivity = ErrorActivity.getReturnActivity(null);
|
||||
assertNull(returnActivity);
|
||||
|
||||
returnActivity = ErrorActivity.getReturnActivity(Integer.class);
|
||||
assertEquals(MainActivity.class, returnActivity);
|
||||
|
||||
returnActivity = ErrorActivity.getReturnActivity(VideoDetailFragment.class);
|
||||
assertEquals(MainActivity.class, returnActivity);
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
|
@ -31,18 +31,18 @@ import static org.mockito.Mockito.when;
|
|||
public class DownloadManagerImplTest {
|
||||
|
||||
private DownloadManagerImpl downloadManager;
|
||||
private DownloadDataSource dowloadDataSource;
|
||||
private DownloadDataSource downloadDataSource;
|
||||
private ArrayList<DownloadMission> missions;
|
||||
|
||||
@org.junit.Before
|
||||
public void setUp() throws Exception {
|
||||
dowloadDataSource = mock(DownloadDataSource.class);
|
||||
downloadDataSource = mock(DownloadDataSource.class);
|
||||
missions = new ArrayList<>();
|
||||
for(int i = 0; i < 50; ++i){
|
||||
missions.add(generateFinishedDownloadMission());
|
||||
}
|
||||
when(dowloadDataSource.loadMissions()).thenReturn(new ArrayList<>(missions));
|
||||
downloadManager = new DownloadManagerImpl(new ArrayList<String>(), dowloadDataSource);
|
||||
when(downloadDataSource.loadMissions()).thenReturn(new ArrayList<>(missions));
|
||||
downloadManager = new DownloadManagerImpl(new ArrayList<String>(), downloadDataSource);
|
||||
}
|
||||
|
||||
@Test(expected = NullPointerException.class)
|
||||
|
@ -82,10 +82,10 @@ public class DownloadManagerImplTest {
|
|||
missions.add(mission);
|
||||
}
|
||||
|
||||
dowloadDataSource = mock(DownloadDataSource.class);
|
||||
when(dowloadDataSource.loadMissions()).thenReturn(new ArrayList<>(missions));
|
||||
downloadManager = new DownloadManagerImpl(new ArrayList<String>(), dowloadDataSource);
|
||||
verify(dowloadDataSource, times(1)).loadMissions();
|
||||
downloadDataSource = mock(DownloadDataSource.class);
|
||||
when(downloadDataSource.loadMissions()).thenReturn(new ArrayList<>(missions));
|
||||
downloadManager = new DownloadManagerImpl(new ArrayList<String>(), downloadDataSource);
|
||||
verify(downloadDataSource, times(1)).loadMissions();
|
||||
|
||||
assertEquals(50, downloadManager.getCount());
|
||||
|
||||
|
|
Loading…
Reference in New Issue