From 5fe01777d0dc8aa3b8c9125d1b2d5441e0c7168c Mon Sep 17 00:00:00 2001 From: OxygenCobalt Date: Mon, 23 Aug 2021 17:05:42 -0600 Subject: [PATCH] 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. --- .../java/org/oxycblt/auxio/MainActivity.kt | 3 + .../java/org/oxycblt/auxio/MainFragment.kt | 2 + .../java/org/oxycblt/auxio/accent/Accent.kt | 2 +- .../org/oxycblt/auxio/accent/AccentAdapter.kt | 4 +- .../org/oxycblt/auxio/accent/AccentDialog.kt | 6 +- .../auxio/detail/AlbumDetailFragment.kt | 6 +- .../auxio/detail/ArtistDetailFragment.kt | 4 +- .../oxycblt/auxio/detail/DetailFragment.kt | 2 +- .../oxycblt/auxio/detail/DetailViewModel.kt | 2 +- .../auxio/detail/GenreDetailFragment.kt | 2 +- .../detail/adapters/AlbumDetailAdapter.kt | 10 +- .../detail/adapters/ArtistDetailAdapter.kt | 12 +- .../detail/adapters/GenreDetailAdapter.kt | 10 +- .../auxio/excluded/ExcludedDatabase.kt | 6 +- .../oxycblt/auxio/excluded/ExcludedDialog.kt | 7 +- .../auxio/excluded/ExcludedEntryAdapter.kt | 2 +- .../org/oxycblt/auxio/home/HomeAdapter.kt | 8 +- .../org/oxycblt/auxio/home/HomeFragment.kt | 6 +- .../oxycblt/auxio/home/HomeListFragment.kt | 14 +- .../org/oxycblt/auxio/home/HomeViewModel.kt | 2 +- .../oxycblt/auxio/loading/LoadingFragment.kt | 2 +- .../org/oxycblt/auxio/music/MusicLoader.kt | 2 +- .../org/oxycblt/auxio/music/MusicStore.kt | 4 +- .../org/oxycblt/auxio/music/MusicUtils.kt | 2 +- .../auxio/playback/CompactPlaybackFragment.kt | 3 +- .../auxio/playback/PlaybackFragment.kt | 6 +- .../auxio/playback/PlaybackViewModel.kt | 6 +- .../auxio/playback/queue/QueueAdapter.kt | 10 +- .../auxio/playback/queue/QueueFragment.kt | 4 +- .../auxio/playback/state/DatabaseQueueItem.kt | 41 ---- .../auxio/playback/state/DatabaseState.kt | 55 ------ .../playback/state/PlaybackStateDatabase.kt | 64 ++++++- .../playback/state/PlaybackStateManager.kt | 4 +- .../auxio/playback/system/AudioReactor.kt | 4 +- .../playback/system/PlaybackNotification.kt | 4 +- .../auxio/playback/system/PlaybackService.kt | 4 +- .../system/PlaybackSessionConnector.kt | 2 +- .../oxycblt/auxio/recycler/BaseViewHolder.kt | 76 -------- .../org/oxycblt/auxio/search/SearchAdapter.kt | 12 +- .../oxycblt/auxio/search/SearchFragment.kt | 49 ++--- .../oxycblt/auxio/search/SearchViewModel.kt | 2 +- .../oxycblt/auxio/settings/AboutFragment.kt | 4 +- .../settings/{ui => }/IntListPrefDialog.kt | 2 +- .../settings/{ui => }/IntListPreference.kt | 2 +- .../oxycblt/auxio/settings/SettingUtils.kt | 5 - .../oxycblt/auxio/settings/SettingsCompat.kt | 5 + .../auxio/settings/SettingsListFragment.kt | 8 +- .../oxycblt/auxio/settings/SettingsManager.kt | 4 +- .../java/org/oxycblt/auxio/ui/ActionMenu.kt | 2 +- .../auxio/{recycler => ui}/DiffCallback.kt | 2 +- .../auxio/{recycler => ui}/DisplayMode.kt | 2 +- .../org/oxycblt/auxio/ui/LifecycleDialog.kt | 2 +- .../java/org/oxycblt/auxio/ui/MemberBinder.kt | 4 +- .../auxio/{recycler => ui}/SortMode.kt | 2 +- .../ModelHolders.kt => ui/ViewHolders.kt} | 61 +++++- .../org/oxycblt/auxio/util/ContextUtil.kt | 127 ++++++++++++ .../java/org/oxycblt/auxio/util/DbUtil.kt | 49 +++++ .../auxio/{LogUtils.kt => util/LogUtil.kt} | 5 +- .../auxio/{AuxioUtils.kt => util/ViewUtil.kt} | 181 +++--------------- .../java/org/oxycblt/auxio/widgets/Forms.kt | 4 +- .../oxycblt/auxio/widgets/WidgetProvider.kt | 4 +- .../main/res/layout/item_action_header.xml | 2 +- app/src/main/res/layout/item_album.xml | 2 +- app/src/main/res/layout/item_artist.xml | 2 +- app/src/main/res/layout/item_artist_song.xml | 2 +- app/src/main/res/layout/item_genre.xml | 2 +- app/src/main/res/layout/item_header.xml | 2 +- app/src/main/res/layout/item_song.xml | 2 +- app/src/main/res/xml/prefs_main.xml | 4 +- 69 files changed, 476 insertions(+), 483 deletions(-) delete mode 100644 app/src/main/java/org/oxycblt/auxio/playback/state/DatabaseQueueItem.kt delete mode 100644 app/src/main/java/org/oxycblt/auxio/playback/state/DatabaseState.kt delete mode 100644 app/src/main/java/org/oxycblt/auxio/recycler/BaseViewHolder.kt rename app/src/main/java/org/oxycblt/auxio/settings/{ui => }/IntListPrefDialog.kt (97%) rename app/src/main/java/org/oxycblt/auxio/settings/{ui => }/IntListPreference.kt (98%) rename app/src/main/java/org/oxycblt/auxio/{recycler => ui}/DiffCallback.kt (97%) rename app/src/main/java/org/oxycblt/auxio/{recycler => ui}/DisplayMode.kt (98%) rename app/src/main/java/org/oxycblt/auxio/{recycler => ui}/SortMode.kt (99%) rename app/src/main/java/org/oxycblt/auxio/{recycler/ModelHolders.kt => ui/ViewHolders.kt} (73%) create mode 100644 app/src/main/java/org/oxycblt/auxio/util/ContextUtil.kt create mode 100644 app/src/main/java/org/oxycblt/auxio/util/DbUtil.kt rename app/src/main/java/org/oxycblt/auxio/{LogUtils.kt => util/LogUtil.kt} (94%) rename app/src/main/java/org/oxycblt/auxio/{AuxioUtils.kt => util/ViewUtil.kt} (51%) diff --git a/app/src/main/java/org/oxycblt/auxio/MainActivity.kt b/app/src/main/java/org/oxycblt/auxio/MainActivity.kt index cb494ef61..d17b0a01a 100644 --- a/app/src/main/java/org/oxycblt/auxio/MainActivity.kt +++ b/app/src/main/java/org/oxycblt/auxio/MainActivity.kt @@ -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. diff --git a/app/src/main/java/org/oxycblt/auxio/MainFragment.kt b/app/src/main/java/org/oxycblt/auxio/MainFragment.kt index 5a8644bae..a0a11c346 100644 --- a/app/src/main/java/org/oxycblt/auxio/MainFragment.kt +++ b/app/src/main/java/org/oxycblt/auxio/MainFragment.kt @@ -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 diff --git a/app/src/main/java/org/oxycblt/auxio/accent/Accent.kt b/app/src/main/java/org/oxycblt/auxio/accent/Accent.kt index 3959a0f4a..29a551434 100644 --- a/app/src/main/java/org/oxycblt/auxio/accent/Accent.kt +++ b/app/src/main/java/org/oxycblt/auxio/accent/Accent.kt @@ -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. diff --git a/app/src/main/java/org/oxycblt/auxio/accent/AccentAdapter.kt b/app/src/main/java/org/oxycblt/auxio/accent/AccentAdapter.kt index a2b2b1d83..f6fb269c0 100644 --- a/app/src/main/java/org/oxycblt/auxio/accent/AccentAdapter.kt +++ b/app/src/main/java/org/oxycblt/auxio/accent/AccentAdapter.kt @@ -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. diff --git a/app/src/main/java/org/oxycblt/auxio/accent/AccentDialog.kt b/app/src/main/java/org/oxycblt/auxio/accent/AccentDialog.kt index 1a1d5e2d5..1003f89f8 100644 --- a/app/src/main/java/org/oxycblt/auxio/accent/AccentDialog.kt +++ b/app/src/main/java/org/oxycblt/auxio/accent/AccentDialog.kt @@ -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" } } diff --git a/app/src/main/java/org/oxycblt/auxio/detail/AlbumDetailFragment.kt b/app/src/main/java/org/oxycblt/auxio/detail/AlbumDetailFragment.kt index 56bbce306..4d84d25fe 100644 --- a/app/src/main/java/org/oxycblt/auxio/detail/AlbumDetailFragment.kt +++ b/app/src/main/java/org/oxycblt/auxio/detail/AlbumDetailFragment.kt @@ -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. diff --git a/app/src/main/java/org/oxycblt/auxio/detail/ArtistDetailFragment.kt b/app/src/main/java/org/oxycblt/auxio/detail/ArtistDetailFragment.kt index 4a627e740..0cedbd5fe 100644 --- a/app/src/main/java/org/oxycblt/auxio/detail/ArtistDetailFragment.kt +++ b/app/src/main/java/org/oxycblt/auxio/detail/ArtistDetailFragment.kt @@ -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. diff --git a/app/src/main/java/org/oxycblt/auxio/detail/DetailFragment.kt b/app/src/main/java/org/oxycblt/auxio/detail/DetailFragment.kt index 23adc169e..d97fd43b2 100644 --- a/app/src/main/java/org/oxycblt/auxio/detail/DetailFragment.kt +++ b/app/src/main/java/org/oxycblt/auxio/detail/DetailFragment.kt @@ -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. diff --git a/app/src/main/java/org/oxycblt/auxio/detail/DetailViewModel.kt b/app/src/main/java/org/oxycblt/auxio/detail/DetailViewModel.kt index c71a05191..15d4133c8 100644 --- a/app/src/main/java/org/oxycblt/auxio/detail/DetailViewModel.kt +++ b/app/src/main/java/org/oxycblt/auxio/detail/DetailViewModel.kt @@ -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 diff --git a/app/src/main/java/org/oxycblt/auxio/detail/GenreDetailFragment.kt b/app/src/main/java/org/oxycblt/auxio/detail/GenreDetailFragment.kt index 5ca8d1a8b..43f5ee30f 100644 --- a/app/src/main/java/org/oxycblt/auxio/detail/GenreDetailFragment.kt +++ b/app/src/main/java/org/oxycblt/auxio/detail/GenreDetailFragment.kt @@ -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. diff --git a/app/src/main/java/org/oxycblt/auxio/detail/adapters/AlbumDetailAdapter.kt b/app/src/main/java/org/oxycblt/auxio/detail/adapters/AlbumDetailAdapter.kt index eddcc6b43..c5263c2c3 100644 --- a/app/src/main/java/org/oxycblt/auxio/detail/adapters/AlbumDetailAdapter.kt +++ b/app/src/main/java/org/oxycblt/auxio/detail/adapters/AlbumDetailAdapter.kt @@ -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] diff --git a/app/src/main/java/org/oxycblt/auxio/detail/adapters/ArtistDetailAdapter.kt b/app/src/main/java/org/oxycblt/auxio/detail/adapters/ArtistDetailAdapter.kt index 605e9efe0..31beca5b8 100644 --- a/app/src/main/java/org/oxycblt/auxio/detail/adapters/ArtistDetailAdapter.kt +++ b/app/src/main/java/org/oxycblt/auxio/detail/adapters/ArtistDetailAdapter.kt @@ -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. diff --git a/app/src/main/java/org/oxycblt/auxio/detail/adapters/GenreDetailAdapter.kt b/app/src/main/java/org/oxycblt/auxio/detail/adapters/GenreDetailAdapter.kt index d73bd0f94..6d0fb279d 100644 --- a/app/src/main/java/org/oxycblt/auxio/detail/adapters/GenreDetailAdapter.kt +++ b/app/src/main/java/org/oxycblt/auxio/detail/adapters/GenreDetailAdapter.kt @@ -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. diff --git a/app/src/main/java/org/oxycblt/auxio/excluded/ExcludedDatabase.kt b/app/src/main/java/org/oxycblt/auxio/excluded/ExcludedDatabase.kt index b1478b022..a5d434f95 100644 --- a/app/src/main/java/org/oxycblt/auxio/excluded/ExcludedDatabase.kt +++ b/app/src/main/java/org/oxycblt/auxio/excluded/ExcludedDatabase.kt @@ -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. diff --git a/app/src/main/java/org/oxycblt/auxio/excluded/ExcludedDialog.kt b/app/src/main/java/org/oxycblt/auxio/excluded/ExcludedDialog.kt index 5932e9116..40b39c00d 100644 --- a/app/src/main/java/org/oxycblt/auxio/excluded/ExcludedDialog.kt +++ b/app/src/main/java/org/oxycblt/auxio/excluded/ExcludedDialog.kt @@ -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" } } diff --git a/app/src/main/java/org/oxycblt/auxio/excluded/ExcludedEntryAdapter.kt b/app/src/main/java/org/oxycblt/auxio/excluded/ExcludedEntryAdapter.kt index 5479f94bf..ba27ac342 100644 --- a/app/src/main/java/org/oxycblt/auxio/excluded/ExcludedEntryAdapter.kt +++ b/app/src/main/java/org/oxycblt/auxio/excluded/ExcludedEntryAdapter.kt @@ -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. diff --git a/app/src/main/java/org/oxycblt/auxio/home/HomeAdapter.kt b/app/src/main/java/org/oxycblt/auxio/home/HomeAdapter.kt index bcb5f4781..3dd747f79 100644 --- a/app/src/main/java/org/oxycblt/auxio/home/HomeAdapter.kt +++ b/app/src/main/java/org/oxycblt/auxio/home/HomeAdapter.kt @@ -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, diff --git a/app/src/main/java/org/oxycblt/auxio/home/HomeFragment.kt b/app/src/main/java/org/oxycblt/auxio/home/HomeFragment.kt index 9034540f9..fe0047558 100644 --- a/app/src/main/java/org/oxycblt/auxio/home/HomeFragment.kt +++ b/app/src/main/java/org/oxycblt/auxio/home/HomeFragment.kt @@ -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 diff --git a/app/src/main/java/org/oxycblt/auxio/home/HomeListFragment.kt b/app/src/main/java/org/oxycblt/auxio/home/HomeListFragment.kt index 2216a08f0..ed43011a0 100644 --- a/app/src/main/java/org/oxycblt/auxio/home/HomeListFragment.kt +++ b/app/src/main/java/org/oxycblt/auxio/home/HomeListFragment.kt @@ -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 --- diff --git a/app/src/main/java/org/oxycblt/auxio/home/HomeViewModel.kt b/app/src/main/java/org/oxycblt/auxio/home/HomeViewModel.kt index aac5b2b3e..70b64ba5d 100644 --- a/app/src/main/java/org/oxycblt/auxio/home/HomeViewModel.kt +++ b/app/src/main/java/org/oxycblt/auxio/home/HomeViewModel.kt @@ -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()) diff --git a/app/src/main/java/org/oxycblt/auxio/loading/LoadingFragment.kt b/app/src/main/java/org/oxycblt/auxio/loading/LoadingFragment.kt index c5b64b81e..a0f84df68 100644 --- a/app/src/main/java/org/oxycblt/auxio/loading/LoadingFragment.kt +++ b/app/src/main/java/org/oxycblt/auxio/loading/LoadingFragment.kt @@ -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. diff --git a/app/src/main/java/org/oxycblt/auxio/music/MusicLoader.kt b/app/src/main/java/org/oxycblt/auxio/music/MusicLoader.kt index 60c10233a..30881a46c 100644 --- a/app/src/main/java/org/oxycblt/auxio/music/MusicLoader.kt +++ b/app/src/main/java/org/oxycblt/auxio/music/MusicLoader.kt @@ -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 diff --git a/app/src/main/java/org/oxycblt/auxio/music/MusicStore.kt b/app/src/main/java/org/oxycblt/auxio/music/MusicStore.kt index 11bd3857a..ced3a2848 100644 --- a/app/src/main/java/org/oxycblt/auxio/music/MusicStore.kt +++ b/app/src/main/java/org/oxycblt/auxio/music/MusicStore.kt @@ -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 /** diff --git a/app/src/main/java/org/oxycblt/auxio/music/MusicUtils.kt b/app/src/main/java/org/oxycblt/auxio/music/MusicUtils.kt index 17b753714..5e905d785 100644 --- a/app/src/main/java/org/oxycblt/auxio/music/MusicUtils.kt +++ b/app/src/main/java/org/oxycblt/auxio/music/MusicUtils.kt @@ -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 . - */ - -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" - } -} diff --git a/app/src/main/java/org/oxycblt/auxio/playback/state/DatabaseState.kt b/app/src/main/java/org/oxycblt/auxio/playback/state/DatabaseState.kt deleted file mode 100644 index b210dfd7c..000000000 --- a/app/src/main/java/org/oxycblt/auxio/playback/state/DatabaseState.kt +++ /dev/null @@ -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 . - */ - -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" - } -} diff --git a/app/src/main/java/org/oxycblt/auxio/playback/state/PlaybackStateDatabase.kt b/app/src/main/java/org/oxycblt/auxio/playback/state/PlaybackStateDatabase.kt index 6c61b77f8..ecdfc38c3 100644 --- a/app/src/main/java/org/oxycblt/auxio/playback/state/PlaybackStateDatabase.kt +++ b/app/src/main/java/org/oxycblt/auxio/playback/state/PlaybackStateDatabase.kt @@ -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" + } +} diff --git a/app/src/main/java/org/oxycblt/auxio/playback/state/PlaybackStateManager.kt b/app/src/main/java/org/oxycblt/auxio/playback/state/PlaybackStateManager.kt index 36c6aaeb9..1eabc616e 100644 --- a/app/src/main/java/org/oxycblt/auxio/playback/state/PlaybackStateManager.kt +++ b/app/src/main/java/org/oxycblt/auxio/playback/state/PlaybackStateManager.kt @@ -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. diff --git a/app/src/main/java/org/oxycblt/auxio/playback/system/AudioReactor.kt b/app/src/main/java/org/oxycblt/auxio/playback/system/AudioReactor.kt index e80d3b100..7eaa8e442 100644 --- a/app/src/main/java/org/oxycblt/auxio/playback/system/AudioReactor.kt +++ b/app/src/main/java/org/oxycblt/auxio/playback/system/AudioReactor.kt @@ -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. diff --git a/app/src/main/java/org/oxycblt/auxio/playback/system/PlaybackNotification.kt b/app/src/main/java/org/oxycblt/auxio/playback/system/PlaybackNotification.kt index 0e546445c..cb42354bc 100644 --- a/app/src/main/java/org/oxycblt/auxio/playback/system/PlaybackNotification.kt +++ b/app/src/main/java/org/oxycblt/auxio/playback/system/PlaybackNotification.kt @@ -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 diff --git a/app/src/main/java/org/oxycblt/auxio/playback/system/PlaybackService.kt b/app/src/main/java/org/oxycblt/auxio/playback/system/PlaybackService.kt index 760b92f29..629b40ff3 100644 --- a/app/src/main/java/org/oxycblt/auxio/playback/system/PlaybackService.kt +++ b/app/src/main/java/org/oxycblt/auxio/playback/system/PlaybackService.kt @@ -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 diff --git a/app/src/main/java/org/oxycblt/auxio/playback/system/PlaybackSessionConnector.kt b/app/src/main/java/org/oxycblt/auxio/playback/system/PlaybackSessionConnector.kt index 1ae65ebee..fa61fa312 100644 --- a/app/src/main/java/org/oxycblt/auxio/playback/system/PlaybackSessionConnector.kt +++ b/app/src/main/java/org/oxycblt/auxio/playback/system/PlaybackSessionConnector.kt @@ -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], diff --git a/app/src/main/java/org/oxycblt/auxio/recycler/BaseViewHolder.kt b/app/src/main/java/org/oxycblt/auxio/recycler/BaseViewHolder.kt deleted file mode 100644 index eea6ee3a5..000000000 --- a/app/src/main/java/org/oxycblt/auxio/recycler/BaseViewHolder.kt +++ /dev/null @@ -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 . - */ - -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( - 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) -} diff --git a/app/src/main/java/org/oxycblt/auxio/search/SearchAdapter.kt b/app/src/main/java/org/oxycblt/auxio/search/SearchAdapter.kt index 2228eaf14..64192ce59 100644 --- a/app/src/main/java/org/oxycblt/auxio/search/SearchAdapter.kt +++ b/app/src/main/java/org/oxycblt/auxio/search/SearchAdapter.kt @@ -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. diff --git a/app/src/main/java/org/oxycblt/auxio/search/SearchFragment.kt b/app/src/main/java/org/oxycblt/auxio/search/SearchFragment.kt index 0ada1817c..7b5889d73 100644 --- a/app/src/main/java/org/oxycblt/auxio/search/SearchFragment.kt +++ b/app/src/main/java/org/oxycblt/auxio/search/SearchFragment.kt @@ -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() } } } diff --git a/app/src/main/java/org/oxycblt/auxio/search/SearchViewModel.kt b/app/src/main/java/org/oxycblt/auxio/search/SearchViewModel.kt index 977f464d5..86df5114d 100644 --- a/app/src/main/java/org/oxycblt/auxio/search/SearchViewModel.kt +++ b/app/src/main/java/org/oxycblt/auxio/search/SearchViewModel.kt @@ -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 diff --git a/app/src/main/java/org/oxycblt/auxio/settings/AboutFragment.kt b/app/src/main/java/org/oxycblt/auxio/settings/AboutFragment.kt index 2829389ed..2eee8c381 100644 --- a/app/src/main/java/org/oxycblt/auxio/settings/AboutFragment.kt +++ b/app/src/main/java/org/oxycblt/auxio/settings/AboutFragment.kt @@ -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. diff --git a/app/src/main/java/org/oxycblt/auxio/settings/ui/IntListPrefDialog.kt b/app/src/main/java/org/oxycblt/auxio/settings/IntListPrefDialog.kt similarity index 97% rename from app/src/main/java/org/oxycblt/auxio/settings/ui/IntListPrefDialog.kt rename to app/src/main/java/org/oxycblt/auxio/settings/IntListPrefDialog.kt index ba418516d..ee24d82b2 100644 --- a/app/src/main/java/org/oxycblt/auxio/settings/ui/IntListPrefDialog.kt +++ b/app/src/main/java/org/oxycblt/auxio/settings/IntListPrefDialog.kt @@ -16,7 +16,7 @@ * along with this program. If not, see . */ -package org.oxycblt.auxio.settings.ui +package org.oxycblt.auxio.settings import androidx.appcompat.app.AlertDialog import org.oxycblt.auxio.ui.LifecycleDialog diff --git a/app/src/main/java/org/oxycblt/auxio/settings/ui/IntListPreference.kt b/app/src/main/java/org/oxycblt/auxio/settings/IntListPreference.kt similarity index 98% rename from app/src/main/java/org/oxycblt/auxio/settings/ui/IntListPreference.kt rename to app/src/main/java/org/oxycblt/auxio/settings/IntListPreference.kt index c9396356a..565b457f5 100644 --- a/app/src/main/java/org/oxycblt/auxio/settings/ui/IntListPreference.kt +++ b/app/src/main/java/org/oxycblt/auxio/settings/IntListPreference.kt @@ -16,7 +16,7 @@ * along with this program. If not, see . */ -package org.oxycblt.auxio.settings.ui +package org.oxycblt.auxio.settings import android.content.Context import android.content.res.TypedArray diff --git a/app/src/main/java/org/oxycblt/auxio/settings/SettingUtils.kt b/app/src/main/java/org/oxycblt/auxio/settings/SettingUtils.kt index 145b4a037..8b11f490d 100644 --- a/app/src/main/java/org/oxycblt/auxio/settings/SettingUtils.kt +++ b/app/src/main/java/org/oxycblt/auxio/settings/SettingUtils.kt @@ -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. diff --git a/app/src/main/java/org/oxycblt/auxio/settings/SettingsCompat.kt b/app/src/main/java/org/oxycblt/auxio/settings/SettingsCompat.kt index 7bec5b494..d508421d6 100644 --- a/app/src/main/java/org/oxycblt/auxio/settings/SettingsCompat.kt +++ b/app/src/main/java/org/oxycblt/auxio/settings/SettingsCompat.kt @@ -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. */ diff --git a/app/src/main/java/org/oxycblt/auxio/settings/SettingsListFragment.kt b/app/src/main/java/org/oxycblt/auxio/settings/SettingsListFragment.kt index 9d1db8b15..fadc6ef74 100644 --- a/app/src/main/java/org/oxycblt/auxio/settings/SettingsListFragment.kt +++ b/app/src/main/java/org/oxycblt/auxio/settings/SettingsListFragment.kt @@ -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]. diff --git a/app/src/main/java/org/oxycblt/auxio/settings/SettingsManager.kt b/app/src/main/java/org/oxycblt/auxio/settings/SettingsManager.kt index 166ce4b11..e9772b296 100644 --- a/app/src/main/java/org/oxycblt/auxio/settings/SettingsManager.kt +++ b/app/src/main/java/org/oxycblt/auxio/settings/SettingsManager.kt @@ -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. diff --git a/app/src/main/java/org/oxycblt/auxio/ui/ActionMenu.kt b/app/src/main/java/org/oxycblt/auxio/ui/ActionMenu.kt index 645bb4732..d132f1414 100644 --- a/app/src/main/java/org/oxycblt/auxio/ui/ActionMenu.kt +++ b/app/src/main/java/org/oxycblt/auxio/ui/ActionMenu.kt @@ -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]. diff --git a/app/src/main/java/org/oxycblt/auxio/recycler/DiffCallback.kt b/app/src/main/java/org/oxycblt/auxio/ui/DiffCallback.kt similarity index 97% rename from app/src/main/java/org/oxycblt/auxio/recycler/DiffCallback.kt rename to app/src/main/java/org/oxycblt/auxio/ui/DiffCallback.kt index e2aad4bae..a1aa55ddb 100644 --- a/app/src/main/java/org/oxycblt/auxio/recycler/DiffCallback.kt +++ b/app/src/main/java/org/oxycblt/auxio/ui/DiffCallback.kt @@ -16,7 +16,7 @@ * along with this program. If not, see . */ -package org.oxycblt.auxio.recycler +package org.oxycblt.auxio.ui import androidx.recyclerview.widget.DiffUtil import org.oxycblt.auxio.music.BaseModel diff --git a/app/src/main/java/org/oxycblt/auxio/recycler/DisplayMode.kt b/app/src/main/java/org/oxycblt/auxio/ui/DisplayMode.kt similarity index 98% rename from app/src/main/java/org/oxycblt/auxio/recycler/DisplayMode.kt rename to app/src/main/java/org/oxycblt/auxio/ui/DisplayMode.kt index 31d8f055d..5bdcc93b1 100644 --- a/app/src/main/java/org/oxycblt/auxio/recycler/DisplayMode.kt +++ b/app/src/main/java/org/oxycblt/auxio/ui/DisplayMode.kt @@ -16,7 +16,7 @@ * along with this program. If not, see . */ -package org.oxycblt.auxio.recycler +package org.oxycblt.auxio.ui /** * An enum for determining what items to show in a given list. diff --git a/app/src/main/java/org/oxycblt/auxio/ui/LifecycleDialog.kt b/app/src/main/java/org/oxycblt/auxio/ui/LifecycleDialog.kt index 7a6a39cdf..ecf0ac8f2 100644 --- a/app/src/main/java/org/oxycblt/auxio/ui/LifecycleDialog.kt +++ b/app/src/main/java/org/oxycblt/auxio/ui/LifecycleDialog.kt @@ -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 diff --git a/app/src/main/java/org/oxycblt/auxio/ui/MemberBinder.kt b/app/src/main/java/org/oxycblt/auxio/ui/MemberBinder.kt index 0dc191aa0..e7b2e0ffe 100644 --- a/app/src/main/java/org/oxycblt/auxio/ui/MemberBinder.kt +++ b/app/src/main/java/org/oxycblt/auxio/ui/MemberBinder.kt @@ -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 diff --git a/app/src/main/java/org/oxycblt/auxio/recycler/SortMode.kt b/app/src/main/java/org/oxycblt/auxio/ui/SortMode.kt similarity index 99% rename from app/src/main/java/org/oxycblt/auxio/recycler/SortMode.kt rename to app/src/main/java/org/oxycblt/auxio/ui/SortMode.kt index a3645debc..5a8e12a32 100644 --- a/app/src/main/java/org/oxycblt/auxio/recycler/SortMode.kt +++ b/app/src/main/java/org/oxycblt/auxio/ui/SortMode.kt @@ -16,7 +16,7 @@ * along with this program. If not, see . */ -package org.oxycblt.auxio.recycler +package org.oxycblt.auxio.ui import android.widget.ImageButton import androidx.annotation.DrawableRes diff --git a/app/src/main/java/org/oxycblt/auxio/recycler/ModelHolders.kt b/app/src/main/java/org/oxycblt/auxio/ui/ViewHolders.kt similarity index 73% rename from app/src/main/java/org/oxycblt/auxio/recycler/ModelHolders.kt rename to app/src/main/java/org/oxycblt/auxio/ui/ViewHolders.kt index 7099fe6ed..0844ee228 100644 --- a/app/src/main/java/org/oxycblt/auxio/recycler/ModelHolders.kt +++ b/app/src/main/java/org/oxycblt/auxio/ui/ViewHolders.kt @@ -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 . */ -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( + 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]. diff --git a/app/src/main/java/org/oxycblt/auxio/util/ContextUtil.kt b/app/src/main/java/org/oxycblt/auxio/util/ContextUtil.kt new file mode 100644 index 000000000..c926c5195 --- /dev/null +++ b/app/src/main/java/org/oxycblt/auxio/util/ContextUtil.kt @@ -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 . + */ + +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 Context.getSystemServiceSafe(serviceClass: KClass): 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 +} diff --git a/app/src/main/java/org/oxycblt/auxio/util/DbUtil.kt b/app/src/main/java/org/oxycblt/auxio/util/DbUtil.kt new file mode 100644 index 000000000..5d7d93fb3 --- /dev/null +++ b/app/src/main/java/org/oxycblt/auxio/util/DbUtil.kt @@ -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 . + */ + +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 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" + } +} diff --git a/app/src/main/java/org/oxycblt/auxio/LogUtils.kt b/app/src/main/java/org/oxycblt/auxio/util/LogUtil.kt similarity index 94% rename from app/src/main/java/org/oxycblt/auxio/LogUtils.kt rename to app/src/main/java/org/oxycblt/auxio/util/LogUtil.kt index f018bad30..195fd73ae 100644 --- a/app/src/main/java/org/oxycblt/auxio/LogUtils.kt +++ b/app/src/main/java/org/oxycblt/auxio/util/LogUtil.kt @@ -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 . */ -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. diff --git a/app/src/main/java/org/oxycblt/auxio/AuxioUtils.kt b/app/src/main/java/org/oxycblt/auxio/util/ViewUtil.kt similarity index 51% rename from app/src/main/java/org/oxycblt/auxio/AuxioUtils.kt rename to app/src/main/java/org/oxycblt/auxio/util/ViewUtil.kt index b963b38b5..387d0676b 100644 --- a/app/src/main/java/org/oxycblt/auxio/AuxioUtils.kt +++ b/app/src/main/java/org/oxycblt/auxio/util/ViewUtil.kt @@ -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 . */ -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 Context.getSystemServiceSafe(serviceClass: KClass): 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 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. diff --git a/app/src/main/java/org/oxycblt/auxio/widgets/Forms.kt b/app/src/main/java/org/oxycblt/auxio/widgets/Forms.kt index e004b6d8a..166619469 100644 --- a/app/src/main/java/org/oxycblt/auxio/widgets/Forms.kt +++ b/app/src/main/java/org/oxycblt/auxio/widgets/Forms.kt @@ -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, diff --git a/app/src/main/java/org/oxycblt/auxio/widgets/WidgetProvider.kt b/app/src/main/java/org/oxycblt/auxio/widgets/WidgetProvider.kt index c59bab6d5..47a459623 100644 --- a/app/src/main/java/org/oxycblt/auxio/widgets/WidgetProvider.kt +++ b/app/src/main/java/org/oxycblt/auxio/widgets/WidgetProvider.kt @@ -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 diff --git a/app/src/main/res/layout/item_action_header.xml b/app/src/main/res/layout/item_action_header.xml index fb1ebfae3..276c70917 100644 --- a/app/src/main/res/layout/item_action_header.xml +++ b/app/src/main/res/layout/item_action_header.xml @@ -2,7 +2,7 @@ + tools:context=".ui.HeaderViewHolder"> diff --git a/app/src/main/res/layout/item_album.xml b/app/src/main/res/layout/item_album.xml index 0e502143f..755d96b2c 100644 --- a/app/src/main/res/layout/item_album.xml +++ b/app/src/main/res/layout/item_album.xml @@ -2,7 +2,7 @@ + tools:context=".ui.AlbumViewHolder"> diff --git a/app/src/main/res/layout/item_artist.xml b/app/src/main/res/layout/item_artist.xml index 17f17edad..5e425c3a5 100644 --- a/app/src/main/res/layout/item_artist.xml +++ b/app/src/main/res/layout/item_artist.xml @@ -2,7 +2,7 @@ + tools:context=".ui.ArtistViewHolder"> diff --git a/app/src/main/res/layout/item_artist_song.xml b/app/src/main/res/layout/item_artist_song.xml index 1305d5519..6cd55d05b 100644 --- a/app/src/main/res/layout/item_artist_song.xml +++ b/app/src/main/res/layout/item_artist_song.xml @@ -2,7 +2,7 @@ + tools:context=".ui.SongViewHolder"> diff --git a/app/src/main/res/layout/item_genre.xml b/app/src/main/res/layout/item_genre.xml index fce33d841..c01e67147 100644 --- a/app/src/main/res/layout/item_genre.xml +++ b/app/src/main/res/layout/item_genre.xml @@ -2,7 +2,7 @@ + tools:context=".ui.GenreViewHolder"> diff --git a/app/src/main/res/layout/item_header.xml b/app/src/main/res/layout/item_header.xml index a7d73be74..90d060cf5 100644 --- a/app/src/main/res/layout/item_header.xml +++ b/app/src/main/res/layout/item_header.xml @@ -1,7 +1,7 @@ + tools:context=".ui.HeaderViewHolder"> diff --git a/app/src/main/res/layout/item_song.xml b/app/src/main/res/layout/item_song.xml index 62bbe5172..5772dc0eb 100644 --- a/app/src/main/res/layout/item_song.xml +++ b/app/src/main/res/layout/item_song.xml @@ -2,7 +2,7 @@ + tools:context=".ui.SongViewHolder"> diff --git a/app/src/main/res/xml/prefs_main.xml b/app/src/main/res/xml/prefs_main.xml index 35c179e59..594832126 100644 --- a/app/src/main/res/xml/prefs_main.xml +++ b/app/src/main/res/xml/prefs_main.xml @@ -4,7 +4,7 @@ app:layout="@layout/item_header" app:title="@string/set_ui"> - -