Browse Source

Fix existing linting problems

housekeeping/mavenCentral
Ryan Harg 3 years ago
parent
commit
ef3387dee0
No known key found for this signature in database
GPG Key ID: 89106F3A84E6958C
  1. 16
      app/build.gradle.kts
  2. 9
      app/src/main/java/audio/funkwhale/ffa/FFA.kt
  3. 6
      app/src/main/java/audio/funkwhale/ffa/activities/DownloadsActivity.kt
  4. 3
      app/src/main/java/audio/funkwhale/ffa/activities/LicencesActivity.kt
  5. 5
      app/src/main/java/audio/funkwhale/ffa/activities/LoginActivity.kt
  6. 69
      app/src/main/java/audio/funkwhale/ffa/activities/MainActivity.kt
  7. 93
      app/src/main/java/audio/funkwhale/ffa/activities/SearchActivity.kt
  8. 6
      app/src/main/java/audio/funkwhale/ffa/activities/SettingsActivity.kt
  9. 4
      app/src/main/java/audio/funkwhale/ffa/activities/SplashActivity.kt
  10. 11
      app/src/main/java/audio/funkwhale/ffa/adapters/BrowseTabsAdapter.kt
  11. 2
      app/src/main/java/audio/funkwhale/ffa/adapters/DownloadsAdapter.kt
  12. 2
      app/src/main/java/audio/funkwhale/ffa/adapters/FavoritesAdapter.kt
  13. 4
      app/src/main/java/audio/funkwhale/ffa/adapters/PlaylistTracksAdapter.kt
  14. 13
      app/src/main/java/audio/funkwhale/ffa/adapters/RadiosAdapter.kt
  15. 179
      app/src/main/java/audio/funkwhale/ffa/adapters/SearchAdapter.kt
  16. 2
      app/src/main/java/audio/funkwhale/ffa/adapters/TracksAdapter.kt
  17. 26
      app/src/main/java/audio/funkwhale/ffa/fragments/AddToPlaylistDialog.kt
  18. 7
      app/src/main/java/audio/funkwhale/ffa/fragments/AlbumsFragment.kt
  19. 2
      app/src/main/java/audio/funkwhale/ffa/fragments/AlbumsGridFragment.kt
  20. 5
      app/src/main/java/audio/funkwhale/ffa/fragments/FFAFragment.kt
  21. 10
      app/src/main/java/audio/funkwhale/ffa/fragments/FavoritesFragment.kt
  22. 10
      app/src/main/java/audio/funkwhale/ffa/fragments/PlaylistTracksFragment.kt
  23. 2
      app/src/main/java/audio/funkwhale/ffa/fragments/PlaylistsFragment.kt
  24. 2
      app/src/main/java/audio/funkwhale/ffa/fragments/RadiosFragment.kt
  25. 19
      app/src/main/java/audio/funkwhale/ffa/fragments/TracksFragment.kt
  26. 2
      app/src/main/java/audio/funkwhale/ffa/koin/Modules.kt
  27. 2
      app/src/main/java/audio/funkwhale/ffa/model/AlbumsResponse.kt
  28. 2
      app/src/main/java/audio/funkwhale/ffa/model/Artist.kt
  29. 2
      app/src/main/java/audio/funkwhale/ffa/model/ArtistsResponse.kt
  30. 2
      app/src/main/java/audio/funkwhale/ffa/model/CacheItem.kt
  31. 2
      app/src/main/java/audio/funkwhale/ffa/model/CoverUrls.kt
  32. 2
      app/src/main/java/audio/funkwhale/ffa/model/Covers.kt
  33. 2
      app/src/main/java/audio/funkwhale/ffa/model/DownloadInfo.kt
  34. 2
      app/src/main/java/audio/funkwhale/ffa/model/FFAResponse.kt
  35. 2
      app/src/main/java/audio/funkwhale/ffa/model/Favorited.kt
  36. 2
      app/src/main/java/audio/funkwhale/ffa/model/FavoritedResponse.kt
  37. 2
      app/src/main/java/audio/funkwhale/ffa/model/Playlist.kt
  38. 2
      app/src/main/java/audio/funkwhale/ffa/model/PlaylistTrack.kt
  39. 2
      app/src/main/java/audio/funkwhale/ffa/model/PlaylistTracksResponse.kt
  40. 2
      app/src/main/java/audio/funkwhale/ffa/model/PlaylistsResponse.kt
  41. 2
      app/src/main/java/audio/funkwhale/ffa/model/Radio.kt
  42. 2
      app/src/main/java/audio/funkwhale/ffa/model/RadiosResponse.kt
  43. 2
      app/src/main/java/audio/funkwhale/ffa/model/SearchResult.kt
  44. 2
      app/src/main/java/audio/funkwhale/ffa/model/Track.kt
  45. 2
      app/src/main/java/audio/funkwhale/ffa/model/TracksResponse.kt
  46. 10
      app/src/main/java/audio/funkwhale/ffa/playback/CacheDataSourceFactoryProvider.kt
  47. 2
      app/src/main/java/audio/funkwhale/ffa/playback/MediaControlsManager.kt
  48. 10
      app/src/main/java/audio/funkwhale/ffa/playback/MediaSession.kt
  49. 8
      app/src/main/java/audio/funkwhale/ffa/playback/OAuth2Datasource.kt
  50. 10
      app/src/main/java/audio/funkwhale/ffa/playback/PinService.kt
  51. 42
      app/src/main/java/audio/funkwhale/ffa/playback/PlayerService.kt
  52. 20
      app/src/main/java/audio/funkwhale/ffa/playback/QueueManager.kt
  53. 11
      app/src/main/java/audio/funkwhale/ffa/playback/RadioPlayer.kt
  54. 15
      app/src/main/java/audio/funkwhale/ffa/repositories/FavoritesRepository.kt
  55. 9
      app/src/main/java/audio/funkwhale/ffa/repositories/HttpUpstream.kt
  56. 6
      app/src/main/java/audio/funkwhale/ffa/repositories/PlaylistsRepository.kt
  57. 10
      app/src/main/java/audio/funkwhale/ffa/repositories/Repository.kt
  58. 13
      app/src/main/java/audio/funkwhale/ffa/repositories/SearchRepository.kt
  59. 4
      app/src/main/java/audio/funkwhale/ffa/utils/Extensions.kt
  60. 2
      app/src/main/java/audio/funkwhale/ffa/utils/FuelResult.kt
  61. 23
      app/src/main/java/audio/funkwhale/ffa/utils/OAuth.kt
  62. 2
      app/src/test/java/audio/funkwhale/ffa/FFATest.kt
  63. 2
      app/src/test/java/audio/funkwhale/ffa/KoinTestApp.kt
  64. 5
      app/src/test/java/audio/funkwhale/ffa/activities/SplashActivityTest.kt

16
app/build.gradle.kts

