diff --git a/app/src/main/kotlin/org/akanework/gramophone/logic/GramophoneExtensions.kt b/app/src/main/kotlin/org/akanework/gramophone/logic/GramophoneExtensions.kt
index ce7fd8ace..55a6c0059 100644
--- a/app/src/main/kotlin/org/akanework/gramophone/logic/GramophoneExtensions.kt
+++ b/app/src/main/kotlin/org/akanework/gramophone/logic/GramophoneExtensions.kt
@@ -164,13 +164,17 @@ fun View.fadInAnimation(duration: Long = 300, completion: (() -> Unit)? = null)
inline fun Int.dpToPx(context: Context): Int =
(this.toFloat() * context.resources.displayMetrics.density).toInt()
-fun MediaController.getTimer(): Int =
+fun MediaController.getTimer(): Int? =
sendCustomCommand(
SessionCommand(SERVICE_QUERY_TIMER, Bundle.EMPTY),
Bundle.EMPTY
- ).get().extras.getInt("duration")
+ ).get().extras.run {
+ if (containsKey("duration"))
+ getInt("duration")
+ else null
+ }
-fun MediaController.hasTimer(): Boolean = getTimer() > 0
+fun MediaController.hasTimer(): Boolean = getTimer() != null
fun MediaController.setTimer(value: Int) {
sendCustomCommand(
SessionCommand(SERVICE_SET_TIMER, Bundle.EMPTY).apply {
diff --git a/app/src/main/kotlin/org/akanework/gramophone/logic/GramophonePlaybackService.kt b/app/src/main/kotlin/org/akanework/gramophone/logic/GramophonePlaybackService.kt
index ff02a5068..eb0d0a56b 100644
--- a/app/src/main/kotlin/org/akanework/gramophone/logic/GramophonePlaybackService.kt
+++ b/app/src/main/kotlin/org/akanework/gramophone/logic/GramophonePlaybackService.kt
@@ -140,14 +140,14 @@ class GramophonePlaybackService : MediaLibraryService(), MediaSessionService.Lis
private val timer: Runnable = Runnable {
controller!!.pause()
- timerDuration = 0
+ timerDuration = null
}
- private var timerDuration = 0
+ private var timerDuration: Long? = null
set(value) {
field = value
- if (value > 0) {
- handler.postDelayed(timer, value.toLong())
+ if (value != null && value > 0) {
+ handler.postDelayed(timer, value - System.currentTimeMillis())
} else {
handler.removeCallbacks(timer)
}
@@ -437,13 +437,17 @@ class GramophonePlaybackService : MediaLibraryService(), MediaSessionService.Lis
SERVICE_SET_TIMER -> {
// 0 = clear timer
- timerDuration = customCommand.customExtras.getInt("duration")
+ customCommand.customExtras.getInt("duration").let {
+ timerDuration = if (it > 0) System.currentTimeMillis() + it else null
+ }
SessionResult(SessionResult.RESULT_SUCCESS)
}
SERVICE_QUERY_TIMER -> {
SessionResult(SessionResult.RESULT_SUCCESS).also {
- it.extras.putInt("duration", timerDuration)
+ timerDuration?.let { td ->
+ it.extras.putInt("duration", (td - System.currentTimeMillis()).toInt())
+ }
}
}
diff --git a/app/src/main/kotlin/org/akanework/gramophone/ui/components/FullBottomSheet.kt b/app/src/main/kotlin/org/akanework/gramophone/ui/components/FullBottomSheet.kt
index b81ffbdfe..355d09e68 100644
--- a/app/src/main/kotlin/org/akanework/gramophone/ui/components/FullBottomSheet.kt
+++ b/app/src/main/kotlin/org/akanework/gramophone/ui/components/FullBottomSheet.kt
@@ -8,6 +8,7 @@ import android.content.res.ColorStateList
import android.graphics.Bitmap
import android.graphics.drawable.BitmapDrawable
import android.graphics.drawable.TransitionDrawable
+import android.text.format.DateFormat
import android.util.AttributeSet
import android.util.Size
import android.view.Gravity
@@ -20,6 +21,7 @@ import android.widget.ImageView
import android.widget.SeekBar
import android.widget.TextView
import androidx.appcompat.content.res.AppCompatResources
+import androidx.appcompat.widget.TooltipCompat
import androidx.constraintlayout.widget.ConstraintLayout
import androidx.core.graphics.Insets
import androidx.core.graphics.TypefaceCompat
@@ -74,7 +76,6 @@ import org.akanework.gramophone.logic.getTimer
import org.akanework.gramophone.logic.hasImagePermission
import org.akanework.gramophone.logic.hasScopedStorageV1
import org.akanework.gramophone.logic.hasScopedStorageWithMediaTypes
-import org.akanework.gramophone.logic.hasTimer
import org.akanework.gramophone.logic.playOrPause
import org.akanework.gramophone.logic.setTextAnimation
import org.akanework.gramophone.logic.setTimer
@@ -257,9 +258,7 @@ class FullBottomSheet(context: Context, attrs: AttributeSet?, defStyleAttr: Int,
prefs.registerOnSharedPreferenceChangeListener(this)
activity.controllerViewModel.customCommandListeners.addCallback(activity.lifecycle) { _, command, _ ->
when (command.customAction) {
- GramophonePlaybackService.SERVICE_TIMER_CHANGED -> {
- bottomSheetTimerButton.isChecked = instance?.hasTimer() == true
- }
+ GramophonePlaybackService.SERVICE_TIMER_CHANGED -> updateTimer()
GramophonePlaybackService.SERVICE_GET_LYRICS -> {
val parsedLyrics = instance?.getLyrics()
@@ -335,9 +334,6 @@ class FullBottomSheet(context: Context, attrs: AttributeSet?, defStyleAttr: Int,
val destinationTime: Int = picker.hour * 1000 * 3600 + picker.minute * 1000 * 60
instance?.setTimer(destinationTime)
}
- picker.addOnDismissListener {
- bottomSheetTimerButton.isChecked = instance?.hasTimer() == true
- }
picker.show(activity.supportFragmentManager, "timer")
}
@@ -460,7 +456,7 @@ class FullBottomSheet(context: Context, attrs: AttributeSet?, defStyleAttr: Int,
activity.controllerViewModel.addControllerCallback(activity.lifecycle) { _, _ ->
firstTime = true
instance?.addListener(this@FullBottomSheet)
- bottomSheetTimerButton.isChecked = instance?.hasTimer() == true
+ updateTimer()
onRepeatModeChanged(instance?.repeatMode ?: Player.REPEAT_MODE_OFF)
onShuffleModeEnabledChanged(instance?.shuffleModeEnabled ?: false)
onPlaybackStateChanged(instance?.playbackState ?: Player.STATE_IDLE)
@@ -483,6 +479,16 @@ class FullBottomSheet(context: Context, attrs: AttributeSet?, defStyleAttr: Int,
}
}
+ private fun updateTimer() {
+ val t = instance?.getTimer()
+ bottomSheetTimerButton.isChecked = t != null
+ TooltipCompat.setTooltipText(bottomSheetTimerButton,
+ if (t != null) context.getString(R.string.timer_expiry,
+ DateFormat.getTimeFormat(context).format(System.currentTimeMillis() + t)
+ ) else context.getString(R.string.timer)
+ )
+ }
+
override fun onSharedPreferenceChanged(sharedPreferences: SharedPreferences?, key: String?) {
if (key == "color_accuracy" || key == "content_based_color") {
if (DynamicColors.isDynamicColorAvailable() &&
diff --git a/app/src/main/res/layout-land/full_player.xml b/app/src/main/res/layout-land/full_player.xml
index 7d3f55f82..db93910b8 100644
--- a/app/src/main/res/layout-land/full_player.xml
+++ b/app/src/main/res/layout-land/full_player.xml
@@ -349,6 +349,7 @@
android:insetRight="0dp"
android:insetBottom="0dp"
android:saveEnabled="false"
+ app:toggleCheckedStateOnClick="false"
app:icon="@drawable/sl_check_timer"
app:iconGravity="textStart"
app:iconPadding="0dp"
diff --git a/app/src/main/res/layout/full_player.xml b/app/src/main/res/layout/full_player.xml
index 7fcac0b6f..e1262401c 100644
--- a/app/src/main/res/layout/full_player.xml
+++ b/app/src/main/res/layout/full_player.xml
@@ -356,6 +356,7 @@
android:insetBottom="0dp"
android:saveEnabled="false"
android:tooltipText="@string/timer"
+ app:toggleCheckedStateOnClick="false"
app:icon="@drawable/sl_check_timer"
app:iconGravity="textStart"
app:iconPadding="0dp"
diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml
index 9e73d9cdd..375400c6a 100644
--- a/app/src/main/res/values/strings.xml
+++ b/app/src/main/res/values/strings.xml
@@ -183,4 +183,5 @@
Click here to open the app and continue playback
Playback failed to resume
Release date
+ Sleep timer will pause music at %s