Browse Source

Merge branch 'housekeeping/fix-linting-problems' into 'develop'

Fix existing linting problems

See merge request funkwhale/funkwhale-android!100
housekeeping/mavenCentral
Ryan Harg 3 years ago
parent
commit
70feb589fa
  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 {
sourceDirectories.setFrom(files(listOf(mainSrc))) sourceDirectories.setFrom(files(listOf(mainSrc)))
classDirectories.setFrom(files(listOf(debugTree))) classDirectories.setFrom(files(listOf(debugTree)))
executionData.setFrom(fileTree(project.buildDir) { executionData.setFrom(
setIncludes( fileTree(project.buildDir) {
listOf( setIncludes(
"outputs/unit_test_code_coverage/debugUnitTest/*.exec", listOf(
"outputs/code_coverage/debugAndroidTest/connected/**/*.ec" "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
import androidx.appcompat.app.AppCompatDelegate import androidx.appcompat.app.AppCompatDelegate
import audio.funkwhale.ffa.koin.authModule import audio.funkwhale.ffa.koin.authModule
import audio.funkwhale.ffa.koin.exoplayerModule 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 com.preference.PowerPreference
import kotlinx.coroutines.channels.BroadcastChannel import kotlinx.coroutines.channels.BroadcastChannel
import kotlinx.coroutines.channels.ConflatedBroadcastChannel import kotlinx.coroutines.channels.ConflatedBroadcastChannel
import org.koin.core.context.startKoin import org.koin.core.context.startKoin
import java.text.SimpleDateFormat import java.text.SimpleDateFormat
import java.util.* import java.util.Date
import java.util.Locale
class FFA : Application() { class FFA : Application() {

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

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

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

@ -90,7 +90,8 @@ class LicencesActivity : AppCompatActivity() {
holder.licence.text = item.licence 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 { View.OnClickListener {
val name = binding.name val name = binding.name
val licence = binding.licence val licence = binding.licence

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

@ -11,7 +11,10 @@ import androidx.lifecycle.lifecycleScope
import audio.funkwhale.ffa.R import audio.funkwhale.ffa.R
import audio.funkwhale.ffa.databinding.ActivityLoginBinding import audio.funkwhale.ffa.databinding.ActivityLoginBinding
import audio.funkwhale.ffa.fragments.LoginDialog 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.Fuel
import com.github.kittinunf.fuel.coroutines.awaitObjectResponseResult import com.github.kittinunf.fuel.coroutines.awaitObjectResponseResult
import com.github.kittinunf.fuel.gson.gsonDeserializerOf 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
import android.os.Build import android.os.Build
import android.os.Bundle import android.os.Bundle
import android.util.DisplayMetrics 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.view.animation.AccelerateDecelerateInterpolator
import android.widget.SeekBar import android.widget.SeekBar
import androidx.appcompat.app.AppCompatActivity import androidx.appcompat.app.AppCompatActivity
@ -24,7 +28,13 @@ import androidx.lifecycle.lifecycleScope
import audio.funkwhale.ffa.FFA import audio.funkwhale.ffa.FFA
import audio.funkwhale.ffa.R import audio.funkwhale.ffa.R
import audio.funkwhale.ffa.databinding.ActivityMainBinding 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.model.Track
import audio.funkwhale.ffa.playback.MediaControlsManager import audio.funkwhale.ffa.playback.MediaControlsManager
import audio.funkwhale.ffa.playback.PinService import audio.funkwhale.ffa.playback.PinService
@ -32,7 +42,25 @@ import audio.funkwhale.ffa.playback.PlayerService
import audio.funkwhale.ffa.repositories.FavoritedRepository import audio.funkwhale.ffa.repositories.FavoritedRepository
import audio.funkwhale.ffa.repositories.FavoritesRepository import audio.funkwhale.ffa.repositories.FavoritesRepository
import audio.funkwhale.ffa.repositories.Repository 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 audio.funkwhale.ffa.views.DisableableFrameLayout
import com.github.kittinunf.fuel.Fuel import com.github.kittinunf.fuel.Fuel
import com.github.kittinunf.fuel.coroutines.awaitStringResponse import com.github.kittinunf.fuel.coroutines.awaitStringResponse
@ -132,17 +160,17 @@ class MainActivity : AppCompatActivity() {
} }
binding.nowPlayingContainer?.nowPlayingDetailsProgress?.setOnSeekBarChangeListener(object : binding.nowPlayingContainer?.nowPlayingDetailsProgress?.setOnSeekBarChangeListener(object :
SeekBar.OnSeekBarChangeListener { SeekBar.OnSeekBarChangeListener {
override fun onStopTrackingTouch(view: SeekBar?) {} override fun onStopTrackingTouch(view: SeekBar?) {}
override fun onStartTrackingTouch(view: SeekBar?) {} override fun onStartTrackingTouch(view: SeekBar?) {}
override fun onProgressChanged(view: SeekBar?, progress: Int, fromUser: Boolean) { override fun onProgressChanged(view: SeekBar?, progress: Int, fromUser: Boolean) {
if (fromUser) { if (fromUser) {
CommandBus.send(Command.Seek(progress)) CommandBus.send(Command.Seek(progress))
}
} }
} })
})
landscapeQueue?.let { landscapeQueue?.let {
supportFragmentManager.beginTransaction() supportFragmentManager.beginTransaction()
@ -303,9 +331,11 @@ class MainActivity : AppCompatActivity() {
when (message) { when (message) {
is Event.LogOut -> { is Event.LogOut -> {
FFA.get().deleteAllData(this@MainActivity) FFA.get().deleteAllData(this@MainActivity)
startActivity(Intent(this@MainActivity, LoginActivity::class.java).apply { startActivity(
flags = Intent.FLAG_ACTIVITY_NO_HISTORY Intent(this@MainActivity, LoginActivity::class.java).apply {
}) flags = Intent.FLAG_ACTIVITY_NO_HISTORY
}
)
finish() finish()
} }
@ -385,12 +415,15 @@ class MainActivity : AppCompatActivity() {
PlayerService::class.java PlayerService::class.java
).apply { ).apply {
putExtra(PlayerService.INITIAL_COMMAND_KEY, command.command.toString()) putExtra(PlayerService.INITIAL_COMMAND_KEY, command.command.toString())
}) }
)
}, },
{ {
startService(Intent(this@MainActivity, PlayerService::class.java).apply { startService(
putExtra(PlayerService.INITIAL_COMMAND_KEY, command.command.toString()) 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
import audio.funkwhale.ffa.fragments.ArtistsFragment import audio.funkwhale.ffa.fragments.ArtistsFragment
import audio.funkwhale.ffa.model.Album import audio.funkwhale.ffa.model.Album
import audio.funkwhale.ffa.model.Artist import audio.funkwhale.ffa.model.Artist
import audio.funkwhale.ffa.repositories.* import audio.funkwhale.ffa.repositories.AlbumsSearchRepository
import audio.funkwhale.ffa.utils.* 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 com.google.android.exoplayer2.offline.Download
import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.flow.collect import kotlinx.coroutines.flow.collect
import kotlinx.coroutines.launch import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext import kotlinx.coroutines.withContext
import java.net.URLEncoder import java.net.URLEncoder
import java.util.* import java.util.Locale
class SearchActivity : AppCompatActivity() { class SearchActivity : AppCompatActivity() {
private lateinit var adapter: SearchAdapter private lateinit var adapter: SearchAdapter
@ -82,58 +91,58 @@ class SearchActivity : AppCompatActivity() {
favoritesRepository = FavoritesRepository(this@SearchActivity) favoritesRepository = FavoritesRepository(this@SearchActivity)
binding.search.setOnQueryTextListener(object : binding.search.setOnQueryTextListener(object :
androidx.appcompat.widget.SearchView.OnQueryTextListener { androidx.appcompat.widget.SearchView.OnQueryTextListener {
override fun onQueryTextSubmit(rawQuery: String?): Boolean { override fun onQueryTextSubmit(rawQuery: String?): Boolean {
binding.search.clearFocus() binding.search.clearFocus()
rawQuery?.let { rawQuery?.let {
done = 0 done = 0
val query = URLEncoder.encode(it, "UTF-8") val query = URLEncoder.encode(it, "UTF-8")
artistsRepository.query = query.lowercase(Locale.ROOT) artistsRepository.query = query.lowercase(Locale.ROOT)
albumsRepository.query = query.lowercase(Locale.ROOT) albumsRepository.query = query.lowercase(Locale.ROOT)
tracksRepository.query = query.lowercase(Locale.ROOT) tracksRepository.query = query.lowercase(Locale.ROOT)
binding.searchSpinner.visibility = View.VISIBLE binding.searchSpinner.visibility = View.VISIBLE
binding.searchEmpty.visibility = View.GONE binding.searchEmpty.visibility = View.GONE
binding.searchNoResults.visibility = View.GONE binding.searchNoResults.visibility = View.GONE
adapter.artists.clear() adapter.artists.clear()
adapter.albums.clear() adapter.albums.clear()
adapter.tracks.clear() adapter.tracks.clear()
adapter.notifyDataSetChanged() adapter.notifyDataSetChanged()
artistsRepository.fetch(Repository.Origin.Network.origin) artistsRepository.fetch(Repository.Origin.Network.origin)
.untilNetwork(lifecycleScope) { artists, _, _, _ -> .untilNetwork(lifecycleScope) { artists, _, _, _ ->
done++ done++
adapter.artists.addAll(artists) adapter.artists.addAll(artists)
refresh() refresh()
} }
albumsRepository.fetch(Repository.Origin.Network.origin) albumsRepository.fetch(Repository.Origin.Network.origin)
.untilNetwork(lifecycleScope) { albums, _, _, _ -> .untilNetwork(lifecycleScope) { albums, _, _, _ ->
done++ done++
adapter.albums.addAll(albums) adapter.albums.addAll(albums)
refresh() refresh()
} }
tracksRepository.fetch(Repository.Origin.Network.origin) tracksRepository.fetch(Repository.Origin.Network.origin)
.untilNetwork(lifecycleScope) { tracks, _, _, _ -> .untilNetwork(lifecycleScope) { tracks, _, _, _ ->
done++ done++
adapter.tracks.addAll(tracks) adapter.tracks.addAll(tracks)
refresh() refresh()
} }
} }
return true return true
} }
override fun onQueryTextChange(newText: String?) = true override fun onQueryTextChange(newText: String?) = true
}) })
} }
private fun refresh() { private fun refresh() {

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

@ -1,6 +1,10 @@
package audio.funkwhale.ffa.activities 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.os.Bundle
import android.widget.Toast import android.widget.Toast
import androidx.appcompat.app.AlertDialog import androidx.appcompat.app.AlertDialog

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

@ -6,7 +6,9 @@ import android.os.Bundle
import android.util.Log import android.util.Log
import androidx.appcompat.app.AppCompatActivity import androidx.appcompat.app.AppCompatActivity
import audio.funkwhale.ffa.FFA 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 import org.koin.java.KoinJavaComponent.inject
class SplashActivity : AppCompatActivity() { class SplashActivity : AppCompatActivity() {

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

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

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

@ -8,9 +8,9 @@ import android.view.ViewGroup
import androidx.recyclerview.widget.RecyclerView import androidx.recyclerview.widget.RecyclerView
import audio.funkwhale.ffa.R import audio.funkwhale.ffa.R
import audio.funkwhale.ffa.databinding.RowDownloadBinding import audio.funkwhale.ffa.databinding.RowDownloadBinding
import audio.funkwhale.ffa.playback.PinService
import audio.funkwhale.ffa.model.DownloadInfo import audio.funkwhale.ffa.model.DownloadInfo
import audio.funkwhale.ffa.model.Track 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.Download
import com.google.android.exoplayer2.offline.DownloadService 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
import audio.funkwhale.ffa.R import audio.funkwhale.ffa.R
import audio.funkwhale.ffa.databinding.RowTrackBinding import audio.funkwhale.ffa.databinding.RowTrackBinding
import audio.funkwhale.ffa.fragments.FFAAdapter import audio.funkwhale.ffa.fragments.FFAAdapter
import audio.funkwhale.ffa.model.Track
import audio.funkwhale.ffa.utils.Command import audio.funkwhale.ffa.utils.Command
import audio.funkwhale.ffa.utils.CommandBus import audio.funkwhale.ffa.utils.CommandBus
import audio.funkwhale.ffa.model.Track
import audio.funkwhale.ffa.utils.maybeLoad import audio.funkwhale.ffa.utils.maybeLoad
import audio.funkwhale.ffa.utils.maybeNormalizeUrl import audio.funkwhale.ffa.utils.maybeNormalizeUrl
import audio.funkwhale.ffa.utils.toast 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
import audio.funkwhale.ffa.R import audio.funkwhale.ffa.R
import audio.funkwhale.ffa.databinding.RowTrackBinding import audio.funkwhale.ffa.databinding.RowTrackBinding
import audio.funkwhale.ffa.fragments.FFAAdapter 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.PlaylistTrack
import audio.funkwhale.ffa.model.Track 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.maybeLoad
import audio.funkwhale.ffa.utils.maybeNormalizeUrl import audio.funkwhale.ffa.utils.maybeNormalizeUrl
import audio.funkwhale.ffa.utils.toast 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
import audio.funkwhale.ffa.databinding.RowRadioBinding import audio.funkwhale.ffa.databinding.RowRadioBinding
import audio.funkwhale.ffa.databinding.RowRadioHeaderBinding import audio.funkwhale.ffa.databinding.RowRadioHeaderBinding
import audio.funkwhale.ffa.fragments.FFAAdapter import audio.funkwhale.ffa.fragments.FFAAdapter
import audio.funkwhale.ffa.model.Radio
import audio.funkwhale.ffa.utils.AppContext import audio.funkwhale.ffa.utils.AppContext
import audio.funkwhale.ffa.utils.Event import audio.funkwhale.ffa.utils.Event
import audio.funkwhale.ffa.utils.EventBus import audio.funkwhale.ffa.utils.EventBus
import audio.funkwhale.ffa.model.Radio
import audio.funkwhale.ffa.views.LoadingImageView import audio.funkwhale.ffa.views.LoadingImageView
import com.preference.PowerPreference import com.preference.PowerPreference
import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.CoroutineScope
@ -42,8 +42,10 @@ class RadiosAdapter(
private val instanceRadios: List<Radio> by lazy { private val instanceRadios: List<Radio> by lazy {
context?.let { context?.let {
return@lazy when (val username = return@lazy when (
PowerPreference.getFileByName(AppContext.PREFS_CREDENTIALS).getString("actor_username")) { val username =
PowerPreference.getFileByName(AppContext.PREFS_CREDENTIALS).getString("actor_username")
) {
"" -> listOf( "" -> listOf(
Radio( Radio(
0, 0,
@ -133,8 +135,9 @@ class RadiosAdapter(
context?.let { context?.let {
when (position) { when (position) {
0 -> holder.label.text = context.getString(R.string.radio_instance_radios) 0 -> holder.label.text = context.getString(R.string.radio_instance_radios)
instanceRadios.size + 1 -> holder.label.text = instanceRadios.size + 1 ->
context.getString(R.string.radio_user_radios) 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
import audio.funkwhale.ffa.databinding.RowTrackBinding import audio.funkwhale.ffa.databinding.RowTrackBinding
import audio.funkwhale.ffa.model.Album import audio.funkwhale.ffa.model.Album
import audio.funkwhale.ffa.model.Artist import audio.funkwhale.ffa.model.Artist
import audio.funkwhale.ffa.model.Track
import audio.funkwhale.ffa.utils.Command import audio.funkwhale.ffa.utils.Command
import audio.funkwhale.ffa.utils.CommandBus import audio.funkwhale.ffa.utils.CommandBus
import audio.funkwhale.ffa.model.Track
import audio.funkwhale.ffa.utils.maybeLoad import audio.funkwhale.ffa.utils.maybeLoad
import audio.funkwhale.ffa.utils.maybeNormalizeUrl import audio.funkwhale.ffa.utils.maybeNormalizeUrl
import audio.funkwhale.ffa.utils.onApi import audio.funkwhale.ffa.utils.onApi
@ -73,20 +73,19 @@ class SearchAdapter(
ResultType.Artist.ordinal -> artists[position].id.toLong() ResultType.Artist.ordinal -> artists[position].id.toLong()
ResultType.Artist.ordinal -> albums[position - artists.size - 2].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 else -> 0
} }
} }
override fun getItemViewType(position: Int): Int { override fun getItemViewType(position: Int): Int = when {
if (position == 0) return ResultType.Header.ordinal // Artists header position == 0 ||
if (position == (artists.size + 1)) return ResultType.Header.ordinal // Albums header position == (artists.size + 1) ||
if (position == (artists.size + albums.size + 2)) return ResultType.Header.ordinal // Tracks header position == (artists.size + albums.size + 2) -> ResultType.Header.ordinal
position <= artists.size -> ResultType.Artist.ordinal
if (position <= artists.size) return ResultType.Artist.ordinal position <= artists.size + albums.size + 2 -> ResultType.Album.ordinal
if (position <= artists.size + albums.size + 2) return ResultType.Album.ordinal else -> ResultType.Track.ordinal
return ResultType.Track.ordinal
} }
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder { override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
@ -205,102 +204,112 @@ class SearchAdapter(
Typeface.create(searchHeaderViewHolder?.title?.typeface, Typeface.NORMAL) Typeface.create(searchHeaderViewHolder?.title?.typeface, Typeface.NORMAL)
rowTrackViewHolder?.artist?.typeface = rowTrackViewHolder?.artist?.typeface =
Typeface.create(rowTrackViewHolder?.artist?.typeface, Typeface.NORMAL) Typeface.create(rowTrackViewHolder?.artist?.typeface, Typeface.NORMAL)
}) }
)
searchHeaderViewHolder?.title?.setCompoundDrawablesWithIntrinsicBounds(0, 0, 0, 0) searchHeaderViewHolder?.title?.setCompoundDrawablesWithIntrinsicBounds(0, 0, 0, 0)
when (resultType) { when (resultType) {
ResultType.Artist.ordinal -> { ResultType.Artist.ordinal -> {
rowTrackViewHolder?.title?.setCompoundDrawablesWithIntrinsicBounds( rowTrackViewHolder?.title?.setCompoundDrawablesWithIntrinsicBounds(
0, 0, 0, 0 0, 0, 0, 0
) )
} }
ResultType.Album.ordinal -> { ResultType.Album.ordinal -> {
rowTrackViewHolder?.title?.setCompoundDrawablesWithIntrinsicBounds( rowTrackViewHolder?.title?.setCompoundDrawablesWithIntrinsicBounds(
0, 0, 0, 0 0, 0, 0, 0
) )
} }
ResultType.Track.ordinal -> { ResultType.Track.ordinal -> {
(item as? Track)?.let { track -> (item as? Track)?.let { track ->
context?.let { context -> context?.let { context ->
if (track == currentTrack || track.current) { if (track == currentTrack || track.current) {
searchHeaderViewHolder?.title?.setTypeface( searchHeaderViewHolder?.title?.setTypeface(
searchHeaderViewHolder.title.typeface, searchHeaderViewHolder.title.typeface,
Typeface.BOLD Typeface.BOLD
) )
rowTrackViewHolder?.artist?.setTypeface( rowTrackViewHolder?.artist?.setTypeface(
rowTrackViewHolder.artist.typeface, rowTrackViewHolder.artist.typeface,
Typeface.BOLD Typeface.BOLD
) )
} }
when (track.favorite) { when (track.favorite) {
true -> rowTrackViewHolder?.favorite?.setColorFilter(context.getColor(R.color.colorFavorite)) true -> rowTrackViewHolder?.favorite?.setColorFilter(
false -> rowTrackViewHolder?.favorite?.setColorFilter(context.getColor(R.color.colorSelected)) context.getColor(R.color.colorFavorite)
} )
false -> rowTrackViewHolder?.favorite?.setColorFilter(
context.getColor(R.color.colorSelected)
)
}
rowTrackViewHolder?.favorite?.setOnClickListener { rowTrackViewHolder?.favorite?.setOnClickListener {
favoriteListener?.let { favoriteListener?.let {
favoriteListener.onToggleFavorite(track.id, !track.favorite) favoriteListener.onToggleFavorite(track.id, !track.favorite)
tracks[position - artists.size - albums.size - sectionCount].favorite = tracks[position - artists.size - albums.size - sectionCount].favorite =
!track.favorite !track.favorite
notifyItemChanged(position) notifyItemChanged(position)
}
} }
}
when (track.cached || track.downloaded) { when (track.cached || track.downloaded) {
true -> rowTrackViewHolder?.title?.setCompoundDrawablesWithIntrinsicBounds( true -> rowTrackViewHolder?.title?.setCompoundDrawablesWithIntrinsicBounds(
R.drawable.downloaded, 0, 0, 0 R.drawable.downloaded, 0, 0, 0
) )
false -> rowTrackViewHolder?.title?.setCompoundDrawablesWithIntrinsicBounds( false -> rowTrackViewHolder?.title?.setCompoundDrawablesWithIntrinsicBounds(
0, 0, 0, 0 0, 0, 0, 0
) )
} }
if (track.cached && !track.downloaded) { if (track.cached && !track.downloaded) {
rowTrackViewHolder?.title?.compoundDrawables?.forEach { rowTrackViewHolder?.title?.compoundDrawables?.forEach {
it?.colorFilter = it?.colorFilter =
PorterDuffColorFilter(context.getColor(R.color.cached), PorterDuff.Mode.SRC_IN) PorterDuffColorFilter(context.getColor(R.color.cached), PorterDuff.Mode.SRC_IN)
}
} }
}
if (track.downloaded) { if (track.downloaded) {
rowTrackViewHolder?.title?.compoundDrawables?.forEach { rowTrackViewHolder?.title?.compoundDrawables?.forEach {
it?.colorFilter = it?.colorFilter =
PorterDuffColorFilter(context.getColor(R.color.downloaded), PorterDuff.Mode.SRC_IN) PorterDuffColorFilter(
} context.getColor(R.color.downloaded),
PorterDuff.Mode.SRC_IN
)
} }
}
rowTrackViewHolder?.actions?.setOnClickListener { rowTrackViewHolder?.actions?.setOnClickListener {
PopupMenu( PopupMenu(
context, context,
rowTrackViewHolder.actions, rowTrackViewHolder.actions,
Gravity.START, Gravity.START,
R.attr.actionOverflowMenuStyle, R.attr.actionOverflowMenuStyle,
0 0
).apply { ).apply {
inflate(R.menu.row_track) inflate(R.menu.row_track)
setOnMenuItemClickListener { setOnMenuItemClickListener {
when (it.itemId) { when (it.itemId) {
R.id.track_add_to_queue -> CommandBus.send(Command.AddToQueue(listOf(track))) 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_play_next -> CommandBus.send(Command.PlayNext(track))
R.id.track_pin -> CommandBus.send(Command.PinTrack(track)) R.id.track_pin -> CommandBus.send(Command.PinTrack(track))
R.id.track_add_to_playlist -> CommandBus.send(Command.AddToPlaylist(listOf(track))) R.id.track_add_to_playlist -> CommandBus.send(
R.id.queue_remove -> CommandBus.send(Command.RemoveFromQueue(track)) Command.AddToPlaylist(listOf(track))
} )
R.id.queue_remove -> CommandBus.send(Command.RemoveFromQueue(track))
true
} }
show() true
} }
show()
} }
} }
} }
} }
}
} }
} }

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

@ -18,9 +18,9 @@ import androidx.recyclerview.widget.RecyclerView
import audio.funkwhale.ffa.R import audio.funkwhale.ffa.R
import audio.funkwhale.ffa.databinding.RowTrackBinding import audio.funkwhale.ffa.databinding.RowTrackBinding
import audio.funkwhale.ffa.fragments.FFAAdapter import audio.funkwhale.ffa.fragments.FFAAdapter
import audio.funkwhale.ffa.model.Track
import audio.funkwhale.ffa.utils.Command import audio.funkwhale.ffa.utils.Command
import audio.funkwhale.ffa.utils.CommandBus import audio.funkwhale.ffa.utils.CommandBus
import audio.funkwhale.ffa.model.Track
import audio.funkwhale.ffa.utils.maybeLoad import audio.funkwhale.ffa.utils.maybeLoad
import audio.funkwhale.ffa.utils.maybeNormalizeUrl import audio.funkwhale.ffa.utils.maybeNormalizeUrl
import audio.funkwhale.ffa.utils.toast 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
import audio.funkwhale.ffa.model.Playlist import audio.funkwhale.ffa.model.Playlist
import audio.funkwhale.ffa.model.Track import audio.funkwhale.ffa.model.Track
import audio.funkwhale.ffa.repositories.ManagementPlaylistsRepository 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 com.google.gson.Gson
import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers.IO import kotlinx.coroutines.Dispatchers.IO
@ -80,19 +81,22 @@ object AddToPlaylistDialog {
} }
val adapter = val adapter =
PlaylistsAdapter(layoutInflater, activity, object : PlaylistsAdapter.OnPlaylistClickListener { PlaylistsAdapter(
override fun onClick(holder: View?, playlist: Playlist) { layoutInflater, activity,
repository.add(playlist.id, tracks) object : PlaylistsAdapter.OnPlaylistClickListener {
override fun onClick(holder: View?, playlist: Playlist) {
repository.add(playlist.id, tracks)
Toast.makeText( Toast.makeText(
activity, activity,
activity.getString(R.string.playlist_added_to, playlist.name), activity.getString(R.string.playlist_added_to, playlist.name),
Toast.LENGTH_SHORT Toast.LENGTH_SHORT
).show() ).show()
dialog.dismiss() dialog.dismiss()
}
} }
}) )
binding.playlists.layoutManager = LinearLayoutManager(activity) binding.playlists.layoutManager = LinearLayoutManager(activity)
binding.playlists.adapter = adapter 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
import audio.funkwhale.ffa.repositories.AlbumsRepository import audio.funkwhale.ffa.repositories.AlbumsRepository
import audio.funkwhale.ffa.repositories.ArtistTracksRepository import audio.funkwhale.ffa.repositories.ArtistTracksRepository
import audio.funkwhale.ffa.repositories.Repository 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 com.squareup.picasso.Picasso
import jp.wasabeef.picasso.transformations.RoundedCornersTransformation import jp.wasabeef.picasso.transformations.RoundedCornersTransformation
import kotlinx.coroutines.Dispatchers.IO 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
import audio.funkwhale.ffa.activities.MainActivity import audio.funkwhale.ffa.activities.MainActivity
import audio.funkwhale.ffa.adapters.AlbumsGridAdapter import audio.funkwhale.ffa.adapters.AlbumsGridAdapter
import audio.funkwhale.ffa.databinding.FragmentAlbumsGridBinding import audio.funkwhale.ffa.databinding.FragmentAlbumsGridBinding
import audio.funkwhale.ffa.repositories.AlbumsRepository
import audio.funkwhale.ffa.model.Album import audio.funkwhale.ffa.model.Album
import audio.funkwhale.ffa.repositories.AlbumsRepository
import audio.funkwhale.ffa.utils.AppContext import audio.funkwhale.ffa.utils.AppContext
class AlbumsGridFragment : FFAFragment<Album, AlbumsGridAdapter>() { 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
import androidx.swiperefreshlayout.widget.SwipeRefreshLayout import androidx.swiperefreshlayout.widget.SwipeRefreshLayout
import audio.funkwhale.ffa.repositories.HttpUpstream import audio.funkwhale.ffa.repositories.HttpUpstream
import audio.funkwhale.ffa.repositories.Repository 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 com.google.gson.Gson
import kotlinx.coroutines.Dispatchers.IO import kotlinx.coroutines.Dispatchers.IO
import kotlinx.coroutines.Dispatchers.Main 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
import audio.funkwhale.ffa.model.Track import audio.funkwhale.ffa.model.Track
import audio.funkwhale.ffa.repositories.FavoritesRepository import audio.funkwhale.ffa.repositories.FavoritesRepository
import audio.funkwhale.ffa.repositories.TracksRepository 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.Download
import com.google.android.exoplayer2.offline.DownloadManager import com.google.android.exoplayer2.offline.DownloadManager
import kotlinx.coroutines.Dispatchers.IO 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
import audio.funkwhale.ffa.repositories.FavoritesRepository import audio.funkwhale.ffa.repositories.FavoritesRepository
import audio.funkwhale.ffa.repositories.ManagementPlaylistsRepository import audio.funkwhale.ffa.repositories.ManagementPlaylistsRepository
import audio.funkwhale.ffa.repositories.PlaylistTracksRepository 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 com.squareup.picasso.Picasso
import jp.wasabeef.picasso.transformations.RoundedCornersTransformation import jp.wasabeef.picasso.transformations.RoundedCornersTransformation
import kotlinx.coroutines.Dispatchers.Main 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
import audio.funkwhale.ffa.activities.MainActivity import audio.funkwhale.ffa.activities.MainActivity
import audio.funkwhale.ffa.adapters.PlaylistsAdapter import audio.funkwhale.ffa.adapters.PlaylistsAdapter
import audio.funkwhale.ffa.databinding.FragmentPlaylistsBinding import audio.funkwhale.ffa.databinding.FragmentPlaylistsBinding
import audio.funkwhale.ffa.model.Playlist
import audio.funkwhale.ffa.repositories.PlaylistsRepository import audio.funkwhale.ffa.repositories.PlaylistsRepository
import audio.funkwhale.ffa.utils.AppContext import audio.funkwhale.ffa.utils.AppContext
import audio.funkwhale.ffa.model.Playlist
class PlaylistsFragment : FFAFragment<Playlist, PlaylistsAdapter>() { class PlaylistsFragment : FFAFragment<Playlist, PlaylistsAdapter>() {

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

@ -9,12 +9,12 @@ import androidx.lifecycle.lifecycleScope
import androidx.recyclerview.widget.RecyclerView import androidx.recyclerview.widget.RecyclerView
import audio.funkwhale.ffa.adapters.RadiosAdapter import audio.funkwhale.ffa.adapters.RadiosAdapter
import audio.funkwhale.ffa.databinding.FragmentRadiosBinding import audio.funkwhale.ffa.databinding.FragmentRadiosBinding
import audio.funkwhale.ffa.model.Radio
import audio.funkwhale.ffa.repositories.RadiosRepository import audio.funkwhale.ffa.repositories.RadiosRepository
import audio.funkwhale.ffa.utils.Command import audio.funkwhale.ffa.utils.Command
import audio.funkwhale.ffa.utils.CommandBus import audio.funkwhale.ffa.utils.CommandBus
import audio.funkwhale.ffa.utils.Event import audio.funkwhale.ffa.utils.Event
import audio.funkwhale.ffa.utils.EventBus import audio.funkwhale.ffa.utils.EventBus
import audio.funkwhale.ffa.model.Radio
import kotlinx.coroutines.Dispatchers.Main import kotlinx.coroutines.Dispatchers.Main
import kotlinx.coroutines.flow.collect import kotlinx.coroutines.flow.collect
import kotlinx.coroutines.launch 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
import audio.funkwhale.ffa.repositories.FavoritedRepository import audio.funkwhale.ffa.repositories.FavoritedRepository
import audio.funkwhale.ffa.repositories.FavoritesRepository import audio.funkwhale.ffa.repositories.FavoritesRepository
import audio.funkwhale.ffa.repositories.TracksRepository 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.Download
import com.google.android.exoplayer2.offline.DownloadManager import com.google.android.exoplayer2.offline.DownloadManager
import com.preference.PowerPreference import com.preference.PowerPreference
@ -199,8 +210,10 @@ class TracksFragment : FFAFragment<Track, TracksAdapter>() {
setOnMenuItemClickListener { setOnMenuItemClickListener {
when (it.itemId) { when (it.itemId) {
R.id.play_secondary -> when (PowerPreference.getDefaultFile() R.id.play_secondary -> when (
.getString("play_order")) { PowerPreference.getDefaultFile()
.getString("play_order")
) {
"in_order" -> CommandBus.send(Command.ReplaceQueue(adapter.data.shuffled())) "in_order" -> CommandBus.send(Command.ReplaceQueue(adapter.data.shuffled()))
else -> CommandBus.send(Command.ReplaceQueue(adapter.data)) 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 {
fun authModule() = module { fun authModule() = module {
single { OAuth(get()) } single { OAuth(get()) }
single { AuthorizationServiceFactory() } single { AuthorizationServiceFactory() }
} }

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

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

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

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

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

@ -6,4 +6,4 @@ data class ArtistsResponse(
val results: List<Artist> val results: List<Artist>
) : FFAResponse<Artist>() { ) : FFAResponse<Artist>() {
override fun getData() = results 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)
class PlaylistTracksCache(data: List<PlaylistTrack>) : CacheItem<PlaylistTrack>(data) class PlaylistTracksCache(data: List<PlaylistTrack>) : CacheItem<PlaylistTrack>(data)
class RadiosCache(data: List<Radio>) : CacheItem<Radio>(data) class RadiosCache(data: List<Radio>) : CacheItem<Radio>(data)
class FavoritedCache(data: List<Int>) : CacheItem<Int>(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 @@
package audio.funkwhale.ffa.model 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 @@
package audio.funkwhale.ffa.model 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(
val title: String, val title: String,
val artist: String, val artist: String,
var download: Download? var download: Download?
) )

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

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

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

@ -1,3 +1,3 @@
package audio.funkwhale.ffa.model 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(
val results: List<Favorited> val results: List<Favorited>
) : FFAResponse<Int>() { ) : FFAResponse<Int>() {
override fun getData() = results.map { it.track } 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(
val album_covers: List<String>, val album_covers: List<String>,
val tracks_count: Int, val tracks_count: Int,
val duration: Int val duration: Int
) )

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

@ -1,3 +1,3 @@
package audio.funkwhale.ffa.model 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(
val results: List<PlaylistTrack> val results: List<PlaylistTrack>
) : FFAResponse<PlaylistTrack>() { ) : FFAResponse<PlaylistTrack>() {
override fun getData() = results override fun getData() = results
} }

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

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

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

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

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

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

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

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

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

@ -61,4 +61,4 @@ data class Track(
override fun subtitle() = artist.name override fun subtitle() = artist.name
val formatted: String get() = "$id $artist ($album): $title" 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(
val results: List<Track> val results: List<Track>
) : FFAResponse<Track>() { ) : FFAResponse<Track>() {
override fun getData() = results override fun getData() = results
} }

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

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

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

@ -12,8 +12,8 @@ import androidx.media.app.NotificationCompat.MediaStyle
import androidx.media.session.MediaButtonReceiver import androidx.media.session.MediaButtonReceiver
import audio.funkwhale.ffa.R import audio.funkwhale.ffa.R
import audio.funkwhale.ffa.activities.MainActivity import audio.funkwhale.ffa.activities.MainActivity
import audio.funkwhale.ffa.utils.AppContext
import audio.funkwhale.ffa.model.Track import audio.funkwhale.ffa.model.Track
import audio.funkwhale.ffa.utils.AppContext
import audio.funkwhale.ffa.utils.maybeNormalizeUrl import audio.funkwhale.ffa.utils.maybeNormalizeUrl
import com.squareup.picasso.Picasso import com.squareup.picasso.Picasso
import kotlinx.coroutines.CoroutineScope 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) {
it.setMediaButtonEventHandler { _, _, intent -> it.setMediaButtonEventHandler { _, _, intent ->
if (!active) { if (!active) {
context.startService(Intent(context, PlayerService::class.java).apply { context.startService(
action = intent.action Intent(context, PlayerService::class.java).apply {
action = intent.action
intent.extras?.let { extras -> putExtras(extras) } intent.extras?.let { extras -> putExtras(extras) }
}) }
)
return@setMediaButtonEventHandler true return@setMediaButtonEventHandler true
} }

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

@ -3,7 +3,11 @@ package audio.funkwhale.ffa.playback
import android.content.Context import android.content.Context
import android.net.Uri import android.net.Uri
import audio.funkwhale.ffa.utils.OAuth 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( class OAuthDatasource(
private val context: Context, private val context: Context,
@ -38,7 +42,7 @@ class OAuthDatasource(
class OAuth2DatasourceFactory( class OAuth2DatasourceFactory(
private val context: Context, private val context: Context,
private val http: DefaultHttpDataSourceFactory, private val http: DefaultHttpDataSource.Factory,
private val oauth: OAuth private val oauth: OAuth
) : DataSource.Factory { ) : DataSource.Factory {

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

@ -7,7 +7,13 @@ import androidx.core.net.toUri
import audio.funkwhale.ffa.R import audio.funkwhale.ffa.R
import audio.funkwhale.ffa.model.DownloadInfo import audio.funkwhale.ffa.model.DownloadInfo
import audio.funkwhale.ffa.model.Track 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.Download
import com.google.android.exoplayer2.offline.DownloadManager import com.google.android.exoplayer2.offline.DownloadManager
import com.google.android.exoplayer2.offline.DownloadRequest import com.google.android.exoplayer2.offline.DownloadRequest
@ -21,7 +27,7 @@ import kotlinx.coroutines.Job
import kotlinx.coroutines.flow.collect import kotlinx.coroutines.flow.collect
import kotlinx.coroutines.launch import kotlinx.coroutines.launch
import org.koin.java.KoinJavaComponent import org.koin.java.KoinJavaComponent
import java.util.* import java.util.Collections
class PinService : DownloadService(AppContext.NOTIFICATION_DOWNLOADS) { 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
import androidx.media.session.MediaButtonReceiver import androidx.media.session.MediaButtonReceiver
import audio.funkwhale.ffa.R import audio.funkwhale.ffa.R
import audio.funkwhale.ffa.model.Track 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.C
import com.google.android.exoplayer2.ExoPlaybackException import com.google.android.exoplayer2.ExoPlaybackException
import com.google.android.exoplayer2.Player import com.google.android.exoplayer2.Player
@ -25,10 +37,15 @@ import com.google.android.exoplayer2.SimpleExoPlayer
import com.google.android.exoplayer2.source.TrackGroupArray import com.google.android.exoplayer2.source.TrackGroupArray
import com.google.android.exoplayer2.trackselection.TrackSelectionArray import com.google.android.exoplayer2.trackselection.TrackSelectionArray
import com.squareup.picasso.Picasso import com.squareup.picasso.Picasso
import kotlinx.coroutines.* import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers.IO import kotlinx.coroutines.Dispatchers.IO
import kotlinx.coroutines.Dispatchers.Main 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.flow.collect
import kotlinx.coroutines.launch
import kotlinx.coroutines.runBlocking
import org.koin.java.KoinJavaComponent.inject import org.koin.java.KoinJavaComponent.inject
class PlayerService : Service() { class PlayerService : Service() {
@ -97,15 +114,17 @@ class PlayerService : Service() {
Build.VERSION_CODES.O.onApi { Build.VERSION_CODES.O.onApi {
audioFocusRequest = AudioFocusRequest.Builder(AudioManager.AUDIOFOCUS_GAIN).run { audioFocusRequest = AudioFocusRequest.Builder(AudioManager.AUDIOFOCUS_GAIN).run {
setAudioAttributes(AudioAttributes.Builder().run { setAudioAttributes(
setUsage(AudioAttributes.USAGE_MEDIA) AudioAttributes.Builder().run {
setContentType(AudioAttributes.CONTENT_TYPE_MUSIC) setUsage(AudioAttributes.USAGE_MEDIA)
setContentType(AudioAttributes.CONTENT_TYPE_MUSIC)
setAcceptsDelayedFocusGain(true) setAcceptsDelayedFocusGain(true)
setOnAudioFocusChangeListener(audioFocusChangeListener) setOnAudioFocusChangeListener(audioFocusChangeListener)
build() build()
}) }
)
build() build()
} }
@ -268,7 +287,8 @@ class PlayerService : Service() {
{ {
@Suppress("DEPRECATION") @Suppress("DEPRECATION")
audioManager.abandonAudioFocus(audioFocusChangeListener) audioManager.abandonAudioFocus(audioFocusChangeListener)
}) }
)
player.removeListener(playerEventListener) player.removeListener(playerEventListener)
setPlaybackState(false) setPlaybackState(false)
@ -461,7 +481,7 @@ class PlayerService : Service() {
} }
if (queue.get().isNotEmpty() && queue.current() == queue.get() if (queue.get().isNotEmpty() && queue.current() == queue.get()
.last() && radioPlayer.isActive() .last() && radioPlayer.isActive()
) { ) {
scope.launch(IO) { scope.launch(IO) {
if (radioPlayer.lock.tryAcquire()) { if (radioPlayer.lock.tryAcquire()) {

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

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

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

@ -1,8 +1,19 @@
package audio.funkwhale.ffa.repositories package audio.funkwhale.ffa.repositories
import android.content.Context import android.content.Context
import audio.funkwhale.ffa.model.* import audio.funkwhale.ffa.model.FFAResponse
import audio.funkwhale.ffa.utils.* 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.Fuel
import com.github.kittinunf.fuel.coroutines.awaitByteArrayResponseResult import com.github.kittinunf.fuel.coroutines.awaitByteArrayResponseResult
import com.github.kittinunf.fuel.gson.gsonDeserializerOf 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
import android.net.Uri import android.net.Uri
import android.util.Log import android.util.Log
import audio.funkwhale.ffa.model.FFAResponse 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.Fuel
import com.github.kittinunf.fuel.core.FuelError import com.github.kittinunf.fuel.core.FuelError
import com.github.kittinunf.fuel.core.ResponseDeserializable import com.github.kittinunf.fuel.core.ResponseDeserializable

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

@ -1,7 +1,11 @@
package audio.funkwhale.ffa.repositories package audio.funkwhale.ffa.repositories
import android.content.Context 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.OAuth
import audio.funkwhale.ffa.utils.Settings import audio.funkwhale.ffa.utils.Settings
import audio.funkwhale.ffa.utils.authorize import audio.funkwhale.ffa.utils.authorize

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

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

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

@ -1,8 +1,17 @@
package audio.funkwhale.ffa.repositories package audio.funkwhale.ffa.repositories
import android.content.Context import android.content.Context
import audio.funkwhale.ffa.model.* import audio.funkwhale.ffa.model.Album
import audio.funkwhale.ffa.utils.* 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.github.kittinunf.fuel.gson.gsonDeserializerOf
import com.google.android.exoplayer2.offline.DownloadManager import com.google.android.exoplayer2.offline.DownloadManager
import com.google.android.exoplayer2.upstream.cache.Cache 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
import kotlinx.coroutines.runBlocking import kotlinx.coroutines.runBlocking
import net.openid.appauth.ClientSecretPost import net.openid.appauth.ClientSecretPost
import java.text.SimpleDateFormat import java.text.SimpleDateFormat
import java.util.* import java.util.Date
import kotlin.coroutines.CoroutineContext import kotlin.coroutines.CoroutineContext
inline fun <D> Flow<Repository.Response<D>>.untilNetwork( 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")
fun Date.format(): String { fun Date.format(): String {
return ISO_8601_DATE_TIME_FORMAT.format(this) 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)
return FuelResult() return FuelResult()
} }
} }
} }

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

@ -13,7 +13,16 @@ import com.github.kittinunf.fuel.gson.jsonBody
import com.github.kittinunf.result.Result import com.github.kittinunf.result.Result
import com.preference.PowerPreference import com.preference.PowerPreference
import kotlinx.coroutines.runBlocking 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() { fun AuthState.save() {
PowerPreference.getFileByName(AppContext.PREFS_CREDENTIALS).apply { PowerPreference.getFileByName(AppContext.PREFS_CREDENTIALS).apply {
@ -56,11 +65,13 @@ class OAuth(private val authorizationServiceFactory: AuthorizationServiceFactory
fun isAuthorized(context: Context): Boolean { fun isAuthorized(context: Context): Boolean {
val state = tryState() val state = tryState()
return (if (state != null) { return (
state.validAuthorization() || refreshAccessToken(state, context) if (state != null) {
} else { state.validAuthorization() || refreshAccessToken(state, context)
false } else {
}).also { false
}
).also {
it.logInfo("isAuthorized()") it.logInfo("isAuthorized()")
} }
} }

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

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

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

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

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

@ -8,7 +8,10 @@ import audio.funkwhale.ffa.KoinTestApp
import audio.funkwhale.ffa.utils.OAuth import audio.funkwhale.ffa.utils.OAuth
import com.preference.PowerPreference import com.preference.PowerPreference
import com.preference.Preference 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.After
import org.junit.Test import org.junit.Test
import org.junit.runner.RunWith import org.junit.runner.RunWith

Loading…
Cancel
Save