kopia lustrzana https://dev.funkwhale.audio/funkwhale/funkwhale-android
rodzic
134a6636ea
commit
94ac0c6b85
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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>() {
|
||||
|
|
|
@ -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>() {
|
||||
|
|
|
@ -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.*
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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>() {
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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>
|
|
@ -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
|
||||
}
|
|
@ -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"
|
||||
}
|
|
@ -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
|
||||
}
|
|
@ -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)
|
|
@ -0,0 +1,3 @@
|
|||
package audio.funkwhale.ffa.model
|
||||
|
||||
data class CoverUrls(val original: String)
|
|
@ -0,0 +1,3 @@
|
|||
package audio.funkwhale.ffa.model
|
||||
|
||||
data class Covers(val urls: CoverUrls)
|
|
@ -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?
|
||||
)
|
|
@ -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>
|
||||
}
|
|
@ -0,0 +1,3 @@
|
|||
package audio.funkwhale.ffa.model
|
||||
|
||||
data class Favorited(val track: Int)
|
|
@ -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 }
|
||||
}
|
|
@ -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
|
||||
)
|
|
@ -0,0 +1,3 @@
|
|||
package audio.funkwhale.ffa.model
|
||||
|
||||
data class PlaylistTrack(val track: Track)
|
|
@ -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
|
||||
}
|
|
@ -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
|
||||
}
|
|
@ -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
|
||||
)
|
|
@ -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
|
||||
}
|
|
@ -0,0 +1,7 @@
|
|||
package audio.funkwhale.ffa.model
|
||||
|
||||
interface SearchResult {
|
||||
fun cover(): String?
|
||||
fun title(): String
|
||||
fun subtitle(): String
|
||||
}
|
|
@ -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"
|
||||
}
|
|
@ -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
|
||||
}
|
|
@ -0,0 +1,5 @@
|
|||
package audio.funkwhale.ffa.model
|
||||
|
||||
data class User(
|
||||
val full_username: String
|
||||
)
|
|
@ -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
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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()))
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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.*
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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",
|
||||
|
|
|
@ -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",
|
||||
|
|
|
@ -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",
|
||||
|
|
|
@ -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)
|
||||
}
|
||||
|
|
|
@ -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",
|
||||
|
|
|
@ -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",
|
||||
|
|
|
@ -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",
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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",
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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?
|
||||
)
|
|
@ -1,4 +1,3 @@
|
|||
package audio.funkwhale.ffa.utils
|
||||
|
||||
object RefreshError : Throwable()
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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}")
|
||||
|
|
|
@ -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"
|
||||
|
|
Ładowanie…
Reference in New Issue