Improve documentation slightly
Add some more documentation to the code.
This commit is contained in:
parent
fd4b7b247f
commit
38afa8f4d2
28 changed files with 188 additions and 53 deletions
|
@ -120,6 +120,9 @@ class MainFragment : Fragment() {
|
|||
return binding.root
|
||||
}
|
||||
|
||||
// Functions that check if MainFragment should nav over to LibraryFragment, or whether
|
||||
// it should stay put. Mostly by checking if the navController is currently in a detail
|
||||
// fragment, and if the playing item is already being shown.
|
||||
private fun shouldGoToAlbum(controller: NavController): Boolean {
|
||||
return (
|
||||
controller.currentDestination!!.id == R.id.album_detail_fragment &&
|
||||
|
@ -157,6 +160,8 @@ class MainFragment : Fragment() {
|
|||
}
|
||||
}
|
||||
|
||||
//
|
||||
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
|
|
@ -11,6 +11,7 @@ package org.oxycblt.auxio.database
|
|||
* @property shuffleSeed - A long for the seed used to shuffle the queue [Used for quick-restore]
|
||||
* @property loopMode - The integer form of the current [org.oxycblt.auxio.playback.state.LoopMode]
|
||||
* @property inUserQueue - A bool for if the state was currently playing from the user queue.
|
||||
* @author OxygenCobalt
|
||||
*/
|
||||
data class PlaybackState(
|
||||
val id: Long = 0L,
|
||||
|
|
|
@ -6,6 +6,7 @@ package org.oxycblt.auxio.database
|
|||
* @property songId The song id for this queue item
|
||||
* @property albumId The album id for this queue item, used to make searching quicker
|
||||
* @property isUserQueue A bool for if this queue item is a user queue item or not
|
||||
* @author OxygenCobalt
|
||||
*/
|
||||
data class QueueItem(
|
||||
var id: Long = 0L,
|
||||
|
|
|
@ -11,13 +11,17 @@ import androidx.navigation.fragment.findNavController
|
|||
import androidx.navigation.fragment.navArgs
|
||||
import org.oxycblt.auxio.R
|
||||
import org.oxycblt.auxio.databinding.FragmentAlbumDetailBinding
|
||||
import org.oxycblt.auxio.detail.adapters.DetailSongAdapter
|
||||
import org.oxycblt.auxio.detail.adapters.AlbumSongAdapter
|
||||
import org.oxycblt.auxio.music.MusicStore
|
||||
import org.oxycblt.auxio.playback.PlaybackViewModel
|
||||
import org.oxycblt.auxio.playback.state.PlaybackMode
|
||||
import org.oxycblt.auxio.ui.disable
|
||||
import org.oxycblt.auxio.ui.setupAlbumSongActions
|
||||
|
||||
/**
|
||||
* The [DetailFragment] for an album.
|
||||
* @author OxygenCobalt
|
||||
*/
|
||||
class AlbumDetailFragment : DetailFragment() {
|
||||
|
||||
private val args: AlbumDetailFragmentArgs by navArgs()
|
||||
|
@ -42,7 +46,7 @@ class AlbumDetailFragment : DetailFragment() {
|
|||
)
|
||||
}
|
||||
|
||||
val songAdapter = DetailSongAdapter(
|
||||
val songAdapter = AlbumSongAdapter(
|
||||
doOnClick = { playbackModel.playSong(it, PlaybackMode.IN_ALBUM) },
|
||||
doOnLongClick = { data, view ->
|
||||
PopupMenu(requireContext(), view).setupAlbumSongActions(
|
||||
|
|
|
@ -11,13 +11,17 @@ import androidx.navigation.fragment.findNavController
|
|||
import androidx.navigation.fragment.navArgs
|
||||
import org.oxycblt.auxio.R
|
||||
import org.oxycblt.auxio.databinding.FragmentArtistDetailBinding
|
||||
import org.oxycblt.auxio.detail.adapters.DetailAlbumAdapter
|
||||
import org.oxycblt.auxio.detail.adapters.ArtistAlbumAdapter
|
||||
import org.oxycblt.auxio.music.Artist
|
||||
import org.oxycblt.auxio.music.MusicStore
|
||||
import org.oxycblt.auxio.playback.PlaybackViewModel
|
||||
import org.oxycblt.auxio.ui.disable
|
||||
import org.oxycblt.auxio.ui.setupAlbumActions
|
||||
|
||||
/**
|
||||
* The [DetailFragment] for an artist.
|
||||
* @author OxygenCobalt
|
||||
*/
|
||||
class ArtistDetailFragment : DetailFragment() {
|
||||
private val args: ArtistDetailFragmentArgs by navArgs()
|
||||
private val playbackModel: PlaybackViewModel by activityViewModels()
|
||||
|
@ -41,7 +45,7 @@ class ArtistDetailFragment : DetailFragment() {
|
|||
)
|
||||
}
|
||||
|
||||
val albumAdapter = DetailAlbumAdapter(
|
||||
val albumAdapter = ArtistAlbumAdapter(
|
||||
doOnClick = {
|
||||
if (!detailModel.isNavigating) {
|
||||
detailModel.updateNavigationStatus(true)
|
||||
|
|
|
@ -8,7 +8,10 @@ import org.oxycblt.auxio.music.Artist
|
|||
import org.oxycblt.auxio.music.Genre
|
||||
import org.oxycblt.auxio.recycler.SortMode
|
||||
|
||||
// ViewModel for the Detail Fragments.
|
||||
/**
|
||||
* ViewModel that stores data for the [DetailFragment]s, such as what they're showing & what
|
||||
* [SortMode] they are currently on.
|
||||
*/
|
||||
class DetailViewModel : ViewModel() {
|
||||
private var mIsNavigating = false
|
||||
val isNavigating: Boolean get() = mIsNavigating
|
||||
|
|
|
@ -11,12 +11,16 @@ import androidx.navigation.fragment.findNavController
|
|||
import androidx.navigation.fragment.navArgs
|
||||
import org.oxycblt.auxio.R
|
||||
import org.oxycblt.auxio.databinding.FragmentGenreDetailBinding
|
||||
import org.oxycblt.auxio.detail.adapters.DetailArtistAdapter
|
||||
import org.oxycblt.auxio.detail.adapters.GenreArtistAdapter
|
||||
import org.oxycblt.auxio.music.MusicStore
|
||||
import org.oxycblt.auxio.playback.PlaybackViewModel
|
||||
import org.oxycblt.auxio.ui.disable
|
||||
import org.oxycblt.auxio.ui.setupArtistActions
|
||||
|
||||
/**
|
||||
* The [DetailFragment] for a genre.
|
||||
* @author OxygenCobalt
|
||||
*/
|
||||
class GenreDetailFragment : DetailFragment() {
|
||||
|
||||
private val args: GenreDetailFragmentArgs by navArgs()
|
||||
|
@ -41,7 +45,7 @@ class GenreDetailFragment : DetailFragment() {
|
|||
)
|
||||
}
|
||||
|
||||
val artistAdapter = DetailArtistAdapter(
|
||||
val artistAdapter = GenreArtistAdapter(
|
||||
doOnClick = {
|
||||
if (!detailModel.isNavigating) {
|
||||
detailModel.updateNavigationStatus(true)
|
||||
|
|
|
@ -9,10 +9,13 @@ import org.oxycblt.auxio.music.Song
|
|||
import org.oxycblt.auxio.recycler.DiffCallback
|
||||
import org.oxycblt.auxio.recycler.viewholders.BaseViewHolder
|
||||
|
||||
class DetailSongAdapter(
|
||||
/**
|
||||
* An adapter for displaying the [Song]s of an album.
|
||||
*/
|
||||
class AlbumSongAdapter(
|
||||
private val doOnClick: (data: Song) -> Unit,
|
||||
private val doOnLongClick: (data: Song, view: View) -> Unit
|
||||
) : ListAdapter<Song, DetailSongAdapter.ViewHolder>(DiffCallback()) {
|
||||
) : ListAdapter<Song, AlbumSongAdapter.ViewHolder>(DiffCallback()) {
|
||||
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
|
||||
return ViewHolder(
|
||||
ItemAlbumSongBinding.inflate(LayoutInflater.from(parent.context))
|
|
@ -10,7 +10,10 @@ import org.oxycblt.auxio.music.Album
|
|||
import org.oxycblt.auxio.recycler.DiffCallback
|
||||
import org.oxycblt.auxio.recycler.viewholders.BaseViewHolder
|
||||
|
||||
class DetailAlbumAdapter(
|
||||
/**
|
||||
* An adapter for displaying the [Album]s of an artist.
|
||||
*/
|
||||
class ArtistAlbumAdapter(
|
||||
private val doOnClick: (data: Album) -> Unit,
|
||||
private val doOnLongClick: (data: Album, view: View) -> Unit,
|
||||
) : ListAdapter<Album, RecyclerView.ViewHolder>(DiffCallback()) {
|
|
@ -9,10 +9,13 @@ import org.oxycblt.auxio.music.Artist
|
|||
import org.oxycblt.auxio.recycler.DiffCallback
|
||||
import org.oxycblt.auxio.recycler.viewholders.BaseViewHolder
|
||||
|
||||
class DetailArtistAdapter(
|
||||
/**
|
||||
* An adapter for displaying the [Artist]s of an genre.
|
||||
*/
|
||||
class GenreArtistAdapter(
|
||||
private val doOnClick: (data: Artist) -> Unit,
|
||||
private val doOnLongClick: (data: Artist, view: View) -> Unit
|
||||
) : ListAdapter<Artist, DetailArtistAdapter.ViewHolder>(DiffCallback()) {
|
||||
) : ListAdapter<Artist, GenreArtistAdapter.ViewHolder>(DiffCallback()) {
|
||||
|
||||
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
|
||||
return ViewHolder(
|
|
@ -69,7 +69,7 @@ class LibraryFragment : Fragment(), SearchView.OnQueryTextListener {
|
|||
|
||||
setOnMenuItemClickListener {
|
||||
if (it.itemId != R.id.action_search) {
|
||||
libraryModel.updateSortMode(it)
|
||||
libraryModel.updateSortMode(it.itemId)
|
||||
} else {
|
||||
// Do whatever this is in order to make the SearchView focusable.
|
||||
(it.actionView as SearchView).isIconified = false
|
||||
|
@ -92,7 +92,7 @@ class LibraryFragment : Fragment(), SearchView.OnQueryTextListener {
|
|||
searchView.setOnQueryTextListener(this@LibraryFragment)
|
||||
searchView.setOnQueryTextFocusChangeListener { _, hasFocus ->
|
||||
libraryModel.updateSearchFocusStatus(hasFocus)
|
||||
libraryModel.updateSearchQuery(searchView.query.toString(), requireContext())
|
||||
libraryModel.doSearch(searchView.query.toString(), requireContext())
|
||||
item.isVisible = !hasFocus
|
||||
}
|
||||
|
||||
|
@ -177,7 +177,7 @@ class LibraryFragment : Fragment(), SearchView.OnQueryTextListener {
|
|||
override fun onQueryTextSubmit(query: String): Boolean = false
|
||||
|
||||
override fun onQueryTextChange(query: String): Boolean {
|
||||
libraryModel.updateSearchQuery(query, requireContext())
|
||||
libraryModel.doSearch(query, requireContext())
|
||||
|
||||
return true
|
||||
}
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
package org.oxycblt.auxio.library
|
||||
|
||||
import android.content.Context
|
||||
import android.view.MenuItem
|
||||
import androidx.annotation.IdRes
|
||||
import androidx.lifecycle.LiveData
|
||||
import androidx.lifecycle.MutableLiveData
|
||||
import androidx.lifecycle.ViewModel
|
||||
|
@ -14,6 +14,11 @@ import org.oxycblt.auxio.music.MusicStore
|
|||
import org.oxycblt.auxio.recycler.ShowMode
|
||||
import org.oxycblt.auxio.recycler.SortMode
|
||||
|
||||
/**
|
||||
* A [ViewModel] that manages what [LibraryFragment] is currently showing, and also the search
|
||||
* functionality.
|
||||
* @author OxygenCobalt
|
||||
*/
|
||||
class LibraryViewModel : ViewModel() {
|
||||
private var mIsNavigating = false
|
||||
val isNavigating: Boolean get() = mIsNavigating
|
||||
|
@ -31,21 +36,13 @@ class LibraryViewModel : ViewModel() {
|
|||
private val mSearchResults = MutableLiveData(listOf<BaseModel>())
|
||||
val searchResults: LiveData<List<BaseModel>> get() = mSearchResults
|
||||
|
||||
fun updateSortMode(item: MenuItem) {
|
||||
val mode = when (item.itemId) {
|
||||
R.id.option_sort_none -> SortMode.NONE
|
||||
R.id.option_sort_alpha_down -> SortMode.ALPHA_DOWN
|
||||
R.id.option_sort_alpha_up -> SortMode.ALPHA_UP
|
||||
|
||||
else -> SortMode.NONE
|
||||
}
|
||||
|
||||
if (mode != mSortMode.value) {
|
||||
mSortMode.value = mode
|
||||
}
|
||||
}
|
||||
|
||||
fun updateSearchQuery(query: String, context: Context) {
|
||||
/**
|
||||
* Perform a search of the music library, given a query.
|
||||
* Results are pushed to [searchResults].
|
||||
* @param query The query for this search
|
||||
* @param context The context needed to create the header text
|
||||
*/
|
||||
fun doSearch(query: String, context: Context) {
|
||||
// Don't bother if the query is blank.
|
||||
if (query == "") {
|
||||
resetQuery()
|
||||
|
@ -110,4 +107,18 @@ class LibraryViewModel : ViewModel() {
|
|||
fun updateSearchFocusStatus(value: Boolean) {
|
||||
mSearchHasFocus = value
|
||||
}
|
||||
|
||||
fun updateSortMode(@IdRes itemId: Int) {
|
||||
val mode = when (itemId) {
|
||||
R.id.option_sort_none -> SortMode.NONE
|
||||
R.id.option_sort_alpha_down -> SortMode.ALPHA_DOWN
|
||||
R.id.option_sort_alpha_up -> SortMode.ALPHA_UP
|
||||
|
||||
else -> SortMode.NONE
|
||||
}
|
||||
|
||||
if (mode != mSortMode.value) {
|
||||
mSortMode.value = mode
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -12,7 +12,10 @@ import org.oxycblt.auxio.recycler.viewholders.AlbumViewHolder
|
|||
import org.oxycblt.auxio.recycler.viewholders.ArtistViewHolder
|
||||
import org.oxycblt.auxio.recycler.viewholders.GenreViewHolder
|
||||
|
||||
// The primary RecyclerView adapter for the library. Displays genres, artists, and albums.
|
||||
/**
|
||||
* The primary recyclerview for the library. Can display either Genres, Artists, and Albums.
|
||||
* @author OxygenCobalt
|
||||
*/
|
||||
class LibraryAdapter(
|
||||
private val showMode: ShowMode,
|
||||
private val doOnClick: (data: BaseModel) -> Unit,
|
||||
|
|
|
@ -17,6 +17,10 @@ import org.oxycblt.auxio.recycler.viewholders.GenreViewHolder
|
|||
import org.oxycblt.auxio.recycler.viewholders.HeaderViewHolder
|
||||
import org.oxycblt.auxio.recycler.viewholders.SongViewHolder
|
||||
|
||||
/**
|
||||
* A Multi-ViewHolder adapter that displays the results of a search query.
|
||||
* @author OxygenCobalt
|
||||
*/
|
||||
class SearchAdapter(
|
||||
private val doOnClick: (data: BaseModel) -> Unit,
|
||||
private val doOnLongClick: (data: BaseModel, view: View) -> Unit
|
||||
|
|
|
@ -17,6 +17,11 @@ import org.oxycblt.auxio.databinding.FragmentLoadingBinding
|
|||
import org.oxycblt.auxio.music.MusicStore
|
||||
import org.oxycblt.auxio.music.processing.MusicLoaderResponse
|
||||
|
||||
/**
|
||||
* The intermediary [Fragment] that asks for the READ_EXTERNAL_STORAGE permission and runs
|
||||
* the music loading process in the background.
|
||||
* @author OxygenCobalt
|
||||
*/
|
||||
class LoadingFragment : Fragment(R.layout.fragment_loading) {
|
||||
|
||||
private val loadingModel: LoadingViewModel by activityViewModels {
|
||||
|
|
|
@ -12,6 +12,11 @@ import kotlinx.coroutines.withContext
|
|||
import org.oxycblt.auxio.music.MusicStore
|
||||
import org.oxycblt.auxio.music.processing.MusicLoaderResponse
|
||||
|
||||
/**
|
||||
* A [ViewModel] responsible for getting the music loading process going and managing the response
|
||||
* returned.
|
||||
* @author OxygenCobalt
|
||||
*/
|
||||
class LoadingViewModel(private val app: Application) : ViewModel() {
|
||||
// UI control
|
||||
private val mResponse = MutableLiveData<MusicLoaderResponse>()
|
||||
|
|
|
@ -9,7 +9,8 @@ import org.oxycblt.auxio.music.processing.MusicSorter
|
|||
import org.oxycblt.auxio.recycler.ShowMode
|
||||
|
||||
/**
|
||||
* The main storage for music items. Use [MusicStore.getInstance] to get the instance.
|
||||
* The main storage for music items. Use [MusicStore.getInstance] to get the single instance of it.
|
||||
* TODO: Add a viewmodel so that UI elements aren't messing with the shared object.
|
||||
*/
|
||||
class MusicStore private constructor() {
|
||||
private var mGenres = listOf<Genre>()
|
||||
|
|
|
@ -80,6 +80,7 @@ class PlaybackService : Service(), Player.EventListener, PlaybackStateManager.Ca
|
|||
return START_NOT_STICKY
|
||||
}
|
||||
|
||||
// No binding, service is headless. Deliver updates through PlaybackStateManager instead.
|
||||
override fun onBind(intent: Intent): IBinder? = null
|
||||
|
||||
override fun onCreate() {
|
||||
|
|
|
@ -20,7 +20,7 @@ import org.oxycblt.auxio.playback.state.PlaybackMode
|
|||
import org.oxycblt.auxio.playback.state.PlaybackStateManager
|
||||
|
||||
/**
|
||||
* The ViewModel that provides a UI-Focused frontend for [PlaybackStateManager].
|
||||
* The ViewModel that provides a UI frontend for [PlaybackStateManager].
|
||||
* @author OxygenCobalt
|
||||
*/
|
||||
class PlaybackViewModel : ViewModel(), PlaybackStateManager.Callback {
|
||||
|
|
|
@ -95,10 +95,13 @@ class QueueAdapter(
|
|||
fun removeItem(adapterIndex: Int) {
|
||||
data.removeAt(adapterIndex)
|
||||
|
||||
// Check for two things:
|
||||
// If the data from the next queue is now entirely empty [Signified by a header at the end]
|
||||
// Or if the data from the last queue is now entirely empty [Signified by there being 2 headers with no items in between]
|
||||
// If so, remove that item and the removed item in a range. Otherwise just remove the item.
|
||||
/*
|
||||
* Check for two things:
|
||||
* If the data from the next queue is now entirely empty [Signified by a header at the end]
|
||||
* Or if the data from the last queue is now entirely empty [Signified by there being
|
||||
* 2 headers with no items in between]
|
||||
* If so, remove the header and the removed item in a range. Otherwise just remove the item.
|
||||
*/
|
||||
if (data[data.lastIndex] is Header) {
|
||||
val lastIndex = data.lastIndex
|
||||
|
||||
|
@ -114,7 +117,7 @@ class QueueAdapter(
|
|||
}
|
||||
}
|
||||
|
||||
fun clearUserQueue() {
|
||||
private fun clearUserQueue() {
|
||||
val nextQueueHeaderIndex = data.indexOfLast { it is Header }
|
||||
val slice = data.slice(0 until nextQueueHeaderIndex)
|
||||
|
||||
|
|
|
@ -8,7 +8,11 @@ import kotlin.math.max
|
|||
import kotlin.math.min
|
||||
import kotlin.math.sign
|
||||
|
||||
// The drag callback used for the Queue RecyclerView.
|
||||
/**
|
||||
* The Drag callback used by the queue recyclerview. Delivers updates to [PlaybackViewModel]
|
||||
* and [QueueAdapter] simultaneously.
|
||||
* @author OxygenCobalt
|
||||
*/
|
||||
class QueueDragCallback(private val playbackModel: PlaybackViewModel) : ItemTouchHelper.Callback() {
|
||||
private lateinit var queueAdapter: QueueAdapter
|
||||
|
||||
|
|
|
@ -20,6 +20,7 @@ import org.oxycblt.auxio.playback.state.PlaybackMode
|
|||
* edit them as well.
|
||||
*
|
||||
* Instantiation is done by the navigation component, **do not instantiate this fragment manually.**
|
||||
* @author OxygenCobalt
|
||||
*/
|
||||
class QueueFragment : Fragment() {
|
||||
private val playbackModel: PlaybackViewModel by activityViewModels()
|
||||
|
|
|
@ -3,7 +3,11 @@ package org.oxycblt.auxio.recycler
|
|||
import androidx.recyclerview.widget.DiffUtil
|
||||
import org.oxycblt.auxio.music.BaseModel
|
||||
|
||||
// Base Diff callback
|
||||
/**
|
||||
* A re-usable diff callback for all [BaseModel] implementations.
|
||||
* **Use this instead of creating a DiffCallback for each adapter.**
|
||||
* @author OxygenCobalt
|
||||
*/
|
||||
class DiffCallback<T : BaseModel> : DiffUtil.ItemCallback<T>() {
|
||||
override fun areContentsTheSame(oldItem: T, newItem: T): Boolean {
|
||||
return oldItem.hashCode() == newItem.hashCode()
|
||||
|
|
|
@ -1,10 +1,18 @@
|
|||
package org.oxycblt.auxio.recycler
|
||||
|
||||
/**
|
||||
* An enum for determining what items to show in a given list.
|
||||
* @author OxygenCobalt
|
||||
*/
|
||||
enum class ShowMode {
|
||||
SHOW_GENRES, SHOW_ARTISTS, SHOW_ALBUMS, SHOW_SONGS;
|
||||
|
||||
// Make a slice of all the values that this ShowMode covers.
|
||||
// ex. SHOW_ARTISTS would return SHOW_ARTISTS, SHOW_ALBUMS, and SHOW_SONGS
|
||||
/**
|
||||
* Make a slice of all the values that this ShowMode covers.
|
||||
*
|
||||
* ex. SHOW_ARTISTS would return SHOW_ARTISTS, SHOW_ALBUMS, and SHOW_SONGS
|
||||
* @return The values that this ShowMode covers.
|
||||
*/
|
||||
fun getChildren(): List<ShowMode> {
|
||||
val vals = values()
|
||||
|
||||
|
|
|
@ -6,7 +6,12 @@ import org.oxycblt.auxio.music.Artist
|
|||
import org.oxycblt.auxio.music.BaseModel
|
||||
import org.oxycblt.auxio.music.Song
|
||||
|
||||
// Sorting modes
|
||||
/**
|
||||
* An enum for the current sorting mode. Contains helper functions to sort lists based
|
||||
* off the given sorting mode.
|
||||
* @property iconRes The icon for this [SortMode]
|
||||
* @author OxygenCobalt
|
||||
*/
|
||||
enum class SortMode(val iconRes: Int) {
|
||||
// Icons for each mode are assigned to the enums themselves
|
||||
NONE(R.drawable.ic_sort_none),
|
||||
|
|
|
@ -15,6 +15,11 @@ import org.oxycblt.auxio.playback.PlaybackViewModel
|
|||
import org.oxycblt.auxio.playback.state.PlaybackMode
|
||||
import org.oxycblt.auxio.ui.setupSongActions
|
||||
|
||||
/**
|
||||
* A [Fragment] that shows a list of all songs on the device. Contains options to search/shuffle
|
||||
* them.
|
||||
* @author OxygenCobalt
|
||||
*/
|
||||
class SongsFragment : Fragment() {
|
||||
private val playbackModel: PlaybackViewModel by activityViewModels()
|
||||
|
||||
|
|
|
@ -21,7 +21,10 @@ import org.oxycblt.auxio.playback.state.PlaybackMode
|
|||
|
||||
// Functions for managing UI elements [Not Colors]
|
||||
|
||||
// Apply a color to a Menu Item
|
||||
/**
|
||||
* Apply a text color to a [MenuItem]
|
||||
* @param color The text color that should be applied.
|
||||
*/
|
||||
fun MenuItem.applyColor(@ColorInt color: Int) {
|
||||
SpannableString(title).apply {
|
||||
setSpan(ForegroundColorSpan(color), 0, length, SpannableString.SPAN_EXCLUSIVE_EXCLUSIVE)
|
||||
|
@ -29,7 +32,10 @@ fun MenuItem.applyColor(@ColorInt color: Int) {
|
|||
}
|
||||
}
|
||||
|
||||
// Disable an ImageButton
|
||||
/**
|
||||
* Disable an image button.
|
||||
* @param context [Context] required to change the [ImageButton]s color.
|
||||
*/
|
||||
fun ImageButton.disable(context: Context) {
|
||||
if (isEnabled) {
|
||||
imageTintList = ColorStateList.valueOf(
|
||||
|
@ -40,10 +46,17 @@ fun ImageButton.disable(context: Context) {
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a [Toast] from a [String]
|
||||
* @param context [Context] required to create the toast
|
||||
*/
|
||||
fun String.createToast(context: Context) {
|
||||
Toast.makeText(context.applicationContext, this, Toast.LENGTH_SHORT).show()
|
||||
}
|
||||
|
||||
/**
|
||||
* Show actions for a song item, such as the ones found in [org.oxycblt.auxio.songs.SongsFragment]
|
||||
*/
|
||||
fun PopupMenu.setupSongActions(song: Song, context: Context, playbackModel: PlaybackViewModel) {
|
||||
setOnMenuItemClickListener {
|
||||
when (it.itemId) {
|
||||
|
@ -68,11 +81,13 @@ fun PopupMenu.setupSongActions(song: Song, context: Context, playbackModel: Play
|
|||
}
|
||||
inflateAndShow(R.menu.menu_song_actions)
|
||||
}
|
||||
|
||||
/**
|
||||
* Show actions for a song item, such as the ones found in [org.oxycblt.auxio.songs.SongsFragment]
|
||||
*/
|
||||
fun PopupMenu.setupAlbumSongActions(
|
||||
song: Song,
|
||||
context: Context,
|
||||
detailViewModel: DetailViewModel,
|
||||
detailModel: DetailViewModel,
|
||||
playbackModel: PlaybackViewModel
|
||||
) {
|
||||
setOnMenuItemClickListener {
|
||||
|
@ -85,7 +100,7 @@ fun PopupMenu.setupAlbumSongActions(
|
|||
}
|
||||
|
||||
R.id.action_go_artist -> {
|
||||
detailViewModel.doNavToParent()
|
||||
detailModel.doNavToParent()
|
||||
true
|
||||
}
|
||||
|
||||
|
@ -100,6 +115,9 @@ fun PopupMenu.setupAlbumSongActions(
|
|||
inflateAndShow(R.menu.menu_album_song_actions)
|
||||
}
|
||||
|
||||
/**
|
||||
* Show actions for an [Album]
|
||||
*/
|
||||
fun PopupMenu.setupAlbumActions(
|
||||
album: Album,
|
||||
context: Context,
|
||||
|
@ -130,6 +148,9 @@ fun PopupMenu.setupAlbumActions(
|
|||
inflateAndShow(R.menu.menu_album_actions)
|
||||
}
|
||||
|
||||
/**
|
||||
* Show actions for an [Artist]
|
||||
*/
|
||||
fun PopupMenu.setupArtistActions(
|
||||
artist: Artist,
|
||||
context: Context,
|
||||
|
@ -160,6 +181,9 @@ fun PopupMenu.setupArtistActions(
|
|||
inflateAndShow(R.menu.menu_detail)
|
||||
}
|
||||
|
||||
/**
|
||||
* Show actions for a [Genre]
|
||||
*/
|
||||
fun PopupMenu.setupGenreActions(
|
||||
genre: Genre,
|
||||
context: Context,
|
||||
|
@ -190,6 +214,9 @@ fun PopupMenu.setupGenreActions(
|
|||
inflateAndShow(R.menu.menu_detail)
|
||||
}
|
||||
|
||||
/**
|
||||
* Shortcut method that inflates a menu and shows the action menu.
|
||||
*/
|
||||
private fun PopupMenu.inflateAndShow(@MenuRes menuRes: Int) {
|
||||
inflate(menuRes)
|
||||
show()
|
||||
|
|
|
@ -36,7 +36,13 @@ private val ACCENTS = listOf(
|
|||
|
||||
val accent = ACCENTS[5]
|
||||
|
||||
// Get the transparent variant of a color int
|
||||
/**
|
||||
* Gets the transparent form of a color.
|
||||
* @param context [Context] required to create the color
|
||||
* @param color The RESOURCE ID for the color
|
||||
* @param alpha The new alpha that wants to be applied
|
||||
* @return The new, resolved transparent color
|
||||
*/
|
||||
@ColorInt
|
||||
fun getTransparentAccent(context: Context, @ColorRes color: Int, alpha: Int): Int {
|
||||
return ColorUtils.setAlphaComponent(
|
||||
|
@ -45,13 +51,19 @@ fun getTransparentAccent(context: Context, @ColorRes color: Int, alpha: Int): In
|
|||
)
|
||||
}
|
||||
|
||||
// Get the inactive transparency of an accent
|
||||
/**
|
||||
* Get the inactive alpha of an accent.
|
||||
*/
|
||||
@ColorInt
|
||||
fun getInactiveAlpha(@ColorRes color: Int): Int {
|
||||
return if (color == R.color.yellow) 100 else 150
|
||||
}
|
||||
|
||||
// Convert an integer to a color
|
||||
/**
|
||||
* Resolve a color.
|
||||
* @param context [Context] required
|
||||
* @return The resolved color, black if the resolving process failed.
|
||||
*/
|
||||
@ColorInt
|
||||
fun Int.toColor(context: Context): Int {
|
||||
return try {
|
||||
|
@ -62,7 +74,12 @@ fun Int.toColor(context: Context): Int {
|
|||
}
|
||||
}
|
||||
|
||||
// Resolve an attribute into a color
|
||||
/**
|
||||
* Resolve an attribute into a color.
|
||||
* @param context [Context] required
|
||||
* @param attr The Resource ID for the attribute
|
||||
* @return The resolved color for that attribute. Black if the process failed.
|
||||
*/
|
||||
@ColorInt
|
||||
fun resolveAttr(context: Context, @AttrRes attr: Int): Int {
|
||||
// Convert the attribute into its color
|
||||
|
|
Loading…
Reference in a new issue