all: refactor utils
Do the final utility refactor, placing custom views into a .ui submodule and the general utils into a new .util module. This system seems to stick well.
This commit is contained in:
parent
9aa2c99be4
commit
5fe01777d0
69 changed files with 476 additions and 483 deletions
|
@ -32,6 +32,9 @@ import org.oxycblt.auxio.databinding.ActivityMainBinding
|
|||
import org.oxycblt.auxio.playback.PlaybackViewModel
|
||||
import org.oxycblt.auxio.playback.system.PlaybackService
|
||||
import org.oxycblt.auxio.settings.SettingsManager
|
||||
import org.oxycblt.auxio.util.isEdgeOn
|
||||
import org.oxycblt.auxio.util.isNight
|
||||
import org.oxycblt.auxio.util.logD
|
||||
|
||||
/**
|
||||
* The single [AppCompatActivity] for Auxio.
|
||||
|
|
|
@ -27,6 +27,8 @@ import androidx.fragment.app.activityViewModels
|
|||
import org.oxycblt.auxio.databinding.FragmentMainBinding
|
||||
import org.oxycblt.auxio.music.Song
|
||||
import org.oxycblt.auxio.playback.PlaybackViewModel
|
||||
import org.oxycblt.auxio.util.isLandscape
|
||||
import org.oxycblt.auxio.util.logD
|
||||
|
||||
/**
|
||||
* A wrapper around the home fragment that shows the playback fragment and controls
|
||||
|
|
|
@ -27,7 +27,7 @@ import androidx.annotation.StringRes
|
|||
import androidx.annotation.StyleRes
|
||||
import androidx.core.text.HtmlCompat
|
||||
import org.oxycblt.auxio.R
|
||||
import org.oxycblt.auxio.resolveStateList
|
||||
import org.oxycblt.auxio.util.resolveStateList
|
||||
|
||||
/**
|
||||
* A list of all possible accents.
|
||||
|
|
|
@ -23,8 +23,8 @@ import androidx.appcompat.widget.TooltipCompat
|
|||
import androidx.recyclerview.widget.RecyclerView
|
||||
import org.oxycblt.auxio.R
|
||||
import org.oxycblt.auxio.databinding.ItemAccentBinding
|
||||
import org.oxycblt.auxio.inflater
|
||||
import org.oxycblt.auxio.resolveStateList
|
||||
import org.oxycblt.auxio.util.inflater
|
||||
import org.oxycblt.auxio.util.resolveStateList
|
||||
|
||||
/**
|
||||
* An adapter that displays the list of all possible accents, and highlights the current one.
|
||||
|
|
|
@ -26,10 +26,10 @@ import androidx.appcompat.app.AlertDialog
|
|||
import org.oxycblt.auxio.BuildConfig
|
||||
import org.oxycblt.auxio.R
|
||||
import org.oxycblt.auxio.databinding.DialogAccentBinding
|
||||
import org.oxycblt.auxio.logD
|
||||
import org.oxycblt.auxio.resolveColor
|
||||
import org.oxycblt.auxio.settings.SettingsManager
|
||||
import org.oxycblt.auxio.ui.LifecycleDialog
|
||||
import org.oxycblt.auxio.util.logD
|
||||
import org.oxycblt.auxio.util.resolveColor
|
||||
|
||||
/**
|
||||
* Dialog responsible for showing the list of accents to select.
|
||||
|
@ -100,7 +100,7 @@ class AccentDialog : LifecycleDialog() {
|
|||
}
|
||||
|
||||
companion object {
|
||||
const val TAG = "TAG_ACCENT_DIALOG"
|
||||
const val TAG = BuildConfig.APPLICATION_ID + ".tag.ACCENT_PICKER"
|
||||
const val KEY_PENDING_ACCENT = BuildConfig.APPLICATION_ID + ".key.PENDING_ACCENT"
|
||||
}
|
||||
}
|
||||
|
|
|
@ -27,18 +27,18 @@ import androidx.navigation.fragment.findNavController
|
|||
import androidx.navigation.fragment.navArgs
|
||||
import androidx.recyclerview.widget.LinearSmoothScroller
|
||||
import org.oxycblt.auxio.R
|
||||
import org.oxycblt.auxio.canScroll
|
||||
import org.oxycblt.auxio.detail.adapters.AlbumDetailAdapter
|
||||
import org.oxycblt.auxio.logD
|
||||
import org.oxycblt.auxio.music.Album
|
||||
import org.oxycblt.auxio.music.Artist
|
||||
import org.oxycblt.auxio.music.BaseModel
|
||||
import org.oxycblt.auxio.music.MusicStore
|
||||
import org.oxycblt.auxio.music.Song
|
||||
import org.oxycblt.auxio.playback.state.PlaybackMode
|
||||
import org.oxycblt.auxio.showToast
|
||||
import org.oxycblt.auxio.ui.ActionMenu
|
||||
import org.oxycblt.auxio.ui.newMenu
|
||||
import org.oxycblt.auxio.util.canScroll
|
||||
import org.oxycblt.auxio.util.logD
|
||||
import org.oxycblt.auxio.util.showToast
|
||||
|
||||
/**
|
||||
* The [DetailFragment] for an album.
|
||||
|
|
|
@ -26,7 +26,6 @@ import androidx.navigation.fragment.findNavController
|
|||
import androidx.navigation.fragment.navArgs
|
||||
import org.oxycblt.auxio.R
|
||||
import org.oxycblt.auxio.detail.adapters.ArtistDetailAdapter
|
||||
import org.oxycblt.auxio.logD
|
||||
import org.oxycblt.auxio.music.Album
|
||||
import org.oxycblt.auxio.music.Artist
|
||||
import org.oxycblt.auxio.music.BaseModel
|
||||
|
@ -34,9 +33,10 @@ import org.oxycblt.auxio.music.Header
|
|||
import org.oxycblt.auxio.music.MusicStore
|
||||
import org.oxycblt.auxio.music.Song
|
||||
import org.oxycblt.auxio.playback.state.PlaybackMode
|
||||
import org.oxycblt.auxio.recycler.SortMode
|
||||
import org.oxycblt.auxio.ui.ActionMenu
|
||||
import org.oxycblt.auxio.ui.SortMode
|
||||
import org.oxycblt.auxio.ui.newMenu
|
||||
import org.oxycblt.auxio.util.logD
|
||||
|
||||
/**
|
||||
* The [DetailFragment] for an artist.
|
||||
|
|
|
@ -28,9 +28,9 @@ import androidx.navigation.fragment.findNavController
|
|||
import androidx.recyclerview.widget.GridLayoutManager
|
||||
import androidx.recyclerview.widget.RecyclerView
|
||||
import org.oxycblt.auxio.databinding.FragmentDetailBinding
|
||||
import org.oxycblt.auxio.isLandscape
|
||||
import org.oxycblt.auxio.playback.PlaybackViewModel
|
||||
import org.oxycblt.auxio.ui.memberBinding
|
||||
import org.oxycblt.auxio.util.isLandscape
|
||||
|
||||
/**
|
||||
* A Base [Fragment] implementing the base features shared across all detail fragments.
|
||||
|
|
|
@ -25,8 +25,8 @@ import org.oxycblt.auxio.music.Album
|
|||
import org.oxycblt.auxio.music.Artist
|
||||
import org.oxycblt.auxio.music.BaseModel
|
||||
import org.oxycblt.auxio.music.Genre
|
||||
import org.oxycblt.auxio.recycler.SortMode
|
||||
import org.oxycblt.auxio.settings.SettingsManager
|
||||
import org.oxycblt.auxio.ui.SortMode
|
||||
|
||||
/**
|
||||
* ViewModel that stores data for the [DetailFragment]s, such as what they're showing & what
|
||||
|
|
|
@ -25,7 +25,6 @@ import android.view.ViewGroup
|
|||
import androidx.navigation.fragment.findNavController
|
||||
import androidx.navigation.fragment.navArgs
|
||||
import org.oxycblt.auxio.detail.adapters.GenreDetailAdapter
|
||||
import org.oxycblt.auxio.logD
|
||||
import org.oxycblt.auxio.music.Album
|
||||
import org.oxycblt.auxio.music.Artist
|
||||
import org.oxycblt.auxio.music.BaseModel
|
||||
|
@ -34,6 +33,7 @@ import org.oxycblt.auxio.music.Song
|
|||
import org.oxycblt.auxio.playback.state.PlaybackMode
|
||||
import org.oxycblt.auxio.ui.ActionMenu
|
||||
import org.oxycblt.auxio.ui.newMenu
|
||||
import org.oxycblt.auxio.util.logD
|
||||
|
||||
/**
|
||||
* The [DetailFragment] for a genre.
|
||||
|
|
|
@ -27,15 +27,15 @@ import org.oxycblt.auxio.accent.Accent
|
|||
import org.oxycblt.auxio.databinding.ItemAlbumHeaderBinding
|
||||
import org.oxycblt.auxio.databinding.ItemAlbumSongBinding
|
||||
import org.oxycblt.auxio.detail.DetailViewModel
|
||||
import org.oxycblt.auxio.disable
|
||||
import org.oxycblt.auxio.inflater
|
||||
import org.oxycblt.auxio.music.Album
|
||||
import org.oxycblt.auxio.music.BaseModel
|
||||
import org.oxycblt.auxio.music.Song
|
||||
import org.oxycblt.auxio.playback.PlaybackViewModel
|
||||
import org.oxycblt.auxio.recycler.BaseViewHolder
|
||||
import org.oxycblt.auxio.recycler.DiffCallback
|
||||
import org.oxycblt.auxio.setTextColorResource
|
||||
import org.oxycblt.auxio.ui.BaseViewHolder
|
||||
import org.oxycblt.auxio.ui.DiffCallback
|
||||
import org.oxycblt.auxio.util.disable
|
||||
import org.oxycblt.auxio.util.inflater
|
||||
import org.oxycblt.auxio.util.setTextColorResource
|
||||
|
||||
/**
|
||||
* An adapter for displaying the details and [Song]s of an [Album]
|
||||
|
|
|
@ -28,18 +28,18 @@ import org.oxycblt.auxio.databinding.ItemArtistAlbumBinding
|
|||
import org.oxycblt.auxio.databinding.ItemArtistHeaderBinding
|
||||
import org.oxycblt.auxio.databinding.ItemArtistSongBinding
|
||||
import org.oxycblt.auxio.detail.DetailViewModel
|
||||
import org.oxycblt.auxio.disable
|
||||
import org.oxycblt.auxio.inflater
|
||||
import org.oxycblt.auxio.logD
|
||||
import org.oxycblt.auxio.music.Album
|
||||
import org.oxycblt.auxio.music.Artist
|
||||
import org.oxycblt.auxio.music.BaseModel
|
||||
import org.oxycblt.auxio.music.Header
|
||||
import org.oxycblt.auxio.music.Song
|
||||
import org.oxycblt.auxio.playback.PlaybackViewModel
|
||||
import org.oxycblt.auxio.recycler.BaseViewHolder
|
||||
import org.oxycblt.auxio.recycler.DiffCallback
|
||||
import org.oxycblt.auxio.setTextColorResource
|
||||
import org.oxycblt.auxio.ui.BaseViewHolder
|
||||
import org.oxycblt.auxio.ui.DiffCallback
|
||||
import org.oxycblt.auxio.util.disable
|
||||
import org.oxycblt.auxio.util.inflater
|
||||
import org.oxycblt.auxio.util.logD
|
||||
import org.oxycblt.auxio.util.setTextColorResource
|
||||
|
||||
/**
|
||||
* An adapter for displaying the [Album]s and [Song]s of an artist.
|
||||
|
|
|
@ -27,15 +27,15 @@ import org.oxycblt.auxio.accent.Accent
|
|||
import org.oxycblt.auxio.databinding.ItemGenreHeaderBinding
|
||||
import org.oxycblt.auxio.databinding.ItemGenreSongBinding
|
||||
import org.oxycblt.auxio.detail.DetailViewModel
|
||||
import org.oxycblt.auxio.disable
|
||||
import org.oxycblt.auxio.inflater
|
||||
import org.oxycblt.auxio.music.BaseModel
|
||||
import org.oxycblt.auxio.music.Genre
|
||||
import org.oxycblt.auxio.music.Song
|
||||
import org.oxycblt.auxio.playback.PlaybackViewModel
|
||||
import org.oxycblt.auxio.recycler.BaseViewHolder
|
||||
import org.oxycblt.auxio.recycler.DiffCallback
|
||||
import org.oxycblt.auxio.setTextColorResource
|
||||
import org.oxycblt.auxio.ui.BaseViewHolder
|
||||
import org.oxycblt.auxio.ui.DiffCallback
|
||||
import org.oxycblt.auxio.util.disable
|
||||
import org.oxycblt.auxio.util.inflater
|
||||
import org.oxycblt.auxio.util.setTextColorResource
|
||||
|
||||
/**
|
||||
* An adapter for displaying the [Song]s of a genre.
|
||||
|
|
|
@ -23,9 +23,9 @@ import android.content.Context
|
|||
import android.database.sqlite.SQLiteDatabase
|
||||
import android.database.sqlite.SQLiteOpenHelper
|
||||
import androidx.core.database.sqlite.transaction
|
||||
import org.oxycblt.auxio.assertBackgroundThread
|
||||
import org.oxycblt.auxio.logD
|
||||
import org.oxycblt.auxio.queryAll
|
||||
import org.oxycblt.auxio.util.assertBackgroundThread
|
||||
import org.oxycblt.auxio.util.logD
|
||||
import org.oxycblt.auxio.util.queryAll
|
||||
|
||||
/**
|
||||
* Database for storing excluded directories.
|
||||
|
|
|
@ -31,13 +31,14 @@ import androidx.appcompat.app.AlertDialog
|
|||
import androidx.core.view.isVisible
|
||||
import androidx.fragment.app.activityViewModels
|
||||
import androidx.fragment.app.viewModels
|
||||
import org.oxycblt.auxio.BuildConfig
|
||||
import org.oxycblt.auxio.MainActivity
|
||||
import org.oxycblt.auxio.R
|
||||
import org.oxycblt.auxio.databinding.DialogExcludedBinding
|
||||
import org.oxycblt.auxio.logD
|
||||
import org.oxycblt.auxio.playback.PlaybackViewModel
|
||||
import org.oxycblt.auxio.showToast
|
||||
import org.oxycblt.auxio.ui.LifecycleDialog
|
||||
import org.oxycblt.auxio.util.logD
|
||||
import org.oxycblt.auxio.util.showToast
|
||||
import kotlin.system.exitProcess
|
||||
|
||||
/**
|
||||
|
@ -177,6 +178,6 @@ class ExcludedDialog : LifecycleDialog() {
|
|||
}
|
||||
|
||||
companion object {
|
||||
const val TAG = "TAG_BLACKLIST_DIALOG"
|
||||
const val TAG = BuildConfig.APPLICATION_ID + ".tag.EXCLUDED"
|
||||
}
|
||||
}
|
||||
|
|
|
@ -22,7 +22,7 @@ import android.annotation.SuppressLint
|
|||
import android.view.ViewGroup
|
||||
import androidx.recyclerview.widget.RecyclerView
|
||||
import org.oxycblt.auxio.databinding.ItemExcludedDirBinding
|
||||
import org.oxycblt.auxio.inflater
|
||||
import org.oxycblt.auxio.util.inflater
|
||||
|
||||
/**
|
||||
* Adapter that shows the blacklist entries and their "Clear" button.
|
||||
|
|
|
@ -27,10 +27,10 @@ import org.oxycblt.auxio.music.Artist
|
|||
import org.oxycblt.auxio.music.BaseModel
|
||||
import org.oxycblt.auxio.music.Genre
|
||||
import org.oxycblt.auxio.music.Song
|
||||
import org.oxycblt.auxio.recycler.AlbumViewHolder
|
||||
import org.oxycblt.auxio.recycler.ArtistViewHolder
|
||||
import org.oxycblt.auxio.recycler.GenreViewHolder
|
||||
import org.oxycblt.auxio.recycler.SongViewHolder
|
||||
import org.oxycblt.auxio.ui.AlbumViewHolder
|
||||
import org.oxycblt.auxio.ui.ArtistViewHolder
|
||||
import org.oxycblt.auxio.ui.GenreViewHolder
|
||||
import org.oxycblt.auxio.ui.SongViewHolder
|
||||
|
||||
class HomeAdapter(
|
||||
private val doOnClick: (data: BaseModel) -> Unit,
|
||||
|
|
|
@ -33,14 +33,14 @@ import org.oxycblt.auxio.MainFragmentDirections
|
|||
import org.oxycblt.auxio.R
|
||||
import org.oxycblt.auxio.databinding.FragmentHomeBinding
|
||||
import org.oxycblt.auxio.detail.DetailViewModel
|
||||
import org.oxycblt.auxio.logD
|
||||
import org.oxycblt.auxio.logE
|
||||
import org.oxycblt.auxio.music.Album
|
||||
import org.oxycblt.auxio.music.Artist
|
||||
import org.oxycblt.auxio.music.Genre
|
||||
import org.oxycblt.auxio.music.Song
|
||||
import org.oxycblt.auxio.playback.PlaybackViewModel
|
||||
import org.oxycblt.auxio.recycler.DisplayMode
|
||||
import org.oxycblt.auxio.ui.DisplayMode
|
||||
import org.oxycblt.auxio.util.logD
|
||||
import org.oxycblt.auxio.util.logE
|
||||
|
||||
/**
|
||||
* The main "Launching Point" fragment of Auxio, allowing navigation to the detail
|
||||
|
|
|
@ -25,19 +25,18 @@ import android.view.ViewGroup
|
|||
import androidx.fragment.app.Fragment
|
||||
import androidx.fragment.app.viewModels
|
||||
import androidx.navigation.fragment.findNavController
|
||||
import androidx.recyclerview.widget.GridLayoutManager
|
||||
import org.oxycblt.auxio.BuildConfig
|
||||
import org.oxycblt.auxio.databinding.FragmentHomeListBinding
|
||||
import org.oxycblt.auxio.logD
|
||||
import org.oxycblt.auxio.music.Album
|
||||
import org.oxycblt.auxio.music.Artist
|
||||
import org.oxycblt.auxio.music.Genre
|
||||
import org.oxycblt.auxio.music.Song
|
||||
import org.oxycblt.auxio.playback.PlaybackViewModel
|
||||
import org.oxycblt.auxio.recycler.DisplayMode
|
||||
import org.oxycblt.auxio.recycler.sliceArticle
|
||||
import org.oxycblt.auxio.spans
|
||||
import org.oxycblt.auxio.ui.DisplayMode
|
||||
import org.oxycblt.auxio.ui.newMenu
|
||||
import org.oxycblt.auxio.ui.sliceArticle
|
||||
import org.oxycblt.auxio.util.applySpans
|
||||
import org.oxycblt.auxio.util.logD
|
||||
|
||||
/**
|
||||
* Fragment that contains a list of items specified by a [DisplayMode]. This fragment
|
||||
|
@ -83,10 +82,7 @@ class HomeListFragment : Fragment() {
|
|||
binding.homeRecycler.apply {
|
||||
adapter = homeAdapter
|
||||
setHasFixedSize(true)
|
||||
|
||||
if (spans != 1) {
|
||||
layoutManager = GridLayoutManager(requireContext(), spans)
|
||||
}
|
||||
applySpans()
|
||||
}
|
||||
|
||||
// --- VIEWMODEL SETUP ---
|
||||
|
|
|
@ -26,7 +26,7 @@ import org.oxycblt.auxio.music.Artist
|
|||
import org.oxycblt.auxio.music.Genre
|
||||
import org.oxycblt.auxio.music.MusicStore
|
||||
import org.oxycblt.auxio.music.Song
|
||||
import org.oxycblt.auxio.recycler.DisplayMode
|
||||
import org.oxycblt.auxio.ui.DisplayMode
|
||||
|
||||
class HomeViewModel : ViewModel() {
|
||||
private val mGenres = MutableLiveData(listOf<Genre>())
|
||||
|
|
|
@ -31,8 +31,8 @@ import androidx.fragment.app.viewModels
|
|||
import androidx.navigation.fragment.findNavController
|
||||
import org.oxycblt.auxio.R
|
||||
import org.oxycblt.auxio.databinding.FragmentLoadingBinding
|
||||
import org.oxycblt.auxio.logD
|
||||
import org.oxycblt.auxio.music.MusicStore
|
||||
import org.oxycblt.auxio.util.logD
|
||||
|
||||
/**
|
||||
* Fragment that handles what to display during the loading process.
|
||||
|
|
|
@ -28,7 +28,7 @@ import android.provider.MediaStore.Audio.Media
|
|||
import androidx.core.database.getStringOrNull
|
||||
import org.oxycblt.auxio.R
|
||||
import org.oxycblt.auxio.excluded.ExcludedDatabase
|
||||
import org.oxycblt.auxio.logD
|
||||
import org.oxycblt.auxio.util.logD
|
||||
|
||||
/**
|
||||
* Class that loads/constructs [Genre]s, [Artist]s, [Album]s, and [Song] objects from the filesystem
|
||||
|
|
|
@ -25,8 +25,8 @@ import android.net.Uri
|
|||
import android.provider.OpenableColumns
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.withContext
|
||||
import org.oxycblt.auxio.logD
|
||||
import org.oxycblt.auxio.logE
|
||||
import org.oxycblt.auxio.util.logD
|
||||
import org.oxycblt.auxio.util.logE
|
||||
import java.lang.Exception
|
||||
|
||||
/**
|
||||
|
|
|
@ -27,7 +27,7 @@ import android.widget.TextView
|
|||
import androidx.core.text.isDigitsOnly
|
||||
import androidx.databinding.BindingAdapter
|
||||
import org.oxycblt.auxio.R
|
||||
import org.oxycblt.auxio.getPlural
|
||||
import org.oxycblt.auxio.util.getPlural
|
||||
|
||||
/**
|
||||
* A complete array of all the hardcoded genre values for ID3 <v3, contains standard genres and
|
||||
|
|
|
@ -28,7 +28,7 @@ import androidx.navigation.fragment.findNavController
|
|||
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.util.logD
|
||||
|
||||
/**
|
||||
* A [Fragment] that displays the currently played song at a glance, with some basic controls.
|
||||
|
@ -36,6 +36,7 @@ import org.oxycblt.auxio.logD
|
|||
*
|
||||
* Instantiation is done by FragmentContainerView, **do not instantiate this fragment manually.**
|
||||
* @author OxygenCobalt
|
||||
* TODO: Add more controls to this view depending on screen width
|
||||
*/
|
||||
class CompactPlaybackFragment : Fragment() {
|
||||
private val playbackModel: PlaybackViewModel by activityViewModels()
|
||||
|
|
|
@ -31,11 +31,11 @@ import org.oxycblt.auxio.R
|
|||
import org.oxycblt.auxio.accent.Accent
|
||||
import org.oxycblt.auxio.databinding.FragmentPlaybackBinding
|
||||
import org.oxycblt.auxio.detail.DetailViewModel
|
||||
import org.oxycblt.auxio.logD
|
||||
import org.oxycblt.auxio.playback.state.LoopMode
|
||||
import org.oxycblt.auxio.resolveDrawable
|
||||
import org.oxycblt.auxio.resolveStateList
|
||||
import org.oxycblt.auxio.ui.memberBinding
|
||||
import org.oxycblt.auxio.util.logD
|
||||
import org.oxycblt.auxio.util.resolveDrawable
|
||||
import org.oxycblt.auxio.util.resolveStateList
|
||||
|
||||
/**
|
||||
* A [Fragment] that displays more information about the song, along with more media controls.
|
||||
|
|
|
@ -26,8 +26,6 @@ import androidx.lifecycle.Transformations
|
|||
import androidx.lifecycle.ViewModel
|
||||
import androidx.lifecycle.viewModelScope
|
||||
import kotlinx.coroutines.launch
|
||||
import org.oxycblt.auxio.logD
|
||||
import org.oxycblt.auxio.logE
|
||||
import org.oxycblt.auxio.music.Album
|
||||
import org.oxycblt.auxio.music.Artist
|
||||
import org.oxycblt.auxio.music.Genre
|
||||
|
@ -39,8 +37,10 @@ import org.oxycblt.auxio.playback.queue.QueueAdapter
|
|||
import org.oxycblt.auxio.playback.state.LoopMode
|
||||
import org.oxycblt.auxio.playback.state.PlaybackMode
|
||||
import org.oxycblt.auxio.playback.state.PlaybackStateManager
|
||||
import org.oxycblt.auxio.recycler.SortMode
|
||||
import org.oxycblt.auxio.settings.SettingsManager
|
||||
import org.oxycblt.auxio.ui.SortMode
|
||||
import org.oxycblt.auxio.util.logD
|
||||
import org.oxycblt.auxio.util.logE
|
||||
|
||||
/**
|
||||
* The ViewModel that provides a UI frontend for [PlaybackStateManager].
|
||||
|
|
|
@ -28,15 +28,15 @@ import androidx.recyclerview.widget.RecyclerView
|
|||
import org.oxycblt.auxio.R
|
||||
import org.oxycblt.auxio.databinding.ItemActionHeaderBinding
|
||||
import org.oxycblt.auxio.databinding.ItemQueueSongBinding
|
||||
import org.oxycblt.auxio.inflater
|
||||
import org.oxycblt.auxio.logE
|
||||
import org.oxycblt.auxio.music.BaseModel
|
||||
import org.oxycblt.auxio.music.Header
|
||||
import org.oxycblt.auxio.music.Song
|
||||
import org.oxycblt.auxio.playback.PlaybackViewModel
|
||||
import org.oxycblt.auxio.recycler.BaseViewHolder
|
||||
import org.oxycblt.auxio.recycler.DiffCallback
|
||||
import org.oxycblt.auxio.recycler.HeaderViewHolder
|
||||
import org.oxycblt.auxio.ui.BaseViewHolder
|
||||
import org.oxycblt.auxio.ui.DiffCallback
|
||||
import org.oxycblt.auxio.ui.HeaderViewHolder
|
||||
import org.oxycblt.auxio.util.inflater
|
||||
import org.oxycblt.auxio.util.logE
|
||||
|
||||
/**
|
||||
* The single adapter for both the Next Queue and the User Queue.
|
||||
|
|
|
@ -32,11 +32,11 @@ import androidx.recyclerview.widget.ItemTouchHelper
|
|||
import androidx.recyclerview.widget.RecyclerView
|
||||
import org.oxycblt.auxio.R
|
||||
import org.oxycblt.auxio.databinding.FragmentQueueBinding
|
||||
import org.oxycblt.auxio.isEdgeOn
|
||||
import org.oxycblt.auxio.isIrregularLandscape
|
||||
import org.oxycblt.auxio.music.BaseModel
|
||||
import org.oxycblt.auxio.music.Header
|
||||
import org.oxycblt.auxio.playback.PlaybackViewModel
|
||||
import org.oxycblt.auxio.util.isEdgeOn
|
||||
import org.oxycblt.auxio.util.isIrregularLandscape
|
||||
|
||||
/**
|
||||
* A [Fragment] that contains both the user queue and the next queue, with the ability to
|
||||
|
|
|
@ -1,41 +0,0 @@
|
|||
/*
|
||||
* Copyright (c) 2021 Auxio Project
|
||||
* QueueItem.kt is part of Auxio.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package org.oxycblt.auxio.playback.state
|
||||
|
||||
/**
|
||||
* A database entity that stores a simplified representation of a song in a queue.
|
||||
* @property id The database entity's id
|
||||
* @property songHash The hash for the song represented
|
||||
* @property albumHash The hash for the album represented
|
||||
* @property isUserQueue A bool for if this queue item is a user queue item or not
|
||||
* @author OxygenCobalt
|
||||
*/
|
||||
data class DatabaseQueueItem(
|
||||
var id: Long = 0L,
|
||||
val songHash: Int,
|
||||
val albumHash: Int,
|
||||
val isUserQueue: Boolean = false
|
||||
) {
|
||||
companion object {
|
||||
const val COLUMN_ID = "id"
|
||||
const val COLUMN_SONG_HASH = "song"
|
||||
const val COLUMN_ALBUM_HASH = "album"
|
||||
const val COLUMN_IS_USER_QUEUE = "is_user_queue"
|
||||
}
|
||||
}
|
|
@ -1,55 +0,0 @@
|
|||
/*
|
||||
* Copyright (c) 2021 Auxio Project
|
||||
* PlaybackState.kt is part of Auxio.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package org.oxycblt.auxio.playback.state
|
||||
|
||||
/**
|
||||
* A database entity that stores a compressed variant of the current playback state.
|
||||
* @property id - The database key for this state
|
||||
* @property songHash - The hash for the currently playing song
|
||||
* @property parentHash - The hash for the currently playing parent
|
||||
* @property index - The current index in the queue.
|
||||
* @property mode - The integer form of the current [org.oxycblt.auxio.playback.state.PlaybackMode]
|
||||
* @property isShuffling - A bool for if the queue was shuffled
|
||||
* @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 DatabaseState(
|
||||
val id: Long = 0L,
|
||||
val songHash: Int,
|
||||
val position: Long,
|
||||
val parentHash: Int,
|
||||
val index: Int,
|
||||
val mode: Int,
|
||||
val isShuffling: Boolean,
|
||||
val loopMode: Int,
|
||||
val inUserQueue: Boolean
|
||||
) {
|
||||
companion object {
|
||||
const val COLUMN_ID = "state_id"
|
||||
const val COLUMN_SONG_HASH = "song"
|
||||
const val COLUMN_POSITION = "position"
|
||||
const val COLUMN_PARENT_HASH = "parent"
|
||||
const val COLUMN_INDEX = "_index"
|
||||
const val COLUMN_MODE = "mode"
|
||||
const val COLUMN_IS_SHUFFLING = "is_shuffling"
|
||||
const val COLUMN_LOOP_MODE = "loop_mode"
|
||||
const val COLUMN_IN_USER_QUEUE = "is_user_queue"
|
||||
}
|
||||
}
|
|
@ -23,9 +23,9 @@ import android.content.Context
|
|||
import android.database.sqlite.SQLiteDatabase
|
||||
import android.database.sqlite.SQLiteOpenHelper
|
||||
import androidx.core.database.sqlite.transaction
|
||||
import org.oxycblt.auxio.assertBackgroundThread
|
||||
import org.oxycblt.auxio.logD
|
||||
import org.oxycblt.auxio.queryAll
|
||||
import org.oxycblt.auxio.util.assertBackgroundThread
|
||||
import org.oxycblt.auxio.util.logD
|
||||
import org.oxycblt.auxio.util.queryAll
|
||||
|
||||
/**
|
||||
* A SQLite database for managing the persistent playback state and queue.
|
||||
|
@ -273,3 +273,61 @@ class PlaybackStateDatabase(context: Context) :
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* A database entity that stores a simplified representation of a song in a queue.
|
||||
* @property id The database entity's id
|
||||
* @property songHash The hash for the song represented
|
||||
* @property albumHash The hash for the album represented
|
||||
* @property isUserQueue A bool for if this queue item is a user queue item or not
|
||||
* @author OxygenCobalt
|
||||
*/
|
||||
data class DatabaseQueueItem(
|
||||
var id: Long = 0L,
|
||||
val songHash: Int,
|
||||
val albumHash: Int,
|
||||
val isUserQueue: Boolean = false
|
||||
) {
|
||||
companion object {
|
||||
const val COLUMN_ID = "id"
|
||||
const val COLUMN_SONG_HASH = "song"
|
||||
const val COLUMN_ALBUM_HASH = "album"
|
||||
const val COLUMN_IS_USER_QUEUE = "is_user_queue"
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* A database entity that stores a compressed variant of the current playback state.
|
||||
* @property id - The database key for this state
|
||||
* @property songHash - The hash for the currently playing song
|
||||
* @property parentHash - The hash for the currently playing parent
|
||||
* @property index - The current index in the queue.
|
||||
* @property mode - The integer form of the current [org.oxycblt.auxio.playback.state.PlaybackMode]
|
||||
* @property isShuffling - A bool for if the queue was shuffled
|
||||
* @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 DatabaseState(
|
||||
val id: Long = 0L,
|
||||
val songHash: Int,
|
||||
val position: Long,
|
||||
val parentHash: Int,
|
||||
val index: Int,
|
||||
val mode: Int,
|
||||
val isShuffling: Boolean,
|
||||
val loopMode: Int,
|
||||
val inUserQueue: Boolean
|
||||
) {
|
||||
companion object {
|
||||
const val COLUMN_ID = "state_id"
|
||||
const val COLUMN_SONG_HASH = "song"
|
||||
const val COLUMN_POSITION = "position"
|
||||
const val COLUMN_PARENT_HASH = "parent"
|
||||
const val COLUMN_INDEX = "_index"
|
||||
const val COLUMN_MODE = "mode"
|
||||
const val COLUMN_IS_SHUFFLING = "is_shuffling"
|
||||
const val COLUMN_LOOP_MODE = "loop_mode"
|
||||
const val COLUMN_IN_USER_QUEUE = "is_user_queue"
|
||||
}
|
||||
}
|
||||
|
|
|
@ -21,8 +21,6 @@ package org.oxycblt.auxio.playback.state
|
|||
import android.content.Context
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.withContext
|
||||
import org.oxycblt.auxio.logD
|
||||
import org.oxycblt.auxio.logE
|
||||
import org.oxycblt.auxio.music.Album
|
||||
import org.oxycblt.auxio.music.Artist
|
||||
import org.oxycblt.auxio.music.Genre
|
||||
|
@ -30,6 +28,8 @@ import org.oxycblt.auxio.music.MusicStore
|
|||
import org.oxycblt.auxio.music.Parent
|
||||
import org.oxycblt.auxio.music.Song
|
||||
import org.oxycblt.auxio.settings.SettingsManager
|
||||
import org.oxycblt.auxio.util.logD
|
||||
import org.oxycblt.auxio.util.logE
|
||||
|
||||
/**
|
||||
* Master class (and possible god object) for the playback state.
|
||||
|
|
|
@ -25,10 +25,10 @@ import androidx.core.animation.addListener
|
|||
import androidx.media.AudioFocusRequestCompat
|
||||
import androidx.media.AudioManagerCompat
|
||||
import com.google.android.exoplayer2.SimpleExoPlayer
|
||||
import org.oxycblt.auxio.getSystemServiceSafe
|
||||
import org.oxycblt.auxio.logD
|
||||
import org.oxycblt.auxio.playback.state.PlaybackStateManager
|
||||
import org.oxycblt.auxio.settings.SettingsManager
|
||||
import org.oxycblt.auxio.util.getSystemServiceSafe
|
||||
import org.oxycblt.auxio.util.logD
|
||||
|
||||
/**
|
||||
* Object that manages the AudioFocus state.
|
||||
|
|
|
@ -31,10 +31,10 @@ import org.oxycblt.auxio.R
|
|||
import org.oxycblt.auxio.coil.loadBitmap
|
||||
import org.oxycblt.auxio.music.Parent
|
||||
import org.oxycblt.auxio.music.Song
|
||||
import org.oxycblt.auxio.newBroadcastIntent
|
||||
import org.oxycblt.auxio.newMainIntent
|
||||
import org.oxycblt.auxio.playback.state.LoopMode
|
||||
import org.oxycblt.auxio.settings.SettingsManager
|
||||
import org.oxycblt.auxio.util.newBroadcastIntent
|
||||
import org.oxycblt.auxio.util.newMainIntent
|
||||
|
||||
/**
|
||||
* The unified notification for [PlaybackService]. This is not self-sufficient, updates have
|
||||
|
|
|
@ -52,14 +52,14 @@ import kotlinx.coroutines.flow.flow
|
|||
import kotlinx.coroutines.flow.takeWhile
|
||||
import kotlinx.coroutines.launch
|
||||
import org.oxycblt.auxio.BuildConfig
|
||||
import org.oxycblt.auxio.getSystemServiceSafe
|
||||
import org.oxycblt.auxio.logD
|
||||
import org.oxycblt.auxio.music.Parent
|
||||
import org.oxycblt.auxio.music.Song
|
||||
import org.oxycblt.auxio.music.toURI
|
||||
import org.oxycblt.auxio.playback.state.LoopMode
|
||||
import org.oxycblt.auxio.playback.state.PlaybackStateManager
|
||||
import org.oxycblt.auxio.settings.SettingsManager
|
||||
import org.oxycblt.auxio.util.getSystemServiceSafe
|
||||
import org.oxycblt.auxio.util.logD
|
||||
import org.oxycblt.auxio.widgets.WidgetController
|
||||
import org.oxycblt.auxio.widgets.WidgetProvider
|
||||
|
||||
|
|
|
@ -27,11 +27,11 @@ import android.support.v4.media.session.MediaSessionCompat
|
|||
import android.support.v4.media.session.PlaybackStateCompat
|
||||
import com.google.android.exoplayer2.Player
|
||||
import org.oxycblt.auxio.coil.loadBitmap
|
||||
import org.oxycblt.auxio.logD
|
||||
import org.oxycblt.auxio.music.Song
|
||||
import org.oxycblt.auxio.playback.state.LoopMode
|
||||
import org.oxycblt.auxio.playback.state.PlaybackStateManager
|
||||
import org.oxycblt.auxio.settings.SettingsManager
|
||||
import org.oxycblt.auxio.util.logD
|
||||
|
||||
/**
|
||||
* Nightmarish class that coordinates communication between [MediaSessionCompat], [Player],
|
||||
|
|
|
@ -1,76 +0,0 @@
|
|||
/*
|
||||
* Copyright (c) 2021 Auxio Project
|
||||
* BaseViewHolder.kt is part of Auxio.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package org.oxycblt.auxio.recycler
|
||||
|
||||
import android.view.View
|
||||
import androidx.databinding.ViewDataBinding
|
||||
import androidx.recyclerview.widget.RecyclerView
|
||||
import org.oxycblt.auxio.music.BaseModel
|
||||
|
||||
/**
|
||||
* A [RecyclerView.ViewHolder] that streamlines a lot of the common things across all viewholders.
|
||||
* @param T The datatype, inheriting [BaseModel] for this ViewHolder.
|
||||
* @param binding Basic [ViewDataBinding] required to set up click listeners & sizing.
|
||||
* @param doOnClick (Optional) Function that calls on a click.
|
||||
* @param doOnLongClick (Optional) Functions that calls on a long-click.
|
||||
* @author OxygenCobalt
|
||||
*/
|
||||
abstract class BaseViewHolder<T : BaseModel>(
|
||||
private val binding: ViewDataBinding,
|
||||
private val doOnClick: ((data: T) -> Unit)? = null,
|
||||
private val doOnLongClick: ((view: View, data: T) -> Unit)? = null
|
||||
) : RecyclerView.ViewHolder(binding.root) {
|
||||
init {
|
||||
// Force the layout to *actually* be the screen width
|
||||
binding.root.layoutParams = RecyclerView.LayoutParams(
|
||||
RecyclerView.LayoutParams.MATCH_PARENT, RecyclerView.LayoutParams.WRAP_CONTENT
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* Bind the viewholder with whatever [BaseModel] instance that has been specified.
|
||||
* Will call [onBind] on the inheriting ViewHolder.
|
||||
* @param data Data that the viewholder should be bound with
|
||||
*/
|
||||
fun bind(data: T) {
|
||||
doOnClick?.let { onClick ->
|
||||
binding.root.setOnClickListener {
|
||||
onClick(data)
|
||||
}
|
||||
}
|
||||
|
||||
doOnLongClick?.let { onLongClick ->
|
||||
binding.root.setOnLongClickListener { view ->
|
||||
onLongClick(view, data)
|
||||
|
||||
true
|
||||
}
|
||||
}
|
||||
|
||||
onBind(data)
|
||||
|
||||
binding.executePendingBindings()
|
||||
}
|
||||
|
||||
/**
|
||||
* Function that performs binding operations unique to the inheriting viewholder.
|
||||
* Add any specialized code to an override of this instead of [BaseViewHolder] itself.
|
||||
*/
|
||||
protected abstract fun onBind(data: T)
|
||||
}
|
|
@ -28,12 +28,12 @@ import org.oxycblt.auxio.music.BaseModel
|
|||
import org.oxycblt.auxio.music.Genre
|
||||
import org.oxycblt.auxio.music.Header
|
||||
import org.oxycblt.auxio.music.Song
|
||||
import org.oxycblt.auxio.recycler.AlbumViewHolder
|
||||
import org.oxycblt.auxio.recycler.ArtistViewHolder
|
||||
import org.oxycblt.auxio.recycler.DiffCallback
|
||||
import org.oxycblt.auxio.recycler.GenreViewHolder
|
||||
import org.oxycblt.auxio.recycler.HeaderViewHolder
|
||||
import org.oxycblt.auxio.recycler.SongViewHolder
|
||||
import org.oxycblt.auxio.ui.AlbumViewHolder
|
||||
import org.oxycblt.auxio.ui.ArtistViewHolder
|
||||
import org.oxycblt.auxio.ui.DiffCallback
|
||||
import org.oxycblt.auxio.ui.GenreViewHolder
|
||||
import org.oxycblt.auxio.ui.HeaderViewHolder
|
||||
import org.oxycblt.auxio.ui.SongViewHolder
|
||||
|
||||
/**
|
||||
* A Multi-ViewHolder adapter that displays the results of a search query.
|
||||
|
|
|
@ -29,13 +29,10 @@ import androidx.fragment.app.Fragment
|
|||
import androidx.fragment.app.activityViewModels
|
||||
import androidx.fragment.app.viewModels
|
||||
import androidx.navigation.fragment.findNavController
|
||||
import androidx.recyclerview.widget.GridLayoutManager
|
||||
import com.google.android.material.appbar.AppBarLayout
|
||||
import org.oxycblt.auxio.R
|
||||
import org.oxycblt.auxio.databinding.FragmentSearchBinding
|
||||
import org.oxycblt.auxio.detail.DetailViewModel
|
||||
import org.oxycblt.auxio.getSystemServiceSafe
|
||||
import org.oxycblt.auxio.logD
|
||||
import org.oxycblt.auxio.music.Album
|
||||
import org.oxycblt.auxio.music.Artist
|
||||
import org.oxycblt.auxio.music.BaseModel
|
||||
|
@ -43,9 +40,11 @@ import org.oxycblt.auxio.music.Genre
|
|||
import org.oxycblt.auxio.music.Header
|
||||
import org.oxycblt.auxio.music.Song
|
||||
import org.oxycblt.auxio.playback.PlaybackViewModel
|
||||
import org.oxycblt.auxio.recycler.DisplayMode
|
||||
import org.oxycblt.auxio.spans
|
||||
import org.oxycblt.auxio.ui.DisplayMode
|
||||
import org.oxycblt.auxio.ui.newMenu
|
||||
import org.oxycblt.auxio.util.applySpans
|
||||
import org.oxycblt.auxio.util.getSystemServiceSafe
|
||||
import org.oxycblt.auxio.util.logD
|
||||
|
||||
/**
|
||||
* A [Fragment] that allows for the searching of the entire music library.
|
||||
|
@ -107,33 +106,27 @@ class SearchFragment : Fragment() {
|
|||
}
|
||||
}
|
||||
|
||||
binding.searchEditText.addTextChangedListener { text ->
|
||||
// Run the search with the updated text as the query
|
||||
searchModel.doSearch(text?.toString() ?: "", requireContext())
|
||||
}
|
||||
binding.searchEditText.apply {
|
||||
addTextChangedListener { text ->
|
||||
// Run the search with the updated text as the query
|
||||
searchModel.doSearch(text?.toString() ?: "", requireContext())
|
||||
}
|
||||
|
||||
// Auto-open the keyboard when this view is shown
|
||||
requestFocus()
|
||||
|
||||
postDelayed(200) {
|
||||
imm.showSoftInput(this, InputMethodManager.SHOW_IMPLICIT)
|
||||
}
|
||||
}
|
||||
binding.searchRecycler.apply {
|
||||
adapter = searchAdapter
|
||||
|
||||
// It's expensive to calculate the spans for each position in the list, so cache it.
|
||||
val spans = spans
|
||||
|
||||
if (spans != -1) {
|
||||
layoutManager = GridLayoutManager(requireContext(), spans).apply {
|
||||
spanSizeLookup = object : GridLayoutManager.SpanSizeLookup() {
|
||||
override fun getSpanSize(position: Int): Int =
|
||||
if (searchAdapter.currentList[position] is Header) spans else 1
|
||||
}
|
||||
}
|
||||
applySpans { pos ->
|
||||
searchAdapter.currentList[pos] is Header
|
||||
}
|
||||
}
|
||||
|
||||
// Auto-open the keyboard
|
||||
binding.searchEditText.requestFocus()
|
||||
binding.searchEditText.postDelayed(200) {
|
||||
imm.showSoftInput(binding.searchEditText, InputMethodManager.SHOW_IMPLICIT)
|
||||
}
|
||||
|
||||
// --- VIEWMODEL SETUP ---
|
||||
|
||||
searchModel.searchResults.observe(viewLifecycleOwner) { results ->
|
||||
|
@ -179,7 +172,7 @@ class SearchFragment : Fragment() {
|
|||
}
|
||||
|
||||
private fun InputMethodManager.hide() {
|
||||
hideSoftInputFromWindow(requireView().windowToken, InputMethodManager.HIDE_IMPLICIT_ONLY)
|
||||
hideSoftInputFromWindow(requireView().windowToken, InputMethodManager.HIDE_NOT_ALWAYS)
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -193,8 +186,6 @@ class SearchFragment : Fragment() {
|
|||
return
|
||||
}
|
||||
|
||||
imm.hide()
|
||||
|
||||
if (!searchModel.isNavigating) {
|
||||
searchModel.setNavigating(true)
|
||||
|
||||
|
@ -214,6 +205,8 @@ class SearchFragment : Fragment() {
|
|||
}
|
||||
}
|
||||
)
|
||||
|
||||
imm.hide()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -29,8 +29,8 @@ import org.oxycblt.auxio.R
|
|||
import org.oxycblt.auxio.music.BaseModel
|
||||
import org.oxycblt.auxio.music.Header
|
||||
import org.oxycblt.auxio.music.MusicStore
|
||||
import org.oxycblt.auxio.recycler.DisplayMode
|
||||
import org.oxycblt.auxio.settings.SettingsManager
|
||||
import org.oxycblt.auxio.ui.DisplayMode
|
||||
|
||||
/**
|
||||
* The [ViewModel] for the search functionality
|
||||
|
|
|
@ -32,9 +32,9 @@ import com.google.android.material.bottomsheet.BottomSheetDialogFragment
|
|||
import org.oxycblt.auxio.BuildConfig
|
||||
import org.oxycblt.auxio.R
|
||||
import org.oxycblt.auxio.databinding.FragmentAboutBinding
|
||||
import org.oxycblt.auxio.logD
|
||||
import org.oxycblt.auxio.music.MusicStore
|
||||
import org.oxycblt.auxio.showToast
|
||||
import org.oxycblt.auxio.util.logD
|
||||
import org.oxycblt.auxio.util.showToast
|
||||
|
||||
/**
|
||||
* A [BottomSheetDialogFragment] that shows Auxio's about screen.
|
||||
|
|
|
@ -16,7 +16,7 @@
|
|||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package org.oxycblt.auxio.settings.ui
|
||||
package org.oxycblt.auxio.settings
|
||||
|
||||
import androidx.appcompat.app.AlertDialog
|
||||
import org.oxycblt.auxio.ui.LifecycleDialog
|
|
@ -16,7 +16,7 @@
|
|||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package org.oxycblt.auxio.settings.ui
|
||||
package org.oxycblt.auxio.settings
|
||||
|
||||
import android.content.Context
|
||||
import android.content.res.TypedArray
|
|
@ -37,11 +37,6 @@ fun Int.toThemeIcon(): Int {
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* A verbose shortcut for getString(key, null). Used during string pref migrations
|
||||
*/
|
||||
fun SharedPreferences.getStringOrNull(key: String): String? = getString(key, null)
|
||||
|
||||
/**
|
||||
* Converts an int preference under [key] to [T] through a [convert] function.
|
||||
* This is only intended for use for the enums with fromInt functions.
|
||||
|
|
|
@ -107,6 +107,11 @@ fun handleSongPlayModeCompat(prefs: SharedPreferences): PlaybackMode {
|
|||
?: PlaybackMode.ALL_SONGS
|
||||
}
|
||||
|
||||
/**
|
||||
* A verbose shortcut for getString(key, null). Used during string pref migrations
|
||||
*/
|
||||
private fun SharedPreferences.getStringOrNull(key: String): String? = getString(key, null)
|
||||
|
||||
/**
|
||||
* Cache of the old keys used in Auxio.
|
||||
*/
|
||||
|
|
|
@ -31,12 +31,10 @@ import org.oxycblt.auxio.R
|
|||
import org.oxycblt.auxio.accent.Accent
|
||||
import org.oxycblt.auxio.accent.AccentDialog
|
||||
import org.oxycblt.auxio.excluded.ExcludedDialog
|
||||
import org.oxycblt.auxio.isNight
|
||||
import org.oxycblt.auxio.logD
|
||||
import org.oxycblt.auxio.playback.PlaybackViewModel
|
||||
import org.oxycblt.auxio.settings.ui.IntListPrefDialog
|
||||
import org.oxycblt.auxio.settings.ui.IntListPreference
|
||||
import org.oxycblt.auxio.showToast
|
||||
import org.oxycblt.auxio.util.isNight
|
||||
import org.oxycblt.auxio.util.logD
|
||||
import org.oxycblt.auxio.util.showToast
|
||||
|
||||
/**
|
||||
* The actual fragment containing the settings menu. Inherits [PreferenceFragmentCompat].
|
||||
|
|
|
@ -25,8 +25,8 @@ import androidx.preference.PreferenceManager
|
|||
import org.oxycblt.auxio.accent.ACCENTS
|
||||
import org.oxycblt.auxio.accent.Accent
|
||||
import org.oxycblt.auxio.playback.state.PlaybackMode
|
||||
import org.oxycblt.auxio.recycler.DisplayMode
|
||||
import org.oxycblt.auxio.recycler.SortMode
|
||||
import org.oxycblt.auxio.ui.DisplayMode
|
||||
import org.oxycblt.auxio.ui.SortMode
|
||||
|
||||
/**
|
||||
* Wrapper around the [SharedPreferences] class that writes & reads values without a context.
|
||||
|
|
|
@ -33,7 +33,7 @@ import org.oxycblt.auxio.music.BaseModel
|
|||
import org.oxycblt.auxio.music.Genre
|
||||
import org.oxycblt.auxio.music.Song
|
||||
import org.oxycblt.auxio.playback.PlaybackViewModel
|
||||
import org.oxycblt.auxio.showToast
|
||||
import org.oxycblt.auxio.util.showToast
|
||||
|
||||
/**
|
||||
* Extension method for creating and showing a new [ActionMenu].
|
||||
|
|
|
@ -16,7 +16,7 @@
|
|||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package org.oxycblt.auxio.recycler
|
||||
package org.oxycblt.auxio.ui
|
||||
|
||||
import androidx.recyclerview.widget.DiffUtil
|
||||
import org.oxycblt.auxio.music.BaseModel
|
|
@ -16,7 +16,7 @@
|
|||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package org.oxycblt.auxio.recycler
|
||||
package org.oxycblt.auxio.ui
|
||||
|
||||
/**
|
||||
* An enum for determining what items to show in a given list.
|
|
@ -27,7 +27,7 @@ import androidx.core.graphics.drawable.toDrawable
|
|||
import androidx.fragment.app.DialogFragment
|
||||
import com.google.android.material.dialog.MaterialAlertDialogBuilder
|
||||
import org.oxycblt.auxio.R
|
||||
import org.oxycblt.auxio.resolveAttr
|
||||
import org.oxycblt.auxio.util.resolveAttr
|
||||
|
||||
/**
|
||||
* A wrapper around [DialogFragment] that allows the usage of the standard Auxio lifecycle
|
||||
|
|
|
@ -26,8 +26,8 @@ import androidx.lifecycle.Lifecycle
|
|||
import androidx.lifecycle.LifecycleObserver
|
||||
import androidx.lifecycle.LifecycleOwner
|
||||
import androidx.lifecycle.OnLifecycleEvent
|
||||
import org.oxycblt.auxio.assertMainThread
|
||||
import org.oxycblt.auxio.inflater
|
||||
import org.oxycblt.auxio.util.assertMainThread
|
||||
import org.oxycblt.auxio.util.inflater
|
||||
import kotlin.properties.ReadOnlyProperty
|
||||
import kotlin.reflect.KProperty
|
||||
|
||||
|
|
|
@ -16,7 +16,7 @@
|
|||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package org.oxycblt.auxio.recycler
|
||||
package org.oxycblt.auxio.ui
|
||||
|
||||
import android.widget.ImageButton
|
||||
import androidx.annotation.DrawableRes
|
|
@ -1,6 +1,6 @@
|
|||
/*
|
||||
* Copyright (c) 2021 Auxio Project
|
||||
* ModelHolders.kt is part of Auxio.
|
||||
* ViewHolders.kt is part of Auxio.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
|
@ -16,21 +16,76 @@
|
|||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package org.oxycblt.auxio.recycler
|
||||
package org.oxycblt.auxio.ui
|
||||
|
||||
import android.content.Context
|
||||
import android.view.View
|
||||
import androidx.databinding.ViewDataBinding
|
||||
import androidx.recyclerview.widget.RecyclerView
|
||||
import org.oxycblt.auxio.databinding.ItemAlbumBinding
|
||||
import org.oxycblt.auxio.databinding.ItemArtistBinding
|
||||
import org.oxycblt.auxio.databinding.ItemGenreBinding
|
||||
import org.oxycblt.auxio.databinding.ItemHeaderBinding
|
||||
import org.oxycblt.auxio.databinding.ItemSongBinding
|
||||
import org.oxycblt.auxio.inflater
|
||||
import org.oxycblt.auxio.music.Album
|
||||
import org.oxycblt.auxio.music.Artist
|
||||
import org.oxycblt.auxio.music.BaseModel
|
||||
import org.oxycblt.auxio.music.Genre
|
||||
import org.oxycblt.auxio.music.Header
|
||||
import org.oxycblt.auxio.music.Song
|
||||
import org.oxycblt.auxio.util.inflater
|
||||
|
||||
/**
|
||||
* A [RecyclerView.ViewHolder] that streamlines a lot of the common things across all viewholders.
|
||||
* @param T The datatype, inheriting [BaseModel] for this ViewHolder.
|
||||
* @param binding Basic [ViewDataBinding] required to set up click listeners & sizing.
|
||||
* @param doOnClick (Optional) Function that calls on a click.
|
||||
* @param doOnLongClick (Optional) Functions that calls on a long-click.
|
||||
* @author OxygenCobalt
|
||||
*/
|
||||
abstract class BaseViewHolder<T : BaseModel>(
|
||||
private val binding: ViewDataBinding,
|
||||
private val doOnClick: ((data: T) -> Unit)? = null,
|
||||
private val doOnLongClick: ((view: View, data: T) -> Unit)? = null
|
||||
) : RecyclerView.ViewHolder(binding.root) {
|
||||
init {
|
||||
// Force the layout to *actually* be the screen width
|
||||
binding.root.layoutParams = RecyclerView.LayoutParams(
|
||||
RecyclerView.LayoutParams.MATCH_PARENT, RecyclerView.LayoutParams.WRAP_CONTENT
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* Bind the viewholder with whatever [BaseModel] instance that has been specified.
|
||||
* Will call [onBind] on the inheriting ViewHolder.
|
||||
* @param data Data that the viewholder should be bound with
|
||||
*/
|
||||
fun bind(data: T) {
|
||||
doOnClick?.let { onClick ->
|
||||
binding.root.setOnClickListener {
|
||||
onClick(data)
|
||||
}
|
||||
}
|
||||
|
||||
doOnLongClick?.let { onLongClick ->
|
||||
binding.root.setOnLongClickListener { view ->
|
||||
onLongClick(view, data)
|
||||
|
||||
true
|
||||
}
|
||||
}
|
||||
|
||||
onBind(data)
|
||||
|
||||
binding.executePendingBindings()
|
||||
}
|
||||
|
||||
/**
|
||||
* Function that performs binding operations unique to the inheriting viewholder.
|
||||
* Add any specialized code to an override of this instead of [BaseViewHolder] itself.
|
||||
*/
|
||||
protected abstract fun onBind(data: T)
|
||||
}
|
||||
|
||||
/**
|
||||
* The Shared ViewHolder for a [Song]. Instantiation should be done with [from].
|
127
app/src/main/java/org/oxycblt/auxio/util/ContextUtil.kt
Normal file
127
app/src/main/java/org/oxycblt/auxio/util/ContextUtil.kt
Normal file
|
@ -0,0 +1,127 @@
|
|||
/*
|
||||
* Copyright (c) 2021 Auxio Project
|
||||
* ContextUtil.kt is part of Auxio.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package org.oxycblt.auxio.util
|
||||
|
||||
import android.app.PendingIntent
|
||||
import android.content.Context
|
||||
import android.content.Intent
|
||||
import android.content.res.Configuration
|
||||
import android.os.Build
|
||||
import android.view.LayoutInflater
|
||||
import android.widget.Toast
|
||||
import androidx.annotation.PluralsRes
|
||||
import androidx.annotation.StringRes
|
||||
import androidx.core.content.ContextCompat
|
||||
import org.oxycblt.auxio.MainActivity
|
||||
import kotlin.reflect.KClass
|
||||
|
||||
const val INTENT_REQUEST_CODE = 0xA0A0
|
||||
|
||||
/**
|
||||
* Shortcut to get a [LayoutInflater] from a [Context]
|
||||
*/
|
||||
val Context.inflater: LayoutInflater get() = LayoutInflater.from(this)
|
||||
|
||||
/**
|
||||
* Returns whether the current UI is in night mode or not. This will work if the theme is
|
||||
* automatic as well.
|
||||
*/
|
||||
val Context.isNight: Boolean get() =
|
||||
resources.configuration.uiMode and Configuration.UI_MODE_NIGHT_MASK ==
|
||||
Configuration.UI_MODE_NIGHT_YES
|
||||
|
||||
/**
|
||||
* Convenience method for getting a system service without nullability issues.
|
||||
* @param T The system service in question.
|
||||
* @param serviceClass The service's kotlin class [Java class will be used in function call]
|
||||
* @return The system service
|
||||
* @throws IllegalArgumentException If the system service cannot be retrieved.
|
||||
*/
|
||||
fun <T : Any> Context.getSystemServiceSafe(serviceClass: KClass<T>): T {
|
||||
return requireNotNull(ContextCompat.getSystemService(this, serviceClass.java)) {
|
||||
"System service ${serviceClass.simpleName} could not be instantiated"
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a broadcast [PendingIntent]
|
||||
*/
|
||||
fun Context.newBroadcastIntent(what: String): PendingIntent {
|
||||
return PendingIntent.getBroadcast(
|
||||
this, INTENT_REQUEST_CODE, Intent(what),
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M)
|
||||
PendingIntent.FLAG_IMMUTABLE
|
||||
else 0
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a [PendingIntent] that leads to Auxio's [MainActivity]
|
||||
*/
|
||||
fun Context.newMainIntent(): PendingIntent {
|
||||
return PendingIntent.getActivity(
|
||||
this, INTENT_REQUEST_CODE, Intent(this, MainActivity::class.java),
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M)
|
||||
PendingIntent.FLAG_IMMUTABLE
|
||||
else 0
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a toast using the provided string resource.
|
||||
*/
|
||||
fun Context.showToast(@StringRes str: Int) {
|
||||
Toast.makeText(applicationContext, getString(str), Toast.LENGTH_SHORT).show()
|
||||
}
|
||||
|
||||
/**
|
||||
* Convenience method for getting a plural.
|
||||
* @param pluralsRes Resource for the plural
|
||||
* @param value Int value for the plural.
|
||||
* @return The formatted string requested
|
||||
*/
|
||||
fun Context.getPlural(@PluralsRes pluralsRes: Int, value: Int): String {
|
||||
return resources.getQuantityString(pluralsRes, value, value)
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine if the device is currently in landscape.
|
||||
*/
|
||||
fun Context.isLandscape(): Boolean {
|
||||
return resources.configuration.orientation == Configuration.ORIENTATION_LANDSCAPE
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine if we are in tablet mode or not
|
||||
*/
|
||||
fun Context.isTablet(): Boolean {
|
||||
val layout = resources.configuration.screenLayout and Configuration.SCREENLAYOUT_SIZE_MASK
|
||||
|
||||
return layout == Configuration.SCREENLAYOUT_SIZE_XLARGE ||
|
||||
layout == Configuration.SCREENLAYOUT_SIZE_LARGE
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine if the tablet is XLARGE, ignoring normal tablets.
|
||||
*/
|
||||
fun Context.isXLTablet(): Boolean {
|
||||
val layout = resources.configuration.screenLayout and Configuration.SCREENLAYOUT_SIZE_MASK
|
||||
|
||||
return layout == Configuration.SCREENLAYOUT_SIZE_XLARGE
|
||||
}
|
49
app/src/main/java/org/oxycblt/auxio/util/DbUtil.kt
Normal file
49
app/src/main/java/org/oxycblt/auxio/util/DbUtil.kt
Normal file
|
@ -0,0 +1,49 @@
|
|||
/*
|
||||
* Copyright (c) 2021 Auxio Project
|
||||
* DbUtil.kt is part of Auxio.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package org.oxycblt.auxio.util
|
||||
|
||||
import android.database.Cursor
|
||||
import android.database.sqlite.SQLiteDatabase
|
||||
import android.os.Looper
|
||||
import org.oxycblt.auxio.R
|
||||
|
||||
/**
|
||||
* Shortcut for querying all items in a database and running [block] with the cursor returned.
|
||||
* Will not run if the cursor is null.
|
||||
*/
|
||||
fun <R> SQLiteDatabase.queryAll(tableName: String, block: (Cursor) -> R) =
|
||||
query(tableName, null, null, null, null, null, null)?.use(block)
|
||||
|
||||
/**
|
||||
* Assert that we are on a background thread.
|
||||
*/
|
||||
fun assertBackgroundThread() {
|
||||
check(Looper.myLooper() != Looper.getMainLooper()) {
|
||||
"This operation must be ran on a background thread."
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Assert that we are on a foreground thread.
|
||||
*/
|
||||
fun assertMainThread() {
|
||||
check(Looper.myLooper() == Looper.getMainLooper()) {
|
||||
"This operation must be ran on the main thread"
|
||||
}
|
||||
}
|
|
@ -1,6 +1,6 @@
|
|||
/*
|
||||
* Copyright (c) 2021 Auxio Project
|
||||
* LogUtils.kt is part of Auxio.
|
||||
* LogUtil.kt is part of Auxio.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
|
@ -16,9 +16,10 @@
|
|||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package org.oxycblt.auxio
|
||||
package org.oxycblt.auxio.util
|
||||
|
||||
import android.util.Log
|
||||
import org.oxycblt.auxio.BuildConfig
|
||||
|
||||
// Shortcut functions for logging.
|
||||
// Yes, I know timber exists but this does what I need.
|
|
@ -1,6 +1,6 @@
|
|||
/*
|
||||
* Copyright (c) 2021 Auxio Project
|
||||
* AuxioUtils.kt is part of Auxio.
|
||||
* ViewUtil.kt is part of Auxio.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
|
@ -16,40 +16,54 @@
|
|||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package org.oxycblt.auxio
|
||||
package org.oxycblt.auxio.util
|
||||
|
||||
import android.app.Activity
|
||||
import android.app.PendingIntent
|
||||
import android.content.Context
|
||||
import android.content.Intent
|
||||
import android.content.res.ColorStateList
|
||||
import android.content.res.Configuration
|
||||
import android.content.res.Resources
|
||||
import android.database.Cursor
|
||||
import android.database.sqlite.SQLiteDatabase
|
||||
import android.graphics.drawable.Drawable
|
||||
import android.os.Build
|
||||
import android.os.Looper
|
||||
import android.util.DisplayMetrics
|
||||
import android.util.TypedValue
|
||||
import android.view.LayoutInflater
|
||||
import android.view.WindowManager
|
||||
import android.widget.ImageButton
|
||||
import android.widget.TextView
|
||||
import android.widget.Toast
|
||||
import androidx.annotation.AttrRes
|
||||
import androidx.annotation.ColorInt
|
||||
import androidx.annotation.ColorRes
|
||||
import androidx.annotation.DrawableRes
|
||||
import androidx.annotation.PluralsRes
|
||||
import androidx.annotation.StringRes
|
||||
import androidx.core.content.ContextCompat
|
||||
import androidx.recyclerview.widget.GridLayoutManager
|
||||
import androidx.recyclerview.widget.RecyclerView
|
||||
import kotlin.reflect.KClass
|
||||
import org.oxycblt.auxio.R
|
||||
|
||||
const val INTENT_REQUEST_CODE = 0xA0A0
|
||||
/**
|
||||
* Apply the recommended spans for a [RecyclerView].
|
||||
*
|
||||
* @param shouldBeFullWidth Optional callback for determining whether an item should be full-width,
|
||||
* regardless of spans
|
||||
*/
|
||||
fun RecyclerView.applySpans(shouldBeFullWidth: ((Int) -> Boolean)? = null) {
|
||||
val spans = if (context.isLandscape()) {
|
||||
if (context.isXLTablet()) 3 else 2
|
||||
} else {
|
||||
if (context.isXLTablet()) 2 else 1
|
||||
}
|
||||
|
||||
// --- VIEW CONFIGURATION ---
|
||||
if (spans > 1) {
|
||||
val mgr = GridLayoutManager(context, spans)
|
||||
|
||||
if (shouldBeFullWidth != null) {
|
||||
mgr.spanSizeLookup = object : GridLayoutManager.SpanSizeLookup() {
|
||||
override fun getSpanSize(position: Int): Int {
|
||||
return if (shouldBeFullWidth(position)) spans else 1
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
layoutManager = mgr
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Disable an image button.
|
||||
|
@ -68,90 +82,11 @@ fun TextView.setTextColorResource(@ColorRes color: Int) {
|
|||
setTextColor(color.resolveColor(context))
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the span count for most RecyclerViews. These probably work right on most displays. Trust me.
|
||||
*/
|
||||
val RecyclerView.spans: Int get() =
|
||||
if (context.isLandscape()) {
|
||||
if (context.isXLTablet()) 3 else 2
|
||||
} else {
|
||||
if (context.isXLTablet()) 2 else 1
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns whether a recyclerview can scroll.
|
||||
*/
|
||||
fun RecyclerView.canScroll(): Boolean = computeVerticalScrollRange() > height
|
||||
|
||||
// --- CONVENIENCE ---
|
||||
|
||||
/**
|
||||
* Shortcut to get a [LayoutInflater] from a [Context]
|
||||
*/
|
||||
val Context.inflater: LayoutInflater get() = LayoutInflater.from(this)
|
||||
|
||||
/**
|
||||
* Returns whether the current UI is in night mode or not. This will work if the theme is
|
||||
* automatic as well.
|
||||
*/
|
||||
val Context.isNight: Boolean get() =
|
||||
resources.configuration.uiMode and Configuration.UI_MODE_NIGHT_MASK ==
|
||||
Configuration.UI_MODE_NIGHT_YES
|
||||
|
||||
/**
|
||||
* Convenience method for getting a system service without nullability issues.
|
||||
* @param T The system service in question.
|
||||
* @param serviceClass The service's kotlin class [Java class will be used in function call]
|
||||
* @return The system service
|
||||
* @throws IllegalArgumentException If the system service cannot be retrieved.
|
||||
*/
|
||||
fun <T : Any> Context.getSystemServiceSafe(serviceClass: KClass<T>): T {
|
||||
return requireNotNull(ContextCompat.getSystemService(this, serviceClass.java)) {
|
||||
"System service ${serviceClass.simpleName} could not be instantiated"
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a broadcast [PendingIntent]
|
||||
*/
|
||||
fun Context.newBroadcastIntent(what: String): PendingIntent {
|
||||
return PendingIntent.getBroadcast(
|
||||
this, INTENT_REQUEST_CODE, Intent(what),
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M)
|
||||
PendingIntent.FLAG_IMMUTABLE
|
||||
else 0
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a [PendingIntent] that leads to Auxio's [MainActivity]
|
||||
*/
|
||||
fun Context.newMainIntent(): PendingIntent {
|
||||
return PendingIntent.getActivity(
|
||||
this, INTENT_REQUEST_CODE, Intent(this, MainActivity::class.java),
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M)
|
||||
PendingIntent.FLAG_IMMUTABLE
|
||||
else 0
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a toast using the provided string resource.
|
||||
*/
|
||||
fun Context.showToast(@StringRes str: Int) {
|
||||
Toast.makeText(applicationContext, getString(str), Toast.LENGTH_SHORT).show()
|
||||
}
|
||||
|
||||
/**
|
||||
* Convenience method for getting a plural.
|
||||
* @param pluralsRes Resource for the plural
|
||||
* @param value Int value for the plural.
|
||||
* @return The formatted string requested
|
||||
*/
|
||||
fun Context.getPlural(@PluralsRes pluralsRes: Int, value: Int): String {
|
||||
return resources.getQuantityString(pluralsRes, value, value)
|
||||
}
|
||||
|
||||
/**
|
||||
* Resolve a color.
|
||||
* @param context [Context] required
|
||||
|
@ -204,64 +139,10 @@ fun @receiver:AttrRes Int.resolveAttr(context: Context): Int {
|
|||
}
|
||||
|
||||
/**
|
||||
* Shortcut for querying all items in a database and running [block] with the cursor returned.
|
||||
* Will not run if the cursor is null.
|
||||
*/
|
||||
fun <R> SQLiteDatabase.queryAll(tableName: String, block: (Cursor) -> R) =
|
||||
query(tableName, null, null, null, null, null, null)?.use(block)
|
||||
|
||||
/**
|
||||
* Assert that we are on a background thread.
|
||||
*/
|
||||
fun assertBackgroundThread() {
|
||||
check(Looper.myLooper() != Looper.getMainLooper()) {
|
||||
"This operation must be ran on a background thread."
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Assert that we are on a foreground thread.
|
||||
*/
|
||||
fun assertMainThread() {
|
||||
check(Looper.myLooper() == Looper.getMainLooper()) {
|
||||
"This operation must be ran on the main thread"
|
||||
}
|
||||
}
|
||||
|
||||
// --- CONFIGURATION ---
|
||||
|
||||
/**
|
||||
* Check if edge is on. Really a glorified version check.
|
||||
* @return Whether edge is on.
|
||||
* Check if edge-to-edge is on. Really a glorified version check.
|
||||
*/
|
||||
fun isEdgeOn(): Boolean = Build.VERSION.SDK_INT >= Build.VERSION_CODES.O_MR1
|
||||
|
||||
/**
|
||||
* Determine if the device is currently in landscape.
|
||||
*/
|
||||
fun Context.isLandscape(): Boolean {
|
||||
return resources.configuration.orientation == Configuration.ORIENTATION_LANDSCAPE
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine if we are in tablet mode or not
|
||||
*/
|
||||
fun Context.isTablet(): Boolean {
|
||||
val layout = resources.configuration.screenLayout and Configuration.SCREENLAYOUT_SIZE_MASK
|
||||
|
||||
return layout == Configuration.SCREENLAYOUT_SIZE_XLARGE ||
|
||||
layout == Configuration.SCREENLAYOUT_SIZE_LARGE
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine if the tablet is XLARGE, ignoring normal tablets.
|
||||
*/
|
||||
fun Context.isXLTablet(): Boolean {
|
||||
val layout = resources.configuration.screenLayout and Configuration.SCREENLAYOUT_SIZE_MASK
|
||||
|
||||
return layout == Configuration.SCREENLAYOUT_SIZE_XLARGE
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if we are in the "Irregular" landscape mode (e.g landscape, but nav bar is on the sides)
|
||||
* Used to disable most of edge-to-edge if that's the case, as I cant get it to work on this mode.
|
|
@ -22,10 +22,10 @@ import android.content.Context
|
|||
import android.widget.RemoteViews
|
||||
import androidx.annotation.LayoutRes
|
||||
import org.oxycblt.auxio.R
|
||||
import org.oxycblt.auxio.newBroadcastIntent
|
||||
import org.oxycblt.auxio.newMainIntent
|
||||
import org.oxycblt.auxio.playback.state.LoopMode
|
||||
import org.oxycblt.auxio.playback.system.PlaybackService
|
||||
import org.oxycblt.auxio.util.newBroadcastIntent
|
||||
import org.oxycblt.auxio.util.newMainIntent
|
||||
|
||||
private fun createViews(
|
||||
context: Context,
|
||||
|
|
|
@ -30,9 +30,9 @@ import android.util.SizeF
|
|||
import android.widget.RemoteViews
|
||||
import org.oxycblt.auxio.BuildConfig
|
||||
import org.oxycblt.auxio.coil.loadBitmap
|
||||
import org.oxycblt.auxio.isLandscape
|
||||
import org.oxycblt.auxio.logD
|
||||
import org.oxycblt.auxio.playback.state.PlaybackStateManager
|
||||
import org.oxycblt.auxio.util.isLandscape
|
||||
import org.oxycblt.auxio.util.logD
|
||||
|
||||
/**
|
||||
* Auxio's one and only appwidget. This widget follows a more unorthodox approach, effectively
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
<layout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
tools:context=".recycler.HeaderViewHolder">
|
||||
tools:context=".ui.HeaderViewHolder">
|
||||
|
||||
<data>
|
||||
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
<layout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
tools:context=".recycler.AlbumViewHolder">
|
||||
tools:context=".ui.AlbumViewHolder">
|
||||
|
||||
<data>
|
||||
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
<layout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
tools:context=".recycler.ArtistViewHolder">
|
||||
tools:context=".ui.ArtistViewHolder">
|
||||
|
||||
<data>
|
||||
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
<layout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
tools:context=".recycler.SongViewHolder">
|
||||
tools:context=".ui.SongViewHolder">
|
||||
|
||||
<data>
|
||||
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
<layout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
tools:context=".recycler.GenreViewHolder">
|
||||
tools:context=".ui.GenreViewHolder">
|
||||
|
||||
<data>
|
||||
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<layout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
tools:context=".recycler.HeaderViewHolder">
|
||||
tools:context=".ui.HeaderViewHolder">
|
||||
|
||||
<data>
|
||||
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
<layout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
tools:context=".recycler.SongViewHolder">
|
||||
tools:context=".ui.SongViewHolder">
|
||||
|
||||
<data>
|
||||
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
app:layout="@layout/item_header"
|
||||
app:title="@string/set_ui">
|
||||
|
||||
<org.oxycblt.auxio.settings.ui.IntListPreference
|
||||
<org.oxycblt.auxio.settings.IntListPreference
|
||||
app:defaultValue="@integer/theme_auto"
|
||||
app:entries="@array/entires_theme"
|
||||
app:entryValues="@array/values_theme"
|
||||
|
@ -93,7 +93,7 @@
|
|||
app:layout="@layout/item_header"
|
||||
app:title="@string/set_behavior">
|
||||
|
||||
<org.oxycblt.auxio.settings.ui.IntListPreference
|
||||
<org.oxycblt.auxio.settings.IntListPreference
|
||||
app:defaultValue="@integer/play_mode_songs"
|
||||
app:entries="@array/entries_song_playback_mode"
|
||||
app:entryValues="@array/values_song_playback_mode"
|
||||
|
|
Loading…
Reference in a new issue