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:
Stypox 2022-06-05 11:47:51 +02:00 committed by GitHub
commit a59660f421
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
7 changed files with 219 additions and 157 deletions

View File

@ -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,
R.string.add_to_playlist_key)) {
handleChoice(choiceChecker.getSelectedChoiceKey());
return;
}
// Check if the choice is player related
if (choiceChecker.isAvailableAndSelected(
R.string.video_player_key,
R.string.background_player_key,
R.string.popup_player_key)) {
final String selectedChoice = choiceChecker.getSelectedChoiceKey();
switch (choices.size()) {
case 1:
handleChoice(choices.get(0).key);
break;
case 0:
handleChoice(showInfoKey);
break;
default:
showDialog(choices);
break;
}
} else if (selectedChoiceKey.equals(showInfoKey)) {
handleChoice(showInfoKey);
} else if (selectedChoiceKey.equals(downloadKey)) {
handleChoice(downloadKey);
} else {
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.LENGTH_LONG).show(); Toast.makeText(this, R.string.external_player_unsupported_link_type,
handleChoice(showInfoKey); Toast.LENGTH_LONG).show();
return; handleChoice(getString(R.string.show_info_key));
} 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,87 +469,64 @@ 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 List<AdapterChoiceItem> returnList = new ArrayList<>();
final List<StreamingService.ServiceInfo.MediaCapability> capabilities
= service.getServiceInfo().getMediaCapabilities();
final SharedPreferences preferences = PreferenceManager
.getDefaultSharedPreferences(this);
final boolean isExtVideoEnabled = preferences.getBoolean(
getString(R.string.use_external_video_player_key), false);
final boolean isExtAudioEnabled = preferences.getBoolean(
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( final AdapterChoiceItem showInfo = new AdapterChoiceItem(
getString(R.string.show_info_key), getString(R.string.show_info), getString(R.string.show_info_key), getString(R.string.show_info),
R.drawable.ic_info_outline); R.drawable.ic_info_outline);
final AdapterChoiceItem popupPlayer = new AdapterChoiceItem( final AdapterChoiceItem videoPlayer = new AdapterChoiceItem(
getString(R.string.popup_player_key), getString(R.string.popup_player), getString(R.string.video_player_key), getString(R.string.video_player),
R.drawable.ic_picture_in_picture); R.drawable.ic_play_arrow);
final AdapterChoiceItem backgroundPlayer = new AdapterChoiceItem( final AdapterChoiceItem backgroundPlayer = new AdapterChoiceItem(
getString(R.string.background_player_key), getString(R.string.background_player), getString(R.string.background_player_key), getString(R.string.background_player),
R.drawable.ic_headset); R.drawable.ic_headset);
final AdapterChoiceItem addToPlaylist = new AdapterChoiceItem( final AdapterChoiceItem popupPlayer = new AdapterChoiceItem(
getString(R.string.add_to_playlist_key), getString(R.string.add_to_playlist), getString(R.string.popup_player_key), getString(R.string.popup_player),
R.drawable.ic_add); R.drawable.ic_picture_in_picture);
final List<AdapterChoiceItem> returnedItems = new ArrayList<>();
returnedItems.add(showInfo); // Always present
final List<StreamingService.ServiceInfo.MediaCapability> capabilities =
service.getServiceInfo().getMediaCapabilities();
if (linkType == LinkType.STREAM) { 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)) { if (capabilities.contains(VIDEO)) {
returnList.add(popupPlayer); returnedItems.add(videoPlayer);
returnedItems.add(popupPlayer);
} }
if (capabilities.contains(AUDIO)) { if (capabilities.contains(AUDIO)) {
returnList.add(backgroundPlayer); returnedItems.add(backgroundPlayer);
} }
// download is redundant for linkType CHANNEL AND PLAYLIST (till playlist downloading is // download is redundant for linkType CHANNEL AND PLAYLIST (till playlist downloading is
// not supported ) // not supported )
returnList.add(new AdapterChoiceItem(getString(R.string.download_key), returnedItems.add(new AdapterChoiceItem(getString(R.string.download_key),
getString(R.string.download), getString(R.string.download),
R.drawable.ic_file_download)); R.drawable.ic_file_download));
// Add to playlist is not necessary for CHANNEL and PLAYLIST linkType since those can // Add to playlist is not necessary for CHANNEL and PLAYLIST linkType since those can
// not be added to a playlist // not be added to a playlist
returnList.add(addToPlaylist); returnedItems.add(new AdapterChoiceItem(getString(R.string.add_to_playlist_key),
getString(R.string.add_to_playlist),
R.drawable.ic_add));
} else { } else {
returnList.add(showInfo); // 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
.getDefaultSharedPreferences(this);
final boolean isExtVideoEnabled = preferences.getBoolean(
getString(R.string.use_external_video_player_key), false);
final boolean isExtAudioEnabled = preferences.getBoolean(
getString(R.string.use_external_audio_player_key), false);
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;
} }
} }

View File

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

View File

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

View File

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

View File

@ -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:id="@android:id/list"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="match_parent"
android:paddingTop="?attr/listPreferredItemPaddingLeft" /> android:fadeScrollbars="false">
<RadioGroup
android:id="@android:id/list"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:paddingTop="?attr/listPreferredItemPaddingLeft" />
</ScrollView>

View File

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

View File

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