diff options
author | H. Lehmann <ByteHamster@users.noreply.github.com> | 2020-02-01 11:05:04 +0100 |
---|---|---|
committer | GitHub <noreply@github.com> | 2020-02-01 11:05:04 +0100 |
commit | f5a30f6eed0fd2f8f85ed7ee697c8c96d5d669e5 (patch) | |
tree | b1b69eb5967fb19904a1ae75c653942c537bea8c | |
parent | a0491bd67e29a2a73db490e56075e4a8bedb43ba (diff) | |
parent | 17444d9a3c275c4f2f865c8e6ec8b886f1e37e7f (diff) | |
download | AntennaPod-f5a30f6eed0fd2f8f85ed7ee697c8c96d5d669e5.zip |
Merge pull request #3811 from ByteHamster/sleep-timer-ui
Updated sleep timer UI
7 files changed, 216 insertions, 159 deletions
diff --git a/app/src/main/java/de/danoeh/antennapod/activity/MediaplayerActivity.java b/app/src/main/java/de/danoeh/antennapod/activity/MediaplayerActivity.java index 538ed1231..021ff774d 100644 --- a/app/src/main/java/de/danoeh/antennapod/activity/MediaplayerActivity.java +++ b/app/src/main/java/de/danoeh/antennapod/activity/MediaplayerActivity.java @@ -358,10 +358,8 @@ public abstract class MediaplayerActivity extends CastEnabledActivity implements menu.findItem(R.id.remove_from_favorites_item).setVisible(isFavorite); } - boolean sleepTimerSet = controller.sleepTimerActive(); - boolean sleepTimerNotSet = controller.sleepTimerNotActive(); - menu.findItem(R.id.set_sleeptimer_item).setVisible(sleepTimerNotSet); - menu.findItem(R.id.disable_sleeptimer_item).setVisible(sleepTimerSet); + menu.findItem(R.id.set_sleeptimer_item).setVisible(!controller.sleepTimerActive()); + menu.findItem(R.id.disable_sleeptimer_item).setVisible(controller.sleepTimerActive()); if (this instanceof AudioplayerActivity) { int[] attrs = {R.attr.action_bar_icon_color}; @@ -422,30 +420,9 @@ public abstract class MediaplayerActivity extends CastEnabledActivity implements .show(); } break; - case R.id.disable_sleeptimer_item: - if (controller.serviceAvailable()) { - - new AlertDialog.Builder(this) - .setTitle(R.string.sleep_timer_label) - .setMessage(getString(R.string.time_left_label) - + Converter.getDurationStringLong((int) controller - .getSleepTimerTimeLeft())) - .setPositiveButton(R.string.disable_sleeptimer_label, (dialog, which) - -> controller.disableSleepTimer()) - .setNegativeButton(R.string.cancel_label, null) - .show(); - } - break; + case R.id.disable_sleeptimer_item: // Fall-through case R.id.set_sleeptimer_item: - if (controller.serviceAvailable()) { - SleepTimerDialog td = new SleepTimerDialog(this) { - @Override - public void onTimerSet(long millis, boolean shakeToReset, boolean vibrate) { - controller.setSleepTimer(millis, shakeToReset, vibrate); - } - }; - td.createNewDialog().show(); - } + new SleepTimerDialog().show(getSupportFragmentManager(), "SleepTimerDialog"); break; case R.id.audio_controls: boolean isPlayingVideo = controller.getMedia().getMediaType() == MediaType.VIDEO; diff --git a/app/src/main/java/de/danoeh/antennapod/dialog/SleepTimerDialog.java b/app/src/main/java/de/danoeh/antennapod/dialog/SleepTimerDialog.java index 8d176c708..d36f97c7a 100644 --- a/app/src/main/java/de/danoeh/antennapod/dialog/SleepTimerDialog.java +++ b/app/src/main/java/de/danoeh/antennapod/dialog/SleepTimerDialog.java @@ -1,67 +1,101 @@ package de.danoeh.antennapod.dialog; +import android.app.Dialog; import android.content.Context; +import android.os.Bundle; import android.text.Editable; import android.text.TextWatcher; import android.view.View; import android.view.inputmethod.InputMethodManager; import android.widget.ArrayAdapter; +import android.widget.Button; import android.widget.CheckBox; import android.widget.EditText; +import android.widget.LinearLayout; import android.widget.Spinner; +import android.widget.TextView; import android.widget.Toast; - +import androidx.annotation.NonNull; import androidx.appcompat.app.AlertDialog; +import androidx.fragment.app.DialogFragment; import de.danoeh.antennapod.R; -import de.danoeh.antennapod.core.event.MessageEvent; import de.danoeh.antennapod.core.preferences.SleepTimerPreferences; -import org.greenrobot.eventbus.EventBus; +import de.danoeh.antennapod.core.service.playback.PlaybackService; +import de.danoeh.antennapod.core.util.Converter; +import de.danoeh.antennapod.core.util.playback.PlaybackController; +import io.reactivex.Observable; +import io.reactivex.android.schedulers.AndroidSchedulers; +import io.reactivex.disposables.Disposable; -public abstract class SleepTimerDialog { - - private static final String TAG = SleepTimerDialog.class.getSimpleName(); +import java.util.concurrent.TimeUnit; - private final Context context; +public class SleepTimerDialog extends DialogFragment { + private PlaybackController controller; + private Disposable timeUpdater; - private AlertDialog dialog; private EditText etxtTime; private Spinner spTimeUnit; private CheckBox cbShakeToReset; private CheckBox cbVibrate; private CheckBox chAutoEnable; + private LinearLayout timeSetup; + private LinearLayout timeDisplay; + private TextView time; + public SleepTimerDialog() { - protected SleepTimerDialog(Context context) { - this.context = context; } - public AlertDialog createNewDialog() { - View content = View.inflate(context, R.layout.time_dialog, null); - AlertDialog.Builder builder = new AlertDialog.Builder(context); - builder.setTitle(R.string.set_sleeptimer_label); - builder.setView(content); - builder.setNegativeButton(R.string.cancel_label, (dialog, which) -> dialog.dismiss()); - builder.setPositiveButton(R.string.set_sleeptimer_label, (dialog, which) -> { - try { - savePreferences(); - long input = SleepTimerPreferences.timerMillis(); - onTimerSet(input, cbShakeToReset.isChecked(), cbVibrate.isChecked()); - dialog.dismiss(); - } catch (NumberFormatException e) { - e.printStackTrace(); - Toast toast = Toast.makeText(context, R.string.time_dialog_invalid_input, - Toast.LENGTH_LONG); - toast.show(); + @Override + public void onStart() { + super.onStart(); + controller = new PlaybackController(getActivity(), false) { + @Override + public void setupGUI() { + updateTime(); } - }); - dialog = builder.create(); + + @Override + public void onSleepTimerUpdate() { + updateTime(); + } + }; + controller.init(); + timeUpdater = Observable.interval(1, TimeUnit.SECONDS) + .observeOn(AndroidSchedulers.mainThread()) + .subscribe(tick -> updateTime()); + } + + @Override + public void onStop() { + super.onStop(); + if (controller != null) { + controller.release(); + } + if (timeUpdater != null) { + timeUpdater.dispose(); + } + } + + @NonNull + @Override + public Dialog onCreateDialog(Bundle savedInstanceState) { + View content = View.inflate(getContext(), R.layout.time_dialog, null); + AlertDialog.Builder builder = new AlertDialog.Builder(getContext()); + builder.setTitle(R.string.sleep_timer_label); + builder.setView(content); + builder.setPositiveButton(android.R.string.ok, null); etxtTime = content.findViewById(R.id.etxtTime); spTimeUnit = content.findViewById(R.id.spTimeUnit); cbShakeToReset = content.findViewById(R.id.cbShakeToReset); cbVibrate = content.findViewById(R.id.cbVibrate); chAutoEnable = content.findViewById(R.id.chAutoEnable); + timeSetup = content.findViewById(R.id.timeSetup); + timeDisplay = content.findViewById(R.id.timeDisplay); + time = content.findViewById(R.id.time); + AlertDialog dialog = builder.create(); etxtTime.setText(SleepTimerPreferences.lastTimerValue()); etxtTime.addTextChangedListener(new TextWatcher() { @Override @@ -78,15 +112,15 @@ public abstract class SleepTimerDialog { } }); etxtTime.postDelayed(() -> { - InputMethodManager imm = (InputMethodManager) context.getSystemService(Context.INPUT_METHOD_SERVICE); + InputMethodManager imm = (InputMethodManager) getContext().getSystemService(Context.INPUT_METHOD_SERVICE); imm.showSoftInput(etxtTime, InputMethodManager.SHOW_IMPLICIT); }, 100); String[] spinnerContent = new String[] { - context.getString(R.string.time_seconds), - context.getString(R.string.time_minutes), - context.getString(R.string.time_hours) }; - ArrayAdapter<String> spinnerAdapter = new ArrayAdapter<>(context, + getString(R.string.time_seconds), + getString(R.string.time_minutes), + getString(R.string.time_hours) }; + ArrayAdapter<String> spinnerAdapter = new ArrayAdapter<>(getContext(), android.R.layout.simple_spinner_item, spinnerContent); spinnerAdapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item); spTimeUnit.setAdapter(spinnerAdapter); @@ -96,16 +130,33 @@ public abstract class SleepTimerDialog { cbVibrate.setChecked(SleepTimerPreferences.vibrate()); chAutoEnable.setChecked(SleepTimerPreferences.autoEnable()); - chAutoEnable.setOnCheckedChangeListener((compoundButton, isChecked) -> { - SleepTimerPreferences.setAutoEnable(isChecked); - int messageString = isChecked ? R.string.sleep_timer_enabled_label : R.string.sleep_timer_disabled_label; - EventBus.getDefault().post(new MessageEvent(context.getString(messageString))); + chAutoEnable.setOnCheckedChangeListener((compoundButton, isChecked) + -> SleepTimerPreferences.setAutoEnable(isChecked)); + Button disableButton = content.findViewById(R.id.disableSleeptimerButton); + disableButton.setOnClickListener(v -> { + if (controller != null) { + controller.disableSleepTimer(); + } + }); + Button setButton = content.findViewById(R.id.setSleeptimerButton); + setButton.setOnClickListener(v -> { + if (!PlaybackService.isRunning) { + Toast.makeText(getContext(), R.string.no_media_playing_label, Toast.LENGTH_LONG).show(); + } + try { + savePreferences(); + long time = SleepTimerPreferences.timerMillis(); + if (controller != null) { + controller.setSleepTimer(time, cbShakeToReset.isChecked(), cbVibrate.isChecked()); + } + } catch (NumberFormatException e) { + e.printStackTrace(); + Toast.makeText(getContext(), R.string.time_dialog_invalid_input, Toast.LENGTH_LONG).show(); + } }); return dialog; } - public abstract void onTimerSet(long millis, boolean shakeToReset, boolean vibrate); - private void savePreferences() { SleepTimerPreferences.setLastTimer(etxtTime.getText().toString(), spTimeUnit.getSelectedItemPosition()); @@ -114,4 +165,12 @@ public abstract class SleepTimerDialog { SleepTimerPreferences.setAutoEnable(chAutoEnable.isChecked()); } + private void updateTime() { + if (controller == null) { + return; + } + timeSetup.setVisibility(controller.sleepTimerActive() ? View.GONE : View.VISIBLE); + timeDisplay.setVisibility(controller.sleepTimerActive() ? View.VISIBLE : View.GONE); + time.setText(Converter.getDurationStringLong((int) controller.getSleepTimerTimeLeft())); + } } diff --git a/app/src/main/res/layout/time_dialog.xml b/app/src/main/res/layout/time_dialog.xml index b3742c20c..8ada0d6cf 100644 --- a/app/src/main/res/layout/time_dialog.xml +++ b/app/src/main/res/layout/time_dialog.xml @@ -1,67 +1,95 @@ <?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" - android:layout_width="match_parent" - android:layout_height="wrap_content" - android:orientation="vertical" - android:gravity="center" - android:padding="16dp"> + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:orientation="vertical" + android:gravity="center" + android:padding="16dp"> <LinearLayout - android:layout_width="match_parent" - android:layout_height="wrap_content" - android:orientation="horizontal" > - - <EditText - android:id="@+id/etxtTime" - android:layout_width="wrap_content" - android:layout_height="wrap_content" - android:layout_weight="1" - android:layout_margin="8dp" - android:ems="2" - android:hint="@string/enter_time_here_label" - android:inputType="number" - android:maxLength="2" > - - <requestFocus /> - </EditText> - - <Spinner - android:id="@+id/spTimeUnit" - android:layout_width="wrap_content" + android:layout_width="match_parent" android:layout_height="wrap_content" - android:layout_marginBottom="8dp" - android:layout_marginTop="8dp" /> + android:id="@+id/timeSetup" + android:orientation="vertical"> + + <LinearLayout + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:orientation="horizontal"> + + <EditText + android:id="@+id/etxtTime" + android:layout_width="0dp" + android:layout_height="wrap_content" + android:layout_weight="1" + android:layout_margin="8dp" + android:ems="2" + android:inputType="number" + android:maxLength="3"/> + + <Spinner + android:id="@+id/spTimeUnit" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:layout_marginBottom="8dp" + android:layout_marginTop="8dp"/> + </LinearLayout> + + <Button + android:text="@string/set_sleeptimer_label" + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:id="@+id/setSleeptimerButton"/> </LinearLayout> <LinearLayout - android:layout_width="match_parent" - android:layout_height="wrap_content" - android:orientation="vertical"> + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:id="@+id/timeDisplay" + android:orientation="vertical" + android:visibility="gone"> <TextView - android:layout_width="wrap_content" + android:text="00:00:00" + android:layout_gravity="center" + android:textSize="32sp" + android:textColor="?android:attr/textColorPrimary" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:id="@+id/time"/> + + <Button + android:text="@string/disable_sleeptimer_label" + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:id="@+id/disableSleeptimerButton"/> + + </LinearLayout> + + + <LinearLayout + android:layout_width="match_parent" android:layout_height="wrap_content" - android:layout_marginTop="8dp" - android:text="@string/timer_about_to_expire_label" - android:textSize="16sp" /> + android:orientation="vertical" + android:layout_marginTop="8dp"> <CheckBox - android:id="@+id/cbShakeToReset" - android:layout_width="wrap_content" - android:layout_height="wrap_content" - android:text="@string/shake_to_reset_label" /> + android:id="@+id/cbShakeToReset" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:text="@string/shake_to_reset_label"/> <CheckBox - android:id="@+id/cbVibrate" - android:layout_width="wrap_content" - android:layout_height="wrap_content" - android:text="@string/timer_vibration_label" /> + android:id="@+id/cbVibrate" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:text="@string/timer_vibration_label"/> <CheckBox - android:id="@+id/chAutoEnable" - android:layout_width="wrap_content" - android:layout_height="wrap_content" - android:text="@string/auto_enable_label" /> + android:id="@+id/chAutoEnable" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:text="@string/auto_enable_label"/> </LinearLayout> diff --git a/core/src/main/java/de/danoeh/antennapod/core/service/playback/PlaybackService.java b/core/src/main/java/de/danoeh/antennapod/core/service/playback/PlaybackService.java index 2fb37cc05..edcaacefc 100644 --- a/core/src/main/java/de/danoeh/antennapod/core/service/playback/PlaybackService.java +++ b/core/src/main/java/de/danoeh/antennapod/core/service/playback/PlaybackService.java @@ -745,10 +745,12 @@ public class PlaybackService extends MediaBrowserServiceCompat { setupPositionUpdater(); stateManager.validStartCommandWasReceived(); // set sleep timer if auto-enabled - if (newInfo.oldPlayerStatus != null && newInfo.oldPlayerStatus != PlayerStatus.SEEKING && - SleepTimerPreferences.autoEnable() && !sleepTimerActive()) { + if (newInfo.oldPlayerStatus != null && newInfo.oldPlayerStatus != PlayerStatus.SEEKING + && SleepTimerPreferences.autoEnable() && !sleepTimerActive()) { setSleepTimer(SleepTimerPreferences.timerMillis(), SleepTimerPreferences.shakeToReset(), SleepTimerPreferences.vibrate()); + EventBus.getDefault().post(new MessageEvent(getString(R.string.sleep_timer_enabled_label), + PlaybackService.this::disableSleepTimer)); } break; @@ -1007,17 +1009,14 @@ public class PlaybackService extends MediaBrowserServiceCompat { } public void setSleepTimer(long waitingTime, boolean shakeToReset, boolean vibrate) { - Log.d(TAG, "Setting sleep timer to " + Long.toString(waitingTime) + " milliseconds"); + Log.d(TAG, "Setting sleep timer to " + waitingTime + " milliseconds"); taskManager.setSleepTimer(waitingTime, shakeToReset, vibrate); sendNotificationBroadcast(NOTIFICATION_TYPE_SLEEPTIMER_UPDATE, 0); - EventBus.getDefault().post(new MessageEvent(getString(R.string.sleep_timer_enabled_label), - this::disableSleepTimer)); } public void disableSleepTimer() { taskManager.disableSleepTimer(); sendNotificationBroadcast(NOTIFICATION_TYPE_SLEEPTIMER_UPDATE, 0); - EventBus.getDefault().post(new MessageEvent(getString(R.string.sleep_timer_disabled_label))); } private void sendNotificationBroadcast(int type, int code) { diff --git a/core/src/main/java/de/danoeh/antennapod/core/service/playback/PlaybackServiceTaskManager.java b/core/src/main/java/de/danoeh/antennapod/core/service/playback/PlaybackServiceTaskManager.java index 736cf8cf2..62eda415e 100644 --- a/core/src/main/java/de/danoeh/antennapod/core/service/playback/PlaybackServiceTaskManager.java +++ b/core/src/main/java/de/danoeh/antennapod/core/service/playback/PlaybackServiceTaskManager.java @@ -397,41 +397,42 @@ public class PlaybackServiceTaskManager { while (timeLeft > 0) { try { Thread.sleep(UPDATE_INTERVAL); - long now = System.currentTimeMillis(); - timeLeft -= now - lastTick; - lastTick = now; - - if(timeLeft < NOTIFICATION_THRESHOLD && !notifiedAlmostExpired) { - Log.d(TAG, "Sleep timer is about to expire"); - if(vibrate) { - Vibrator v = (Vibrator) context.getSystemService(Context.VIBRATOR_SERVICE); - if(v != null) { - v.vibrate(500); - } - } - if(shakeListener == null && shakeToReset) { - shakeListener = new ShakeListener(context, this); - } - postCallback(callback::onSleepTimerAlmostExpired); - notifiedAlmostExpired = true; - } - if (timeLeft <= 0) { - Log.d(TAG, "Sleep timer expired"); - if(shakeListener != null) { - shakeListener.pause(); - shakeListener = null; - } - if (!Thread.currentThread().isInterrupted()) { - postCallback(callback::onSleepTimerExpired); - } else { - Log.d(TAG, "Sleep timer interrupted"); - } - } } catch (InterruptedException e) { Log.d(TAG, "Thread was interrupted while waiting"); e.printStackTrace(); break; } + + long now = System.currentTimeMillis(); + timeLeft -= now - lastTick; + lastTick = now; + + if (timeLeft < NOTIFICATION_THRESHOLD && !notifiedAlmostExpired) { + Log.d(TAG, "Sleep timer is about to expire"); + if (vibrate) { + Vibrator v = (Vibrator) context.getSystemService(Context.VIBRATOR_SERVICE); + if (v != null) { + v.vibrate(500); + } + } + if (shakeListener == null && shakeToReset) { + shakeListener = new ShakeListener(context, this); + } + postCallback(callback::onSleepTimerAlmostExpired); + notifiedAlmostExpired = true; + } + if (timeLeft <= 0) { + Log.d(TAG, "Sleep timer expired"); + if (shakeListener != null) { + shakeListener.pause(); + shakeListener = null; + } + if (!Thread.currentThread().isInterrupted()) { + postCallback(callback::onSleepTimerExpired); + } else { + Log.d(TAG, "Sleep timer interrupted"); + } + } } } diff --git a/core/src/main/java/de/danoeh/antennapod/core/util/playback/PlaybackController.java b/core/src/main/java/de/danoeh/antennapod/core/util/playback/PlaybackController.java index e7f6ad4f1..cb22fbcc9 100644 --- a/core/src/main/java/de/danoeh/antennapod/core/util/playback/PlaybackController.java +++ b/core/src/main/java/de/danoeh/antennapod/core/util/playback/PlaybackController.java @@ -628,10 +628,6 @@ public class PlaybackController { return playbackService != null && playbackService.sleepTimerActive(); } - public boolean sleepTimerNotActive() { - return playbackService != null && !playbackService.sleepTimerActive(); - } - public void disableSleepTimer() { if (playbackService != null) { playbackService.disableSleepTimer(); diff --git a/core/src/main/res/values/strings.xml b/core/src/main/res/values/strings.xml index d2774ac7a..8c6697c4c 100644 --- a/core/src/main/res/values/strings.xml +++ b/core/src/main/res/values/strings.xml @@ -312,6 +312,7 @@ <string name="clear_queue_confirmation_msg">Please confirm that you want to clear the queue of ALL of the episodes in it</string> <string name="sort_old_to_new">Old to new</string> <string name="sort_new_to_old">New to old</string> + <string name="time_left_label">Time left:\u0020</string> <!-- Variable Speed --> <string name="download_plugin_label">Download Plugin</string> @@ -574,12 +575,9 @@ <!-- Sleep timer --> <string name="set_sleeptimer_label">Set sleep timer</string> <string name="disable_sleeptimer_label">Disable sleep timer</string> - <string name="enter_time_here_label">Enter time</string> <string name="sleep_timer_label">Sleep timer</string> - <string name="time_left_label">Time left:\u0020</string> <string name="time_dialog_invalid_input">Invalid input, time has to be an integer</string> - <string name="timer_about_to_expire_label"><b>When timer is about to expire:</b></string> - <string name="shake_to_reset_label">Shake to reset timer</string> + <string name="shake_to_reset_label">Shake to reset</string> <string name="timer_vibration_label">Vibrate</string> <string name="time_seconds">seconds</string> <string name="time_minutes">minutes</string> @@ -598,7 +596,6 @@ </plurals> <string name="auto_enable_label">Auto-enable</string> <string name="sleep_timer_enabled_label">Sleep timer enabled</string> - <string name="sleep_timer_disabled_label">Sleep timer disabled</string> <!-- gpodder.net --> <string name="gpodnet_taglist_header">CATEGORIES</string> |