settings: add option to clear state
Add an option to clear the currently saved playback state. This does not clear playback entirely, but rather remove the saved state so that it's not restored on the next startup. This is generally the cleanest solution compared to allowing state restore to be toggled, which opens up a bunch of race conditions. Resolves #107.
This commit is contained in:
parent
86a1815b1f
commit
6381815fd9
9 changed files with 36 additions and 10 deletions
|
@ -31,6 +31,11 @@ import org.oxycblt.auxio.util.androidActivityViewModels
|
||||||
import org.oxycblt.auxio.util.collectImmediately
|
import org.oxycblt.auxio.util.collectImmediately
|
||||||
import org.oxycblt.auxio.util.formatDuration
|
import org.oxycblt.auxio.util.formatDuration
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A dialog displayed when "View properties" is selected on a song, showing more information about
|
||||||
|
* the properties of the audio file itself.
|
||||||
|
* @author OxygenCobalt
|
||||||
|
*/
|
||||||
class SongDetailDialog : ViewBindingDialogFragment<DialogSongDetailBinding>() {
|
class SongDetailDialog : ViewBindingDialogFragment<DialogSongDetailBinding>() {
|
||||||
private val detailModel: DetailViewModel by androidActivityViewModels()
|
private val detailModel: DetailViewModel by androidActivityViewModels()
|
||||||
private val args: SongDetailDialogArgs by navArgs()
|
private val args: SongDetailDialogArgs by navArgs()
|
||||||
|
|
|
@ -282,6 +282,14 @@ class PlaybackViewModel(application: Application) :
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** Wipe the saved playback state (if any). */
|
||||||
|
fun wipePlaybackState(onDone: () -> Unit) {
|
||||||
|
viewModelScope.launch {
|
||||||
|
playbackManager.wipeState(PlaybackStateDatabase.getInstance(application))
|
||||||
|
onDone()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Force restore the last [PlaybackStateManager] saved state, regardless of if a library exists
|
* Force restore the last [PlaybackStateManager] saved state, regardless of if a library exists
|
||||||
* or not. [onDone] will be called with true if it was successfully done, or false if there was
|
* or not. [onDone] will be called with true if it was successfully done, or false if there was
|
||||||
|
|
|
@ -186,19 +186,17 @@ class PlaybackStateDatabase private constructor(context: Context) :
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Clear the previously written [SavedState] and write a new one. */
|
/** Clear the previously written [SavedState] and write a new one. */
|
||||||
fun write(state: SavedState) {
|
fun write(state: SavedState?) {
|
||||||
requireBackgroundThread()
|
requireBackgroundThread()
|
||||||
|
|
||||||
val song = state.queue.getOrNull(state.index)
|
if (state != null && state.index in state.queue.indices) {
|
||||||
|
|
||||||
if (song != null) {
|
|
||||||
val rawState =
|
val rawState =
|
||||||
RawState(
|
RawState(
|
||||||
index = state.index,
|
index = state.index,
|
||||||
positionMs = state.positionMs,
|
positionMs = state.positionMs,
|
||||||
repeatMode = state.repeatMode,
|
repeatMode = state.repeatMode,
|
||||||
isShuffled = state.isShuffled,
|
isShuffled = state.isShuffled,
|
||||||
songId = song.id,
|
songId = state.queue[state.index].id,
|
||||||
parentId = state.parent?.id,
|
parentId = state.parent?.id,
|
||||||
playbackMode =
|
playbackMode =
|
||||||
when (state.parent) {
|
when (state.parent) {
|
||||||
|
|
|
@ -388,12 +388,15 @@ class PlaybackStateManager private constructor() {
|
||||||
/** Save the current state to the [database]. */
|
/** Save the current state to the [database]. */
|
||||||
suspend fun saveState(database: PlaybackStateDatabase) {
|
suspend fun saveState(database: PlaybackStateDatabase) {
|
||||||
logD("Saving state to DB")
|
logD("Saving state to DB")
|
||||||
|
|
||||||
val state = synchronized(this) { makeStateImpl() }
|
val state = synchronized(this) { makeStateImpl() }
|
||||||
|
|
||||||
withContext(Dispatchers.IO) { database.write(state) }
|
withContext(Dispatchers.IO) { database.write(state) }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
suspend fun wipeState(database: PlaybackStateDatabase) {
|
||||||
|
logD("Wiping state")
|
||||||
|
withContext(Dispatchers.IO) { database.write(null) }
|
||||||
|
}
|
||||||
|
|
||||||
/** Sanitize the state with [newLibrary]. */
|
/** Sanitize the state with [newLibrary]. */
|
||||||
@Synchronized
|
@Synchronized
|
||||||
fun sanitize(newLibrary: MusicStore.Library) {
|
fun sanitize(newLibrary: MusicStore.Library) {
|
||||||
|
|
|
@ -49,8 +49,6 @@ import org.oxycblt.auxio.util.systemBarInsetsCompat
|
||||||
/**
|
/**
|
||||||
* The actual fragment containing the settings menu. Inherits [PreferenceFragmentCompat].
|
* The actual fragment containing the settings menu. Inherits [PreferenceFragmentCompat].
|
||||||
* @author OxygenCobalt
|
* @author OxygenCobalt
|
||||||
*
|
|
||||||
* TODO: Add option to not restore state
|
|
||||||
*/
|
*/
|
||||||
@Suppress("UNUSED")
|
@Suppress("UNUSED")
|
||||||
class SettingsListFragment : PreferenceFragmentCompat() {
|
class SettingsListFragment : PreferenceFragmentCompat() {
|
||||||
|
@ -120,6 +118,9 @@ class SettingsListFragment : PreferenceFragmentCompat() {
|
||||||
getString(R.string.set_key_save_state) -> {
|
getString(R.string.set_key_save_state) -> {
|
||||||
playbackModel.savePlaybackState { context?.showToast(R.string.lbl_state_saved) }
|
playbackModel.savePlaybackState { context?.showToast(R.string.lbl_state_saved) }
|
||||||
}
|
}
|
||||||
|
getString(R.string.set_key_wipe_state) -> {
|
||||||
|
playbackModel.wipePlaybackState { context?.showToast(R.string.lbl_state_wiped) }
|
||||||
|
}
|
||||||
getString(R.string.set_key_restore_state) ->
|
getString(R.string.set_key_restore_state) ->
|
||||||
playbackModel.tryRestorePlaybackState { restored ->
|
playbackModel.tryRestorePlaybackState { restored ->
|
||||||
if (restored) {
|
if (restored) {
|
||||||
|
|
|
@ -24,6 +24,7 @@
|
||||||
<string name="set_key_repeat_pause" translatable="false">KEY_LOOP_PAUSE</string>
|
<string name="set_key_repeat_pause" translatable="false">KEY_LOOP_PAUSE</string>
|
||||||
|
|
||||||
<string name="set_key_save_state" translatable="false">auxio_save_state</string>
|
<string name="set_key_save_state" translatable="false">auxio_save_state</string>
|
||||||
|
<string name="set_key_wipe_state" translatable="false">auxio_wipe_state</string>
|
||||||
<string name="set_key_restore_state" translatable="false">auxio_restore_state</string>
|
<string name="set_key_restore_state" translatable="false">auxio_restore_state</string>
|
||||||
<string name="set_key_reindex" translatable="false">auxio_reindex</string>
|
<string name="set_key_reindex" translatable="false">auxio_reindex</string>
|
||||||
<string name="set_key_music_dirs" translatable="false">auxio_music_dirs</string>
|
<string name="set_key_music_dirs" translatable="false">auxio_music_dirs</string>
|
||||||
|
|
|
@ -102,6 +102,8 @@
|
||||||
<!-- Referring to playback state -->
|
<!-- Referring to playback state -->
|
||||||
<string name="lbl_state_saved">State saved</string>
|
<string name="lbl_state_saved">State saved</string>
|
||||||
<!-- Referring to playback state -->
|
<!-- Referring to playback state -->
|
||||||
|
<string name="lbl_state_wiped">State cleared</string>
|
||||||
|
<!-- Referring to playback state -->
|
||||||
<string name="lbl_state_restored">State restored</string>
|
<string name="lbl_state_restored">State restored</string>
|
||||||
|
|
||||||
<!-- Limit to 10 characters -->
|
<!-- Limit to 10 characters -->
|
||||||
|
@ -181,6 +183,8 @@
|
||||||
<string name="set_content">Content</string>
|
<string name="set_content">Content</string>
|
||||||
<string name="set_save">Save playback state</string>
|
<string name="set_save">Save playback state</string>
|
||||||
<string name="set_save_desc">Save the current playback state now</string>
|
<string name="set_save_desc">Save the current playback state now</string>
|
||||||
|
<string name="set_wipe">Clear playback state</string>
|
||||||
|
<string name="set_wipe_desc">Wipe the previously saved playback state (if any)</string>
|
||||||
<string name="set_restore">Restore playback state</string>
|
<string name="set_restore">Restore playback state</string>
|
||||||
<string name="set_restore_desc">Restore the previously saved playback state (if any)</string>
|
<string name="set_restore_desc">Restore the previously saved playback state (if any)</string>
|
||||||
<string name="set_reindex">Reload music</string>
|
<string name="set_reindex">Reload music</string>
|
||||||
|
|
|
@ -128,6 +128,11 @@
|
||||||
app:summary="@string/set_save_desc"
|
app:summary="@string/set_save_desc"
|
||||||
app:title="@string/set_save" />
|
app:title="@string/set_save" />
|
||||||
|
|
||||||
|
<Preference
|
||||||
|
app:key="@string/set_key_wipe_state"
|
||||||
|
app:title="@string/set_wipe"
|
||||||
|
app:summary="@string/set_wipe_desc" />
|
||||||
|
|
||||||
<Preference
|
<Preference
|
||||||
app:key="@string/set_key_restore_state"
|
app:key="@string/set_key_restore_state"
|
||||||
app:summary="@string/set_restore_desc"
|
app:summary="@string/set_restore_desc"
|
||||||
|
|
|
@ -51,7 +51,8 @@ a regression introduced by Google in that version. If this issue appears in anot
|
||||||
**There should be one artist, but instead I get a bunch of "Artist & Collaborator" artists:** This likely means your tags are wrong. By default, Auxio will use the
|
**There should be one artist, but instead I get a bunch of "Artist & Collaborator" artists:** This likely means your tags are wrong. By default, Auxio will use the
|
||||||
"album artist" tag for grouping if present, falling back to the "artist" tag otherwise. If your music does not have such a field, it will result in fragmented artists.
|
"album artist" tag for grouping if present, falling back to the "artist" tag otherwise. If your music does not have such a field, it will result in fragmented artists.
|
||||||
The reason why Auxio does not simply parse for separators and then extract artists that way is that it risks mangling artists that don't actually have collaborators,
|
The reason why Auxio does not simply parse for separators and then extract artists that way is that it risks mangling artists that don't actually have collaborators,
|
||||||
such as "Black Country, New Road" becoming "Black Country".
|
such as "Black Country, New Road" becoming "Black Country". I understand that some users may leverage MusicBrainz tags that enable a song to be referenced by several
|
||||||
|
artists, but such functionality in Auxio will likely take awhile to implement to to UI and technical constraints.
|
||||||
|
|
||||||
**Auxio does not detect new music:** This is Auxio's default behavior due to limitations regarding android's filesystem APIs. To enable such behavior, turn on
|
**Auxio does not detect new music:** This is Auxio's default behavior due to limitations regarding android's filesystem APIs. To enable such behavior, turn on
|
||||||
"Automatic reloading" in settings. Note that this option does require a persistent notification and higher battery usage.
|
"Automatic reloading" in settings. Note that this option does require a persistent notification and higher battery usage.
|
||||||
|
|
Loading…
Reference in a new issue