mirror of
				https://github.com/TeamNewPipe/NewPipe
				synced 2025-10-31 07:13:00 +00:00 
			
		
		
		
	Merge pull request #7056 from TeamNewPipe/fix/playOnPopup
Fix handling exception in `playOnPopup` and toggle description tab
This commit is contained in:
		| @@ -16,7 +16,7 @@ import leakcanary.AppWatcher; | |||||||
|  |  | ||||||
| public abstract class BaseFragment extends Fragment { | public abstract class BaseFragment extends Fragment { | ||||||
|     protected final String TAG = getClass().getSimpleName() + "@" + Integer.toHexString(hashCode()); |     protected final String TAG = getClass().getSimpleName() + "@" + Integer.toHexString(hashCode()); | ||||||
|     protected final boolean DEBUG = MainActivity.DEBUG; |     protected static final boolean DEBUG = MainActivity.DEBUG; | ||||||
|     protected AppCompatActivity activity; |     protected AppCompatActivity activity; | ||||||
|     //These values are used for controlling fragments when they are part of the frontpage |     //These values are used for controlling fragments when they are part of the frontpage | ||||||
|     @State |     @State | ||||||
|   | |||||||
| @@ -121,28 +121,15 @@ class ErrorPanelHelper( | |||||||
|                 ErrorActivity.reportError(context, errorInfo) |                 ErrorActivity.reportError(context, errorInfo) | ||||||
|             } |             } | ||||||
|  |  | ||||||
|             errorTextView.setText( |             errorTextView.setText(getExceptionDescription(errorInfo.throwable)) | ||||||
|                 when (errorInfo.throwable) { |  | ||||||
|                     is AgeRestrictedContentException -> R.string.restricted_video_no_stream |             if (errorInfo.throwable !is ContentNotAvailableException && | ||||||
|                     is GeographicRestrictionException -> R.string.georestricted_content |                 errorInfo.throwable !is ContentNotSupportedException | ||||||
|                     is PaidContentException -> R.string.paid_content |             ) { | ||||||
|                     is PrivateContentException -> R.string.private_content |  | ||||||
|                     is SoundCloudGoPlusContentException -> R.string.soundcloud_go_plus_content |  | ||||||
|                     is YoutubeMusicPremiumContentException -> R.string.youtube_music_premium_content |  | ||||||
|                     is ContentNotAvailableException -> R.string.content_not_available |  | ||||||
|                     is ContentNotSupportedException -> R.string.content_not_supported |  | ||||||
|                     else -> { |  | ||||||
|                 // show retry button only for content which is not unavailable or unsupported |                 // show retry button only for content which is not unavailable or unsupported | ||||||
|                 errorRetryButton.isVisible = true |                 errorRetryButton.isVisible = true | ||||||
|                         if (errorInfo.throwable != null && errorInfo.throwable!!.isNetworkRelated) { |  | ||||||
|                             R.string.network_error |  | ||||||
|                         } else { |  | ||||||
|                             R.string.error_snackbar_message |  | ||||||
|             } |             } | ||||||
|         } |         } | ||||||
|                 } |  | ||||||
|             ) |  | ||||||
|         } |  | ||||||
|  |  | ||||||
|         setRootVisible() |         setRootVisible() | ||||||
|     } |     } | ||||||
| @@ -189,5 +176,27 @@ class ErrorPanelHelper( | |||||||
|     companion object { |     companion object { | ||||||
|         val TAG: String = ErrorPanelHelper::class.simpleName!! |         val TAG: String = ErrorPanelHelper::class.simpleName!! | ||||||
|         val DEBUG: Boolean = MainActivity.DEBUG |         val DEBUG: Boolean = MainActivity.DEBUG | ||||||
|  |  | ||||||
|  |         @StringRes | ||||||
|  |         public fun getExceptionDescription(throwable: Throwable?): Int { | ||||||
|  |             return when (throwable) { | ||||||
|  |                 is AgeRestrictedContentException -> R.string.restricted_video_no_stream | ||||||
|  |                 is GeographicRestrictionException -> R.string.georestricted_content | ||||||
|  |                 is PaidContentException -> R.string.paid_content | ||||||
|  |                 is PrivateContentException -> R.string.private_content | ||||||
|  |                 is SoundCloudGoPlusContentException -> R.string.soundcloud_go_plus_content | ||||||
|  |                 is YoutubeMusicPremiumContentException -> R.string.youtube_music_premium_content | ||||||
|  |                 is ContentNotAvailableException -> R.string.content_not_available | ||||||
|  |                 is ContentNotSupportedException -> R.string.content_not_supported | ||||||
|  |                 else -> { | ||||||
|  |                     // show retry button only for content which is not unavailable or unsupported | ||||||
|  |                     if (throwable != null && throwable.isNetworkRelated) { | ||||||
|  |                         R.string.network_error | ||||||
|  |                     } else { | ||||||
|  |                         R.string.error_snackbar_message | ||||||
|  |                     } | ||||||
|  |                 } | ||||||
|  |             } | ||||||
|  |         } | ||||||
|     } |     } | ||||||
| } | } | ||||||
|   | |||||||
| @@ -1,5 +1,6 @@ | |||||||
| package org.schabi.newpipe.error; | package org.schabi.newpipe.error; | ||||||
|  |  | ||||||
|  | import android.annotation.SuppressLint; | ||||||
| import android.content.Intent; | import android.content.Intent; | ||||||
| import android.content.SharedPreferences; | import android.content.SharedPreferences; | ||||||
| import android.os.Build; | import android.os.Build; | ||||||
| @@ -66,6 +67,7 @@ public class ReCaptchaActivity extends AppCompatActivity { | |||||||
|     private ActivityRecaptchaBinding recaptchaBinding; |     private ActivityRecaptchaBinding recaptchaBinding; | ||||||
|     private String foundCookies = ""; |     private String foundCookies = ""; | ||||||
|  |  | ||||||
|  |     @SuppressLint("SetJavaScriptEnabled") | ||||||
|     @Override |     @Override | ||||||
|     protected void onCreate(final Bundle savedInstanceState) { |     protected void onCreate(final Bundle savedInstanceState) { | ||||||
|         ThemeHelper.setTheme(this); |         ThemeHelper.setTheme(this); | ||||||
|   | |||||||
| @@ -423,7 +423,7 @@ public final class VideoDetailFragment | |||||||
|             showRelatedItems = sharedPreferences.getBoolean(key, true); |             showRelatedItems = sharedPreferences.getBoolean(key, true); | ||||||
|             tabSettingsChanged = true; |             tabSettingsChanged = true; | ||||||
|         } else if (key.equals(getString(R.string.show_description_key))) { |         } else if (key.equals(getString(R.string.show_description_key))) { | ||||||
|             showComments = sharedPreferences.getBoolean(key, true); |             showDescription = sharedPreferences.getBoolean(key, true); | ||||||
|             tabSettingsChanged = true; |             tabSettingsChanged = true; | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
|   | |||||||
| @@ -215,6 +215,7 @@ public class SearchFragment extends BaseListFragment<SearchInfo, ListExtractor.I | |||||||
|  |  | ||||||
|     @Override |     @Override | ||||||
|     public void onViewCreated(@NonNull final View rootView, final Bundle savedInstanceState) { |     public void onViewCreated(@NonNull final View rootView, final Bundle savedInstanceState) { | ||||||
|  |         searchBinding = FragmentSearchBinding.bind(rootView); | ||||||
|         super.onViewCreated(rootView, savedInstanceState); |         super.onViewCreated(rootView, savedInstanceState); | ||||||
|         showSearchOnStart(); |         showSearchOnStart(); | ||||||
|         initSearchListeners(); |         initSearchListeners(); | ||||||
| @@ -341,7 +342,6 @@ public class SearchFragment extends BaseListFragment<SearchInfo, ListExtractor.I | |||||||
|     @Override |     @Override | ||||||
|     protected void initViews(final View rootView, final Bundle savedInstanceState) { |     protected void initViews(final View rootView, final Bundle savedInstanceState) { | ||||||
|         super.initViews(rootView, savedInstanceState); |         super.initViews(rootView, savedInstanceState); | ||||||
|         searchBinding = FragmentSearchBinding.bind(rootView); |  | ||||||
|  |  | ||||||
|         searchBinding.suggestionsList.setAdapter(suggestionListAdapter); |         searchBinding.suggestionsList.setAdapter(suggestionListAdapter); | ||||||
|         new ItemTouchHelper(new ItemTouchHelper.Callback() { |         new ItemTouchHelper(new ItemTouchHelper.Callback() { | ||||||
| @@ -807,18 +807,21 @@ public class SearchFragment extends BaseListFragment<SearchInfo, ListExtractor.I | |||||||
|                 }) |                 }) | ||||||
|                 .subscribeOn(Schedulers.io()) |                 .subscribeOn(Schedulers.io()) | ||||||
|                 .observeOn(AndroidSchedulers.mainThread()) |                 .observeOn(AndroidSchedulers.mainThread()) | ||||||
|                 .subscribe(listNotification -> { |                 .subscribe( | ||||||
|  |                         listNotification -> { | ||||||
|                             if (listNotification.isOnNext()) { |                             if (listNotification.isOnNext()) { | ||||||
|                                 if (listNotification.getValue() != null) { |                                 if (listNotification.getValue() != null) { | ||||||
|                                     handleSuggestions(listNotification.getValue()); |                                     handleSuggestions(listNotification.getValue()); | ||||||
|                                 } |                                 } | ||||||
|                             } else if (listNotification.isOnError() |                             } else if (listNotification.isOnError() | ||||||
|                                     && listNotification.getError() != null |                                     && listNotification.getError() != null | ||||||
|                             && !ExceptionUtils.isInterruptedCaused(listNotification.getError())) { |                                     && !ExceptionUtils.isInterruptedCaused( | ||||||
|  |                                             listNotification.getError())) { | ||||||
|                                 showSnackBarError(new ErrorInfo(listNotification.getError(), |                                 showSnackBarError(new ErrorInfo(listNotification.getError(), | ||||||
|                                         UserAction.GET_SUGGESTIONS, searchString, serviceId)); |                                         UserAction.GET_SUGGESTIONS, searchString, serviceId)); | ||||||
|                             } |                             } | ||||||
|                 }); |                         }, throwable -> showSnackBarError(new ErrorInfo( | ||||||
|  |                             throwable, UserAction.GET_SUGGESTIONS, searchString, serviceId))); | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     @Override |     @Override | ||||||
|   | |||||||
| @@ -614,7 +614,7 @@ public final class Player implements | |||||||
|             playQueue.append(newQueue.getStreams()); |             playQueue.append(newQueue.getStreams()); | ||||||
|  |  | ||||||
|             if ((intent.getBooleanExtra(SELECT_ON_APPEND, false) |             if ((intent.getBooleanExtra(SELECT_ON_APPEND, false) | ||||||
|                     || currentState == STATE_COMPLETED) && newQueue.getStreams().size() > 0) { |                     || currentState == STATE_COMPLETED) && !newQueue.getStreams().isEmpty()) { | ||||||
|                 playQueue.setIndex(sizeBeforeAppend); |                 playQueue.setIndex(sizeBeforeAppend); | ||||||
|             } |             } | ||||||
|  |  | ||||||
| @@ -2326,7 +2326,7 @@ public final class Player implements | |||||||
|             Log.d(TAG, "ExoPlayer - onRepeatModeChanged() called with: " |             Log.d(TAG, "ExoPlayer - onRepeatModeChanged() called with: " | ||||||
|                     + "repeatMode = [" + repeatMode + "]"); |                     + "repeatMode = [" + repeatMode + "]"); | ||||||
|         } |         } | ||||||
|         setRepeatModeButton(((AppCompatImageButton) binding.repeatButton), repeatMode); |         setRepeatModeButton(binding.repeatButton, repeatMode); | ||||||
|         onShuffleOrRepeatModeChanged(); |         onShuffleOrRepeatModeChanged(); | ||||||
|     } |     } | ||||||
|  |  | ||||||
| @@ -3189,7 +3189,7 @@ public final class Player implements | |||||||
|     private StreamSegmentAdapter.StreamSegmentListener getStreamSegmentListener() { |     private StreamSegmentAdapter.StreamSegmentListener getStreamSegmentListener() { | ||||||
|         return (item, seconds) -> { |         return (item, seconds) -> { | ||||||
|             segmentAdapter.selectSegment(item); |             segmentAdapter.selectSegment(item); | ||||||
|             seekTo(seconds * 1000); |             seekTo(seconds * 1000L); | ||||||
|             triggerProgressUpdate(); |             triggerProgressUpdate(); | ||||||
|         }; |         }; | ||||||
|     } |     } | ||||||
| @@ -3199,7 +3199,7 @@ public final class Player implements | |||||||
|         final List<StreamSegment> segments = currentMetadata.getMetadata().getStreamSegments(); |         final List<StreamSegment> segments = currentMetadata.getMetadata().getStreamSegments(); | ||||||
|  |  | ||||||
|         for (int i = 0; i < segments.size(); i++) { |         for (int i = 0; i < segments.size(); i++) { | ||||||
|             if (segments.get(i).getStartTimeSeconds() * 1000 > playbackPosition) { |             if (segments.get(i).getStartTimeSeconds() * 1000L > playbackPosition) { | ||||||
|                 break; |                 break; | ||||||
|             } |             } | ||||||
|             nearestPosition++; |             nearestPosition++; | ||||||
|   | |||||||
| @@ -360,7 +360,7 @@ public final class NavigationHelper { | |||||||
|             autoPlay = false; |             autoPlay = false; | ||||||
|         } |         } | ||||||
|  |  | ||||||
|         final RunnableWithVideoDetailFragment onVideoDetailFragmentReady = (detailFragment) -> { |         final RunnableWithVideoDetailFragment onVideoDetailFragmentReady = detailFragment -> { | ||||||
|             expandMainPlayer(detailFragment.requireActivity()); |             expandMainPlayer(detailFragment.requireActivity()); | ||||||
|             detailFragment.setAutoPlay(autoPlay); |             detailFragment.setAutoPlay(autoPlay); | ||||||
|             if (switchingPlayers) { |             if (switchingPlayers) { | ||||||
|   | |||||||
| @@ -119,7 +119,7 @@ public final class PermissionHelper { | |||||||
|  |  | ||||||
|     public static boolean isPopupEnabled(final Context context) { |     public static boolean isPopupEnabled(final Context context) { | ||||||
|         return Build.VERSION.SDK_INT < Build.VERSION_CODES.M |         return Build.VERSION.SDK_INT < Build.VERSION_CODES.M | ||||||
|                 || PermissionHelper.checkSystemAlertWindowPermission(context); |                 || checkSystemAlertWindowPermission(context); | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     public static void showPopupEnablementToast(final Context context) { |     public static void showPopupEnablementToast(final Context context) { | ||||||
|   | |||||||
| @@ -1,9 +1,14 @@ | |||||||
| package org.schabi.newpipe.util.external_communication; | package org.schabi.newpipe.util.external_communication; | ||||||
|  |  | ||||||
| import android.content.Context; | import android.content.Context; | ||||||
|  | import android.util.Log; | ||||||
|  |  | ||||||
| import androidx.annotation.NonNull; | import androidx.annotation.NonNull; | ||||||
|  | import androidx.appcompat.app.AlertDialog; | ||||||
|  |  | ||||||
|  | import org.schabi.newpipe.MainActivity; | ||||||
|  | import org.schabi.newpipe.R; | ||||||
|  | import org.schabi.newpipe.error.ErrorPanelHelper; | ||||||
| import org.schabi.newpipe.extractor.NewPipe; | import org.schabi.newpipe.extractor.NewPipe; | ||||||
| import org.schabi.newpipe.extractor.StreamingService; | import org.schabi.newpipe.extractor.StreamingService; | ||||||
| import org.schabi.newpipe.extractor.exceptions.ExtractionException; | import org.schabi.newpipe.extractor.exceptions.ExtractionException; | ||||||
| @@ -24,6 +29,9 @@ import io.reactivex.rxjava3.disposables.CompositeDisposable; | |||||||
| import io.reactivex.rxjava3.schedulers.Schedulers; | import io.reactivex.rxjava3.schedulers.Schedulers; | ||||||
|  |  | ||||||
| public final class InternalUrlsHandler { | public final class InternalUrlsHandler { | ||||||
|  |     private static final String TAG = InternalUrlsHandler.class.getSimpleName(); | ||||||
|  |     private static final boolean DEBUG = MainActivity.DEBUG; | ||||||
|  |  | ||||||
|     private static final Pattern AMPERSAND_TIMESTAMP_PATTERN = Pattern.compile("(.*)&t=(\\d+)"); |     private static final Pattern AMPERSAND_TIMESTAMP_PATTERN = Pattern.compile("(.*)&t=(\\d+)"); | ||||||
|     private static final Pattern HASHTAG_TIMESTAMP_PATTERN = |     private static final Pattern HASHTAG_TIMESTAMP_PATTERN = | ||||||
|             Pattern.compile("(.*)#timestamp=(\\d+)"); |             Pattern.compile("(.*)#timestamp=(\\d+)"); | ||||||
| @@ -93,7 +101,12 @@ public final class InternalUrlsHandler { | |||||||
|             return false; |             return false; | ||||||
|         } |         } | ||||||
|         final String matchedUrl = matcher.group(1); |         final String matchedUrl = matcher.group(1); | ||||||
|         final int seconds = Integer.parseInt(matcher.group(2)); |         final int seconds; | ||||||
|  |         if (matcher.group(2) == null) { | ||||||
|  |             seconds = -1; | ||||||
|  |         } else { | ||||||
|  |             seconds = Integer.parseInt(matcher.group(2)); | ||||||
|  |         } | ||||||
|  |  | ||||||
|         final StreamingService service; |         final StreamingService service; | ||||||
|         final StreamingService.LinkType linkType; |         final StreamingService.LinkType linkType; | ||||||
| @@ -146,8 +159,18 @@ public final class InternalUrlsHandler { | |||||||
|                 .observeOn(AndroidSchedulers.mainThread()) |                 .observeOn(AndroidSchedulers.mainThread()) | ||||||
|                 .subscribe(info -> { |                 .subscribe(info -> { | ||||||
|                     final PlayQueue playQueue |                     final PlayQueue playQueue | ||||||
|                             = new SinglePlayQueue(info, seconds * 1000); |                             = new SinglePlayQueue(info, seconds * 1000L); | ||||||
|                     NavigationHelper.playOnPopupPlayer(context, playQueue, false); |                     NavigationHelper.playOnPopupPlayer(context, playQueue, false); | ||||||
|  |                 }, throwable -> { | ||||||
|  |                     if (DEBUG) { | ||||||
|  |                         Log.e(TAG, "Could not play on popup: " + url, throwable); | ||||||
|  |                     } | ||||||
|  |                     new AlertDialog.Builder(context) | ||||||
|  |                             .setTitle(R.string.player_stream_failure) | ||||||
|  |                             .setMessage( | ||||||
|  |                                     ErrorPanelHelper.Companion.getExceptionDescription(throwable)) | ||||||
|  |                             .setPositiveButton(R.string.ok, (v, b) -> { }) | ||||||
|  |                             .show(); | ||||||
|                 })); |                 })); | ||||||
|         return true; |         return true; | ||||||
|     } |     } | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user
	 Tobi
					Tobi