mirror of
https://github.com/advplyr/audiobookshelf-app.git
synced 2026-08-27 22:04:08 +02:00
Merge pull request #1508 from complacentsee/ios_sleep_fadeout
IOS: Add support for fading out on sleep timer end
This commit is contained in:
@@ -14,7 +14,7 @@ class AppDelegate: UIResponder, UIApplicationDelegate {
|
|||||||
// Override point for customization after application launch.
|
// Override point for customization after application launch.
|
||||||
|
|
||||||
let configuration = Realm.Configuration(
|
let configuration = Realm.Configuration(
|
||||||
schemaVersion: 18,
|
schemaVersion: 19,
|
||||||
migrationBlock: { [weak self] migration, oldSchemaVersion in
|
migrationBlock: { [weak self] migration, oldSchemaVersion in
|
||||||
if (oldSchemaVersion < 1) {
|
if (oldSchemaVersion < 1) {
|
||||||
self?.logger.log("Realm schema version was \(oldSchemaVersion)")
|
self?.logger.log("Realm schema version was \(oldSchemaVersion)")
|
||||||
@@ -61,6 +61,12 @@ class AppDelegate: UIResponder, UIApplicationDelegate {
|
|||||||
newObject?["streamingUsingCellular"] = "ALWAYS"
|
newObject?["streamingUsingCellular"] = "ALWAYS"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (oldSchemaVersion < 18) {
|
||||||
|
self?.logger.log("Realm schema version was \(oldSchemaVersion)... Adding disableSleepTimerFadeOut settings")
|
||||||
|
migration.enumerateObjects(ofType: PlayerSettings.className()) { oldObject, newObject in
|
||||||
|
newObject?["disableSleepTimerFadeOut"] = false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -246,6 +246,7 @@ public class AbsDatabase: CAPPlugin {
|
|||||||
let languageCode = call.getString("languageCode") ?? "en-us"
|
let languageCode = call.getString("languageCode") ?? "en-us"
|
||||||
let downloadUsingCellular = call.getString("downloadUsingCellular") ?? "ALWAYS"
|
let downloadUsingCellular = call.getString("downloadUsingCellular") ?? "ALWAYS"
|
||||||
let streamingUsingCellular = call.getString("streamingUsingCellular") ?? "ALWAYS"
|
let streamingUsingCellular = call.getString("streamingUsingCellular") ?? "ALWAYS"
|
||||||
|
let disableSleepTimerFadeOut = call.getBool("disableSleepTimerFadeOut") ?? false
|
||||||
let settings = DeviceSettings()
|
let settings = DeviceSettings()
|
||||||
settings.disableAutoRewind = disableAutoRewind
|
settings.disableAutoRewind = disableAutoRewind
|
||||||
settings.enableAltView = enableAltView
|
settings.enableAltView = enableAltView
|
||||||
@@ -257,6 +258,7 @@ public class AbsDatabase: CAPPlugin {
|
|||||||
settings.languageCode = languageCode
|
settings.languageCode = languageCode
|
||||||
settings.downloadUsingCellular = downloadUsingCellular
|
settings.downloadUsingCellular = downloadUsingCellular
|
||||||
settings.streamingUsingCellular = streamingUsingCellular
|
settings.streamingUsingCellular = streamingUsingCellular
|
||||||
|
settings.disableSleepTimerFadeOut = disableSleepTimerFadeOut
|
||||||
|
|
||||||
Database.shared.setDeviceSettings(deviceSettings: settings)
|
Database.shared.setDeviceSettings(deviceSettings: settings)
|
||||||
|
|
||||||
|
|||||||
@@ -19,6 +19,7 @@ class DeviceSettings: Object {
|
|||||||
@Persisted var languageCode: String = "en-us"
|
@Persisted var languageCode: String = "en-us"
|
||||||
@Persisted var downloadUsingCellular: String = "ALWAYS"
|
@Persisted var downloadUsingCellular: String = "ALWAYS"
|
||||||
@Persisted var streamingUsingCellular: String = "ALWAYS"
|
@Persisted var streamingUsingCellular: String = "ALWAYS"
|
||||||
|
@Persisted var disableSleepTimerFadeOut: Bool = false
|
||||||
}
|
}
|
||||||
|
|
||||||
func getDefaultDeviceSettings() -> DeviceSettings {
|
func getDefaultDeviceSettings() -> DeviceSettings {
|
||||||
@@ -36,6 +37,7 @@ func deviceSettingsToJSON(settings: DeviceSettings) -> Dictionary<String, Any> {
|
|||||||
"hapticFeedback": settings.hapticFeedback,
|
"hapticFeedback": settings.hapticFeedback,
|
||||||
"languageCode": settings.languageCode,
|
"languageCode": settings.languageCode,
|
||||||
"downloadUsingCellular": settings.downloadUsingCellular,
|
"downloadUsingCellular": settings.downloadUsingCellular,
|
||||||
"streamingUsingCellular": settings.streamingUsingCellular
|
"streamingUsingCellular": settings.streamingUsingCellular,
|
||||||
|
"disableSleepTimerFadeOut": settings.disableSleepTimerFadeOut
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -366,6 +366,56 @@ class AudioPlayer: NSObject {
|
|||||||
updateNowPlaying()
|
updateNowPlaying()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public func startFadeOut() {
|
||||||
|
guard self.isInitialized() else { return }
|
||||||
|
guard let currentTime = self.getCurrentTime() else { return }
|
||||||
|
logger.log("fadeOut: Fading out playback")
|
||||||
|
|
||||||
|
// Define fade parameters.
|
||||||
|
let fadeDuration: Float = 60.0 // total fade duration in seconds
|
||||||
|
let interval: Float = 1.0 // timer interval in seconds
|
||||||
|
|
||||||
|
// Get the current volume.
|
||||||
|
let initialVolume = self.audioPlayer.volume
|
||||||
|
let targetVolume: Float = 0.0
|
||||||
|
|
||||||
|
// If the current volume is already at or below zero, just pause.
|
||||||
|
if initialVolume <= targetVolume {
|
||||||
|
self.pause()
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// Calculate the volume change per timer tick.
|
||||||
|
// (targetVolume - initialVolume) is negative since target < initial.
|
||||||
|
let step = (targetVolume - initialVolume) * interval / fadeDuration
|
||||||
|
|
||||||
|
// Schedule a timer on the main queue to adjust the volume.
|
||||||
|
DispatchQueue.runOnMainQueue { [weak self] in
|
||||||
|
var timer = Timer.scheduledTimer(withTimeInterval: TimeInterval(interval), repeats: true) { t in
|
||||||
|
guard let self = self else {
|
||||||
|
t.invalidate()
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// Calculate the new volume.
|
||||||
|
let newVolume = self.audioPlayer.volume + step
|
||||||
|
|
||||||
|
// Check if the next step would go below zero.
|
||||||
|
if newVolume > targetVolume {
|
||||||
|
self.audioPlayer.volume = newVolume
|
||||||
|
} else {
|
||||||
|
// Ensure volume is exactly zero and end fade.
|
||||||
|
self.audioPlayer.volume = targetVolume
|
||||||
|
t.invalidate()
|
||||||
|
self.logger.log("Fadeout: Fade complete, pausing playback")
|
||||||
|
self.pause()
|
||||||
|
self.audioPlayer.volume = initialVolume
|
||||||
|
self.seek(currentTime, from: "fadeOut")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public func seek(_ to: Double, from: String) {
|
public func seek(_ to: Double, from: String) {
|
||||||
logger.log("SEEK: Seek to \(to) from \(from)")
|
logger.log("SEEK: Seek to \(to) from \(from)")
|
||||||
|
|
||||||
|
|||||||
@@ -126,6 +126,10 @@ extension AudioPlayer {
|
|||||||
sleepTimeRemaining -= 1
|
sleepTimeRemaining -= 1
|
||||||
self.sleepTimeRemaining = sleepTimeRemaining
|
self.sleepTimeRemaining = sleepTimeRemaining
|
||||||
|
|
||||||
|
if sleepTimeRemaining == 60 && self.isSleepTimerFadeOutEnabled() {
|
||||||
|
self.startFadeOut()
|
||||||
|
}
|
||||||
|
|
||||||
// Handle the sleep if the timer has expired
|
// Handle the sleep if the timer has expired
|
||||||
if sleepTimeRemaining <= 0 {
|
if sleepTimeRemaining <= 0 {
|
||||||
self.handleSleepEnd()
|
self.handleSleepEnd()
|
||||||
@@ -155,4 +159,8 @@ extension AudioPlayer {
|
|||||||
return self.sleepTimeChapterStopAt != nil
|
return self.sleepTimeChapterStopAt != nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private func isSleepTimerFadeOutEnabled() -> Bool {
|
||||||
|
let deviceSettings = Database.shared.getDeviceSettings()
|
||||||
|
return !deviceSettings.disableSleepTimerFadeOut
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -84,6 +84,7 @@
|
|||||||
<ui-text-input :value="shakeSensitivityOption" readonly append-icon="expand_more" style="width: 145px; max-width: 145px" />
|
<ui-text-input :value="shakeSensitivityOption" readonly append-icon="expand_more" style="width: 145px; max-width: 145px" />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
</template>
|
||||||
<div class="flex items-center py-3">
|
<div class="flex items-center py-3">
|
||||||
<div class="w-10 flex justify-center" @click="toggleDisableSleepTimerFadeOut">
|
<div class="w-10 flex justify-center" @click="toggleDisableSleepTimerFadeOut">
|
||||||
<ui-toggle-switch v-model="settings.disableSleepTimerFadeOut" @input="saveSettings" />
|
<ui-toggle-switch v-model="settings.disableSleepTimerFadeOut" @input="saveSettings" />
|
||||||
@@ -91,6 +92,7 @@
|
|||||||
<p class="pl-4">{{ $strings.LabelDisableAudioFadeOut }}</p>
|
<p class="pl-4">{{ $strings.LabelDisableAudioFadeOut }}</p>
|
||||||
<span class="material-icons-outlined ml-2" @click.stop="showInfo('disableSleepTimerFadeOut')">info</span>
|
<span class="material-icons-outlined ml-2" @click.stop="showInfo('disableSleepTimerFadeOut')">info</span>
|
||||||
</div>
|
</div>
|
||||||
|
<template v-if="!isiOS">
|
||||||
<div class="flex items-center py-3">
|
<div class="flex items-center py-3">
|
||||||
<div class="w-10 flex justify-center" @click="toggleDisableSleepTimerResetFeedback">
|
<div class="w-10 flex justify-center" @click="toggleDisableSleepTimerResetFeedback">
|
||||||
<ui-toggle-switch v-model="settings.disableSleepTimerResetFeedback" @input="saveSettings" />
|
<ui-toggle-switch v-model="settings.disableSleepTimerResetFeedback" @input="saveSettings" />
|
||||||
|
|||||||
Reference in New Issue
Block a user