diff --git a/app/src/main/java/audio/funkwhale/ffa/activities/MainActivity.kt b/app/src/main/java/audio/funkwhale/ffa/activities/MainActivity.kt
index 5fe32dff1992da8838f64ed4cbab41ef99caefc5..737f51eff3b4cfd764bc9288bc365771e00621c7 100644
--- a/app/src/main/java/audio/funkwhale/ffa/activities/MainActivity.kt
+++ b/app/src/main/java/audio/funkwhale/ffa/activities/MainActivity.kt
@@ -25,6 +25,7 @@ import audio.funkwhale.ffa.FFA
 import audio.funkwhale.ffa.R
 import audio.funkwhale.ffa.databinding.ActivityMainBinding
 import audio.funkwhale.ffa.fragments.*
+import audio.funkwhale.ffa.model.Track
 import audio.funkwhale.ffa.playback.MediaControlsManager
 import audio.funkwhale.ffa.playback.PinService
 import audio.funkwhale.ffa.playback.PlayerService
diff --git a/app/src/main/java/audio/funkwhale/ffa/activities/SearchActivity.kt b/app/src/main/java/audio/funkwhale/ffa/activities/SearchActivity.kt
index b865427d036d38ca9a8179256bf861e982d230f0..0a530bc7dc271efc821f123e8da012872c84ebcf 100644
--- a/app/src/main/java/audio/funkwhale/ffa/activities/SearchActivity.kt
+++ b/app/src/main/java/audio/funkwhale/ffa/activities/SearchActivity.kt
@@ -11,6 +11,8 @@ import audio.funkwhale.ffa.databinding.ActivitySearchBinding
 import audio.funkwhale.ffa.fragments.AddToPlaylistDialog
 import audio.funkwhale.ffa.fragments.AlbumsFragment
 import audio.funkwhale.ffa.fragments.ArtistsFragment
+import audio.funkwhale.ffa.model.Album
+import audio.funkwhale.ffa.model.Artist
 import audio.funkwhale.ffa.repositories.*
 import audio.funkwhale.ffa.utils.*
 import com.google.android.exoplayer2.offline.Download
diff --git a/app/src/main/java/audio/funkwhale/ffa/adapters/AlbumsAdapter.kt b/app/src/main/java/audio/funkwhale/ffa/adapters/AlbumsAdapter.kt
index 49043849ad31f48dcd652ee3e9f6d34ffa7a8b5d..839f7706f0b9f0a58da1994c8564ce888b06d4ea 100644
--- a/app/src/main/java/audio/funkwhale/ffa/adapters/AlbumsAdapter.kt
+++ b/app/src/main/java/audio/funkwhale/ffa/adapters/AlbumsAdapter.kt
@@ -7,7 +7,7 @@ import android.view.ViewGroup
 import androidx.recyclerview.widget.RecyclerView
 import audio.funkwhale.ffa.databinding.RowAlbumBinding
 import audio.funkwhale.ffa.fragments.FFAAdapter
-import audio.funkwhale.ffa.utils.Album
+import audio.funkwhale.ffa.model.Album
 import audio.funkwhale.ffa.utils.maybeLoad
 import audio.funkwhale.ffa.utils.maybeNormalizeUrl
 import com.squareup.picasso.Picasso
diff --git a/app/src/main/java/audio/funkwhale/ffa/adapters/AlbumsGridAdapter.kt b/app/src/main/java/audio/funkwhale/ffa/adapters/AlbumsGridAdapter.kt
index 0847e0be7748ac72b7b48ba84b8447f0bfc04efc..f3bde832b12e19b9489f5296fda3e470b6d8a168 100644
--- a/app/src/main/java/audio/funkwhale/ffa/adapters/AlbumsGridAdapter.kt
+++ b/app/src/main/java/audio/funkwhale/ffa/adapters/AlbumsGridAdapter.kt
@@ -7,7 +7,7 @@ import androidx.recyclerview.widget.RecyclerView
 import audio.funkwhale.ffa.R
 import audio.funkwhale.ffa.databinding.RowAlbumGridBinding
 import audio.funkwhale.ffa.fragments.FFAAdapter
-import audio.funkwhale.ffa.utils.Album
+import audio.funkwhale.ffa.model.Album
 import audio.funkwhale.ffa.utils.maybeLoad
 import audio.funkwhale.ffa.utils.maybeNormalizeUrl
 import com.squareup.picasso.Picasso
diff --git a/app/src/main/java/audio/funkwhale/ffa/adapters/ArtistsAdapter.kt b/app/src/main/java/audio/funkwhale/ffa/adapters/ArtistsAdapter.kt
index 08d67bd3f7cd297efbe6064c2e79f64f6cdefad1..afdfe42bc958ac6ec3813d44c66f0e551daad0a9 100644
--- a/app/src/main/java/audio/funkwhale/ffa/adapters/ArtistsAdapter.kt
+++ b/app/src/main/java/audio/funkwhale/ffa/adapters/ArtistsAdapter.kt
@@ -8,7 +8,7 @@ import androidx.recyclerview.widget.RecyclerView
 import audio.funkwhale.ffa.R
 import audio.funkwhale.ffa.databinding.RowArtistBinding
 import audio.funkwhale.ffa.fragments.FFAAdapter
-import audio.funkwhale.ffa.utils.Artist
+import audio.funkwhale.ffa.model.Artist
 import audio.funkwhale.ffa.utils.maybeLoad
 import audio.funkwhale.ffa.utils.maybeNormalizeUrl
 import com.squareup.picasso.Picasso
diff --git a/app/src/main/java/audio/funkwhale/ffa/adapters/DownloadsAdapter.kt b/app/src/main/java/audio/funkwhale/ffa/adapters/DownloadsAdapter.kt
index 6cfd35f256e28be5141c8da18f5c29316bb3fa9f..c70032835297d11f1f46948fac2227e0e2bb1fe4 100644
--- a/app/src/main/java/audio/funkwhale/ffa/adapters/DownloadsAdapter.kt
+++ b/app/src/main/java/audio/funkwhale/ffa/adapters/DownloadsAdapter.kt
@@ -9,8 +9,8 @@ import androidx.recyclerview.widget.RecyclerView
 import audio.funkwhale.ffa.R
 import audio.funkwhale.ffa.databinding.RowDownloadBinding
 import audio.funkwhale.ffa.playback.PinService
-import audio.funkwhale.ffa.utils.DownloadInfo
-import audio.funkwhale.ffa.utils.Track
+import audio.funkwhale.ffa.model.DownloadInfo
+import audio.funkwhale.ffa.model.Track
 import com.google.android.exoplayer2.offline.Download
 import com.google.android.exoplayer2.offline.DownloadService
 
diff --git a/app/src/main/java/audio/funkwhale/ffa/adapters/FavoritesAdapter.kt b/app/src/main/java/audio/funkwhale/ffa/adapters/FavoritesAdapter.kt
index 70155d946f6f0d04004ed42b1ef52c35981ca4cc..ac9ceda2bcba42827cf5aa45204c2d774ca16c8d 100644
--- a/app/src/main/java/audio/funkwhale/ffa/adapters/FavoritesAdapter.kt
+++ b/app/src/main/java/audio/funkwhale/ffa/adapters/FavoritesAdapter.kt
@@ -15,7 +15,7 @@ import audio.funkwhale.ffa.databinding.RowTrackBinding
 import audio.funkwhale.ffa.fragments.FFAAdapter
 import audio.funkwhale.ffa.utils.Command
 import audio.funkwhale.ffa.utils.CommandBus
-import audio.funkwhale.ffa.utils.Track
+import audio.funkwhale.ffa.model.Track
 import audio.funkwhale.ffa.utils.maybeLoad
 import audio.funkwhale.ffa.utils.maybeNormalizeUrl
 import audio.funkwhale.ffa.utils.toast
diff --git a/app/src/main/java/audio/funkwhale/ffa/adapters/PlaylistTracksAdapter.kt b/app/src/main/java/audio/funkwhale/ffa/adapters/PlaylistTracksAdapter.kt
index 0d6a4de2aa647f0b5ee95ed9ac8476dae022720d..a51f502372f17477ffa6308a34fc8e1817ac62b7 100644
--- a/app/src/main/java/audio/funkwhale/ffa/adapters/PlaylistTracksAdapter.kt
+++ b/app/src/main/java/audio/funkwhale/ffa/adapters/PlaylistTracksAdapter.kt
@@ -18,8 +18,8 @@ import audio.funkwhale.ffa.databinding.RowTrackBinding
 import audio.funkwhale.ffa.fragments.FFAAdapter
 import audio.funkwhale.ffa.utils.Command
 import audio.funkwhale.ffa.utils.CommandBus
-import audio.funkwhale.ffa.utils.PlaylistTrack
-import audio.funkwhale.ffa.utils.Track
+import audio.funkwhale.ffa.model.PlaylistTrack
+import audio.funkwhale.ffa.model.Track
 import audio.funkwhale.ffa.utils.maybeLoad
 import audio.funkwhale.ffa.utils.maybeNormalizeUrl
 import audio.funkwhale.ffa.utils.toast
diff --git a/app/src/main/java/audio/funkwhale/ffa/adapters/PlaylistsAdapter.kt b/app/src/main/java/audio/funkwhale/ffa/adapters/PlaylistsAdapter.kt
index 66ea686c4fd4be13d71710c036fd1005f69e2026..b6b29d5100cf0d8dbd80c54375a8f7accd369f82 100644
--- a/app/src/main/java/audio/funkwhale/ffa/adapters/PlaylistsAdapter.kt
+++ b/app/src/main/java/audio/funkwhale/ffa/adapters/PlaylistsAdapter.kt
@@ -9,7 +9,7 @@ import androidx.recyclerview.widget.RecyclerView
 import audio.funkwhale.ffa.R
 import audio.funkwhale.ffa.databinding.RowPlaylistBinding
 import audio.funkwhale.ffa.fragments.FFAAdapter
-import audio.funkwhale.ffa.utils.Playlist
+import audio.funkwhale.ffa.model.Playlist
 import audio.funkwhale.ffa.utils.toDurationString
 import com.squareup.picasso.Picasso
 import jp.wasabeef.picasso.transformations.RoundedCornersTransformation
