Merge pull request #8170 from Stypox/player-refactor
Refactor player and extract UI components
This commit is contained in:
commit
1706856f24
45 changed files with 5012 additions and 4098 deletions
|
|
@ -1,5 +1,16 @@
|
|||
package org.schabi.newpipe.fragments.detail;
|
||||
|
||||
import static android.text.TextUtils.isEmpty;
|
||||
import static org.schabi.newpipe.extractor.StreamingService.ServiceInfo.MediaCapability.COMMENTS;
|
||||
import static org.schabi.newpipe.extractor.stream.StreamExtractor.NO_AGE_LIMIT;
|
||||
import static org.schabi.newpipe.ktx.ViewUtils.animate;
|
||||
import static org.schabi.newpipe.ktx.ViewUtils.animateRotation;
|
||||
import static org.schabi.newpipe.player.helper.PlayerHelper.globalScreenOrientationLocked;
|
||||
import static org.schabi.newpipe.player.helper.PlayerHelper.isClearingQueueConfirmationRequired;
|
||||
import static org.schabi.newpipe.player.playqueue.PlayQueueItem.RECOVERY_UNSET;
|
||||
import static org.schabi.newpipe.util.ExtractorHelper.showMetaInfoInTextView;
|
||||
import static org.schabi.newpipe.util.ListHelper.getUrlAndNonTorrentStreams;
|
||||
|
||||
import android.animation.ValueAnimator;
|
||||
import android.app.Activity;
|
||||
import android.content.BroadcastReceiver;
|
||||
|
|
@ -77,9 +88,9 @@ import org.schabi.newpipe.fragments.list.videos.RelatedItemsFragment;
|
|||
import org.schabi.newpipe.ktx.AnimationType;
|
||||
import org.schabi.newpipe.local.dialog.PlaylistDialog;
|
||||
import org.schabi.newpipe.local.history.HistoryRecordManager;
|
||||
import org.schabi.newpipe.player.MainPlayer;
|
||||
import org.schabi.newpipe.player.MainPlayer.PlayerType;
|
||||
import org.schabi.newpipe.player.Player;
|
||||
import org.schabi.newpipe.player.PlayerService;
|
||||
import org.schabi.newpipe.player.PlayerType;
|
||||
import org.schabi.newpipe.player.event.OnKeyDownListener;
|
||||
import org.schabi.newpipe.player.event.PlayerServiceExtendedEventListener;
|
||||
import org.schabi.newpipe.player.helper.PlayerHelper;
|
||||
|
|
@ -87,6 +98,8 @@ import org.schabi.newpipe.player.helper.PlayerHolder;
|
|||
import org.schabi.newpipe.player.playqueue.PlayQueue;
|
||||
import org.schabi.newpipe.player.playqueue.PlayQueueItem;
|
||||
import org.schabi.newpipe.player.playqueue.SinglePlayQueue;
|
||||
import org.schabi.newpipe.player.ui.MainPlayerUi;
|
||||
import org.schabi.newpipe.player.ui.VideoPlayerUi;
|
||||
import org.schabi.newpipe.util.Constants;
|
||||
import org.schabi.newpipe.util.DeviceUtils;
|
||||
import org.schabi.newpipe.util.ExtractorHelper;
|
||||
|
|
@ -106,6 +119,7 @@ import java.util.Iterator;
|
|||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
import java.util.Optional;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
import icepick.State;
|
||||
|
|
@ -114,17 +128,6 @@ import io.reactivex.rxjava3.disposables.CompositeDisposable;
|
|||
import io.reactivex.rxjava3.disposables.Disposable;
|
||||
import io.reactivex.rxjava3.schedulers.Schedulers;
|
||||
|
||||
import static android.text.TextUtils.isEmpty;
|
||||
import static org.schabi.newpipe.extractor.StreamingService.ServiceInfo.MediaCapability.COMMENTS;
|
||||
import static org.schabi.newpipe.extractor.stream.StreamExtractor.NO_AGE_LIMIT;
|
||||
import static org.schabi.newpipe.ktx.ViewUtils.animate;
|
||||
import static org.schabi.newpipe.ktx.ViewUtils.animateRotation;
|
||||
import static org.schabi.newpipe.player.helper.PlayerHelper.globalScreenOrientationLocked;
|
||||
import static org.schabi.newpipe.player.helper.PlayerHelper.isClearingQueueConfirmationRequired;
|
||||
import static org.schabi.newpipe.player.playqueue.PlayQueueItem.RECOVERY_UNSET;
|
||||
import static org.schabi.newpipe.util.ExtractorHelper.showMetaInfoInTextView;
|
||||
import static org.schabi.newpipe.util.ListHelper.getUrlAndNonTorrentStreams;
|
||||
|
||||
public final class VideoDetailFragment
|
||||
extends BaseStateFragment<StreamInfo>
|
||||
implements BackPressable,
|
||||
|
|
@ -202,7 +205,7 @@ public final class VideoDetailFragment
|
|||
|
||||
private ContentObserver settingsContentObserver;
|
||||
@Nullable
|
||||
private MainPlayer playerService;
|
||||
private PlayerService playerService;
|
||||
private Player player;
|
||||
private final PlayerHolder playerHolder = PlayerHolder.getInstance();
|
||||
|
||||
|
|
@ -211,7 +214,7 @@ public final class VideoDetailFragment
|
|||
//////////////////////////////////////////////////////////////////////////*/
|
||||
@Override
|
||||
public void onServiceConnected(final Player connectedPlayer,
|
||||
final MainPlayer connectedPlayerService,
|
||||
final PlayerService connectedPlayerService,
|
||||
final boolean playAfterConnect) {
|
||||
player = connectedPlayer;
|
||||
playerService = connectedPlayerService;
|
||||
|
|
@ -219,6 +222,7 @@ public final class VideoDetailFragment
|
|||
// It will do nothing if the player is not in fullscreen mode
|
||||
hideSystemUiIfNeeded();
|
||||
|
||||
final Optional<MainPlayerUi> playerUi = player.UIs().get(MainPlayerUi.class);
|
||||
if (!player.videoPlayerSelected() && !playAfterConnect) {
|
||||
return;
|
||||
}
|
||||
|
|
@ -227,22 +231,19 @@ public final class VideoDetailFragment
|
|||
// If the video is playing but orientation changed
|
||||
// let's make the video in fullscreen again
|
||||
checkLandscape();
|
||||
} else if (player.isFullscreen() && !player.isVerticalVideo()
|
||||
} else if (playerUi.map(ui -> ui.isFullscreen() && !ui.isVerticalVideo()).orElse(false)
|
||||
// Tablet UI has orientation-independent fullscreen
|
||||
&& !DeviceUtils.isTablet(activity)) {
|
||||
// Device is in portrait orientation after rotation but UI is in fullscreen.
|
||||
// Return back to non-fullscreen state
|
||||
player.toggleFullscreen();
|
||||
}
|
||||
|
||||
if (playerIsNotStopped() && player.videoPlayerSelected()) {
|
||||
addVideoPlayerView();
|
||||
playerUi.ifPresent(MainPlayerUi::toggleFullscreen);
|
||||
}
|
||||
|
||||
//noinspection SimplifyOptionalCallChains
|
||||
if (playAfterConnect
|
||||
|| (currentInfo != null
|
||||
&& isAutoplayEnabled()
|
||||
&& player.getParentActivity() == null)) {
|
||||
&& !playerUi.isPresent())) {
|
||||
autoPlayEnabled = true; // forcefully start playing
|
||||
openVideoPlayerAutoFullscreen();
|
||||
}
|
||||
|
|
@ -329,6 +330,9 @@ public final class VideoDetailFragment
|
|||
@Override
|
||||
public void onResume() {
|
||||
super.onResume();
|
||||
if (DEBUG) {
|
||||
Log.d(TAG, "onResume() called");
|
||||
}
|
||||
|
||||
activity.sendBroadcast(new Intent(ACTION_VIDEO_FRAGMENT_RESUMED));
|
||||
|
||||
|
|
@ -518,7 +522,7 @@ public final class VideoDetailFragment
|
|||
case R.id.overlay_play_pause_button:
|
||||
if (playerIsNotStopped()) {
|
||||
player.playPause();
|
||||
player.hideControls(0, 0);
|
||||
player.UIs().get(VideoPlayerUi.class).ifPresent(ui -> ui.hideControls(0, 0));
|
||||
showSystemUi();
|
||||
} else {
|
||||
autoPlayEnabled = true; // forcefully start playing
|
||||
|
|
@ -583,12 +587,12 @@ public final class VideoDetailFragment
|
|||
if (binding.detailSecondaryControlPanel.getVisibility() == View.GONE) {
|
||||
binding.detailVideoTitleView.setMaxLines(10);
|
||||
animateRotation(binding.detailToggleSecondaryControlsView,
|
||||
Player.DEFAULT_CONTROLS_DURATION, 180);
|
||||
VideoPlayerUi.DEFAULT_CONTROLS_DURATION, 180);
|
||||
binding.detailSecondaryControlPanel.setVisibility(View.VISIBLE);
|
||||
} else {
|
||||
binding.detailVideoTitleView.setMaxLines(1);
|
||||
animateRotation(binding.detailToggleSecondaryControlsView,
|
||||
Player.DEFAULT_CONTROLS_DURATION, 0);
|
||||
VideoPlayerUi.DEFAULT_CONTROLS_DURATION, 0);
|
||||
binding.detailSecondaryControlPanel.setVisibility(View.GONE);
|
||||
}
|
||||
// view pager height has changed, update the tab layout
|
||||
|
|
@ -746,7 +750,9 @@ public final class VideoDetailFragment
|
|||
|
||||
@Override
|
||||
public boolean onKeyDown(final int keyCode) {
|
||||
return isPlayerAvailable() && player.onKeyDown(keyCode);
|
||||
return isPlayerAvailable()
|
||||
&& player.UIs().get(VideoPlayerUi.class)
|
||||
.map(playerUi -> playerUi.onKeyDown(keyCode)).orElse(false);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
@ -756,7 +762,7 @@ public final class VideoDetailFragment
|
|||
}
|
||||
|
||||
// If we are in fullscreen mode just exit from it via first back press
|
||||
if (isPlayerAvailable() && player.isFullscreen()) {
|
||||
if (isFullscreen()) {
|
||||
if (!DeviceUtils.isTablet(activity)) {
|
||||
player.pause();
|
||||
}
|
||||
|
|
@ -1006,8 +1012,7 @@ public final class VideoDetailFragment
|
|||
getChildFragmentManager().beginTransaction()
|
||||
.replace(R.id.relatedItemsLayout, RelatedItemsFragment.getInstance(info))
|
||||
.commitAllowingStateLoss();
|
||||
binding.relatedItemsLayout.setVisibility(
|
||||
isPlayerAvailable() && player.isFullscreen() ? View.GONE : View.VISIBLE);
|
||||
binding.relatedItemsLayout.setVisibility(isFullscreen() ? View.GONE : View.VISIBLE);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -1087,8 +1092,12 @@ public final class VideoDetailFragment
|
|||
private void toggleFullscreenIfInFullscreenMode() {
|
||||
// If a user watched video inside fullscreen mode and than chose another player
|
||||
// return to non-fullscreen mode
|
||||
if (isPlayerAvailable() && player.isFullscreen()) {
|
||||
player.toggleFullscreen();
|
||||
if (isPlayerAvailable()) {
|
||||
player.UIs().get(MainPlayerUi.class).ifPresent(playerUi -> {
|
||||
if (playerUi.isFullscreen()) {
|
||||
playerUi.toggleFullscreen();
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -1214,16 +1223,10 @@ public final class VideoDetailFragment
|
|||
}
|
||||
|
||||
final PlayQueue queue = setupPlayQueueForIntent(false);
|
||||
|
||||
// Video view can have elements visible from popup,
|
||||
// We hide it here but once it ready the view will be shown in handleIntent()
|
||||
if (playerService.getView() != null) {
|
||||
playerService.getView().setVisibility(View.GONE);
|
||||
}
|
||||
addVideoPlayerView();
|
||||
|
||||
final Intent playerIntent = NavigationHelper.getPlayerIntent(requireContext(),
|
||||
MainPlayer.class, queue, true, autoPlayEnabled);
|
||||
PlayerService.class, queue, true, autoPlayEnabled);
|
||||
ContextCompat.startForegroundService(activity, playerIntent);
|
||||
}
|
||||
|
||||
|
|
@ -1235,8 +1238,8 @@ public final class VideoDetailFragment
|
|||
* be reused in a few milliseconds and the flickering would be annoying.
|
||||
*/
|
||||
private void hideMainPlayerOnLoadingNewStream() {
|
||||
if (!isPlayerServiceAvailable()
|
||||
|| playerService.getView() == null
|
||||
//noinspection SimplifyOptionalCallChains
|
||||
if (!isPlayerServiceAvailable() || !getRoot().isPresent()
|
||||
|| !player.videoPlayerSelected()) {
|
||||
return;
|
||||
}
|
||||
|
|
@ -1244,7 +1247,7 @@ public final class VideoDetailFragment
|
|||
removeVideoPlayerView();
|
||||
if (isAutoplayEnabled()) {
|
||||
playerService.stopForImmediateReusing();
|
||||
playerService.getView().setVisibility(View.GONE);
|
||||
getRoot().ifPresent(view -> view.setVisibility(View.GONE));
|
||||
} else {
|
||||
playerHolder.stopService();
|
||||
}
|
||||
|
|
@ -1305,23 +1308,23 @@ public final class VideoDetailFragment
|
|||
if (!isPlayerAvailable() || getView() == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Check if viewHolder already contains a child
|
||||
if (player.getRootView().getParent() != binding.playerPlaceholder) {
|
||||
playerService.removeViewFromParent();
|
||||
}
|
||||
setHeightThumbnail();
|
||||
|
||||
// Prevent from re-adding a view multiple times
|
||||
if (player.getRootView().getParent() == null) {
|
||||
binding.playerPlaceholder.addView(player.getRootView());
|
||||
}
|
||||
new Handler(Looper.getMainLooper()).post(() ->
|
||||
player.UIs().get(MainPlayerUi.class).ifPresent(playerUi -> {
|
||||
playerUi.removeViewFromParent();
|
||||
binding.playerPlaceholder.addView(playerUi.getBinding().getRoot());
|
||||
playerUi.setupVideoSurfaceIfNeeded();
|
||||
}));
|
||||
}
|
||||
|
||||
private void removeVideoPlayerView() {
|
||||
makeDefaultHeightForVideoPlaceholder();
|
||||
|
||||
playerService.removeViewFromParent();
|
||||
if (player != null) {
|
||||
player.UIs().get(VideoPlayerUi.class).ifPresent(VideoPlayerUi::removeViewFromParent);
|
||||
}
|
||||
}
|
||||
|
||||
private void makeDefaultHeightForVideoPlaceholder() {
|
||||
|
|
@ -1362,7 +1365,7 @@ public final class VideoDetailFragment
|
|||
final boolean isPortrait = metrics.heightPixels > metrics.widthPixels;
|
||||
requireView().getViewTreeObserver().removeOnPreDrawListener(preDrawListener);
|
||||
|
||||
if (isPlayerAvailable() && player.isFullscreen()) {
|
||||
if (isFullscreen()) {
|
||||
final int height = (DeviceUtils.isInMultiWindow(activity)
|
||||
? requireView()
|
||||
: activity.getWindow().getDecorView()).getHeight();
|
||||
|
|
@ -1387,8 +1390,9 @@ public final class VideoDetailFragment
|
|||
binding.detailThumbnailImageView.setMinimumHeight(newHeight);
|
||||
if (isPlayerAvailable()) {
|
||||
final int maxHeight = (int) (metrics.heightPixels * MAX_PLAYER_HEIGHT);
|
||||
player.getSurfaceView()
|
||||
.setHeights(newHeight, player.isFullscreen() ? newHeight : maxHeight);
|
||||
player.UIs().get(VideoPlayerUi.class).ifPresent(ui ->
|
||||
ui.getBinding().surfaceView.setHeights(newHeight,
|
||||
ui.isFullscreen() ? newHeight : maxHeight));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -1517,7 +1521,7 @@ public final class VideoDetailFragment
|
|||
if (binding.relatedItemsLayout != null) {
|
||||
if (showRelatedItems) {
|
||||
binding.relatedItemsLayout.setVisibility(
|
||||
isPlayerAvailable() && player.isFullscreen() ? View.GONE : View.INVISIBLE);
|
||||
isFullscreen() ? View.GONE : View.INVISIBLE);
|
||||
} else {
|
||||
binding.relatedItemsLayout.setVisibility(View.GONE);
|
||||
}
|
||||
|
|
@ -1779,6 +1783,11 @@ public final class VideoDetailFragment
|
|||
// Player event listener
|
||||
//////////////////////////////////////////////////////////////////////////*/
|
||||
|
||||
@Override
|
||||
public void onViewCreated() {
|
||||
addVideoPlayerView();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onQueueUpdate(final PlayQueue queue) {
|
||||
playQueue = queue;
|
||||
|
|
@ -1899,15 +1908,10 @@ public final class VideoDetailFragment
|
|||
@Override
|
||||
public void onFullscreenStateChanged(final boolean fullscreen) {
|
||||
setupBrightness();
|
||||
//noinspection SimplifyOptionalCallChains
|
||||
if (!isPlayerAndPlayerServiceAvailable()
|
||||
|| playerService.getView() == null
|
||||
|| player.getParentActivity() == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
final View view = playerService.getView();
|
||||
final ViewGroup parent = (ViewGroup) view.getParent();
|
||||
if (parent == null) {
|
||||
|| !player.UIs().get(MainPlayerUi.class).isPresent()
|
||||
|| getRoot().map(View::getParent).orElse(null) == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
@ -1935,7 +1939,7 @@ public final class VideoDetailFragment
|
|||
final boolean isLandscape = DeviceUtils.isLandscape(requireContext());
|
||||
if (DeviceUtils.isTablet(activity)
|
||||
&& (!globalScreenOrientationLocked(activity) || isLandscape)) {
|
||||
player.toggleFullscreen();
|
||||
player.UIs().get(MainPlayerUi.class).ifPresent(MainPlayerUi::toggleFullscreen);
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
@ -2018,7 +2022,7 @@ public final class VideoDetailFragment
|
|||
}
|
||||
activity.getWindow().getDecorView().setSystemUiVisibility(visibility);
|
||||
|
||||
if (isInMultiWindow || (isPlayerAvailable() && player.isFullscreen())) {
|
||||
if (isInMultiWindow || isFullscreen()) {
|
||||
activity.getWindow().setStatusBarColor(Color.TRANSPARENT);
|
||||
activity.getWindow().setNavigationBarColor(Color.TRANSPARENT);
|
||||
}
|
||||
|
|
@ -2027,13 +2031,17 @@ public final class VideoDetailFragment
|
|||
|
||||
// Listener implementation
|
||||
public void hideSystemUiIfNeeded() {
|
||||
if (isPlayerAvailable()
|
||||
&& player.isFullscreen()
|
||||
if (isFullscreen()
|
||||
&& bottomSheetBehavior.getState() == BottomSheetBehavior.STATE_EXPANDED) {
|
||||
hideSystemUi();
|
||||
}
|
||||
}
|
||||
|
||||
private boolean isFullscreen() {
|
||||
return isPlayerAvailable() && player.UIs().get(VideoPlayerUi.class)
|
||||
.map(VideoPlayerUi::isFullscreen).orElse(false);
|
||||
}
|
||||
|
||||
private boolean playerIsNotStopped() {
|
||||
return isPlayerAvailable() && !player.isStopped();
|
||||
}
|
||||
|
|
@ -2056,10 +2064,7 @@ public final class VideoDetailFragment
|
|||
}
|
||||
|
||||
final WindowManager.LayoutParams lp = activity.getWindow().getAttributes();
|
||||
if (!isPlayerAvailable()
|
||||
|| !player.videoPlayerSelected()
|
||||
|| !player.isFullscreen()
|
||||
|| bottomSheetState != BottomSheetBehavior.STATE_EXPANDED) {
|
||||
if (!isFullscreen() || bottomSheetState != BottomSheetBehavior.STATE_EXPANDED) {
|
||||
// Apply system brightness when the player is not in fullscreen
|
||||
restoreDefaultBrightness();
|
||||
} else {
|
||||
|
|
@ -2083,7 +2088,7 @@ public final class VideoDetailFragment
|
|||
setAutoPlay(true);
|
||||
}
|
||||
|
||||
player.checkLandscape();
|
||||
player.UIs().get(MainPlayerUi.class).ifPresent(MainPlayerUi::checkLandscape);
|
||||
// Let's give a user time to look at video information page if video is not playing
|
||||
if (globalScreenOrientationLocked(activity) && !player.isPlaying()) {
|
||||
player.play();
|
||||
|
|
@ -2310,10 +2315,10 @@ public final class VideoDetailFragment
|
|||
if (DeviceUtils.isLandscape(requireContext())
|
||||
&& isPlayerAvailable()
|
||||
&& player.isPlaying()
|
||||
&& !player.isFullscreen()
|
||||
&& !DeviceUtils.isTablet(activity)
|
||||
&& player.videoPlayerSelected()) {
|
||||
player.toggleFullscreen();
|
||||
&& !isFullscreen()
|
||||
&& !DeviceUtils.isTablet(activity)) {
|
||||
player.UIs().get(MainPlayerUi.class)
|
||||
.ifPresent(MainPlayerUi::toggleFullscreen);
|
||||
}
|
||||
setOverlayLook(binding.appBarLayout, behavior, 1);
|
||||
break;
|
||||
|
|
@ -2326,17 +2331,22 @@ public final class VideoDetailFragment
|
|||
// Re-enable clicks
|
||||
setOverlayElementsClickable(true);
|
||||
if (isPlayerAvailable()) {
|
||||
player.closeItemsList();
|
||||
player.UIs().get(MainPlayerUi.class)
|
||||
.ifPresent(MainPlayerUi::closeItemsList);
|
||||
}
|
||||
setOverlayLook(binding.appBarLayout, behavior, 0);
|
||||
break;
|
||||
case BottomSheetBehavior.STATE_DRAGGING:
|
||||
case BottomSheetBehavior.STATE_SETTLING:
|
||||
if (isPlayerAvailable() && player.isFullscreen()) {
|
||||
if (isFullscreen()) {
|
||||
showSystemUi();
|
||||
}
|
||||
if (isPlayerAvailable() && player.isControlsVisible()) {
|
||||
player.hideControls(0, 0);
|
||||
if (isPlayerAvailable()) {
|
||||
player.UIs().get(MainPlayerUi.class).ifPresent(ui -> {
|
||||
if (ui.isControlsVisible()) {
|
||||
ui.hideControls(0, 0);
|
||||
}
|
||||
});
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
|
@ -2410,4 +2420,13 @@ public final class VideoDetailFragment
|
|||
boolean isPlayerAndPlayerServiceAvailable() {
|
||||
return (player != null && playerService != null);
|
||||
}
|
||||
|
||||
public Optional<View> getRoot() {
|
||||
if (player == null) {
|
||||
return Optional.empty();
|
||||
}
|
||||
|
||||
return player.UIs().get(VideoPlayerUi.class)
|
||||
.map(playerUi -> playerUi.getBinding().getRoot());
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -43,7 +43,7 @@ import org.schabi.newpipe.fragments.list.BaseListInfoFragment;
|
|||
import org.schabi.newpipe.ktx.AnimationType;
|
||||
import org.schabi.newpipe.local.subscription.SubscriptionManager;
|
||||
import org.schabi.newpipe.local.feed.notifications.NotificationHelper;
|
||||
import org.schabi.newpipe.player.MainPlayer.PlayerType;
|
||||
import org.schabi.newpipe.player.PlayerType;
|
||||
import org.schabi.newpipe.player.playqueue.ChannelPlayQueue;
|
||||
import org.schabi.newpipe.player.playqueue.PlayQueue;
|
||||
import org.schabi.newpipe.util.ExtractorHelper;
|
||||
|
|
|
|||
|
|
@ -43,7 +43,7 @@ import org.schabi.newpipe.info_list.dialog.InfoItemDialog;
|
|||
import org.schabi.newpipe.info_list.dialog.StreamDialogDefaultEntry;
|
||||
import org.schabi.newpipe.local.dialog.PlaylistDialog;
|
||||
import org.schabi.newpipe.local.playlist.RemotePlaylistManager;
|
||||
import org.schabi.newpipe.player.MainPlayer.PlayerType;
|
||||
import org.schabi.newpipe.player.PlayerType;
|
||||
import org.schabi.newpipe.player.playqueue.PlayQueue;
|
||||
import org.schabi.newpipe.player.playqueue.PlaylistPlayQueue;
|
||||
import org.schabi.newpipe.util.ExtractorHelper;
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue