55import android .content .Context ;
66import android .content .Intent ;
77import android .content .SharedPreferences ;
8- import android .content .res .ColorStateList ;
98import android .os .Build ;
109import android .util .AttributeSet ;
11- import android .view .LayoutInflater ;
1210import android .view .View ;
13- import android .view .ViewGroup ;
1411import android .widget .CheckBox ;
15- import android .widget .ImageView ;
16- import android .widget .RadioButton ;
17- import android .widget .RadioGroup ;
1812import android .widget .TextView ;
1913import android .widget .Toast ;
2014
2115import androidx .annotation .NonNull ;
22- import androidx .annotation .Nullable ;
23- import androidx .appcompat .app .AlertDialog ;
24- import androidx .appcompat .content .res .AppCompatResources ;
25- import androidx .core .widget .TextViewCompat ;
2616import androidx .preference .Preference ;
2717import androidx .preference .PreferenceViewHolder ;
2818
2919import org .schabi .newpipe .App ;
3020import org .schabi .newpipe .R ;
31- import org .schabi .newpipe .databinding .ListRadioIconItemBinding ;
32- import org .schabi .newpipe .databinding .SingleChoiceDialogViewBinding ;
3321import org .schabi .newpipe .player .notification .NotificationConstants ;
34- import org .schabi .newpipe .util .DeviceUtils ;
35- import org .schabi .newpipe .util .ThemeHelper ;
36- import org .schabi .newpipe .views .FocusOverlayView ;
3722
3823import java .util .List ;
39- import java .util .Objects ;
4024import java .util .stream .IntStream ;
4125
4226public class NotificationActionsPreference extends Preference {
@@ -47,8 +31,9 @@ public NotificationActionsPreference(final Context context, final AttributeSet a
4731 }
4832
4933
50- @ Nullable private NotificationSlot [] notificationSlots = null ;
51- @ Nullable private List <Integer > compactSlots = null ;
34+ private NotificationSlot [] notificationSlots ;
35+ private List <Integer > compactSlots ;
36+
5237
5338 ////////////////////////////////////////////////////////////////////////////
5439 // Lifecycle
@@ -85,10 +70,26 @@ private void setupActions(@NonNull final View view) {
8570 compactSlots = NotificationConstants .getCompactSlotsFromPreferences (getContext (),
8671 getSharedPreferences (), 5 );
8772 notificationSlots = IntStream .range (0 , 5 )
88- .mapToObj (i -> new NotificationSlot (i , view ))
73+ .mapToObj (i -> new NotificationSlot (getContext (), getSharedPreferences (), i , view ,
74+ compactSlots .contains (i ), this ::onToggleCompactSlot ))
8975 .toArray (NotificationSlot []::new );
9076 }
9177
78+ private void onToggleCompactSlot (final int i , final CheckBox checkBox ) {
79+ if (checkBox .isChecked ()) {
80+ compactSlots .remove ((Integer ) i );
81+ } else if (compactSlots .size () < 3 ) {
82+ compactSlots .add (i );
83+ } else {
84+ Toast .makeText (getContext (),
85+ R .string .notification_actions_at_most_three ,
86+ Toast .LENGTH_SHORT ).show ();
87+ return ;
88+ }
89+
90+ checkBox .toggle ();
91+ }
92+
9293
9394 ////////////////////////////////////////////////////////////////////////////
9495 // Saving
@@ -106,156 +107,10 @@ private void saveChanges() {
106107
107108 for (int i = 0 ; i < 5 ; i ++) {
108109 editor .putInt (getContext ().getString (NotificationConstants .SLOT_PREF_KEYS [i ]),
109- notificationSlots [i ].selectedAction );
110+ notificationSlots [i ].getSelectedAction () );
110111 }
111112
112113 editor .apply ();
113114 }
114115 }
115-
116-
117- ////////////////////////////////////////////////////////////////////////////
118- // Notification action
119- ////////////////////////////////////////////////////////////////////////////
120-
121- private static final int [] SLOT_ITEMS = {
122- R .id .notificationAction0 ,
123- R .id .notificationAction1 ,
124- R .id .notificationAction2 ,
125- R .id .notificationAction3 ,
126- R .id .notificationAction4 ,
127- };
128-
129- private static final int [] SLOT_TITLES = {
130- R .string .notification_action_0_title ,
131- R .string .notification_action_1_title ,
132- R .string .notification_action_2_title ,
133- R .string .notification_action_3_title ,
134- R .string .notification_action_4_title ,
135- };
136-
137- private class NotificationSlot {
138-
139- final int i ;
140- @ NotificationConstants .Action int selectedAction ;
141-
142- ImageView icon ;
143- TextView summary ;
144-
145- NotificationSlot (final int actionIndex , final View parentView ) {
146- this .i = actionIndex ;
147- selectedAction = Objects .requireNonNull (getSharedPreferences ()).getInt (
148- getContext ().getString (NotificationConstants .SLOT_PREF_KEYS [i ]),
149- NotificationConstants .SLOT_DEFAULTS [i ]);
150- final View view = parentView .findViewById (SLOT_ITEMS [i ]);
151-
152- // only show the last two notification slots on Android 13+
153- if (Build .VERSION .SDK_INT < Build .VERSION_CODES .TIRAMISU || i >= 3 ) {
154- setupSelectedAction (view );
155- setupTitle (view );
156- setupCheckbox (view );
157- } else {
158- view .setVisibility (View .GONE );
159- }
160- }
161-
162- void setupTitle (final View view ) {
163- ((TextView ) view .findViewById (R .id .notificationActionTitle ))
164- .setText (SLOT_TITLES [i ]);
165- view .findViewById (R .id .notificationActionClickableArea ).setOnClickListener (
166- v -> openActionChooserDialog ());
167- }
168-
169- void setupCheckbox (final View view ) {
170- final CheckBox compactSlotCheckBox = view .findViewById (R .id .notificationActionCheckBox );
171- if (Build .VERSION .SDK_INT >= Build .VERSION_CODES .TIRAMISU ) {
172- // there are no compact slots to customize on Android 33+
173- compactSlotCheckBox .setVisibility (View .GONE );
174- view .findViewById (R .id .notificationActionCheckBoxClickableArea )
175- .setVisibility (View .GONE );
176- return ;
177- }
178-
179- compactSlotCheckBox .setChecked (compactSlots .contains (i ));
180- view .findViewById (R .id .notificationActionCheckBoxClickableArea ).setOnClickListener (
181- v -> {
182- if (compactSlotCheckBox .isChecked ()) {
183- compactSlots .remove ((Integer ) i );
184- } else if (compactSlots .size () < 3 ) {
185- compactSlots .add (i );
186- } else {
187- Toast .makeText (getContext (),
188- R .string .notification_actions_at_most_three ,
189- Toast .LENGTH_SHORT ).show ();
190- return ;
191- }
192-
193- compactSlotCheckBox .toggle ();
194- });
195- }
196-
197- void setupSelectedAction (final View view ) {
198- icon = view .findViewById (R .id .notificationActionIcon );
199- summary = view .findViewById (R .id .notificationActionSummary );
200- updateInfo ();
201- }
202-
203- void updateInfo () {
204- if (NotificationConstants .ACTION_ICONS [selectedAction ] == 0 ) {
205- icon .setImageDrawable (null );
206- } else {
207- icon .setImageDrawable (AppCompatResources .getDrawable (getContext (),
208- NotificationConstants .ACTION_ICONS [selectedAction ]));
209- }
210-
211- summary .setText (NotificationConstants .getActionName (getContext (), selectedAction ));
212- }
213-
214- void openActionChooserDialog () {
215- final LayoutInflater inflater = LayoutInflater .from (getContext ());
216- final SingleChoiceDialogViewBinding binding =
217- SingleChoiceDialogViewBinding .inflate (inflater );
218-
219- final AlertDialog alertDialog = new AlertDialog .Builder (getContext ())
220- .setTitle (SLOT_TITLES [i ])
221- .setView (binding .getRoot ())
222- .setCancelable (true )
223- .create ();
224-
225- final View .OnClickListener radioButtonsClickListener = v -> {
226- selectedAction = NotificationConstants .SLOT_ALLOWED_ACTIONS [i ][v .getId ()];
227- updateInfo ();
228- alertDialog .dismiss ();
229- };
230-
231- for (int id = 0 ; id < NotificationConstants .SLOT_ALLOWED_ACTIONS [i ].length ; ++id ) {
232- final int action = NotificationConstants .SLOT_ALLOWED_ACTIONS [i ][id ];
233- final RadioButton radioButton = ListRadioIconItemBinding .inflate (inflater )
234- .getRoot ();
235-
236- // if present set action icon with correct color
237- final int iconId = NotificationConstants .ACTION_ICONS [action ];
238- if (iconId != 0 ) {
239- radioButton .setCompoundDrawablesRelativeWithIntrinsicBounds (0 , 0 , iconId , 0 );
240-
241- final var color = ColorStateList .valueOf (ThemeHelper
242- .resolveColorFromAttr (getContext (), android .R .attr .textColorPrimary ));
243- TextViewCompat .setCompoundDrawableTintList (radioButton , color );
244- }
245-
246- radioButton .setText (NotificationConstants .getActionName (getContext (), action ));
247- radioButton .setChecked (action == selectedAction );
248- radioButton .setId (id );
249- radioButton .setLayoutParams (new RadioGroup .LayoutParams (
250- ViewGroup .LayoutParams .MATCH_PARENT , ViewGroup .LayoutParams .WRAP_CONTENT ));
251- radioButton .setOnClickListener (radioButtonsClickListener );
252- binding .list .addView (radioButton );
253- }
254- alertDialog .show ();
255-
256- if (DeviceUtils .isTv (getContext ())) {
257- FocusOverlayView .setupFocusObserver (alertDialog );
258- }
259- }
260- }
261116}
0 commit comments