@ -241,13 +241,15 @@ project.afterEvaluate { @@ -241,13 +241,15 @@ project.afterEvaluate {
sourceDirectories.setFrom(files(listOf(mainSrc)))
classDirectories.setFrom(files(listOf(debugTree)))
executionData.setFrom(fileTree(project.buildDir) {
setIncludes(
listOf(
"outputs/unit_test_code_coverage/debugUnitTest/*.exec",
"outputs/code_coverage/debugAndroidTest/connected/**/*.ec"
executionData.setFrom(
fileTree(project.buildDir) {
setIncludes(
listOf(
"outputs/unit_test_code_coverage/debugUnitTest/*.exec",
"outputs/code_coverage/debugAndroidTest/connected/**/*.ec"
)
)
)
})
}
)
}
}

9
app/src/main/java/audio/funkwhale/ffa/FFA.kt

@ -5,13 +5,18 @@ import android.content.Context @@ -5,13 +5,18 @@ import android.content.Context
import androidx.appcompat.app.AppCompatDelegate
import audio.funkwhale.ffa.koin.authModule
import audio.funkwhale.ffa.koin.exoplayerModule
import audio.funkwhale.ffa.utils.*
import audio.funkwhale.ffa.utils.AppContext
import audio.funkwhale.ffa.utils.Command
import audio.funkwhale.ffa.utils.Event
import audio.funkwhale.ffa.utils.FFACache
import audio.funkwhale.ffa.utils.Request
import com.preference.PowerPreference
import kotlinx.coroutines.channels.BroadcastChannel
import kotlinx.coroutines.channels.ConflatedBroadcastChannel
import org.koin.core.context.startKoin
import java.text.SimpleDateFormat
import java.util.*
import java.util.Date
import java.util.Locale
class FFA : Application() {

6
app/src/main/java/audio/funkwhale/ffa/activities/DownloadsActivity.kt

@ -73,9 +73,9 @@ class DownloadsActivity : AppCompatActivity() { @@ -73,9 +73,9 @@ class DownloadsActivity : AppCompatActivity() {
val download = cursor.download
download.getMetadata()?.let { info ->
adapter.downloads.add(info.apply {
this.download = download
})
adapter.downloads.add(
info.apply { this.download = download }
)
}
}

3
app/src/main/java/audio/funkwhale/ffa/activities/LicencesActivity.kt

@ -90,7 +90,8 @@ class LicencesActivity : AppCompatActivity() { @@ -90,7 +90,8 @@ class LicencesActivity : AppCompatActivity() {
holder.licence.text = item.licence
}
inner class ViewHolder(binding: RowLicenceBinding) : RecyclerView.ViewHolder(binding.root),
inner class ViewHolder(binding: RowLicenceBinding) :
RecyclerView.ViewHolder(binding.root),
View.OnClickListener {
val name = binding.name
val licence = binding.licence

5
app/src/main/java/audio/funkwhale/ffa/activities/LoginActivity.kt

@ -11,7 +11,10 @@ import androidx.lifecycle.lifecycleScope @@ -11,7 +11,10 @@ import androidx.lifecycle.lifecycleScope
import audio.funkwhale.ffa.R
import audio.funkwhale.ffa.databinding.ActivityLoginBinding
import audio.funkwhale.ffa.fragments.LoginDialog
import audio.funkwhale.ffa.utils.*
import audio.funkwhale.ffa.utils.AppContext
import audio.funkwhale.ffa.utils.FuelResult
import audio.funkwhale.ffa.utils.OAuth
import audio.funkwhale.ffa.utils.Userinfo
import com.github.kittinunf.fuel.Fuel
import com.github.kittinunf.fuel.coroutines.awaitObjectResponseResult
import com.github.kittinunf.fuel.gson.gsonDeserializerOf

69
app/src/main/java/audio/funkwhale/ffa/activities/MainActivity.kt

@ -9,7 +9,11 @@ import android.graphics.Bitmap @@ -9,7 +9,11 @@ import android.graphics.Bitmap
import android.os.Build
import android.os.Bundle
import android.util.DisplayMetrics
import android.view.*
import android.view.Gravity
import android.view.Menu
import android.view.MenuItem
import android.view.View
import android.view.ViewGroup
import android.view.animation.AccelerateDecelerateInterpolator
import android.widget.SeekBar
import androidx.appcompat.app.AppCompatActivity
@ -24,7 +28,13 @@ import androidx.lifecycle.lifecycleScope @@ -24,7 +28,13 @@ import androidx.lifecycle.lifecycleScope
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.fragments.AddToPlaylistDialog
import audio.funkwhale.ffa.fragments.AlbumsFragment
import audio.funkwhale.ffa.fragments.ArtistsFragment
import audio.funkwhale.ffa.fragments.BrowseFragment
import audio.funkwhale.ffa.fragments.LandscapeQueueFragment
import audio.funkwhale.ffa.fragments.QueueFragment
import audio.funkwhale.ffa.fragments.TrackInfoDetailsFragment
import audio.funkwhale.ffa.model.Track
import audio.funkwhale.ffa.playback.MediaControlsManager
import audio.funkwhale.ffa.playback.PinService
@ -32,7 +42,25 @@ import audio.funkwhale.ffa.playback.PlayerService @@ -32,7 +42,25 @@ import audio.funkwhale.ffa.playback.PlayerService
import audio.funkwhale.ffa.repositories.FavoritedRepository
import audio.funkwhale.ffa.repositories.FavoritesRepository
import audio.funkwhale.ffa.repositories.Repository
import audio.funkwhale.ffa.utils.*
import audio.funkwhale.ffa.utils.AppContext
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.FFACache
import audio.funkwhale.ffa.utils.OAuth
import audio.funkwhale.ffa.utils.ProgressBus
import audio.funkwhale.ffa.utils.Settings
import audio.funkwhale.ffa.utils.Userinfo
import audio.funkwhale.ffa.utils.authorize
import audio.funkwhale.ffa.utils.log
import audio.funkwhale.ffa.utils.logError
import audio.funkwhale.ffa.utils.maybeLoad
import audio.funkwhale.ffa.utils.maybeNormalizeUrl
import audio.funkwhale.ffa.utils.mustNormalizeUrl
import audio.funkwhale.ffa.utils.onApi
import audio.funkwhale.ffa.utils.toast
import audio.funkwhale.ffa.utils.untilNetwork
import audio.funkwhale.ffa.views.DisableableFrameLayout
import com.github.kittinunf.fuel.Fuel
import com.github.kittinunf.fuel.coroutines.awaitStringResponse
@ -132,17 +160,17 @@ class MainActivity : AppCompatActivity() { @@ -132,17 +160,17 @@ class MainActivity : AppCompatActivity() {
}
binding.nowPlayingContainer?.nowPlayingDetailsProgress?.setOnSeekBarChangeListener(object :
SeekBar.OnSeekBarChangeListener {
override fun onStopTrackingTouch(view: SeekBar?) {}
SeekBar.OnSeekBarChangeListener {
override fun onStopTrackingTouch(view: SeekBar?) {}
override fun onStartTrackingTouch(view: SeekBar?) {}
override fun onStartTrackingTouch(view: SeekBar?) {}
override fun onProgressChanged(view: SeekBar?, progress: Int, fromUser: Boolean) {
if (fromUser) {
CommandBus.send(Command.Seek(progress))
override fun onProgressChanged(view: SeekBar?, progress: Int, fromUser: Boolean) {
if (fromUser) {
CommandBus.send(Command.Seek(progress))
}
}
}
})
})
landscapeQueue?.let {
supportFragmentManager.beginTransaction()
@ -303,9 +331,11 @@ class MainActivity : AppCompatActivity() { @@ -303,9 +331,11 @@ class MainActivity : AppCompatActivity() {
when (message) {
is Event.LogOut -> {
FFA.get().deleteAllData(this@MainActivity)
startActivity(Intent(this@MainActivity, LoginActivity::class.java).apply {
flags = Intent.FLAG_ACTIVITY_NO_HISTORY
})
startActivity(
Intent(this@MainActivity, LoginActivity::class.java).apply {
flags = Intent.FLAG_ACTIVITY_NO_HISTORY
}
)
finish()
}
@ -385,12 +415,15 @@ class MainActivity : AppCompatActivity() { @@ -385,12 +415,15 @@ class MainActivity : AppCompatActivity() {
PlayerService::class.java
).apply {
putExtra(PlayerService.INITIAL_COMMAND_KEY, command.command.toString())
})
}
)
},
{
startService(Intent(this@MainActivity, PlayerService::class.java).apply {
putExtra(PlayerService.INITIAL_COMMAND_KEY, command.command.toString())
})
startService(
Intent(this@MainActivity, PlayerService::class.java).apply {
putExtra(PlayerService.INITIAL_COMMAND_KEY, command.command.toString())
}
)
}
)
}

93
app/src/main/java/audio/funkwhale/ffa/activities/SearchActivity.kt

@ -13,15 +13,24 @@ import audio.funkwhale.ffa.fragments.AlbumsFragment @@ -13,15 +13,24 @@ 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 audio.funkwhale.ffa.repositories.AlbumsSearchRepository
import audio.funkwhale.ffa.repositories.ArtistsSearchRepository
import audio.funkwhale.ffa.repositories.FavoritesRepository
import audio.funkwhale.ffa.repositories.Repository
import audio.funkwhale.ffa.repositories.TracksSearchRepository
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.getMetadata
import audio.funkwhale.ffa.utils.untilNetwork
import com.google.android.exoplayer2.offline.Download
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.flow.collect
import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext
import java.net.URLEncoder
import java.util.*
import java.util.Locale
class SearchActivity : AppCompatActivity() {
private lateinit var adapter: SearchAdapter
@ -82,58 +91,58 @@ class SearchActivity : AppCompatActivity() { @@ -82,58 +91,58 @@ class SearchActivity : AppCompatActivity() {
favoritesRepository = FavoritesRepository(this@SearchActivity)
binding.search.setOnQueryTextListener(object :
androidx.appcompat.widget.SearchView.OnQueryTextListener {
override fun onQueryTextSubmit(rawQuery: String?): Boolean {
binding.search.clearFocus()
androidx.appcompat.widget.SearchView.OnQueryTextListener {
override fun onQueryTextSubmit(rawQuery: String?): Boolean {
binding.search.clearFocus()
rawQuery?.let {
done = 0
rawQuery?.let {
done = 0
val query = URLEncoder.encode(it, "UTF-8")
val query = URLEncoder.encode(it, "UTF-8")
artistsRepository.query = query.lowercase(Locale.ROOT)
albumsRepository.query = query.lowercase(Locale.ROOT)
tracksRepository.query = query.lowercase(Locale.ROOT)
artistsRepository.query = query.lowercase(Locale.ROOT)
albumsRepository.query = query.lowercase(Locale.ROOT)
tracksRepository.query = query.lowercase(Locale.ROOT)
binding.searchSpinner.visibility = View.VISIBLE
binding.searchEmpty.visibility = View.GONE
binding.searchNoResults.visibility = View.GONE
binding.searchSpinner.visibility = View.VISIBLE
binding.searchEmpty.visibility = View.GONE
binding.searchNoResults.visibility = View.GONE
adapter.artists.clear()
adapter.albums.clear()
adapter.tracks.clear()
adapter.notifyDataSetChanged()
adapter.artists.clear()
adapter.albums.clear()
adapter.tracks.clear()
adapter.notifyDataSetChanged()
artistsRepository.fetch(Repository.Origin.Network.origin)
.untilNetwork(lifecycleScope) { artists, _, _, _ ->
done++
artistsRepository.fetch(Repository.Origin.Network.origin)
.untilNetwork(lifecycleScope) { artists, _, _, _ ->
done++
adapter.artists.addAll(artists)
refresh()
}
adapter.artists.addAll(artists)
refresh()
}
albumsRepository.fetch(Repository.Origin.Network.origin)
.untilNetwork(lifecycleScope) { albums, _, _, _ ->
done++
albumsRepository.fetch(Repository.Origin.Network.origin)
.untilNetwork(lifecycleScope) { albums, _, _, _ ->
done++
adapter.albums.addAll(albums)
refresh()
}
adapter.albums.addAll(albums)
refresh()
}
tracksRepository.fetch(Repository.Origin.Network.origin)
.untilNetwork(lifecycleScope) { tracks, _, _, _ ->
done++
tracksRepository.fetch(Repository.Origin.Network.origin)
.untilNetwork(lifecycleScope) { tracks, _, _, _ ->
done++
adapter.tracks.addAll(tracks)
refresh()
}
}
adapter.tracks.addAll(tracks)
refresh()
}
}
return true
}
return true
}
override fun onQueryTextChange(newText: String?) = true
})
override fun onQueryTextChange(newText: String?) = true
})
}
private fun refresh() {

6
app/src/main/java/audio/funkwhale/ffa/activities/SettingsActivity.kt

@ -1,6 +1,10 @@ @@ -1,6 +1,10 @@
package audio.funkwhale.ffa.activities
import android.content.*
import android.content.ClipData
import android.content.ClipboardManager
import android.content.Context
import android.content.Intent
import android.content.SharedPreferences
import android.os.Bundle
import android.widget.Toast
import androidx.appcompat.app.AlertDialog

4
app/src/main/java/audio/funkwhale/ffa/activities/SplashActivity.kt

@ -6,7 +6,9 @@ import android.os.Bundle @@ -6,7 +6,9 @@ import android.os.Bundle
import android.util.Log
import androidx.appcompat.app.AppCompatActivity
import audio.funkwhale.ffa.FFA
import audio.funkwhale.ffa.utils.*
import audio.funkwhale.ffa.utils.AppContext
import audio.funkwhale.ffa.utils.OAuth
import audio.funkwhale.ffa.utils.Settings
import org.koin.java.KoinJavaComponent.inject
class SplashActivity : AppCompatActivity() {

11
app/src/main/java/audio/funkwhale/ffa/adapters/BrowseTabsAdapter.kt

@ -4,9 +4,14 @@ import androidx.fragment.app.Fragment @@ -4,9 +4,14 @@ import androidx.fragment.app.Fragment
import androidx.fragment.app.FragmentManager
import androidx.fragment.app.FragmentPagerAdapter
import audio.funkwhale.ffa.R
import audio.funkwhale.ffa.fragments.*
class BrowseTabsAdapter(val context: Fragment, manager: FragmentManager) : FragmentPagerAdapter(manager, BEHAVIOR_RESUME_ONLY_CURRENT_FRAGMENT) {
import audio.funkwhale.ffa.fragments.AlbumsGridFragment
import audio.funkwhale.ffa.fragments.ArtistsFragment
import audio.funkwhale.ffa.fragments.FavoritesFragment
import audio.funkwhale.ffa.fragments.PlaylistsFragment
import audio.funkwhale.ffa.fragments.RadiosFragment
class BrowseTabsAdapter(val context: Fragment, manager: FragmentManager) :
FragmentPagerAdapter(manager, BEHAVIOR_RESUME_ONLY_CURRENT_FRAGMENT) {
var tabs = mutableListOf<Fragment>()
override fun getCount() = 5

2
app/src/main/java/audio/funkwhale/ffa/adapters/DownloadsAdapter.kt

@ -8,9 +8,9 @@ import android.view.ViewGroup @@ -8,9 +8,9 @@ import android.view.ViewGroup
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.model.DownloadInfo
import audio.funkwhale.ffa.model.Track
import audio.funkwhale.ffa.playback.PinService
import com.google.android.exoplayer2.offline.Download
import com.google.android.exoplayer2.offline.DownloadService

2
app/src/main/java/audio/funkwhale/ffa/adapters/FavoritesAdapter.kt

@ -13,9 +13,9 @@ import androidx.recyclerview.widget.RecyclerView @@ -13,9 +13,9 @@ import androidx.recyclerview.widget.RecyclerView
import audio.funkwhale.ffa.R
import audio.funkwhale.ffa.databinding.RowTrackBinding
import audio.funkwhale.ffa.fragments.FFAAdapter
import audio.funkwhale.ffa.model.Track
import audio.funkwhale.ffa.utils.Command
import audio.funkwhale.ffa.utils.CommandBus
import audio.funkwhale.ffa.model.Track
import audio.funkwhale.ffa.utils.maybeLoad
import audio.funkwhale.ffa.utils.maybeNormalizeUrl
import audio.funkwhale.ffa.utils.toast

4
app/src/main/java/audio/funkwhale/ffa/adapters/PlaylistTracksAdapter.kt

@ -16,10 +16,10 @@ import androidx.recyclerview.widget.RecyclerView @@ -16,10 +16,10 @@ import androidx.recyclerview.widget.RecyclerView
import audio.funkwhale.ffa.R
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.model.PlaylistTrack
import audio.funkwhale.ffa.model.Track
import audio.funkwhale.ffa.utils.Command
import audio.funkwhale.ffa.utils.CommandBus
import audio.funkwhale.ffa.utils.maybeLoad
import audio.funkwhale.ffa.utils.maybeNormalizeUrl
import audio.funkwhale.ffa.utils.toast

13
app/src/main/java/audio/funkwhale/ffa/adapters/RadiosAdapter.kt

@ -9,10 +9,10 @@ import audio.funkwhale.ffa.R @@ -9,10 +9,10 @@ import audio.funkwhale.ffa.R
import audio.funkwhale.ffa.databinding.RowRadioBinding
import audio.funkwhale.ffa.databinding.RowRadioHeaderBinding
import audio.funkwhale.ffa.fragments.FFAAdapter
import audio.funkwhale.ffa.model.Radio
import audio.funkwhale.ffa.utils.AppContext
import audio.funkwhale.ffa.utils.Event
import audio.funkwhale.ffa.utils.EventBus
import audio.funkwhale.ffa.model.Radio
import audio.funkwhale.ffa.views.LoadingImageView
import com.preference.PowerPreference
import kotlinx.coroutines.CoroutineScope
@ -42,8 +42,10 @@ class RadiosAdapter( @@ -42,8 +42,10 @@ class RadiosAdapter(
private val instanceRadios: List<Radio> by lazy {
context?.let {
return@lazy when (val username =
PowerPreference.getFileByName(AppContext.PREFS_CREDENTIALS).getString("actor_username")) {
return@lazy when (
val username =
PowerPreference.getFileByName(AppContext.PREFS_CREDENTIALS).getString("actor_username")
) {
"" -> listOf(
Radio(
0,
@ -133,8 +135,9 @@ class RadiosAdapter( @@ -133,8 +135,9 @@ class RadiosAdapter(
context?.let {
when (position) {
0 -> holder.label.text = context.getString(R.string.radio_instance_radios)
instanceRadios.size + 1 -> holder.label.text =
context.getString(R.string.radio_user_radios)
instanceRadios.size + 1 ->
holder.label.text =
context.getString(R.string.radio_user_radios)
}
}
}

179
app/src/main/java/audio/funkwhale/ffa/adapters/SearchAdapter.kt

@ -17,9 +17,9 @@ import audio.funkwhale.ffa.databinding.RowSearchHeaderBinding @@ -17,9 +17,9 @@ import audio.funkwhale.ffa.databinding.RowSearchHeaderBinding
import audio.funkwhale.ffa.databinding.RowTrackBinding
import audio.funkwhale.ffa.model.Album
import audio.funkwhale.ffa.model.Artist
import audio.funkwhale.ffa.model.Track
import audio.funkwhale.ffa.utils.Command
import audio.funkwhale.ffa.utils.CommandBus
import audio.funkwhale.ffa.model.Track
import audio.funkwhale.ffa.utils.maybeLoad
import audio.funkwhale.ffa.utils.maybeNormalizeUrl
import audio.funkwhale.ffa.utils.onApi
@ -73,20 +73,19 @@ class SearchAdapter( @@ -73,20 +73,19 @@ class SearchAdapter(
ResultType.Artist.ordinal -> artists[position].id.toLong()
ResultType.Artist.ordinal -> albums[position - artists.size - 2].id.toLong()
ResultType.Track.ordinal -> tracks[position - artists.size - albums.size - sectionCount].id.toLong()
ResultType.Track.ordinal ->
tracks[position - artists.size - albums.size - sectionCount].id.toLong()
else -> 0
}
}
override fun getItemViewType(position: Int): Int {
if (position == 0) return ResultType.Header.ordinal // Artists header
if (position == (artists.size + 1)) return ResultType.Header.ordinal // Albums header
if (position == (artists.size + albums.size + 2)) return ResultType.Header.ordinal // Tracks header
if (position <= artists.size) return ResultType.Artist.ordinal
if (position <= artists.size + albums.size + 2) return ResultType.Album.ordinal
return ResultType.Track.ordinal
override fun getItemViewType(position: Int): Int = when {
position == 0 ||
position == (artists.size + 1) ||
position == (artists.size + albums.size + 2) -> ResultType.Header.ordinal
position <= artists.size -> ResultType.Artist.ordinal
position <= artists.size + albums.size + 2 -> ResultType.Album.ordinal
else -> ResultType.Track.ordinal
}
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
@ -205,102 +204,112 @@ class SearchAdapter( @@ -205,102 +204,112 @@ class SearchAdapter(
Typeface.create(searchHeaderViewHolder?.title?.typeface, Typeface.NORMAL)
rowTrackViewHolder?.artist?.typeface =
Typeface.create(rowTrackViewHolder?.artist?.typeface, Typeface.NORMAL)
})
}
)
searchHeaderViewHolder?.title?.setCompoundDrawablesWithIntrinsicBounds(0, 0, 0, 0)
when (resultType) {
ResultType.Artist.ordinal -> {
rowTrackViewHolder?.title?.setCompoundDrawablesWithIntrinsicBounds(
0, 0, 0, 0
)
}
ResultType.Album.ordinal -> {
rowTrackViewHolder?.title?.setCompoundDrawablesWithIntrinsicBounds(
0, 0, 0, 0
)
}
ResultType.Track.ordinal -> {
(item as? Track)?.let { track ->
context?.let { context ->
if (track == currentTrack || track.current) {
searchHeaderViewHolder?.title?.setTypeface(
searchHeaderViewHolder.title.typeface,
Typeface.BOLD
)
rowTrackViewHolder?.artist?.setTypeface(
rowTrackViewHolder.artist.typeface,
Typeface.BOLD
)
}
ResultType.Artist.ordinal -> {
rowTrackViewHolder?.title?.setCompoundDrawablesWithIntrinsicBounds(
0, 0, 0, 0
)
}
ResultType.Album.ordinal -> {
rowTrackViewHolder?.title?.setCompoundDrawablesWithIntrinsicBounds(
0, 0, 0, 0
)
}
ResultType.Track.ordinal -> {
(item as? Track)?.let { track ->
context?.let { context ->
if (track == currentTrack || track.current) {
searchHeaderViewHolder?.title?.setTypeface(
searchHeaderViewHolder.title.typeface,
Typeface.BOLD
)
rowTrackViewHolder?.artist?.setTypeface(
rowTrackViewHolder.artist.typeface,
Typeface.BOLD
)
}
when (track.favorite) {
true -> rowTrackViewHolder?.favorite?.setColorFilter(context.getColor(R.color.colorFavorite))
false -> rowTrackViewHolder?.favorite?.setColorFilter(context.getColor(R.color.colorSelected))
}
when (track.favorite) {
true -> rowTrackViewHolder?.favorite?.setColorFilter(
context.getColor(R.color.colorFavorite)
)
false -> rowTrackViewHolder?.favorite?.setColorFilter(
context.getColor(R.color.colorSelected)
)
}
rowTrackViewHolder?.favorite?.setOnClickListener {
favoriteListener?.let {
favoriteListener.onToggleFavorite(track.id, !track.favorite)
rowTrackViewHolder?.favorite?.setOnClickListener {
favoriteListener?.let {
favoriteListener.onToggleFavorite(track.id, !track.favorite)
tracks[position - artists.size - albums.size - sectionCount].favorite =
!track.favorite
tracks[position - artists.size - albums.size - sectionCount].favorite =
!track.favorite
notifyItemChanged(position)
}
notifyItemChanged(position)
}
}
when (track.cached || track.downloaded) {
true -> rowTrackViewHolder?.title?.setCompoundDrawablesWithIntrinsicBounds(
R.drawable.downloaded, 0, 0, 0
)
false -> rowTrackViewHolder?.title?.setCompoundDrawablesWithIntrinsicBounds(
0, 0, 0, 0
)
}
when (track.cached || track.downloaded) {
true -> rowTrackViewHolder?.title?.setCompoundDrawablesWithIntrinsicBounds(
R.drawable.downloaded, 0, 0, 0
)
false -> rowTrackViewHolder?.title?.setCompoundDrawablesWithIntrinsicBounds(
0, 0, 0, 0
)
}
if (track.cached && !track.downloaded) {
rowTrackViewHolder?.title?.compoundDrawables?.forEach {
it?.colorFilter =
PorterDuffColorFilter(context.getColor(R.color.cached), PorterDuff.Mode.SRC_IN)
}
if (track.cached && !track.downloaded) {
rowTrackViewHolder?.title?.compoundDrawables?.forEach {
it?.colorFilter =
PorterDuffColorFilter(context.getColor(R.color.cached), PorterDuff.Mode.SRC_IN)
}
}
if (track.downloaded) {
rowTrackViewHolder?.title?.compoundDrawables?.forEach {
it?.colorFilter =
PorterDuffColorFilter(context.getColor(R.color.downloaded), PorterDuff.Mode.SRC_IN)
}
if (track.downloaded) {
rowTrackViewHolder?.title?.compoundDrawables?.forEach {
it?.colorFilter =
PorterDuffColorFilter(
context.getColor(R.color.downloaded),
PorterDuff.Mode.SRC_IN
)
}
}
rowTrackViewHolder?.actions?.setOnClickListener {
PopupMenu(
context,
rowTrackViewHolder.actions,
Gravity.START,
R.attr.actionOverflowMenuStyle,
0
).apply {
inflate(R.menu.row_track)
setOnMenuItemClickListener {
when (it.itemId) {
R.id.track_add_to_queue -> CommandBus.send(Command.AddToQueue(listOf(track)))
R.id.track_play_next -> CommandBus.send(Command.PlayNext(track))
R.id.track_pin -> CommandBus.send(Command.PinTrack(track))
R.id.track_add_to_playlist -> CommandBus.send(Command.AddToPlaylist(listOf(track)))
R.id.queue_remove -> CommandBus.send(Command.RemoveFromQueue(track))
}
true
rowTrackViewHolder?.actions?.setOnClickListener {
PopupMenu(
context,
rowTrackViewHolder.actions,
Gravity.START,
R.attr.actionOverflowMenuStyle,
0
).apply {
inflate(R.menu.row_track)
setOnMenuItemClickListener {
when (it.itemId) {
R.id.track_add_to_queue -> CommandBus.send(Command.AddToQueue(listOf(track)))
R.id.track_play_next -> CommandBus.send(Command.PlayNext(track))
R.id.track_pin -> CommandBus.send(Command.PinTrack(track))
R.id.track_add_to_playlist -> CommandBus.send(
Command.AddToPlaylist(listOf(track))
)
R.id.queue_remove -> CommandBus.send(Command.RemoveFromQueue(track))
}
show()
true
}
show()
}
}
}
}
}
}
}

2
app/src/main/java/audio/funkwhale/ffa/adapters/TracksAdapter.kt

@ -18,9 +18,9 @@ import androidx.recyclerview.widget.RecyclerView @@ -18,9 +18,9 @@ import androidx.recyclerview.widget.RecyclerView
import audio.funkwhale.ffa.R
import audio.funkwhale.ffa.databinding.RowTrackBinding
import audio.funkwhale.ffa.fragments.FFAAdapter
import audio.funkwhale.ffa.model.Track
import audio.funkwhale.ffa.utils.Command
import audio.funkwhale.ffa.utils.CommandBus
import audio.funkwhale.ffa.model.Track
import audio.funkwhale.ffa.utils.maybeLoad
import audio.funkwhale.ffa.utils.maybeNormalizeUrl
import audio.funkwhale.ffa.utils.toast

26
app/src/main/java/audio/funkwhale/ffa/fragments/AddToPlaylistDialog.kt

@ -14,7 +14,8 @@ import audio.funkwhale.ffa.databinding.DialogAddToPlaylistBinding @@ -14,7 +14,8 @@ 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 audio.funkwhale.ffa.utils.FFACache
import audio.funkwhale.ffa.utils.untilNetwork
import com.google.gson.Gson
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers.IO
@ -80,19 +81,22 @@ object AddToPlaylistDialog { @@ -80,19 +81,22 @@ object AddToPlaylistDialog {
}
val adapter =
PlaylistsAdapter(layoutInflater, activity, object : PlaylistsAdapter.OnPlaylistClickListener {
override fun onClick(holder: View?, playlist: Playlist) {
repository.add(playlist.id, tracks)
PlaylistsAdapter(
layoutInflater, activity,
object : PlaylistsAdapter.OnPlaylistClickListener {
override fun onClick(holder: View?, playlist: Playlist) {
repository.add(playlist.id, tracks)
Toast.makeText(
activity,
activity.getString(R.string.playlist_added_to, playlist.name),
Toast.LENGTH_SHORT
).show()
Toast.makeText(
activity,
activity.getString(R.string.playlist_added_to, playlist.name),
Toast.LENGTH_SHORT
).show()
dialog.dismiss()
dialog.dismiss()
}
}
})
)
binding.playlists.layoutManager = LinearLayoutManager(activity)
binding.playlists.adapter = adapter

7
app/src/main/java/audio/funkwhale/ffa/fragments/AlbumsFragment.kt

@ -25,7 +25,12 @@ import audio.funkwhale.ffa.model.Artist @@ -25,7 +25,12 @@ import audio.funkwhale.ffa.model.Artist
import audio.funkwhale.ffa.repositories.AlbumsRepository
import audio.funkwhale.ffa.repositories.ArtistTracksRepository
import audio.funkwhale.ffa.repositories.Repository
import audio.funkwhale.ffa.utils.*
import audio.funkwhale.ffa.utils.AppContext
import audio.funkwhale.ffa.utils.Command
import audio.funkwhale.ffa.utils.CommandBus
import audio.funkwhale.ffa.utils.maybeLoad
import audio.funkwhale.ffa.utils.maybeNormalizeUrl
import audio.funkwhale.ffa.utils.onViewPager
import com.squareup.picasso.Picasso
import jp.wasabeef.picasso.transformations.RoundedCornersTransformation
import kotlinx.coroutines.Dispatchers.IO

2
app/src/main/java/audio/funkwhale/ffa/fragments/AlbumsGridFragment.kt

@ -13,8 +13,8 @@ import audio.funkwhale.ffa.R @@ -13,8 +13,8 @@ import audio.funkwhale.ffa.R
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.model.Album
import audio.funkwhale.ffa.repositories.AlbumsRepository
import audio.funkwhale.ffa.utils.AppContext
class AlbumsGridFragment : FFAFragment<Album, AlbumsGridAdapter>() {

5
app/src/main/java/audio/funkwhale/ffa/fragments/FFAFragment.kt

@ -10,7 +10,10 @@ import androidx.recyclerview.widget.SimpleItemAnimator @@ -10,7 +10,10 @@ import androidx.recyclerview.widget.SimpleItemAnimator
import androidx.swiperefreshlayout.widget.SwipeRefreshLayout
import audio.funkwhale.ffa.repositories.HttpUpstream
import audio.funkwhale.ffa.repositories.Repository
import audio.funkwhale.ffa.utils.*
import audio.funkwhale.ffa.utils.Event
import audio.funkwhale.ffa.utils.EventBus
import audio.funkwhale.ffa.utils.FFACache
import audio.funkwhale.ffa.utils.untilNetwork
import com.google.gson.Gson
import kotlinx.coroutines.Dispatchers.IO
import kotlinx.coroutines.Dispatchers.Main

10
app/src/main/java/audio/funkwhale/ffa/fragments/FavoritesFragment.kt

@ -11,7 +11,15 @@ import audio.funkwhale.ffa.databinding.FragmentFavoritesBinding @@ -11,7 +11,15 @@ 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.*
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.Request
import audio.funkwhale.ffa.utils.RequestBus
import audio.funkwhale.ffa.utils.Response
import audio.funkwhale.ffa.utils.getMetadata
import audio.funkwhale.ffa.utils.wait
import com.google.android.exoplayer2.offline.Download
import com.google.android.exoplayer2.offline.DownloadManager
import kotlinx.coroutines.Dispatchers.IO

10
app/src/main/java/audio/funkwhale/ffa/fragments/PlaylistTracksFragment.kt

@ -18,7 +18,15 @@ import audio.funkwhale.ffa.model.Track @@ -18,7 +18,15 @@ import audio.funkwhale.ffa.model.Track
import audio.funkwhale.ffa.repositories.FavoritesRepository
import audio.funkwhale.ffa.repositories.ManagementPlaylistsRepository
import audio.funkwhale.ffa.repositories.PlaylistTracksRepository
import audio.funkwhale.ffa.utils.*
import audio.funkwhale.ffa.utils.Command
import audio.funkwhale.ffa.utils.CommandBus
import audio.funkwhale.ffa.utils.Request
import audio.funkwhale.ffa.utils.RequestBus
import audio.funkwhale.ffa.utils.Response
import audio.funkwhale.ffa.utils.maybeLoad
import audio.funkwhale.ffa.utils.maybeNormalizeUrl
import audio.funkwhale.ffa.utils.toast
import audio.funkwhale.ffa.utils.wait
import com.squareup.picasso.Picasso
import jp.wasabeef.picasso.transformations.RoundedCornersTransformation
import kotlinx.coroutines.Dispatchers.Main

2
app/src/main/java/audio/funkwhale/ffa/fragments/PlaylistsFragment.kt

@ -12,9 +12,9 @@ import audio.funkwhale.ffa.R @@ -12,9 +12,9 @@ import audio.funkwhale.ffa.R
import audio.funkwhale.ffa.activities.MainActivity
import audio.funkwhale.ffa.adapters.PlaylistsAdapter
import audio.funkwhale.ffa.databinding.FragmentPlaylistsBinding
import audio.funkwhale.ffa.model.Playlist
import audio.funkwhale.ffa.repositories.PlaylistsRepository
import audio.funkwhale.ffa.utils.AppContext
import audio.funkwhale.ffa.model.Playlist
class PlaylistsFragment : FFAFragment<Playlist, PlaylistsAdapter>() {

2
app/src/main/java/audio/funkwhale/ffa/fragments/RadiosFragment.kt

@ -9,12 +9,12 @@ import androidx.lifecycle.lifecycleScope @@ -9,12 +9,12 @@ import androidx.lifecycle.lifecycleScope
import androidx.recyclerview.widget.RecyclerView
import audio.funkwhale.ffa.adapters.RadiosAdapter
import audio.funkwhale.ffa.databinding.FragmentRadiosBinding
import audio.funkwhale.ffa.model.Radio
import audio.funkwhale.ffa.repositories.RadiosRepository
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.model.Radio
import kotlinx.coroutines.Dispatchers.Main
import kotlinx.coroutines.flow.collect
import kotlinx.coroutines.launch

19
app/src/main/java/audio/funkwhale/ffa/fragments/TracksFragment.kt

@ -19,7 +19,18 @@ import audio.funkwhale.ffa.model.Track @@ -19,7 +19,18 @@ import audio.funkwhale.ffa.model.Track
import audio.funkwhale.ffa.repositories.FavoritedRepository
import audio.funkwhale.ffa.repositories.FavoritesRepository
import audio.funkwhale.ffa.repositories.TracksRepository
import audio.funkwhale.ffa.utils.*
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.Request
import audio.funkwhale.ffa.utils.RequestBus
import audio.funkwhale.ffa.utils.Response
import audio.funkwhale.ffa.utils.getMetadata
import audio.funkwhale.ffa.utils.maybeLoad
import audio.funkwhale.ffa.utils.maybeNormalizeUrl
import audio.funkwhale.ffa.utils.toast
import audio.funkwhale.ffa.utils.wait
import com.google.android.exoplayer2.offline.Download
import com.google.android.exoplayer2.offline.DownloadManager
import com.preference.PowerPreference
@ -199,8 +210,10 @@ class TracksFragment : FFAFragment<Track, TracksAdapter>() { @@ -199,8 +210,10 @@ class TracksFragment : FFAFragment<Track, TracksAdapter>() {
setOnMenuItemClickListener {
when (it.itemId) {
R.id.play_secondary -> when (PowerPreference.getDefaultFile()
.getString("play_order")) {
R.id.play_secondary -> when (
PowerPreference.getDefaultFile()
.getString("play_order")
) {
"in_order" -> CommandBus.send(Command.ReplaceQueue(adapter.data.shuffled()))
else -> CommandBus.send(Command.ReplaceQueue(adapter.data))
}

2
app/src/main/java/audio/funkwhale/ffa/koin/Modules.kt

@ -64,4 +64,4 @@ fun exoplayerModule(context: Context) = module { @@ -64,4 +64,4 @@ fun exoplayerModule(context: Context) = module {
fun authModule() = module {
single { OAuth(get()) }
single { AuthorizationServiceFactory() }
}
}

2
app/src/main/java/audio/funkwhale/ffa/model/AlbumsResponse.kt

@ -6,4 +6,4 @@ data class AlbumsResponse( @@ -6,4 +6,4 @@ data class AlbumsResponse(
val results: AlbumList
) : FFAResponse<Album>() {
override fun getData() = results
}
}

2
app/src/main/java/audio/funkwhale/ffa/model/Artist.kt

@ -13,4 +13,4 @@ data class Artist( @@ -13,4 +13,4 @@ data class Artist(
override fun cover(): String? = albums?.getOrNull(0)?.cover?.urls?.original
override fun title() = name
override fun subtitle() = "Artist"
}
}

2
app/src/main/java/audio/funkwhale/ffa/model/ArtistsResponse.kt

@ -6,4 +6,4 @@ data class ArtistsResponse( @@ -6,4 +6,4 @@ data class ArtistsResponse(
val results: List<Artist>
) : FFAResponse<Artist>() {
override fun getData() = results
}
}

2
app/src/main/java/audio/funkwhale/ffa/model/CacheItem.kt

@ -9,4 +9,4 @@ class PlaylistsCache(data: List<Playlist>) : CacheItem<Playlist>(data) @@ -9,4 +9,4 @@ 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)
class QueueCache(data: List<Track>) : CacheItem<Track>(data)

2
app/src/main/java/audio/funkwhale/ffa/model/CoverUrls.kt

@ -1,3 +1,3 @@ @@ -1,3 +1,3 @@
package audio.funkwhale.ffa.model
data class CoverUrls(val original: String)
data class CoverUrls(val original: String)

2
app/src/main/java/audio/funkwhale/ffa/model/Covers.kt

@ -1,3 +1,3 @@ @@ -1,3 +1,3 @@
package audio.funkwhale.ffa.model
data class Covers(val urls: CoverUrls)
data class Covers(val urls: CoverUrls)

2
app/src/main/java/audio/funkwhale/ffa/model/DownloadInfo.kt

@ -8,4 +8,4 @@ data class DownloadInfo( @@ -8,4 +8,4 @@ data class DownloadInfo(
val title: String,
val artist: String,
var download: Download?
)
)

2
app/src/main/java/audio/funkwhale/ffa/model/FFAResponse.kt

@ -5,4 +5,4 @@ abstract class FFAResponse<D : Any> { @@ -5,4 +5,4 @@ abstract class FFAResponse<D : Any> {
abstract val next: String?
abstract fun getData(): List<D>
}
}

2
app/src/main/java/audio/funkwhale/ffa/model/Favorited.kt

@ -1,3 +1,3 @@ @@ -1,3 +1,3 @@
package audio.funkwhale.ffa.model
data class Favorited(val track: Int)
data class Favorited(val track: Int)

2
app/src/main/java/audio/funkwhale/ffa/model/FavoritedResponse.kt

@ -6,4 +6,4 @@ data class FavoritedResponse( @@ -6,4 +6,4 @@ data class FavoritedResponse(
val results: List<Favorited>
) : FFAResponse<Int>() {
override fun getData() = results.map { it.track }
}
}

2
app/src/main/java/audio/funkwhale/ffa/model/Playlist.kt

@ -6,4 +6,4 @@ data class Playlist( @@ -6,4 +6,4 @@ data class Playlist(
val album_covers: List<String>,
val tracks_count: Int,
val duration: Int
)
)

2
app/src/main/java/audio/funkwhale/ffa/model/PlaylistTrack.kt

@ -1,3 +1,3 @@ @@ -1,3 +1,3 @@
package audio.funkwhale.ffa.model
data class PlaylistTrack(val track: Track)
data class PlaylistTrack(val track: Track)

2
app/src/main/java/audio/funkwhale/ffa/model/PlaylistTracksResponse.kt

@ -6,4 +6,4 @@ data class PlaylistTracksResponse( @@ -6,4 +6,4 @@ data class PlaylistTracksResponse(
val results: List<PlaylistTrack>
) : FFAResponse<PlaylistTrack>() {
override fun getData() = results
}
}

2
app/src/main/java/audio/funkwhale/ffa/model/PlaylistsResponse.kt

@ -6,4 +6,4 @@ data class PlaylistsResponse( @@ -6,4 +6,4 @@ data class PlaylistsResponse(
val results: List<Playlist>
) : FFAResponse<Playlist>() {
override fun getData() = results
}
}

2
app/src/main/java/audio/funkwhale/ffa/model/Radio.kt

@ -6,4 +6,4 @@ data class Radio( @@ -6,4 +6,4 @@ data class Radio(
val name: String,
val description: String,
var related_object_id: String? = null
)
)

2
app/src/main/java/audio/funkwhale/ffa/model/RadiosResponse.kt

@ -6,4 +6,4 @@ data class RadiosResponse( @@ -6,4 +6,4 @@ data class RadiosResponse(
val results: List<Radio>
) : FFAResponse<Radio>() {
override fun getData() = results
}
}

2
app/src/main/java/audio/funkwhale/ffa/model/SearchResult.kt

@ -4,4 +4,4 @@ interface SearchResult { @@ -4,4 +4,4 @@ interface SearchResult {
fun cover(): String?
fun title(): String
fun subtitle(): String
}
}

2
app/src/main/java/audio/funkwhale/ffa/model/Track.kt

@ -61,4 +61,4 @@ data class Track( @@ -61,4 +61,4 @@ data class Track(
override fun subtitle() = artist.name
val formatted: String get() = "$id $artist ($album): $title"
}
}

2
app/src/main/java/audio/funkwhale/ffa/model/TracksResponse.kt

@ -6,4 +6,4 @@ data class TracksResponse( @@ -6,4 +6,4 @@ data class TracksResponse(
val results: List<Track>
) : FFAResponse<Track>() {
override fun getData() = results
}
}

10
app/src/main/java/audio/funkwhale/ffa/playback/CacheDataSourceFactoryProvider.kt

@ -5,7 +5,7 @@ import audio.funkwhale.ffa.R @@ -5,7 +5,7 @@ import audio.funkwhale.ffa.R
import audio.funkwhale.ffa.utils.OAuth
import audio.funkwhale.ffa.utils.Settings
import com.google.android.exoplayer2.upstream.DataSource
import com.google.android.exoplayer2.upstream.DefaultHttpDataSourceFactory
import com.google.android.exoplayer2.upstream.DefaultHttpDataSource
import com.google.android.exoplayer2.upstream.FileDataSource
import com.google.android.exoplayer2.upstream.cache.Cache
import com.google.android.exoplayer2.upstream.cache.CacheDataSource
@ -33,13 +33,13 @@ class CacheDataSourceFactoryProvider( @@ -33,13 +33,13 @@ class CacheDataSourceFactoryProvider(
}
private fun createDatasourceFactory(context: Context, oAuth: OAuth): DataSource.Factory {
val http = DefaultHttpDataSourceFactory(
Util.getUserAgent(context, context.getString(R.string.app_name))
)
val http = DefaultHttpDataSource.Factory().apply {
setUserAgent(Util.getUserAgent(context, context.getString(R.string.app_name)))
}
return if (!Settings.isAnonymous()) {
OAuth2DatasourceFactory(context, http, oAuth)
} else {
http
}
}
}
}

2
app/src/main/java/audio/funkwhale/ffa/playback/MediaControlsManager.kt

@ -12,8 +12,8 @@ import androidx.media.app.NotificationCompat.MediaStyle @@ -12,8 +12,8 @@ import androidx.media.app.NotificationCompat.MediaStyle
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.model.Track
import audio.funkwhale.ffa.utils.AppContext
import audio.funkwhale.ffa.utils.maybeNormalizeUrl
import com.squareup.picasso.Picasso
import kotlinx.coroutines.CoroutineScope

10
app/src/main/java/audio/funkwhale/ffa/playback/MediaSession.kt

@ -44,11 +44,13 @@ class MediaSession(private val context: Context) { @@ -44,11 +44,13 @@ class MediaSession(private val context: Context) {
it.setMediaButtonEventHandler { _, _, intent ->
if (!active) {
context.startService(Intent(context, PlayerService::class.java).apply {
action = intent.action
context.startService(
Intent(context, PlayerService::class.java).apply {
action = intent.action
intent.extras?.let { extras -> putExtras(extras) }
})
intent.extras?.let { extras -> putExtras(extras) }
}
)
return@setMediaButtonEventHandler true
}

8
app/src/main/java/audio/funkwhale/ffa/playback/OAuth2Datasource.kt

@ -3,7 +3,11 @@ package audio.funkwhale.ffa.playback @@ -3,7 +3,11 @@ package audio.funkwhale.ffa.playback
import android.content.Context
import android.net.Uri
import audio.funkwhale.ffa.utils.OAuth
import com.google.android.exoplayer2.upstream.*
import com.google.android.exoplayer2.upstream.DataSource
import com.google.android.exoplayer2.upstream.DataSpec
import com.google.android.exoplayer2.upstream.DefaultHttpDataSource
import com.google.android.exoplayer2.upstream.HttpDataSource
import com.google.android.exoplayer2.upstream.TransferListener
class OAuthDatasource(
private val context: Context,
@ -38,7 +42,7 @@ class OAuthDatasource( @@ -38,7 +42,7 @@ class OAuthDatasource(
class OAuth2DatasourceFactory(
private val context: Context,
private val http: DefaultHttpDataSourceFactory,
private val http: DefaultHttpDataSource.Factory,
private val oauth: OAuth
) : DataSource.Factory {

10
app/src/main/java/audio/funkwhale/ffa/playback/PinService.kt

@ -7,7 +7,13 @@ import androidx.core.net.toUri @@ -7,7 +7,13 @@ import androidx.core.net.toUri
import audio.funkwhale.ffa.R
import audio.funkwhale.ffa.model.DownloadInfo
import audio.funkwhale.ffa.model.Track
import audio.funkwhale.ffa.utils.*
import audio.funkwhale.ffa.utils.AppContext
import audio.funkwhale.ffa.utils.Event
import audio.funkwhale.ffa.utils.EventBus
import audio.funkwhale.ffa.utils.Request
import audio.funkwhale.ffa.utils.RequestBus
import audio.funkwhale.ffa.utils.Response
import audio.funkwhale.ffa.utils.mustNormalizeUrl
import com.google.android.exoplayer2.offline.Download
import com.google.android.exoplayer2.offline.DownloadManager
import com.google.android.exoplayer2.offline.DownloadRequest
@ -21,7 +27,7 @@ import kotlinx.coroutines.Job @@ -21,7 +27,7 @@ import kotlinx.coroutines.Job
import kotlinx.coroutines.flow.collect
import kotlinx.coroutines.launch
import org.koin.java.KoinJavaComponent
import java.util.*
import java.util.Collections
class PinService : DownloadService(AppContext.NOTIFICATION_DOWNLOADS) {

42
app/src/main/java/audio/funkwhale/ffa/playback/PlayerService.kt

@ -17,7 +17,19 @@ import androidx.core.app.NotificationManagerCompat @@ -17,7 +17,19 @@ 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 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.FFACache
import audio.funkwhale.ffa.utils.HeadphonesUnpluggedReceiver
import audio.funkwhale.ffa.utils.ProgressBus
import audio.funkwhale.ffa.utils.Request
import audio.funkwhale.ffa.utils.RequestBus
import audio.funkwhale.ffa.utils.Response
import audio.funkwhale.ffa.utils.log
import audio.funkwhale.ffa.utils.maybeNormalizeUrl
import audio.funkwhale.ffa.utils.onApi
import com.google.android.exoplayer2.C
import com.google.android.exoplayer2.ExoPlaybackException
import com.google.android.exoplayer2.Player
@ -25,10 +37,15 @@ import com.google.android.exoplayer2.SimpleExoPlayer @@ -25,10 +37,15 @@ import com.google.android.exoplayer2.SimpleExoPlayer
import com.google.android.exoplayer2.source.TrackGroupArray
import com.google.android.exoplayer2.trackselection.TrackSelectionArray
import com.squareup.picasso.Picasso
import kotlinx.coroutines.*
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers.IO
import kotlinx.coroutines.Dispatchers.Main
import kotlinx.coroutines.Job
import kotlinx.coroutines.cancel
import kotlinx.coroutines.delay
import kotlinx.coroutines.flow.collect
import kotlinx.coroutines.launch
import kotlinx.coroutines.runBlocking
import org.koin.java.KoinJavaComponent.inject
class PlayerService : Service() {
@ -97,15 +114,17 @@ class PlayerService : Service() { @@ -97,15 +114,17 @@ class PlayerService : Service() {
Build.VERSION_CODES.O.onApi {
audioFocusRequest = AudioFocusRequest.Builder(AudioManager.AUDIOFOCUS_GAIN).run {
setAudioAttributes(AudioAttributes.Builder().run {
setUsage(AudioAttributes.USAGE_MEDIA)
setContentType(AudioAttributes.CONTENT_TYPE_MUSIC)
setAudioAttributes(
AudioAttributes.Builder().run {
setUsage(AudioAttributes.USAGE_MEDIA)
setContentType(AudioAttributes.CONTENT_TYPE_MUSIC)
setAcceptsDelayedFocusGain(true)
setOnAudioFocusChangeListener(audioFocusChangeListener)
setAcceptsDelayedFocusGain(true)
setOnAudioFocusChangeListener(audioFocusChangeListener)
build()
})
build()
}
)
build()
}
@ -268,7 +287,8 @@ class PlayerService : Service() { @@ -268,7 +287,8 @@ class PlayerService : Service() {
{
@Suppress("DEPRECATION")
audioManager.abandonAudioFocus(audioFocusChangeListener)
})
}
)
player.removeListener(playerEventListener)
setPlaybackState(false)
@ -461,7 +481,7 @@ class PlayerService : Service() { @@ -461,7 +481,7 @@ class PlayerService : Service() {
}
if (queue.get().isNotEmpty() && queue.current() == queue.get()
.last() && radioPlayer.isActive()
.last() && radioPlayer.isActive()
) {
scope.launch(IO) {
if (radioPlayer.lock.tryAcquire()) {

20
app/src/main/java/audio/funkwhale/ffa/playback/QueueManager.kt

@ -4,7 +4,13 @@ import android.content.Context @@ -4,7 +4,13 @@ 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 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.FFACache
import audio.funkwhale.ffa.utils.log
import audio.funkwhale.ffa.utils.mustNormalizeUrl
import com.github.kittinunf.fuel.gson.gsonDeserializerOf
import com.google.android.exoplayer2.source.ConcatenatingMediaSource
import com.google.android.exoplayer2.source.ProgressiveMediaSource
@ -28,12 +34,14 @@ class QueueManager(val context: Context) { @@ -28,12 +34,14 @@ class QueueManager(val context: Context) {
val factory = cacheDataSourceFactoryProvider.create(context)
dataSources.addMediaSources(metadata.map { track ->
val url = mustNormalizeUrl(track.bestUpload()?.listen_url ?: "")
dataSources.addMediaSources(
metadata.map { track ->
val url = mustNormalizeUrl(track.bestUpload()?.listen_url ?: "")
ProgressiveMediaSource.Factory(factory).setTag(track.title)
.createMediaSource(Uri.parse(url))
})
ProgressiveMediaSource.Factory(factory).setTag(track.title)
.createMediaSource(Uri.parse(url))
}
)
}
}

11
app/src/main/java/audio/funkwhale/ffa/playback/RadioPlayer.kt

@ -6,7 +6,16 @@ import audio.funkwhale.ffa.model.Radio @@ -6,7 +6,16 @@ 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.*
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.FFACache
import audio.funkwhale.ffa.utils.OAuth
import audio.funkwhale.ffa.utils.authorize
import audio.funkwhale.ffa.utils.logError
import audio.funkwhale.ffa.utils.mustNormalizeUrl
import audio.funkwhale.ffa.utils.toast
import com.github.kittinunf.fuel.Fuel
import com.github.kittinunf.fuel.coroutines.awaitObjectResponseResult
import com.github.kittinunf.fuel.coroutines.awaitObjectResult

15
app/src/main/java/audio/funkwhale/ffa/repositories/FavoritesRepository.kt

@ -1,8 +1,19 @@ @@ -1,8 +1,19 @@
package audio.funkwhale.ffa.repositories
import android.content.Context
import audio.funkwhale.ffa.model.*
import audio.funkwhale.ffa.utils.*
import audio.funkwhale.ffa.model.FFAResponse
import audio.funkwhale.ffa.model.FavoritedCache
import audio.funkwhale.ffa.model.FavoritedResponse
import audio.funkwhale.ffa.model.Track
import audio.funkwhale.ffa.model.TracksCache
import audio.funkwhale.ffa.model.TracksResponse
import audio.funkwhale.ffa.utils.FFACache
import audio.funkwhale.ffa.utils.OAuth
import audio.funkwhale.ffa.utils.Settings
import audio.funkwhale.ffa.utils.authorize
import audio.funkwhale.ffa.utils.maybeNormalizeUrl
import audio.funkwhale.ffa.utils.mustNormalizeUrl
import audio.funkwhale.ffa.utils.untilNetwork
import com.github.kittinunf.fuel.Fuel
import com.github.kittinunf.fuel.coroutines.awaitByteArrayResponseResult
import com.github.kittinunf.fuel.gson.gsonDeserializerOf

9
app/src/main/java/audio/funkwhale/ffa/repositories/HttpUpstream.kt

@ -4,7 +4,14 @@ import android.content.Context @@ -4,7 +4,14 @@ import android.content.Context
import android.net.Uri
import android.util.Log
import audio.funkwhale.ffa.model.FFAResponse
import audio.funkwhale.ffa.utils.*
import audio.funkwhale.ffa.utils.AppContext
import audio.funkwhale.ffa.utils.Event
import audio.funkwhale.ffa.utils.EventBus
import audio.funkwhale.ffa.utils.OAuth
import audio.funkwhale.ffa.utils.RefreshError
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.core.FuelError
import com.github.kittinunf.fuel.core.ResponseDeserializable

6
app/src/main/java/audio/funkwhale/ffa/repositories/PlaylistsRepository.kt

@ -1,7 +1,11 @@ @@ -1,7 +1,11 @@
package audio.funkwhale.ffa.repositories
import android.content.Context
import audio.funkwhale.ffa.model.*
import audio.funkwhale.ffa.model.FFAResponse
import audio.funkwhale.ffa.model.Playlist
import audio.funkwhale.ffa.model.PlaylistsCache
import audio.funkwhale.ffa.model.PlaylistsResponse
import audio.funkwhale.ffa.model.Track
import audio.funkwhale.ffa.utils.OAuth
import audio.funkwhale.ffa.utils.Settings
import audio.funkwhale.ffa.utils.authorize

10
app/src/main/java/audio/funkwhale/ffa/repositories/Repository.kt

@ -1,13 +1,17 @@ @@ -1,13 +1,17 @@
package audio.funkwhale.ffa.repositories
import android.content.Context
import audio.funkwhale.ffa.utils.AppContext
import audio.funkwhale.ffa.model.CacheItem
import audio.funkwhale.ffa.utils.AppContext
import audio.funkwhale.ffa.utils.FFACache
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers.IO
import kotlinx.coroutines.Job
import kotlinx.coroutines.flow.*
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.collect
import kotlinx.coroutines.flow.flow
import kotlinx.coroutines.flow.flowOn
import kotlinx.coroutines.flow.map
import java.io.BufferedReader
import kotlin.math.ceil
@ -59,7 +63,7 @@ abstract class Repository<D : Any, C : CacheItem<D>> { @@ -59,7 +63,7 @@ abstract class Repository<D : Any, C : CacheItem<D>> {
}
}.flowOn(IO)
private fun fromNetwork(size: Int) = flow {
private fun fromNetwork(size: Int): Flow<Response<D>> = flow {
upstream
.fetch(size)
.map { response ->

13
app/src/main/java/audio/funkwhale/ffa/repositories/SearchRepository.kt

@ -1,8 +1,17 @@ @@ -1,8 +1,17 @@
package audio.funkwhale.ffa.repositories
import android.content.Context
import audio.funkwhale.ffa.model.*
import audio.funkwhale.ffa.utils.*
import audio.funkwhale.ffa.model.Album
import audio.funkwhale.ffa.model.AlbumsCache
import audio.funkwhale.ffa.model.AlbumsResponse
import audio.funkwhale.ffa.model.Artist
import audio.funkwhale.ffa.model.ArtistsCache
import audio.funkwhale.ffa.model.ArtistsResponse
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.mustNormalizeUrl
import com.github.kittinunf.fuel.gson.gsonDeserializerOf
import com.google.android.exoplayer2.offline.DownloadManager
import com.google.android.exoplayer2.upstream.cache.Cache

4
app/src/main/java/audio/funkwhale/ffa/utils/Extensions.kt

@ -23,7 +23,7 @@ import kotlinx.coroutines.launch @@ -23,7 +23,7 @@ import kotlinx.coroutines.launch
import kotlinx.coroutines.runBlocking
import net.openid.appauth.ClientSecretPost
import java.text.SimpleDateFormat
import java.util.*
import java.util.Date
import kotlin.coroutines.CoroutineContext
inline fun <D> Flow<Repository.Response<D>>.untilNetwork(
@ -106,4 +106,4 @@ val ISO_8601_DATE_TIME_FORMAT = SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ssZ") @@ -106,4 +106,4 @@ val ISO_8601_DATE_TIME_FORMAT = SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ssZ")
fun Date.format(): String {
return ISO_8601_DATE_TIME_FORMAT.format(this)
}
}

2
app/src/main/java/audio/funkwhale/ffa/utils/FuelResult.kt

@ -19,4 +19,4 @@ data class FuelResult(val httpStatus: Int? = null, val message: String? = null) @@ -19,4 +19,4 @@ data class FuelResult(val httpStatus: Int? = null, val message: String? = null)
return FuelResult()
}
}
}
}

23
app/src/main/java/audio/funkwhale/ffa/utils/OAuth.kt

@ -13,7 +13,16 @@ import com.github.kittinunf.fuel.gson.jsonBody @@ -13,7 +13,16 @@ import com.github.kittinunf.fuel.gson.jsonBody
import com.github.kittinunf.result.Result
import com.preference.PowerPreference
import kotlinx.coroutines.runBlocking
import net.openid.appauth.*
import net.openid.appauth.AuthState
import net.openid.appauth.AuthorizationException
import net.openid.appauth.AuthorizationRequest
import net.openid.appauth.AuthorizationResponse
import net.openid.appauth.AuthorizationService
import net.openid.appauth.AuthorizationServiceConfiguration
import net.openid.appauth.ClientSecretPost
import net.openid.appauth.RegistrationRequest
import net.openid.appauth.RegistrationResponse
import net.openid.appauth.ResponseTypeValues
fun AuthState.save() {
PowerPreference.getFileByName(AppContext.PREFS_CREDENTIALS).apply {
@ -56,11 +65,13 @@ class OAuth(private val authorizationServiceFactory: AuthorizationServiceFactory @@ -56,11 +65,13 @@ class OAuth(private val authorizationServiceFactory: AuthorizationServiceFactory
fun isAuthorized(context: Context): Boolean {
val state = tryState()
return (if (state != null) {
state.validAuthorization() || refreshAccessToken(state, context)
} else {
false
}).also {
return (
if (state != null) {
state.validAuthorization() || refreshAccessToken(state, context)
} else {
false
}
).also {
it.logInfo("isAuthorized()")
}
}

2
app/src/test/java/audio/funkwhale/ffa/FFATest.kt

@ -58,4 +58,4 @@ class FFATest { @@ -58,4 +58,4 @@ class FFATest {
expectThat(picassoCache.exists()).isFalse()
}
}
}

2
app/src/test/java/audio/funkwhale/ffa/KoinTestApp.kt

@ -24,4 +24,4 @@ class KoinTestApp : Application() { @@ -24,4 +24,4 @@ class KoinTestApp : Application() {
block()
unloadKoinModules(module)
}
}
}

5
app/src/test/java/audio/funkwhale/ffa/activities/SplashActivityTest.kt

@ -8,7 +8,10 @@ import audio.funkwhale.ffa.KoinTestApp @@ -8,7 +8,10 @@ import audio.funkwhale.ffa.KoinTestApp
import audio.funkwhale.ffa.utils.OAuth
import com.preference.PowerPreference
import com.preference.Preference
import io.mockk.*
import io.mockk.every
import io.mockk.mockk
import io.mockk.mockkStatic
import io.mockk.verify
import org.junit.After
import org.junit.Test
import org.junit.runner.RunWith

Loading…
Cancel
Save