mirror of
				https://github.com/TeamNewPipe/NewPipe
				synced 2025-10-31 07:13:00 +00:00 
			
		
		
		
	Merge branch 'TeamNewPipe:dev' into dev
This commit is contained in:
		| @@ -16,8 +16,8 @@ android { | ||||
|         resValue "string", "app_name", "NewPipe" | ||||
|         minSdkVersion 19 | ||||
|         targetSdkVersion 29 | ||||
|         versionCode 980 | ||||
|         versionName "0.21.14" | ||||
|         versionCode 981 | ||||
|         versionName "0.21.15" | ||||
|  | ||||
|         multiDexEnabled true | ||||
|  | ||||
|   | ||||
| @@ -63,6 +63,7 @@ public final class FlingBehavior extends AppBarLayout.Behavior { | ||||
|         return consumed == dy; | ||||
|     } | ||||
|  | ||||
|     @Override | ||||
|     public boolean onInterceptTouchEvent(@NonNull final CoordinatorLayout parent, | ||||
|                                          @NonNull final AppBarLayout child, | ||||
|                                          @NonNull final MotionEvent ev) { | ||||
|   | ||||
| @@ -685,7 +685,7 @@ public final class VideoDetailFragment | ||||
|         }); | ||||
|  | ||||
|         setupBottomPlayer(); | ||||
|         if (!playerHolder.bound) { | ||||
|         if (!playerHolder.isBound()) { | ||||
|             setHeightThumbnail(); | ||||
|         } else { | ||||
|             playerHolder.startService(false, this); | ||||
| @@ -1434,7 +1434,7 @@ public final class VideoDetailFragment | ||||
|                             bottomSheetBehavior.setState(BottomSheetBehavior.STATE_COLLAPSED); | ||||
|                         } | ||||
|                         // Rebound to the service if it was closed via notification or mini player | ||||
|                         if (!playerHolder.bound) { | ||||
|                         if (!playerHolder.isBound()) { | ||||
|                             playerHolder.startService( | ||||
|                                     false, VideoDetailFragment.this); | ||||
|                         } | ||||
|   | ||||
| @@ -724,7 +724,7 @@ public class SearchFragment extends BaseListFragment<SearchInfo, ListExtractor.I | ||||
|     @Override | ||||
|     public boolean onBackPressed() { | ||||
|         if (suggestionsPanelVisible | ||||
|                 && infoListAdapter.getItemsList().size() > 0 | ||||
|                 && !infoListAdapter.getItemsList().isEmpty() | ||||
|                 && !isLoading.get()) { | ||||
|             hideSuggestionsPanel(); | ||||
|             hideKeyboardSearch(); | ||||
|   | ||||
| @@ -54,11 +54,9 @@ class ChannelItem( | ||||
|             context.getString(R.string.subscribers_count_not_available) | ||||
|         } | ||||
|  | ||||
|         if (itemVersion == ItemVersion.NORMAL) { | ||||
|             if (infoItem.streamCount >= 0) { | ||||
|                 val formattedVideoAmount = Localization.localizeStreamCount(context, infoItem.streamCount) | ||||
|                 details = Localization.concatenateStrings(details, formattedVideoAmount) | ||||
|             } | ||||
|         if (itemVersion == ItemVersion.NORMAL && infoItem.streamCount >= 0) { | ||||
|             val formattedVideoAmount = Localization.localizeStreamCount(context, infoItem.streamCount) | ||||
|             details = Localization.concatenateStrings(details, formattedVideoAmount) | ||||
|         } | ||||
|         return details | ||||
|     } | ||||
|   | ||||
| @@ -2348,7 +2348,8 @@ public final class Player implements | ||||
|         NotificationUtil.getInstance().createNotificationIfNeededAndUpdate(this, false); | ||||
|     } | ||||
|  | ||||
|     private void setRepeatModeButton(final AppCompatImageButton imageButton, final int repeatMode) { | ||||
|     private void setRepeatModeButton(final AppCompatImageButton imageButton, | ||||
|                                      @RepeatMode final int repeatMode) { | ||||
|         switch (repeatMode) { | ||||
|             case REPEAT_MODE_OFF: | ||||
|                 imageButton.setImageResource(R.drawable.exo_controls_repeat_off); | ||||
| @@ -2362,7 +2363,7 @@ public final class Player implements | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     private void setShuffleButton(final ImageButton button, final boolean shuffled) { | ||||
|     private void setShuffleButton(@NonNull final ImageButton button, final boolean shuffled) { | ||||
|         button.setImageAlpha(shuffled ? 255 : 77); | ||||
|     } | ||||
|     //endregion | ||||
| @@ -2387,7 +2388,7 @@ public final class Player implements | ||||
|         return !exoPlayerIsNull() && simpleExoPlayer.getVolume() == 0; | ||||
|     } | ||||
|  | ||||
|     private void setMuteButton(final ImageButton button, final boolean isMuted) { | ||||
|     private void setMuteButton(@NonNull final ImageButton button, final boolean isMuted) { | ||||
|         button.setImageDrawable(AppCompatResources.getDrawable(context, isMuted | ||||
|                 ? R.drawable.ic_volume_off : R.drawable.ic_volume_up)); | ||||
|     } | ||||
| @@ -2876,7 +2877,7 @@ public final class Player implements | ||||
|         databaseUpdateDisposable | ||||
|                 .add(recordManager.saveStreamState(currentMetadata.getMetadata(), progressMillis) | ||||
|                 .observeOn(AndroidSchedulers.mainThread()) | ||||
|                 .doOnError((e) -> { | ||||
|                 .doOnError(e -> { | ||||
|                     if (DEBUG) { | ||||
|                         e.printStackTrace(); | ||||
|                     } | ||||
| @@ -3386,7 +3387,7 @@ public final class Player implements | ||||
|         playbackSpeedPopupMenu.setOnDismissListener(this); | ||||
|     } | ||||
|  | ||||
|     private void buildCaptionMenu(final List<String> availableLanguages) { | ||||
|     private void buildCaptionMenu(@NonNull final List<String> availableLanguages) { | ||||
|         if (captionPopupMenu == null) { | ||||
|             return; | ||||
|         } | ||||
| @@ -3454,7 +3455,7 @@ public final class Player implements | ||||
|      * Called when an item of the quality selector or the playback speed selector is selected. | ||||
|      */ | ||||
|     @Override | ||||
|     public boolean onMenuItemClick(final MenuItem menuItem) { | ||||
|     public boolean onMenuItemClick(@NonNull final MenuItem menuItem) { | ||||
|         if (DEBUG) { | ||||
|             Log.d(TAG, "onMenuItemClick() called with: " | ||||
|                     + "menuItem = [" + menuItem + "], " | ||||
| @@ -3491,7 +3492,7 @@ public final class Player implements | ||||
|      * Called when some popup menu is dismissed. | ||||
|      */ | ||||
|     @Override | ||||
|     public void onDismiss(final PopupMenu menu) { | ||||
|     public void onDismiss(@Nullable final PopupMenu menu) { | ||||
|         if (DEBUG) { | ||||
|             Log.d(TAG, "onDismiss() called with: menu = [" + menu + "]"); | ||||
|         } | ||||
| @@ -3544,7 +3545,7 @@ public final class Player implements | ||||
|         isSomePopupMenuVisible = true; | ||||
|     } | ||||
|  | ||||
|     private void setPlaybackQuality(final String quality) { | ||||
|     private void setPlaybackQuality(@Nullable final String quality) { | ||||
|         videoResolver.setPlaybackQuality(quality); | ||||
|     } | ||||
|     //endregion | ||||
| @@ -3568,7 +3569,7 @@ public final class Player implements | ||||
|             final int minimumLength = Math.min(metrics.heightPixels, metrics.widthPixels); | ||||
|             final float captionRatioInverse = 20f + 4f * (1.0f - captionScale); | ||||
|             binding.subtitleView.setFixedTextSize( | ||||
|                     TypedValue.COMPLEX_UNIT_PX, (float) minimumLength / captionRatioInverse); | ||||
|                     TypedValue.COMPLEX_UNIT_PX, minimumLength / captionRatioInverse); | ||||
|         } | ||||
|         binding.subtitleView.setApplyEmbeddedStyles(captionStyle == CaptionStyleCompat.DEFAULT); | ||||
|         binding.subtitleView.setStyle(captionStyle); | ||||
| @@ -3845,7 +3846,7 @@ public final class Player implements | ||||
|     } | ||||
|  | ||||
|     @Override // exoplayer listener | ||||
|     public void onVideoSizeChanged(final VideoSize videoSize) { | ||||
|     public void onVideoSizeChanged(@NonNull final VideoSize videoSize) { | ||||
|         if (DEBUG) { | ||||
|             Log.d(TAG, "onVideoSizeChanged() called with: " | ||||
|                     + "width / height = [" + videoSize.width + " / " + videoSize.height | ||||
| @@ -3959,7 +3960,7 @@ public final class Player implements | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     private int distanceFromCloseButton(final MotionEvent popupMotionEvent) { | ||||
|     private int distanceFromCloseButton(@NonNull final MotionEvent popupMotionEvent) { | ||||
|         final int closeOverlayButtonX = closeOverlayBinding.closeButton.getLeft() | ||||
|                 + closeOverlayBinding.closeButton.getWidth() / 2; | ||||
|         final int closeOverlayButtonY = closeOverlayBinding.closeButton.getTop() | ||||
| @@ -3978,7 +3979,7 @@ public final class Player implements | ||||
|         return buttonRadius * 1.2f; | ||||
|     } | ||||
|  | ||||
|     public boolean isInsideClosingRadius(final MotionEvent popupMotionEvent) { | ||||
|     public boolean isInsideClosingRadius(@NonNull final MotionEvent popupMotionEvent) { | ||||
|         return distanceFromCloseButton(popupMotionEvent) <= getClosingRadius(); | ||||
|     } | ||||
|     //endregion | ||||
| @@ -4098,6 +4099,7 @@ public final class Player implements | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     @Nullable | ||||
|     public AppCompatActivity getParentActivity() { | ||||
|         // ! instanceof ViewGroup means that view was added via windowManager for Popup | ||||
|         if (binding == null || !(binding.getRoot().getParent() instanceof ViewGroup)) { | ||||
|   | ||||
| @@ -1,5 +1,12 @@ | ||||
| package org.schabi.newpipe.player.event; | ||||
|  | ||||
| import static org.schabi.newpipe.ktx.AnimationType.ALPHA; | ||||
| import static org.schabi.newpipe.ktx.AnimationType.SCALE_AND_ALPHA; | ||||
| import static org.schabi.newpipe.ktx.ViewUtils.animate; | ||||
| import static org.schabi.newpipe.player.Player.DEFAULT_CONTROLS_DURATION; | ||||
| import static org.schabi.newpipe.player.Player.DEFAULT_CONTROLS_HIDE_TIME; | ||||
| import static org.schabi.newpipe.player.Player.STATE_PLAYING; | ||||
|  | ||||
| import android.app.Activity; | ||||
| import android.util.Log; | ||||
| import android.view.MotionEvent; | ||||
| @@ -8,22 +15,15 @@ import android.view.Window; | ||||
| import android.view.WindowManager; | ||||
| import android.widget.ProgressBar; | ||||
|  | ||||
| import androidx.annotation.NonNull; | ||||
| import androidx.appcompat.content.res.AppCompatResources; | ||||
|  | ||||
| import org.jetbrains.annotations.NotNull; | ||||
| import org.schabi.newpipe.MainActivity; | ||||
| import org.schabi.newpipe.R; | ||||
| import org.schabi.newpipe.player.MainPlayer; | ||||
| import org.schabi.newpipe.player.Player; | ||||
| import org.schabi.newpipe.player.helper.PlayerHelper; | ||||
|  | ||||
| import static org.schabi.newpipe.ktx.AnimationType.ALPHA; | ||||
| import static org.schabi.newpipe.ktx.AnimationType.SCALE_AND_ALPHA; | ||||
| import static org.schabi.newpipe.ktx.ViewUtils.animate; | ||||
| import static org.schabi.newpipe.player.Player.DEFAULT_CONTROLS_DURATION; | ||||
| import static org.schabi.newpipe.player.Player.DEFAULT_CONTROLS_HIDE_TIME; | ||||
| import static org.schabi.newpipe.player.Player.STATE_PLAYING; | ||||
|  | ||||
| /** | ||||
|  * GestureListener for the player | ||||
|  * | ||||
| @@ -45,8 +45,8 @@ public class PlayerGestureListener | ||||
|     } | ||||
|  | ||||
|     @Override | ||||
|     public void onDoubleTap(@NotNull final MotionEvent event, | ||||
|                             @NotNull final DisplayPortion portion) { | ||||
|     public void onDoubleTap(@NonNull final MotionEvent event, | ||||
|                             @NonNull final DisplayPortion portion) { | ||||
|         if (DEBUG) { | ||||
|             Log.d(TAG, "onDoubleTap called with playerType = [" | ||||
|                     + player.getPlayerType() + "], portion = [" + portion + "]"); | ||||
| @@ -65,7 +65,7 @@ public class PlayerGestureListener | ||||
|     } | ||||
|  | ||||
|     @Override | ||||
|     public void onSingleTap(@NotNull final MainPlayer.PlayerType playerType) { | ||||
|     public void onSingleTap(@NonNull final MainPlayer.PlayerType playerType) { | ||||
|         if (DEBUG) { | ||||
|             Log.d(TAG, "onSingleTap called with playerType = [" + player.getPlayerType() + "]"); | ||||
|         } | ||||
| @@ -85,10 +85,10 @@ public class PlayerGestureListener | ||||
|     } | ||||
|  | ||||
|     @Override | ||||
|     public void onScroll(@NotNull final MainPlayer.PlayerType playerType, | ||||
|                          @NotNull final DisplayPortion portion, | ||||
|                          @NotNull final MotionEvent initialEvent, | ||||
|                          @NotNull final MotionEvent movingEvent, | ||||
|     public void onScroll(@NonNull final MainPlayer.PlayerType playerType, | ||||
|                          @NonNull final DisplayPortion portion, | ||||
|                          @NonNull final MotionEvent initialEvent, | ||||
|                          @NonNull final MotionEvent movingEvent, | ||||
|                          final float distanceX, final float distanceY) { | ||||
|         if (DEBUG) { | ||||
|             Log.d(TAG, "onScroll called with playerType = [" | ||||
| @@ -197,8 +197,8 @@ public class PlayerGestureListener | ||||
|     } | ||||
|  | ||||
|     @Override | ||||
|     public void onScrollEnd(@NotNull final MainPlayer.PlayerType playerType, | ||||
|                             @NotNull final MotionEvent event) { | ||||
|     public void onScrollEnd(@NonNull final MainPlayer.PlayerType playerType, | ||||
|                             @NonNull final MotionEvent event) { | ||||
|         if (DEBUG) { | ||||
|             Log.d(TAG, "onScrollEnd called with playerType = [" | ||||
|                 + player.getPlayerType() + "]"); | ||||
|   | ||||
| @@ -35,13 +35,13 @@ public final class PlayerHolder { | ||||
|         return PlayerHolder.instance; | ||||
|     } | ||||
|  | ||||
|     private final boolean DEBUG = MainActivity.DEBUG; | ||||
|     private final String TAG = PlayerHolder.class.getSimpleName(); | ||||
|     private static final boolean DEBUG = MainActivity.DEBUG; | ||||
|     private static final String TAG = PlayerHolder.class.getSimpleName(); | ||||
|  | ||||
|     private PlayerServiceExtendedEventListener listener; | ||||
|  | ||||
|     private final PlayerServiceConnection serviceConnection = new PlayerServiceConnection(); | ||||
|     public boolean bound; | ||||
|     private boolean bound; | ||||
|     private MainPlayer playerService; | ||||
|     private Player player; | ||||
|  | ||||
| @@ -70,6 +70,10 @@ public final class PlayerHolder { | ||||
|         return player != null; | ||||
|     } | ||||
|  | ||||
|     public boolean isBound() { | ||||
|         return bound; | ||||
|     } | ||||
|  | ||||
|     public int getQueueSize() { | ||||
|         return isPlayerOpen() ? player.getPlayQueue().size() : 0; | ||||
|     } | ||||
| @@ -148,7 +152,7 @@ public final class PlayerHolder { | ||||
|             } | ||||
|             startPlayerListener(); | ||||
|         } | ||||
|     }; | ||||
|     } | ||||
|  | ||||
|     private void bind(final Context context) { | ||||
|         if (DEBUG) { | ||||
|   | ||||
| @@ -18,7 +18,7 @@ import java.util.Objects; | ||||
|  | ||||
| public abstract class BasePreferenceFragment extends PreferenceFragmentCompat { | ||||
|     protected final String TAG = getClass().getSimpleName() + "@" + Integer.toHexString(hashCode()); | ||||
|     protected final boolean DEBUG = MainActivity.DEBUG; | ||||
|     protected static final boolean DEBUG = MainActivity.DEBUG; | ||||
|  | ||||
|     SharedPreferences defaultPreferences; | ||||
|  | ||||
|   | ||||
| @@ -36,6 +36,10 @@ import java.util.Objects; | ||||
| public abstract class Tab { | ||||
|     private static final String JSON_TAB_ID_KEY = "tab_id"; | ||||
|  | ||||
|     private static final String NO_NAME = "<no-name>"; | ||||
|     private static final String NO_ID = "<no-id>"; | ||||
|     private static final String NO_URL = "<no-url>"; | ||||
|  | ||||
|     Tab() { | ||||
|     } | ||||
|  | ||||
| @@ -185,7 +189,9 @@ public abstract class Tab { | ||||
|  | ||||
|         @Override | ||||
|         public String getTabName(final Context context) { | ||||
|             return "NewPipe"; //context.getString(R.string.blank_page_summary); | ||||
|             // TODO: find a better name for the blank tab (maybe "blank_tab") or replace it with | ||||
|             //       context.getString(R.string.app_name); | ||||
|             return "NewPipe"; // context.getString(R.string.blank_page_summary); | ||||
|         } | ||||
|  | ||||
|         @DrawableRes | ||||
| @@ -309,7 +315,7 @@ public abstract class Tab { | ||||
|         private String kioskId; | ||||
|  | ||||
|         private KioskTab() { | ||||
|             this(-1, "<no-id>"); | ||||
|             this(-1, NO_ID); | ||||
|         } | ||||
|  | ||||
|         public KioskTab(final int kioskServiceId, final String kioskId) { | ||||
| @@ -357,7 +363,7 @@ public abstract class Tab { | ||||
|         @Override | ||||
|         protected void readDataFromJson(final JsonObject jsonObject) { | ||||
|             kioskServiceId = jsonObject.getInt(JSON_KIOSK_SERVICE_ID_KEY, -1); | ||||
|             kioskId = jsonObject.getString(JSON_KIOSK_ID_KEY, "<no-id>"); | ||||
|             kioskId = jsonObject.getString(JSON_KIOSK_ID_KEY, NO_ID); | ||||
|         } | ||||
|  | ||||
|         @Override | ||||
| @@ -395,7 +401,7 @@ public abstract class Tab { | ||||
|         private String channelName; | ||||
|  | ||||
|         private ChannelTab() { | ||||
|             this(-1, "<no-url>", "<no-name>"); | ||||
|             this(-1, NO_URL, NO_NAME); | ||||
|         } | ||||
|  | ||||
|         public ChannelTab(final int channelServiceId, final String channelUrl, | ||||
| @@ -440,8 +446,8 @@ public abstract class Tab { | ||||
|         @Override | ||||
|         protected void readDataFromJson(final JsonObject jsonObject) { | ||||
|             channelServiceId = jsonObject.getInt(JSON_CHANNEL_SERVICE_ID_KEY, -1); | ||||
|             channelUrl = jsonObject.getString(JSON_CHANNEL_URL_KEY, "<no-url>"); | ||||
|             channelName = jsonObject.getString(JSON_CHANNEL_NAME_KEY, "<no-name>"); | ||||
|             channelUrl = jsonObject.getString(JSON_CHANNEL_URL_KEY, NO_URL); | ||||
|             channelName = jsonObject.getString(JSON_CHANNEL_NAME_KEY, NO_NAME); | ||||
|         } | ||||
|  | ||||
|         @Override | ||||
| @@ -527,7 +533,7 @@ public abstract class Tab { | ||||
|         private LocalItemType playlistType; | ||||
|  | ||||
|         private PlaylistTab() { | ||||
|             this(-1, "<no-name>"); | ||||
|             this(-1, NO_NAME); | ||||
|         } | ||||
|  | ||||
|         public PlaylistTab(final long playlistId, final String playlistName) { | ||||
| @@ -535,7 +541,7 @@ public abstract class Tab { | ||||
|             this.playlistId = playlistId; | ||||
|             this.playlistType = LocalItemType.PLAYLIST_LOCAL_ITEM; | ||||
|             this.playlistServiceId = -1; | ||||
|             this.playlistUrl = "<no-url>"; | ||||
|             this.playlistUrl = NO_URL; | ||||
|         } | ||||
|  | ||||
|         public PlaylistTab(final int playlistServiceId, final String playlistUrl, | ||||
| @@ -589,8 +595,8 @@ public abstract class Tab { | ||||
|         @Override | ||||
|         protected void readDataFromJson(final JsonObject jsonObject) { | ||||
|             playlistServiceId = jsonObject.getInt(JSON_PLAYLIST_SERVICE_ID_KEY, -1); | ||||
|             playlistUrl = jsonObject.getString(JSON_PLAYLIST_URL_KEY, "<no-url>"); | ||||
|             playlistName = jsonObject.getString(JSON_PLAYLIST_NAME_KEY, "<no-name>"); | ||||
|             playlistUrl = jsonObject.getString(JSON_PLAYLIST_URL_KEY, NO_URL); | ||||
|             playlistName = jsonObject.getString(JSON_PLAYLIST_NAME_KEY, NO_NAME); | ||||
|             playlistId = jsonObject.getInt(JSON_PLAYLIST_ID_KEY, -1); | ||||
|             playlistType = LocalItemType.valueOf( | ||||
|                     jsonObject.getString(JSON_PLAYLIST_TYPE_KEY, | ||||
|   | ||||
| @@ -108,10 +108,12 @@ public class FileStreamSAF extends SharpStream { | ||||
|         return true; | ||||
|     } | ||||
|  | ||||
|     @Override | ||||
|     public boolean canSetLength() { | ||||
|         return true; | ||||
|     } | ||||
|  | ||||
|     @Override | ||||
|     public boolean canSeek() { | ||||
|         return true; | ||||
|     } | ||||
| @@ -131,10 +133,12 @@ public class FileStreamSAF extends SharpStream { | ||||
|         out.write(buffer, offset, count); | ||||
|     } | ||||
|  | ||||
|     @Override | ||||
|     public void setLength(long length) throws IOException { | ||||
|         channel.truncate(length); | ||||
|     } | ||||
|  | ||||
|     @Override | ||||
|     public void seek(long offset) throws IOException { | ||||
|         channel.position(offset); | ||||
|     } | ||||
|   | ||||
							
								
								
									
										2
									
								
								fastlane/metadata/android/en-US/changelogs/981.txt
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										2
									
								
								fastlane/metadata/android/en-US/changelogs/981.txt
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,2 @@ | ||||
| Removed MediaParser support to fix failing playback resume after buffering on Android 11+. | ||||
| Disabled media tunneling on Philips QM16XE to fix playback problems. | ||||
		Reference in New Issue
	
	Block a user
	 Martin
					Martin