Convert sleep timer to bottom sheet (#8090)

This commit is contained in:
Hans-Peter Lehmann
2025-11-13 20:06:50 +01:00
committed by GitHub
parent b0efc992a6
commit 458d8732c6
2 changed files with 122 additions and 143 deletions

View File

@ -8,22 +8,22 @@ import android.os.Bundle;
import android.text.Editable; import android.text.Editable;
import android.text.TextWatcher; import android.text.TextWatcher;
import android.text.format.DateFormat; import android.text.format.DateFormat;
import android.view.LayoutInflater;
import android.view.View; import android.view.View;
import android.view.ViewGroup;
import android.view.inputmethod.InputMethodManager; import android.view.inputmethod.InputMethodManager;
import android.widget.AdapterView; import android.widget.AdapterView;
import android.widget.ArrayAdapter; import android.widget.ArrayAdapter;
import android.widget.Button; import android.widget.FrameLayout;
import android.widget.CheckBox;
import android.widget.EditText;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.Spinner;
import android.widget.TextView; import android.widget.TextView;
import androidx.annotation.NonNull; import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.appcompat.app.AlertDialog; import androidx.appcompat.app.AlertDialog;
import androidx.fragment.app.DialogFragment;
import com.google.android.material.bottomsheet.BottomSheetBehavior;
import com.google.android.material.bottomsheet.BottomSheetDialog;
import com.google.android.material.bottomsheet.BottomSheetDialogFragment;
import com.google.android.material.dialog.MaterialAlertDialogBuilder; import com.google.android.material.dialog.MaterialAlertDialogBuilder;
import com.google.android.material.snackbar.Snackbar; import com.google.android.material.snackbar.Snackbar;
@ -37,6 +37,7 @@ import java.util.Locale;
import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeUnit;
import de.danoeh.antennapod.R; import de.danoeh.antennapod.R;
import de.danoeh.antennapod.databinding.TimeDialogBinding;
import de.danoeh.antennapod.event.playback.SleepTimerUpdatedEvent; import de.danoeh.antennapod.event.playback.SleepTimerUpdatedEvent;
import de.danoeh.antennapod.playback.base.PlayerStatus; import de.danoeh.antennapod.playback.base.PlayerStatus;
import de.danoeh.antennapod.playback.service.PlaybackController; import de.danoeh.antennapod.playback.service.PlaybackController;
@ -54,28 +55,7 @@ import io.reactivex.rxjava3.core.Single;
import io.reactivex.rxjava3.disposables.Disposable; import io.reactivex.rxjava3.disposables.Disposable;
import io.reactivex.rxjava3.schedulers.Schedulers; import io.reactivex.rxjava3.schedulers.Schedulers;
public class SleepTimerDialog extends DialogFragment { public class SleepTimerDialog extends BottomSheetDialogFragment {
private PlaybackController controller;
private EditText etxtTime;
private TextView sleepTimerHintText;
private LinearLayout timeSetup;
private LinearLayout timeDisplay;
private TextView time;
private Spinner sleepTimerType;
private CheckBox chAutoEnable;
private ImageView changeTimesButton;
private CheckBox cbVibrate;
private CheckBox cbShakeToReset;
private Button setTimerButton;
private Button playbackPreferencesButton;
private Disposable disposable;
private volatile Integer currentQueueSize = null;
Button extendSleepFiveMinutesButton;
Button extendSleepTenMinutesButton;
Button extendSleepTwentyMinutesButton;
private static final int EXTEND_FEW_MINUTES_DISPLAY_VALUE = 5; private static final int EXTEND_FEW_MINUTES_DISPLAY_VALUE = 5;
private static final int EXTEND_FEW_MINUTES = 5 * 1000 * 60; private static final int EXTEND_FEW_MINUTES = 5 * 1000 * 60;
private static final int EXTEND_MID_MINUTES_DISPLAY_VALUE = 10; private static final int EXTEND_MID_MINUTES_DISPLAY_VALUE = 10;
@ -85,9 +65,13 @@ public class SleepTimerDialog extends DialogFragment {
private static final int EXTEND_FEW_EPISODES = 1; private static final int EXTEND_FEW_EPISODES = 1;
private static final int EXTEND_MID_EPISODES = 2; private static final int EXTEND_MID_EPISODES = 2;
private static final int EXTEND_LOTS_EPISODES = 3; private static final int EXTEND_LOTS_EPISODES = 3;
private static final int SLEEP_DURATION_DAILY_HOURS_CUTOFF = 12; private static final int SLEEP_DURATION_DAILY_HOURS_CUTOFF = 12;
private PlaybackController controller;
private TimeDialogBinding viewBinding;
private Disposable disposable;
private volatile Integer currentQueueSize = null;
public SleepTimerDialog() { public SleepTimerDialog() {
} }
@ -124,13 +108,30 @@ public class SleepTimerDialog extends DialogFragment {
@NonNull @NonNull
@Override @Override
public Dialog onCreateDialog(Bundle savedInstanceState) { public Dialog onCreateDialog(@Nullable Bundle savedInstanceState) {
View content = View.inflate(getContext(), R.layout.time_dialog, null); Dialog dialog = super.onCreateDialog(savedInstanceState);
MaterialAlertDialogBuilder builder = new MaterialAlertDialogBuilder(requireContext()); dialog.setOnShowListener(dialogInterface -> {
builder.setTitle(R.string.sleep_timer_label); BottomSheetDialog bottomSheetDialog = (BottomSheetDialog) dialogInterface;
builder.setView(content); setupFullHeight(bottomSheetDialog);
builder.setPositiveButton(R.string.close_label, null); });
return dialog;
}
private void setupFullHeight(BottomSheetDialog bottomSheetDialog) {
FrameLayout bottomSheet = bottomSheetDialog.findViewById(R.id.design_bottom_sheet);
if (bottomSheet != null) {
BottomSheetBehavior<FrameLayout> behavior = BottomSheetBehavior.from(bottomSheet);
ViewGroup.LayoutParams layoutParams = bottomSheet.getLayoutParams();
bottomSheet.setLayoutParams(layoutParams);
behavior.setState(BottomSheetBehavior.STATE_EXPANDED);
}
}
@Nullable
@Override
public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container,
@Nullable Bundle savedInstanceState) {
viewBinding = TimeDialogBinding.inflate(inflater);
List<String> spinnerContent = new ArrayList<>(); List<String> spinnerContent = new ArrayList<>();
// add "title" for all options // add "title" for all options
spinnerContent.add(getString(R.string.time_minutes)); spinnerContent.add(getString(R.string.time_minutes));
@ -138,10 +139,9 @@ public class SleepTimerDialog extends DialogFragment {
ArrayAdapter<String> spinnerAdapter = new ArrayAdapter<>( ArrayAdapter<String> spinnerAdapter = new ArrayAdapter<>(
getContext(), android.R.layout.simple_spinner_item, spinnerContent); getContext(), android.R.layout.simple_spinner_item, spinnerContent);
spinnerAdapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item); spinnerAdapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
sleepTimerType = content.findViewById(R.id.sleepTimerType); viewBinding.sleepTimerType.setAdapter(spinnerAdapter);
sleepTimerType.setAdapter(spinnerAdapter); viewBinding.sleepTimerType.setSelection(SleepTimerPreferences.getSleepTimerType().index);
sleepTimerType.setSelection(SleepTimerPreferences.getSleepTimerType().index); viewBinding.sleepTimerType.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
sleepTimerType.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
private boolean sleepTimerTypeInitialized = false; private boolean sleepTimerTypeInitialized = false;
@Override @Override
@ -153,13 +153,13 @@ public class SleepTimerDialog extends DialogFragment {
if (sleepTimerTypeInitialized) { if (sleepTimerTypeInitialized) {
// disable auto sleep timer if they've configured it for most of the day // disable auto sleep timer if they've configured it for most of the day
if (isSleepTimerConfiguredForMostOfTheDay()) { if (isSleepTimerConfiguredForMostOfTheDay()) {
chAutoEnable.setChecked(false); viewBinding.autoEnableCheckbox.setChecked(false);
} }
// change suggested value back to default value for sleep type // change suggested value back to default value for sleep type
if (sleepType == SleepTimerType.EPISODES) { if (sleepType == SleepTimerType.EPISODES) {
etxtTime.setText(SleepTimerPreferences.DEFAULT_SLEEP_TIMER_EPISODES); viewBinding.timeEditText.setText(SleepTimerPreferences.DEFAULT_SLEEP_TIMER_EPISODES);
} else { } else {
etxtTime.setText(SleepTimerPreferences.DEFAULT_SLEEP_TIMER_MINUTES); viewBinding.timeEditText.setText(SleepTimerPreferences.DEFAULT_SLEEP_TIMER_MINUTES);
} }
} }
sleepTimerTypeInitialized = true; sleepTimerTypeInitialized = true;
@ -170,27 +170,9 @@ public class SleepTimerDialog extends DialogFragment {
public void onNothingSelected(AdapterView<?> parent) { public void onNothingSelected(AdapterView<?> parent) {
} }
}); });
viewBinding.timeDisplayContainer.setVisibility(View.GONE);
etxtTime = content.findViewById(R.id.etxtTime); viewBinding.timeEditText.setText(SleepTimerPreferences.lastTimerValue());
sleepTimerHintText = content.findViewById(R.id.sleepTimerHintText); viewBinding.timeEditText.addTextChangedListener(new TextWatcher() {
timeSetup = content.findViewById(R.id.timeSetup);
timeDisplay = content.findViewById(R.id.timeDisplay);
timeDisplay.setVisibility(View.GONE);
time = content.findViewById(R.id.time);
cbShakeToReset = content.findViewById(R.id.cbShakeToReset);
cbVibrate = content.findViewById(R.id.cbVibrate);
chAutoEnable = content.findViewById(R.id.chAutoEnable);
changeTimesButton = content.findViewById(R.id.changeTimesButton);
setTimerButton = content.findViewById(R.id.setSleeptimerButton);
playbackPreferencesButton = content.findViewById(R.id.playbackPreferencesButton);
extendSleepFiveMinutesButton = content.findViewById(R.id.extendSleepFiveMinutesButton);
extendSleepTenMinutesButton = content.findViewById(R.id.extendSleepTenMinutesButton);
extendSleepTwentyMinutesButton = content.findViewById(R.id.extendSleepTwentyMinutesButton);
etxtTime.setText(SleepTimerPreferences.lastTimerValue());
etxtTime.addTextChangedListener(new TextWatcher() {
@Override @Override
public void beforeTextChanged(CharSequence charSequence, int i, int i1, int i2) { public void beforeTextChanged(CharSequence charSequence, int i, int i1, int i2) {
} }
@ -204,30 +186,27 @@ public class SleepTimerDialog extends DialogFragment {
refreshUiState(); refreshUiState();
} }
}); });
viewBinding.playbackPreferencesButton.setOnClickListener(view -> {
playbackPreferencesButton.setOnClickListener(view -> {
final Intent playbackIntent = new Intent(getActivity(), PreferenceActivity.class); final Intent playbackIntent = new Intent(getActivity(), PreferenceActivity.class);
playbackIntent.putExtra(PreferenceActivity.OPEN_PLAYBACK_SETTINGS, true); playbackIntent.putExtra(PreferenceActivity.OPEN_PLAYBACK_SETTINGS, true);
startActivity(playbackIntent); startActivity(playbackIntent);
dismiss(); dismiss();
}); });
viewBinding.timeEditText.postDelayed(() -> {
etxtTime.postDelayed(() -> {
InputMethodManager imm = (InputMethodManager) getContext().getSystemService(Context.INPUT_METHOD_SERVICE); InputMethodManager imm = (InputMethodManager) getContext().getSystemService(Context.INPUT_METHOD_SERVICE);
imm.showSoftInput(etxtTime, InputMethodManager.SHOW_IMPLICIT); imm.showSoftInput(viewBinding.timeEditText, InputMethodManager.SHOW_IMPLICIT);
}, 100); }, 100);
refreshUiState(); refreshUiState();
chAutoEnable.setChecked(SleepTimerPreferences.autoEnable()); viewBinding.autoEnableCheckbox.setChecked(SleepTimerPreferences.autoEnable());
cbShakeToReset.setChecked(SleepTimerPreferences.shakeToReset()); viewBinding.shakeToResetCheckbox.setChecked(SleepTimerPreferences.shakeToReset());
cbVibrate.setChecked(SleepTimerPreferences.vibrate()); viewBinding.vibrateCheckbox.setChecked(SleepTimerPreferences.vibrate());
refreshAutoEnableControls(SleepTimerPreferences.autoEnable()); refreshAutoEnableControls(SleepTimerPreferences.autoEnable());
cbShakeToReset.setOnCheckedChangeListener((buttonView, isChecked) viewBinding.shakeToResetCheckbox.setOnCheckedChangeListener((buttonView, isChecked)
-> SleepTimerPreferences.setShakeToReset(isChecked)); -> SleepTimerPreferences.setShakeToReset(isChecked));
cbVibrate.setOnCheckedChangeListener((buttonView, isChecked) viewBinding.vibrateCheckbox.setOnCheckedChangeListener((buttonView, isChecked)
-> SleepTimerPreferences.setVibrate(isChecked)); -> SleepTimerPreferences.setVibrate(isChecked));
chAutoEnable.setOnCheckedChangeListener((compoundButton, isChecked) viewBinding.autoEnableCheckbox.setOnCheckedChangeListener((compoundButton, isChecked)
-> { -> {
boolean mostOfDay = isSleepTimerConfiguredForMostOfTheDay(); boolean mostOfDay = isSleepTimerConfiguredForMostOfTheDay();
if (isChecked && mostOfDay && SleepTimerPreferences.getSleepTimerType() == SleepTimerType.EPISODES) { if (isChecked && mostOfDay && SleepTimerPreferences.getSleepTimerType() == SleepTimerType.EPISODES) {
@ -237,23 +216,20 @@ public class SleepTimerDialog extends DialogFragment {
}); });
updateAutoEnableText(); updateAutoEnableText();
changeTimesButton.setOnClickListener(changeTimesBtn -> { viewBinding.changeTimesButton.setOnClickListener(changeTimesBtn -> {
int from = SleepTimerPreferences.autoEnableFrom(); int from = SleepTimerPreferences.autoEnableFrom();
int to = SleepTimerPreferences.autoEnableTo(); int to = SleepTimerPreferences.autoEnableTo();
showTimeRangeDialog(getContext(), from, to); showTimeRangeDialog(getContext(), from, to);
}); });
viewBinding.disableSleeptimerButton.setOnClickListener(v -> {
Button disableButton = content.findViewById(R.id.disableSleeptimerButton);
disableButton.setOnClickListener(v -> {
if (controller != null) { if (controller != null) {
controller.disableSleepTimer(); controller.disableSleepTimer();
} }
}); });
viewBinding.setSleeptimerButton.setOnClickListener(v -> {
setTimerButton.setOnClickListener(v -> {
if (!PlaybackService.isRunning if (!PlaybackService.isRunning
|| (controller != null && controller.getStatus() != PlayerStatus.PLAYING)) { || (controller != null && controller.getStatus() != PlayerStatus.PLAYING)) {
Snackbar.make(content, R.string.no_media_playing_label, Snackbar.LENGTH_LONG).show(); Snackbar.make(viewBinding.getRoot(), R.string.no_media_playing_label, Snackbar.LENGTH_LONG).show();
return; return;
} }
try { try {
@ -261,13 +237,13 @@ public class SleepTimerDialog extends DialogFragment {
if (controller != null) { if (controller != null) {
controller.setSleepTimer(SleepTimerPreferences.timerMillisOrEpisodes()); controller.setSleepTimer(SleepTimerPreferences.timerMillisOrEpisodes());
} }
closeKeyboard(content); closeKeyboard(viewBinding.getRoot());
} catch (NumberFormatException e) { } catch (NumberFormatException e) {
e.printStackTrace(); e.printStackTrace();
Snackbar.make(content, R.string.time_dialog_invalid_input, Snackbar.LENGTH_LONG).show(); Snackbar.make(viewBinding.getRoot(), R.string.time_dialog_invalid_input, Snackbar.LENGTH_LONG).show();
} }
}); });
return builder.create(); return viewBinding.getRoot();
} }
private boolean isSleepTimerConfiguredForMostOfTheDay() { private boolean isSleepTimerConfiguredForMostOfTheDay() {
@ -282,7 +258,7 @@ public class SleepTimerDialog extends DialogFragment {
(dialogInterface, i) -> { (dialogInterface, i) -> {
// disable continuous playback and also disable the auto sleep timer // disable continuous playback and also disable the auto sleep timer
UserPreferences.setFollowQueue(false); UserPreferences.setFollowQueue(false);
chAutoEnable.setChecked(false); viewBinding.autoEnableCheckbox.setChecked(false);
refreshUiState(); refreshUiState();
}) })
.setPositiveButton(R.string.sleep_timer_without_continuous_playback_change_hours, .setPositiveButton(R.string.sleep_timer_without_continuous_playback_change_hours,
@ -292,15 +268,14 @@ public class SleepTimerDialog extends DialogFragment {
showTimeRangeDialog(getContext(), from, to); showTimeRangeDialog(getContext(), from, to);
}) })
.create(); .create();
dialog.setOnCancelListener(dialogInterface -> chAutoEnable.setChecked(false)); dialog.setOnCancelListener(dialogInterface -> viewBinding.autoEnableCheckbox.setChecked(false));
dialog.show(); dialog.show();
// mark the disable continuous playback option in red
dialog.getButton(AlertDialog.BUTTON_NEGATIVE) dialog.getButton(AlertDialog.BUTTON_NEGATIVE)
.setTextColor(ThemeUtils.getColorFromAttr(requireContext(), R.attr.colorError)); .setTextColor(ThemeUtils.getColorFromAttr(requireContext(), R.attr.colorError));
} }
private long getSelectedSleepTime() throws NumberFormatException { private long getSelectedSleepTime() throws NumberFormatException {
long time = Long.parseLong(etxtTime.getText().toString()); long time = Long.parseLong(viewBinding.timeEditText.getText().toString());
if (time == 0) { if (time == 0) {
throw new NumberFormatException("Timer must not be zero"); throw new NumberFormatException("Timer must not be zero");
} }
@ -309,7 +284,7 @@ public class SleepTimerDialog extends DialogFragment {
private void refreshAutoEnableControls(boolean enabled) { private void refreshAutoEnableControls(boolean enabled) {
SleepTimerPreferences.setAutoEnable(enabled); SleepTimerPreferences.setAutoEnable(enabled);
changeTimesButton.setAlpha(enabled ? 1.0f : 0.5f); viewBinding.changeTimesButton.setAlpha(enabled ? 1.0f : 0.5f);
} }
private void refreshUiState() { private void refreshUiState() {
@ -319,23 +294,23 @@ public class SleepTimerDialog extends DialogFragment {
boolean noEpisodeSelection = isEpisodeType && !UserPreferences.isFollowQueue(); boolean noEpisodeSelection = isEpisodeType && !UserPreferences.isFollowQueue();
if (noEpisodeSelection) { if (noEpisodeSelection) {
etxtTime.setEnabled(false); viewBinding.timeEditText.setEnabled(false);
playbackPreferencesButton.setVisibility(View.VISIBLE); viewBinding.playbackPreferencesButton.setVisibility(View.VISIBLE);
sleepTimerHintText.setText(R.string.multiple_sleep_episodes_while_continuous_playback_disabled); viewBinding.sleepTimerHintText.setText(R.string.multiple_sleep_episodes_while_continuous_playback_disabled);
sleepTimerHintText.setVisibility(View.VISIBLE); viewBinding.sleepTimerHintText.setVisibility(View.VISIBLE);
chAutoEnable.setVisibility(View.GONE); viewBinding.autoEnableCheckbox.setVisibility(View.GONE);
changeTimesButton.setVisibility(View.GONE); viewBinding.changeTimesButton.setVisibility(View.GONE);
cbShakeToReset.setVisibility(View.GONE); viewBinding.shakeToResetCheckbox.setVisibility(View.GONE);
cbVibrate.setVisibility(View.GONE); viewBinding.vibrateCheckbox.setVisibility(View.GONE);
setTimerButton.setEnabled(false); viewBinding.setSleeptimerButton.setEnabled(false);
} else { } else {
playbackPreferencesButton.setVisibility(View.GONE); viewBinding.playbackPreferencesButton.setVisibility(View.GONE);
chAutoEnable.setVisibility(View.VISIBLE); viewBinding.autoEnableCheckbox.setVisibility(View.VISIBLE);
changeTimesButton.setVisibility(View.VISIBLE); viewBinding.changeTimesButton.setVisibility(View.VISIBLE);
cbShakeToReset.setVisibility(isEpisodeType ? View.GONE : View.VISIBLE); viewBinding.shakeToResetCheckbox.setVisibility(isEpisodeType ? View.GONE : View.VISIBLE);
cbVibrate.setVisibility(View.VISIBLE); viewBinding.vibrateCheckbox.setVisibility(View.VISIBLE);
setTimerButton.setEnabled(true); viewBinding.setSleeptimerButton.setEnabled(true);
etxtTime.setEnabled(true); viewBinding.timeEditText.setEnabled(true);
long selectedSleepTime; long selectedSleepTime;
try { try {
selectedSleepTime = getSelectedSleepTime(); selectedSleepTime = getSelectedSleepTime();
@ -346,13 +321,13 @@ public class SleepTimerDialog extends DialogFragment {
if (isEpisodeType) { if (isEpisodeType) {
// for episode timers check if the queue length exceeds the number of sleep episodes we have // for episode timers check if the queue length exceeds the number of sleep episodes we have
if (currentQueueSize != null && selectedSleepTime > currentQueueSize) { if (currentQueueSize != null && selectedSleepTime > currentQueueSize) {
sleepTimerHintText.setText(getResources().getQuantityString( viewBinding.sleepTimerHintText.setText(getResources().getQuantityString(
R.plurals.episodes_sleep_timer_exceeds_queue, R.plurals.episodes_sleep_timer_exceeds_queue,
currentQueueSize, currentQueueSize,
currentQueueSize)); currentQueueSize));
sleepTimerHintText.setVisibility(View.VISIBLE); viewBinding.sleepTimerHintText.setVisibility(View.VISIBLE);
} else { } else {
sleepTimerHintText.setVisibility(View.GONE); // could maybe show duration in minutes viewBinding.sleepTimerHintText.setVisibility(View.GONE);
} }
} else { } else {
// for time sleep timers check if the selected value exceeds the remaining play time in the episode // for time sleep timers check if the selected value exceeds the remaining play time in the episode
@ -361,43 +336,43 @@ public class SleepTimerDialog extends DialogFragment {
final long timer = TimeUnit.MINUTES.toMillis(selectedSleepTime); final long timer = TimeUnit.MINUTES.toMillis(selectedSleepTime);
if ((timer > remaining) && !UserPreferences.isFollowQueue()) { if ((timer > remaining) && !UserPreferences.isFollowQueue()) {
final int remainingMinutes = Math.toIntExact(TimeUnit.MILLISECONDS.toMinutes(remaining)); final int remainingMinutes = Math.toIntExact(TimeUnit.MILLISECONDS.toMinutes(remaining));
sleepTimerHintText viewBinding.sleepTimerHintText
.setText(getResources().getQuantityString( .setText(getResources().getQuantityString(
R.plurals.timer_exceeds_remaining_time_while_continuous_playback_disabled, R.plurals.timer_exceeds_remaining_time_while_continuous_playback_disabled,
remainingMinutes, remainingMinutes,
remainingMinutes remainingMinutes
)); ));
sleepTimerHintText.setVisibility(View.VISIBLE); viewBinding.sleepTimerHintText.setVisibility(View.VISIBLE);
} else { } else {
// don't show it at all // don't show it at all
sleepTimerHintText.setVisibility(View.GONE); viewBinding.sleepTimerHintText.setVisibility(View.GONE); // could maybe show duration in minutes
} }
} }
} }
// disable extension for episodes if we're not moving to next one // disable extension for episodes if we're not moving to next one
extendSleepFiveMinutesButton.setEnabled(!noEpisodeSelection); viewBinding.extendSleepFiveMinutesButton.setEnabled(!noEpisodeSelection);
extendSleepTenMinutesButton.setEnabled(!noEpisodeSelection); viewBinding.extendSleepTenMinutesButton.setEnabled(!noEpisodeSelection);
extendSleepTwentyMinutesButton.setEnabled(!noEpisodeSelection); viewBinding.extendSleepTwentyMinutesButton.setEnabled(!noEpisodeSelection);
if (SleepTimerPreferences.getSleepTimerType() == SleepTimerType.CLOCK) { if (SleepTimerPreferences.getSleepTimerType() == SleepTimerType.CLOCK) {
setupExtendButton(extendSleepFiveMinutesButton, setupExtendButton(viewBinding.extendSleepFiveMinutesButton,
getString(R.string.extend_sleep_timer_label, EXTEND_FEW_MINUTES_DISPLAY_VALUE), getString(R.string.extend_sleep_timer_label, EXTEND_FEW_MINUTES_DISPLAY_VALUE),
EXTEND_FEW_MINUTES); EXTEND_FEW_MINUTES);
setupExtendButton(extendSleepTenMinutesButton, setupExtendButton(viewBinding.extendSleepTenMinutesButton,
getString(R.string.extend_sleep_timer_label, EXTEND_MID_MINUTES_DISPLAY_VALUE), getString(R.string.extend_sleep_timer_label, EXTEND_MID_MINUTES_DISPLAY_VALUE),
EXTEND_MID_MINUTES); EXTEND_MID_MINUTES);
setupExtendButton(extendSleepTwentyMinutesButton, setupExtendButton(viewBinding.extendSleepTwentyMinutesButton,
getString(R.string.extend_sleep_timer_label, EXTEND_LOTS_MINUTES_DISPLAY_VALUE), getString(R.string.extend_sleep_timer_label, EXTEND_LOTS_MINUTES_DISPLAY_VALUE),
EXTEND_LOTS_MINUTES); EXTEND_LOTS_MINUTES);
} else { } else {
setupExtendButton(extendSleepFiveMinutesButton, setupExtendButton(viewBinding.extendSleepFiveMinutesButton,
"+" + getResources().getQuantityString(R.plurals.num_episodes, "+" + getResources().getQuantityString(R.plurals.num_episodes,
EXTEND_FEW_EPISODES, EXTEND_FEW_EPISODES), EXTEND_FEW_EPISODES); EXTEND_FEW_EPISODES, EXTEND_FEW_EPISODES), EXTEND_FEW_EPISODES);
setupExtendButton(extendSleepTenMinutesButton, setupExtendButton(viewBinding.extendSleepTenMinutesButton,
"+" + getResources().getQuantityString(R.plurals.num_episodes, "+" + getResources().getQuantityString(R.plurals.num_episodes,
EXTEND_MID_EPISODES, EXTEND_MID_EPISODES), EXTEND_MID_EPISODES); EXTEND_MID_EPISODES, EXTEND_MID_EPISODES), EXTEND_MID_EPISODES);
setupExtendButton(extendSleepTwentyMinutesButton, setupExtendButton(viewBinding.extendSleepTwentyMinutesButton,
"+" + getResources().getQuantityString(R.plurals.num_episodes, "+" + getResources().getQuantityString(R.plurals.num_episodes,
EXTEND_LOTS_EPISODES, EXTEND_LOTS_EPISODES), EXTEND_LOTS_EPISODES); EXTEND_LOTS_EPISODES, EXTEND_LOTS_EPISODES), EXTEND_LOTS_EPISODES);
} }
@ -422,8 +397,9 @@ public class SleepTimerDialog extends DialogFragment {
// only change the state if true, don't change it regardless of flag (although we could) // only change the state if true, don't change it regardless of flag (although we could)
if (mostOfDay && SleepTimerPreferences.getSleepTimerType() == SleepTimerType.EPISODES) { if (mostOfDay && SleepTimerPreferences.getSleepTimerType() == SleepTimerType.EPISODES) {
confirmAlwaysSleepTimerDialog(); confirmAlwaysSleepTimerDialog();
} else if (!chAutoEnable.isChecked()) { // if it's not checked, then make sure it's checked in UI too } else if (!viewBinding.autoEnableCheckbox.isChecked()) {
chAutoEnable.setChecked(true); // if it's not checked, then make sure it's checked in UI too
viewBinding.autoEnableCheckbox.setChecked(true);
} }
updateAutoEnableText(); updateAutoEnableText();
}); });
@ -449,21 +425,22 @@ public class SleepTimerDialog extends DialogFragment {
text = getString(R.string.auto_enable_label_with_times, formattedFrom, formattedTo); text = getString(R.string.auto_enable_label_with_times, formattedFrom, formattedTo);
} }
chAutoEnable.setText(text); viewBinding.autoEnableCheckbox.setText(text);
} }
@Subscribe(threadMode = ThreadMode.MAIN, sticky = true) @Subscribe(threadMode = ThreadMode.MAIN, sticky = true)
@SuppressWarnings("unused") @SuppressWarnings("unused")
public void timerUpdated(SleepTimerUpdatedEvent event) { public void timerUpdated(SleepTimerUpdatedEvent event) {
timeDisplay.setVisibility(event.isOver() || event.isCancelled() ? View.GONE : View.VISIBLE); viewBinding.timeDisplayContainer.setVisibility(
timeSetup.setVisibility(event.isOver() || event.isCancelled() ? View.VISIBLE : View.GONE); event.isOver() || event.isCancelled() ? View.GONE : View.VISIBLE);
sleepTimerType.setEnabled(event.isOver() || event.isCancelled()); viewBinding.timeSetupContainer.setVisibility(event.isOver() || event.isCancelled() ? View.VISIBLE : View.GONE);
viewBinding.sleepTimerType.setEnabled(event.isOver() || event.isCancelled());
if (SleepTimerPreferences.getSleepTimerType() == SleepTimerType.EPISODES) { if (SleepTimerPreferences.getSleepTimerType() == SleepTimerType.EPISODES) {
time.setText(getResources().getQuantityString(R.plurals.num_episodes, viewBinding.time.setText(getResources().getQuantityString(R.plurals.num_episodes,
(int) event.getDisplayTimeLeft(), (int) event.getDisplayTimeLeft())); (int) event.getDisplayTimeLeft(), (int) event.getDisplayTimeLeft()));
} else { } else {
time.setText(Converter.getDurationStringLong((int) event.getDisplayTimeLeft())); viewBinding.time.setText(Converter.getDurationStringLong((int) event.getDisplayTimeLeft()));
} }
} }

View File

@ -14,7 +14,7 @@
android:padding="16dp"> android:padding="16dp">
<LinearLayout <LinearLayout
android:id="@+id/timeSetup" android:id="@+id/timeSetupContainer"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:orientation="vertical"> android:orientation="vertical">
@ -25,7 +25,7 @@
android:orientation="horizontal"> android:orientation="horizontal">
<EditText <EditText
android:id="@+id/etxtTime" android:id="@+id/timeEditText"
android:layout_width="0dp" android:layout_width="0dp"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_weight="1" android:layout_weight="1"
@ -60,12 +60,13 @@
android:id="@+id/setSleeptimerButton" android:id="@+id/setSleeptimerButton"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:text="@string/set_sleeptimer_label" /> android:text="@string/set_sleeptimer_label"
style="@style/Widget.Material3.Button" />
</LinearLayout> </LinearLayout>
<LinearLayout <LinearLayout
android:id="@+id/timeDisplay" android:id="@+id/timeDisplayContainer"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:orientation="vertical" android:orientation="vertical"
@ -81,12 +82,6 @@
android:textSize="32sp" android:textSize="32sp"
android:textColor="?android:attr/textColorPrimary" /> android:textColor="?android:attr/textColorPrimary" />
<Button
android:id="@+id/disableSleeptimerButton"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="@string/disable_sleeptimer_label" />
<LinearLayout <LinearLayout
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
@ -132,6 +127,13 @@
</LinearLayout> </LinearLayout>
<Button
android:id="@+id/disableSleeptimerButton"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="@string/disable_sleeptimer_label"
style="@style/Widget.Material3.Button" />
</LinearLayout> </LinearLayout>
<LinearLayout <LinearLayout
@ -141,13 +143,13 @@
android:layout_marginTop="8dp"> android:layout_marginTop="8dp">
<CheckBox <CheckBox
android:id="@+id/cbShakeToReset" android:id="@+id/shakeToResetCheckbox"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:text="@string/shake_to_reset_label" /> android:text="@string/shake_to_reset_label" />
<CheckBox <CheckBox
android:id="@+id/cbVibrate" android:id="@+id/vibrateCheckbox"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:text="@string/timer_vibration_label" /> android:text="@string/timer_vibration_label" />
@ -159,7 +161,7 @@
android:weightSum="1"> android:weightSum="1">
<CheckBox <CheckBox
android:id="@+id/chAutoEnable" android:id="@+id/autoEnableCheckbox"
android:layout_width="0dp" android:layout_width="0dp"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_weight="1" android:layout_weight="1"