all: update logging

Improve logging use across the app.
This commit is contained in:
OxygenCobalt 2022-06-15 11:06:10 -06:00
parent 2f85d694d1
commit 3d8d2e0975
No known key found for this signature in database
GPG key ID: 37DBE3621FE9AD47
31 changed files with 142 additions and 95 deletions

View file

@ -46,7 +46,7 @@ import org.oxycblt.auxio.util.canScroll
import org.oxycblt.auxio.util.collectWith import org.oxycblt.auxio.util.collectWith
import org.oxycblt.auxio.util.launch import org.oxycblt.auxio.util.launch
import org.oxycblt.auxio.util.logD import org.oxycblt.auxio.util.logD
import org.oxycblt.auxio.util.logW import org.oxycblt.auxio.util.logEOrThrow
import org.oxycblt.auxio.util.showToast import org.oxycblt.auxio.util.showToast
import org.oxycblt.auxio.util.unlikelyToBeNull import org.oxycblt.auxio.util.unlikelyToBeNull
@ -125,7 +125,7 @@ class AlbumDetailFragment :
override fun onOpenMenu(item: Item, anchor: View) { override fun onOpenMenu(item: Item, anchor: View) {
when (item) { when (item) {
is Song -> musicMenu(anchor, R.menu.menu_album_song_actions, item) is Song -> musicMenu(anchor, R.menu.menu_album_song_actions, item)
else -> logW("Unexpected datatype when opening menu: ${item::class.java}") else -> logEOrThrow("Unexpected datatype when opening menu: ${item::class.java}")
} }
} }
@ -204,7 +204,7 @@ class AlbumDetailFragment :
.navigate(AlbumDetailFragmentDirections.actionShowArtist(item.id)) .navigate(AlbumDetailFragmentDirections.actionShowArtist(item.id))
} }
null -> {} null -> {}
else -> logW("Unsupported navigation item ${item::class.java}") else -> logEOrThrow("Unexpected navigation item ${item::class.java}")
} }
} }

View file

@ -43,7 +43,7 @@ import org.oxycblt.auxio.util.applySpans
import org.oxycblt.auxio.util.collectWith import org.oxycblt.auxio.util.collectWith
import org.oxycblt.auxio.util.launch import org.oxycblt.auxio.util.launch
import org.oxycblt.auxio.util.logD import org.oxycblt.auxio.util.logD
import org.oxycblt.auxio.util.logW import org.oxycblt.auxio.util.logEOrThrow
import org.oxycblt.auxio.util.showToast import org.oxycblt.auxio.util.showToast
import org.oxycblt.auxio.util.unlikelyToBeNull import org.oxycblt.auxio.util.unlikelyToBeNull
@ -119,7 +119,7 @@ class ArtistDetailFragment :
when (item) { when (item) {
is Song -> musicMenu(anchor, R.menu.menu_artist_song_actions, item) is Song -> musicMenu(anchor, R.menu.menu_artist_song_actions, item)
is Album -> musicMenu(anchor, R.menu.menu_artist_album_actions, item) is Album -> musicMenu(anchor, R.menu.menu_artist_album_actions, item)
else -> logW("Unexpected datatype when opening menu: ${item::class.java}") else -> logEOrThrow("Unexpected datatype when opening menu: ${item::class.java}")
} }
} }
@ -179,7 +179,7 @@ class ArtistDetailFragment :
} }
} }
null -> {} null -> {}
else -> logW("Unsupported navigation item ${item::class.java}") else -> logEOrThrow("Unexpected navigation item ${item::class.java}")
} }
} }

View file

