SponsorBlock: Merge branch 'dev' into sponsorblock

This commit is contained in:
polymorphicshade 2020-09-05 22:13:36 -06:00
commit 62b109171c
17 changed files with 154 additions and 52 deletions

View file

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

View file

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

View file

@ -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) {

View file

@ -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);
}
}
} }

View file

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

View file

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

View file

@ -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);

View file

@ -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());
} }

View file

@ -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);

View file

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

View file

@ -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;
} }

View file

@ -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;
} }

View file

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

View file

@ -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);
} }
} }

View file

@ -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) {

View file

@ -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;
} }
} }

View file

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