Cleanup code

Do some code cleanup.
This commit is contained in:
OxygenCobalt 2021-03-21 09:56:20 -06:00
parent 824ac56bfa
commit ba79ac0001
No known key found for this signature in database
GPG key ID: 37DBE3621FE9AD47
16 changed files with 51 additions and 40 deletions

View file

@ -30,6 +30,7 @@ fun Any.logE(msg: String) {
/**
* Get a non-nullable name, used so that logs will always show up in the console.
* This also applies a special "Auxio" prefix so that messages can be filtered to just from the main codebase.
* @return The name of the object, otherwise "Anonymous Object"
*/
private fun Any.getName(): String = this::class.simpleName ?: "Anonymous Object"
private fun Any.getName(): String = "Auxio.${this::class.simpleName ?: "Anonymous Object"}"

View file

@ -38,6 +38,8 @@ class MainActivity : AppCompatActivity() {
if (isEdgeOn()) {
setupEdgeToEdge(binding)
}
logD("Activity created.")
}
override fun onStart() {

View file

@ -16,7 +16,6 @@ import androidx.navigation.fragment.findNavController
import com.google.android.material.bottomnavigation.LabelVisibilityMode
import org.oxycblt.auxio.databinding.FragmentMainBinding
import org.oxycblt.auxio.detail.DetailViewModel
import org.oxycblt.auxio.music.MusicStore
import org.oxycblt.auxio.music.Song
import org.oxycblt.auxio.playback.PlaybackViewModel
import org.oxycblt.auxio.ui.Accent
@ -36,18 +35,9 @@ class MainFragment : Fragment() {
inflater: LayoutInflater,
container: ViewGroup?,
savedInstanceState: Bundle?
): View? {
): View {
val binding = FragmentMainBinding.inflate(inflater)
// If the music was cleared while the app was closed [Likely due to Auxio being suspended
// in the background], then navigate back to LoadingFragment to reload the music.
// This may actually not happen in normal use, but its a good failsafe.
if (MusicStore.getInstance().songs.isEmpty()) {
findNavController().navigate(MainFragmentDirections.actionReturnToLoading())
return null
}
val colorActive = Accent.get().color.toColor(requireContext())
val colorInactive = ColorUtils.setAlphaComponent(colorActive, 150)

View file

@ -23,15 +23,15 @@ import org.oxycblt.auxio.settings.SettingsManager
* Bind the album art for a [song].
*/
@BindingAdapter("albumArt")
fun ImageView.bindAlbumArt(song: Song) {
load(song.album, R.drawable.ic_song, AlbumArtFetcher(context))
fun ImageView.bindAlbumArt(song: Song?) {
load(song?.album, R.drawable.ic_song, AlbumArtFetcher(context))
}
/**
* Bind the album art for an [album].
*/
@BindingAdapter("albumArt")
fun ImageView.bindAlbumArt(album: Album) {
fun ImageView.bindAlbumArt(album: Album?) {
load(album, R.drawable.ic_album, AlbumArtFetcher(context))
}
@ -39,7 +39,7 @@ fun ImageView.bindAlbumArt(album: Album) {
* Bind the image for an [artist]
*/
@BindingAdapter("artistImage")
fun ImageView.bindArtistImage(artist: Artist) {
fun ImageView.bindArtistImage(artist: Artist?) {
load(artist, R.drawable.ic_artist, MosaicFetcher(context))
}
@ -47,20 +47,20 @@ fun ImageView.bindArtistImage(artist: Artist) {
* Bind the image for a [genre]
*/
@BindingAdapter("genreImage")
fun ImageView.bindGenreImage(genre: Genre) {
fun ImageView.bindGenreImage(genre: Genre?) {
load(genre, R.drawable.ic_genre, MosaicFetcher(context))
}
/**
* Custom extension function similar to the stock coil load extensions, but handles whether
* to show images and custom fetchers.
* @param T Any datatype that inherits [BaseModel]
* @param T Any datatype that inherits [BaseModel]. This can be null, but keep in mind that it will cause loading to fail.
* @param data The data itself
* @param error Drawable resource to use when loading failed/should not occur.
* @param fetcher Required fetcher that uses [T] as its datatype
*/
inline fun <reified T : BaseModel> ImageView.load(
data: T,
data: T?,
@DrawableRes error: Int,
fetcher: Fetcher<T>,
) {

View file

@ -34,7 +34,6 @@ class MosaicFetcher(private val context: Context) : Fetcher<Parent> {
size: Size,
options: Options
): FetchResult {
options.allowRgb565
// Get the URIs for either a genre or artist
val uris = mutableListOf<Uri>()

View file

@ -77,7 +77,7 @@ class MusicStore private constructor() {
/**
* Find a song from this instance in a safe manner.
* Using a normal search of the songs list runs the risk of getting the *wrong* song with
* the same name, so the album name is used to fix the above problem.
* the same name, so the album name is also used to fix the above problem.
* @param name The name of the song
* @param albumName The name of the song's album.
* @return The song requested, null if there isnt one.

View file

@ -11,7 +11,6 @@ import org.oxycblt.auxio.MainFragmentDirections
import org.oxycblt.auxio.databinding.FragmentCompactPlaybackBinding
import org.oxycblt.auxio.detail.DetailViewModel
import org.oxycblt.auxio.logD
import org.oxycblt.auxio.music.MusicStore
/**
* A [Fragment] that displays the currently played song at a glance, with some basic controls.
@ -34,9 +33,6 @@ class CompactPlaybackFragment : Fragment() {
// --- UI SETUP ---
binding.lifecycleOwner = viewLifecycleOwner
// Put a placeholder song in the binding & hide the playback fragment initially.
binding.song = MusicStore.getInstance().songs[0]
binding.playbackModel = playbackModel
binding.executePendingBindings()

View file

@ -52,12 +52,15 @@ class PlayPauseButton @JvmOverloads constructor(
/**
* Hack that fixes an issue where a seam would display in the middle of the play button,
* probably as a result of floating point precision errors. Gotta love IEEE 754.
* probably as a result of floating point precision errors. Thanks IEEE 754.
*/
@RequiresApi(Build.VERSION_CODES.M)
private fun fixSeams() {
iconPauseToPlay.registerAnimationCallback(object : Animatable2.AnimationCallback() {
override fun onAnimationEnd(drawable: Drawable?) {
// ic_play_large is a unified vector, compared to the two paths on the
// animated vector. So switch to that when the animation completes to prevent the
// seam from displaying.
setImageResource(R.drawable.ic_play_large)
}
})

View file

@ -54,7 +54,6 @@ class PlaybackFragment : Fragment(), SeekBar.OnSeekBarChangeListener {
binding.lifecycleOwner = viewLifecycleOwner
binding.playbackModel = playbackModel
binding.detailModel = detailModel
binding.song = playbackModel.song.value!!
binding.playbackToolbar.apply {
setNavigationOnClickListener {

View file

@ -7,6 +7,7 @@ import androidx.core.animation.addListener
import androidx.media.AudioFocusRequestCompat
import androidx.media.AudioManagerCompat
import com.google.android.exoplayer2.SimpleExoPlayer
import org.oxycblt.auxio.logD
import org.oxycblt.auxio.playback.state.PlaybackStateManager
import org.oxycblt.auxio.settings.SettingsManager
import org.oxycblt.auxio.ui.getSystemServiceSafe
@ -61,9 +62,11 @@ class AudioReactor(
}
private fun onGain() {
if (player.volume == VOLUME_DUCK && playbackManager.isPlaying) {
if (player.volume == VOLUME_DUCK) {
unduck()
} else if (pauseWasTransient) {
logD("Gained focus after transient loss")
// Play again if the pause was only temporary [AudioManager.AUDIOFOCUS_LOSS_TRANSIENT]
playbackManager.setPlaying(true)
pauseWasTransient = false
@ -73,20 +76,28 @@ class AudioReactor(
private fun onLossTransient() {
// Since this loss is only temporary, mark it as such if we had to pause playback.
if (playbackManager.isPlaying) {
pauseWasTransient = true
logD("Pausing for transient loss")
playbackManager.setPlaying(false)
pauseWasTransient = true
}
}
private fun onLossPermanent() {
logD("Pausing for permanent loss")
playbackManager.setPlaying(false)
}
private fun onDuck() {
logD("Ducking, lowering volume")
player.volume = VOLUME_DUCK
}
private fun unduck() {
logD("Unducking, raising volume")
player.volume = VOLUME_DUCK
ValueAnimator().apply {

View file

@ -9,8 +9,10 @@ import android.content.Intent
import android.content.IntentFilter
import android.content.pm.ServiceInfo
import android.media.AudioManager
import android.media.audiofx.Visualizer
import android.os.Build
import android.os.IBinder
import android.os.PowerManager
import android.support.v4.media.MediaMetadataCompat
import android.support.v4.media.session.MediaSessionCompat
import android.view.KeyEvent

View file

@ -20,6 +20,7 @@ import org.oxycblt.auxio.ui.createToast
/**
* The actual fragment containing the settings menu. Inherits [PreferenceFragmentCompat].
* TODO: Roll your own ListPreference that supports int prefs [and is a bottom sheet]
* @author OxygenCobalt
*/
@Suppress("UNUSED")

View file

@ -22,6 +22,7 @@ import com.google.android.material.bottomsheet.BottomSheetDialogFragment
import org.oxycblt.auxio.MainActivity
import org.oxycblt.auxio.R
import org.oxycblt.auxio.databinding.FragmentBlacklistBinding
import org.oxycblt.auxio.logD
import org.oxycblt.auxio.playback.PlaybackViewModel
import org.oxycblt.auxio.ui.createToast
import java.io.File
@ -78,6 +79,8 @@ class BlacklistDialog : BottomSheetDialogFragment() {
binding.blacklistEmptyText.isVisible = paths.isEmpty()
}
logD("Dialog created.")
return binding.root
}
@ -139,6 +142,8 @@ class BlacklistDialog : BottomSheetDialogFragment() {
}
private fun hardRestart() {
logD("Performing hard-restart.")
// Instead of having to do a ton of cleanup and horrible code changes
// to restart this application non-destructively, I just restart the UI task [There is only
// one, after all] and then kill the application using exitProcess. Works well enough.

View file

@ -13,10 +13,10 @@ import org.oxycblt.auxio.ui.toStateList
/**
* An adapter that displays the list of all possible accents, and highlights the current one.
* @author OxygenCobalt
* @param doOnAccentConfirm What to do when an accent is confirmed.
* @param onConfirm What to do when an accent is confirmed.
*/
class AccentAdapter(
private val doOnAccentConfirm: (accent: Accent) -> Unit
private val onConfirm: (accent: Accent) -> Unit
) : RecyclerView.Adapter<AccentAdapter.ViewHolder>() {
override fun getItemCount(): Int = ACCENTS.size
@ -51,7 +51,7 @@ class AccentAdapter(
TooltipCompat.setTooltipText(this, contentDescription)
setOnClickListener {
doOnAccentConfirm(accent)
onConfirm(accent)
}
}
}

View file

@ -13,6 +13,11 @@ import org.oxycblt.auxio.settings.SettingsManager
import org.oxycblt.auxio.ui.ACCENTS
import org.oxycblt.auxio.ui.Accent
/**
* Dialog responsible for showing the list of accents to select.
* TODO: Move this to a Bottom Sheet and eliminate the MaterialDialogs dependency
* @author OxygenCobalt
*/
class AccentDialog : DialogFragment() {
private val settingsManager = SettingsManager.getInstance()

View file

@ -34,14 +34,6 @@ class SongsFragment : Fragment() {
private val playbackModel: PlaybackViewModel by activityViewModels()
private val musicStore = MusicStore.getInstance()
// Lazy init the text size so that it doesn't have to be calculated every time.
private val indicatorTextSize: Float by lazy {
TypedValue.applyDimension(
TypedValue.COMPLEX_UNIT_SP, 14F,
resources.displayMetrics
)
}
override fun onCreateView(
inflater: LayoutInflater,
container: ViewGroup?,
@ -90,9 +82,14 @@ class SongsFragment : Fragment() {
/**
* Perform the (Frustratingly Long and Complicated) FastScrollerView setup.
* TODO: Roll FastScrollerView yourself and eliminate its dependency, you're already customizing it enough as it is.
*/
private fun FastScrollerView.setup(recycler: RecyclerView, thumb: CobaltScrollThumb) {
var truncateInterval: Int = -1
val indicatorTextSize = TypedValue.applyDimension(
TypedValue.COMPLEX_UNIT_SP, 14F,
resources.displayMetrics
)
// API 22 and below don't support the state color, so just use the accent.
if (Build.VERSION.SDK_INT <= Build.VERSION_CODES.M) {