diff --git a/app/src/main/java/audio/funkwhale/ffa/adapters/RadiosAdapter.kt b/app/src/main/java/audio/funkwhale/ffa/adapters/RadiosAdapter.kt
index b4567af2ccb5a5a52e34516734623d2859517934..fb24a520e7aa424359c2b6af88fcc54318277eaa 100644
--- a/app/src/main/java/audio/funkwhale/ffa/adapters/RadiosAdapter.kt
+++ b/app/src/main/java/audio/funkwhale/ffa/adapters/RadiosAdapter.kt
@@ -12,7 +12,7 @@ import audio.funkwhale.ffa.fragments.FFAAdapter
 import audio.funkwhale.ffa.utils.AppContext
 import audio.funkwhale.ffa.utils.Event
 import audio.funkwhale.ffa.utils.EventBus
-import audio.funkwhale.ffa.utils.Radio
+import audio.funkwhale.ffa.model.Radio
 import audio.funkwhale.ffa.views.LoadingImageView
 import com.preference.PowerPreference
 import kotlinx.coroutines.CoroutineScope
diff --git a/app/src/main/java/audio/funkwhale/ffa/adapters/SearchAdapter.kt b/app/src/main/java/audio/funkwhale/ffa/adapters/SearchAdapter.kt
index f7cd7ee23ae3c1eaf6edf12814533b263041d5ce..65181e8033900c7f4d11ccceeb919e04a365e979 100644
--- a/app/src/main/java/audio/funkwhale/ffa/adapters/SearchAdapter.kt
+++ b/app/src/main/java/audio/funkwhale/ffa/adapters/SearchAdapter.kt
@@ -15,11 +15,11 @@ import androidx.recyclerview.widget.RecyclerView
 import audio.funkwhale.ffa.R
 import audio.funkwhale.ffa.databinding.RowSearchHeaderBinding
 import audio.funkwhale.ffa.databinding.RowTrackBinding
-import audio.funkwhale.ffa.utils.Album
-import audio.funkwhale.ffa.utils.Artist
+import audio.funkwhale.ffa.model.Album
+import audio.funkwhale.ffa.model.Artist
 import audio.funkwhale.ffa.utils.Command
 import audio.funkwhale.ffa.utils.CommandBus
-import audio.funkwhale.ffa.utils.Track
+import audio.funkwhale.ffa.model.Track
 import audio.funkwhale.ffa.utils.maybeLoad
 import audio.funkwhale.ffa.utils.maybeNormalizeUrl
 import audio.funkwhale.ffa.utils.onApi
diff --git a/app/src/main/java/audio/funkwhale/ffa/adapters/TracksAdapter.kt b/app/src/main/java/audio/funkwhale/ffa/adapters/TracksAdapter.kt
index 37a9e64994dbff0b8e6075650ddfd960ab524673..381b05f51964198ab2fbd3b0f815667ab30f297d 100644
--- a/app/src/main/java/audio/funkwhale/ffa/adapters/TracksAdapter.kt
+++ b/app/src/main/java/audio/funkwhale/ffa/adapters/TracksAdapter.kt
@@ -20,7 +20,7 @@ import audio.funkwhale.ffa.databinding.RowTrackBinding
 import audio.funkwhale.ffa.fragments.FFAAdapter
 import audio.funkwhale.ffa.utils.Command
 import audio.funkwhale.ffa.utils.CommandBus
-import audio.funkwhale.ffa.utils.Track
+import audio.funkwhale.ffa.model.Track
 import audio.funkwhale.ffa.utils.maybeLoad
 import audio.funkwhale.ffa.utils.maybeNormalizeUrl
 import audio.funkwhale.ffa.utils.toast
diff --git a/app/src/main/java/audio/funkwhale/ffa/fragments/AddToPlaylistDialog.kt b/app/src/main/java/audio/funkwhale/ffa/fragments/AddToPlaylistDialog.kt
index 3002e078b256f782fd35a9d1e80a322693d7ad91..4498e5d6898f4ba592648e8cd18d75949c35c31b 100644
--- a/app/src/main/java/audio/funkwhale/ffa/fragments/AddToPlaylistDialog.kt
+++ b/app/src/main/java/audio/funkwhale/ffa/fragments/AddToPlaylistDialog.kt
@@ -11,6 +11,8 @@ import androidx.recyclerview.widget.LinearLayoutManager
 import audio.funkwhale.ffa.R
 import audio.funkwhale.ffa.adapters.PlaylistsAdapter
 import audio.funkwhale.ffa.databinding.DialogAddToPlaylistBinding
+import audio.funkwhale.ffa.model.Playlist
+import audio.funkwhale.ffa.model.Track
 import audio.funkwhale.ffa.repositories.ManagementPlaylistsRepository
 import audio.funkwhale.ffa.utils.*
 import com.google.gson.Gson
diff --git a/app/src/main/java/audio/funkwhale/ffa/fragments/AlbumsFragment.kt b/app/src/main/java/audio/funkwhale/ffa/fragments/AlbumsFragment.kt
index c5a9e035d7a59f5dd63fd0d83359d2390bf201a7..a6a2116f60c6d02cfa3bf507b1eda8663fcbb04d 100644
--- a/app/src/main/java/audio/funkwhale/ffa/fragments/AlbumsFragment.kt
+++ b/app/src/main/java/audio/funkwhale/ffa/fragments/AlbumsFragment.kt
@@ -20,6 +20,8 @@ import audio.funkwhale.ffa.R
 import audio.funkwhale.ffa.activities.MainActivity
 import audio.funkwhale.ffa.adapters.AlbumsAdapter
 import audio.funkwhale.ffa.databinding.FragmentAlbumsBinding
+import audio.funkwhale.ffa.model.Album
+import audio.funkwhale.ffa.model.Artist
 import audio.funkwhale.ffa.repositories.AlbumsRepository
 import audio.funkwhale.ffa.repositories.ArtistTracksRepository
 import audio.funkwhale.ffa.repositories.Repository
diff --git a/app/src/main/java/audio/funkwhale/ffa/fragments/AlbumsGridFragment.kt b/app/src/main/java/audio/funkwhale/ffa/fragments/AlbumsGridFragment.kt
index bfc041fb579c81ec0266a2447afb3d49d8666174..263ad64f22582221b250887b35f09ff04b707d2d 100644
--- a/app/src/main/java/audio/funkwhale/ffa/fragments/AlbumsGridFragment.kt
+++ b/app/src/main/java/audio/funkwhale/ffa/fragments/AlbumsGridFragment.kt
@@ -14,7 +14,7 @@ import audio.funkwhale.ffa.activities.MainActivity
 import audio.funkwhale.ffa.adapters.AlbumsGridAdapter
 import audio.funkwhale.ffa.databinding.FragmentAlbumsGridBinding
 import audio.funkwhale.ffa.repositories.AlbumsRepository
