mirror of
				https://github.com/TeamNewPipe/NewPipe
				synced 2025-10-31 15:23:00 +00:00 
			
		
		
		
	Merge pull request #8340 from litetex/fix-add-to-playlist
Fix "Add to playlist" not working and cleanup "RouterActivity" choice handling
This commit is contained in:
		| @@ -24,6 +24,7 @@ import android.widget.Toast; | |||||||
| import androidx.annotation.DrawableRes; | import androidx.annotation.DrawableRes; | ||||||
| import androidx.annotation.NonNull; | import androidx.annotation.NonNull; | ||||||
| import androidx.annotation.Nullable; | import androidx.annotation.Nullable; | ||||||
|  | import androidx.annotation.StringRes; | ||||||
| import androidx.appcompat.app.AlertDialog; | import androidx.appcompat.app.AlertDialog; | ||||||
| import androidx.appcompat.app.AppCompatActivity; | import androidx.appcompat.app.AppCompatActivity; | ||||||
| import androidx.appcompat.content.res.AppCompatResources; | import androidx.appcompat.content.res.AppCompatResources; | ||||||
| @@ -259,80 +260,122 @@ public class RouterActivity extends AppCompatActivity { | |||||||
|     protected void onSuccess() { |     protected void onSuccess() { | ||||||
|         final SharedPreferences preferences = PreferenceManager |         final SharedPreferences preferences = PreferenceManager | ||||||
|                 .getDefaultSharedPreferences(this); |                 .getDefaultSharedPreferences(this); | ||||||
|         final String selectedChoiceKey = preferences |  | ||||||
|                 .getString(getString(R.string.preferred_open_action_key), |  | ||||||
|                         getString(R.string.preferred_open_action_default)); |  | ||||||
|  |  | ||||||
|         final String showInfoKey = getString(R.string.show_info_key); |         final ChoiceAvailabilityChecker choiceChecker = new ChoiceAvailabilityChecker( | ||||||
|         final String videoPlayerKey = getString(R.string.video_player_key); |                 getChoicesForService(currentService, currentLinkType), | ||||||
|         final String backgroundPlayerKey = getString(R.string.background_player_key); |                 preferences.getString(getString(R.string.preferred_open_action_key), | ||||||
|         final String popupPlayerKey = getString(R.string.popup_player_key); |                         getString(R.string.preferred_open_action_default))); | ||||||
|         final String downloadKey = getString(R.string.download_key); |  | ||||||
|         final String alwaysAskKey = getString(R.string.always_ask_open_action_key); |  | ||||||
|  |  | ||||||
|         if (selectedChoiceKey.equals(alwaysAskKey)) { |         // Check for non-player related choices | ||||||
|             final List<AdapterChoiceItem> choices |         if (choiceChecker.isAvailableAndSelected( | ||||||
|                     = getChoicesForService(currentService, currentLinkType); |                 R.string.show_info_key, | ||||||
|  |                 R.string.download_key, | ||||||
|             switch (choices.size()) { |                 R.string.add_to_playlist_key)) { | ||||||
|                 case 1: |             handleChoice(choiceChecker.getSelectedChoiceKey()); | ||||||
|                     handleChoice(choices.get(0).key); |             return; | ||||||
|                     break; |  | ||||||
|                 case 0: |  | ||||||
|                     handleChoice(showInfoKey); |  | ||||||
|                     break; |  | ||||||
|                 default: |  | ||||||
|                     showDialog(choices); |  | ||||||
|                     break; |  | ||||||
|         } |         } | ||||||
|         } else if (selectedChoiceKey.equals(showInfoKey)) { |         // Check if the choice is player related | ||||||
|             handleChoice(showInfoKey); |         if (choiceChecker.isAvailableAndSelected( | ||||||
|         } else if (selectedChoiceKey.equals(downloadKey)) { |                 R.string.video_player_key, | ||||||
|             handleChoice(downloadKey); |                 R.string.background_player_key, | ||||||
|         } else { |                 R.string.popup_player_key)) { | ||||||
|  |  | ||||||
|  |             final String selectedChoice = choiceChecker.getSelectedChoiceKey(); | ||||||
|  |  | ||||||
|             final boolean isExtVideoEnabled = preferences.getBoolean( |             final boolean isExtVideoEnabled = preferences.getBoolean( | ||||||
|                     getString(R.string.use_external_video_player_key), false); |                     getString(R.string.use_external_video_player_key), false); | ||||||
|             final boolean isExtAudioEnabled = preferences.getBoolean( |             final boolean isExtAudioEnabled = preferences.getBoolean( | ||||||
|                     getString(R.string.use_external_audio_player_key), false); |                     getString(R.string.use_external_audio_player_key), false); | ||||||
|             final boolean isVideoPlayerSelected = selectedChoiceKey.equals(videoPlayerKey) |             final boolean isVideoPlayerSelected = | ||||||
|                     || selectedChoiceKey.equals(popupPlayerKey); |                     selectedChoice.equals(getString(R.string.video_player_key)) | ||||||
|             final boolean isAudioPlayerSelected = selectedChoiceKey.equals(backgroundPlayerKey); |                             || selectedChoice.equals(getString(R.string.popup_player_key)); | ||||||
|  |             final boolean isAudioPlayerSelected = | ||||||
|  |                     selectedChoice.equals(getString(R.string.background_player_key)); | ||||||
|  |  | ||||||
|             if (currentLinkType != LinkType.STREAM) { |             if (currentLinkType != LinkType.STREAM | ||||||
|                 if (isExtAudioEnabled && isAudioPlayerSelected |                     && ((isExtAudioEnabled && isAudioPlayerSelected) | ||||||
|                         || isExtVideoEnabled && isVideoPlayerSelected) { |                     || (isExtVideoEnabled && isVideoPlayerSelected)) | ||||||
|  |             ) { | ||||||
|                 Toast.makeText(this, R.string.external_player_unsupported_link_type, |                 Toast.makeText(this, R.string.external_player_unsupported_link_type, | ||||||
|                         Toast.LENGTH_LONG).show(); |                         Toast.LENGTH_LONG).show(); | ||||||
|                     handleChoice(showInfoKey); |                 handleChoice(getString(R.string.show_info_key)); | ||||||
|                 return; |                 return; | ||||||
|             } |             } | ||||||
|             } |  | ||||||
|  |  | ||||||
|             final List<StreamingService.ServiceInfo.MediaCapability> capabilities |             final List<StreamingService.ServiceInfo.MediaCapability> capabilities = | ||||||
|                     = currentService.getServiceInfo().getMediaCapabilities(); |                     currentService.getServiceInfo().getMediaCapabilities(); | ||||||
|  |  | ||||||
|             boolean serviceSupportsChoice = false; |             // Check if the service supports the choice | ||||||
|             if (isVideoPlayerSelected) { |             if ((isVideoPlayerSelected && capabilities.contains(VIDEO)) | ||||||
|                 serviceSupportsChoice = capabilities.contains(VIDEO); |                     || (isAudioPlayerSelected && capabilities.contains(AUDIO))) { | ||||||
|             } else if (selectedChoiceKey.equals(backgroundPlayerKey)) { |                 handleChoice(selectedChoice); | ||||||
|                 serviceSupportsChoice = capabilities.contains(AUDIO); |  | ||||||
|             } |  | ||||||
|  |  | ||||||
|             if (serviceSupportsChoice) { |  | ||||||
|                 handleChoice(selectedChoiceKey); |  | ||||||
|             } else { |             } else { | ||||||
|                 handleChoice(showInfoKey); |                 handleChoice(getString(R.string.show_info_key)); | ||||||
|             } |             } | ||||||
|  |             return; | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         // Default / Ask always | ||||||
|  |         final List<AdapterChoiceItem> availableChoices = choiceChecker.getAvailableChoices(); | ||||||
|  |         switch (availableChoices.size()) { | ||||||
|  |             case 1: | ||||||
|  |                 handleChoice(availableChoices.get(0).key); | ||||||
|  |                 break; | ||||||
|  |             case 0: | ||||||
|  |                 handleChoice(getString(R.string.show_info_key)); | ||||||
|  |                 break; | ||||||
|  |             default: | ||||||
|  |                 showDialog(availableChoices); | ||||||
|  |                 break; | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     /** | ||||||
|  |      * This is a helper class for checking if the choices are available and/or selected. | ||||||
|  |      */ | ||||||
|  |     class ChoiceAvailabilityChecker { | ||||||
|  |         private final List<AdapterChoiceItem> availableChoices; | ||||||
|  |         private final String selectedChoiceKey; | ||||||
|  |  | ||||||
|  |         ChoiceAvailabilityChecker( | ||||||
|  |                 @NonNull final List<AdapterChoiceItem> availableChoices, | ||||||
|  |                 @NonNull final String selectedChoiceKey) { | ||||||
|  |             this.availableChoices = availableChoices; | ||||||
|  |             this.selectedChoiceKey = selectedChoiceKey; | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         public List<AdapterChoiceItem> getAvailableChoices() { | ||||||
|  |             return availableChoices; | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         public String getSelectedChoiceKey() { | ||||||
|  |             return selectedChoiceKey; | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         public boolean isAvailableAndSelected(@StringRes final int... wantedKeys) { | ||||||
|  |             return Arrays.stream(wantedKeys).anyMatch(this::isAvailableAndSelected); | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         public boolean isAvailableAndSelected(@StringRes final int wantedKey) { | ||||||
|  |             final String wanted = getString(wantedKey); | ||||||
|  |             // Check if the wanted option is selected | ||||||
|  |             if (!selectedChoiceKey.equals(wanted)) { | ||||||
|  |                 return false; | ||||||
|  |             } | ||||||
|  |             // Check if it's available | ||||||
|  |             return availableChoices.stream().anyMatch(item -> wanted.equals(item.key)); | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     private void showDialog(final List<AdapterChoiceItem> choices) { |     private void showDialog(final List<AdapterChoiceItem> choices) { | ||||||
|         final SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(this); |         final SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(this); | ||||||
|         final Context themeWrapperContext = getThemeWrapperContext(); |  | ||||||
|  |  | ||||||
|         final LayoutInflater inflater = LayoutInflater.from(themeWrapperContext); |         final Context themeWrapperContext = getThemeWrapperContext(); | ||||||
|         final RadioGroup radioGroup = SingleChoiceDialogViewBinding.inflate(getLayoutInflater()) |         final LayoutInflater layoutInflater = LayoutInflater.from(themeWrapperContext); | ||||||
|                 .list; |  | ||||||
|  |         final SingleChoiceDialogViewBinding binding = | ||||||
|  |                 SingleChoiceDialogViewBinding.inflate(layoutInflater); | ||||||
|  |         final RadioGroup radioGroup = binding.list; | ||||||
|  |  | ||||||
|         final DialogInterface.OnClickListener dialogButtonsClickListener = (dialog, which) -> { |         final DialogInterface.OnClickListener dialogButtonsClickListener = (dialog, which) -> { | ||||||
|             final int indexOfChild = radioGroup.indexOfChild( |             final int indexOfChild = radioGroup.indexOfChild( | ||||||
| @@ -351,21 +394,19 @@ public class RouterActivity extends AppCompatActivity { | |||||||
|  |  | ||||||
|         alertDialogChoice = new AlertDialog.Builder(themeWrapperContext) |         alertDialogChoice = new AlertDialog.Builder(themeWrapperContext) | ||||||
|                 .setTitle(R.string.preferred_open_action_share_menu_title) |                 .setTitle(R.string.preferred_open_action_share_menu_title) | ||||||
|                 .setView(radioGroup) |                 .setView(binding.getRoot()) | ||||||
|                 .setCancelable(true) |                 .setCancelable(true) | ||||||
|                 .setNegativeButton(R.string.just_once, dialogButtonsClickListener) |                 .setNegativeButton(R.string.just_once, dialogButtonsClickListener) | ||||||
|                 .setPositiveButton(R.string.always, dialogButtonsClickListener) |                 .setPositiveButton(R.string.always, dialogButtonsClickListener) | ||||||
|                 .setOnDismissListener((dialog) -> { |                 .setOnDismissListener(dialog -> { | ||||||
|                     if (!selectionIsDownload && !selectionIsAddToPlaylist) { |                     if (!selectionIsDownload && !selectionIsAddToPlaylist) { | ||||||
|                         finish(); |                         finish(); | ||||||
|                     } |                     } | ||||||
|                 }) |                 }) | ||||||
|                 .create(); |                 .create(); | ||||||
|  |  | ||||||
|         //noinspection CodeBlock2Expr |         alertDialogChoice.setOnShowListener(dialog -> setDialogButtonsState( | ||||||
|         alertDialogChoice.setOnShowListener(dialog -> { |                 alertDialogChoice, radioGroup.getCheckedRadioButtonId() != -1)); | ||||||
|             setDialogButtonsState(alertDialogChoice, radioGroup.getCheckedRadioButtonId() != -1); |  | ||||||
|         }); |  | ||||||
|  |  | ||||||
|         radioGroup.setOnCheckedChangeListener((group, checkedId) -> |         radioGroup.setOnCheckedChangeListener((group, checkedId) -> | ||||||
|                 setDialogButtonsState(alertDialogChoice, true)); |                 setDialogButtonsState(alertDialogChoice, true)); | ||||||
| @@ -385,7 +426,8 @@ public class RouterActivity extends AppCompatActivity { | |||||||
|  |  | ||||||
|         int id = 12345; |         int id = 12345; | ||||||
|         for (final AdapterChoiceItem item : choices) { |         for (final AdapterChoiceItem item : choices) { | ||||||
|             final RadioButton radioButton = ListRadioIconItemBinding.inflate(inflater).getRoot(); |             final RadioButton radioButton = ListRadioIconItemBinding.inflate(layoutInflater) | ||||||
|  |                     .getRoot(); | ||||||
|             radioButton.setText(item.description); |             radioButton.setText(item.description); | ||||||
|             radioButton.setCompoundDrawablesRelativeWithIntrinsicBounds( |             radioButton.setCompoundDrawablesRelativeWithIntrinsicBounds( | ||||||
|                     AppCompatResources.getDrawable(themeWrapperContext, item.icon), |                     AppCompatResources.getDrawable(themeWrapperContext, item.icon), | ||||||
| @@ -427,12 +469,47 @@ public class RouterActivity extends AppCompatActivity { | |||||||
|  |  | ||||||
|     private List<AdapterChoiceItem> getChoicesForService(final StreamingService service, |     private List<AdapterChoiceItem> getChoicesForService(final StreamingService service, | ||||||
|                                                          final LinkType linkType) { |                                                          final LinkType linkType) { | ||||||
|         final Context context = getThemeWrapperContext(); |         final AdapterChoiceItem showInfo = new AdapterChoiceItem( | ||||||
|  |                 getString(R.string.show_info_key), getString(R.string.show_info), | ||||||
|  |                 R.drawable.ic_info_outline); | ||||||
|  |         final AdapterChoiceItem videoPlayer = new AdapterChoiceItem( | ||||||
|  |                 getString(R.string.video_player_key), getString(R.string.video_player), | ||||||
|  |                 R.drawable.ic_play_arrow); | ||||||
|  |         final AdapterChoiceItem backgroundPlayer = new AdapterChoiceItem( | ||||||
|  |                 getString(R.string.background_player_key), getString(R.string.background_player), | ||||||
|  |                 R.drawable.ic_headset); | ||||||
|  |         final AdapterChoiceItem popupPlayer = new AdapterChoiceItem( | ||||||
|  |                 getString(R.string.popup_player_key), getString(R.string.popup_player), | ||||||
|  |                 R.drawable.ic_picture_in_picture); | ||||||
|  |  | ||||||
|         final List<AdapterChoiceItem> returnList = new ArrayList<>(); |         final List<AdapterChoiceItem> returnedItems = new ArrayList<>(); | ||||||
|         final List<StreamingService.ServiceInfo.MediaCapability> capabilities |         returnedItems.add(showInfo); // Always present | ||||||
|                 = service.getServiceInfo().getMediaCapabilities(); |  | ||||||
|  |  | ||||||
|  |         final List<StreamingService.ServiceInfo.MediaCapability> capabilities = | ||||||
|  |                 service.getServiceInfo().getMediaCapabilities(); | ||||||
|  |  | ||||||
|  |         if (linkType == LinkType.STREAM) { | ||||||
|  |             if (capabilities.contains(VIDEO)) { | ||||||
|  |                 returnedItems.add(videoPlayer); | ||||||
|  |                 returnedItems.add(popupPlayer); | ||||||
|  |             } | ||||||
|  |             if (capabilities.contains(AUDIO)) { | ||||||
|  |                 returnedItems.add(backgroundPlayer); | ||||||
|  |             } | ||||||
|  |             // download is redundant for linkType CHANNEL AND PLAYLIST (till playlist downloading is | ||||||
|  |             // not supported ) | ||||||
|  |             returnedItems.add(new AdapterChoiceItem(getString(R.string.download_key), | ||||||
|  |                     getString(R.string.download), | ||||||
|  |                     R.drawable.ic_file_download)); | ||||||
|  |  | ||||||
|  |             // Add to playlist is not necessary for CHANNEL and PLAYLIST linkType since those can | ||||||
|  |             // not be added to a playlist | ||||||
|  |             returnedItems.add(new AdapterChoiceItem(getString(R.string.add_to_playlist_key), | ||||||
|  |                     getString(R.string.add_to_playlist), | ||||||
|  |                     R.drawable.ic_add)); | ||||||
|  |         } else { | ||||||
|  |             // LinkType.NONE is never present because it's filtered out before | ||||||
|  |             // channels and playlist can be played as they contain a list of videos | ||||||
|             final SharedPreferences preferences = PreferenceManager |             final SharedPreferences preferences = PreferenceManager | ||||||
|                     .getDefaultSharedPreferences(this); |                     .getDefaultSharedPreferences(this); | ||||||
|             final boolean isExtVideoEnabled = preferences.getBoolean( |             final boolean isExtVideoEnabled = preferences.getBoolean( | ||||||
| @@ -440,74 +517,16 @@ public class RouterActivity extends AppCompatActivity { | |||||||
|             final boolean isExtAudioEnabled = preferences.getBoolean( |             final boolean isExtAudioEnabled = preferences.getBoolean( | ||||||
|                     getString(R.string.use_external_audio_player_key), false); |                     getString(R.string.use_external_audio_player_key), false); | ||||||
|  |  | ||||||
|         final AdapterChoiceItem videoPlayer = new AdapterChoiceItem( |  | ||||||
|                 getString(R.string.video_player_key), getString(R.string.video_player), |  | ||||||
|                 R.drawable.ic_play_arrow); |  | ||||||
|         final AdapterChoiceItem showInfo = new AdapterChoiceItem( |  | ||||||
|                 getString(R.string.show_info_key), getString(R.string.show_info), |  | ||||||
|                 R.drawable.ic_info_outline); |  | ||||||
|         final AdapterChoiceItem popupPlayer = new AdapterChoiceItem( |  | ||||||
|                 getString(R.string.popup_player_key), getString(R.string.popup_player), |  | ||||||
|                 R.drawable.ic_picture_in_picture); |  | ||||||
|         final AdapterChoiceItem backgroundPlayer = new AdapterChoiceItem( |  | ||||||
|                 getString(R.string.background_player_key), getString(R.string.background_player), |  | ||||||
|                 R.drawable.ic_headset); |  | ||||||
|         final AdapterChoiceItem addToPlaylist = new AdapterChoiceItem( |  | ||||||
|                 getString(R.string.add_to_playlist_key), getString(R.string.add_to_playlist), |  | ||||||
|                 R.drawable.ic_add); |  | ||||||
|  |  | ||||||
|  |  | ||||||
|         if (linkType == LinkType.STREAM) { |  | ||||||
|             if (isExtVideoEnabled) { |  | ||||||
|                 // show both "show info" and "video player", they are two different activities |  | ||||||
|                 returnList.add(showInfo); |  | ||||||
|                 returnList.add(videoPlayer); |  | ||||||
|             } else { |  | ||||||
|                 final MainPlayer.PlayerType playerType = PlayerHolder.getInstance().getType(); |  | ||||||
|                 if (capabilities.contains(VIDEO) |  | ||||||
|                         && PlayerHelper.isAutoplayAllowedByUser(context) |  | ||||||
|                         && playerType == null || playerType == MainPlayer.PlayerType.VIDEO) { |  | ||||||
|                     // show only "video player" since the details activity will be opened and the |  | ||||||
|                     // video will be auto played there. Since "show info" would do the exact same |  | ||||||
|                     // thing, use that as a key to let VideoDetailFragment load the stream instead |  | ||||||
|                     // of using FetcherService (see comment in handleChoice()) |  | ||||||
|                     returnList.add(new AdapterChoiceItem( |  | ||||||
|                             showInfo.key, videoPlayer.description, videoPlayer.icon)); |  | ||||||
|                 } else { |  | ||||||
|                     // show only "show info" if video player is not applicable, auto play is |  | ||||||
|                     // disabled or a video is playing in a player different than the main one |  | ||||||
|                     returnList.add(showInfo); |  | ||||||
|                 } |  | ||||||
|             } |  | ||||||
|  |  | ||||||
|             if (capabilities.contains(VIDEO)) { |  | ||||||
|                 returnList.add(popupPlayer); |  | ||||||
|             } |  | ||||||
|             if (capabilities.contains(AUDIO)) { |  | ||||||
|                 returnList.add(backgroundPlayer); |  | ||||||
|             } |  | ||||||
|             // download is redundant for linkType CHANNEL AND PLAYLIST (till playlist downloading is |  | ||||||
|             // not supported ) |  | ||||||
|             returnList.add(new AdapterChoiceItem(getString(R.string.download_key), |  | ||||||
|                     getString(R.string.download), |  | ||||||
|                     R.drawable.ic_file_download)); |  | ||||||
|  |  | ||||||
|             // Add to playlist is not necessary for CHANNEL and PLAYLIST linkType since those can |  | ||||||
|             // not be added to a playlist |  | ||||||
|             returnList.add(addToPlaylist); |  | ||||||
|  |  | ||||||
|         } else { |  | ||||||
|             returnList.add(showInfo); |  | ||||||
|             if (capabilities.contains(VIDEO) && !isExtVideoEnabled) { |             if (capabilities.contains(VIDEO) && !isExtVideoEnabled) { | ||||||
|                 returnList.add(videoPlayer); |                 returnedItems.add(videoPlayer); | ||||||
|                 returnList.add(popupPlayer); |                 returnedItems.add(popupPlayer); | ||||||
|             } |             } | ||||||
|             if (capabilities.contains(AUDIO) && !isExtAudioEnabled) { |             if (capabilities.contains(AUDIO) && !isExtAudioEnabled) { | ||||||
|                 returnList.add(backgroundPlayer); |                 returnedItems.add(backgroundPlayer); | ||||||
|             } |             } | ||||||
|         } |         } | ||||||
|  |  | ||||||
|         return returnList; |         return returnedItems; | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     private Context getThemeWrapperContext() { |     private Context getThemeWrapperContext() { | ||||||
| @@ -569,7 +588,8 @@ public class RouterActivity extends AppCompatActivity { | |||||||
|  |  | ||||||
|         // stop and bypass FetcherService if InfoScreen was selected since |         // stop and bypass FetcherService if InfoScreen was selected since | ||||||
|         // StreamDetailFragment can fetch data itself |         // StreamDetailFragment can fetch data itself | ||||||
|         if (selectedChoiceKey.equals(getString(R.string.show_info_key))) { |         if (selectedChoiceKey.equals(getString(R.string.show_info_key)) | ||||||
|  |                 || canHandleChoiceLikeShowInfo(selectedChoiceKey)) { | ||||||
|             disposables.add(Observable |             disposables.add(Observable | ||||||
|                     .fromCallable(() -> NavigationHelper.getIntentByLink(this, currentUrl)) |                     .fromCallable(() -> NavigationHelper.getIntentByLink(this, currentUrl)) | ||||||
|                     .subscribeOn(Schedulers.io()) |                     .subscribeOn(Schedulers.io()) | ||||||
| @@ -592,6 +612,30 @@ public class RouterActivity extends AppCompatActivity { | |||||||
|         finish(); |         finish(); | ||||||
|     } |     } | ||||||
|  |  | ||||||
|  |     private boolean canHandleChoiceLikeShowInfo(final String selectedChoiceKey) { | ||||||
|  |         if (!selectedChoiceKey.equals(getString(R.string.video_player_key))) { | ||||||
|  |             return false; | ||||||
|  |         } | ||||||
|  |         // "video player" can be handled like "show info" (because VideoDetailFragment can load | ||||||
|  |         // the stream instead of FetcherService) when... | ||||||
|  |  | ||||||
|  |         // ...Autoplay is enabled | ||||||
|  |         if (!PlayerHelper.isAutoplayAllowedByUser(getThemeWrapperContext())) { | ||||||
|  |             return false; | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         final boolean isExtVideoEnabled = PreferenceManager.getDefaultSharedPreferences(this) | ||||||
|  |                 .getBoolean(getString(R.string.use_external_video_player_key), false); | ||||||
|  |         // ...it's not done via an external player | ||||||
|  |         if (isExtVideoEnabled) { | ||||||
|  |             return false; | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         // ...the player is not running or in normal Video-mode/type | ||||||
|  |         final MainPlayer.PlayerType playerType = PlayerHolder.getInstance().getType(); | ||||||
|  |         return playerType == null || playerType == MainPlayer.PlayerType.VIDEO; | ||||||
|  |     } | ||||||
|  |  | ||||||
|     private void openAddToPlaylistDialog() { |     private void openAddToPlaylistDialog() { | ||||||
|         // Getting the stream info usually takes a moment |         // Getting the stream info usually takes a moment | ||||||
|         // Notifying the user here to ensure that no confusion arises |         // Notifying the user here to ensure that no confusion arises | ||||||
| @@ -674,8 +718,8 @@ public class RouterActivity extends AppCompatActivity { | |||||||
|         final int icon; |         final int icon; | ||||||
|  |  | ||||||
|         AdapterChoiceItem(final String key, final String description, final int icon) { |         AdapterChoiceItem(final String key, final String description, final int icon) { | ||||||
|             this.description = description; |  | ||||||
|             this.key = key; |             this.key = key; | ||||||
|  |             this.description = description; | ||||||
|             this.icon = icon; |             this.icon = icon; | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
|   | |||||||
| @@ -663,8 +663,7 @@ public final class VideoDetailFragment | |||||||
|             binding.detailControlsCrashThePlayer.setOnClickListener( |             binding.detailControlsCrashThePlayer.setOnClickListener( | ||||||
|                     v -> VideoDetailPlayerCrasher.onCrashThePlayer( |                     v -> VideoDetailPlayerCrasher.onCrashThePlayer( | ||||||
|                             this.getContext(), |                             this.getContext(), | ||||||
|                             this.player, |                             this.player) | ||||||
|                             getLayoutInflater()) |  | ||||||
|             ); |             ); | ||||||
|         } |         } | ||||||
|  |  | ||||||
|   | |||||||
| @@ -1,5 +1,9 @@ | |||||||
| package org.schabi.newpipe.fragments.detail; | package org.schabi.newpipe.fragments.detail; | ||||||
|  |  | ||||||
|  | import static com.google.android.exoplayer2.PlaybackException.ERROR_CODE_BEHIND_LIVE_WINDOW; | ||||||
|  | import static com.google.android.exoplayer2.PlaybackException.ERROR_CODE_DECODING_FAILED; | ||||||
|  | import static com.google.android.exoplayer2.PlaybackException.ERROR_CODE_UNSPECIFIED; | ||||||
|  |  | ||||||
| import android.content.Context; | import android.content.Context; | ||||||
| import android.util.Log; | import android.util.Log; | ||||||
| import android.view.ContextThemeWrapper; | import android.view.ContextThemeWrapper; | ||||||
| @@ -29,10 +33,6 @@ import java.util.LinkedHashMap; | |||||||
| import java.util.Map; | import java.util.Map; | ||||||
| import java.util.function.Supplier; | import java.util.function.Supplier; | ||||||
|  |  | ||||||
| import static com.google.android.exoplayer2.PlaybackException.ERROR_CODE_BEHIND_LIVE_WINDOW; |  | ||||||
| import static com.google.android.exoplayer2.PlaybackException.ERROR_CODE_DECODING_FAILED; |  | ||||||
| import static com.google.android.exoplayer2.PlaybackException.ERROR_CODE_UNSPECIFIED; |  | ||||||
|  |  | ||||||
| /** | /** | ||||||
|  * Outsourced logic for crashing the player in the {@link VideoDetailFragment}. |  * Outsourced logic for crashing the player in the {@link VideoDetailFragment}. | ||||||
|  */ |  */ | ||||||
| @@ -97,8 +97,7 @@ public final class VideoDetailPlayerCrasher { | |||||||
|  |  | ||||||
|     public static void onCrashThePlayer( |     public static void onCrashThePlayer( | ||||||
|             @NonNull final Context context, |             @NonNull final Context context, | ||||||
|             @Nullable final Player player, |             @Nullable final Player player | ||||||
|             @NonNull final LayoutInflater layoutInflater |  | ||||||
|     ) { |     ) { | ||||||
|         if (player == null) { |         if (player == null) { | ||||||
|             Log.d(TAG, "Player is not available"); |             Log.d(TAG, "Player is not available"); | ||||||
| @@ -109,16 +108,15 @@ public final class VideoDetailPlayerCrasher { | |||||||
|         } |         } | ||||||
|  |  | ||||||
|         // -- Build the dialog/UI -- |         // -- Build the dialog/UI -- | ||||||
|  |  | ||||||
|         final Context themeWrapperContext = getThemeWrapperContext(context); |         final Context themeWrapperContext = getThemeWrapperContext(context); | ||||||
|  |  | ||||||
|         final LayoutInflater inflater = LayoutInflater.from(themeWrapperContext); |         final LayoutInflater inflater = LayoutInflater.from(themeWrapperContext); | ||||||
|         final RadioGroup radioGroup = SingleChoiceDialogViewBinding.inflate(layoutInflater) |  | ||||||
|                 .list; |  | ||||||
|  |  | ||||||
|         final AlertDialog alertDialog = new AlertDialog.Builder(getThemeWrapperContext(context)) |         final SingleChoiceDialogViewBinding binding = | ||||||
|  |                 SingleChoiceDialogViewBinding.inflate(inflater); | ||||||
|  |  | ||||||
|  |         final AlertDialog alertDialog = new AlertDialog.Builder(themeWrapperContext) | ||||||
|                 .setTitle("Choose an exception") |                 .setTitle("Choose an exception") | ||||||
|                 .setView(radioGroup) |                 .setView(binding.getRoot()) | ||||||
|                 .setCancelable(true) |                 .setCancelable(true) | ||||||
|                 .setNegativeButton(R.string.cancel, null) |                 .setNegativeButton(R.string.cancel, null) | ||||||
|                 .create(); |                 .create(); | ||||||
| @@ -136,11 +134,9 @@ public final class VideoDetailPlayerCrasher { | |||||||
|             ); |             ); | ||||||
|             radioButton.setOnClickListener(v -> { |             radioButton.setOnClickListener(v -> { | ||||||
|                 tryCrashPlayerWith(player, entry.getValue().get()); |                 tryCrashPlayerWith(player, entry.getValue().get()); | ||||||
|                 if (alertDialog != null) { |  | ||||||
|                 alertDialog.cancel(); |                 alertDialog.cancel(); | ||||||
|                 } |  | ||||||
|             }); |             }); | ||||||
|             radioGroup.addView(radioButton); |             binding.list.addView(radioButton); | ||||||
|         } |         } | ||||||
|  |  | ||||||
|         alertDialog.show(); |         alertDialog.show(); | ||||||
|   | |||||||
| @@ -10,7 +10,6 @@ import android.view.View; | |||||||
| import android.view.ViewGroup; | import android.view.ViewGroup; | ||||||
| import android.widget.CheckBox; | import android.widget.CheckBox; | ||||||
| import android.widget.ImageView; | import android.widget.ImageView; | ||||||
| import android.widget.LinearLayout; |  | ||||||
| import android.widget.RadioButton; | import android.widget.RadioButton; | ||||||
| import android.widget.RadioGroup; | import android.widget.RadioGroup; | ||||||
| import android.widget.TextView; | import android.widget.TextView; | ||||||
| @@ -25,6 +24,8 @@ import androidx.preference.Preference; | |||||||
| import androidx.preference.PreferenceViewHolder; | import androidx.preference.PreferenceViewHolder; | ||||||
|  |  | ||||||
| import org.schabi.newpipe.R; | import org.schabi.newpipe.R; | ||||||
|  | import org.schabi.newpipe.databinding.ListRadioIconItemBinding; | ||||||
|  | import org.schabi.newpipe.databinding.SingleChoiceDialogViewBinding; | ||||||
| import org.schabi.newpipe.player.MainPlayer; | import org.schabi.newpipe.player.MainPlayer; | ||||||
| import org.schabi.newpipe.player.NotificationConstants; | import org.schabi.newpipe.player.NotificationConstants; | ||||||
| import org.schabi.newpipe.util.DeviceUtils; | import org.schabi.newpipe.util.DeviceUtils; | ||||||
| @@ -189,13 +190,12 @@ public class NotificationActionsPreference extends Preference { | |||||||
|  |  | ||||||
|         void openActionChooserDialog() { |         void openActionChooserDialog() { | ||||||
|             final LayoutInflater inflater = LayoutInflater.from(getContext()); |             final LayoutInflater inflater = LayoutInflater.from(getContext()); | ||||||
|             final LinearLayout rootLayout = (LinearLayout) inflater.inflate( |             final SingleChoiceDialogViewBinding binding = | ||||||
|                     R.layout.single_choice_dialog_view, null, false); |                     SingleChoiceDialogViewBinding.inflate(inflater); | ||||||
|             final RadioGroup radioGroup = rootLayout.findViewById(android.R.id.list); |  | ||||||
|  |  | ||||||
|             final AlertDialog alertDialog = new AlertDialog.Builder(getContext()) |             final AlertDialog alertDialog = new AlertDialog.Builder(getContext()) | ||||||
|                     .setTitle(SLOT_TITLES[i]) |                     .setTitle(SLOT_TITLES[i]) | ||||||
|                     .setView(radioGroup) |                     .setView(binding.getRoot()) | ||||||
|                     .setCancelable(true) |                     .setCancelable(true) | ||||||
|                     .create(); |                     .create(); | ||||||
|  |  | ||||||
| @@ -207,8 +207,8 @@ public class NotificationActionsPreference extends Preference { | |||||||
|  |  | ||||||
|             for (int id = 0; id < NotificationConstants.SLOT_ALLOWED_ACTIONS[i].length; ++id) { |             for (int id = 0; id < NotificationConstants.SLOT_ALLOWED_ACTIONS[i].length; ++id) { | ||||||
|                 final int action = NotificationConstants.SLOT_ALLOWED_ACTIONS[i][id]; |                 final int action = NotificationConstants.SLOT_ALLOWED_ACTIONS[i][id]; | ||||||
|                 final RadioButton radioButton |                 final RadioButton radioButton = ListRadioIconItemBinding.inflate(inflater) | ||||||
|                         = (RadioButton) inflater.inflate(R.layout.list_radio_icon_item, null); |                         .getRoot(); | ||||||
|  |  | ||||||
|                 // if present set action icon with correct color |                 // if present set action icon with correct color | ||||||
|                 if (NotificationConstants.ACTION_ICONS[action] != 0) { |                 if (NotificationConstants.ACTION_ICONS[action] != 0) { | ||||||
| @@ -230,7 +230,7 @@ public class NotificationActionsPreference extends Preference { | |||||||
|                 radioButton.setLayoutParams(new RadioGroup.LayoutParams( |                 radioButton.setLayoutParams(new RadioGroup.LayoutParams( | ||||||
|                         ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT)); |                         ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT)); | ||||||
|                 radioButton.setOnClickListener(radioButtonsClickListener); |                 radioButton.setOnClickListener(radioButtonsClickListener); | ||||||
|                 radioGroup.addView(radioButton); |                 binding.list.addView(radioButton); | ||||||
|             } |             } | ||||||
|             alertDialog.show(); |             alertDialog.show(); | ||||||
|  |  | ||||||
|   | |||||||
| @@ -1,6 +1,14 @@ | |||||||
| <?xml version="1.0" encoding="utf-8"?> | <?xml version="1.0" encoding="utf-8"?><!-- --> | ||||||
| <RadioGroup xmlns:android="http://schemas.android.com/apk/res/android" | <ScrollView xmlns:android="http://schemas.android.com/apk/res/android" | ||||||
|  |     android:layout_width="match_parent" | ||||||
|  |     android:layout_height="match_parent" | ||||||
|  |     android:fadeScrollbars="false"> | ||||||
|  |  | ||||||
|  |     <RadioGroup | ||||||
|         android:id="@android:id/list" |         android:id="@android:id/list" | ||||||
|         android:layout_width="match_parent" |         android:layout_width="match_parent" | ||||||
|         android:layout_height="wrap_content" |         android:layout_height="wrap_content" | ||||||
|         android:paddingTop="?attr/listPreferredItemPaddingLeft" /> |         android:paddingTop="?attr/listPreferredItemPaddingLeft" /> | ||||||
|  | </ScrollView> | ||||||
|  |  | ||||||
|  |  | ||||||
|   | |||||||
| @@ -12,21 +12,31 @@ | |||||||
|     <style name="Base" parent="Base.V21"/> |     <style name="Base" parent="Base.V21"/> | ||||||
|  |  | ||||||
|     <!-- Light Theme --> |     <!-- Light Theme --> | ||||||
|     <style name="Base.V21.LightTheme" parent="Base.V19.LightTheme"> |     <style name="Base.V21.LightTheme" parent="Base.V19.LightTheme" /> | ||||||
|  |  | ||||||
|     </style> |  | ||||||
|     <style name="Base.LightTheme" parent="Base.V21.LightTheme" /> |     <style name="Base.LightTheme" parent="Base.V21.LightTheme" /> | ||||||
|  |  | ||||||
|     <!-- Dark Theme --> |     <!-- Dark Theme --> | ||||||
|     <style name="Base.V21.DarkTheme" parent="Base.V19.DarkTheme"> |     <style name="Base.V21.DarkTheme" parent="Base.V19.DarkTheme" /> | ||||||
|  |  | ||||||
|     </style> |  | ||||||
|     <style name="Base.DarkTheme" parent="Base.V21.DarkTheme" /> |     <style name="Base.DarkTheme" parent="Base.V21.DarkTheme" /> | ||||||
|  |  | ||||||
|     <!-- Black Theme --> |     <!-- Black Theme --> | ||||||
|     <style name="Base.V21.BlackTheme" parent="Base.V19.BlackTheme"> |     <style name="Base.V21.BlackTheme" parent="Base.V19.BlackTheme" /> | ||||||
|  |  | ||||||
|     </style> |  | ||||||
|     <style name="Base.BlackTheme" parent="Base.V21.BlackTheme" /> |     <style name="Base.BlackTheme" parent="Base.V21.BlackTheme" /> | ||||||
|  |  | ||||||
|  |     <!-- Router Activity --> | ||||||
|  |     <style name="Base.V21.RouterActivityThemeLight" parent="Base.RouterActivityThemeLight"> | ||||||
|  |         <item name="android:statusBarColor">@android:color/transparent</item> | ||||||
|  |     </style> | ||||||
|  |  | ||||||
|  |     <style name="RouterActivityThemeLight" parent="Base.V21.RouterActivityThemeLight" /> | ||||||
|  |  | ||||||
|  |     <style name="Base.V21.RouterActivityThemeDark" parent="Base.RouterActivityThemeDark"> | ||||||
|  |         <item name="android:statusBarColor">@android:color/transparent</item> | ||||||
|  |     </style> | ||||||
|  |  | ||||||
|  |     <style name="RouterActivityThemeDark" parent="Base.V21.RouterActivityThemeDark" /> | ||||||
|  |  | ||||||
| </resources> | </resources> | ||||||
|   | |||||||
| @@ -130,7 +130,8 @@ | |||||||
|         <item name="colorAccent">@color/black_settings_accent_color</item> |         <item name="colorAccent">@color/black_settings_accent_color</item> | ||||||
|     </style> |     </style> | ||||||
|  |  | ||||||
|     <style name="RouterActivityThemeLight" parent="LightTheme"> |     <!-- Router Activity --> | ||||||
|  |     <style name="Base.RouterActivityThemeLight" parent="LightTheme"> | ||||||
|         <item name="android:windowNoTitle">true</item> |         <item name="android:windowNoTitle">true</item> | ||||||
|         <item name="android:windowBackground">@android:color/transparent</item> |         <item name="android:windowBackground">@android:color/transparent</item> | ||||||
|         <item name="android:colorBackgroundCacheHint">@null</item> |         <item name="android:colorBackgroundCacheHint">@null</item> | ||||||
| @@ -138,7 +139,9 @@ | |||||||
|         <item name="android:windowAnimationStyle">@null</item> |         <item name="android:windowAnimationStyle">@null</item> | ||||||
|     </style> |     </style> | ||||||
|  |  | ||||||
|     <style name="RouterActivityThemeDark" parent="DarkTheme"> |     <style name="RouterActivityThemeLight" parent="Base.RouterActivityThemeLight" /> | ||||||
|  |  | ||||||
|  |     <style name="Base.RouterActivityThemeDark" parent="DarkTheme"> | ||||||
|         <item name="android:windowNoTitle">true</item> |         <item name="android:windowNoTitle">true</item> | ||||||
|         <item name="android:windowBackground">@android:color/transparent</item> |         <item name="android:windowBackground">@android:color/transparent</item> | ||||||
|         <item name="android:colorBackgroundCacheHint">@null</item> |         <item name="android:colorBackgroundCacheHint">@null</item> | ||||||
| @@ -146,4 +149,6 @@ | |||||||
|         <item name="android:windowAnimationStyle">@null</item> |         <item name="android:windowAnimationStyle">@null</item> | ||||||
|     </style> |     </style> | ||||||
|  |  | ||||||
|  |     <style name="RouterActivityThemeDark" parent="Base.RouterActivityThemeDark" /> | ||||||
|  |  | ||||||
| </resources> | </resources> | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user
	 Stypox
					Stypox