Compare commits

...
15 changed files with 79 additions and 45 deletions
@@ -135,6 +135,7 @@ data class DeviceSettings(
var sleepTimerLength: Long, // Time in milliseconds var sleepTimerLength: Long, // Time in milliseconds
var disableSleepTimerFadeOut: Boolean, var disableSleepTimerFadeOut: Boolean,
var disableSleepTimerResetFeedback: Boolean, var disableSleepTimerResetFeedback: Boolean,
var enableSleepTimerAlmostDoneChime: Boolean,
var languageCode: String, var languageCode: String,
var downloadUsingCellular: DownloadUsingCellularSetting, var downloadUsingCellular: DownloadUsingCellularSetting,
var streamingUsingCellular: StreamingUsingCellularSetting, var streamingUsingCellular: StreamingUsingCellularSetting,
@@ -163,6 +164,7 @@ data class DeviceSettings(
autoSleepTimerAutoRewindTime = 300000L, // 5 minutes autoSleepTimerAutoRewindTime = 300000L, // 5 minutes
disableSleepTimerFadeOut = false, disableSleepTimerFadeOut = false,
disableSleepTimerResetFeedback = false, disableSleepTimerResetFeedback = false,
enableSleepTimerAlmostDoneChime = false,
languageCode = "en-us", languageCode = "en-us",
downloadUsingCellular = DownloadUsingCellularSetting.ALWAYS, downloadUsingCellular = DownloadUsingCellularSetting.ALWAYS,
streamingUsingCellular = StreamingUsingCellularSetting.ALWAYS, streamingUsingCellular = StreamingUsingCellularSetting.ALWAYS,
@@ -188,9 +190,9 @@ data class DeviceSettings(
@JsonIgnore @JsonIgnore
fun getShakeThresholdGravity() : Float { // Used in ShakeDetector fun getShakeThresholdGravity() : Float { // Used in ShakeDetector
return if (shakeSensitivity == ShakeSensitivitySetting.VERY_HIGH) 1.2f return if (shakeSensitivity == ShakeSensitivitySetting.VERY_HIGH) 1.1f
else if (shakeSensitivity == ShakeSensitivitySetting.HIGH) 1.4f else if (shakeSensitivity == ShakeSensitivitySetting.HIGH) 1.3f
else if (shakeSensitivity == ShakeSensitivitySetting.MEDIUM) 1.6f else if (shakeSensitivity == ShakeSensitivitySetting.MEDIUM) 1.5f
else if (shakeSensitivity == ShakeSensitivitySetting.LOW) 2f else if (shakeSensitivity == ShakeSensitivitySetting.LOW) 2f
else if (shakeSensitivity == ShakeSensitivitySetting.VERY_LOW) 2.7f else if (shakeSensitivity == ShakeSensitivitySetting.VERY_LOW) 2.7f
else { else {
@@ -34,6 +34,7 @@ object DeviceManager {
val serverConnectionConfigId get() = serverConnectionConfig?.id ?: "" val serverConnectionConfigId get() = serverConnectionConfig?.id ?: ""
val serverConnectionConfigName get() = serverConnectionConfig?.name ?: "" val serverConnectionConfigName get() = serverConnectionConfig?.name ?: ""
val serverConnectionConfigString get() = serverConnectionConfig?.name ?: "No server connection"
val serverAddress val serverAddress
get() = serverConnectionConfig?.address ?: "" get() = serverConnectionConfig?.address ?: ""
val serverUserId val serverUserId
@@ -63,6 +64,10 @@ object DeviceManager {
if (deviceData.deviceSettings?.autoSleepTimerAutoRewindTime == null) { if (deviceData.deviceSettings?.autoSleepTimerAutoRewindTime == null) {
deviceData.deviceSettings?.autoSleepTimerAutoRewindTime = 300000L // 5 minutes deviceData.deviceSettings?.autoSleepTimerAutoRewindTime = 300000L // 5 minutes
} }
// Initialize sleep timer almost done chime added in v0.9.81
if (deviceData.deviceSettings?.enableSleepTimerAlmostDoneChime == null) {
deviceData.deviceSettings?.enableSleepTimerAlmostDoneChime = false
}
// Language added in v0.9.69 // Language added in v0.9.69
if (deviceData.deviceSettings?.languageCode == null) { if (deviceData.deviceSettings?.languageCode == null) {
@@ -1,15 +1,20 @@
package com.audiobookshelf.app.managers package com.audiobookshelf.app.managers
import android.content.Context import android.content.Context
import android.media.MediaPlayer
import android.os.* import android.os.*
import android.util.Log import android.util.Log
import com.audiobookshelf.app.R
import com.audiobookshelf.app.device.DeviceManager import com.audiobookshelf.app.device.DeviceManager
import com.audiobookshelf.app.player.PlayerNotificationService import com.audiobookshelf.app.player.PlayerNotificationService
import com.audiobookshelf.app.player.SLEEP_TIMER_WAKE_UP_EXPIRATION import com.audiobookshelf.app.player.SLEEP_TIMER_WAKE_UP_EXPIRATION
import com.audiobookshelf.app.plugins.AbsLogger
import java.util.* import java.util.*
import kotlin.concurrent.schedule import kotlin.concurrent.schedule
import kotlin.math.roundToInt import kotlin.math.roundToInt
const val SLEEP_TIMER_CHIME_SOUND_VOLUME = 0.7f
class SleepTimerManager class SleepTimerManager
constructor(private val playerNotificationService: PlayerNotificationService) { constructor(private val playerNotificationService: PlayerNotificationService) {
private val tag = "SleepTimerManager" private val tag = "SleepTimerManager"
@@ -156,6 +161,10 @@ constructor(private val playerNotificationService: PlayerNotificationService) {
) )
} }
if (sleepTimeSecondsRemaining == 30 && sleepTimerElapsed > 1 && DeviceManager.deviceData.deviceSettings?.enableSleepTimerAlmostDoneChime == true) {
playChimeSound()
}
if (sleepTimeSecondsRemaining <= 0) { if (sleepTimeSecondsRemaining <= 0) {
Log.d(tag, "Sleep Timer Pausing Player on Chapter") Log.d(tag, "Sleep Timer Pausing Player on Chapter")
pause() pause()
@@ -263,6 +272,18 @@ constructor(private val playerNotificationService: PlayerNotificationService) {
} }
} }
/** Plays chime sound */
private fun playChimeSound() {
AbsLogger.info(tag, "playChimeSound: Playing sleep timer chime sound")
val ctx = playerNotificationService.getContext()
val mediaPlayer = MediaPlayer.create(ctx, R.raw.bell)
mediaPlayer.setVolume(SLEEP_TIMER_CHIME_SOUND_VOLUME, SLEEP_TIMER_CHIME_SOUND_VOLUME)
mediaPlayer.start()
mediaPlayer.setOnCompletionListener {
mediaPlayer.release()
}
}
/** /**
* Gets the chapter end time for use in End of Chapter timers. If less than 10 seconds remain in * Gets the chapter end time for use in End of Chapter timers. If less than 10 seconds remain in
* the chapter, then use the next chapter. * the chapter, then use the next chapter.
@@ -136,7 +136,6 @@ class MediaManager(private var apiHandler: ApiHandler, var ctx: Context) {
val serverConnConfig = if (DeviceManager.isConnectedToServer) DeviceManager.serverConnectionConfig else DeviceManager.deviceData.getLastServerConnectionConfig() val serverConnConfig = if (DeviceManager.isConnectedToServer) DeviceManager.serverConnectionConfig else DeviceManager.deviceData.getLastServerConnectionConfig()
if (!DeviceManager.isConnectedToServer || !DeviceManager.checkConnectivity(ctx) || serverConnConfig == null || serverConnConfig.id !== serverConfigIdUsed) { if (!DeviceManager.isConnectedToServer || !DeviceManager.checkConnectivity(ctx) || serverConnConfig == null || serverConnConfig.id !== serverConfigIdUsed) {
Log.d(tag, "Reset caches")
podcastEpisodeLibraryItemMap = mutableMapOf() podcastEpisodeLibraryItemMap = mutableMapOf()
serverLibraries = listOf() serverLibraries = listOf()
serverLibraryItems = mutableListOf() serverLibraryItems = mutableListOf()
@@ -7,7 +7,6 @@ import android.net.Uri
import android.os.Build import android.os.Build
import android.provider.MediaStore import android.provider.MediaStore
import android.support.v4.media.session.MediaControllerCompat import android.support.v4.media.session.MediaControllerCompat
import android.util.Log
import com.audiobookshelf.app.BuildConfig import com.audiobookshelf.app.BuildConfig
import com.audiobookshelf.app.R import com.audiobookshelf.app.R
import com.bumptech.glide.Glide import com.bumptech.glide.Glide
@@ -41,7 +40,6 @@ class AbMediaDescriptionAdapter constructor(private val controller: MediaControl
// Cache the bitmap for the current audiobook so that successive calls to // Cache the bitmap for the current audiobook so that successive calls to
// `getCurrentLargeIcon` don't cause the bitmap to be recreated. // `getCurrentLargeIcon` don't cause the bitmap to be recreated.
currentIconUri = albumArtUri currentIconUri = albumArtUri
Log.d(tag, "ART $currentIconUri")
if (currentIconUri.toString().startsWith("content://")) { if (currentIconUri.toString().startsWith("content://")) {
currentBitmap = if (Build.VERSION.SDK_INT < 28) { currentBitmap = if (Build.VERSION.SDK_INT < 28) {
@@ -8,7 +8,6 @@ import android.util.Log
import android.view.KeyEvent import android.view.KeyEvent
import com.audiobookshelf.app.data.LibraryItemWrapper import com.audiobookshelf.app.data.LibraryItemWrapper
import com.audiobookshelf.app.data.PodcastEpisode import com.audiobookshelf.app.data.PodcastEpisode
import com.audiobookshelf.app.device.DeviceManager
import java.util.* import java.util.*
import kotlin.concurrent.schedule import kotlin.concurrent.schedule
@@ -4,14 +4,11 @@ import android.annotation.SuppressLint
import android.app.* import android.app.*
import android.content.Context import android.content.Context
import android.content.Intent import android.content.Intent
import android.graphics.Bitmap
import android.graphics.Color import android.graphics.Color
import android.graphics.ImageDecoder
import android.hardware.Sensor import android.hardware.Sensor
import android.hardware.SensorManager import android.hardware.SensorManager
import android.net.* import android.net.*
import android.os.* import android.os.*
import android.provider.MediaStore
import android.provider.Settings import android.provider.Settings
import android.support.v4.media.MediaBrowserCompat import android.support.v4.media.MediaBrowserCompat
import android.support.v4.media.MediaDescriptionCompat import android.support.v4.media.MediaDescriptionCompat
@@ -311,19 +308,6 @@ class PlayerNotificationService : MediaBrowserServiceCompat() {
val coverUri = currentPlaybackSession!!.getCoverUri(ctx) val coverUri = currentPlaybackSession!!.getCoverUri(ctx)
var bitmap: Bitmap? = null
// Local covers get bitmap
if (currentPlaybackSession!!.localLibraryItem?.coverContentUrl != null) {
bitmap =
if (Build.VERSION.SDK_INT < 28) {
MediaStore.Images.Media.getBitmap(ctx.contentResolver, coverUri)
} else {
val source: ImageDecoder.Source =
ImageDecoder.createSource(ctx.contentResolver, coverUri)
ImageDecoder.decodeBitmap(source)
}
}
// Fix for local images crashing on Android 11 for specific devices // Fix for local images crashing on Android 11 for specific devices
// https://stackoverflow.com/questions/64186578/android-11-mediastyle-notification-crash/64232958#64232958 // https://stackoverflow.com/questions/64186578/android-11-mediastyle-notification-crash/64232958#64232958
try { try {
@@ -347,8 +331,7 @@ class PlayerNotificationService : MediaBrowserServiceCompat() {
.setExtras(extra) .setExtras(extra)
.setTitle(currentPlaybackSession!!.displayTitle) .setTitle(currentPlaybackSession!!.displayTitle)
bitmap?.let { mediaDescriptionBuilder.setIconBitmap(it) } mediaDescriptionBuilder.setIconUri(coverUri)
?: mediaDescriptionBuilder.setIconUri(coverUri)
return mediaDescriptionBuilder.build() return mediaDescriptionBuilder.build()
} }
@@ -1106,11 +1089,12 @@ class PlayerNotificationService : MediaBrowserServiceCompat() {
// No further calls will be made to other media browsing methods. // No further calls will be made to other media browsing methods.
null null
} else { } else {
Log.d(tag, "Android Auto starting $clientPackageName $clientUid") AbsLogger.info(tag, "onGetRoot: clientPackageName: $clientPackageName, clientUid: $clientUid")
isStarted = true isStarted = true
// Reset cache if no longer connected to server or server changed // Reset cache if no longer connected to server or server changed
if (mediaManager.checkResetServerItems()) { if (mediaManager.checkResetServerItems()) {
AbsLogger.info(tag, "onGetRoot: Reset Android Auto server items cache (${DeviceManager.serverConnectionConfigString})")
forceReloadingAndroidAuto = true forceReloadingAndroidAuto = true
} }
@@ -1135,7 +1119,7 @@ class PlayerNotificationService : MediaBrowserServiceCompat() {
parentMediaId: String, parentMediaId: String,
result: Result<MutableList<MediaBrowserCompat.MediaItem>> result: Result<MutableList<MediaBrowserCompat.MediaItem>>
) { ) {
Log.d(tag, "ON LOAD CHILDREN $parentMediaId") AbsLogger.info(tag, "onLoadChildren: parentMediaId: $parentMediaId (${DeviceManager.serverConnectionConfigString})")
result.detach() result.detach()
@@ -1146,7 +1130,6 @@ class PlayerNotificationService : MediaBrowserServiceCompat() {
} }
if (parentMediaId == DOWNLOADS_ROOT) { // Load downloads if (parentMediaId == DOWNLOADS_ROOT) { // Load downloads
val localBooks = DeviceManager.dbManager.getLocalLibraryItems("book") val localBooks = DeviceManager.dbManager.getLocalLibraryItems("book")
val localPodcasts = DeviceManager.dbManager.getLocalLibraryItems("podcast") val localPodcasts = DeviceManager.dbManager.getLocalLibraryItems("podcast")
val localBrowseItems: MutableList<MediaBrowserCompat.MediaItem> = mutableListOf() val localBrowseItems: MutableList<MediaBrowserCompat.MediaItem> = mutableListOf()
@@ -1243,8 +1226,10 @@ class PlayerNotificationService : MediaBrowserServiceCompat() {
Log.d(tag, "Trying to initialize browseTree.") Log.d(tag, "Trying to initialize browseTree.")
if (!this::browseTree.isInitialized || forceReloadingAndroidAuto) { if (!this::browseTree.isInitialized || forceReloadingAndroidAuto) {
forceReloadingAndroidAuto = false forceReloadingAndroidAuto = false
AbsLogger.info(tag, "onLoadChildren: Loading Android Auto items")
mediaManager.loadAndroidAutoItems { mediaManager.loadAndroidAutoItems {
Log.d(tag, "android auto loaded. Starting browseTree initialize") AbsLogger.info(tag, "onLoadChildren: Loaded Android Auto data, initializing browseTree")
browseTree = browseTree =
BrowseTree( BrowseTree(
this, this,
@@ -1260,15 +1245,21 @@ class PlayerNotificationService : MediaBrowserServiceCompat() {
MediaBrowserCompat.MediaItem.FLAG_BROWSABLE MediaBrowserCompat.MediaItem.FLAG_BROWSABLE
) )
} }
Log.d(tag, "browseTree initialize and android auto loaded")
result.sendResult(children as MutableList<MediaBrowserCompat.MediaItem>?) result.sendResult(children as MutableList<MediaBrowserCompat.MediaItem>?)
firstLoadDone = true firstLoadDone = true
if (mediaManager.serverLibraries.isNotEmpty()) { if (mediaManager.serverLibraries.isNotEmpty()) {
Log.d(tag, "Starting personalization fetch") AbsLogger.info(tag, "onLoadChildren: Android Auto fetching personalized data for all libraries")
mediaManager.populatePersonalizedDataForAllLibraries { notifyChildrenChanged("/") } mediaManager.populatePersonalizedDataForAllLibraries {
AbsLogger.info(tag, "onLoadChildren: Android Auto loaded personalized data for all libraries")
notifyChildrenChanged("/")
}
Log.d(tag, "Initialize inprogress items") AbsLogger.info(tag, "onLoadChildren: Android Auto fetching in progress items")
mediaManager.initializeInProgressItems { notifyChildrenChanged("/") } mediaManager.initializeInProgressItems {
AbsLogger.info(tag, "onLoadChildren: Android Auto loaded in progress items")
notifyChildrenChanged("/")
}
} }
} }
} else { } else {
@@ -1288,7 +1279,8 @@ class PlayerNotificationService : MediaBrowserServiceCompat() {
MediaBrowserCompat.MediaItem.FLAG_BROWSABLE MediaBrowserCompat.MediaItem.FLAG_BROWSABLE
) )
} }
Log.d(tag, "browseTree initialize and android auto loaded")
AbsLogger.info(tag, "onLoadChildren: Android auto data loaded")
result.sendResult(children as MutableList<MediaBrowserCompat.MediaItem>?) result.sendResult(children as MutableList<MediaBrowserCompat.MediaItem>?)
} }
} else if (parentMediaId == LIBRARIES_ROOT || parentMediaId == RECENTLY_ROOT) { } else if (parentMediaId == LIBRARIES_ROOT || parentMediaId == RECENTLY_ROOT) {
@@ -5,6 +5,7 @@ import android.hardware.SensorEvent
import android.hardware.SensorEventListener import android.hardware.SensorEventListener
import android.hardware.SensorManager import android.hardware.SensorManager
import com.audiobookshelf.app.device.DeviceManager import com.audiobookshelf.app.device.DeviceManager
import com.audiobookshelf.app.plugins.AbsLogger
import kotlin.math.sqrt import kotlin.math.sqrt
class ShakeDetector : SensorEventListener { class ShakeDetector : SensorEventListener {
@@ -46,6 +47,7 @@ class ShakeDetector : SensorEventListener {
if (mShakeTimestamp + SHAKE_COUNT_RESET_TIME_MS < now) { if (mShakeTimestamp + SHAKE_COUNT_RESET_TIME_MS < now) {
mShakeCount = 0 mShakeCount = 0
} }
AbsLogger.info("ShakeDetector", "Device shake above threshold ($gForce > $shakeThreshold)")
mShakeTimestamp = now mShakeTimestamp = now
mShakeCount++ mShakeCount++
mListener!!.onShake(mShakeCount) mListener!!.onShake(mShakeCount)
@@ -29,16 +29,16 @@ class AbsLogger : Plugin() {
onLogEmitter = { log:AbsLog -> onLogEmitter = { log:AbsLog ->
notifyListeners("onLog", JSObject(jacksonMapper.writeValueAsString(log))) notifyListeners("onLog", JSObject(jacksonMapper.writeValueAsString(log)))
} }
Log.i("AbsLogger", "Initialize AbsLogger plugin") info("AbsLogger", "load: AbsLogger plugin initialized")
} }
companion object { companion object {
lateinit var onLogEmitter:(log:AbsLog) -> Unit var onLogEmitter:((log:AbsLog) -> Unit)? = null
fun log(level:String, tag:String, message:String) { fun log(level:String, tag:String, message:String) {
val absLog = AbsLog(id = UUID.randomUUID().toString(), tag, level, message, timestamp = System.currentTimeMillis()) val absLog = AbsLog(id = UUID.randomUUID().toString(), tag, level, message, timestamp = System.currentTimeMillis())
DeviceManager.dbManager.saveLog(absLog) DeviceManager.dbManager.saveLog(absLog)
onLogEmitter(absLog) onLogEmitter?.let { it(absLog) }
} }
fun info(tag:String, message:String) { fun info(tag:String, message:String) {
Log.i("AbsLogger", message) Log.i("AbsLogger", message)
Binary file not shown.
+1 -1
View File
@@ -14,7 +14,7 @@ ext {
androidx_core_ktx_version = '1.16.0' androidx_core_ktx_version = '1.16.0'
androidx_media_version = '1.7.0' androidx_media_version = '1.7.0'
exoplayer_version = '2.18.7' exoplayer_version = '2.18.7'
glide_version = '4.11.0' glide_version = '4.16.0'
junit_version = '4.13.2' junit_version = '4.13.2'
kotlin_version = '2.1.0' kotlin_version = '2.1.0'
kotlin_coroutines_version = '1.10.1' kotlin_coroutines_version = '1.10.1'
+1 -4
View File
@@ -7,7 +7,7 @@
<a v-if="showBack" @click="back" class="rounded-full h-10 w-10 flex items-center justify-center mr-2 cursor-pointer"> <a v-if="showBack" @click="back" class="rounded-full h-10 w-10 flex items-center justify-center mr-2 cursor-pointer">
<span class="material-symbols text-3xl text-fg">arrow_back</span> <span class="material-symbols text-3xl text-fg">arrow_back</span>
</a> </a>
<div v-if="user && currentLibrary && socketConnected"> <div v-if="user && currentLibrary">
<div class="pl-1.5 pr-2.5 py-2 bg-bg bg-opacity-30 rounded-md flex items-center" @click="clickShowLibraryModal"> <div class="pl-1.5 pr-2.5 py-2 bg-bg bg-opacity-30 rounded-md flex items-center" @click="clickShowLibraryModal">
<ui-library-icon :icon="currentLibraryIcon" :size="4" font-size="base" /> <ui-library-icon :icon="currentLibraryIcon" :size="4" font-size="base" />
<p class="text-sm leading-4 ml-2 mt-0.5 max-w-24 truncate">{{ currentLibraryName }}</p> <p class="text-sm leading-4 ml-2 mt-0.5 max-w-24 truncate">{{ currentLibraryName }}</p>
@@ -56,9 +56,6 @@ export default {
this.$store.commit('setCastAvailable', val) this.$store.commit('setCastAvailable', val)
} }
}, },
socketConnected() {
return this.$store.state.socketConnected
},
currentLibrary() { currentLibrary() {
return this.$store.getters['libraries/getCurrentLibrary'] return this.$store.getters['libraries/getCurrentLibrary']
}, },
+2 -2
View File
@@ -77,12 +77,12 @@
</div> </div>
<!-- Series sequence --> <!-- Series sequence -->
<div v-if="seriesSequence && showSequence && !isSelectionMode" class="absolute rounded-lg bg-black bg-opacity-90 box-shadow-md z-10" :style="{ top: 0.375 * sizeMultiplier + 'rem', right: 0.375 * sizeMultiplier + 'rem', padding: `${0.1 * sizeMultiplier}rem ${0.25 * sizeMultiplier}rem` }"> <div v-if="seriesSequence && showSequence && !isSelectionMode" class="absolute rounded-lg bg-black/90 text-white box-shadow-md z-10" :style="{ top: 0.375 * sizeMultiplier + 'rem', right: 0.375 * sizeMultiplier + 'rem', padding: `${0.1 * sizeMultiplier}rem ${0.25 * sizeMultiplier}rem` }">
<p :style="{ fontSize: sizeMultiplier * 0.8 + 'rem' }">#{{ seriesSequence }}</p> <p :style="{ fontSize: sizeMultiplier * 0.8 + 'rem' }">#{{ seriesSequence }}</p>
</div> </div>
<!-- Podcast Episode # --> <!-- Podcast Episode # -->
<div v-if="recentEpisodeNumber !== null && !isSelectionMode" class="absolute rounded-lg bg-black bg-opacity-90 box-shadow-md z-10" :style="{ top: 0.375 * sizeMultiplier + 'rem', right: 0.375 * sizeMultiplier + 'rem', padding: `${0.1 * sizeMultiplier}rem ${0.25 * sizeMultiplier}rem` }"> <div v-if="recentEpisodeNumber !== null && !isSelectionMode" class="absolute rounded-lg bg-black/90 box-shadow-md z-10" :style="{ top: 0.375 * sizeMultiplier + 'rem', right: 0.375 * sizeMultiplier + 'rem', padding: `${0.1 * sizeMultiplier}rem ${0.25 * sizeMultiplier}rem` }">
<p class="text-white" :style="{ fontSize: sizeMultiplier * 0.8 + 'rem' }"> <p class="text-white" :style="{ fontSize: sizeMultiplier * 0.8 + 'rem' }">
Episode<span v-if="recentEpisodeNumber"> #{{ recentEpisodeNumber }}</span> Episode<span v-if="recentEpisodeNumber"> #{{ recentEpisodeNumber }}</span>
</p> </p>
+17
View File
@@ -100,6 +100,13 @@
<p class="pl-4">{{ $strings.LabelDisableVibrateOnReset }}</p> <p class="pl-4">{{ $strings.LabelDisableVibrateOnReset }}</p>
<span class="material-symbols text-xl ml-2" @click.stop="showInfo('disableSleepTimerResetFeedback')">info</span> <span class="material-symbols text-xl ml-2" @click.stop="showInfo('disableSleepTimerResetFeedback')">info</span>
</div> </div>
<div class="flex items-center py-3">
<div class="w-10 flex justify-center" @click="toggleSleepTimerAlmostDoneChime">
<ui-toggle-switch v-model="settings.enableSleepTimerAlmostDoneChime" @input="saveSettings" />
</div>
<p class="pl-4">{{ $strings.LabelSleepTimerAlmostDoneChime }}</p>
<span class="material-symbols text-xl ml-2" @click.stop="showInfo('enableSleepTimerAlmostDoneChime')">info</span>
</div>
<div class="flex items-center py-3"> <div class="flex items-center py-3">
<div class="w-10 flex justify-center" @click="toggleAutoSleepTimer"> <div class="w-10 flex justify-center" @click="toggleAutoSleepTimer">
<ui-toggle-switch v-model="settings.autoSleepTimer" @input="saveSettings" /> <ui-toggle-switch v-model="settings.autoSleepTimer" @input="saveSettings" />
@@ -207,6 +214,7 @@ export default {
sleepTimerLength: 900000, // 15 minutes sleepTimerLength: 900000, // 15 minutes
disableSleepTimerFadeOut: false, disableSleepTimerFadeOut: false,
disableSleepTimerResetFeedback: false, disableSleepTimerResetFeedback: false,
enableSleepTimerAlmostDoneChime: false,
autoSleepTimerAutoRewind: false, autoSleepTimerAutoRewind: false,
autoSleepTimerAutoRewindTime: 300000, // 5 minutes autoSleepTimerAutoRewindTime: 300000, // 5 minutes
languageCode: 'en-us', languageCode: 'en-us',
@@ -234,6 +242,10 @@ export default {
name: this.$strings.LabelDisableVibrateOnReset, name: this.$strings.LabelDisableVibrateOnReset,
message: this.$strings.LabelDisableVibrateOnResetHelp message: this.$strings.LabelDisableVibrateOnResetHelp
}, },
enableSleepTimerAlmostDoneChime: {
name: this.$strings.LabelSleepTimerAlmostDoneChime,
message: this.$strings.LabelSleepTimerAlmostDoneChimeHelp
},
autoSleepTimerAutoRewind: { autoSleepTimerAutoRewind: {
name: this.$strings.LabelAutoSleepTimerAutoRewind, name: this.$strings.LabelAutoSleepTimerAutoRewind,
message: this.$strings.LabelAutoSleepTimerAutoRewindHelp message: this.$strings.LabelAutoSleepTimerAutoRewindHelp
@@ -549,6 +561,10 @@ export default {
this.settings.disableSleepTimerResetFeedback = !this.settings.disableSleepTimerResetFeedback this.settings.disableSleepTimerResetFeedback = !this.settings.disableSleepTimerResetFeedback
this.saveSettings() this.saveSettings()
}, },
toggleSleepTimerAlmostDoneChime() {
this.settings.enableSleepTimerAlmostDoneChime = !this.settings.enableSleepTimerAlmostDoneChime
this.saveSettings()
},
toggleDisableAutoRewind() { toggleDisableAutoRewind() {
this.settings.disableAutoRewind = !this.settings.disableAutoRewind this.settings.disableAutoRewind = !this.settings.disableAutoRewind
this.saveSettings() this.saveSettings()
@@ -620,6 +636,7 @@ export default {
this.settings.sleepTimerLength = !isNaN(deviceSettings.sleepTimerLength) ? deviceSettings.sleepTimerLength : 900000 // 15 minutes this.settings.sleepTimerLength = !isNaN(deviceSettings.sleepTimerLength) ? deviceSettings.sleepTimerLength : 900000 // 15 minutes
this.settings.disableSleepTimerFadeOut = !!deviceSettings.disableSleepTimerFadeOut this.settings.disableSleepTimerFadeOut = !!deviceSettings.disableSleepTimerFadeOut
this.settings.disableSleepTimerResetFeedback = !!deviceSettings.disableSleepTimerResetFeedback this.settings.disableSleepTimerResetFeedback = !!deviceSettings.disableSleepTimerResetFeedback
this.settings.enableSleepTimerAlmostDoneChime = !!deviceSettings.enableSleepTimerAlmostDoneChime
this.settings.autoSleepTimerAutoRewind = !!deviceSettings.autoSleepTimerAutoRewind this.settings.autoSleepTimerAutoRewind = !!deviceSettings.autoSleepTimerAutoRewind
this.settings.autoSleepTimerAutoRewindTime = !isNaN(deviceSettings.autoSleepTimerAutoRewindTime) ? deviceSettings.autoSleepTimerAutoRewindTime : 300000 // 5 minutes this.settings.autoSleepTimerAutoRewindTime = !isNaN(deviceSettings.autoSleepTimerAutoRewindTime) ? deviceSettings.autoSleepTimerAutoRewindTime : 300000 // 5 minutes
+2
View File
@@ -241,6 +241,8 @@
"LabelShowAll": "Show All", "LabelShowAll": "Show All",
"LabelSize": "Size", "LabelSize": "Size",
"LabelSleepTimer": "Sleep timer", "LabelSleepTimer": "Sleep timer",
"LabelSleepTimerAlmostDoneChime": "Play a chime when almost finished",
"LabelSleepTimerAlmostDoneChimeHelp": "Play a chime when the sleep timer has 30 seconds remaining",
"LabelStart": "Start", "LabelStart": "Start",
"LabelStartTime": "Start time", "LabelStartTime": "Start time",
"LabelStatsBestDay": "Best Day", "LabelStatsBestDay": "Best Day",