-import audio.funkwhale.ffa.utils.Album
+import audio.funkwhale.ffa.model.Album
 import audio.funkwhale.ffa.utils.AppContext
 
 class AlbumsGridFragment : FFAFragment<Album, AlbumsGridAdapter>() {
diff --git a/app/src/main/java/audio/funkwhale/ffa/fragments/ArtistsFragment.kt b/app/src/main/java/audio/funkwhale/ffa/fragments/ArtistsFragment.kt
index 75de8a0d4cf9df93b6f2af3ca80cd0ed0741e884..c2ef420de7319a143d19761ee356a27adc4014ea 100644
--- a/app/src/main/java/audio/funkwhale/ffa/fragments/ArtistsFragment.kt
+++ b/app/src/main/java/audio/funkwhale/ffa/fragments/ArtistsFragment.kt
@@ -15,9 +15,9 @@ import audio.funkwhale.ffa.R
 import audio.funkwhale.ffa.activities.MainActivity
 import audio.funkwhale.ffa.adapters.ArtistsAdapter
 import audio.funkwhale.ffa.databinding.FragmentArtistsBinding
+import audio.funkwhale.ffa.model.Artist
 import audio.funkwhale.ffa.repositories.ArtistsRepository
 import audio.funkwhale.ffa.utils.AppContext
-import audio.funkwhale.ffa.utils.Artist
 import audio.funkwhale.ffa.utils.onViewPager
 
 class ArtistsFragment : FFAFragment<Artist, ArtistsAdapter>() {
diff --git a/app/src/main/java/audio/funkwhale/ffa/fragments/FavoritesFragment.kt b/app/src/main/java/audio/funkwhale/ffa/fragments/FavoritesFragment.kt
index 12bb8e2bb5b2e5d13904ff0641cf6fcb74e42368..1a4d27fddd339053a0b9b14fd3ca0d4f84edc0f6 100644
--- a/app/src/main/java/audio/funkwhale/ffa/fragments/FavoritesFragment.kt
+++ b/app/src/main/java/audio/funkwhale/ffa/fragments/FavoritesFragment.kt
@@ -8,6 +8,7 @@ import androidx.lifecycle.lifecycleScope
 import androidx.recyclerview.widget.RecyclerView
 import audio.funkwhale.ffa.adapters.FavoritesAdapter
 import audio.funkwhale.ffa.databinding.FragmentFavoritesBinding
+import audio.funkwhale.ffa.model.Track
 import audio.funkwhale.ffa.repositories.FavoritesRepository
 import audio.funkwhale.ffa.repositories.TracksRepository
 import audio.funkwhale.ffa.utils.*
diff --git a/app/src/main/java/audio/funkwhale/ffa/fragments/PlaylistTracksFragment.kt b/app/src/main/java/audio/funkwhale/ffa/fragments/PlaylistTracksFragment.kt
index 594d603491340880e39dd83049d42f4f8f9a7949..da40ee22091f41f30e00874adfb8335c6916e1ad 100644
--- a/app/src/main/java/audio/funkwhale/ffa/fragments/PlaylistTracksFragment.kt
+++ b/app/src/main/java/audio/funkwhale/ffa/fragments/PlaylistTracksFragment.kt
@@ -17,12 +17,12 @@ import audio.funkwhale.ffa.repositories.ManagementPlaylistsRepository
 import audio.funkwhale.ffa.repositories.PlaylistTracksRepository
 import audio.funkwhale.ffa.utils.Command
 import audio.funkwhale.ffa.utils.CommandBus
-import audio.funkwhale.ffa.utils.Playlist
-import audio.funkwhale.ffa.utils.PlaylistTrack
+import audio.funkwhale.ffa.model.Playlist
+import audio.funkwhale.ffa.model.PlaylistTrack
 import audio.funkwhale.ffa.utils.Request
 import audio.funkwhale.ffa.utils.RequestBus
 import audio.funkwhale.ffa.utils.Response
-import audio.funkwhale.ffa.utils.Track
+import audio.funkwhale.ffa.model.Track
 import audio.funkwhale.ffa.utils.maybeLoad
 import audio.funkwhale.ffa.utils.maybeNormalizeUrl
 import audio.funkwhale.ffa.utils.toast
diff --git a/app/src/main/java/audio/funkwhale/ffa/fragments/PlaylistsFragment.kt b/app/src/main/java/audio/funkwhale/ffa/fragments/PlaylistsFragment.kt
index a6b0081c84cc92de48c0eab57d2b48287d62b49a..83875c57e86c416029f460bcc3a061bce5114fd9 100644
--- a/app/src/main/java/audio/funkwhale/ffa/fragments/PlaylistsFragment.kt
+++ b/app/src/main/java/audio/funkwhale/ffa/fragments/PlaylistsFragment.kt
@@ -14,7 +14,7 @@ import audio.funkwhale.ffa.adapters.PlaylistsAdapter
 import audio.funkwhale.ffa.databinding.FragmentPlaylistsBinding
 import audio.funkwhale.ffa.repositories.PlaylistsRepository
 import audio.funkwhale.ffa.utils.AppContext
-import audio.funkwhale.ffa.utils.Playlist
+import audio.funkwhale.ffa.model.Playlist
 
 class PlaylistsFragment : FFAFragment<Playlist, PlaylistsAdapter>() {
 
diff --git a/app/src/main/java/audio/funkwhale/ffa/fragments/RadiosFragment.kt b/app/src/main/java/audio/funkwhale/ffa/fragments/RadiosFragment.kt
index cdbb7fb1ef74e35e8d1203c4c27ecdc7ccc2ac4d..d57d6258a462185c49084d01219285115626eef3 100644
--- a/app/src/main/java/audio/funkwhale/ffa/fragments/RadiosFragment.kt
+++ b/app/src/main/java/audio/funkwhale/ffa/fragments/RadiosFragment.kt
@@ -14,7 +14,7 @@ import audio.funkwhale.ffa.utils.Command
 import audio.funkwhale.ffa.utils.CommandBus
 import audio.funkwhale.ffa.utils.Event
 import audio.funkwhale.ffa.utils.EventBus
-import audio.funkwhale.ffa.utils.Radio
+import audio.funkwhale.ffa.model.Radio
 import kotlinx.coroutines.Dispatchers.Main
 import kotlinx.coroutines.flow.collect
 import kotlinx.coroutines.launch
diff --git a/app/src/main/java/audio/funkwhale/ffa/fragments/TrackInfoDetailsFragment.kt b/app/src/main/java/audio/funkwhale/ffa/fragments/TrackInfoDetailsFragment.kt
index bed7e24e611856e684b43d37d526ab859a99d670..998073edb4a0603dca65218d9314b8bdde1871e9 100644
--- a/app/src/main/java/audio/funkwhale/ffa/fragments/TrackInfoDetailsFragment.kt
+++ b/app/src/main/java/audio/funkwhale/ffa/fragments/TrackInfoDetailsFragment.kt
@@ -12,7 +12,7 @@ import androidx.core.os.bundleOf
 import androidx.fragment.app.DialogFragment
 import audio.funkwhale.ffa.R
 import audio.funkwhale.ffa.databinding.FragmentTrackInfoDetailsBinding
-import audio.funkwhale.ffa.utils.Track
+import audio.funkwhale.ffa.model.Track
 import audio.funkwhale.ffa.utils.mustNormalizeUrl
 import audio.funkwhale.ffa.utils.toDurationString
 
diff --git a/app/src/main/java/audio/funkwhale/ffa/fragments/TracksFragment.kt b/app/src/main/java/audio/funkwhale/ffa/fragments/TracksFragment.kt
index 70422f4e21eda88cc23c49c4f20c2d296cd32534..ce64521d177b83d1d1e4d47b753ddd222d6f4b0b 100644
--- a/app/src/main/java/audio/funkwhale/ffa/fragments/TracksFragment.kt
+++ b/app/src/main/java/audio/funkwhale/ffa/fragments/TracksFragment.kt
@@ -14,6 +14,8 @@ import androidx.recyclerview.widget.RecyclerView
 import audio.funkwhale.ffa.R
 import audio.funkwhale.ffa.adapters.TracksAdapter
 import audio.funkwhale.ffa.databinding.FragmentTracksBinding
+import audio.funkwhale.ffa.model.Album
+import audio.funkwhale.ffa.model.Track
 import audio.funkwhale.ffa.repositories.FavoritedRepository
 import audio.funkwhale.ffa.repositories.FavoritesRepository
 import audio.funkwhale.ffa.repositories.TracksRepository
diff --git a/app/src/main/java/audio/funkwhale/ffa/model/Album.kt b/app/src/main/java/audio/funkwhale/ffa/model/Album.kt
new file mode 100644
index 0000000000000000000000000000000000000000..cf71c322f25ee1ae7d84f5fec733183df8ac1130
--- /dev/null
+++ b/app/src/main/java/audio/funkwhale/ffa/model/Album.kt
@@ -0,0 +1,17 @@
+package audio.funkwhale.ffa.model
+
+data class Album(
+  val id: Int,
+  val artist: Artist,
+  val title: String,
+  val cover: Covers?,
+  val release_date: String?
+) : SearchResult {
+  data class Artist(val name: String)
+
+  override fun cover() = cover?.urls?.original
+  override fun title() = title
+  override fun subtitle() = artist.name
+}
+
+typealias AlbumList = List<Album>
diff --git a/app/src/main/java/audio/funkwhale/ffa/model/AlbumsResponse.kt b/app/src/main/java/audio/funkwhale/ffa/model/AlbumsResponse.kt
new file mode 100644
index 0000000000000000000000000000000000000000..98aa991bfa81264950d4b7bacb5835fe88f5c34b
--- /dev/null
+++ b/app/src/main/java/audio/funkwhale/ffa/model/AlbumsResponse.kt
@@ -0,0 +1,9 @@
+package audio.funkwhale.ffa.model
+
+data class AlbumsResponse(
+  override val count: Int,
+  override val next: String?,
+  val results: AlbumList
+) : FFAResponse<Album>() {
+  override fun getData() = results
+}
\ No newline at end of file
diff --git a/app/src/main/java/audio/funkwhale/ffa/model/Artist.kt b/app/src/main/java/audio/funkwhale/ffa/model/Artist.kt
new file mode 100644
index 0000000000000000000000000000000000000000..2a74b6d8ad1605112341b4b97ba0154295f183c0
--- /dev/null
+++ b/app/src/main/java/audio/funkwhale/ffa/model/Artist.kt
@@ -0,0 +1,16 @@
+package audio.funkwhale.ffa.model
+
+data class Artist(
+  val id: Int,
+  val name: String,
+  val albums: List<Album>?
+) : SearchResult {
+  data class Album(
+    val title: String,
+    val cover: Covers?
+  )
+
+  override fun cover(): String? = albums?.getOrNull(0)?.cover?.urls?.original
+  override fun title() = name
+  override fun subtitle() = "Artist"
+}
\ No newline at end of file
diff --git a/app/src/main/java/audio/funkwhale/ffa/model/ArtistsResponse.kt b/app/src/main/java/audio/funkwhale/ffa/model/ArtistsResponse.kt
new file mode 100644
index 0000000000000000000000000000000000000000..d59b793e7b01ff6d0dbbb9215cdfa1052fe94418
--- /dev/null
+++ b/app/src/main/java/audio/funkwhale/ffa/model/ArtistsResponse.kt
@@ -0,0 +1,9 @@
+package audio.funkwhale.ffa.model
+
+data class ArtistsResponse(
+  override val count: Int,
+  override val next: String?,
+  val results: List<Artist>
+) : FFAResponse<Artist>() {
+  override fun getData() = results
+}
\ No newline at end of file
diff --git a/app/src/main/java/audio/funkwhale/ffa/model/CacheItem.kt b/app/src/main/java/audio/funkwhale/ffa/model/CacheItem.kt
new file mode 100644
index 0000000000000000000000000000000000000000..616bb87aef25cd4e7bf0094cb68331117519e2cc
--- /dev/null
+++ b/app/src/main/java/audio/funkwhale/ffa/model/CacheItem.kt
@@ -0,0 +1,12 @@
+package audio.funkwhale.ffa.model
+
+sealed class CacheItem<D : Any>(val data: List<D>)
+
+class ArtistsCache(data: List<Artist>) : CacheItem<Artist>(data)
+class AlbumsCache(data: List<Album>) : CacheItem<Album>(data)
+class TracksCache(data: List<Track>) : CacheItem<Track>(data)
+class PlaylistsCache(data: List<Playlist>) : CacheItem<Playlist>(data)
+class PlaylistTracksCache(data: List<PlaylistTrack>) : CacheItem<PlaylistTrack>(data)
+class RadiosCache(data: List<Radio>) : CacheItem<Radio>(data)
+class FavoritedCache(data: List<Int>) : CacheItem<Int>(data)
+class QueueCache(data: List<Track>) : CacheItem<Track>(data)
\ No newline at end of file
diff --git a/app/src/main/java/audio/funkwhale/ffa/model/CoverUrls.kt b/app/src/main/java/audio/funkwhale/ffa/model/CoverUrls.kt
new file mode 100644
index 0000000000000000000000000000000000000000..6c935becc5a805f585693f31dea08e65a1210538
--- /dev/null
+++ b/app/src/main/java/audio/funkwhale/ffa/model/CoverUrls.kt
@@ -0,0 +1,3 @@
+package audio.funkwhale.ffa.model
+
+data class CoverUrls(val original: String)
\ No newline at end of file
diff --git a/app/src/main/java/audio/funkwhale/ffa/model/Covers.kt b/app/src/main/java/audio/funkwhale/ffa/model/Covers.kt
new file mode 100644
index 0000000000000000000000000000000000000000..86b98803395ca762627e8ec7d72e871dc525542d
--- /dev/null
+++ b/app/src/main/java/audio/funkwhale/ffa/model/Covers.kt
@@ -0,0 +1,3 @@
+package audio.funkwhale.ffa.model
+
+data class Covers(val urls: CoverUrls)
\ No newline at end of file
diff --git a/app/src/main/java/audio/funkwhale/ffa/model/DownloadInfo.kt b/app/src/main/java/audio/funkwhale/ffa/model/DownloadInfo.kt
new file mode 100644
index 0000000000000000000000000000000000000000..47d5e0a18019780a2441059ee0d21714d8267d32
--- /dev/null
+++ b/app/src/main/java/audio/funkwhale/ffa/model/DownloadInfo.kt
@@ -0,0 +1,11 @@
+package audio.funkwhale.ffa.model
+
+import com.google.android.exoplayer2.offline.Download
+
+data class DownloadInfo(
+  val id: Int,
+  val contentId: String,
+  val title: String,
+  val artist: String,
+  var download: Download?
+)
\ No newline at end of file
diff --git a/app/src/main/java/audio/funkwhale/ffa/model/FFAResponse.kt b/app/src/main/java/audio/funkwhale/ffa/model/FFAResponse.kt
new file mode 100644
index 0000000000000000000000000000000000000000..289fa29097eff07f330f8d09aafeb34a21758ca8
--- /dev/null
+++ b/app/src/main/java/audio/funkwhale/ffa/model/FFAResponse.kt
@@ -0,0 +1,8 @@
+package audio.funkwhale.ffa.model
+
+abstract class FFAResponse<D : Any> {
+  abstract val count: Int
+  abstract val next: String?
+
+  abstract fun getData(): List<D>
+}
\ No newline at end of file
diff --git a/app/src/main/java/audio/funkwhale/ffa/model/Favorited.kt b/app/src/main/java/audio/funkwhale/ffa/model/Favorited.kt
new file mode 100644
index 0000000000000000000000000000000000000000..facfd2f1a979107dfd1415883fe40358b7589097
--- /dev/null
+++ b/app/src/main/java/audio/funkwhale/ffa/model/Favorited.kt
@@ -0,0 +1,3 @@
+package audio.funkwhale.ffa.model
+
+data class Favorited(val track: Int)
\ No newline at end of file
diff --git a/app/src/main/java/audio/funkwhale/ffa/model/FavoritedResponse.kt b/app/src/main/java/audio/funkwhale/ffa/model/FavoritedResponse.kt
new file mode 100644
index 0000000000000000000000000000000000000000..ab8ae623b52d6be31265cb1fc413bfd0b39c5418
--- /dev/null
+++ b/app/src/main/java/audio/funkwhale/ffa/model/FavoritedResponse.kt
@@ -0,0 +1,9 @@
+package audio.funkwhale.ffa.model
+
+data class FavoritedResponse(
+  override val count: Int,
+  override val next: String?,
+  val results: List<Favorited>
+) : FFAResponse<Int>() {
+  override fun getData() = results.map { it.track }
+}
\ No newline at end of file
diff --git a/app/src/main/java/audio/funkwhale/ffa/model/Playlist.kt b/app/src/main/java/audio/funkwhale/ffa/model/Playlist.kt
new file mode 100644
index 0000000000000000000000000000000000000000..7bf432ad0ecf698b78d9594cfcf9d3366ba7d73a
--- /dev/null
+++ b/app/src/main/java/audio/funkwhale/ffa/model/Playlist.kt
@@ -0,0 +1,9 @@
+package audio.funkwhale.ffa.model
+
+data class Playlist(
+  val id: Int,
+  val name: String,
+  val album_covers: List<String>,
+  val tracks_count: Int,
+  val duration: Int
+)
\ No newline at end of file
diff --git a/app/src/main/java/audio/funkwhale/ffa/model/PlaylistTrack.kt b/app/src/main/java/audio/funkwhale/ffa/model/PlaylistTrack.kt
new file mode 100644
index 0000000000000000000000000000000000000000..4948f57ba7aa2bd6a23c64efcce46e6dc0ba53c0
--- /dev/null
+++ b/app/src/main/java/audio/funkwhale/ffa/model/PlaylistTrack.kt
@@ -0,0 +1,3 @@
+package audio.funkwhale.ffa.model
+
+data class PlaylistTrack(val track: Track)
\ No newline at end of file
diff --git a/app/src/main/java/audio/funkwhale/ffa/model/PlaylistTracksResponse.kt b/app/src/main/java/audio/funkwhale/ffa/model/PlaylistTracksResponse.kt
new file mode 100644
index 0000000000000000000000000000000000000000..ecfddaeba77b337872858e252bc78171de7ced1f
--- /dev/null
+++ b/app/src/main/java/audio/funkwhale/ffa/model/PlaylistTracksResponse.kt
@@ -0,0 +1,9 @@
+package audio.funkwhale.ffa.model
+
+data class PlaylistTracksResponse(
+  override val count: Int,
+  override val next: String?,
+  val results: List<PlaylistTrack>
+) : FFAResponse<PlaylistTrack>() {
+  override fun getData() = results
+}
\ No newline at end of file
diff --git a/app/src/main/java/audio/funkwhale/ffa/model/PlaylistsResponse.kt b/app/src/main/java/audio/funkwhale/ffa/model/PlaylistsResponse.kt
new file mode 100644
index 0000000000000000000000000000000000000000..623ddb267ef2a1f7c31d8f56c930c026e67458ba
--- /dev/null
+++ b/app/src/main/java/audio/funkwhale/ffa/model/PlaylistsResponse.kt
@@ -0,0 +1,9 @@
+package audio.funkwhale.ffa.model
+
+data class PlaylistsResponse(
+  override val count: Int,
+  override val next: String?,
+  val results: List<Playlist>
+) : FFAResponse<Playlist>() {
+  override fun getData() = results
+}
\ No newline at end of file
diff --git a/app/src/main/java/audio/funkwhale/ffa/model/Radio.kt b/app/src/main/java/audio/funkwhale/ffa/model/Radio.kt
new file mode 100644
index 0000000000000000000000000000000000000000..b8d71355af546a6035cbabe55bd4e2a2b42d157d
--- /dev/null
+++ b/app/src/main/java/audio/funkwhale/ffa/model/Radio.kt
@@ -0,0 +1,9 @@
+package audio.funkwhale.ffa.model
+
+data class Radio(
+  val id: Int,
+  var radio_type: String,
+  val name: String,
+  val description: String,
+  var related_object_id: String? = null
+)
\ No newline at end of file
diff --git a/app/src/main/java/audio/funkwhale/ffa/model/RadiosResponse.kt b/app/src/main/java/audio/funkwhale/ffa/model/RadiosResponse.kt
new file mode 100644
index 0000000000000000000000000000000000000000..f2f6d9e989d6333e25f28f73174e959138df8361
--- /dev/null
+++ b/app/src/main/java/audio/funkwhale/ffa/model/RadiosResponse.kt
@@ -0,0 +1,9 @@
+package audio.funkwhale.ffa.model
+
+data class RadiosResponse(
+  override val count: Int,
+  override val next: String?,
+  val results: List<Radio>
+) : FFAResponse<Radio>() {
+  override fun getData() = results
+}
\ No newline at end of file
diff --git a/app/src/main/java/audio/funkwhale/ffa/model/SearchResult.kt b/app/src/main/java/audio/funkwhale/ffa/model/SearchResult.kt
new file mode 100644
index 0000000000000000000000000000000000000000..e5125763b60ede8eb3b804408f82391a72659ecc
--- /dev/null
+++ b/app/src/main/java/audio/funkwhale/ffa/model/SearchResult.kt
@@ -0,0 +1,7 @@
+package audio.funkwhale.ffa.model
+
+interface SearchResult {
+  fun cover(): String?
+  fun title(): String
+  fun subtitle(): String
+}
\ No newline at end of file
diff --git a/app/src/main/java/audio/funkwhale/ffa/model/Track.kt b/app/src/main/java/audio/funkwhale/ffa/model/Track.kt
new file mode 100644
index 0000000000000000000000000000000000000000..a7ea22804f2c1a2a2cc2628571fa0dc8d31183df
--- /dev/null
+++ b/app/src/main/java/audio/funkwhale/ffa/model/Track.kt
@@ -0,0 +1,64 @@
+package audio.funkwhale.ffa.model
+
+import com.preference.PowerPreference
+
+data class Track(
+  val id: Int = 0,
+  val title: String,
+  val artist: Artist,
+  val album: Album?,
+  val disc_number: Int = 0,
+  val position: Int = 0,
+  val uploads: List<Upload> = listOf(),
+  val copyright: String? = null,
+  val license: String? = null
+) : SearchResult {
+  var current: Boolean = false
+  var favorite: Boolean = false
+  var cached: Boolean = false
+  var downloaded: Boolean = false
+
+  companion object {
+
+    fun fromDownload(download: DownloadInfo): Track = Track(
+      id = download.id,
+      title = download.title,
+      artist = Artist(0, download.artist, listOf()),
+      album = Album(0, Album.Artist(""), "", Covers(CoverUrls("")), ""),
+      uploads = listOf(Upload(download.contentId, 0, 0))
+    )
+  }
+
+  data class Upload(
+    val listen_url: String,
+    val duration: Int,
+    val bitrate: Int
+  )
+
+  override fun equals(other: Any?): Boolean {
+    return when (other) {
+      is Track -> other.id == id
+      else -> false
+    }
+  }
+
+  override fun hashCode(): Int {
+    return id
+  }
+
+  fun bestUpload(): Upload? {
+    if (uploads.isEmpty()) return null
+
+    return when (PowerPreference.getDefaultFile().getString("media_cache_quality")) {
+      "quality" -> uploads.maxByOrNull { it.bitrate } ?: uploads[0]
+      "size" -> uploads.minByOrNull { it.bitrate } ?: uploads[0]
+      else -> uploads.maxByOrNull { it.bitrate } ?: uploads[0]
+    }
+  }
+
+  override fun cover() = album?.cover?.urls?.original
+  override fun title() = title
+  override fun subtitle() = artist.name
+
+  val formatted: String get() = "$id $artist ($album): $title"
+}
\ No newline at end of file
diff --git a/app/src/main/java/audio/funkwhale/ffa/model/TracksResponse.kt b/app/src/main/java/audio/funkwhale/ffa/model/TracksResponse.kt
new file mode 100644
index 0000000000000000000000000000000000000000..21cc942a579ad7924312430410e99e7afe798142
--- /dev/null
+++ b/app/src/main/java/audio/funkwhale/ffa/model/TracksResponse.kt
@@ -0,0 +1,9 @@
+package audio.funkwhale.ffa.model
+
+data class TracksResponse(
+  override val count: Int,
+  override val next: String?,
+  val results: List<Track>
+) : FFAResponse<Track>() {
+  override fun getData() = results
+}
\ No newline at end of file
diff --git a/app/src/main/java/audio/funkwhale/ffa/model/User.kt b/app/src/main/java/audio/funkwhale/ffa/model/User.kt
new file mode 100644
index 0000000000000000000000000000000000000000..590f1c5fe790d0baa264c19079a30405e55ff26d
--- /dev/null
+++ b/app/src/main/java/audio/funkwhale/ffa/model/User.kt
@@ -0,0 +1,5 @@
+package audio.funkwhale.ffa.model
+
+data class User(
+  val full_username: String
+)
diff --git a/app/src/main/java/audio/funkwhale/ffa/playback/CacheDataSourceFactoryProvider.kt b/app/src/main/java/audio/funkwhale/ffa/playback/CacheDataSourceFactoryProvider.kt
index 44478f6bd862b723bfceca10db49aa5fa1eab679..74132d2588bceae1e29b48e84bb7a9e684394195 100644
--- a/app/src/main/java/audio/funkwhale/ffa/playback/CacheDataSourceFactoryProvider.kt
+++ b/app/src/main/java/audio/funkwhale/ffa/playback/CacheDataSourceFactoryProvider.kt
@@ -13,32 +13,32 @@ import com.google.android.exoplayer2.upstream.cache.CacheDataSourceFactory
 import com.google.android.exoplayer2.util.Util
 
 class CacheDataSourceFactoryProvider(
-    private val oAuth: OAuth,
-    private val exoCache: Cache,
-    private val exoDownloadCache: Cache
+  private val oAuth: OAuth,
+  private val exoCache: Cache,
+  private val exoDownloadCache: Cache
 ) {
 
   fun create(context: Context): CacheDataSourceFactory {
 
     val playbackCache =
-        CacheDataSourceFactory(exoCache, createDatasourceFactory(context, oAuth))
+      CacheDataSourceFactory(exoCache, createDatasourceFactory(context, oAuth))
 
     return CacheDataSourceFactory(
-        exoDownloadCache,
-        playbackCache,
-        FileDataSource.Factory(),
-        null,
-        CacheDataSource.FLAG_IGNORE_CACHE_ON_ERROR,
-        null
+      exoDownloadCache,
+      playbackCache,
+      FileDataSource.Factory(),
+      null,
+      CacheDataSource.FLAG_IGNORE_CACHE_ON_ERROR,
+      null
     )
   }
 
   private fun createDatasourceFactory(context: Context, oAuth: OAuth): DataSource.Factory {
     val http = DefaultHttpDataSourceFactory(
-        Util.getUserAgent(context, context.getString(R.string.app_name))
+      Util.getUserAgent(context, context.getString(R.string.app_name))
     )
     return if (!Settings.isAnonymous()) {
-        OAuth2DatasourceFactory(context, http, oAuth)
+      OAuth2DatasourceFactory(context, http, oAuth)
     } else {
       http
     }
diff --git a/app/src/main/java/audio/funkwhale/ffa/playback/MediaControlsManager.kt b/app/src/main/java/audio/funkwhale/ffa/playback/MediaControlsManager.kt
index 27c94ad8f4bc7ced907d2d1bf12503b568f9aba5..7fe2a5b7fd318e4ca8f8585cb48188f83824411e 100644
--- a/app/src/main/java/audio/funkwhale/ffa/playback/MediaControlsManager.kt
+++ b/app/src/main/java/audio/funkwhale/ffa/playback/MediaControlsManager.kt
@@ -13,7 +13,7 @@ import androidx.media.session.MediaButtonReceiver
 import audio.funkwhale.ffa.R
 import audio.funkwhale.ffa.activities.MainActivity
 import audio.funkwhale.ffa.utils.AppContext
-import audio.funkwhale.ffa.utils.Track
+import audio.funkwhale.ffa.model.Track
 import audio.funkwhale.ffa.utils.maybeNormalizeUrl
 import com.squareup.picasso.Picasso
 import kotlinx.coroutines.CoroutineScope
diff --git a/app/src/main/java/audio/funkwhale/ffa/playback/MediaSession.kt b/app/src/main/java/audio/funkwhale/ffa/playback/MediaSession.kt
index 2e39bd346c1a8c372777566a22db721ef9225ef8..34ce450d1419403e26762c4125f0c856a08b6952 100644
--- a/app/src/main/java/audio/funkwhale/ffa/playback/MediaSession.kt
+++ b/app/src/main/java/audio/funkwhale/ffa/playback/MediaSession.kt
@@ -40,7 +40,7 @@ class MediaSession(private val context: Context) {
 
   val connector: MediaSessionConnector by lazy {
     MediaSessionConnector(session).also {
-      it.setQueueNavigator(OtterQueueNavigator())
+      it.setQueueNavigator(FFAQueueNavigator())
 
       it.setMediaButtonEventHandler { _, _, intent ->
         if (!active) {
@@ -59,7 +59,7 @@ class MediaSession(private val context: Context) {
   }
 }
 
-class OtterQueueNavigator : MediaSessionConnector.QueueNavigator {
+class FFAQueueNavigator : MediaSessionConnector.QueueNavigator {
   override fun onSkipToQueueItem(player: Player, controlDispatcher: ControlDispatcher, id: Long) {
     CommandBus.send(Command.PlayTrack(id.toInt()))
   }
diff --git a/app/src/main/java/audio/funkwhale/ffa/playback/PinService.kt b/app/src/main/java/audio/funkwhale/ffa/playback/PinService.kt
index e9a30910cafe7f20babf6ad93f100fd0623a7f78..0ef225c7f5d8ff354af4577a43f5ec680237b8f4 100644
--- a/app/src/main/java/audio/funkwhale/ffa/playback/PinService.kt
+++ b/app/src/main/java/audio/funkwhale/ffa/playback/PinService.kt
@@ -5,6 +5,8 @@ import android.content.Context
 import android.content.Intent
 import android.net.Uri
 import audio.funkwhale.ffa.R
+import audio.funkwhale.ffa.model.DownloadInfo
+import audio.funkwhale.ffa.model.Track
 import audio.funkwhale.ffa.utils.*
 import com.google.android.exoplayer2.offline.Download
 import com.google.android.exoplayer2.offline.DownloadManager
diff --git a/app/src/main/java/audio/funkwhale/ffa/playback/PlayerService.kt b/app/src/main/java/audio/funkwhale/ffa/playback/PlayerService.kt
index 310834d8b57f766b9be7102ab0fb177f5e8066d7..5032195c19faf4f64b77ff923f4dba83db8e9bba 100644
--- a/app/src/main/java/audio/funkwhale/ffa/playback/PlayerService.kt
+++ b/app/src/main/java/audio/funkwhale/ffa/playback/PlayerService.kt
@@ -12,11 +12,11 @@ import android.media.MediaMetadata
 import android.os.Build
 import android.os.IBinder
 import android.support.v4.media.MediaMetadataCompat
-import android.util.Log
 import android.view.KeyEvent
 import androidx.core.app.NotificationManagerCompat
 import androidx.media.session.MediaButtonReceiver
 import audio.funkwhale.ffa.R
+import audio.funkwhale.ffa.model.Track
 import audio.funkwhale.ffa.utils.*
 import com.google.android.exoplayer2.C
 import com.google.android.exoplayer2.ExoPlaybackException
diff --git a/app/src/main/java/audio/funkwhale/ffa/playback/QueueManager.kt b/app/src/main/java/audio/funkwhale/ffa/playback/QueueManager.kt
index 45e90fb3f3f07f0d45f28312f7b7df9dfb8f1a87..f7167010389ec54ef8743a47d07f23c9bf2fe75c 100644
--- a/app/src/main/java/audio/funkwhale/ffa/playback/QueueManager.kt
+++ b/app/src/main/java/audio/funkwhale/ffa/playback/QueueManager.kt
@@ -2,6 +2,8 @@ package audio.funkwhale.ffa.playback
 
 import android.content.Context
 import android.net.Uri
+import audio.funkwhale.ffa.model.QueueCache
+import audio.funkwhale.ffa.model.Track
 import audio.funkwhale.ffa.utils.*
 import com.github.kittinunf.fuel.gson.gsonDeserializerOf
 import com.google.android.exoplayer2.source.ConcatenatingMediaSource
@@ -48,7 +50,6 @@ class QueueManager(val context: Context) {
     )
   }
 
-
   fun replace(tracks: List<Track>) {
     tracks.map { it.formatted }.log("Replacing queue with ${tracks.size} tracks")
     val factory = cacheDataSourceFactoryProvider.create(context)
diff --git a/app/src/main/java/audio/funkwhale/ffa/playback/RadioPlayer.kt b/app/src/main/java/audio/funkwhale/ffa/playback/RadioPlayer.kt
index 9a6666558f99b05a4b21bd2fb8bcfbbbcf497f5f..35a9c867558af5726dead677c058b80258d74edb 100644
--- a/app/src/main/java/audio/funkwhale/ffa/playback/RadioPlayer.kt
+++ b/app/src/main/java/audio/funkwhale/ffa/playback/RadioPlayer.kt
@@ -2,6 +2,8 @@ package audio.funkwhale.ffa.playback
 
 import android.content.Context
 import audio.funkwhale.ffa.R
+import audio.funkwhale.ffa.model.Radio
+import audio.funkwhale.ffa.model.Track
 import audio.funkwhale.ffa.repositories.FavoritedRepository
 import audio.funkwhale.ffa.repositories.Repository
 import audio.funkwhale.ffa.utils.*
diff --git a/app/src/main/java/audio/funkwhale/ffa/repositories/AlbumsRepository.kt b/app/src/main/java/audio/funkwhale/ffa/repositories/AlbumsRepository.kt
index daa43f5acbe0b4a81a5aaeab54874550592b3aa5..37df6e701439199f74cd94d4efa1d40453ff1d6c 100644
--- a/app/src/main/java/audio/funkwhale/ffa/repositories/AlbumsRepository.kt
+++ b/app/src/main/java/audio/funkwhale/ffa/repositories/AlbumsRepository.kt
@@ -1,9 +1,9 @@
 package audio.funkwhale.ffa.repositories
 
 import android.content.Context
-import audio.funkwhale.ffa.utils.Album
-import audio.funkwhale.ffa.utils.AlbumsCache
-import audio.funkwhale.ffa.utils.AlbumsResponse
+import audio.funkwhale.ffa.model.Album
+import audio.funkwhale.ffa.model.AlbumsCache
+import audio.funkwhale.ffa.model.AlbumsResponse
 import audio.funkwhale.ffa.utils.OAuth
 import com.github.kittinunf.fuel.gson.gsonDeserializerOf
 import com.google.gson.reflect.TypeToken
diff --git a/app/src/main/java/audio/funkwhale/ffa/repositories/ArtistTracksRepository.kt b/app/src/main/java/audio/funkwhale/ffa/repositories/ArtistTracksRepository.kt
index b5aeadeb176f69ad1a1191ad04742e65e9d6a2dd..46f9dd98345205712c90919d1340ee0fd9a795fc 100644
--- a/app/src/main/java/audio/funkwhale/ffa/repositories/ArtistTracksRepository.kt
+++ b/app/src/main/java/audio/funkwhale/ffa/repositories/ArtistTracksRepository.kt
@@ -1,7 +1,11 @@
 package audio.funkwhale.ffa.repositories
 
 import android.content.Context
-import audio.funkwhale.ffa.utils.*
+import audio.funkwhale.ffa.model.FFAResponse
+import audio.funkwhale.ffa.model.Track
+import audio.funkwhale.ffa.model.TracksCache
+import audio.funkwhale.ffa.model.TracksResponse
+import audio.funkwhale.ffa.utils.OAuth
 import com.github.kittinunf.fuel.gson.gsonDeserializerOf
 import com.google.gson.reflect.TypeToken
 import org.koin.java.KoinJavaComponent.inject
@@ -14,7 +18,7 @@ class ArtistTracksRepository(override val context: Context?, private val artistI
 
   override val cacheId = "tracks-artist-$artistId"
 
-  override val upstream = HttpUpstream<Track, OtterResponse<Track>>(
+  override val upstream = HttpUpstream<Track, FFAResponse<Track>>(
     context,
     HttpUpstream.Behavior.AtOnce,
     "/api/v1/tracks/?playable=true&artist=$artistId",
diff --git a/app/src/main/java/audio/funkwhale/ffa/repositories/ArtistsRepository.kt b/app/src/main/java/audio/funkwhale/ffa/repositories/ArtistsRepository.kt
index a67d99443f0b83dca73d192db95a862276e407b4..3a108d73eedd07e6c24790c135ad009d135169b3 100644
--- a/app/src/main/java/audio/funkwhale/ffa/repositories/ArtistsRepository.kt
+++ b/app/src/main/java/audio/funkwhale/ffa/repositories/ArtistsRepository.kt
@@ -1,7 +1,11 @@
 package audio.funkwhale.ffa.repositories
 
 import android.content.Context
-import audio.funkwhale.ffa.utils.*
+import audio.funkwhale.ffa.model.Artist
+import audio.funkwhale.ffa.model.ArtistsCache
+import audio.funkwhale.ffa.model.ArtistsResponse
+import audio.funkwhale.ffa.model.FFAResponse
+import audio.funkwhale.ffa.utils.OAuth
 import com.github.kittinunf.fuel.gson.gsonDeserializerOf
 import com.google.gson.reflect.TypeToken
 import org.koin.java.KoinJavaComponent.inject
@@ -13,7 +17,7 @@ class ArtistsRepository(override val context: Context?) : Repository<Artist, Art
 
   override val cacheId = "artists"
 
-  override val upstream = HttpUpstream<Artist, OtterResponse<Artist>>(
+  override val upstream = HttpUpstream<Artist, FFAResponse<Artist>>(
     context,
     HttpUpstream.Behavior.Progressive,
     "/api/v1/artists/?playable=true&ordering=name",
diff --git a/app/src/main/java/audio/funkwhale/ffa/repositories/FavoritesRepository.kt b/app/src/main/java/audio/funkwhale/ffa/repositories/FavoritesRepository.kt
index 049c115966a594977ded03550bfbaf82f1981bfd..ca7a04ddeafc7812124e302cb70859cf7cb555c8 100644
--- a/app/src/main/java/audio/funkwhale/ffa/repositories/FavoritesRepository.kt
+++ b/app/src/main/java/audio/funkwhale/ffa/repositories/FavoritesRepository.kt
@@ -1,6 +1,7 @@
 package audio.funkwhale.ffa.repositories
 
 import android.content.Context
+import audio.funkwhale.ffa.model.*
 import audio.funkwhale.ffa.utils.*
 import com.github.kittinunf.fuel.Fuel
 import com.github.kittinunf.fuel.coroutines.awaitByteArrayResponseResult
@@ -25,7 +26,7 @@ class FavoritesRepository(override val context: Context?) : Repository<Track, Tr
 
   override val cacheId = "favorites.v2"
 
-  override val upstream = HttpUpstream<Track, OtterResponse<Track>>(
+  override val upstream = HttpUpstream<Track, FFAResponse<Track>>(
     context!!,
     HttpUpstream.Behavior.AtOnce,
     "/api/v1/tracks/?favorites=true&playable=true&ordering=title",
@@ -106,7 +107,7 @@ class FavoritedRepository(override val context: Context?) : Repository<Int, Favo
   private val oAuth: OAuth by inject(OAuth::class.java)
 
   override val cacheId = "favorited"
-  override val upstream = HttpUpstream<Int, OtterResponse<Int>>(
+  override val upstream = HttpUpstream<Int, FFAResponse<Int>>(
     context,
     HttpUpstream.Behavior.Single,
     "/api/v1/favorites/tracks/all/?playable=true",
diff --git a/app/src/main/java/audio/funkwhale/ffa/repositories/HttpUpstream.kt b/app/src/main/java/audio/funkwhale/ffa/repositories/HttpUpstream.kt
index f01c4d384b21b66f8950d8df5ce898e681a16532..bbf71cb6db7fc744e223fef5d986ec88fb8181de 100644
--- a/app/src/main/java/audio/funkwhale/ffa/repositories/HttpUpstream.kt
+++ b/app/src/main/java/audio/funkwhale/ffa/repositories/HttpUpstream.kt
@@ -3,6 +3,7 @@ package audio.funkwhale.ffa.repositories
 import android.content.Context
 import android.net.Uri
 import android.util.Log
+import audio.funkwhale.ffa.model.FFAResponse
 import audio.funkwhale.ffa.utils.*
 import com.github.kittinunf.fuel.Fuel
 import com.github.kittinunf.fuel.core.FuelError
@@ -19,7 +20,7 @@ import java.io.Reader
 import java.lang.reflect.Type
 import kotlin.math.ceil
 
-class HttpUpstream<D : Any, R : OtterResponse<D>>(
+class HttpUpstream<D : Any, R : FFAResponse<D>>(
   val context: Context?,
   val behavior: Behavior,
   private val url: String,
@@ -78,7 +79,7 @@ class HttpUpstream<D : Any, R : OtterResponse<D>>(
     hasMore
   )
 
-  class GenericDeserializer<T : OtterResponse<*>>(val type: Type) : ResponseDeserializable<T> {
+  class GenericDeserializer<T : FFAResponse<*>>(val type: Type) : ResponseDeserializable<T> {
     override fun deserialize(reader: Reader): T? {
       return Gson().fromJson(reader, type)
     }
diff --git a/app/src/main/java/audio/funkwhale/ffa/repositories/PlaylistTracksRepository.kt b/app/src/main/java/audio/funkwhale/ffa/repositories/PlaylistTracksRepository.kt
index 0dde71cffb21e7442400d211d6b0f2d394ad7be5..e8802ac56d2b96e870033497912cade023773305 100644
--- a/app/src/main/java/audio/funkwhale/ffa/repositories/PlaylistTracksRepository.kt
+++ b/app/src/main/java/audio/funkwhale/ffa/repositories/PlaylistTracksRepository.kt
@@ -1,7 +1,11 @@
 package audio.funkwhale.ffa.repositories
 
 import android.content.Context
-import audio.funkwhale.ffa.utils.*
+import audio.funkwhale.ffa.model.FFAResponse
+import audio.funkwhale.ffa.model.PlaylistTrack
+import audio.funkwhale.ffa.model.PlaylistTracksCache
+import audio.funkwhale.ffa.model.PlaylistTracksResponse
+import audio.funkwhale.ffa.utils.OAuth
 import com.github.kittinunf.fuel.gson.gsonDeserializerOf
 import com.google.gson.reflect.TypeToken
 import kotlinx.coroutines.flow.map
@@ -17,7 +21,7 @@ class PlaylistTracksRepository(override val context: Context?, playlistId: Int)
 
   override val cacheId = "tracks-playlist-$playlistId"
 
-  override val upstream = HttpUpstream<PlaylistTrack, OtterResponse<PlaylistTrack>>(
+  override val upstream = HttpUpstream<PlaylistTrack, FFAResponse<PlaylistTrack>>(
     context,
     HttpUpstream.Behavior.Single,
     "/api/v1/playlists/$playlistId/tracks/?playable=true",
diff --git a/app/src/main/java/audio/funkwhale/ffa/repositories/PlaylistsRepository.kt b/app/src/main/java/audio/funkwhale/ffa/repositories/PlaylistsRepository.kt
index 2aeab5267ed65ccebb94e708e1fac1a90e222309..a496447fc6c90139816c2b7a118db237ab65c2fd 100644
--- a/app/src/main/java/audio/funkwhale/ffa/repositories/PlaylistsRepository.kt
+++ b/app/src/main/java/audio/funkwhale/ffa/repositories/PlaylistsRepository.kt
@@ -1,7 +1,11 @@
 package audio.funkwhale.ffa.repositories
 
 import android.content.Context
-import audio.funkwhale.ffa.utils.*
+import audio.funkwhale.ffa.model.*
+import audio.funkwhale.ffa.utils.OAuth
+import audio.funkwhale.ffa.utils.Settings
+import audio.funkwhale.ffa.utils.authorize
+import audio.funkwhale.ffa.utils.mustNormalizeUrl
 import com.github.kittinunf.fuel.Fuel
 import com.github.kittinunf.fuel.coroutines.awaitByteArrayResponseResult
 import com.github.kittinunf.fuel.coroutines.awaitObjectResponseResult
@@ -21,7 +25,7 @@ class PlaylistsRepository(override val context: Context?) : Repository<Playlist,
 
   private val oAuth: OAuth by inject(OAuth::class.java)
 
-  override val upstream = HttpUpstream<Playlist, OtterResponse<Playlist>>(
+  override val upstream = HttpUpstream<Playlist, FFAResponse<Playlist>>(
     context!!,
     HttpUpstream.Behavior.Progressive,
     "/api/v1/playlists/?playable=true&ordering=name",
@@ -41,7 +45,7 @@ class ManagementPlaylistsRepository(override val context: Context?) :
 
   override val cacheId = "tracks-playlists-management"
 
-  override val upstream = HttpUpstream<Playlist, OtterResponse<Playlist>>(
+  override val upstream = HttpUpstream<Playlist, FFAResponse<Playlist>>(
     context,
     HttpUpstream.Behavior.AtOnce,
     "/api/v1/playlists/?scope=me&ordering=name",
diff --git a/app/src/main/java/audio/funkwhale/ffa/repositories/RadiosRepository.kt b/app/src/main/java/audio/funkwhale/ffa/repositories/RadiosRepository.kt
index 8684befcc8c667bbeae33d9b3e73767c8a299baa..cf70f5336e26d3d6a9972c2faf05796cfe6c33ad 100644
--- a/app/src/main/java/audio/funkwhale/ffa/repositories/RadiosRepository.kt
+++ b/app/src/main/java/audio/funkwhale/ffa/repositories/RadiosRepository.kt
@@ -1,7 +1,11 @@
 package audio.funkwhale.ffa.repositories
 
 import android.content.Context
-import audio.funkwhale.ffa.utils.*
+import audio.funkwhale.ffa.model.FFAResponse
+import audio.funkwhale.ffa.model.Radio
+import audio.funkwhale.ffa.model.RadiosCache
+import audio.funkwhale.ffa.model.RadiosResponse
+import audio.funkwhale.ffa.utils.OAuth
 import com.github.kittinunf.fuel.gson.gsonDeserializerOf
 import com.google.gson.reflect.TypeToken
 import org.koin.java.KoinJavaComponent.inject
@@ -13,7 +17,7 @@ class RadiosRepository(override val context: Context?) : Repository<Radio, Radio
 
   override val cacheId = "radios"
 
-  override val upstream = HttpUpstream<Radio, OtterResponse<Radio>>(
+  override val upstream = HttpUpstream<Radio, FFAResponse<Radio>>(
     context,
     HttpUpstream.Behavior.Progressive,
     "/api/v1/radios/radios/?ordering=name",
diff --git a/app/src/main/java/audio/funkwhale/ffa/repositories/Repository.kt b/app/src/main/java/audio/funkwhale/ffa/repositories/Repository.kt
index adc53ff700c84eb96f2c1fe255190032a40c3ac8..bef2f27d50588fef76b165bc24ece9303fe94140 100644
--- a/app/src/main/java/audio/funkwhale/ffa/repositories/Repository.kt
+++ b/app/src/main/java/audio/funkwhale/ffa/repositories/Repository.kt
@@ -2,7 +2,7 @@ package audio.funkwhale.ffa.repositories
 
 import android.content.Context
 import audio.funkwhale.ffa.utils.AppContext
-import audio.funkwhale.ffa.utils.CacheItem
+import audio.funkwhale.ffa.model.CacheItem
 import audio.funkwhale.ffa.utils.FFACache
 import kotlinx.coroutines.CoroutineScope
 import kotlinx.coroutines.Dispatchers.IO
diff --git a/app/src/main/java/audio/funkwhale/ffa/repositories/SearchRepository.kt b/app/src/main/java/audio/funkwhale/ffa/repositories/SearchRepository.kt
index c23788c92ecb5a08c7b05f29da9ef549174636df..cd27c73a9c31461ff78cba5581c07b98d7396387 100644
--- a/app/src/main/java/audio/funkwhale/ffa/repositories/SearchRepository.kt
+++ b/app/src/main/java/audio/funkwhale/ffa/repositories/SearchRepository.kt
@@ -1,6 +1,7 @@
 package audio.funkwhale.ffa.repositories
 
 import android.content.Context
+import audio.funkwhale.ffa.model.*
 import audio.funkwhale.ffa.utils.*
 import com.github.kittinunf.fuel.gson.gsonDeserializerOf
 import com.google.android.exoplayer2.offline.DownloadManager
diff --git a/app/src/main/java/audio/funkwhale/ffa/repositories/TracksRepository.kt b/app/src/main/java/audio/funkwhale/ffa/repositories/TracksRepository.kt
index b6b5f3e0095bee1ca10c0d57792af97c41d54ddb..c247869ef574e07bd5759f3b773460b8d6dffa70 100644
--- a/app/src/main/java/audio/funkwhale/ffa/repositories/TracksRepository.kt
+++ b/app/src/main/java/audio/funkwhale/ffa/repositories/TracksRepository.kt
@@ -1,7 +1,13 @@
 package audio.funkwhale.ffa.repositories
 
 import android.content.Context
-import audio.funkwhale.ffa.utils.*
+import audio.funkwhale.ffa.model.FFAResponse
+import audio.funkwhale.ffa.model.Track
+import audio.funkwhale.ffa.model.TracksCache
+import audio.funkwhale.ffa.model.TracksResponse
+import audio.funkwhale.ffa.utils.OAuth
+import audio.funkwhale.ffa.utils.getMetadata
+import audio.funkwhale.ffa.utils.mustNormalizeUrl
 import com.github.kittinunf.fuel.gson.gsonDeserializerOf
 import com.google.android.exoplayer2.offline.Download
 import com.google.android.exoplayer2.offline.DownloadManager
@@ -23,7 +29,7 @@ class TracksRepository(override val context: Context?, albumId: Int) :
 
   override val cacheId = "tracks-album-$albumId"
 
-  override val upstream = HttpUpstream<Track, OtterResponse<Track>>(
+  override val upstream = HttpUpstream<Track, FFAResponse<Track>>(
     context,
     HttpUpstream.Behavior.AtOnce,
     "/api/v1/tracks/?playable=true&album=$albumId&ordering=disc_number,position",
diff --git a/app/src/main/java/audio/funkwhale/ffa/utils/Bus.kt b/app/src/main/java/audio/funkwhale/ffa/utils/Bus.kt
index 791df86e2ec9a92bc2c8235f4a60c9a95f587bf7..49e836c5b012e77ecc90c85b4609d939f7533446 100644
--- a/app/src/main/java/audio/funkwhale/ffa/utils/Bus.kt
+++ b/app/src/main/java/audio/funkwhale/ffa/utils/Bus.kt
@@ -1,6 +1,8 @@
 package audio.funkwhale.ffa.utils
 
 import audio.funkwhale.ffa.FFA
+import audio.funkwhale.ffa.model.Radio
+import audio.funkwhale.ffa.model.Track
 import com.google.android.exoplayer2.offline.Download
 import com.google.android.exoplayer2.offline.DownloadCursor
 import kotlinx.coroutines.Dispatchers.IO
diff --git a/app/src/main/java/audio/funkwhale/ffa/utils/Extensions.kt b/app/src/main/java/audio/funkwhale/ffa/utils/Extensions.kt
index ababd6e91b3cda27da5378420248023d0d80390a..70d5d11c57f2c2c424c31423f9d3eed3f5c90356 100644
--- a/app/src/main/java/audio/funkwhale/ffa/utils/Extensions.kt
+++ b/app/src/main/java/audio/funkwhale/ffa/utils/Extensions.kt
@@ -2,11 +2,11 @@ package audio.funkwhale.ffa.utils
 
 import android.content.Context
 import android.os.Build
-import android.os.SystemClock
 import android.util.Log
 import androidx.fragment.app.Fragment
 import audio.funkwhale.ffa.R
 import audio.funkwhale.ffa.fragments.BrowseFragment
+import audio.funkwhale.ffa.model.DownloadInfo
 import audio.funkwhale.ffa.repositories.Repository
 import com.github.kittinunf.fuel.core.FuelError
 import com.github.kittinunf.fuel.core.Request
@@ -26,7 +26,6 @@ import java.text.SimpleDateFormat
 import java.util.*
 import kotlin.coroutines.CoroutineContext
 
-
 inline fun <D> Flow<Repository.Response<D>>.untilNetwork(
   scope: CoroutineScope,
   context: CoroutineContext = Main,
diff --git a/app/src/main/java/audio/funkwhale/ffa/utils/FFACache.kt b/app/src/main/java/audio/funkwhale/ffa/utils/FFACache.kt
index 446c209269522be3c86c42e157a6590fc00bc44d..2d4bbca76201e2d4a8f7ad10dd36b756d0a436f0 100644
--- a/app/src/main/java/audio/funkwhale/ffa/utils/FFACache.kt
+++ b/app/src/main/java/audio/funkwhale/ffa/utils/FFACache.kt
@@ -7,6 +7,7 @@ import java.nio.charset.Charset
 import java.security.MessageDigest
 
 object FFACache {
+
   private fun key(key: String): String {
     val md = MessageDigest.getInstance("SHA-1")
     val digest = md.digest(key.toByteArray(Charset.defaultCharset()))
@@ -35,4 +36,4 @@ object FFACache {
       delete()
     }
   }
-}
\ No newline at end of file
+}
diff --git a/app/src/main/java/audio/funkwhale/ffa/utils/Models.kt b/app/src/main/java/audio/funkwhale/ffa/utils/Models.kt
deleted file mode 100644
index dc6bae9691115e2c053110c3d4b8c32825f7abc5..0000000000000000000000000000000000000000
--- a/app/src/main/java/audio/funkwhale/ffa/utils/Models.kt
+++ /dev/null
@@ -1,213 +0,0 @@
-package audio.funkwhale.ffa.utils
-
-import com.google.android.exoplayer2.offline.Download
-import com.preference.PowerPreference
-
-data class User(
-  val full_username: String
-)
-
-sealed class CacheItem<D : Any>(val data: List<D>)
-class ArtistsCache(data: List<Artist>) : CacheItem<Artist>(data)
-class AlbumsCache(data: List<Album>) : CacheItem<Album>(data)
-class TracksCache(data: List<Track>) : CacheItem<Track>(data)
-class PlaylistsCache(data: List<Playlist>) : CacheItem<Playlist>(data)
-class PlaylistTracksCache(data: List<PlaylistTrack>) : CacheItem<PlaylistTrack>(data)
-class RadiosCache(data: List<Radio>) : CacheItem<Radio>(data)
-class FavoritedCache(data: List<Int>) : CacheItem<Int>(data)
-class QueueCache(data: List<Track>) : CacheItem<Track>(data)
-
-abstract class OtterResponse<D : Any> {
-  abstract val count: Int
-  abstract val next: String?
-
-  abstract fun getData(): List<D>
-}
-
-data class UserResponse(
-  override val count: Int,
-  override val next: String?,
-  val results: List<Artist>
-) : OtterResponse<Artist>() {
-  override fun getData() = results
-}
-
-data class ArtistsResponse(
-  override val count: Int,
-  override val next: String?,
-  val results: List<Artist>
-) : OtterResponse<Artist>() {
-  override fun getData() = results
-}
-
-data class AlbumsResponse(
-  override val count: Int,
-  override val next: String?,
-  val results: AlbumList
-) : OtterResponse<Album>() {
-  override fun getData() = results
-}
-
-data class TracksResponse(
-  override val count: Int,
-  override val next: String?,
-  val results: List<Track>
-) : OtterResponse<Track>() {
-  override fun getData() = results
-}
-
-data class FavoritedResponse(
-  override val count: Int,
-  override val next: String?,
-  val results: List<Favorited>
-) : OtterResponse<Int>() {
-  override fun getData() = results.map { it.track }
-}
-
-data class PlaylistsResponse(
-  override val count: Int,
-  override val next: String?,
-  val results: List<Playlist>
-) : OtterResponse<Playlist>() {
-  override fun getData() = results
-}
-
-data class PlaylistTracksResponse(
-  override val count: Int,
-  override val next: String?,
-  val results: List<PlaylistTrack>
-) : OtterResponse<PlaylistTrack>() {
-  override fun getData() = results
-}
-
-data class RadiosResponse(
-  override val count: Int,
-  override val next: String?,
-  val results: List<Radio>
-) : OtterResponse<Radio>() {
-  override fun getData() = results
-}
-
-data class Covers(val urls: CoverUrls)
-data class CoverUrls(val original: String)
-
-typealias AlbumList = List<Album>
-
-interface SearchResult {
-  fun cover(): String?
-  fun title(): String
-  fun subtitle(): String
-}
-
-data class Album(
-  val id: Int,
-  val artist: Artist,
-  val title: String,
-  val cover: Covers?,
-  val release_date: String?
-) : SearchResult {
-  data class Artist(val name: String)
-
-  override fun cover() = cover?.urls?.original
-  override fun title() = title
-  override fun subtitle() = artist.name
-}
-
-data class Artist(
-  val id: Int,
-  val name: String,
-  val albums: List<Album>?
-) : SearchResult {
-  data class Album(
-    val title: String,
-    val cover: Covers?
-  )
-
-  override fun cover(): String? = albums?.getOrNull(0)?.cover?.urls?.original
-  override fun title() = name
-  override fun subtitle() = "Artist"
-}
-
-data class Track(
-  val id: Int = 0,
-  val title: String,
-  val artist: Artist,
-  val album: Album?,
-  val disc_number: Int = 0,
-  val position: Int = 0,
-  val uploads: List<Upload> = listOf(),
-  val copyright: String? = null,
-  val license: String? = null
-) : SearchResult {
-  var current: Boolean = false
-  var favorite: Boolean = false
-  var cached: Boolean = false
-  var downloaded: Boolean = false
-
-  companion object {
-    fun fromDownload(download: DownloadInfo): Track = Track(
-      id = download.id,
-      title = download.title,
-      artist = Artist(0, download.artist, listOf()),
-      album = Album(0, Album.Artist(""), "", Covers(CoverUrls("")), ""),
-      uploads = listOf(Upload(download.contentId, 0, 0))
-    )
-  }
-
-  data class Upload(
-    val listen_url: String,
-    val duration: Int,
-    val bitrate: Int
-  )
-
-  override fun equals(other: Any?): Boolean {
-    return when (other) {
-      is Track -> other.id == id
-      else -> false
-    }
-  }
-
-  fun bestUpload(): Upload? {
-    if (uploads.isEmpty()) return null
-
-    return when (PowerPreference.getDefaultFile().getString("media_cache_quality")) {
-      "quality" -> uploads.maxByOrNull { it.bitrate } ?: uploads[0]
-      "size" -> uploads.minByOrNull { it.bitrate } ?: uploads[0]
-      else -> uploads.maxByOrNull { it.bitrate } ?: uploads[0]
-    }
-  }
-
-  override fun cover() = album?.cover?.urls?.original
-  override fun title() = title
-  override fun subtitle() = artist.name
-
-  val formatted: String get() = "$id $artist ($album): $title"
-}
-
-data class Favorited(val track: Int)
-
-data class Playlist(
-  val id: Int,
-  val name: String,
-  val album_covers: List<String>,
-  val tracks_count: Int,
-  val duration: Int
-)
-
-data class PlaylistTrack(val track: Track)
-
-data class Radio(
-  val id: Int,
-  var radio_type: String,
-  val name: String,
-  val description: String,
-  var related_object_id: String? = null
-)
-
-data class DownloadInfo(
-  val id: Int,
-  val contentId: String,
-  val title: String,
-  val artist: String,
-  var download: Download?
-)
diff --git a/app/src/main/java/audio/funkwhale/ffa/utils/RefreshError.kt b/app/src/main/java/audio/funkwhale/ffa/utils/RefreshError.kt
index 1f572a4139fd570c9b8cf8b7ab9f629eee113a06..1aa42715c1a5b301dc43e575ab5b61ffb633c116 100644
--- a/app/src/main/java/audio/funkwhale/ffa/utils/RefreshError.kt
+++ b/app/src/main/java/audio/funkwhale/ffa/utils/RefreshError.kt
@@ -1,4 +1,3 @@
 package audio.funkwhale.ffa.utils
 
 object RefreshError : Throwable()
-
diff --git a/app/src/main/java/audio/funkwhale/ffa/utils/Userinfo.kt b/app/src/main/java/audio/funkwhale/ffa/utils/Userinfo.kt
index 2131d0b578bd9f8940558543a64e8a719e251aa9..737c890490870c3f8c296c695946ed3daed0b94f 100644
--- a/app/src/main/java/audio/funkwhale/ffa/utils/Userinfo.kt
+++ b/app/src/main/java/audio/funkwhale/ffa/utils/Userinfo.kt
@@ -1,6 +1,7 @@
 package audio.funkwhale.ffa.utils
 
 import android.content.Context
+import audio.funkwhale.ffa.model.User
 import com.github.kittinunf.fuel.Fuel
 import com.github.kittinunf.fuel.coroutines.awaitObjectResponseResult
 import com.github.kittinunf.fuel.gson.gsonDeserializerOf
diff --git a/build.gradle.kts b/build.gradle.kts
index 13a86505cb79dec51855bde694a2363cec84d6b9..4fd1c5d6fac7883ea9866110977a721954e04bce 100644
--- a/build.gradle.kts
+++ b/build.gradle.kts
@@ -7,7 +7,7 @@ buildscript {
   }
 
   dependencies {
-    classpath("com.android.tools.build:gradle:${Versions.androidGradlePlugin}")
+    classpath("com.android.tools.build:gradle:7.0.1")
     classpath("org.jetbrains.kotlin:kotlin-gradle-plugin:${Versions.kotlin}")
     classpath("com.github.bjoernq:unmockplugin:${Versions.unmock}")
     classpath("com.github.ben-manes:gradle-versions-plugin:${Versions.gradleDependencyPlugin}")
diff --git a/buildSrc/src/main/java/Versions.kt b/buildSrc/src/main/java/Versions.kt
index dd2f605c7842cada28458867ce4c65ccca172d9b..db8e8f85bf9d4b3cf0577e4f75b46aef9a0b492e 100644
--- a/buildSrc/src/main/java/Versions.kt
+++ b/buildSrc/src/main/java/Versions.kt
@@ -2,7 +2,6 @@ object Versions {
   const val kotlin = "1.5.21"
   const val jacoco = "0.8.7"
   const val unmock = "0.7.8"
-  const val androidGradlePlugin = "7.0.0"
   const val gradleDependencyPlugin = "0.38.0"
 
   const val exoPlayer = "2.11.8"