detail: fix song deletion issue
Fix an issue where the song dialog would not properly close when the song it corresponded to was deleted.
This commit is contained in:
parent
35f05ed902
commit
201f132686
3 changed files with 48 additions and 24 deletions
|
@ -26,7 +26,6 @@ import kotlinx.coroutines.Dispatchers
|
|||
import kotlinx.coroutines.flow.MutableStateFlow
|
||||
import kotlinx.coroutines.flow.StateFlow
|
||||
import kotlinx.coroutines.launch
|
||||
import kotlinx.coroutines.withContext
|
||||
import org.oxycblt.auxio.R
|
||||
import org.oxycblt.auxio.detail.recycler.DiscHeader
|
||||
import org.oxycblt.auxio.detail.recycler.SortHeader
|
||||
|
@ -54,8 +53,9 @@ import org.oxycblt.auxio.util.unlikelyToBeNull
|
|||
*/
|
||||
class DetailViewModel(application: Application) :
|
||||
AndroidViewModel(application), MusicStore.Callback {
|
||||
data class DetailSong(
|
||||
val song: Song,
|
||||
data class DetailSong(val song: Song, val info: SongInfo?)
|
||||
|
||||
data class SongInfo(
|
||||
val bitrateKbps: Int?,
|
||||
val sampleRate: Int?,
|
||||
val resolvedMimeType: MimeType
|
||||
|
@ -156,12 +156,20 @@ class DetailViewModel(application: Application) :
|
|||
}
|
||||
|
||||
private fun generateDetailSong(song: Song) {
|
||||
viewModelScope.launch {
|
||||
_currentSong.value = withContext(Dispatchers.IO) { generateDetailSongImpl(song) }
|
||||
_currentSong.value = DetailSong(song, null)
|
||||
viewModelScope.launch(Dispatchers.IO) {
|
||||
val info = generateDetailSongInfo(song)
|
||||
|
||||
// Theoretically, the song could have been changed again while we were
|
||||
// extracting song information, so make sure that we can update the song
|
||||
// in the first place.
|
||||
if (_currentSong.value?.run { this.song.id } == song.id) {
|
||||
_currentSong.value = DetailSong(song, info)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun generateDetailSongImpl(song: Song): DetailSong {
|
||||
private fun generateDetailSongInfo(song: Song): SongInfo {
|
||||
val extractor = MediaExtractor()
|
||||
|
||||
try {
|
||||
|
@ -169,7 +177,7 @@ class DetailViewModel(application: Application) :
|
|||
} catch (e: Exception) {
|
||||
logW("Unable to extract song attributes.")
|
||||
logW(e.stackTraceToString())
|
||||
return DetailSong(song, null, null, song.mimeType)
|
||||
return SongInfo(null, null, song.mimeType)
|
||||
}
|
||||
|
||||
val format = extractor.getTrackFormat(0)
|
||||
|
@ -203,7 +211,7 @@ class DetailViewModel(application: Application) :
|
|||
MimeType(song.mimeType.fromExtension, formatMimeType)
|
||||
}
|
||||
|
||||
return DetailSong(song, bitrate, sampleRate, resolvedMimeType)
|
||||
return SongInfo(bitrate, sampleRate, resolvedMimeType)
|
||||
}
|
||||
|
||||
private fun refreshAlbumData(album: Album) {
|
||||
|
@ -258,6 +266,8 @@ class DetailViewModel(application: Application) :
|
|||
val newSong = library.sanitize(song.song)
|
||||
if (newSong != null) {
|
||||
generateDetailSong(newSong)
|
||||
} else {
|
||||
_currentSong.value = null
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -22,6 +22,7 @@ import android.text.format.Formatter
|
|||
import android.view.LayoutInflater
|
||||
import androidx.appcompat.app.AlertDialog
|
||||
import androidx.core.view.isGone
|
||||
import androidx.navigation.fragment.findNavController
|
||||
import androidx.navigation.fragment.navArgs
|
||||
import org.oxycblt.auxio.R
|
||||
import org.oxycblt.auxio.databinding.DialogSongDetailBinding
|
||||
|
@ -29,6 +30,7 @@ import org.oxycblt.auxio.ui.fragment.ViewBindingDialogFragment
|
|||
import org.oxycblt.auxio.util.androidActivityViewModels
|
||||
import org.oxycblt.auxio.util.collectImmediately
|
||||
import org.oxycblt.auxio.util.formatDuration
|
||||
import org.oxycblt.auxio.util.logD
|
||||
|
||||
class SongDetailDialog : ViewBindingDialogFragment<DialogSongDetailBinding>() {
|
||||
private val detailModel: DetailViewModel by androidActivityViewModels()
|
||||
|
@ -56,28 +58,38 @@ class SongDetailDialog : ViewBindingDialogFragment<DialogSongDetailBinding>() {
|
|||
private fun updateSong(song: DetailViewModel.DetailSong?) {
|
||||
val binding = requireBinding()
|
||||
|
||||
logD("$song")
|
||||
|
||||
if (song != null) {
|
||||
binding.detailContainer.isGone = false
|
||||
binding.detailFileName.setText(song.song.path.name)
|
||||
binding.detailRelativeDir.setText(song.song.path.parent.resolveName(requireContext()))
|
||||
binding.detailFormat.setText(song.resolvedMimeType.resolveName(requireContext()))
|
||||
binding.detailSize.setText(Formatter.formatFileSize(requireContext(), song.song.size))
|
||||
binding.detailDuration.setText(song.song.durationSecs.formatDuration(true))
|
||||
if (song.info != null) {
|
||||
binding.detailContainer.isGone = false
|
||||
binding.detailFileName.setText(song.song.path.name)
|
||||
binding.detailRelativeDir.setText(
|
||||
song.song.path.parent.resolveName(requireContext()))
|
||||
binding.detailFormat.setText(
|
||||
song.info.resolvedMimeType.resolveName(requireContext()))
|
||||
binding.detailSize.setText(
|
||||
Formatter.formatFileSize(requireContext(), song.song.size))
|
||||
binding.detailDuration.setText(song.song.durationSecs.formatDuration(true))
|
||||
|
||||
if (song.bitrateKbps != null) {
|
||||
binding.detailBitrate.setText(getString(R.string.fmt_bitrate, song.bitrateKbps))
|
||||
} else {
|
||||
binding.detailBitrate.setText(R.string.def_bitrate)
|
||||
}
|
||||
if (song.info.bitrateKbps != null) {
|
||||
binding.detailBitrate.setText(
|
||||
getString(R.string.fmt_bitrate, song.info.bitrateKbps))
|
||||
} else {
|
||||
binding.detailBitrate.setText(R.string.def_bitrate)
|
||||
}
|
||||
|
||||
if (song.sampleRate != null) {
|
||||
binding.detailSampleRate.setText(
|
||||
getString(R.string.fmt_sample_rate, song.sampleRate))
|
||||
if (song.info.sampleRate != null) {
|
||||
binding.detailSampleRate.setText(
|
||||
getString(R.string.fmt_sample_rate, song.info.sampleRate))
|
||||
} else {
|
||||
binding.detailSampleRate.setText(R.string.def_sample_rate)
|
||||
}
|
||||
} else {
|
||||
binding.detailSampleRate.setText(R.string.def_sample_rate)
|
||||
binding.detailContainer.isGone = true
|
||||
}
|
||||
} else {
|
||||
binding.detailContainer.isGone = true
|
||||
findNavController().navigateUp()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -49,6 +49,8 @@ import org.oxycblt.auxio.util.logD
|
|||
* boilerplate you skip is not worth the insanity of androidx.
|
||||
*
|
||||
* @author OxygenCobalt
|
||||
*
|
||||
* TODO: Add abstractions for services. notifications, and generations
|
||||
*/
|
||||
class IndexerService : Service(), Indexer.Controller, Settings.Callback {
|
||||
private val indexer = Indexer.getInstance()
|
||||
|
|
Loading…
Reference in a new issue