@ -156,17 +156,19 @@ class DetailViewModel(application: Application) :
private fun generateDetailSong(song: Song) { private fun generateDetailSong(song: Song) {
viewModelScope.launch { viewModelScope.launch {
_currentSong.value = _currentSong.value = withContext(Dispatchers.IO) { generateDetailSongImpl(song) }
withContext(Dispatchers.IO) { }
}
private fun generateDetailSongImpl(song: Song): DetailSong {
val extractor = MediaExtractor() val extractor = MediaExtractor()
try { try {
@Suppress("BlockingMethodInNonBlockingContext")
extractor.setDataSource(application, song.uri, emptyMap()) extractor.setDataSource(application, song.uri, emptyMap())
} catch (e: Exception) { } catch (e: Exception) {
logW("Unable to extract song attributes.") logW("Unable to extract song attributes.")
logW(e.stackTraceToString()) logW(e.stackTraceToString())
return@withContext DetailSong(song, null, null, song.mimeType) return DetailSong(song, null, null, song.mimeType)
} }
val format = extractor.getTrackFormat(0) val format = extractor.getTrackFormat(0)
@ -202,9 +204,7 @@ class DetailViewModel(application: Application) :
MimeType(song.mimeType.fromExtension, formatMimeType) MimeType(song.mimeType.fromExtension, formatMimeType)
} }
DetailSong(song, bitrate, sampleRate, resolvedMimeType) return DetailSong(song, bitrate, sampleRate, resolvedMimeType)
}
}
} }
private fun refreshAlbumData(album: Album) { private fun refreshAlbumData(album: Album) {
@ -255,6 +255,7 @@ class DetailViewModel(application: Application) :
if (library != null) { if (library != null) {
val song = currentSong.value val song = currentSong.value
if (song != null) { if (song != null) {
logD("Song changed, refreshing data")
val newSong = library.sanitize(song.song) val newSong = library.sanitize(song.song)
if (newSong != null) { if (newSong != null) {
generateDetailSong(newSong) generateDetailSong(newSong)
@ -263,6 +264,7 @@ class DetailViewModel(application: Application) :
val album = currentAlbum.value val album = currentAlbum.value
if (album != null) { if (album != null) {
logD("Album changed, refreshing data")
val newAlbum = library.sanitize(album).also { _currentAlbum.value = it } val newAlbum = library.sanitize(album).also { _currentAlbum.value = it }
if (newAlbum != null) { if (newAlbum != null) {
refreshAlbumData(newAlbum) refreshAlbumData(newAlbum)
@ -271,6 +273,7 @@ class DetailViewModel(application: Application) :
val artist = currentArtist.value val artist = currentArtist.value
if (artist != null) { if (artist != null) {
logD("Artist changed, refreshing data")
val newArtist = library.sanitize(artist).also { _currentArtist.value = it } val newArtist = library.sanitize(artist).also { _currentArtist.value = it }
if (newArtist != null) { if (newArtist != null) {
refreshArtistData(newArtist) refreshArtistData(newArtist)

View file

@ -44,7 +44,7 @@ import org.oxycblt.auxio.util.applySpans
import org.oxycblt.auxio.util.collectWith import org.oxycblt.auxio.util.collectWith
import org.oxycblt.auxio.util.launch import org.oxycblt.auxio.util.launch
import org.oxycblt.auxio.util.logD import org.oxycblt.auxio.util.logD
import org.oxycblt.auxio.util.logW import org.oxycblt.auxio.util.logEOrThrow
import org.oxycblt.auxio.util.showToast import org.oxycblt.auxio.util.showToast
import org.oxycblt.auxio.util.unlikelyToBeNull import org.oxycblt.auxio.util.unlikelyToBeNull
@ -120,7 +120,7 @@ class GenreDetailFragment :
override fun onOpenMenu(item: Item, anchor: View) { override fun onOpenMenu(item: Item, anchor: View) {
when (item) { when (item) {
is Song -> musicMenu(anchor, R.menu.menu_song_actions, item) is Song -> musicMenu(anchor, R.menu.menu_song_actions, item)
else -> logW("Unexpected datatype when opening menu: ${item::class.java}") else -> logEOrThrow("Unexpected datatype when opening menu: ${item::class.java}")
} }
} }

View file

@ -60,7 +60,6 @@ import org.oxycblt.auxio.util.launch
import org.oxycblt.auxio.util.logD import org.oxycblt.auxio.util.logD
import org.oxycblt.auxio.util.logE import org.oxycblt.auxio.util.logE
import org.oxycblt.auxio.util.logTraceOrThrow import org.oxycblt.auxio.util.logTraceOrThrow
import org.oxycblt.auxio.util.logW
import org.oxycblt.auxio.util.textSafe import org.oxycblt.auxio.util.textSafe
import org.oxycblt.auxio.util.unlikelyToBeNull import org.oxycblt.auxio.util.unlikelyToBeNull
@ -282,7 +281,7 @@ class HomeFragment : ViewBindingFragment<FragmentHomeBinding>(), Toolbar.OnMenuI
is Indexer.State.Complete -> handleIndexerResponse(binding, state.response) is Indexer.State.Complete -> handleIndexerResponse(binding, state.response)
is Indexer.State.Indexing -> handleIndexingState(binding, state.indexing) is Indexer.State.Indexing -> handleIndexingState(binding, state.indexing)
null -> { null -> {
logW("Indexer is in indeterminate state, doing nothing") logD("Indexer is in indeterminate state, doing nothing")
} }
} }
} }

View file

@ -128,6 +128,7 @@ class HomeViewModel : ViewModel(), SettingsManager.Callback, MusicStore.Callback
* begins to fast scroll. * begins to fast scroll.
*/ */
fun updateFastScrolling(scrolling: Boolean) { fun updateFastScrolling(scrolling: Boolean) {
logD("Updating fast scrolling state: $scrolling")
_isFastScrolling.value = scrolling _isFastScrolling.value = scrolling
} }

View file

@ -32,7 +32,7 @@ import org.oxycblt.auxio.ui.Sort
import org.oxycblt.auxio.ui.SyncBackingData import org.oxycblt.auxio.ui.SyncBackingData
import org.oxycblt.auxio.util.formatDuration import org.oxycblt.auxio.util.formatDuration
import org.oxycblt.auxio.util.launch import org.oxycblt.auxio.util.launch
import org.oxycblt.auxio.util.logW import org.oxycblt.auxio.util.logEOrThrow
import org.oxycblt.auxio.util.unlikelyToBeNull import org.oxycblt.auxio.util.unlikelyToBeNull
/** /**
@ -86,7 +86,7 @@ class AlbumListFragment : HomeListFragment<Album>() {
override fun onOpenMenu(item: Item, anchor: View) { override fun onOpenMenu(item: Item, anchor: View) {
when (item) { when (item) {
is Album -> musicMenu(anchor, R.menu.menu_album_actions, item) is Album -> musicMenu(anchor, R.menu.menu_album_actions, item)
else -> logW("Unexpected datatype when opening menu: ${item::class.java}") else -> logEOrThrow("Unexpected datatype when opening menu: ${item::class.java}")
} }
} }

View file

@ -32,7 +32,7 @@ import org.oxycblt.auxio.ui.Sort
import org.oxycblt.auxio.ui.SyncBackingData import org.oxycblt.auxio.ui.SyncBackingData
import org.oxycblt.auxio.util.formatDuration import org.oxycblt.auxio.util.formatDuration
import org.oxycblt.auxio.util.launch import org.oxycblt.auxio.util.launch
import org.oxycblt.auxio.util.logW import org.oxycblt.auxio.util.logEOrThrow
import org.oxycblt.auxio.util.unlikelyToBeNull import org.oxycblt.auxio.util.unlikelyToBeNull
/** /**
@ -80,7 +80,7 @@ class ArtistListFragment : HomeListFragment<Artist>() {
override fun onOpenMenu(item: Item, anchor: View) { override fun onOpenMenu(item: Item, anchor: View) {
when (item) { when (item) {
is Artist -> musicMenu(anchor, R.menu.menu_genre_artist_actions, item) is Artist -> musicMenu(anchor, R.menu.menu_genre_artist_actions, item)
else -> logW("Unexpected datatype when opening menu: ${item::class.java}") else -> logEOrThrow("Unexpected datatype when opening menu: ${item::class.java}")
} }
} }

View file

@ -32,7 +32,7 @@ import org.oxycblt.auxio.ui.Sort
import org.oxycblt.auxio.ui.SyncBackingData import org.oxycblt.auxio.ui.SyncBackingData
import org.oxycblt.auxio.util.formatDuration import org.oxycblt.auxio.util.formatDuration
import org.oxycblt.auxio.util.launch import org.oxycblt.auxio.util.launch
import org.oxycblt.auxio.util.logW import org.oxycblt.auxio.util.logEOrThrow
import org.oxycblt.auxio.util.unlikelyToBeNull import org.oxycblt.auxio.util.unlikelyToBeNull
/** /**
@ -80,7 +80,7 @@ class GenreListFragment : HomeListFragment<Genre>() {
override fun onOpenMenu(item: Item, anchor: View) { override fun onOpenMenu(item: Item, anchor: View) {
when (item) { when (item) {
is Genre -> musicMenu(anchor, R.menu.menu_genre_artist_actions, item) is Genre -> musicMenu(anchor, R.menu.menu_genre_artist_actions, item)
else -> logW("Unexpected datatype when opening menu: ${item::class.java}") else -> logEOrThrow("Unexpected datatype when opening menu: ${item::class.java}")
} }
} }

View file

@ -31,7 +31,7 @@ import org.oxycblt.auxio.ui.Sort
import org.oxycblt.auxio.ui.SyncBackingData import org.oxycblt.auxio.ui.SyncBackingData
import org.oxycblt.auxio.util.formatDuration import org.oxycblt.auxio.util.formatDuration
import org.oxycblt.auxio.util.launch import org.oxycblt.auxio.util.launch
import org.oxycblt.auxio.util.logW import org.oxycblt.auxio.util.logEOrThrow
import org.oxycblt.auxio.util.unlikelyToBeNull import org.oxycblt.auxio.util.unlikelyToBeNull
/** /**
@ -87,7 +87,7 @@ class SongListFragment : HomeListFragment<Song>() {
override fun onOpenMenu(item: Item, anchor: View) { override fun onOpenMenu(item: Item, anchor: View) {
when (item) { when (item) {
is Song -> musicMenu(anchor, R.menu.menu_song_actions, item) is Song -> musicMenu(anchor, R.menu.menu_song_actions, item)
else -> logW("Unexpected datatype when opening menu: ${item::class.java}") else -> logEOrThrow("Unexpected datatype when opening menu: ${item::class.java}")
} }
} }

View file

@ -31,6 +31,7 @@ import org.oxycblt.auxio.music.Genre
import org.oxycblt.auxio.music.Song import org.oxycblt.auxio.music.Song
import org.oxycblt.auxio.settings.SettingsManager import org.oxycblt.auxio.settings.SettingsManager
import org.oxycblt.auxio.util.getColorStateListSafe import org.oxycblt.auxio.util.getColorStateListSafe
import org.oxycblt.auxio.util.logD
/** /**
* Effectively a super-charged [StyledImageView]. * Effectively a super-charged [StyledImageView].

View file

@ -118,6 +118,7 @@ class Indexer {
* the indexing process to re-index music. * the indexing process to re-index music.
*/ */
fun requestReindex() { fun requestReindex() {
logD("Requesting reindex")
for (callback in callbacks) { for (callback in callbacks) {
callback.onRequestReindex() callback.onRequestReindex()
} }
@ -130,6 +131,7 @@ class Indexer {
* corrupt the current state. * corrupt the current state.
*/ */
fun cancelLast() { fun cancelLast() {
logD("Cancelling last job")
synchronized(this) { synchronized(this) {
currentGeneration++ currentGeneration++
emitIndexing(null, currentGeneration) emitIndexing(null, currentGeneration)

View file

@ -90,6 +90,7 @@ class IndexerService : Service(), Indexer.Callback {
is Indexer.State.Complete -> { is Indexer.State.Complete -> {
if (state.response is Indexer.Response.Ok && if (state.response is Indexer.Response.Ok &&
state.response.library != musicStore.library) { state.response.library != musicStore.library) {
logD("Applying new library")
// Load was completed successfully, so apply the new library if we // Load was completed successfully, so apply the new library if we
// have not already. // have not already.
musicStore.library = state.response.library musicStore.library = state.response.library
@ -174,6 +175,7 @@ private class IndexerNotification(private val context: Context) :
fun updateIndexingState(indexing: Indexer.Indexing): Boolean { fun updateIndexingState(indexing: Indexer.Indexing): Boolean {
when (indexing) { when (indexing) {
is Indexer.Indexing.Indeterminate -> { is Indexer.Indexing.Indeterminate -> {
logD("Updating state to $indexing")
setContentText(context.getString(R.string.lbl_indexing)) setContentText(context.getString(R.string.lbl_indexing))
setProgress(0, 0, true) setProgress(0, 0, true)
return true return true
@ -181,6 +183,7 @@ private class IndexerNotification(private val context: Context) :
is Indexer.Indexing.Songs -> { is Indexer.Indexing.Songs -> {
// Only update the notification every 50 songs to prevent excessive updates. // Only update the notification every 50 songs to prevent excessive updates.
if (indexing.current % 50 == 0) { if (indexing.current % 50 == 0) {
logD("Updating state to $indexing")
setContentText( setContentText(
context.getString(R.string.fmt_indexing, indexing.current, indexing.total)) context.getString(R.string.fmt_indexing, indexing.current, indexing.total))
setProgress(indexing.total, indexing.current, false) setProgress(indexing.total, indexing.current, false)

View file

@ -23,6 +23,7 @@ import android.database.Cursor
import android.net.Uri import android.net.Uri
import android.provider.MediaStore import android.provider.MediaStore
import androidx.core.text.isDigitsOnly import androidx.core.text.isDigitsOnly
import org.oxycblt.auxio.util.logD
/** Shortcut for making a [ContentResolver] query with less superfluous arguments. */ /** Shortcut for making a [ContentResolver] query with less superfluous arguments. */
fun ContentResolver.queryCursor( fun ContentResolver.queryCursor(

View file

@ -113,9 +113,11 @@ val StorageVolume.directoryCompat: String?
@SuppressLint("NewApi") @SuppressLint("NewApi")
fun StorageVolume.getDescriptionCompat(context: Context): String = getDescription(context) fun StorageVolume.getDescriptionCompat(context: Context): String = getDescription(context)
/** If this volume is the primary volume. May still be removable storage. */
val StorageVolume.isPrimaryCompat: Boolean val StorageVolume.isPrimaryCompat: Boolean
@SuppressLint("NewApi") get() = isPrimary @SuppressLint("NewApi") get() = isPrimary
/** If this volume is emulated. */
val StorageVolume.isEmulatedCompat: Boolean val StorageVolume.isEmulatedCompat: Boolean
@SuppressLint("NewApi") get() = isEmulated @SuppressLint("NewApi") get() = isEmulated

View file

@ -167,8 +167,6 @@ class MusicDirsDialog :
DocumentsContract.buildDocumentUriUsingTree( DocumentsContract.buildDocumentUriUsingTree(
uri, DocumentsContract.getTreeDocumentId(uri)) uri, DocumentsContract.getTreeDocumentId(uri))
logD(uri)
// Turn it into a semi-usable path // Turn it into a semi-usable path
val treeUri = DocumentsContract.getTreeDocumentId(docUri) val treeUri = DocumentsContract.getTreeDocumentId(docUri)

View file

@ -25,6 +25,7 @@ import kotlin.math.max
import org.oxycblt.auxio.databinding.ViewSeekBarBinding import org.oxycblt.auxio.databinding.ViewSeekBarBinding
import org.oxycblt.auxio.util.formatDuration import org.oxycblt.auxio.util.formatDuration
import org.oxycblt.auxio.util.inflater import org.oxycblt.auxio.util.inflater
import org.oxycblt.auxio.util.logD
import org.oxycblt.auxio.util.textSafe import org.oxycblt.auxio.util.textSafe
/** /**
@ -97,6 +98,7 @@ constructor(
// Sanity check 2: If the current value exceeds the new duration value, clamp it // Sanity check 2: If the current value exceeds the new duration value, clamp it
// down so that we don't crash and instead have an annoying visual flicker. // down so that we don't crash and instead have an annoying visual flicker.
if (positionSecs > to) { if (positionSecs > to) {
logD("Clamping invalid position [current: $positionSecs new max: $to]")
binding.seekBarSlider.value = to.toFloat() binding.seekBarSlider.value = to.toFloat()
} }
@ -105,12 +107,14 @@ constructor(
} }
override fun onStartTrackingTouch(slider: Slider) { override fun onStartTrackingTouch(slider: Slider) {
logD("Starting seek mode")
// User has begun seeking, place the SeekBar into a "Suspended" mode in which no // User has begun seeking, place the SeekBar into a "Suspended" mode in which no
// position updates are sent and is indicated by the position value turning accented. // position updates are sent and is indicated by the position value turning accented.
isActivated = true isActivated = true
} }
override fun onStopTrackingTouch(slider: Slider) { override fun onStopTrackingTouch(slider: Slider) {
logD("Confirming seek")
// End of seek event, send off new value to callback. // End of seek event, send off new value to callback.
isActivated = false isActivated = false
callback?.seekTo(slider.value.toLong()) callback?.seekTo(slider.value.toLong())

View file

@ -30,7 +30,6 @@ import org.oxycblt.auxio.playback.state.PlaybackStateManager
import org.oxycblt.auxio.settings.SettingsManager import org.oxycblt.auxio.settings.SettingsManager
import org.oxycblt.auxio.util.clamp import org.oxycblt.auxio.util.clamp
import org.oxycblt.auxio.util.logD import org.oxycblt.auxio.util.logD
import org.oxycblt.auxio.util.logW
import org.oxycblt.auxio.util.unlikelyToBeNull import org.oxycblt.auxio.util.unlikelyToBeNull
/** /**
@ -65,7 +64,7 @@ class ReplayGainAudioProcessor : BaseAudioProcessor() {
*/ */
fun applyReplayGain(metadata: Metadata?) { fun applyReplayGain(metadata: Metadata?) {
if (settingsManager.replayGainMode == ReplayGainMode.OFF) { if (settingsManager.replayGainMode == ReplayGainMode.OFF) {
logW("ReplayGain not enabled") logD("ReplayGain not enabled")
volume = 1f volume = 1f
return return
} }

View file

@ -23,6 +23,7 @@ import android.database.sqlite.SQLiteDatabase
import android.database.sqlite.SQLiteOpenHelper import android.database.sqlite.SQLiteOpenHelper
import android.os.Build import android.os.Build
import android.os.storage.StorageManager import android.os.storage.StorageManager
import android.util.Log
import androidx.core.content.edit import androidx.core.content.edit
import org.oxycblt.auxio.music.Directory import org.oxycblt.auxio.music.Directory
import org.oxycblt.auxio.music.directoryCompat import org.oxycblt.auxio.music.directoryCompat
@ -37,6 +38,8 @@ import org.oxycblt.auxio.util.queryAll
fun handleAccentCompat(prefs: SharedPreferences): Accent { fun handleAccentCompat(prefs: SharedPreferences): Accent {
if (prefs.contains(OldKeys.KEY_ACCENT2)) { if (prefs.contains(OldKeys.KEY_ACCENT2)) {
Log.d("SettingsCompat", "Migrating ${OldKeys.KEY_ACCENT2}")
var accent = prefs.getInt(OldKeys.KEY_ACCENT2, 5) var accent = prefs.getInt(OldKeys.KEY_ACCENT2, 5)
// Blue grey was merged with Light Blue in 2.0.0 // Blue grey was merged with Light Blue in 2.0.0
@ -62,6 +65,8 @@ fun handleAccentCompat(prefs: SharedPreferences): Accent {
} }
if (prefs.contains(OldKeys.KEY_ACCENT3)) { if (prefs.contains(OldKeys.KEY_ACCENT3)) {
Log.d("SettingsCompat", "Migrating ${OldKeys.KEY_ACCENT3}")
var accent = prefs.getInt(OldKeys.KEY_ACCENT3, 5) var accent = prefs.getInt(OldKeys.KEY_ACCENT3, 5)
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) {
// Accents were previously frozen as soon as the OS was updated to android twelve, // Accents were previously frozen as soon as the OS was updated to android twelve,
@ -82,7 +87,8 @@ fun handleAccentCompat(prefs: SharedPreferences): Accent {
} }
/** /**
* Converts paths from the old excluded directory database to a list of modern [Dir] instances. * Converts paths from the old excluded directory database to a list of modern [Directory]
* instances.
* *
* Historically, Auxio used an excluded directory database shamelessly ripped from Phonograph. This * Historically, Auxio used an excluded directory database shamelessly ripped from Phonograph. This
* was a dumb idea, as the choice of a full-blown database for a few paths was overkill, version * was a dumb idea, as the choice of a full-blown database for a few paths was overkill, version
@ -93,6 +99,7 @@ fun handleAccentCompat(prefs: SharedPreferences): Accent {
* rolled into this conversion. * rolled into this conversion.
*/ */
fun handleExcludedCompat(context: Context, storageManager: StorageManager): List<Directory> { fun handleExcludedCompat(context: Context, storageManager: StorageManager): List<Directory> {
Log.d("SettingsCompat", "Migrating old excluded database")
val db = LegacyExcludedDatabase(context) val db = LegacyExcludedDatabase(context)
// /storage/emulated/0 (the old path prefix) should correspond to primary *emulated* storage. // /storage/emulated/0 (the old path prefix) should correspond to primary *emulated* storage.
val primaryVolume = val primaryVolume =

View file

@ -33,7 +33,7 @@ class SettingsFragment : ViewBindingFragment<FragmentSettingsBinding>() {
FragmentSettingsBinding.inflate(inflater) FragmentSettingsBinding.inflate(inflater)
override fun onBindingCreated(binding: FragmentSettingsBinding, savedInstanceState: Bundle?) { override fun onBindingCreated(binding: FragmentSettingsBinding, savedInstanceState: Bundle?) {
binding.settingsToolbar.setNavigationOnClickListener { findNavController().navigateUp() }
binding.settingsAppbar.liftOnScrollTargetViewId = androidx.preference.R.id.recycler_view binding.settingsAppbar.liftOnScrollTargetViewId = androidx.preference.R.id.recycler_view
binding.settingsToolbar.setNavigationOnClickListener { findNavController().navigateUp() }
} }
} }

View file

@ -291,6 +291,8 @@ constructor(context: Context, attrs: AttributeSet? = null, defStyle: Int = 0) :
panelRange = measuredHeight - barView.measuredHeight panelRange = measuredHeight - barView.measuredHeight
if (!isLaidOut) { if (!isLaidOut) {
logD("Doing initial panel layout")
// This is our first layout, so make sure we know what offset we should work with // This is our first layout, so make sure we know what offset we should work with
// before we measure our content // before we measure our content
panelOffset = panelOffset =
@ -383,6 +385,7 @@ constructor(context: Context, attrs: AttributeSet? = null, defStyle: Int = 0) :
// not apply any window insets at all, which results in scroll desynchronization on // not apply any window insets at all, which results in scroll desynchronization on
// certain views. This is considered tolerable as the other options are to convert // certain views. This is considered tolerable as the other options are to convert
// the playback fragments to views, which is not nice. // the playback fragments to views, which is not nice.
logD("Readjusting window insets")
val bars = insets.getSystemBarInsetsCompat(this) val bars = insets.getSystemBarInsetsCompat(this)
val consumedByPanel = computePanelTopPosition(panelOffset) - measuredHeight val consumedByPanel = computePanelTopPosition(panelOffset) - measuredHeight
val adjustedBottomInset = (consumedByPanel + bars.bottom).coerceAtLeast(0) val adjustedBottomInset = (consumedByPanel + bars.bottom).coerceAtLeast(0)
@ -495,9 +498,11 @@ constructor(context: Context, attrs: AttributeSet? = null, defStyle: Int = 0) :
private fun setPanelStateInternal(state: PanelState) { private fun setPanelStateInternal(state: PanelState) {
if (panelState == state) { if (panelState == state) {
logD("State is already $state, not applying")
return return
} }
logD("new state: $state")
panelState = state panelState = state
sendAccessibilityEvent(AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED) sendAccessibilityEvent(AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED)

View file

@ -51,19 +51,16 @@ constructor(context: Context, attrs: AttributeSet? = null, @AttrRes defStyleAttr
add(topDivider) add(topDivider)
add(bottomDivider) add(bottomDivider)
} }
}
addOnScrollListener( override fun onScrolled(dx: Int, dy: Int) {
object : RecyclerView.OnScrollListener() { super.onScrolled(dx, dy)
override fun onScrolled(recyclerView: RecyclerView, dx: Int, dy: Int) {
super.onScrolled(recyclerView, dx, dy)
val manager = recyclerView.layoutManager as LinearLayoutManager val manager = layoutManager as LinearLayoutManager
topDivider.isInvisible = manager.findFirstCompletelyVisibleItemPosition() < 1 topDivider.isInvisible = manager.findFirstCompletelyVisibleItemPosition() < 1
bottomDivider.isInvisible = bottomDivider.isInvisible =
manager.findLastCompletelyVisibleItemPosition() == (manager.itemCount - 1) manager.findLastCompletelyVisibleItemPosition() == (manager.itemCount - 1)
} }
})
}
override fun onMeasure(widthSpec: Int, heightSpec: Int) { override fun onMeasure(widthSpec: Int, heightSpec: Int) {
super.onMeasure(widthSpec, heightSpec) super.onMeasure(widthSpec, heightSpec)

View file

@ -29,7 +29,6 @@ import androidx.core.content.res.ResourcesCompat
import androidx.core.view.updatePadding import androidx.core.view.updatePadding
import com.google.android.material.appbar.AppBarLayout import com.google.android.material.appbar.AppBarLayout
import org.oxycblt.auxio.util.getSystemBarInsetsCompat import org.oxycblt.auxio.util.getSystemBarInsetsCompat
import org.oxycblt.auxio.util.logW
/** /**
* An [AppBarLayout] that fixes a bug with the default implementation where the lifted state will * An [AppBarLayout] that fixes a bug with the default implementation where the lifted state will
@ -90,7 +89,7 @@ constructor(context: Context, attrs: AttributeSet? = null, @AttrRes defStyleAttr
if (liftOnScrollTargetViewId != ResourcesCompat.ID_NULL) { if (liftOnScrollTargetViewId != ResourcesCompat.ID_NULL) {
scrollingChild = (parent as ViewGroup).findViewById(liftOnScrollTargetViewId) scrollingChild = (parent as ViewGroup).findViewById(liftOnScrollTargetViewId)
} else { } else {
logW("liftOnScrollTargetViewId was not specified, ignoring scroll events") error("liftOnScrollTargetViewId was not specified")
} }
} }

View file

@ -29,7 +29,8 @@ import org.oxycblt.auxio.music.Artist
import org.oxycblt.auxio.music.Genre import org.oxycblt.auxio.music.Genre
import org.oxycblt.auxio.music.Song import org.oxycblt.auxio.music.Song
import org.oxycblt.auxio.playback.PlaybackViewModel import org.oxycblt.auxio.playback.PlaybackViewModel
import org.oxycblt.auxio.util.logW import org.oxycblt.auxio.util.logD
import org.oxycblt.auxio.util.logEOrThrow
import org.oxycblt.auxio.util.showToast import org.oxycblt.auxio.util.showToast
abstract class MenuFragment<T : ViewBinding> : ViewBindingFragment<T>() { abstract class MenuFragment<T : ViewBinding> : ViewBindingFragment<T>() {
@ -39,6 +40,8 @@ abstract class MenuFragment<T : ViewBinding> : ViewBindingFragment<T>() {
protected val navModel: NavigationViewModel by activityViewModels() protected val navModel: NavigationViewModel by activityViewModels()
protected fun musicMenu(anchor: View, @MenuRes menuRes: Int, song: Song) { protected fun musicMenu(anchor: View, @MenuRes menuRes: Int, song: Song) {
logD("Launching new song menu: ${song.rawName}")
musicMenuImpl(anchor, menuRes) { id -> musicMenuImpl(anchor, menuRes) { id ->
when (id) { when (id) {
R.id.action_play_next -> { R.id.action_play_next -> {
@ -59,7 +62,7 @@ abstract class MenuFragment<T : ViewBinding> : ViewBindingFragment<T>() {
navModel.mainNavigateTo(MainNavigationAction.SongDetails(song)) navModel.mainNavigateTo(MainNavigationAction.SongDetails(song))
} }
else -> { else -> {
logW("Unknown menu item selected") logEOrThrow("Unexpected menu item selected")
return@musicMenuImpl false return@musicMenuImpl false
} }
} }
@ -69,6 +72,8 @@ abstract class MenuFragment<T : ViewBinding> : ViewBindingFragment<T>() {
} }
protected fun musicMenu(anchor: View, @MenuRes menuRes: Int, album: Album) { protected fun musicMenu(anchor: View, @MenuRes menuRes: Int, album: Album) {
logD("Launching new album menu: ${album.rawName}")
musicMenuImpl(anchor, menuRes) { id -> musicMenuImpl(anchor, menuRes) { id ->
when (id) { when (id) {
R.id.action_play -> { R.id.action_play -> {
@ -89,7 +94,7 @@ abstract class MenuFragment<T : ViewBinding> : ViewBindingFragment<T>() {
navModel.exploreNavigateTo(album.artist) navModel.exploreNavigateTo(album.artist)
} }
else -> { else -> {
logW("Unknown menu item selected") logEOrThrow("Unexpected menu item selected")
return@musicMenuImpl false return@musicMenuImpl false
} }
} }
@ -99,6 +104,8 @@ abstract class MenuFragment<T : ViewBinding> : ViewBindingFragment<T>() {
} }
protected fun musicMenu(anchor: View, @MenuRes menuRes: Int, artist: Artist) { protected fun musicMenu(anchor: View, @MenuRes menuRes: Int, artist: Artist) {
logD("Launching new artist menu: ${artist.rawName}")
musicMenuImpl(anchor, menuRes) { id -> musicMenuImpl(anchor, menuRes) { id ->
when (id) { when (id) {
R.id.action_play -> { R.id.action_play -> {
@ -116,7 +123,7 @@ abstract class MenuFragment<T : ViewBinding> : ViewBindingFragment<T>() {
requireContext().showToast(R.string.lbl_queue_added) requireContext().showToast(R.string.lbl_queue_added)
} }
else -> { else -> {
logW("Unknown menu item selected") logEOrThrow("Unexpected menu item selected")
return@musicMenuImpl false return@musicMenuImpl false
} }
} }
@ -126,6 +133,8 @@ abstract class MenuFragment<T : ViewBinding> : ViewBindingFragment<T>() {
} }
protected fun musicMenu(anchor: View, @MenuRes menuRes: Int, genre: Genre) { protected fun musicMenu(anchor: View, @MenuRes menuRes: Int, genre: Genre) {
logD("Launching new genre menu: ${genre.rawName}")
musicMenuImpl(anchor, menuRes) { id -> musicMenuImpl(anchor, menuRes) { id ->
when (id) { when (id) {
R.id.action_play -> { R.id.action_play -> {
@ -143,7 +152,7 @@ abstract class MenuFragment<T : ViewBinding> : ViewBindingFragment<T>() {
requireContext().showToast(R.string.lbl_queue_added) requireContext().showToast(R.string.lbl_queue_added)
} }
else -> { else -> {
logW("Unknown menu item selected") logEOrThrow("Unexpected menu item selected")
return@musicMenuImpl false return@musicMenuImpl false
} }
} }
@ -166,6 +175,7 @@ abstract class MenuFragment<T : ViewBinding> : ViewBindingFragment<T>() {
protected fun menu(anchor: View, @MenuRes menuRes: Int, block: PopupMenu.() -> Unit) { protected fun menu(anchor: View, @MenuRes menuRes: Int, block: PopupMenu.() -> Unit) {
if (currentMenu != null) { if (currentMenu != null) {
logD("Menu already present, not launching")
return return
} }

View file

@ -22,6 +22,7 @@ import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.StateFlow import kotlinx.coroutines.flow.StateFlow
import org.oxycblt.auxio.music.Music import org.oxycblt.auxio.music.Music
import org.oxycblt.auxio.music.Song import org.oxycblt.auxio.music.Song
import org.oxycblt.auxio.util.logD
/** /**
* A ViewModel that handles complicated navigation situations. * A ViewModel that handles complicated navigation situations.
@ -43,23 +44,35 @@ class NavigationViewModel : ViewModel() {
/** Notify MainFragment to navigate to the location outlined in [MainNavigationAction]. */ /** Notify MainFragment to navigate to the location outlined in [MainNavigationAction]. */
fun mainNavigateTo(action: MainNavigationAction) { fun mainNavigateTo(action: MainNavigationAction) {
if (_mainNavigationAction.value != null) return if (_mainNavigationAction.value != null) {
logD("Already navigating, not doing main action")
return
}
logD("Navigating with action $action")
_mainNavigationAction.value = action _mainNavigationAction.value = action
} }
/** Mark that the main navigation process is done. */ /** Mark that the main navigation process is done. */
fun finishMainNavigation() { fun finishMainNavigation() {
logD("Finishing main navigation process")
_mainNavigationAction.value = null _mainNavigationAction.value = null
} }
/** Navigate to an item's detail menu, whether a song/album/artist */ /** Navigate to an item's detail menu, whether a song/album/artist */
fun exploreNavigateTo(item: Music) { fun exploreNavigateTo(item: Music) {
if (_exploreNavigationItem.value != null) return if (_exploreNavigationItem.value != null) {
logD("Already navigation, not doing explore action")
return
}
logD("Navigating to ${item.rawName}")
_exploreNavigationItem.value = item _exploreNavigationItem.value = item
} }
/** Mark that the item navigation process is done. */ /** Mark that the item navigation process is done. */
fun finishExploreNavigation() { fun finishExploreNavigation() {
logD("Finishing explore navigation process")
_exploreNavigationItem.value = null _exploreNavigationItem.value = null
} }
} }

View file

@ -25,7 +25,7 @@ import org.oxycblt.auxio.music.Artist
import org.oxycblt.auxio.music.Genre import org.oxycblt.auxio.music.Genre
import org.oxycblt.auxio.music.Music import org.oxycblt.auxio.music.Music
import org.oxycblt.auxio.music.Song import org.oxycblt.auxio.music.Song
import org.oxycblt.auxio.util.logW import org.oxycblt.auxio.util.logEOrThrow
/** /**
* A data class representing the sort modes used in Auxio. * A data class representing the sort modes used in Auxio.
@ -74,19 +74,19 @@ sealed class Sort(open val isAscending: Boolean) {
} }
open fun songsInPlace(songs: MutableList<Song>) { open fun songsInPlace(songs: MutableList<Song>) {
logW("This sort is not supported for songs") logEOrThrow("This sort is not supported for songs")
} }
open fun albumsInPlace(albums: MutableList<Album>) { open fun albumsInPlace(albums: MutableList<Album>) {
logW("This sort is not supported for albums") logEOrThrow("This sort is not supported for albums")
} }
open fun artistsInPlace(artists: MutableList<Artist>) { open fun artistsInPlace(artists: MutableList<Artist>) {
logW("This sort is not supported for artists") logEOrThrow("This sort is not supported for artists")
} }
open fun genresInPlace(genres: MutableList<Genre>) { open fun genresInPlace(genres: MutableList<Genre>) {
logW("This sort is not supported for genres") logEOrThrow("This sort is not supported for genres")
} }
/** /**

View file

@ -131,7 +131,7 @@ class Accent private constructor(val index: Int) {
companion object { companion object {
fun from(index: Int): Accent { fun from(index: Int): Accent {
if (index > (MAX - 1)) { if (index > (MAX - 1)) {
logW("Account outside of bounds [idx: $index, max: $MAX") logW("Account outside of bounds [idx: $index, max: $MAX]")
return Accent(5) return Accent(5)
} }

View file

@ -54,7 +54,6 @@ import org.oxycblt.auxio.R
*/ */
fun View.disableDropShadowCompat() { fun View.disableDropShadowCompat() {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) {
logD("Disabling drop shadows")
val transparent = context.getColorSafe(android.R.color.transparent) val transparent = context.getColorSafe(android.R.color.transparent)
outlineAmbientShadowColor = transparent outlineAmbientShadowColor = transparent
outlineSpotShadowColor = transparent outlineSpotShadowColor = transparent

View file

@ -52,7 +52,7 @@ fun Any.logE(msg: String) = Log.e(autoTag, msg)
*/ */
fun Any.logEOrThrow(msg: String) { fun Any.logEOrThrow(msg: String) {
if (BuildConfig.DEBUG) { if (BuildConfig.DEBUG) {
error("${autoTag}: $msg") error(msg)
} else { } else {
logE(msg) logE(msg)
} }

View file

@ -31,6 +31,7 @@ import org.oxycblt.auxio.playback.state.PlaybackStateManager
import org.oxycblt.auxio.playback.state.RepeatMode import org.oxycblt.auxio.playback.state.RepeatMode
import org.oxycblt.auxio.settings.SettingsManager import org.oxycblt.auxio.settings.SettingsManager
import org.oxycblt.auxio.util.getDimenSizeSafe import org.oxycblt.auxio.util.getDimenSizeSafe
import org.oxycblt.auxio.util.logD
/** /**
* A wrapper around each [WidgetProvider] that plugs into the main Auxio process and updates the * A wrapper around each [WidgetProvider] that plugs into the main Auxio process and updates the
@ -67,6 +68,7 @@ class WidgetComponent(private val context: Context) :
// possible. // possible.
val song = playbackManager.song val song = playbackManager.song
if (song == null) { if (song == null) {
logD("No song, resetting widget")
widget.update(context, null) widget.update(context, null)
return return
} }
@ -87,6 +89,8 @@ class WidgetComponent(private val context: Context) :
// - After Android 12, the widget has round edges, so we need to round out // - After Android 12, the widget has round edges, so we need to round out
// the album art. I dislike this, but it's mainly for stylistic cohesion. // the album art. I dislike this, but it's mainly for stylistic cohesion.
return if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) { return if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) {
this@WidgetComponent.logD("Doing API 31 cover load")
val metrics = context.resources.displayMetrics val metrics = context.resources.displayMetrics
// Use RoundedCornersTransformation. This is because our hack to get a 1:1 // Use RoundedCornersTransformation. This is because our hack to get a 1:1
@ -106,6 +110,7 @@ class WidgetComponent(private val context: Context) :
// bitmap on very large screens. // bitmap on very large screens.
.size(minOf(metrics.widthPixels, metrics.heightPixels, 1024)) .size(minOf(metrics.widthPixels, metrics.heightPixels, 1024))
} else { } else {
this@WidgetComponent.logD("Doing API 21 cover load")
// Note: Explicitly use the "original" size as without it the scaling logic // Note: Explicitly use the "original" size as without it the scaling logic
// in coil breaks down and results in an error. // in coil breaks down and results in an error.
builder.size(Size.ORIGINAL) builder.size(Size.ORIGINAL)

View file

@ -15,7 +15,6 @@
app:liftOnScroll="true" app:liftOnScroll="true"
app:liftOnScrollTargetViewId="@id/detail_recycler"> app:liftOnScrollTargetViewId="@id/detail_recycler">
<!-- FIXME: Not every detail view has actions -->
<com.google.android.material.appbar.MaterialToolbar <com.google.android.material.appbar.MaterialToolbar
android:id="@+id/detail_toolbar" android:id="@+id/detail_toolbar"