From 71b32fe64104eabd422b7aa4cea6b30e53c48d22 Mon Sep 17 00:00:00 2001 From: Stypox Date: Tue, 8 Sep 2020 19:02:05 +0200 Subject: [PATCH] Add notification costumization settings menu --- .../org/schabi/newpipe/RouterActivity.java | 2 +- .../org/schabi/newpipe/player/MainPlayer.java | 8 +- .../newpipe/player/NotificationConstants.java | 141 +++++++++ .../newpipe/player/NotificationUtil.java | 189 ++++++------ .../newpipe/player/VideoPlayerImpl.java | 5 + .../NotificationSettingsFragment.java | 271 ++++++++++++++++++ .../drawable-hdpi/ic_close_white_24dp_png.png | Bin 0 -> 415 bytes ...ng => ic_hourglass_top_white_24dp_png.png} | Bin .../drawable-mdpi/ic_close_white_24dp_png.png | Bin 0 -> 285 bytes ...ng => ic_hourglass_top_white_24dp_png.png} | Bin .../ic_close_white_24dp_png.png | Bin 0 -> 602 bytes ...ng => ic_hourglass_top_white_24dp_png.png} | Bin .../ic_close_white_24dp_png.png | Bin 0 -> 1034 bytes ...ng => ic_hourglass_top_white_24dp_png.png} | Bin .../ic_close_white_24dp_png.png | Bin 0 -> 2068 bytes ...ng => ic_hourglass_top_white_24dp_png.png} | Bin .../drawable/ic_hourglass_top_white_24dp.xml | 9 + .../main/res/layout/list_radio_icon_item.xml | 4 +- .../main/res/layout/settings_notification.xml | 135 +++++++++ .../layout/settings_notification_action.xml | 88 ++++++ ...view.xml => single_choice_dialog_view.xml} | 0 app/src/main/res/values/settings_keys.xml | 109 +------ app/src/main/res/values/strings.xml | 31 +- app/src/main/res/xml/appearance_settings.xml | 66 ----- app/src/main/res/xml/main_settings.xml | 6 + 25 files changed, 774 insertions(+), 290 deletions(-) create mode 100644 app/src/main/java/org/schabi/newpipe/player/NotificationConstants.java create mode 100644 app/src/main/java/org/schabi/newpipe/settings/NotificationSettingsFragment.java create mode 100644 app/src/main/res/drawable-hdpi/ic_close_white_24dp_png.png rename app/src/main/res/drawable-hdpi/{ic_hourglass_top_white_24dp.png => ic_hourglass_top_white_24dp_png.png} (100%) create mode 100644 app/src/main/res/drawable-mdpi/ic_close_white_24dp_png.png rename app/src/main/res/drawable-mdpi/{ic_hourglass_top_white_24dp.png => ic_hourglass_top_white_24dp_png.png} (100%) create mode 100644 app/src/main/res/drawable-xhdpi/ic_close_white_24dp_png.png rename app/src/main/res/drawable-xhdpi/{ic_hourglass_top_white_24dp.png => ic_hourglass_top_white_24dp_png.png} (100%) create mode 100644 app/src/main/res/drawable-xxhdpi/ic_close_white_24dp_png.png rename app/src/main/res/drawable-xxhdpi/{ic_hourglass_top_white_24dp.png => ic_hourglass_top_white_24dp_png.png} (100%) create mode 100644 app/src/main/res/drawable-xxxhdpi/ic_close_white_24dp_png.png rename app/src/main/res/drawable-xxxhdpi/{ic_hourglass_top_white_24dp.png => ic_hourglass_top_white_24dp_png.png} (100%) create mode 100644 app/src/main/res/drawable/ic_hourglass_top_white_24dp.xml create mode 100644 app/src/main/res/layout/settings_notification.xml create mode 100644 app/src/main/res/layout/settings_notification_action.xml rename app/src/main/res/layout/{preferred_player_dialog_view.xml => single_choice_dialog_view.xml} (100%) diff --git a/app/src/main/java/org/schabi/newpipe/RouterActivity.java b/app/src/main/java/org/schabi/newpipe/RouterActivity.java index 70fceaf07..0d658f3a1 100644 --- a/app/src/main/java/org/schabi/newpipe/RouterActivity.java +++ b/app/src/main/java/org/schabi/newpipe/RouterActivity.java @@ -258,7 +258,7 @@ public class RouterActivity extends AppCompatActivity { final LayoutInflater inflater = LayoutInflater.from(themeWrapperContext); final LinearLayout rootLayout = (LinearLayout) inflater.inflate( - R.layout.preferred_player_dialog_view, null, false); + R.layout.single_choice_dialog_view, null, false); final RadioGroup radioGroup = rootLayout.findViewById(android.R.id.list); final DialogInterface.OnClickListener dialogButtonsClickListener = (dialog, which) -> { diff --git a/app/src/main/java/org/schabi/newpipe/player/MainPlayer.java b/app/src/main/java/org/schabi/newpipe/player/MainPlayer.java index 065efca02..a16fc3cbf 100644 --- a/app/src/main/java/org/schabi/newpipe/player/MainPlayer.java +++ b/app/src/main/java/org/schabi/newpipe/player/MainPlayer.java @@ -77,11 +77,11 @@ public final class MainPlayer extends Service { static final String ACTION_FAST_FORWARD = "org.schabi.newpipe.player.MainPlayer.ACTION_FAST_FORWARD"; static final String ACTION_BUFFERING - = "org.schabi.newpipe.player.BackgroundPlayer.ACTION_BUFFERING"; + = "org.schabi.newpipe.player.MainPlayer.ACTION_BUFFERING"; static final String ACTION_SHUFFLE - = "org.schabi.newpipe.player.BackgroundPlayer.ACTION_SHUFFLE"; - - static final String SET_IMAGE_RESOURCE_METHOD = "setImageResource"; + = "org.schabi.newpipe.player.MainPlayer.ACTION_SHUFFLE"; + public static final String ACTION_RECREATE_NOTIFICATION + = "org.schabi.newpipe.player.MainPlayer.ACTION_RECREATE_NOTIFICATION"; /*////////////////////////////////////////////////////////////////////////// // Service's LifeCycle diff --git a/app/src/main/java/org/schabi/newpipe/player/NotificationConstants.java b/app/src/main/java/org/schabi/newpipe/player/NotificationConstants.java new file mode 100644 index 000000000..599e18e65 --- /dev/null +++ b/app/src/main/java/org/schabi/newpipe/player/NotificationConstants.java @@ -0,0 +1,141 @@ +package org.schabi.newpipe.player; + +import android.content.Context; +import android.content.SharedPreferences; + +import androidx.annotation.DrawableRes; +import androidx.annotation.IntDef; +import androidx.annotation.NonNull; +import androidx.annotation.StringRes; + +import org.schabi.newpipe.R; + +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; +import java.util.SortedSet; +import java.util.TreeSet; + +public final class NotificationConstants { + + private NotificationConstants() { } + + + public static final int NOTHING = 0; + public static final int PREVIOUS = 1; + public static final int NEXT = 2; + public static final int REWIND = 3; + public static final int FORWARD = 4; + public static final int SMART_REWIND_PREVIOUS = 5; + public static final int SMART_FORWARD_NEXT = 6; + public static final int PLAY_PAUSE = 7; + public static final int PLAY_PAUSE_BUFFERING = 8; + public static final int REPEAT = 9; + public static final int SHUFFLE = 10; + public static final int CLOSE = 11; + + @Retention(RetentionPolicy.SOURCE) + @IntDef({NOTHING, PREVIOUS, NEXT, REWIND, FORWARD, SMART_REWIND_PREVIOUS, SMART_FORWARD_NEXT, + PLAY_PAUSE, PLAY_PAUSE_BUFFERING, REPEAT, SHUFFLE, CLOSE}) + public @interface Action { } + + @StringRes + public static final int[] ACTION_SUMMARIES = { + R.string.notification_action_nothing, + R.string.notification_action_previous, + R.string.notification_action_next, + R.string.notification_action_rewind, + R.string.notification_action_forward, + R.string.notification_action_smart_rewind_previous, + R.string.notification_action_smart_forward_next, + R.string.notification_action_play_pause, + R.string.notification_action_play_pause_buffering, + R.string.notification_action_repeat, + R.string.notification_action_shuffle, + R.string.close, + }; + + @DrawableRes + public static final int[] ACTION_ICONS = { + 0, + R.drawable.exo_icon_previous, + R.drawable.exo_icon_next, + R.drawable.exo_icon_rewind, + R.drawable.exo_icon_fastforward, + R.drawable.exo_icon_previous, + R.drawable.exo_icon_next, + R.drawable.ic_pause_white_24dp, + R.drawable.ic_hourglass_top_white_24dp, + R.drawable.exo_icon_repeat_all, + R.drawable.exo_icon_shuffle_on, + R.drawable.ic_close_white_24dp, + }; + + + @Action + public static final int[] SLOT_DEFAULTS = { + SMART_REWIND_PREVIOUS, + PLAY_PAUSE_BUFFERING, + SMART_FORWARD_NEXT, + REPEAT, + CLOSE, + }; + + @Action + public static final int[][] SLOT_ALLOWED_ACTIONS = { + new int[] {PREVIOUS, REWIND, SMART_REWIND_PREVIOUS}, + new int[] {REWIND, PLAY_PAUSE, PLAY_PAUSE_BUFFERING}, + new int[] {NEXT, FORWARD, SMART_FORWARD_NEXT, PLAY_PAUSE, PLAY_PAUSE_BUFFERING}, + new int[] {NOTHING, PREVIOUS, NEXT, REWIND, FORWARD, SMART_REWIND_PREVIOUS, + SMART_FORWARD_NEXT, REPEAT, SHUFFLE, CLOSE}, + new int[] {NOTHING, NEXT, FORWARD, SMART_FORWARD_NEXT, REPEAT, SHUFFLE, CLOSE}, + }; + + public static final int[] SLOT_PREF_KEYS = { + R.string.notification_slot_0_key, + R.string.notification_slot_1_key, + R.string.notification_slot_2_key, + R.string.notification_slot_3_key, + R.string.notification_slot_4_key, + }; + + + public static final Integer[] SLOT_COMPACT_DEFAULTS = {0, 1, 2}; + + public static final int[] SLOT_COMPACT_PREF_KEYS = { + R.string.notification_slot_compact_0_key, + R.string.notification_slot_compact_1_key, + R.string.notification_slot_compact_2_key, + }; + + /** + * @param context the context to use + * @param sharedPreferences the shared preferences to query values from + * @param slotCount remove indices >= than this value (set to {@code 5} to do nothing, or make + * it lower if there are slots with empty actions) + * @return a sorted list of the indices of the slots to use as compact slots + */ + public static List getCompactSlotsFromPreferences( + @NonNull final Context context, + final SharedPreferences sharedPreferences, + final int slotCount) { + final SortedSet compactSlots = new TreeSet<>(); + for (int i = 0; i < 3; i++) { + final int compactSlot = sharedPreferences.getInt( + context.getString(SLOT_COMPACT_PREF_KEYS[i]), Integer.MAX_VALUE); + + if (compactSlot == Integer.MAX_VALUE) { + // settings not yet populated, return default values + return new ArrayList<>(Arrays.asList(SLOT_COMPACT_DEFAULTS)); + } + + // a negative value (-1) is set when the user does not want a particular compact slot + if (compactSlot >= 0 && compactSlot < slotCount) { + compactSlots.add(compactSlot); + } + } + return new ArrayList<>(compactSlots); + } +} diff --git a/app/src/main/java/org/schabi/newpipe/player/NotificationUtil.java b/app/src/main/java/org/schabi/newpipe/player/NotificationUtil.java index 95c604472..2c5e882bb 100644 --- a/app/src/main/java/org/schabi/newpipe/player/NotificationUtil.java +++ b/app/src/main/java/org/schabi/newpipe/player/NotificationUtil.java @@ -20,6 +20,8 @@ import org.schabi.newpipe.MainActivity; import org.schabi.newpipe.R; import org.schabi.newpipe.util.NavigationHelper; +import java.util.List; + import static android.app.PendingIntent.FLAG_UPDATE_CURRENT; import static android.content.Context.NOTIFICATION_SERVICE; import static com.google.android.exoplayer2.Player.REPEAT_MODE_ALL; @@ -46,11 +48,8 @@ public final class NotificationUtil { @Nullable private static NotificationUtil instance = null; - private String notificationSlot0 = "smart_rewind_prev"; - private String notificationSlot1 = "play_pause_buffering"; - private String notificationSlot2 = "smart_forward_next"; - private String notificationSlot3 = "repeat"; - private String notificationSlot4 = "close"; + @NotificationConstants.Action + private int[] notificationSlots = NotificationConstants.SLOT_DEFAULTS.clone(); private NotificationManager notificationManager; private NotificationCompat.Builder notificationBuilder; @@ -91,35 +90,28 @@ public final class NotificationUtil { final NotificationCompat.Builder builder = new NotificationCompat.Builder(player.context, player.context.getString(R.string.notification_channel_id)); - final String compactView = player.sharedPreferences.getString(player.context.getString( - R.string.settings_notifications_compact_view_key), "0,1,2"); - int compactSlot0 = 0; - int compactSlot1 = 1; - int compactSlot2 = 2; - try { - if (compactView != null) { - final String[] parts = compactView.split(","); - compactSlot0 = Integer.parseInt(parts[0]); - compactSlot1 = Integer.parseInt(parts[1]); - compactSlot2 = Integer.parseInt(parts[2]); - if (compactSlot0 > 4) { - compactSlot0 = 0; - } - if (compactSlot1 > 4) { - compactSlot1 = 1; - } - if (compactSlot2 > 4) { - compactSlot2 = 2; - } - } - } catch (final Exception e) { - e.printStackTrace(); + initializeNotificationSlots(player); + + // count the number of real slots, to make sure compact slots indices are not out of bound + int nonNothingSlotCount = 5; + if (notificationSlots[3] == NotificationConstants.NOTHING) { + --nonNothingSlotCount; + } + if (notificationSlots[4] == NotificationConstants.NOTHING) { + --nonNothingSlotCount; } + // build the compact slot indices array (need code to convert from Integer... because Java) + final List compactSlotList = NotificationConstants.getCompactSlotsFromPreferences( + player.context, player.sharedPreferences, nonNothingSlotCount); + final int[] compactSlots = new int[compactSlotList.size()]; + for (int i = 0; i < compactSlotList.size(); i++) { + compactSlots[i] = compactSlotList.get(i); + } builder.setStyle(new androidx.media.app.NotificationCompat.MediaStyle() .setMediaSession(player.mediaSessionManager.getSessionToken()) - .setShowActionsInCompactView(compactSlot0, compactSlot1, compactSlot2)) + .setShowActionsInCompactView(compactSlots)) .setPriority(NotificationCompat.PRIORITY_HIGH) .setSmallIcon(R.drawable.ic_newpipe_triangle_white) .setVisibility(NotificationCompat.VISIBILITY_PUBLIC) @@ -131,7 +123,6 @@ public final class NotificationUtil { .setDeleteIntent(PendingIntent.getBroadcast(player.context, NOTIFICATION_ID, new Intent(ACTION_CLOSE), FLAG_UPDATE_CURRENT)); - initializeNotificationSlots(player); updateActions(builder, player); setLargeIcon(builder, player); @@ -171,22 +162,20 @@ public final class NotificationUtil { boolean hasSlotWithBuffering() { - return notificationSlot0.equals("play_pause_buffering") - || notificationSlot1.equals("play_pause_buffering") - || notificationSlot2.equals("play_pause_buffering") - || notificationSlot3.equals("play_pause_buffering") - || notificationSlot4.equals("play_pause_buffering"); + return notificationSlots[1] == NotificationConstants.PLAY_PAUSE_BUFFERING + || notificationSlots[2] == NotificationConstants.PLAY_PAUSE_BUFFERING; } - public void cancelNotification() { + void cancelNotification() { try { if (notificationManager != null) { notificationManager.cancel(NOTIFICATION_ID); - notificationManager = null; } } catch (final Exception e) { Log.e(TAG, "Could not cancel notification", e); } + notificationManager = null; + notificationBuilder = null; } @@ -195,32 +184,25 @@ public final class NotificationUtil { ///////////////////////////////////////////////////// private void initializeNotificationSlots(final VideoPlayerImpl player) { - notificationSlot0 = player.sharedPreferences.getString( - player.context.getString(R.string.notification_action_0_key), notificationSlot0); - notificationSlot1 = player.sharedPreferences.getString( - player.context.getString(R.string.notification_action_1_key), notificationSlot1); - notificationSlot2 = player.sharedPreferences.getString( - player.context.getString(R.string.notification_action_2_key), notificationSlot2); - notificationSlot3 = player.sharedPreferences.getString( - player.context.getString(R.string.notification_action_3_key), notificationSlot3); - notificationSlot4 = player.sharedPreferences.getString( - player.context.getString(R.string.notification_action_4_key), notificationSlot4); + for (int i = 0; i < 5; ++i) { + notificationSlots[i] = player.sharedPreferences.getInt( + player.context.getString(NotificationConstants.SLOT_PREF_KEYS[i]), + NotificationConstants.SLOT_DEFAULTS[i]); + } } @SuppressLint("RestrictedApi") private void updateActions(final NotificationCompat.Builder builder, final VideoPlayerImpl player) { builder.mActions.clear(); - addAction(builder, player, notificationSlot0); - addAction(builder, player, notificationSlot1); - addAction(builder, player, notificationSlot2); - addAction(builder, player, notificationSlot3); - addAction(builder, player, notificationSlot4); + for (int i = 0; i < 5; ++i) { + addAction(builder, player, notificationSlots[i]); + } } private void addAction(final NotificationCompat.Builder builder, final VideoPlayerImpl player, - final String slot) { + @NotificationConstants.Action final int slot) { final NotificationCompat.Action action = getAction(player, slot); if (action != null) { builder.addAction(action); @@ -228,23 +210,42 @@ public final class NotificationUtil { } @Nullable - private NotificationCompat.Action getAction(final VideoPlayerImpl player, - final String slot) { - switch (slot) { - case "play_pause_buffering": - if (player.getCurrentState() == BasePlayer.STATE_PREFLIGHT - || player.getCurrentState() == BasePlayer.STATE_BLOCKED - || player.getCurrentState() == BasePlayer.STATE_BUFFERING) { - return getAction(player, R.drawable.ic_hourglass_top_white_24dp, - "Buffering", ACTION_BUFFERING); + private NotificationCompat.Action getAction( + final VideoPlayerImpl player, + @NotificationConstants.Action final int selectedAction) { + final int baseActionIcon = NotificationConstants.ACTION_ICONS[selectedAction]; + switch (selectedAction) { + case NotificationConstants.PREVIOUS: + return getAction(player, baseActionIcon, "Previous", ACTION_PLAY_PREVIOUS); + + case NotificationConstants.NEXT: + return getAction(player, baseActionIcon, "Next", ACTION_PLAY_NEXT); + + case NotificationConstants.REWIND: + return getAction(player, baseActionIcon, "Rewind", ACTION_FAST_REWIND); + + case NotificationConstants.FORWARD: + return getAction(player, baseActionIcon, "Forward", ACTION_FAST_FORWARD); + + case NotificationConstants.SMART_REWIND_PREVIOUS: + if (player.playQueue != null && player.playQueue.size() > 1) { + return getAction(player, R.drawable.exo_notification_previous, + "Previous", ACTION_PLAY_PREVIOUS); } else { - return getAction(player, - player.isPlaying() ? R.drawable.exo_notification_pause - : R.drawable.exo_notification_play, - player.isPlaying() ? "Pause" : "Play", - ACTION_PLAY_PAUSE); + return getAction(player, R.drawable.exo_controls_rewind, + "Rewind", ACTION_FAST_REWIND); } - case "play_pause": + + case NotificationConstants.SMART_FORWARD_NEXT: + if (player.playQueue != null && player.playQueue.size() > 1) { + return getAction(player, R.drawable.exo_notification_next, + "Next", ACTION_PLAY_NEXT); + } else { + return getAction(player, R.drawable.exo_controls_fastforward, + "Forward", ACTION_FAST_FORWARD); + } + + case NotificationConstants.PLAY_PAUSE: final boolean pauseOrPlay = player.isPlaying() || player.getCurrentState() == BasePlayer.STATE_PREFLIGHT || player.getCurrentState() == BasePlayer.STATE_BLOCKED @@ -254,48 +255,38 @@ public final class NotificationUtil { : R.drawable.exo_notification_play, pauseOrPlay ? "Pause" : "Play", ACTION_PLAY_PAUSE); - case "rewind": - return getAction(player, R.drawable.exo_controls_rewind, - "Rewind", ACTION_FAST_REWIND); - case "smart_rewind_prev": - if (player.playQueue != null && player.playQueue.size() > 1) { - return getAction(player, R.drawable.exo_notification_previous, - "Prev", ACTION_PLAY_PREVIOUS); + + case NotificationConstants.PLAY_PAUSE_BUFFERING: + if (player.getCurrentState() == BasePlayer.STATE_PREFLIGHT + || player.getCurrentState() == BasePlayer.STATE_BLOCKED + || player.getCurrentState() == BasePlayer.STATE_BUFFERING) { + return getAction(player, R.drawable.ic_hourglass_top_white_24dp_png, + "Buffering", ACTION_BUFFERING); } else { - return getAction(player, R.drawable.exo_controls_rewind, - "Rewind", ACTION_FAST_REWIND); + return getAction(player, + player.isPlaying() ? R.drawable.exo_notification_pause + : R.drawable.exo_notification_play, + player.isPlaying() ? "Pause" : "Play", + ACTION_PLAY_PAUSE); } - case "forward": - return getAction(player, R.drawable.exo_controls_fastforward, - "Forward", ACTION_FAST_FORWARD); - case "smart_forward_next": - if (player.playQueue != null && player.playQueue.size() > 1) { - return getAction(player, R.drawable.exo_notification_next, - "Next", ACTION_PLAY_NEXT); - } else { - return getAction(player, R.drawable.exo_controls_fastforward, - "Forward", ACTION_FAST_FORWARD); - } - case "next": - return getAction(player, R.drawable.exo_notification_next, - "Next", ACTION_PLAY_NEXT); - case "prev": - return getAction(player, R.drawable.exo_notification_previous, - "Prev", ACTION_PLAY_PREVIOUS); - case "repeat": + + case NotificationConstants.REPEAT: return getAction(player, getRepeatModeDrawable(player.getRepeatMode()), getRepeatModeTitle(player.getRepeatMode()), ACTION_REPEAT); - case "shuffle": + + case NotificationConstants.SHUFFLE: final boolean shuffled = player.playQueue != null && player.playQueue.isShuffled(); return getAction(player, shuffled ? R.drawable.exo_controls_shuffle_on : R.drawable.exo_controls_shuffle_off, shuffled ? "ShuffleOn" : "ShuffleOff", ACTION_SHUFFLE); - case "close": - return getAction(player, R.drawable.ic_close_white_24dp, + + case NotificationConstants.CLOSE: + return getAction(player, R.drawable.ic_close_white_24dp_png, "Close", ACTION_CLOSE); - case "n/a": + + case NotificationConstants.NOTHING: default: // do nothing return null; diff --git a/app/src/main/java/org/schabi/newpipe/player/VideoPlayerImpl.java b/app/src/main/java/org/schabi/newpipe/player/VideoPlayerImpl.java index 024be26dc..c1171efb7 100644 --- a/app/src/main/java/org/schabi/newpipe/player/VideoPlayerImpl.java +++ b/app/src/main/java/org/schabi/newpipe/player/VideoPlayerImpl.java @@ -112,6 +112,7 @@ import static org.schabi.newpipe.player.MainPlayer.ACTION_OPEN_CONTROLS; import static org.schabi.newpipe.player.MainPlayer.ACTION_PLAY_NEXT; import static org.schabi.newpipe.player.MainPlayer.ACTION_PLAY_PAUSE; import static org.schabi.newpipe.player.MainPlayer.ACTION_PLAY_PREVIOUS; +import static org.schabi.newpipe.player.MainPlayer.ACTION_RECREATE_NOTIFICATION; import static org.schabi.newpipe.player.MainPlayer.ACTION_REPEAT; import static org.schabi.newpipe.player.MainPlayer.ACTION_SHUFFLE; import static org.schabi.newpipe.player.helper.PlayerHelper.MinimizeMode.MINIMIZE_ON_EXIT_MODE_BACKGROUND; @@ -1179,6 +1180,7 @@ public class VideoPlayerImpl extends VideoPlayer intentFilter.addAction(ACTION_FAST_FORWARD); intentFilter.addAction(ACTION_BUFFERING); intentFilter.addAction(ACTION_SHUFFLE); + intentFilter.addAction(ACTION_RECREATE_NOTIFICATION); intentFilter.addAction(VideoDetailFragment.ACTION_VIDEO_FRAGMENT_RESUMED); intentFilter.addAction(VideoDetailFragment.ACTION_VIDEO_FRAGMENT_STOPPED); @@ -1236,6 +1238,9 @@ public class VideoPlayerImpl extends VideoPlayer case ACTION_SHUFFLE: onShuffleClicked(); break; + case ACTION_RECREATE_NOTIFICATION: + resetNotification(true); + break; case Intent.ACTION_HEADSET_PLUG: //FIXME /*notificationManager.cancel(NOTIFICATION_ID); mediaSessionManager.dispose(); diff --git a/app/src/main/java/org/schabi/newpipe/settings/NotificationSettingsFragment.java b/app/src/main/java/org/schabi/newpipe/settings/NotificationSettingsFragment.java new file mode 100644 index 000000000..f4bbc96a7 --- /dev/null +++ b/app/src/main/java/org/schabi/newpipe/settings/NotificationSettingsFragment.java @@ -0,0 +1,271 @@ +package org.schabi.newpipe.settings; + +import android.content.Intent; +import android.content.SharedPreferences; +import android.graphics.PorterDuff; +import android.graphics.drawable.Drawable; +import android.os.Build; +import android.os.Bundle; +import android.preference.PreferenceManager; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import android.widget.CheckBox; +import android.widget.ImageView; +import android.widget.LinearLayout; +import android.widget.RadioButton; +import android.widget.RadioGroup; +import android.widget.Switch; +import android.widget.TextView; +import android.widget.Toast; + +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; +import androidx.appcompat.app.AlertDialog; +import androidx.appcompat.content.res.AppCompatResources; +import androidx.fragment.app.Fragment; + +import org.schabi.newpipe.R; +import org.schabi.newpipe.player.MainPlayer; +import org.schabi.newpipe.player.NotificationConstants; +import org.schabi.newpipe.util.DeviceUtils; +import org.schabi.newpipe.util.ThemeHelper; +import org.schabi.newpipe.views.FocusOverlayView; + +import java.util.List; + +public class NotificationSettingsFragment extends Fragment { + + private Switch scaleSwitch; + private NotificationSlot[] notificationSlots; + + private SharedPreferences pref; + private List compactSlots; + private String scaleKey; + + //////////////////////////////////////////////////////////////////////////// + // Lifecycle + //////////////////////////////////////////////////////////////////////////// + + @Override + public void onCreate(@Nullable final Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + pref = PreferenceManager.getDefaultSharedPreferences(requireContext()); + scaleKey = getString(R.string.scale_to_square_image_in_notifications_key); + } + + @Override + public View onCreateView(@NonNull final LayoutInflater inflater, + final ViewGroup container, + @Nullable final Bundle savedInstanceState) { + return inflater.inflate(R.layout.settings_notification, container, false); + } + + @Override + public void onViewCreated(@NonNull final View rootView, + @Nullable final Bundle savedInstanceState) { + super.onViewCreated(rootView, savedInstanceState); + + setupScaleSwitch(rootView); + setupActions(rootView); + } + + @Override + public void onResume() { + super.onResume(); + ThemeHelper.setTitleToAppCompatActivity(getActivity(), + getString(R.string.settings_category_notification_title)); + } + + @Override + public void onPause() { + super.onPause(); + saveChanges(); + requireContext().sendBroadcast(new Intent(MainPlayer.ACTION_RECREATE_NOTIFICATION)); + } + + + //////////////////////////////////////////////////////////////////////////// + // Setup + //////////////////////////////////////////////////////////////////////////// + + private void setupScaleSwitch(@NonNull final View view) { + scaleSwitch = view.findViewById(R.id.notificationScaleSwitch); + scaleSwitch.setChecked(pref.getBoolean(scaleKey, false)); + + view.findViewById(R.id.notificationScaleSwitchClickableArea) + .setOnClickListener(v -> scaleSwitch.toggle()); + } + + private void setupActions(@NonNull final View view) { + compactSlots = + NotificationConstants.getCompactSlotsFromPreferences(requireContext(), pref, 5); + notificationSlots = new NotificationSlot[5]; + for (int i = 0; i < 5; i++) { + notificationSlots[i] = new NotificationSlot(i, view); + } + } + + + //////////////////////////////////////////////////////////////////////////// + // Saving + //////////////////////////////////////////////////////////////////////////// + + private void saveChanges() { + final SharedPreferences.Editor editor = pref.edit(); + editor.putBoolean(scaleKey, scaleSwitch.isChecked()); + + for (int i = 0; i < 3; i++) { + editor.putInt(getString(NotificationConstants.SLOT_COMPACT_PREF_KEYS[i]), + (i < compactSlots.size() ? compactSlots.get(i) : -1)); + } + + for (int i = 0; i < 5; i++) { + editor.putInt(getString(NotificationConstants.SLOT_PREF_KEYS[i]), + notificationSlots[i].selectedAction); + } + + editor.apply(); + } + + + //////////////////////////////////////////////////////////////////////////// + // Notification action + //////////////////////////////////////////////////////////////////////////// + + private static final int[] SLOT_ITEMS = { + R.id.notificationAction0, + R.id.notificationAction1, + R.id.notificationAction2, + R.id.notificationAction3, + R.id.notificationAction4, + }; + + private static final int[] SLOT_TITLES = { + R.string.notification_action_0_title, + R.string.notification_action_1_title, + R.string.notification_action_2_title, + R.string.notification_action_3_title, + R.string.notification_action_4_title, + }; + + private class NotificationSlot { + + final int i; + @NotificationConstants.Action int selectedAction; + + ImageView icon; + TextView summary; + + NotificationSlot(final int actionIndex, final View parentView) { + this.i = actionIndex; + + final View view = parentView.findViewById(SLOT_ITEMS[i]); + setupSelectedAction(view); + setupTitle(view); + setupCheckbox(view); + } + + void setupTitle(final View view) { + ((TextView) view.findViewById(R.id.notificationActionTitle)) + .setText(SLOT_TITLES[i]); + view.findViewById(R.id.notificationActionClickableArea).setOnClickListener( + v -> openActionChooserDialog()); + } + + void setupCheckbox(final View view) { + final CheckBox compactSlotCheckBox = view.findViewById(R.id.notificationActionCheckBox); + compactSlotCheckBox.setChecked(compactSlots.contains(i)); + view.findViewById(R.id.notificationActionCheckBoxClickableArea).setOnClickListener( + v -> { + if (compactSlotCheckBox.isChecked()) { + compactSlots.remove((Integer) i); + } else if (compactSlots.size() < 3) { + compactSlots.add(i); + } else { + Toast.makeText(requireContext(), + R.string.notification_actions_at_most_three, + Toast.LENGTH_SHORT).show(); + return; + } + + compactSlotCheckBox.toggle(); + }); + } + + void setupSelectedAction(final View view) { + icon = view.findViewById(R.id.notificationActionIcon); + summary = view.findViewById(R.id.notificationActionSummary); + selectedAction = pref.getInt(getString(NotificationConstants.SLOT_PREF_KEYS[i]), + NotificationConstants.SLOT_DEFAULTS[i]); + updateInfo(); + } + + void updateInfo() { + if (NotificationConstants.ACTION_ICONS[selectedAction] == 0) { + icon.setImageDrawable(null); + } else { + icon.setImageDrawable(AppCompatResources.getDrawable(requireContext(), + NotificationConstants.ACTION_ICONS[selectedAction])); + } + + summary.setText(NotificationConstants.ACTION_SUMMARIES[selectedAction]); + } + + void openActionChooserDialog() { + final LayoutInflater inflater = LayoutInflater.from(requireContext()); + final LinearLayout rootLayout = (LinearLayout) inflater.inflate( + R.layout.single_choice_dialog_view, null, false); + final RadioGroup radioGroup = rootLayout.findViewById(android.R.id.list); + + final AlertDialog alertDialog = new AlertDialog.Builder(requireContext()) + .setTitle(SLOT_TITLES[i]) + .setView(radioGroup) + .setCancelable(true) + .create(); + + final View.OnClickListener radioButtonsClickListener = v -> { + final int id = ((RadioButton) v).getId(); + selectedAction = NotificationConstants.SLOT_ALLOWED_ACTIONS[i][id]; + updateInfo(); + alertDialog.dismiss(); + }; + + for (int id = 0; id < NotificationConstants.SLOT_ALLOWED_ACTIONS[i].length; ++id) { + final int action = NotificationConstants.SLOT_ALLOWED_ACTIONS[i][id]; + final RadioButton radioButton + = (RadioButton) inflater.inflate(R.layout.list_radio_icon_item, null); + + // if present set action icon with correct color + if (NotificationConstants.ACTION_ICONS[action] != 0) { + final Drawable drawable = AppCompatResources.getDrawable(requireContext(), + NotificationConstants.ACTION_ICONS[action]); + if (drawable != null) { + final int color = ThemeHelper.resolveColorFromAttr(requireContext(), + android.R.attr.textColorPrimary); + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { + drawable.setTint(color); + } else { + drawable.mutate().setColorFilter(color, PorterDuff.Mode.SRC_IN); + } + radioButton.setCompoundDrawablesWithIntrinsicBounds( + null, null, drawable, null); + } + } + + radioButton.setText(NotificationConstants.ACTION_SUMMARIES[action]); + radioButton.setChecked(action == selectedAction); + radioButton.setId(id); + radioButton.setLayoutParams(new RadioGroup.LayoutParams( + ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT)); + radioButton.setOnClickListener(radioButtonsClickListener); + radioGroup.addView(radioButton); + } + alertDialog.show(); + + if (DeviceUtils.isTv(requireContext())) { + FocusOverlayView.setupFocusObserver(alertDialog); + } + } + } +} diff --git a/app/src/main/res/drawable-hdpi/ic_close_white_24dp_png.png b/app/src/main/res/drawable-hdpi/ic_close_white_24dp_png.png new file mode 100644 index 0000000000000000000000000000000000000000..2f73a04b16de2d72f6dde7b999d52c196a3d77ed GIT binary patch literal 415 zcmV;Q0bu@#P))B%|VoRJ~51*73|4$uU7wV=LfQ}Z6z>*ua= zz!a=!$bizDY7D3=LCrcgQ_)sin3`_iNWwV%t4_3`c2fu2KEo#SHr)s=ll~i65tRL) z|JmoTsohM)ks)MLjmtidO||%D0_>BqNzgtyn}qC>w~5hB=56xY_Xrr5O-}nB0pzo( zk?6iq7;iU8bYCdUzugqueVom7b`!VzVr}Z|roP=LWmB(i>gqm8o3em23Nia|(N3b9 zJoarlK<~&`Y&SXV(=QGs2WU!AyV!0r?Az1Z%s9Phrb+Xx`32$efF+z^MPdK|002ov JPDHLkV1i~e!B_wQ literal 0 HcmV?d00001 diff --git a/app/src/main/res/drawable-hdpi/ic_hourglass_top_white_24dp.png b/app/src/main/res/drawable-hdpi/ic_hourglass_top_white_24dp_png.png similarity index 100% rename from app/src/main/res/drawable-hdpi/ic_hourglass_top_white_24dp.png rename to app/src/main/res/drawable-hdpi/ic_hourglass_top_white_24dp_png.png diff --git a/app/src/main/res/drawable-mdpi/ic_close_white_24dp_png.png b/app/src/main/res/drawable-mdpi/ic_close_white_24dp_png.png new file mode 100644 index 0000000000000000000000000000000000000000..d8aa2f7c4728f3b856ceb84edeb60832e79fcf23 GIT binary patch literal 285 zcmV+&0pk9NP)8bGvk?rMKCB{yZl|vD)G+ z##jL@;0!SyI09S7`2@Uy3qzvGufR)47=iTNaY121+M& z#z&Ih)F;r%lLUL11@0g20P(mp)0?=xB5iB0Yp6QBD7W zx1`g!JG;FZJ>=ZD}aQdPT4cF2JX< z=7`eifcqnhf_N9pnt~GwB5(NSrTLa(UeHeT+085IG!TC^rJX1ntPyJ7yrBO*wzP>c zum^56LColzs3d%_y%pwVP@#*aCi8b6+$biZ{MGh}g*rdcm~T;96#^H+gSIFLbtkla zLR06}H!sZ>U5^(pJ|>qJx_21&<3xz z=J}XDA+Is(906Q`A^5O0&ujX`obFV!Z literal 0 HcmV?d00001 diff --git a/app/src/main/res/drawable-xhdpi/ic_hourglass_top_white_24dp.png b/app/src/main/res/drawable-xhdpi/ic_hourglass_top_white_24dp_png.png similarity index 100% rename from app/src/main/res/drawable-xhdpi/ic_hourglass_top_white_24dp.png rename to app/src/main/res/drawable-xhdpi/ic_hourglass_top_white_24dp_png.png diff --git a/app/src/main/res/drawable-xxhdpi/ic_close_white_24dp_png.png b/app/src/main/res/drawable-xxhdpi/ic_close_white_24dp_png.png new file mode 100644 index 0000000000000000000000000000000000000000..2cd1a88659f07386e028e70877802dd38ecb7ecb GIT binary patch literal 1034 zcmV+l1oiugP)o$Qc;3T*Sj)DV%>Kg$kz!h*T4RN}_C*T|K3-}tG2D`z#DGJj87Qi`h3H-#r zAAxyWMYK?ykKn%hAAi6-@G1B(MS+UoGw=YcvbG=Kdn1yqB8*cODb5LtsDQt~E%2og z$)=O&oFbjP4W5D*tnG**%~@$TI_JB49S#fIqLaEU3RIwTw)xMx@TkwU+lq~1=D`iu z8xEbcN2d)~sAq)kIH+;XB`(-*W+qM85a>Dhj@CW%5UIkM^cEZk+rT>s)X{1NFE|6P zQv@$@PAQ%dam1FTAAqmGZ*F~@u{hIi{Rz}C$hN9n8OXKbRM>Xrx`NHSMGrUxE>k2g zC;bJ_dCd#37i^E=y*t4^umqOb)=nMgY;$m%0p5|uZFPuFI`VOnDfBCy)EmQl_R$eL zbch$KY%6nJG0hWe58KVmqz^vD9#JIYr2Z%~i8E)A&N1Q~d(0e%@3+pGQ%J=*bq4o> zkBh2w(lVXY7U4bebVS+bR_^e%8EXSM#0ThNyM6W%>YPH2hdBc9RzAZI@AwSlGDXbi zq`?eeb5iAbW0yjB4em1@0dCB0HQDO&R_-;BkJ)x5wqdK}r2m*s+Vyc#pzKyBTX~(k zc6eQ179NG%qex3W?dF@^ZpcHEIylf>byUEQ~Lb99OY$YVS$1k6Es_e&Th9spfK4gbauN91365#3YFcm zEKH=mm6W}k4S^!>tt9N-k`$)ly;YifHyZ-Qwzo=S@0Rq;iFI#fbMIzDpv3l8Hui35 zXRC(yR!Q#N(#}?~?5&d6yGhAbvF@$n+`CE1Rd7Xh0#ikSu1z(er2guT@b+3kd1dN)6t zn6!0b9_E+H4<+rb>SVWle)-+}e4@oh5zXLzinPXdTa~c4s>yB}{3k9_95c|HY!%W> zC(UvuO-b5Yad6MmIn(?BPE$^yP$(1%g+ifFC={8%Keh)tWYG$(asU7T07*qoM6N<$ Ef)k_jzyJUM literal 0 HcmV?d00001 diff --git a/app/src/main/res/drawable-xxhdpi/ic_hourglass_top_white_24dp.png b/app/src/main/res/drawable-xxhdpi/ic_hourglass_top_white_24dp_png.png similarity index 100% rename from app/src/main/res/drawable-xxhdpi/ic_hourglass_top_white_24dp.png rename to app/src/main/res/drawable-xxhdpi/ic_hourglass_top_white_24dp_png.png diff --git a/app/src/main/res/drawable-xxxhdpi/ic_close_white_24dp_png.png b/app/src/main/res/drawable-xxxhdpi/ic_close_white_24dp_png.png new file mode 100644 index 0000000000000000000000000000000000000000..4d278c5bfba91b997502367af09ec686afaf7584 GIT binary patch literal 2068 zcmV+v2elZDN|DP|FjR$7bbg?m#k)*mJjK_RVG z3=%PQgJxK(7)4QUd{bG0f+Mgu1*N5_znvSOyFD}Y_gqbX_owFz-#6v+yXQXVIro0g zdCq+T0fj=LP$(1%g+ifFC=?2XLZMJ76befOgTWYKtT0=6T399g7|x2&drA~;fCq(# zg-g`|>VS79-eI0_4-?-eY!x=buY?)GIT14PX~HaFiSPz&5k3?i;om>;i?OlLnfw~z z?cjfS0n3Pl^aydlQda$b;T!1U4`HR_1iu)&5}so69~;KLg1-nWg!#e*VZ2W#K1rA& z+{`3j5cWbB%{bu*j#?USqif*b!J*MbB-9WISw3~Z=dAootoq(z?&%@#gu~%Bx*E0* zW9%y&;H;?C!W>~Vj0&^;QO0}Bnfy({CJP6&@M1m~ZU^jy&B4&qbQL=Cb)loV!yq-CoTXTJ2lim& zP!r$FV{|`KG;zG`9`1(L6A5Q6BB9@qsNWI^Y2$3~5>{}V#!doF6@EV>G9zdcxD=J}(?MxP?3QL8@g>^h~hI;I{|JQ^%+Kl{63-}RY*a9Nq z`=A|MiTW#%uzZZ|TgM9i-9qW~8!LYk<5K*dMSdvUCfqLUguNjo>PvEjwN8p}WY7ECL)M_ZC8SlxK*@n{TuuwXE{LLL> zTuh`@64e1d$S{+jBTd7U+^;98GTvzT$Ifr$vYvH7g7 z?}X3c8w-hgo|46NiBfXZ%LF@iOhVkeXGD%Lz>?mP)CL22@a!mmhGMKHIeY!2psSRb>yu2RXUp^b3iWbAJriw=0LpW zC4G`SAxmd-WDZ!x3O-{YH3yTZM@iO}=xlm>2e{AcLZ0CbA*AL|67?Jzvs1R12BUPA zhj+kKL$TbqD5}{M@$MQ$yf~d@b$~A?K7|amz{px{s+xTvN)UZKj#{9zsk6*>dvh{5 zAe~je)v~JD>mfRNjVfv$kuX9$Zh7g0wAM(gd+bu)%eY0Oxb9B+j=V_J14P2YNSB&!Z+$WS_H~w0)9vLiB2P#i zp$(Zhu#678N0t)x3}0{N8I{?nNOM4pp;+#CP&ysPxY_T?mPA7#J@=rHt{Ms{S{YP95&qcMSmB^ua$8S;jFNq2x%ym8y2l2uF`pCj7tc!{Yi#G>a^^* zc!6kmtB}+IliUGKu){*>G#RIkxaYL_;mkPqaFFes@^Z_<5v|mzs>1C6_vEXm77n=N zo;u=FCAW=8xM|^lHckjW9d4s@p(D{AkhBbT%vU86HN~$-zHrpe0wn6$AtdT!&PT06 zJYaqn3?eo6v-16U@b$a*w3!$d{IH88eQHOEr zNeOvET7)=YG5w_FMrF30!)Z@3`FZYp%r8byArf+VCo~yKCn7gC=o@ksQZr4!Dba8$F0000 + + diff --git a/app/src/main/res/layout/list_radio_icon_item.xml b/app/src/main/res/layout/list_radio_icon_item.xml index 947747c16..3446e351c 100644 --- a/app/src/main/res/layout/list_radio_icon_item.xml +++ b/app/src/main/res/layout/list_radio_icon_item.xml @@ -10,10 +10,8 @@ android:maxLines="2" android:minHeight="?attr/listPreferredItemHeightSmall" android:paddingEnd="?attr/listPreferredItemPaddingRight" - android:paddingLeft="?attr/listPreferredItemPaddingLeft" - android:paddingRight="?attr/listPreferredItemPaddingRight" android:paddingStart="?attr/listPreferredItemPaddingLeft" android:background="?attr/checked_selector" android:textColor="?attr/textColorAlertDialogListItem" - tools:drawableLeft="?attr/ic_play" + tools:drawableLeft="?attr/ic_play_arrow" tools:text="Lorem ipsum dolor sit amet" /> diff --git a/app/src/main/res/layout/settings_notification.xml b/app/src/main/res/layout/settings_notification.xml new file mode 100644 index 000000000..61b7f1aad --- /dev/null +++ b/app/src/main/res/layout/settings_notification.xml @@ -0,0 +1,135 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/settings_notification_action.xml b/app/src/main/res/layout/settings_notification_action.xml new file mode 100644 index 000000000..8ef2d8ab2 --- /dev/null +++ b/app/src/main/res/layout/settings_notification_action.xml @@ -0,0 +1,88 @@ + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/preferred_player_dialog_view.xml b/app/src/main/res/layout/single_choice_dialog_view.xml similarity index 100% rename from app/src/main/res/layout/preferred_player_dialog_view.xml rename to app/src/main/res/layout/single_choice_dialog_view.xml diff --git a/app/src/main/res/values/settings_keys.xml b/app/src/main/res/values/settings_keys.xml index 52b43002d..0aa1435c1 100644 --- a/app/src/main/res/values/settings_keys.xml +++ b/app/src/main/res/values/settings_keys.xml @@ -118,108 +118,15 @@ 0,1,2 scale_to_square_image_in_notifications - prev - next - rewind - forward - smart_rewind_prev - smart_forward_next - play_pause_buffering - play_pause - repeat - shuffle - close - n/a + notification_slot_0_key + notification_slot_1_key + notification_slot_2_key + notification_slot_3_key + notification_slot_4_key - notification_action_0_key - @string/notification_action_smart_rewind_prev_key - - @string/notification_action_smart_rewind_prev_value - @string/notification_action_prev_value - @string/notification_action_rewind_value - - - @string/notification_action_smart_rewind_prev_key - @string/notification_action_prev_key - @string/notification_action_rewind_key - - - notification_action_1_key - @string/notification_action_play_pause_buffering_key - - @string/notification_action_play_pause_buffering_value - @string/notification_action_play_pause_value - @string/notification_action_rewind_value - - - @string/notification_action_play_pause_buffering_key - @string/notification_action_play_pause_key - @string/notification_action_rewind_key - - - - notification_action_2_key - @string/notification_action_smart_forward_next_key - - @string/notification_action_smart_forward_next_value - @string/notification_action_forward_value - @string/notification_action_next_value - @string/notification_action_play_pause_buffering_value - @string/notification_action_play_pause_value - - - @string/notification_action_smart_forward_next_key - @string/notification_action_forward_key - @string/notification_action_next_key - @string/notification_action_play_pause_buffering_key - @string/notification_action_play_pause_key - - - notification_action_3_key - @string/notification_action_repeat_key - - @string/notification_action_repeat_value - @string/notification_action_shuffle_value - @string/notification_action_prev_value - @string/notification_action_forward_value - @string/notification_action_smart_forward_next_value - @string/notification_action_rewind_value - @string/notification_action_smart_rewind_prev_value - @string/notification_action_close_value - @string/notification_action_n_a_value - - - @string/notification_action_repeat_key - @string/notification_action_shuffle_key - @string/notification_action_prev_key - @string/notification_action_forward_key - @string/notification_action_smart_forward_next_key - @string/notification_action_rewind_key - @string/notification_action_smart_rewind_prev_key - @string/notification_action_close_key - @string/notification_action_n_a_key - - - notification_action_4_key - @string/notification_action_close_key - - @string/notification_action_close_value - @string/notification_action_repeat_value - @string/notification_action_shuffle_value - @string/notification_action_next_value - @string/notification_action_forward_value - @string/notification_action_smart_forward_next_value - @string/notification_action_n_a_value - - - @string/notification_action_close_key - @string/notification_action_repeat_key - @string/notification_action_shuffle_key - @string/notification_action_next_key - @string/notification_action_forward_key - @string/notification_action_smart_forward_next_key - @string/notification_action_n_a_key - + notification_slot_compact_0_key + notification_slot_compact_1_key + notification_slot_compact_2_key video_mp4 video_webm diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 45d806728..21c734741 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -66,21 +66,20 @@ Third action button Fourth action button Fifth action button - Notification compact view - Notification slots to show in compact view - - Previous - Next - Rewind - Forward - Rewind / Previous - Forward / Next - Play / Pause / Buffering - Play / Pause - Repeat - Shuffle - Close - Nothing + Edit each notification action below by tapping on it.\nSelect up to three of them to be shown in the compact notification by using the checkboxes on the right. + You can select at most three actions to show in the compact notification! + + Previous + Next + Rewind + Forward + Rewind / Previous + Forward / Next + Play / Pause / Buffering + Play / Pause + Repeat + Shuffle + Nothing Audio Default audio format @@ -154,7 +153,7 @@ Other Debug Updates - Notifications + Notification Playing in background Playing in popup mode Queued on background player diff --git a/app/src/main/res/xml/appearance_settings.xml b/app/src/main/res/xml/appearance_settings.xml index 7b25a4ab5..e45641f91 100644 --- a/app/src/main/res/xml/appearance_settings.xml +++ b/app/src/main/res/xml/appearance_settings.xml @@ -34,70 +34,4 @@ android:title="@string/caption_setting_title" app:iconSpaceReserved="false" /> - - - - - - - - - - - - - - - - - - diff --git a/app/src/main/res/xml/main_settings.xml b/app/src/main/res/xml/main_settings.xml index 604f3bb05..af093a757 100644 --- a/app/src/main/res/xml/main_settings.xml +++ b/app/src/main/res/xml/main_settings.xml @@ -35,6 +35,12 @@ android:icon="?attr/ic_language" android:title="@string/content"/> + +