SponsorBlock: Merge branch 'dev' into sponsorblock
This commit is contained in:
commit
62b109171c
17 changed files with 154 additions and 52 deletions
|
@ -164,7 +164,7 @@ dependencies {
|
||||||
exclude module: 'support-annotations'
|
exclude module: 'support-annotations'
|
||||||
}
|
}
|
||||||
|
|
||||||
implementation 'com.github.TeamNewPipe:NewPipeExtractor:5ac80624a40f4c600ae493e66881b5bf008f0ddb'
|
implementation 'com.github.TeamNewPipe:NewPipeExtractor:6633f26ec5a73a8e932de575b7a0643b6ad6c890'
|
||||||
|
|
||||||
implementation "com.github.TeamNewPipe:nanojson:1d9e1aea9049fc9f85e68b43ba39fe7be1c1f751"
|
implementation "com.github.TeamNewPipe:nanojson:1d9e1aea9049fc9f85e68b43ba39fe7be1c1f751"
|
||||||
implementation "org.jsoup:jsoup:1.13.1"
|
implementation "org.jsoup:jsoup:1.13.1"
|
||||||
|
|
|
@ -68,6 +68,14 @@ public final class FlingBehavior extends AppBarLayout.Behavior {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
final View seekBar = child.findViewById(R.id.playbackSeekBar);
|
||||||
|
if (seekBar != null) {
|
||||||
|
final boolean visible = seekBar.getGlobalVisibleRect(globalRect);
|
||||||
|
if (visible && globalRect.contains((int) ev.getRawX(), (int) ev.getRawY())) {
|
||||||
|
allowScroll = false;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
allowScroll = true;
|
allowScroll = true;
|
||||||
switch (ev.getActionMasked()) {
|
switch (ev.getActionMasked()) {
|
||||||
case MotionEvent.ACTION_DOWN:
|
case MotionEvent.ACTION_DOWN:
|
||||||
|
|
|
@ -4,10 +4,12 @@ import android.net.Uri;
|
||||||
import android.os.Parcel;
|
import android.os.Parcel;
|
||||||
import android.os.Parcelable;
|
import android.os.Parcelable;
|
||||||
|
|
||||||
|
import java.io.Serializable;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Class for storing information about a software license.
|
* Class for storing information about a software license.
|
||||||
*/
|
*/
|
||||||
public class License implements Parcelable {
|
public class License implements Parcelable, Serializable {
|
||||||
public static final Creator<License> CREATOR = new Creator<License>() {
|
public static final Creator<License> CREATOR = new Creator<License>() {
|
||||||
@Override
|
@Override
|
||||||
public License createFromParcel(final Parcel source) {
|
public License createFromParcel(final Parcel source) {
|
||||||
|
|
|
@ -1,7 +1,6 @@
|
||||||
package org.schabi.newpipe.about;
|
package org.schabi.newpipe.about;
|
||||||
|
|
||||||
import android.app.Activity;
|
import android.app.Activity;
|
||||||
import android.content.Context;
|
|
||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
import android.view.ContextMenu;
|
import android.view.ContextMenu;
|
||||||
import android.view.LayoutInflater;
|
import android.view.LayoutInflater;
|
||||||
|
@ -11,12 +10,14 @@ import android.view.View;
|
||||||
import android.view.ViewGroup;
|
import android.view.ViewGroup;
|
||||||
import android.widget.TextView;
|
import android.widget.TextView;
|
||||||
|
|
||||||
|
import androidx.annotation.NonNull;
|
||||||
import androidx.annotation.Nullable;
|
import androidx.annotation.Nullable;
|
||||||
import androidx.fragment.app.Fragment;
|
import androidx.fragment.app.Fragment;
|
||||||
|
|
||||||
import org.schabi.newpipe.R;
|
import org.schabi.newpipe.R;
|
||||||
import org.schabi.newpipe.util.ShareUtils;
|
import org.schabi.newpipe.util.ShareUtils;
|
||||||
|
|
||||||
|
import java.io.Serializable;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -26,6 +27,8 @@ public class LicenseFragment extends Fragment {
|
||||||
private static final String ARG_COMPONENTS = "components";
|
private static final String ARG_COMPONENTS = "components";
|
||||||
private SoftwareComponent[] softwareComponents;
|
private SoftwareComponent[] softwareComponents;
|
||||||
private SoftwareComponent componentForContextMenu;
|
private SoftwareComponent componentForContextMenu;
|
||||||
|
private License activeLicense;
|
||||||
|
private static final String LICENSE_KEY = "ACTIVE_LICENSE";
|
||||||
|
|
||||||
public static LicenseFragment newInstance(final SoftwareComponent[] softwareComponents) {
|
public static LicenseFragment newInstance(final SoftwareComponent[] softwareComponents) {
|
||||||
if (softwareComponents == null) {
|
if (softwareComponents == null) {
|
||||||
|
@ -44,8 +47,8 @@ public class LicenseFragment extends Fragment {
|
||||||
* @param context the context to use
|
* @param context the context to use
|
||||||
* @param license the license to show
|
* @param license the license to show
|
||||||
*/
|
*/
|
||||||
private static void showLicense(final Context context, final License license) {
|
private static void showLicense(final Activity context, final License license) {
|
||||||
new LicenseFragmentHelper((Activity) context).execute(license);
|
new LicenseFragmentHelper(context).execute(license);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -54,6 +57,12 @@ public class LicenseFragment extends Fragment {
|
||||||
softwareComponents = (SoftwareComponent[]) getArguments()
|
softwareComponents = (SoftwareComponent[]) getArguments()
|
||||||
.getParcelableArray(ARG_COMPONENTS);
|
.getParcelableArray(ARG_COMPONENTS);
|
||||||
|
|
||||||
|
if (savedInstanceState != null) {
|
||||||
|
final Serializable license = savedInstanceState.getSerializable(LICENSE_KEY);
|
||||||
|
if (license != null) {
|
||||||
|
activeLicense = (License) license;
|
||||||
|
}
|
||||||
|
}
|
||||||
// Sort components by name
|
// Sort components by name
|
||||||
Arrays.sort(softwareComponents, (o1, o2) -> o1.getName().compareTo(o2.getName()));
|
Arrays.sort(softwareComponents, (o1, o2) -> o1.getName().compareTo(o2.getName()));
|
||||||
}
|
}
|
||||||
|
@ -66,8 +75,10 @@ public class LicenseFragment extends Fragment {
|
||||||
final ViewGroup softwareComponentsView = rootView.findViewById(R.id.software_components);
|
final ViewGroup softwareComponentsView = rootView.findViewById(R.id.software_components);
|
||||||
|
|
||||||
final View licenseLink = rootView.findViewById(R.id.app_read_license);
|
final View licenseLink = rootView.findViewById(R.id.app_read_license);
|
||||||
licenseLink.setOnClickListener(v ->
|
licenseLink.setOnClickListener(v -> {
|
||||||
showLicense(getActivity(), StandardLicenses.GPL3));
|
activeLicense = StandardLicenses.GPL3;
|
||||||
|
showLicense(getActivity(), StandardLicenses.GPL3);
|
||||||
|
});
|
||||||
|
|
||||||
for (final SoftwareComponent component : softwareComponents) {
|
for (final SoftwareComponent component : softwareComponents) {
|
||||||
final View componentView = inflater
|
final View componentView = inflater
|
||||||
|
@ -81,11 +92,16 @@ public class LicenseFragment extends Fragment {
|
||||||
component.getLicense().getAbbreviation()));
|
component.getLicense().getAbbreviation()));
|
||||||
|
|
||||||
componentView.setTag(component);
|
componentView.setTag(component);
|
||||||
componentView.setOnClickListener(v ->
|
componentView.setOnClickListener(v -> {
|
||||||
showLicense(getActivity(), component.getLicense()));
|
activeLicense = component.getLicense();
|
||||||
|
showLicense(getActivity(), component.getLicense());
|
||||||
|
});
|
||||||
softwareComponentsView.addView(componentView);
|
softwareComponentsView.addView(componentView);
|
||||||
registerForContextMenu(componentView);
|
registerForContextMenu(componentView);
|
||||||
}
|
}
|
||||||
|
if (activeLicense != null) {
|
||||||
|
showLicense(getActivity(), activeLicense);
|
||||||
|
}
|
||||||
return rootView;
|
return rootView;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -101,7 +117,7 @@ public class LicenseFragment extends Fragment {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean onContextItemSelected(final MenuItem item) {
|
public boolean onContextItemSelected(@NonNull final MenuItem item) {
|
||||||
// item.getMenuInfo() is null so we use the tag of the view
|
// item.getMenuInfo() is null so we use the tag of the view
|
||||||
final SoftwareComponent component = componentForContextMenu;
|
final SoftwareComponent component = componentForContextMenu;
|
||||||
if (component == null) {
|
if (component == null) {
|
||||||
|
@ -116,4 +132,12 @@ public class LicenseFragment extends Fragment {
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onSaveInstanceState(@NonNull final Bundle savedInstanceState) {
|
||||||
|
super.onSaveInstanceState(savedInstanceState);
|
||||||
|
if (activeLicense != null) {
|
||||||
|
savedInstanceState.putSerializable(LICENSE_KEY, activeLicense);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -6,7 +6,7 @@ import androidx.annotation.NonNull;
|
||||||
import androidx.room.migration.Migration;
|
import androidx.room.migration.Migration;
|
||||||
import androidx.sqlite.db.SupportSQLiteDatabase;
|
import androidx.sqlite.db.SupportSQLiteDatabase;
|
||||||
|
|
||||||
import org.schabi.newpipe.BuildConfig;
|
import org.schabi.newpipe.MainActivity;
|
||||||
|
|
||||||
public final class Migrations {
|
public final class Migrations {
|
||||||
public static final int DB_VER_1 = 1;
|
public static final int DB_VER_1 = 1;
|
||||||
|
@ -14,7 +14,7 @@ public final class Migrations {
|
||||||
public static final int DB_VER_3 = 3;
|
public static final int DB_VER_3 = 3;
|
||||||
|
|
||||||
private static final String TAG = Migrations.class.getName();
|
private static final String TAG = Migrations.class.getName();
|
||||||
public static final boolean DEBUG = !BuildConfig.BUILD_TYPE.equals("release");
|
public static final boolean DEBUG = MainActivity.DEBUG;
|
||||||
|
|
||||||
public static final Migration MIGRATION_1_2 = new Migration(DB_VER_1, DB_VER_2) {
|
public static final Migration MIGRATION_1_2 = new Migration(DB_VER_1, DB_VER_2) {
|
||||||
@Override
|
@Override
|
||||||
|
|
|
@ -516,7 +516,23 @@ public class DownloadDialog extends DialogFragment
|
||||||
videoButton.setVisibility(isVideoStreamsAvailable ? View.VISIBLE : View.GONE);
|
videoButton.setVisibility(isVideoStreamsAvailable ? View.VISIBLE : View.GONE);
|
||||||
subtitleButton.setVisibility(isSubtitleStreamsAvailable ? View.VISIBLE : View.GONE);
|
subtitleButton.setVisibility(isSubtitleStreamsAvailable ? View.VISIBLE : View.GONE);
|
||||||
|
|
||||||
if (isVideoStreamsAvailable) {
|
prefs = PreferenceManager.getDefaultSharedPreferences(getContext());
|
||||||
|
final String defaultMedia = prefs.getString(getString(R.string.last_used_download_type),
|
||||||
|
getString(R.string.last_download_type_video_key));
|
||||||
|
|
||||||
|
if (isVideoStreamsAvailable
|
||||||
|
&& (defaultMedia.equals(getString(R.string.last_download_type_video_key)))) {
|
||||||
|
videoButton.setChecked(true);
|
||||||
|
setupVideoSpinner();
|
||||||
|
} else if (isAudioStreamsAvailable
|
||||||
|
&& (defaultMedia.equals(getString(R.string.last_download_type_audio_key)))) {
|
||||||
|
audioButton.setChecked(true);
|
||||||
|
setupAudioSpinner();
|
||||||
|
} else if (isSubtitleStreamsAvailable
|
||||||
|
&& (defaultMedia.equals(getString(R.string.last_download_type_subtitle_key)))) {
|
||||||
|
subtitleButton.setChecked(true);
|
||||||
|
setupSubtitleSpinner();
|
||||||
|
} else if (isVideoStreamsAvailable) {
|
||||||
videoButton.setChecked(true);
|
videoButton.setChecked(true);
|
||||||
setupVideoSpinner();
|
setupVideoSpinner();
|
||||||
} else if (isAudioStreamsAvailable) {
|
} else if (isAudioStreamsAvailable) {
|
||||||
|
@ -595,6 +611,7 @@ public class DownloadDialog extends DialogFragment
|
||||||
final StoredDirectoryHelper mainStorage;
|
final StoredDirectoryHelper mainStorage;
|
||||||
final MediaFormat format;
|
final MediaFormat format;
|
||||||
final String mime;
|
final String mime;
|
||||||
|
final String selectedMediaType;
|
||||||
|
|
||||||
// first, build the filename and get the output folder (if possible)
|
// first, build the filename and get the output folder (if possible)
|
||||||
// later, run a very very very large file checking logic
|
// later, run a very very very large file checking logic
|
||||||
|
@ -603,6 +620,7 @@ public class DownloadDialog extends DialogFragment
|
||||||
|
|
||||||
switch (radioStreamsGroup.getCheckedRadioButtonId()) {
|
switch (radioStreamsGroup.getCheckedRadioButtonId()) {
|
||||||
case R.id.audio_button:
|
case R.id.audio_button:
|
||||||
|
selectedMediaType = getString(R.string.last_download_type_audio_key);
|
||||||
mainStorage = mainStorageAudio;
|
mainStorage = mainStorageAudio;
|
||||||
format = audioStreamsAdapter.getItem(selectedAudioIndex).getFormat();
|
format = audioStreamsAdapter.getItem(selectedAudioIndex).getFormat();
|
||||||
switch (format) {
|
switch (format) {
|
||||||
|
@ -617,12 +635,14 @@ public class DownloadDialog extends DialogFragment
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case R.id.video_button:
|
case R.id.video_button:
|
||||||
|
selectedMediaType = getString(R.string.last_download_type_video_key);
|
||||||
mainStorage = mainStorageVideo;
|
mainStorage = mainStorageVideo;
|
||||||
format = videoStreamsAdapter.getItem(selectedVideoIndex).getFormat();
|
format = videoStreamsAdapter.getItem(selectedVideoIndex).getFormat();
|
||||||
mime = format.mimeType;
|
mime = format.mimeType;
|
||||||
filename += format.suffix;
|
filename += format.suffix;
|
||||||
break;
|
break;
|
||||||
case R.id.subtitle_button:
|
case R.id.subtitle_button:
|
||||||
|
selectedMediaType = getString(R.string.last_download_type_subtitle_key);
|
||||||
mainStorage = mainStorageVideo; // subtitle & video files go together
|
mainStorage = mainStorageVideo; // subtitle & video files go together
|
||||||
format = subtitleStreamsAdapter.getItem(selectedSubtitleIndex).getFormat();
|
format = subtitleStreamsAdapter.getItem(selectedSubtitleIndex).getFormat();
|
||||||
mime = format.mimeType;
|
mime = format.mimeType;
|
||||||
|
@ -664,6 +684,11 @@ public class DownloadDialog extends DialogFragment
|
||||||
|
|
||||||
// check for existing file with the same name
|
// check for existing file with the same name
|
||||||
checkSelectedDownload(mainStorage, mainStorage.findFile(filename), filename, mime);
|
checkSelectedDownload(mainStorage, mainStorage.findFile(filename), filename, mime);
|
||||||
|
|
||||||
|
// remember the last media type downloaded by the user
|
||||||
|
prefs.edit()
|
||||||
|
.putString(getString(R.string.last_used_download_type), selectedMediaType)
|
||||||
|
.apply();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void checkSelectedDownload(final StoredDirectoryHelper mainStorage,
|
private void checkSelectedDownload(final StoredDirectoryHelper mainStorage,
|
||||||
|
|
|
@ -202,6 +202,7 @@ public class VideoDetailFragment
|
||||||
private ImageView thumbnailImageView;
|
private ImageView thumbnailImageView;
|
||||||
private ImageView thumbnailPlayButton;
|
private ImageView thumbnailPlayButton;
|
||||||
private AnimatedProgressBar positionView;
|
private AnimatedProgressBar positionView;
|
||||||
|
private ViewGroup playerPlaceholder;
|
||||||
|
|
||||||
private View videoTitleRoot;
|
private View videoTitleRoot;
|
||||||
private TextView videoTitleTextView;
|
private TextView videoTitleTextView;
|
||||||
|
@ -336,6 +337,7 @@ public class VideoDetailFragment
|
||||||
stopPlayerListener();
|
stopPlayerListener();
|
||||||
playerService = null;
|
playerService = null;
|
||||||
player = null;
|
player = null;
|
||||||
|
saveCurrentAndRestoreDefaultBrightness();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -424,7 +426,7 @@ public class VideoDetailFragment
|
||||||
if (currentWorker != null) {
|
if (currentWorker != null) {
|
||||||
currentWorker.dispose();
|
currentWorker.dispose();
|
||||||
}
|
}
|
||||||
setupBrightness(true);
|
saveCurrentAndRestoreDefaultBrightness();
|
||||||
PreferenceManager.getDefaultSharedPreferences(getContext())
|
PreferenceManager.getDefaultSharedPreferences(getContext())
|
||||||
.edit()
|
.edit()
|
||||||
.putString(getString(R.string.stream_info_selected_tab_key),
|
.putString(getString(R.string.stream_info_selected_tab_key),
|
||||||
|
@ -438,7 +440,7 @@ public class VideoDetailFragment
|
||||||
|
|
||||||
activity.sendBroadcast(new Intent(ACTION_VIDEO_FRAGMENT_RESUMED));
|
activity.sendBroadcast(new Intent(ACTION_VIDEO_FRAGMENT_RESUMED));
|
||||||
|
|
||||||
setupBrightness(false);
|
setupBrightness();
|
||||||
|
|
||||||
if (updateFlags != 0) {
|
if (updateFlags != 0) {
|
||||||
if (!isLoading.get() && currentInfo != null) {
|
if (!isLoading.get() && currentInfo != null) {
|
||||||
|
@ -705,6 +707,7 @@ public class VideoDetailFragment
|
||||||
thumbnailBackgroundButton = rootView.findViewById(R.id.detail_thumbnail_root_layout);
|
thumbnailBackgroundButton = rootView.findViewById(R.id.detail_thumbnail_root_layout);
|
||||||
thumbnailImageView = rootView.findViewById(R.id.detail_thumbnail_image_view);
|
thumbnailImageView = rootView.findViewById(R.id.detail_thumbnail_image_view);
|
||||||
thumbnailPlayButton = rootView.findViewById(R.id.detail_thumbnail_play_button);
|
thumbnailPlayButton = rootView.findViewById(R.id.detail_thumbnail_play_button);
|
||||||
|
playerPlaceholder = rootView.findViewById(R.id.player_placeholder);
|
||||||
|
|
||||||
contentRootLayoutHiding = rootView.findViewById(R.id.detail_content_root_hiding);
|
contentRootLayoutHiding = rootView.findViewById(R.id.detail_content_root_hiding);
|
||||||
|
|
||||||
|
@ -1265,17 +1268,15 @@ public class VideoDetailFragment
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
final FrameLayout viewHolder = getView().findViewById(R.id.player_placeholder);
|
|
||||||
|
|
||||||
// Check if viewHolder already contains a child
|
// Check if viewHolder already contains a child
|
||||||
if (player.getRootView().getParent() != viewHolder) {
|
if (player.getRootView().getParent() != playerPlaceholder) {
|
||||||
removeVideoPlayerView();
|
removeVideoPlayerView();
|
||||||
}
|
}
|
||||||
setHeightThumbnail();
|
setHeightThumbnail();
|
||||||
|
|
||||||
// Prevent from re-adding a view multiple times
|
// Prevent from re-adding a view multiple times
|
||||||
if (player.getRootView().getParent() == null) {
|
if (player.getRootView().getParent() == null) {
|
||||||
viewHolder.addView(player.getRootView());
|
playerPlaceholder.addView(player.getRootView());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1290,9 +1291,8 @@ public class VideoDetailFragment
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
final FrameLayout viewHolder = getView().findViewById(R.id.player_placeholder);
|
playerPlaceholder.getLayoutParams().height = FrameLayout.LayoutParams.MATCH_PARENT;
|
||||||
viewHolder.getLayoutParams().height = FrameLayout.LayoutParams.MATCH_PARENT;
|
playerPlaceholder.requestLayout();
|
||||||
viewHolder.requestLayout();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void prepareDescription(final Description description) {
|
private void prepareDescription(final Description description) {
|
||||||
|
@ -1770,9 +1770,19 @@ public class VideoDetailFragment
|
||||||
private void showPlaybackProgress(final long progress, final long duration) {
|
private void showPlaybackProgress(final long progress, final long duration) {
|
||||||
final int progressSeconds = (int) TimeUnit.MILLISECONDS.toSeconds(progress);
|
final int progressSeconds = (int) TimeUnit.MILLISECONDS.toSeconds(progress);
|
||||||
final int durationSeconds = (int) TimeUnit.MILLISECONDS.toSeconds(duration);
|
final int durationSeconds = (int) TimeUnit.MILLISECONDS.toSeconds(duration);
|
||||||
|
// If the old and the new progress values have a big difference then use
|
||||||
|
// animation. Otherwise don't because it affects CPU
|
||||||
|
final boolean shouldAnimate = Math.abs(positionView.getProgress() - progressSeconds) > 2;
|
||||||
positionView.setMax(durationSeconds);
|
positionView.setMax(durationSeconds);
|
||||||
|
if (shouldAnimate) {
|
||||||
positionView.setProgressAnimated(progressSeconds);
|
positionView.setProgressAnimated(progressSeconds);
|
||||||
detailPositionView.setText(Localization.getDurationString(progressSeconds));
|
} else {
|
||||||
|
positionView.setProgress(progressSeconds);
|
||||||
|
}
|
||||||
|
final String position = Localization.getDurationString(progressSeconds);
|
||||||
|
if (position != detailPositionView.getText()) {
|
||||||
|
detailPositionView.setText(position);
|
||||||
|
}
|
||||||
if (positionView.getVisibility() != View.VISIBLE) {
|
if (positionView.getVisibility() != View.VISIBLE) {
|
||||||
animateView(positionView, true, 100);
|
animateView(positionView, true, 100);
|
||||||
animateView(detailPositionView, true, 100);
|
animateView(detailPositionView, true, 100);
|
||||||
|
@ -1899,6 +1909,7 @@ public class VideoDetailFragment
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onFullscreenStateChanged(final boolean fullscreen) {
|
public void onFullscreenStateChanged(final boolean fullscreen) {
|
||||||
|
setupBrightness();
|
||||||
if (playerService.getView() == null || player.getParentActivity() == null) {
|
if (playerService.getView() == null || player.getParentActivity() == null) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -1949,7 +1960,7 @@ public class VideoDetailFragment
|
||||||
(CoordinatorLayout.LayoutParams) appBarLayout.getLayoutParams();
|
(CoordinatorLayout.LayoutParams) appBarLayout.getLayoutParams();
|
||||||
final AppBarLayout.Behavior behavior = (AppBarLayout.Behavior) params.getBehavior();
|
final AppBarLayout.Behavior behavior = (AppBarLayout.Behavior) params.getBehavior();
|
||||||
final ValueAnimator valueAnimator = ValueAnimator
|
final ValueAnimator valueAnimator = ValueAnimator
|
||||||
.ofInt(0, -getView().findViewById(R.id.player_placeholder).getHeight());
|
.ofInt(0, -playerPlaceholder.getHeight());
|
||||||
valueAnimator.setInterpolator(new DecelerateInterpolator());
|
valueAnimator.setInterpolator(new DecelerateInterpolator());
|
||||||
valueAnimator.addUpdateListener(animation -> {
|
valueAnimator.addUpdateListener(animation -> {
|
||||||
behavior.setTopAndBottomOffset((int) animation.getAnimatedValue());
|
behavior.setTopAndBottomOffset((int) animation.getAnimatedValue());
|
||||||
|
@ -2013,30 +2024,42 @@ public class VideoDetailFragment
|
||||||
&& player.getPlayer().getPlaybackState() != Player.STATE_IDLE;
|
&& player.getPlayer().getPlaybackState() != Player.STATE_IDLE;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void setupBrightness(final boolean save) {
|
private void saveCurrentAndRestoreDefaultBrightness() {
|
||||||
|
final WindowManager.LayoutParams lp = activity.getWindow().getAttributes();
|
||||||
|
if (lp.screenBrightness == -1) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
// Save current brightness level
|
||||||
|
PlayerHelper.setScreenBrightness(activity, lp.screenBrightness);
|
||||||
|
|
||||||
|
// Restore the old brightness when fragment.onPause() called or
|
||||||
|
// when a player is in portrait
|
||||||
|
lp.screenBrightness = -1;
|
||||||
|
activity.getWindow().setAttributes(lp);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void setupBrightness() {
|
||||||
if (activity == null) {
|
if (activity == null) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
final WindowManager.LayoutParams lp = activity.getWindow().getAttributes();
|
final WindowManager.LayoutParams lp = activity.getWindow().getAttributes();
|
||||||
if (save) {
|
if (player == null
|
||||||
// Save current brightness level
|
|| !player.videoPlayerSelected()
|
||||||
PlayerHelper.setScreenBrightness(activity, lp.screenBrightness);
|
|| !player.isFullscreen()
|
||||||
|
|| bottomSheetState != BottomSheetBehavior.STATE_EXPANDED) {
|
||||||
// Restore the old brightness when fragment.onPause() called.
|
// Apply system brightness when the player is not in fullscreen
|
||||||
// It means when user leaves this fragment brightness will be set to system brightness
|
saveCurrentAndRestoreDefaultBrightness();
|
||||||
lp.screenBrightness = -1;
|
|
||||||
} else {
|
} else {
|
||||||
// Restore already saved brightness level
|
// Restore already saved brightness level
|
||||||
final float brightnessLevel = PlayerHelper.getScreenBrightness(activity);
|
final float brightnessLevel = PlayerHelper.getScreenBrightness(activity);
|
||||||
if (brightnessLevel <= 0.0f && brightnessLevel > 1.0f) {
|
if (brightnessLevel == lp.screenBrightness) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
lp.screenBrightness = brightnessLevel;
|
lp.screenBrightness = brightnessLevel;
|
||||||
}
|
|
||||||
activity.getWindow().setAttributes(lp);
|
activity.getWindow().setAttributes(lp);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private void checkLandscape() {
|
private void checkLandscape() {
|
||||||
if ((!player.isPlaying() && player.getPlayQueue() != playQueue)
|
if ((!player.isPlaying() && player.getPlayQueue() != playQueue)
|
||||||
|
@ -2158,6 +2181,7 @@ public class VideoDetailFragment
|
||||||
* @param toMain if true than the main fragment will be focused or the player otherwise
|
* @param toMain if true than the main fragment will be focused or the player otherwise
|
||||||
*/
|
*/
|
||||||
private void moveFocusToMainFragment(final boolean toMain) {
|
private void moveFocusToMainFragment(final boolean toMain) {
|
||||||
|
setupBrightness();
|
||||||
final ViewGroup mainFragment = requireActivity().findViewById(R.id.fragment_holder);
|
final ViewGroup mainFragment = requireActivity().findViewById(R.id.fragment_holder);
|
||||||
// Hamburger button steels a focus even under bottomSheet
|
// Hamburger button steels a focus even under bottomSheet
|
||||||
final Toolbar toolbar = requireActivity().findViewById(R.id.toolbar);
|
final Toolbar toolbar = requireActivity().findViewById(R.id.toolbar);
|
||||||
|
@ -2181,7 +2205,7 @@ public class VideoDetailFragment
|
||||||
* Bottom padding should be equal to the mini player's height in this case
|
* Bottom padding should be equal to the mini player's height in this case
|
||||||
*
|
*
|
||||||
* @param showMore whether main fragment should be expanded or not
|
* @param showMore whether main fragment should be expanded or not
|
||||||
* */
|
*/
|
||||||
private void manageSpaceAtTheBottom(final boolean showMore) {
|
private void manageSpaceAtTheBottom(final boolean showMore) {
|
||||||
final int peekHeight = getResources().getDimensionPixelSize(R.dimen.mini_player_height);
|
final int peekHeight = getResources().getDimensionPixelSize(R.dimen.mini_player_height);
|
||||||
final ViewGroup holder = requireActivity().findViewById(R.id.fragment_holder);
|
final ViewGroup holder = requireActivity().findViewById(R.id.fragment_holder);
|
||||||
|
|
|
@ -55,8 +55,8 @@ import com.nostra13.universalimageloader.core.assist.FailReason;
|
||||||
import com.nostra13.universalimageloader.core.listener.ImageLoadingListener;
|
import com.nostra13.universalimageloader.core.listener.ImageLoadingListener;
|
||||||
|
|
||||||
import org.schabi.newpipe.App;
|
import org.schabi.newpipe.App;
|
||||||
import org.schabi.newpipe.BuildConfig;
|
|
||||||
import org.schabi.newpipe.DownloaderImpl;
|
import org.schabi.newpipe.DownloaderImpl;
|
||||||
|
import org.schabi.newpipe.MainActivity;
|
||||||
import org.schabi.newpipe.R;
|
import org.schabi.newpipe.R;
|
||||||
import org.schabi.newpipe.SponsorBlockApiTask;
|
import org.schabi.newpipe.SponsorBlockApiTask;
|
||||||
import org.schabi.newpipe.extractor.stream.StreamInfo;
|
import org.schabi.newpipe.extractor.stream.StreamInfo;
|
||||||
|
@ -103,7 +103,7 @@ import static java.util.concurrent.TimeUnit.MILLISECONDS;
|
||||||
@SuppressWarnings({"WeakerAccess"})
|
@SuppressWarnings({"WeakerAccess"})
|
||||||
public abstract class BasePlayer implements
|
public abstract class BasePlayer implements
|
||||||
Player.EventListener, PlaybackListener, ImageLoadingListener {
|
Player.EventListener, PlaybackListener, ImageLoadingListener {
|
||||||
public static final boolean DEBUG = !BuildConfig.BUILD_TYPE.equals("release");
|
public static final boolean DEBUG = MainActivity.DEBUG;
|
||||||
@NonNull
|
@NonNull
|
||||||
public static final String TAG = "BasePlayer";
|
public static final String TAG = "BasePlayer";
|
||||||
|
|
||||||
|
@ -989,7 +989,6 @@ public abstract class BasePlayer implements
|
||||||
}
|
}
|
||||||
setRecovery();
|
setRecovery();
|
||||||
|
|
||||||
final Throwable cause = error.getCause();
|
|
||||||
if (error instanceof BehindLiveWindowException) {
|
if (error instanceof BehindLiveWindowException) {
|
||||||
reload();
|
reload();
|
||||||
} else {
|
} else {
|
||||||
|
@ -1516,6 +1515,11 @@ public abstract class BasePlayer implements
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
final StreamInfo currentInfo = currentMetadata.getMetadata();
|
final StreamInfo currentInfo = currentMetadata.getMetadata();
|
||||||
|
if (playQueue != null) {
|
||||||
|
// Save current position. It will help to restore this position once a user
|
||||||
|
// wants to play prev or next stream from the queue
|
||||||
|
playQueue.setRecovery(playQueue.getIndex(), simpleExoPlayer.getContentPosition());
|
||||||
|
}
|
||||||
savePlaybackState(currentInfo, simpleExoPlayer.getCurrentPosition());
|
savePlaybackState(currentInfo, simpleExoPlayer.getCurrentPosition());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -184,6 +184,9 @@ public final class MainPlayer extends Service {
|
||||||
@Override
|
@Override
|
||||||
public void onTaskRemoved(final Intent rootIntent) {
|
public void onTaskRemoved(final Intent rootIntent) {
|
||||||
super.onTaskRemoved(rootIntent);
|
super.onTaskRemoved(rootIntent);
|
||||||
|
if (!playerImpl.videoPlayerSelected()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
onDestroy();
|
onDestroy();
|
||||||
// Unload from memory completely
|
// Unload from memory completely
|
||||||
Runtime.getRuntime().halt(0);
|
Runtime.getRuntime().halt(0);
|
||||||
|
|
|
@ -329,18 +329,16 @@ public class VideoPlayerImpl extends VideoPlayer
|
||||||
if (popupPlayerSelected()) {
|
if (popupPlayerSelected()) {
|
||||||
final float captionRatio = (captionScale - 1.0f) / 5.0f + 1.0f;
|
final float captionRatio = (captionScale - 1.0f) / 5.0f + 1.0f;
|
||||||
view.setFractionalTextSize(SubtitleView.DEFAULT_TEXT_SIZE_FRACTION * captionRatio);
|
view.setFractionalTextSize(SubtitleView.DEFAULT_TEXT_SIZE_FRACTION * captionRatio);
|
||||||
view.setApplyEmbeddedStyles(captionStyle.equals(CaptionStyleCompat.DEFAULT));
|
|
||||||
view.setStyle(captionStyle);
|
|
||||||
} else {
|
} else {
|
||||||
final DisplayMetrics metrics = context.getResources().getDisplayMetrics();
|
final DisplayMetrics metrics = context.getResources().getDisplayMetrics();
|
||||||
final int minimumLength = Math.min(metrics.heightPixels, metrics.widthPixels);
|
final int minimumLength = Math.min(metrics.heightPixels, metrics.widthPixels);
|
||||||
final float captionRatioInverse = 20f + 4f * (1.0f - captionScale);
|
final float captionRatioInverse = 20f + 4f * (1.0f - captionScale);
|
||||||
view.setFixedTextSize(TypedValue.COMPLEX_UNIT_PX,
|
view.setFixedTextSize(TypedValue.COMPLEX_UNIT_PX,
|
||||||
(float) minimumLength / captionRatioInverse);
|
(float) minimumLength / captionRatioInverse);
|
||||||
|
}
|
||||||
view.setApplyEmbeddedStyles(captionStyle.equals(CaptionStyleCompat.DEFAULT));
|
view.setApplyEmbeddedStyles(captionStyle.equals(CaptionStyleCompat.DEFAULT));
|
||||||
view.setStyle(captionStyle);
|
view.setStyle(captionStyle);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This method ensures that popup and main players have different look.
|
* This method ensures that popup and main players have different look.
|
||||||
|
|
|
@ -4,6 +4,7 @@ import android.content.Context;
|
||||||
import android.graphics.Rect;
|
import android.graphics.Rect;
|
||||||
import android.util.AttributeSet;
|
import android.util.AttributeSet;
|
||||||
import android.view.MotionEvent;
|
import android.view.MotionEvent;
|
||||||
|
import android.view.View;
|
||||||
import android.view.ViewGroup;
|
import android.view.ViewGroup;
|
||||||
import android.widget.FrameLayout;
|
import android.widget.FrameLayout;
|
||||||
import androidx.annotation.NonNull;
|
import androidx.annotation.NonNull;
|
||||||
|
@ -25,7 +26,7 @@ public class CustomBottomSheetBehavior extends BottomSheetBehavior<FrameLayout>
|
||||||
private boolean skippingInterception = false;
|
private boolean skippingInterception = false;
|
||||||
private final List<Integer> skipInterceptionOfElements = Arrays.asList(
|
private final List<Integer> skipInterceptionOfElements = Arrays.asList(
|
||||||
R.id.detail_content_root_layout, R.id.relatedStreamsLayout,
|
R.id.detail_content_root_layout, R.id.relatedStreamsLayout,
|
||||||
R.id.playQueuePanel, R.id.viewpager);
|
R.id.playQueuePanel, R.id.viewpager, R.id.bottomControls);
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean onInterceptTouchEvent(@NonNull final CoordinatorLayout parent,
|
public boolean onInterceptTouchEvent(@NonNull final CoordinatorLayout parent,
|
||||||
|
@ -51,6 +52,13 @@ public class CustomBottomSheetBehavior extends BottomSheetBehavior<FrameLayout>
|
||||||
visible = viewGroup.getGlobalVisibleRect(globalRect);
|
visible = viewGroup.getGlobalVisibleRect(globalRect);
|
||||||
if (visible
|
if (visible
|
||||||
&& globalRect.contains((int) event.getRawX(), (int) event.getRawY())) {
|
&& globalRect.contains((int) event.getRawX(), (int) event.getRawY())) {
|
||||||
|
// Makes bottom part of the player draggable in portrait when
|
||||||
|
// playbackControlRoot is hidden
|
||||||
|
if (element == R.id.bottomControls
|
||||||
|
&& child.findViewById(R.id.playbackControlRoot)
|
||||||
|
.getVisibility() != View.VISIBLE) {
|
||||||
|
return super.onInterceptTouchEvent(parent, child, event);
|
||||||
|
}
|
||||||
skippingInterception = true;
|
skippingInterception = true;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
|
@ -202,7 +202,8 @@ public class PlayerGestureListener
|
||||||
|
|
||||||
private boolean onScrollInMain(final MotionEvent initialEvent, final MotionEvent movingEvent,
|
private boolean onScrollInMain(final MotionEvent initialEvent, final MotionEvent movingEvent,
|
||||||
final float distanceX, final float distanceY) {
|
final float distanceX, final float distanceY) {
|
||||||
if (!isVolumeGestureEnabled && !isBrightnessGestureEnabled) {
|
if ((!isVolumeGestureEnabled && !isBrightnessGestureEnabled)
|
||||||
|
|| !playerImpl.isFullscreen()) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -7,7 +7,7 @@ import androidx.annotation.Nullable;
|
||||||
|
|
||||||
import org.reactivestreams.Subscriber;
|
import org.reactivestreams.Subscriber;
|
||||||
import org.reactivestreams.Subscription;
|
import org.reactivestreams.Subscription;
|
||||||
import org.schabi.newpipe.BuildConfig;
|
import org.schabi.newpipe.MainActivity;
|
||||||
import org.schabi.newpipe.player.playqueue.events.AppendEvent;
|
import org.schabi.newpipe.player.playqueue.events.AppendEvent;
|
||||||
import org.schabi.newpipe.player.playqueue.events.ErrorEvent;
|
import org.schabi.newpipe.player.playqueue.events.ErrorEvent;
|
||||||
import org.schabi.newpipe.player.playqueue.events.InitEvent;
|
import org.schabi.newpipe.player.playqueue.events.InitEvent;
|
||||||
|
@ -44,7 +44,7 @@ import io.reactivex.subjects.BehaviorSubject;
|
||||||
*/
|
*/
|
||||||
public abstract class PlayQueue implements Serializable {
|
public abstract class PlayQueue implements Serializable {
|
||||||
private final String TAG = "PlayQueue@" + Integer.toHexString(hashCode());
|
private final String TAG = "PlayQueue@" + Integer.toHexString(hashCode());
|
||||||
public static final boolean DEBUG = !BuildConfig.BUILD_TYPE.equals("release");
|
public static final boolean DEBUG = MainActivity.DEBUG;
|
||||||
|
|
||||||
private ArrayList<PlayQueueItem> backup;
|
private ArrayList<PlayQueueItem> backup;
|
||||||
private ArrayList<PlayQueueItem> streams;
|
private ArrayList<PlayQueueItem> streams;
|
||||||
|
|
|
@ -106,7 +106,7 @@ public class VideoPlaybackResolver implements PlaybackResolver {
|
||||||
SELECTION_FLAG_AUTOSELECT,
|
SELECTION_FLAG_AUTOSELECT,
|
||||||
PlayerHelper.captionLanguageOf(context, subtitle));
|
PlayerHelper.captionLanguageOf(context, subtitle));
|
||||||
final MediaSource textSource = dataSource.getSampleMediaSourceFactory()
|
final MediaSource textSource = dataSource.getSampleMediaSourceFactory()
|
||||||
.createMediaSource(Uri.parse(subtitle.getURL()), textFormat, TIME_UNSET);
|
.createMediaSource(Uri.parse(subtitle.getUrl()), textFormat, TIME_UNSET);
|
||||||
mediaSources.add(textSource);
|
mediaSources.add(textSource);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,12 +4,12 @@ import android.os.Bundle;
|
||||||
|
|
||||||
import androidx.preference.Preference;
|
import androidx.preference.Preference;
|
||||||
|
|
||||||
import org.schabi.newpipe.BuildConfig;
|
|
||||||
import org.schabi.newpipe.CheckForNewAppVersionTask;
|
import org.schabi.newpipe.CheckForNewAppVersionTask;
|
||||||
|
import org.schabi.newpipe.MainActivity;
|
||||||
import org.schabi.newpipe.R;
|
import org.schabi.newpipe.R;
|
||||||
|
|
||||||
public class MainSettingsFragment extends BasePreferenceFragment {
|
public class MainSettingsFragment extends BasePreferenceFragment {
|
||||||
public static final boolean DEBUG = !BuildConfig.BUILD_TYPE.equals("release");
|
public static final boolean DEBUG = MainActivity.DEBUG;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onCreatePreferences(final Bundle savedInstanceState, final String rootKey) {
|
public void onCreatePreferences(final Bundle savedInstanceState, final String rootKey) {
|
||||||
|
|
|
@ -155,7 +155,7 @@ public class DownloadMissionRecover extends Thread {
|
||||||
for (SubtitlesStream subtitles : mExtractor.getSubtitles(mRecovery.format)) {
|
for (SubtitlesStream subtitles : mExtractor.getSubtitles(mRecovery.format)) {
|
||||||
String tag = subtitles.getLanguageTag();
|
String tag = subtitles.getLanguageTag();
|
||||||
if (tag.equals(mRecovery.desired) && subtitles.isAutoGenerated() == mRecovery.desired2) {
|
if (tag.equals(mRecovery.desired) && subtitles.isAutoGenerated() == mRecovery.desired2) {
|
||||||
url = subtitles.getURL();
|
url = subtitles.getUrl();
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -236,6 +236,11 @@
|
||||||
<string name="clear_playback_states_key" translatable="false">clear_playback_states</string>
|
<string name="clear_playback_states_key" translatable="false">clear_playback_states</string>
|
||||||
<string name="clear_search_history_key" translatable="false">clear_search_history</string>
|
<string name="clear_search_history_key" translatable="false">clear_search_history</string>
|
||||||
|
|
||||||
|
<string name="last_used_download_type" translatable="false">@string/last_download_type_video_key</string>
|
||||||
|
<string name="last_download_type_video_key" translatable="false">last_dl_type_video</string>
|
||||||
|
<string name="last_download_type_audio_key" translatable="false">last_dl_type_audio</string>
|
||||||
|
<string name="last_download_type_subtitle_key" translatable="false">last_dl_type_subtitle</string>
|
||||||
|
|
||||||
<string name="downloads_storage_ask" translatable="false">downloads_storage_ask</string>
|
<string name="downloads_storage_ask" translatable="false">downloads_storage_ask</string>
|
||||||
<string name="storage_use_saf" translatable="false">storage_use_saf</string>
|
<string name="storage_use_saf" translatable="false">storage_use_saf</string>
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue