Merge branch 'technical/upgrade-kotlin' into 'develop'
Upgrade to Kotlin 1.7.0 See merge request funkwhale/funkwhale-android!210
This commit is contained in:
commit
6ce043893e
|
@ -153,7 +153,7 @@ play {
|
||||||
dependencies {
|
dependencies {
|
||||||
implementation(fileTree(mapOf("dir" to "libs", "include" to listOf("*.jar", "*.aar"))))
|
implementation(fileTree(mapOf("dir" to "libs", "include" to listOf("*.jar", "*.aar"))))
|
||||||
|
|
||||||
implementation("org.jetbrains.kotlin:kotlin-stdlib-jdk7:1.5.21")
|
implementation("org.jetbrains.kotlin:kotlin-stdlib-jdk7:1.7.10")
|
||||||
implementation("org.jetbrains.kotlinx:kotlinx-coroutines-core:1.6.4")
|
implementation("org.jetbrains.kotlinx:kotlinx-coroutines-core:1.6.4")
|
||||||
implementation("org.jetbrains.kotlinx:kotlinx-coroutines-android:1.6.4")
|
implementation("org.jetbrains.kotlinx:kotlinx-coroutines-android:1.6.4")
|
||||||
|
|
||||||
|
|
|
@ -326,77 +326,67 @@ class MainActivity : AppCompatActivity() {
|
||||||
@SuppressLint("NewApi")
|
@SuppressLint("NewApi")
|
||||||
private fun watchEventBus() {
|
private fun watchEventBus() {
|
||||||
lifecycleScope.launch(Main) {
|
lifecycleScope.launch(Main) {
|
||||||
EventBus.get().collect { message ->
|
EventBus.get().collect { event ->
|
||||||
when (message) {
|
if (event is Event.LogOut) {
|
||||||
is Event.LogOut -> {
|
FFA.get().deleteAllData(this@MainActivity)
|
||||||
FFA.get().deleteAllData(this@MainActivity)
|
startActivity(
|
||||||
startActivity(
|
Intent(this@MainActivity, LoginActivity::class.java).apply {
|
||||||
Intent(this@MainActivity, LoginActivity::class.java).apply {
|
flags = Intent.FLAG_ACTIVITY_NO_HISTORY
|
||||||
flags = Intent.FLAG_ACTIVITY_NO_HISTORY
|
|
||||||
}
|
|
||||||
)
|
|
||||||
|
|
||||||
finish()
|
|
||||||
}
|
|
||||||
|
|
||||||
is Event.PlaybackError -> toast(message.message)
|
|
||||||
|
|
||||||
is Event.Buffering -> {
|
|
||||||
when (message.value) {
|
|
||||||
true -> binding.nowPlayingContainer?.nowPlayingBuffering?.visibility = View.VISIBLE
|
|
||||||
false -> binding.nowPlayingContainer?.nowPlayingBuffering?.visibility = View.GONE
|
|
||||||
}
|
}
|
||||||
}
|
)
|
||||||
|
|
||||||
is Event.PlaybackStopped -> {
|
finish()
|
||||||
if (binding.nowPlaying.visibility == View.VISIBLE) {
|
} else if (event is Event.PlaybackError) {
|
||||||
(binding.container.layoutParams as? ViewGroup.MarginLayoutParams)?.let {
|
toast(event.message)
|
||||||
|
} else if (event is Event.Buffering) {
|
||||||
|
when (event.value) {
|
||||||
|
true -> binding.nowPlayingContainer?.nowPlayingBuffering?.visibility = View.VISIBLE
|
||||||
|
false -> binding.nowPlayingContainer?.nowPlayingBuffering?.visibility = View.GONE
|
||||||
|
}
|
||||||
|
} else if (event is Event.PlaybackStopped) {
|
||||||
|
if (binding.nowPlaying.visibility == View.VISIBLE) {
|
||||||
|
(binding.container.layoutParams as? ViewGroup.MarginLayoutParams)?.let {
|
||||||
|
it.bottomMargin = it.bottomMargin / 2
|
||||||
|
}
|
||||||
|
|
||||||
|
binding.landscapeQueue?.let { landscape_queue ->
|
||||||
|
(landscape_queue.layoutParams as? ViewGroup.MarginLayoutParams)?.let {
|
||||||
it.bottomMargin = it.bottomMargin / 2
|
it.bottomMargin = it.bottomMargin / 2
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
binding.landscapeQueue?.let { landscape_queue ->
|
binding.nowPlaying.animate()
|
||||||
(landscape_queue.layoutParams as? ViewGroup.MarginLayoutParams)?.let {
|
.alpha(0.0f)
|
||||||
it.bottomMargin = it.bottomMargin / 2
|
.setDuration(400)
|
||||||
|
.setListener(object : AnimatorListenerAdapter() {
|
||||||
|
override fun onAnimationEnd(animator: Animator?) {
|
||||||
|
binding.nowPlaying.visibility = View.GONE
|
||||||
}
|
}
|
||||||
}
|
})
|
||||||
|
.start()
|
||||||
|
}
|
||||||
|
} else if (event is Event.TrackFinished) {
|
||||||
|
incrementListenCount(event.track)
|
||||||
|
} else if (event is Event.StateChanged) {
|
||||||
|
when (event.playing) {
|
||||||
|
true -> {
|
||||||
|
binding.nowPlayingContainer?.nowPlayingToggle?.icon = getDrawable(R.drawable.pause)
|
||||||
|
binding.nowPlayingContainer?.nowPlayingDetailsToggle?.icon =
|
||||||
|
getDrawable(R.drawable.pause)
|
||||||
|
}
|
||||||
|
|
||||||
binding.nowPlaying.animate()
|
false -> {
|
||||||
.alpha(0.0f)
|
binding.nowPlayingContainer?.nowPlayingToggle?.icon = getDrawable(R.drawable.play)
|
||||||
.setDuration(400)
|
binding.nowPlayingContainer?.nowPlayingDetailsToggle?.icon =
|
||||||
.setListener(object : AnimatorListenerAdapter() {
|
getDrawable(R.drawable.play)
|
||||||
override fun onAnimationEnd(animator: Animator?) {
|
|
||||||
binding.nowPlaying.visibility = View.GONE
|
|
||||||
}
|
|
||||||
})
|
|
||||||
.start()
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
} else if (event is Event.QueueChanged) {
|
||||||
is Event.TrackFinished -> incrementListenCount(message.track)
|
findViewById<View>(R.id.nav_queue)?.let { view ->
|
||||||
|
ObjectAnimator.ofFloat(view, View.ROTATION, 0f, 360f).let {
|
||||||
is Event.StateChanged -> {
|
it.duration = 500
|
||||||
when (message.playing) {
|
it.interpolator = AccelerateDecelerateInterpolator()
|
||||||
true -> {
|
it.start()
|
||||||
binding.nowPlayingContainer?.nowPlayingToggle?.icon = getDrawable(R.drawable.pause)
|
|
||||||
binding.nowPlayingContainer?.nowPlayingDetailsToggle?.icon =
|
|
||||||
getDrawable(R.drawable.pause)
|
|
||||||
}
|
|
||||||
|
|
||||||
false -> {
|
|
||||||
binding.nowPlayingContainer?.nowPlayingToggle?.icon = getDrawable(R.drawable.play)
|
|
||||||
binding.nowPlayingContainer?.nowPlayingDetailsToggle?.icon =
|
|
||||||
getDrawable(R.drawable.play)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
is Event.QueueChanged -> {
|
|
||||||
findViewById<View>(R.id.nav_queue)?.let { view ->
|
|
||||||
ObjectAnimator.ofFloat(view, View.ROTATION, 0f, 360f).let {
|
|
||||||
it.duration = 500
|
|
||||||
it.interpolator = AccelerateDecelerateInterpolator()
|
|
||||||
it.start()
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -405,32 +395,30 @@ class MainActivity : AppCompatActivity() {
|
||||||
|
|
||||||
lifecycleScope.launch(Main) {
|
lifecycleScope.launch(Main) {
|
||||||
CommandBus.get().collect { command ->
|
CommandBus.get().collect { command ->
|
||||||
when (command) {
|
if (command is Command.StartService) {
|
||||||
is Command.StartService -> {
|
Build.VERSION_CODES.O.onApi(
|
||||||
Build.VERSION_CODES.O.onApi(
|
{
|
||||||
{
|
startForegroundService(
|
||||||
startForegroundService(
|
Intent(
|
||||||
Intent(
|
this@MainActivity,
|
||||||
this@MainActivity,
|
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(
|
||||||
startService(
|
Intent(this@MainActivity, PlayerService::class.java).apply {
|
||||||
Intent(this@MainActivity, PlayerService::class.java).apply {
|
putExtra(PlayerService.INITIAL_COMMAND_KEY, command.command.toString())
|
||||||
putExtra(PlayerService.INITIAL_COMMAND_KEY, command.command.toString())
|
}
|
||||||
}
|
)
|
||||||
)
|
}
|
||||||
}
|
)
|
||||||
)
|
} else if (command is Command.RefreshTrack) {
|
||||||
}
|
refreshCurrentTrack(command.track)
|
||||||
|
} else if (command is Command.AddToPlaylist) {
|
||||||
is Command.RefreshTrack -> refreshCurrentTrack(command.track)
|
if (lifecycle.currentState.isAtLeast(Lifecycle.State.RESUMED)) {
|
||||||
|
|
||||||
is Command.AddToPlaylist -> if (lifecycle.currentState.isAtLeast(Lifecycle.State.RESUMED)) {
|
|
||||||
AddToPlaylistDialog.show(
|
AddToPlaylistDialog.show(
|
||||||
layoutInflater,
|
layoutInflater,
|
||||||
this@MainActivity,
|
this@MainActivity,
|
||||||
|
|
|
@ -28,7 +28,6 @@ import audio.funkwhale.ffa.utils.getMetadata
|
||||||
import audio.funkwhale.ffa.utils.untilNetwork
|
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.launch
|
import kotlinx.coroutines.launch
|
||||||
import kotlinx.coroutines.withContext
|
import kotlinx.coroutines.withContext
|
||||||
import java.net.URLEncoder
|
import java.net.URLEncoder
|
||||||
|
@ -65,8 +64,9 @@ class SearchActivity : AppCompatActivity() {
|
||||||
|
|
||||||
lifecycleScope.launch(Dispatchers.Main) {
|
lifecycleScope.launch(Dispatchers.Main) {
|
||||||
CommandBus.get().collect { command ->
|
CommandBus.get().collect { command ->
|
||||||
when (command) {
|
if (command is Command.AddToPlaylist) {
|
||||||
is Command.AddToPlaylist -> if (lifecycle.currentState.isAtLeast(Lifecycle.State.RESUMED)) {
|
|
||||||
|
if (lifecycle.currentState.isAtLeast(Lifecycle.State.RESUMED)) {
|
||||||
AddToPlaylistDialog.show(
|
AddToPlaylistDialog.show(
|
||||||
layoutInflater,
|
layoutInflater,
|
||||||
this@SearchActivity,
|
this@SearchActivity,
|
||||||
|
@ -79,10 +79,8 @@ class SearchActivity : AppCompatActivity() {
|
||||||
}
|
}
|
||||||
|
|
||||||
lifecycleScope.launch(Dispatchers.IO) {
|
lifecycleScope.launch(Dispatchers.IO) {
|
||||||
EventBus.get().collect { message ->
|
EventBus.get().collect { event ->
|
||||||
when (message) {
|
if (event is Event.DownloadChanged) refreshDownloadedTrack(event.download)
|
||||||
is Event.DownloadChanged -> refreshDownloadedTrack(message.download)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -17,7 +17,6 @@ import audio.funkwhale.ffa.views.LoadingImageView
|
||||||
import com.preference.PowerPreference
|
import com.preference.PowerPreference
|
||||||
import kotlinx.coroutines.CoroutineScope
|
import kotlinx.coroutines.CoroutineScope
|
||||||
import kotlinx.coroutines.Dispatchers.Main
|
import kotlinx.coroutines.Dispatchers.Main
|
||||||
import kotlinx.coroutines.flow.collect
|
|
||||||
import kotlinx.coroutines.launch
|
import kotlinx.coroutines.launch
|
||||||
|
|
||||||
class RadiosAdapter(
|
class RadiosAdapter(
|
||||||
|
@ -190,12 +189,10 @@ class RadiosAdapter(
|
||||||
art.setColorFilter(context.getColor(R.color.controlForeground))
|
art.setColorFilter(context.getColor(R.color.controlForeground))
|
||||||
|
|
||||||
scope.launch(Main) {
|
scope.launch(Main) {
|
||||||
EventBus.get().collect { message ->
|
EventBus.get().collect { event ->
|
||||||
when (message) {
|
if (event is Event.RadioStarted) {
|
||||||
is Event.RadioStarted -> {
|
art.colorFilter = originalColorFilter
|
||||||
art.colorFilter = originalColorFilter
|
LoadingImageView.stop(context, originalDrawable, art, imageAnimator)
|
||||||
LoadingImageView.stop(context, originalDrawable, art, imageAnimator)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -25,7 +25,6 @@ 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
|
||||||
import kotlinx.coroutines.Dispatchers.Main
|
import kotlinx.coroutines.Dispatchers.Main
|
||||||
import kotlinx.coroutines.flow.collect
|
|
||||||
import kotlinx.coroutines.launch
|
import kotlinx.coroutines.launch
|
||||||
import kotlinx.coroutines.withContext
|
import kotlinx.coroutines.withContext
|
||||||
import org.koin.java.KoinJavaComponent.inject
|
import org.koin.java.KoinJavaComponent.inject
|
||||||
|
@ -84,18 +83,14 @@ class FavoritesFragment : FFAFragment<Track, FavoritesAdapter>() {
|
||||||
|
|
||||||
private fun watchEventBus() {
|
private fun watchEventBus() {
|
||||||
lifecycleScope.launch(Main) {
|
lifecycleScope.launch(Main) {
|
||||||
EventBus.get().collect { message ->
|
EventBus.get().collect { event ->
|
||||||
when (message) {
|
if (event is Event.DownloadChanged) refreshDownloadedTrack(event.download)
|
||||||
is Event.DownloadChanged -> refreshDownloadedTrack(message.download)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
lifecycleScope.launch(Main) {
|
lifecycleScope.launch(Main) {
|
||||||
CommandBus.get().collect { command ->
|
CommandBus.get().collect { command ->
|
||||||
when (command) {
|
if (command is Command.RefreshTrack) refreshCurrentTrack(command.track)
|
||||||
is Command.RefreshTrack -> refreshCurrentTrack(command.track)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -110,17 +110,13 @@ class LandscapeQueueFragment : Fragment() {
|
||||||
private fun watchEventBus() {
|
private fun watchEventBus() {
|
||||||
activity?.lifecycleScope?.launch(Main) {
|
activity?.lifecycleScope?.launch(Main) {
|
||||||
EventBus.get().collect { message ->
|
EventBus.get().collect { message ->
|
||||||
when (message) {
|
if (message is Event.QueueChanged) refresh()
|
||||||
is Event.QueueChanged -> refresh()
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
activity?.lifecycleScope?.launch(Main) {
|
activity?.lifecycleScope?.launch(Main) {
|
||||||
CommandBus.get().collect { command ->
|
CommandBus.get().collect { command ->
|
||||||
when (command) {
|
if (command is Command.RefreshTrack) refresh()
|
||||||
is Command.RefreshTrack -> refresh()
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -75,7 +75,12 @@ class PlaylistTracksFragment : FFAFragment<PlaylistTrack, PlaylistTracksAdapter>
|
||||||
favoritesRepository = FavoritesRepository(context)
|
favoritesRepository = FavoritesRepository(context)
|
||||||
playlistsRepository = ManagementPlaylistsRepository(context)
|
playlistsRepository = ManagementPlaylistsRepository(context)
|
||||||
|
|
||||||
adapter = PlaylistTracksAdapter(layoutInflater, context, FavoriteListener(favoritesRepository), PlaylistListener())
|
adapter = PlaylistTracksAdapter(
|
||||||
|
layoutInflater,
|
||||||
|
context,
|
||||||
|
FavoriteListener(favoritesRepository),
|
||||||
|
PlaylistListener()
|
||||||
|
)
|
||||||
repository = PlaylistTracksRepository(context, albumId)
|
repository = PlaylistTracksRepository(context, albumId)
|
||||||
|
|
||||||
watchEventBus()
|
watchEventBus()
|
||||||
|
@ -199,8 +204,8 @@ class PlaylistTracksFragment : FFAFragment<PlaylistTrack, PlaylistTracksAdapter>
|
||||||
private fun watchEventBus() {
|
private fun watchEventBus() {
|
||||||
lifecycleScope.launch(Main) {
|
lifecycleScope.launch(Main) {
|
||||||
CommandBus.get().collect { command ->
|
CommandBus.get().collect { command ->
|
||||||
when (command) {
|
if (command is Command.RefreshTrack) {
|
||||||
is Command.RefreshTrack -> refreshCurrentTrack(command.track)
|
refreshCurrentTrack(command.track)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -127,16 +127,16 @@ class QueueFragment : BottomSheetDialogFragment() {
|
||||||
private fun watchEventBus() {
|
private fun watchEventBus() {
|
||||||
lifecycleScope.launch(Main) {
|
lifecycleScope.launch(Main) {
|
||||||
EventBus.get().collect { message ->
|
EventBus.get().collect { message ->
|
||||||
when (message) {
|
if (message is Event.QueueChanged) {
|
||||||
is Event.QueueChanged -> refresh()
|
refresh()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
lifecycleScope.launch(Main) {
|
lifecycleScope.launch(Main) {
|
||||||
CommandBus.get().collect { command ->
|
CommandBus.get().collect { command ->
|
||||||
when (command) {
|
if (command is Command.RefreshTrack) {
|
||||||
is Command.RefreshTrack -> refresh()
|
refresh()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -62,12 +62,11 @@ class RadiosFragment : FFAFragment<Radio, RadiosAdapter>() {
|
||||||
|
|
||||||
lifecycleScope.launch(Main) {
|
lifecycleScope.launch(Main) {
|
||||||
EventBus.get().collect { message ->
|
EventBus.get().collect { message ->
|
||||||
when (message) {
|
if (message is Event.RadioStarted) {
|
||||||
is Event.RadioStarted ->
|
recycler.forEach {
|
||||||
recycler.forEach {
|
it.isEnabled = true
|
||||||
it.isEnabled = true
|
it.isClickable = true
|
||||||
it.isClickable = true
|
}
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -250,16 +250,16 @@ class TracksFragment : FFAFragment<Track, TracksAdapter>() {
|
||||||
private fun watchEventBus() {
|
private fun watchEventBus() {
|
||||||
lifecycleScope.launch(IO) {
|
lifecycleScope.launch(IO) {
|
||||||
EventBus.get().collect { message ->
|
EventBus.get().collect { message ->
|
||||||
when (message) {
|
if (message is Event.DownloadChanged) {
|
||||||
is Event.DownloadChanged -> refreshDownloadedTrack(message.download)
|
refreshDownloadedTrack(message.download)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
lifecycleScope.launch(Main) {
|
lifecycleScope.launch(Main) {
|
||||||
CommandBus.get().collect { command ->
|
CommandBus.get().collect { command ->
|
||||||
when (command) {
|
if (command is Command.RefreshTrack) {
|
||||||
is Command.RefreshTrack -> refreshCurrentTrack(command.track)
|
refreshCurrentTrack(command.track)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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
|
||||||
|
@ -20,7 +26,7 @@ import kotlinx.coroutines.Dispatchers.Main
|
||||||
import kotlinx.coroutines.Job
|
import kotlinx.coroutines.Job
|
||||||
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) {
|
||||||
|
|
||||||
|
@ -57,8 +63,8 @@ class PinService : DownloadService(AppContext.NOTIFICATION_DOWNLOADS) {
|
||||||
|
|
||||||
scope.launch(Main) {
|
scope.launch(Main) {
|
||||||
RequestBus.get().collect { request ->
|
RequestBus.get().collect { request ->
|
||||||
when (request) {
|
if (request is Request.GetDownloads) {
|
||||||
is Request.GetDownloads -> request.channel?.trySend(Response.Downloads(getDownloads()))?.isSuccess
|
request.channel?.trySend(Response.Downloads(getDownloads()))?.isSuccess
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -171,61 +171,59 @@ class PlayerService : Service() {
|
||||||
private fun watchEventBus() {
|
private fun watchEventBus() {
|
||||||
scope.launch(Main) {
|
scope.launch(Main) {
|
||||||
CommandBus.get().collect { command ->
|
CommandBus.get().collect { command ->
|
||||||
when (command) {
|
if (command is Command.RefreshService) {
|
||||||
is Command.RefreshService -> {
|
if (queue.metadata.isNotEmpty()) {
|
||||||
if (queue.metadata.isNotEmpty()) {
|
|
||||||
CommandBus.send(Command.RefreshTrack(queue.current()))
|
|
||||||
EventBus.send(Event.StateChanged(player.playWhenReady))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
is Command.ReplaceQueue -> {
|
|
||||||
if (!command.fromRadio) radioPlayer.stop()
|
|
||||||
|
|
||||||
queue.replace(command.queue)
|
|
||||||
player.prepare(queue.dataSources, true, true)
|
|
||||||
|
|
||||||
setPlaybackState(true)
|
|
||||||
|
|
||||||
CommandBus.send(Command.RefreshTrack(queue.current()))
|
CommandBus.send(Command.RefreshTrack(queue.current()))
|
||||||
|
EventBus.send(Event.StateChanged(player.playWhenReady))
|
||||||
}
|
}
|
||||||
|
} else if (command is Command.ReplaceQueue) {
|
||||||
|
if (!command.fromRadio) radioPlayer.stop()
|
||||||
|
|
||||||
is Command.AddToQueue -> queue.append(command.tracks)
|
queue.replace(command.queue)
|
||||||
is Command.PlayNext -> queue.insertNext(command.track)
|
player.prepare(queue.dataSources, true, true)
|
||||||
is Command.RemoveFromQueue -> queue.remove(command.track)
|
|
||||||
is Command.MoveFromQueue -> queue.move(command.oldPosition, command.newPosition)
|
|
||||||
|
|
||||||
is Command.PlayTrack -> {
|
setPlaybackState(true)
|
||||||
queue.current = command.index
|
|
||||||
player.seekTo(command.index, C.TIME_UNSET)
|
|
||||||
|
|
||||||
setPlaybackState(true)
|
CommandBus.send(Command.RefreshTrack(queue.current()))
|
||||||
|
} else if (command is Command.AddToQueue) {
|
||||||
|
queue.append(command.tracks)
|
||||||
|
} else if (command is Command.PlayNext) {
|
||||||
|
queue.insertNext(command.track)
|
||||||
|
} else if (command is Command.RemoveFromQueue) {
|
||||||
|
queue.remove(command.track)
|
||||||
|
} else if (command is Command.MoveFromQueue) {
|
||||||
|
queue.move(command.oldPosition, command.newPosition)
|
||||||
|
} else if (command is Command.PlayTrack) {
|
||||||
|
queue.current = command.index
|
||||||
|
player.seekTo(command.index, C.TIME_UNSET)
|
||||||
|
|
||||||
CommandBus.send(Command.RefreshTrack(queue.current()))
|
setPlaybackState(true)
|
||||||
}
|
|
||||||
|
|
||||||
is Command.ToggleState -> togglePlayback()
|
CommandBus.send(Command.RefreshTrack(queue.current()))
|
||||||
is Command.SetState -> setPlaybackState(command.state)
|
} else if (command is Command.ToggleState) {
|
||||||
|
togglePlayback()
|
||||||
is Command.NextTrack -> skipToNextTrack()
|
} else if (command is Command.SetState) {
|
||||||
is Command.PreviousTrack -> skipToPreviousTrack()
|
setPlaybackState(command.state)
|
||||||
is Command.Seek -> seek(command.progress)
|
} else if (command is Command.NextTrack) {
|
||||||
|
skipToNextTrack()
|
||||||
is Command.ClearQueue -> {
|
} else if (command is Command.PreviousTrack) {
|
||||||
queue.clear()
|
skipToPreviousTrack()
|
||||||
player.stop()
|
} else if (command is Command.Seek) {
|
||||||
}
|
seek(command.progress)
|
||||||
is Command.ShuffleQueue -> queue.shuffle()
|
} else if (command is Command.ClearQueue) {
|
||||||
|
queue.clear()
|
||||||
is Command.PlayRadio -> {
|
player.stop()
|
||||||
queue.clear()
|
} else if (command is Command.ShuffleQueue) {
|
||||||
radioPlayer.play(command.radio)
|
queue.shuffle()
|
||||||
}
|
} else if (command is Command.PlayRadio) {
|
||||||
|
queue.clear()
|
||||||
is Command.SetRepeatMode -> player.repeatMode = command.mode
|
radioPlayer.play(command.radio)
|
||||||
|
} else if (command is Command.SetRepeatMode) {
|
||||||
is Command.PinTrack -> PinService.download(this@PlayerService, command.track)
|
player.repeatMode = command.mode
|
||||||
is Command.PinTracks -> command.tracks.forEach {
|
} else if (command is Command.PinTrack) {
|
||||||
|
PinService.download(this@PlayerService, command.track)
|
||||||
|
} else if (command is Command.PinTracks) {
|
||||||
|
command.tracks.forEach {
|
||||||
PinService.download(
|
PinService.download(
|
||||||
this@PlayerService,
|
this@PlayerService,
|
||||||
it
|
it
|
||||||
|
@ -237,10 +235,12 @@ class PlayerService : Service() {
|
||||||
|
|
||||||
scope.launch(Main) {
|
scope.launch(Main) {
|
||||||
RequestBus.get().collect { request ->
|
RequestBus.get().collect { request ->
|
||||||
when (request) {
|
if (request is Request.GetCurrentTrack) {
|
||||||
is Request.GetCurrentTrack -> request.channel?.trySend(Response.CurrentTrack(queue.current()))?.isSuccess
|
request.channel?.trySend(Response.CurrentTrack(queue.current()))?.isSuccess
|
||||||
is Request.GetState -> request.channel?.trySend(Response.State(player.playWhenReady))?.isSuccess
|
} else if (request is Request.GetState) {
|
||||||
is Request.GetQueue -> request.channel?.trySend(Response.Queue(queue.get()))?.isSuccess
|
request.channel?.trySend(Response.State(player.playWhenReady))?.isSuccess
|
||||||
|
} else if (request is Request.GetQueue) {
|
||||||
|
request.channel?.trySend(Response.Queue(queue.get()))?.isSuccess
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,8 +1,16 @@
|
||||||
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.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
|
||||||
|
import audio.funkwhale.ffa.utils.gsonDeserializerOf
|
||||||
|
import audio.funkwhale.ffa.utils.mustNormalizeUrl
|
||||||
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.coroutines.awaitObjectResponseResult
|
import com.github.kittinunf.fuel.coroutines.awaitObjectResponseResult
|
||||||
|
|
|
@ -8,11 +8,9 @@ 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.Flow
|
import kotlinx.coroutines.flow.Flow
|
||||||
import kotlinx.coroutines.flow.collect
|
|
||||||
import kotlinx.coroutines.flow.flow
|
import kotlinx.coroutines.flow.flow
|
||||||
import kotlinx.coroutines.flow.flowOn
|
import kotlinx.coroutines.flow.flowOn
|
||||||
import kotlinx.coroutines.flow.map
|
import kotlinx.coroutines.flow.map
|
||||||
import java.io.BufferedReader
|
|
||||||
import kotlin.math.ceil
|
import kotlin.math.ceil
|
||||||
|
|
||||||
interface Upstream<D> {
|
interface Upstream<D> {
|
||||||
|
|
|
@ -1,7 +1,15 @@
|
||||||
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.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.OAuth
|
||||||
import audio.funkwhale.ffa.utils.gsonDeserializerOf
|
import audio.funkwhale.ffa.utils.gsonDeserializerOf
|
||||||
import audio.funkwhale.ffa.utils.mustNormalizeUrl
|
import audio.funkwhale.ffa.utils.mustNormalizeUrl
|
||||||
|
|
|
@ -25,7 +25,7 @@ import kotlinx.coroutines.runBlocking
|
||||||
import net.openid.appauth.ClientSecretPost
|
import net.openid.appauth.ClientSecretPost
|
||||||
import java.io.Reader
|
import java.io.Reader
|
||||||
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(
|
||||||
|
@ -82,7 +82,7 @@ fun Request.authorize(context: Context, oAuth: OAuth): Request {
|
||||||
|
|
||||||
state.performActionWithFreshTokens(tokenService, auth) { token, _, e ->
|
state.performActionWithFreshTokens(tokenService, auth) { token, _, e ->
|
||||||
if (e != null) {
|
if (e != null) {
|
||||||
Log.e("Request.authorize()", "performActionWithFreshToken failed: ${e}")
|
Log.e("Request.authorize()", "performActionWithFreshToken failed: $e")
|
||||||
Log.e("Request.authorize()", Log.getStackTraceString(e))
|
Log.e("Request.authorize()", Log.getStackTraceString(e))
|
||||||
}
|
}
|
||||||
if (token == old) {
|
if (token == old) {
|
||||||
|
|
|
@ -15,7 +15,7 @@ object FFACache {
|
||||||
return digest.fold("") { acc, it -> acc + "%02x".format(it) }
|
return digest.fold("") { acc, it -> acc + "%02x".format(it) }
|
||||||
}
|
}
|
||||||
|
|
||||||
fun set(context: Context?, key:String, value: String){
|
fun set(context: Context?, key: String, value: String) {
|
||||||
set(context, key, value.toByteArray())
|
set(context, key, value.toByteArray())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -71,9 +71,8 @@ class OAuth(private val authorizationServiceFactory: AuthorizationServiceFactory
|
||||||
} else {
|
} else {
|
||||||
false
|
false
|
||||||
}
|
}
|
||||||
).also {
|
)
|
||||||
it.logInfo("isAuthorized()")
|
.also { it.logInfo("isAuthorized()") }
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun AuthState.validAuthorization() = this.isAuthorized && !this.needsTokenRefresh
|
private fun AuthState.validAuthorization() = this.isAuthorized && !this.needsTokenRefresh
|
||||||
|
@ -102,7 +101,7 @@ class OAuth(private val authorizationServiceFactory: AuthorizationServiceFactory
|
||||||
runBlocking {
|
runBlocking {
|
||||||
refreshService.performTokenRequest(refreshRequest, auth) { response, e ->
|
refreshService.performTokenRequest(refreshRequest, auth) { response, e ->
|
||||||
if (e != null) {
|
if (e != null) {
|
||||||
Log.e("OAuth", "performTokenRequest failed: ${e}")
|
Log.e("OAuth", "performTokenRequest failed: $e")
|
||||||
Log.e("OAuth", Log.getStackTraceString(e))
|
Log.e("OAuth", Log.getStackTraceString(e))
|
||||||
} else {
|
} else {
|
||||||
state.apply {
|
state.apply {
|
||||||
|
@ -213,13 +212,13 @@ class OAuth(private val authorizationServiceFactory: AuthorizationServiceFactory
|
||||||
|
|
||||||
requestService.performTokenRequest(it.createTokenExchangeRequest(), auth) { response, e ->
|
requestService.performTokenRequest(it.createTokenExchangeRequest(), auth) { response, e ->
|
||||||
if (e != null) {
|
if (e != null) {
|
||||||
Log.e("FFA", "performTokenRequest failed: ${e}")
|
Log.e("FFA", "performTokenRequest failed: $e")
|
||||||
Log.e("FFA", Log.getStackTraceString(e))
|
Log.e("FFA", Log.getStackTraceString(e))
|
||||||
} else {
|
} else {
|
||||||
state.apply {
|
state.apply {
|
||||||
update(response, e)
|
update(response, e)
|
||||||
save()
|
save()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (response != null) success()
|
if (response != null) success()
|
||||||
|
|
|
@ -8,7 +8,7 @@ buildscript {
|
||||||
|
|
||||||
dependencies {
|
dependencies {
|
||||||
classpath("com.android.tools.build:gradle:7.2.2")
|
classpath("com.android.tools.build:gradle:7.2.2")
|
||||||
classpath("org.jetbrains.kotlin:kotlin-gradle-plugin:1.5.21")
|
classpath("org.jetbrains.kotlin:kotlin-gradle-plugin:1.7.10")
|
||||||
classpath("com.github.bjoernq:unmockplugin:0.7.9")
|
classpath("com.github.bjoernq:unmockplugin:0.7.9")
|
||||||
classpath("com.github.ben-manes:gradle-versions-plugin:0.42.0")
|
classpath("com.github.ben-manes:gradle-versions-plugin:0.42.0")
|
||||||
classpath("org.jacoco:org.jacoco.core:0.8.7")
|
classpath("org.jacoco:org.jacoco.core:0.8.7")
|
||||||
|
|
Loading…
Reference in New Issue