mirror of
https://github.com/clangen/musikcube.git
synced 2024-10-02 13:02:35 +00:00
Added context menu to PlayQueueActivity and PlayQueueAdapter.
This commit is contained in:
parent
a573265092
commit
93f1980b77
@ -3,13 +3,13 @@ package io.casey.musikcube.remote
|
||||
import android.arch.persistence.room.Room
|
||||
import com.crashlytics.android.Crashlytics
|
||||
import com.facebook.stetho.Stetho
|
||||
import io.casey.musikcube.remote.ui.settings.model.ConnectionsDb
|
||||
import io.casey.musikcube.remote.service.playback.impl.streaming.offline.OfflineDb
|
||||
import io.casey.musikcube.remote.injection.DaggerAppComponent
|
||||
import io.casey.musikcube.remote.injection.AppComponent
|
||||
import io.casey.musikcube.remote.injection.AppModule
|
||||
import io.casey.musikcube.remote.injection.DaggerAppComponent
|
||||
import io.casey.musikcube.remote.injection.ServiceModule
|
||||
import io.casey.musikcube.remote.service.playback.impl.streaming.StreamProxy
|
||||
import io.casey.musikcube.remote.service.playback.impl.streaming.offline.OfflineDb
|
||||
import io.casey.musikcube.remote.ui.settings.model.ConnectionsDb
|
||||
import io.casey.musikcube.remote.ui.shared.util.NetworkUtil
|
||||
import io.fabric.sdk.android.Fabric
|
||||
|
||||
|
@ -2,14 +2,12 @@ package io.casey.musikcube.remote.injection
|
||||
|
||||
import dagger.Module
|
||||
import dagger.Provides
|
||||
import io.casey.musikcube.remote.service.websocket.model.IDataProvider
|
||||
import io.casey.musikcube.remote.model.impl.remote.RemoteDataProvider
|
||||
import io.casey.musikcube.remote.service.websocket.WebSocketService
|
||||
import io.casey.musikcube.remote.service.websocket.model.IDataProvider
|
||||
import io.casey.musikcube.remote.service.websocket.model.impl.remote.RemoteDataProvider
|
||||
|
||||
@Module
|
||||
class DataModule {
|
||||
@Provides
|
||||
fun providesDataProvider(wss: WebSocketService): IDataProvider {
|
||||
return RemoteDataProvider(wss)
|
||||
}
|
||||
fun providesDataProvider(wss: WebSocketService): IDataProvider = RemoteDataProvider(wss)
|
||||
}
|
@ -11,9 +11,9 @@ import com.bumptech.glide.load.model.GlideUrl
|
||||
import com.bumptech.glide.module.AppGlideModule
|
||||
import io.casey.musikcube.remote.ui.settings.constants.Prefs
|
||||
import okhttp3.*
|
||||
import java.io.InputStream
|
||||
import io.casey.musikcube.remote.ui.shared.model.albumart.canIntercept as canInterceptArtwork
|
||||
import io.casey.musikcube.remote.ui.shared.model.albumart.intercept as interceptArtwork
|
||||
import java.io.InputStream
|
||||
|
||||
@GlideModule
|
||||
class GlideModule : AppGlideModule() {
|
||||
|
@ -1,17 +1,17 @@
|
||||
package io.casey.musikcube.remote.injection
|
||||
|
||||
import dagger.Component
|
||||
import io.casey.musikcube.remote.ui.home.activity.MainActivity
|
||||
import io.casey.musikcube.remote.ui.category.activity.*
|
||||
import io.casey.musikcube.remote.ui.albums.activity.AlbumBrowseActivity
|
||||
import io.casey.musikcube.remote.ui.playqueue.activity.PlayQueueActivity
|
||||
import io.casey.musikcube.remote.ui.shared.activity.BaseActivity
|
||||
import io.casey.musikcube.remote.ui.shared.view.EmptyListView
|
||||
import io.casey.musikcube.remote.ui.category.activity.CategoryBrowseActivity
|
||||
import io.casey.musikcube.remote.ui.home.activity.MainActivity
|
||||
import io.casey.musikcube.remote.ui.home.view.MainMetadataView
|
||||
import io.casey.musikcube.remote.ui.playqueue.activity.PlayQueueActivity
|
||||
import io.casey.musikcube.remote.ui.settings.activity.ConnectionsActivity
|
||||
import io.casey.musikcube.remote.ui.settings.activity.SettingsActivity
|
||||
import io.casey.musikcube.remote.ui.shared.activity.BaseActivity
|
||||
import io.casey.musikcube.remote.ui.shared.mixin.DataProviderMixin
|
||||
import io.casey.musikcube.remote.ui.shared.mixin.ItemContextMenuMixin
|
||||
import io.casey.musikcube.remote.ui.shared.view.EmptyListView
|
||||
import io.casey.musikcube.remote.ui.tracks.activity.TrackListActivity
|
||||
|
||||
@ViewScope
|
||||
|
@ -1,10 +1,10 @@
|
||||
package io.casey.musikcube.remote.service.playback
|
||||
|
||||
import io.casey.musikcube.remote.Application
|
||||
import io.casey.musikcube.remote.service.websocket.model.ITrack
|
||||
import io.casey.musikcube.remote.service.playback.impl.streaming.offline.OfflineTrack
|
||||
import io.casey.musikcube.remote.service.playback.impl.player.ExoPlayerWrapper
|
||||
import io.casey.musikcube.remote.service.playback.impl.player.MediaPlayerWrapper
|
||||
import io.casey.musikcube.remote.service.playback.impl.streaming.offline.OfflineTrack
|
||||
import io.casey.musikcube.remote.service.websocket.model.ITrack
|
||||
import io.casey.musikcube.remote.util.Preconditions
|
||||
import io.reactivex.Single
|
||||
import io.reactivex.android.schedulers.AndroidSchedulers
|
||||
|
@ -21,12 +21,12 @@ import com.google.android.exoplayer2.upstream.DefaultBandwidthMeter
|
||||
import com.google.android.exoplayer2.upstream.DefaultDataSourceFactory
|
||||
import com.google.android.exoplayer2.util.Util
|
||||
import io.casey.musikcube.remote.Application
|
||||
import io.casey.musikcube.remote.service.websocket.model.ITrack
|
||||
import io.casey.musikcube.remote.service.playback.PlayerWrapper
|
||||
import io.casey.musikcube.remote.service.playback.impl.streaming.StreamProxy
|
||||
import io.casey.musikcube.remote.service.websocket.model.ITrack
|
||||
import io.casey.musikcube.remote.ui.settings.constants.Prefs
|
||||
import io.casey.musikcube.remote.ui.shared.util.NetworkUtil
|
||||
import io.casey.musikcube.remote.util.Preconditions
|
||||
import io.casey.musikcube.remote.ui.settings.constants.Prefs
|
||||
import okhttp3.Cache
|
||||
import okhttp3.OkHttpClient
|
||||
import java.io.File
|
||||
|
@ -9,11 +9,11 @@ import android.os.PowerManager
|
||||
import android.util.Base64
|
||||
import android.util.Log
|
||||
import io.casey.musikcube.remote.Application
|
||||
import io.casey.musikcube.remote.service.websocket.model.ITrack
|
||||
import io.casey.musikcube.remote.service.playback.PlayerWrapper
|
||||
import io.casey.musikcube.remote.service.playback.impl.streaming.StreamProxy
|
||||
import io.casey.musikcube.remote.util.Preconditions
|
||||
import io.casey.musikcube.remote.service.websocket.model.ITrack
|
||||
import io.casey.musikcube.remote.ui.settings.constants.Prefs
|
||||
import io.casey.musikcube.remote.util.Preconditions
|
||||
import java.io.IOException
|
||||
import java.util.*
|
||||
|
||||
|
@ -4,7 +4,6 @@ import android.os.Handler
|
||||
import io.casey.musikcube.remote.Application
|
||||
import io.casey.musikcube.remote.injection.DaggerServiceComponent
|
||||
import io.casey.musikcube.remote.injection.DataModule
|
||||
import io.casey.musikcube.remote.model.impl.remote.RemoteTrack
|
||||
import io.casey.musikcube.remote.service.playback.IPlaybackService
|
||||
import io.casey.musikcube.remote.service.playback.PlaybackState
|
||||
import io.casey.musikcube.remote.service.playback.RepeatMode
|
||||
@ -13,6 +12,7 @@ import io.casey.musikcube.remote.service.websocket.SocketMessage
|
||||
import io.casey.musikcube.remote.service.websocket.WebSocketService
|
||||
import io.casey.musikcube.remote.service.websocket.model.IDataProvider
|
||||
import io.casey.musikcube.remote.service.websocket.model.ITrack
|
||||
import io.casey.musikcube.remote.service.websocket.model.impl.remote.RemoteTrack
|
||||
import io.casey.musikcube.remote.ui.shared.model.TrackListSlidingWindow
|
||||
import io.reactivex.Observable
|
||||
import org.json.JSONObject
|
||||
|
@ -8,9 +8,9 @@ import com.danikula.videocache.CacheListener
|
||||
import com.danikula.videocache.HttpProxyCacheServer
|
||||
import com.danikula.videocache.file.Md5FileNameGenerator
|
||||
import io.casey.musikcube.remote.Application
|
||||
import io.casey.musikcube.remote.ui.settings.constants.Prefs
|
||||
import io.casey.musikcube.remote.ui.shared.util.NetworkUtil
|
||||
import io.casey.musikcube.remote.util.Strings
|
||||
import io.casey.musikcube.remote.ui.settings.constants.Prefs
|
||||
import java.io.File
|
||||
import java.util.*
|
||||
|
||||
|
@ -12,7 +12,6 @@ import io.casey.musikcube.remote.Application
|
||||
import io.casey.musikcube.remote.R
|
||||
import io.casey.musikcube.remote.injection.DaggerServiceComponent
|
||||
import io.casey.musikcube.remote.injection.DataModule
|
||||
import io.casey.musikcube.remote.model.impl.remote.RemoteTrack
|
||||
import io.casey.musikcube.remote.service.playback.IPlaybackService
|
||||
import io.casey.musikcube.remote.service.playback.PlaybackState
|
||||
import io.casey.musikcube.remote.service.playback.PlayerWrapper
|
||||
@ -21,6 +20,7 @@ import io.casey.musikcube.remote.service.system.SystemService
|
||||
import io.casey.musikcube.remote.service.websocket.Messages
|
||||
import io.casey.musikcube.remote.service.websocket.model.IDataProvider
|
||||
import io.casey.musikcube.remote.service.websocket.model.ITrack
|
||||
import io.casey.musikcube.remote.service.websocket.model.impl.remote.RemoteTrack
|
||||
import io.casey.musikcube.remote.ui.settings.constants.Prefs
|
||||
import io.casey.musikcube.remote.ui.shared.model.TrackListSlidingWindow
|
||||
import io.casey.musikcube.remote.util.Strings
|
||||
|
@ -5,10 +5,10 @@ import android.arch.persistence.room.RoomDatabase
|
||||
import io.casey.musikcube.remote.Application
|
||||
import io.casey.musikcube.remote.injection.DaggerDataComponent
|
||||
import io.casey.musikcube.remote.service.playback.impl.streaming.StreamProxy
|
||||
import io.casey.musikcube.remote.util.Strings
|
||||
import io.casey.musikcube.remote.service.websocket.Messages
|
||||
import io.casey.musikcube.remote.service.websocket.SocketMessage
|
||||
import io.casey.musikcube.remote.service.websocket.WebSocketService
|
||||
import io.casey.musikcube.remote.util.Strings
|
||||
import io.reactivex.Single
|
||||
import io.reactivex.android.schedulers.AndroidSchedulers
|
||||
import io.reactivex.schedulers.Schedulers
|
||||
@ -22,6 +22,7 @@ abstract class OfflineDb : RoomDatabase() {
|
||||
@Inject lateinit var wss: WebSocketService
|
||||
|
||||
init {
|
||||
|
||||
DaggerDataComponent.builder()
|
||||
.appComponent(Application.appComponent)
|
||||
.build().inject(this)
|
||||
|
@ -21,19 +21,19 @@ import com.bumptech.glide.request.target.SimpleTarget
|
||||
import com.bumptech.glide.request.target.Target
|
||||
import com.bumptech.glide.request.transition.Transition
|
||||
import io.casey.musikcube.remote.Application
|
||||
import io.casey.musikcube.remote.ui.home.activity.MainActivity
|
||||
import io.casey.musikcube.remote.R
|
||||
import io.casey.musikcube.remote.injection.GlideApp
|
||||
import io.casey.musikcube.remote.injection.GlideRequest
|
||||
import io.casey.musikcube.remote.service.websocket.model.ITrack
|
||||
import io.casey.musikcube.remote.service.playback.PlaybackServiceFactory
|
||||
import io.casey.musikcube.remote.service.playback.PlaybackState
|
||||
import io.casey.musikcube.remote.service.playback.impl.streaming.StreamingPlaybackService
|
||||
import io.casey.musikcube.remote.service.websocket.model.ITrack
|
||||
import io.casey.musikcube.remote.ui.home.activity.MainActivity
|
||||
import io.casey.musikcube.remote.ui.settings.constants.Prefs
|
||||
import io.casey.musikcube.remote.ui.shared.extension.fallback
|
||||
import io.casey.musikcube.remote.ui.shared.model.albumart.Size
|
||||
import io.casey.musikcube.remote.util.Debouncer
|
||||
import io.casey.musikcube.remote.util.Strings
|
||||
import io.casey.musikcube.remote.ui.settings.constants.Prefs
|
||||
import android.support.v4.app.NotificationCompat.Action as NotifAction
|
||||
import io.casey.musikcube.remote.ui.shared.model.albumart.getUrl as getAlbumArtUrl
|
||||
|
||||
|
@ -1,8 +1,8 @@
|
||||
package io.casey.musikcube.remote.model.impl.remote
|
||||
package io.casey.musikcube.remote.service.websocket.model.impl.remote
|
||||
|
||||
import io.casey.musikcube.remote.service.websocket.model.IAlbum
|
||||
import io.casey.musikcube.remote.service.playback.impl.remote.Metadata
|
||||
import io.casey.musikcube.remote.service.websocket.Messages
|
||||
import io.casey.musikcube.remote.service.websocket.model.IAlbum
|
||||
import org.json.JSONObject
|
||||
|
||||
class RemoteAlbum(val json: JSONObject) : IAlbum {
|
||||
|
@ -1,7 +1,7 @@
|
||||
package io.casey.musikcube.remote.model.impl.remote
|
||||
package io.casey.musikcube.remote.service.websocket.model.impl.remote
|
||||
|
||||
import io.casey.musikcube.remote.service.websocket.model.IAlbumArtist
|
||||
import io.casey.musikcube.remote.service.websocket.Messages
|
||||
import io.casey.musikcube.remote.service.websocket.model.IAlbumArtist
|
||||
import org.json.JSONObject
|
||||
|
||||
class RemoteAlbumArtist(private val json: JSONObject) : IAlbumArtist {
|
||||
|
@ -1,7 +1,7 @@
|
||||
package io.casey.musikcube.remote.model.impl.remote
|
||||
package io.casey.musikcube.remote.service.websocket.model.impl.remote
|
||||
|
||||
import io.casey.musikcube.remote.service.websocket.model.ICategoryValue
|
||||
import io.casey.musikcube.remote.service.websocket.Messages
|
||||
import io.casey.musikcube.remote.service.websocket.model.ICategoryValue
|
||||
import org.json.JSONObject
|
||||
|
||||
class RemoteCategoryValue(private val categoryType: String,
|
||||
|
@ -1,4 +1,4 @@
|
||||
package io.casey.musikcube.remote.model.impl.remote
|
||||
package io.casey.musikcube.remote.service.websocket.model.impl.remote
|
||||
|
||||
import io.casey.musikcube.remote.service.websocket.Messages
|
||||
import io.casey.musikcube.remote.service.websocket.SocketMessage
|
||||
@ -33,9 +33,8 @@ class RemoteDataProvider(private val service: WebSocketService) : IDataProvider
|
||||
override val state: IDataProvider.State
|
||||
get() = currentState
|
||||
|
||||
override fun getAlbums(filter: String): Observable<List<IAlbum>> {
|
||||
return getAlbumsForCategory("", 0, filter)
|
||||
}
|
||||
override fun getAlbums(filter: String): Observable<List<IAlbum>> =
|
||||
getAlbumsForCategory("", 0, filter)
|
||||
|
||||
override fun getAlbumsForCategory(categoryType: String, categoryId: Long, filter: String): Observable<List<IAlbum>> {
|
||||
val message = SocketMessage.Builder
|
||||
@ -100,9 +99,8 @@ class RemoteDataProvider(private val service: WebSocketService) : IDataProvider
|
||||
.observeOn(AndroidSchedulers.mainThread())
|
||||
}
|
||||
|
||||
override fun getTracks(filter: String): Observable<List<ITrack>> {
|
||||
return getTracks(-1, -1, filter)
|
||||
}
|
||||
override fun getTracks(filter: String): Observable<List<ITrack>> =
|
||||
getTracks(-1, -1, filter)
|
||||
|
||||
override fun getTrackCountByCategory(category: String, id: Long, filter: String): Observable<Int> {
|
||||
val message = SocketMessage.Builder
|
||||
@ -118,9 +116,8 @@ class RemoteDataProvider(private val service: WebSocketService) : IDataProvider
|
||||
.observeOn(AndroidSchedulers.mainThread())
|
||||
}
|
||||
|
||||
override fun getTracksByCategory(category: String, id: Long, filter: String): Observable<List<ITrack>> {
|
||||
return getTracksByCategory(category, id, -1, -1, filter)
|
||||
}
|
||||
override fun getTracksByCategory(category: String, id: Long, filter: String): Observable<List<ITrack>> =
|
||||
getTracksByCategory(category, id, -1, -1, filter)
|
||||
|
||||
override fun getTracksByCategory(category: String, id: Long, limit: Int, offset: Int, filter: String): Observable<List<ITrack>> {
|
||||
val builder = SocketMessage.Builder
|
||||
@ -152,9 +149,8 @@ class RemoteDataProvider(private val service: WebSocketService) : IDataProvider
|
||||
.observeOn(AndroidSchedulers.mainThread())
|
||||
}
|
||||
|
||||
override fun getPlayQueueTracks(filter: String): Observable<List<ITrack>> {
|
||||
return getPlayQueueTracks(-1, -1, filter)
|
||||
}
|
||||
override fun getPlayQueueTracks(filter: String): Observable<List<ITrack>> =
|
||||
getPlayQueueTracks(-1, -1, filter)
|
||||
|
||||
override fun getPlayQueueTracks(limit: Int, offset: Int, filter: String): Observable<List<ITrack>> {
|
||||
val builder = SocketMessage.Builder
|
||||
@ -360,17 +356,14 @@ class RemoteDataProvider(private val service: WebSocketService) : IDataProvider
|
||||
.observeOn(AndroidSchedulers.mainThread())
|
||||
}
|
||||
|
||||
override fun observeState(): Observable<Pair<IDataProvider.State, IDataProvider.State>> {
|
||||
return connectionStatePublisher.observeOn(AndroidSchedulers.mainThread())
|
||||
}
|
||||
override fun observeState(): Observable<Pair<IDataProvider.State, IDataProvider.State>> =
|
||||
connectionStatePublisher.observeOn(AndroidSchedulers.mainThread())
|
||||
|
||||
override fun observePlayQueue(): Observable<Unit> {
|
||||
return playQueueStatePublisher.observeOn(AndroidSchedulers.mainThread())
|
||||
}
|
||||
override fun observePlayQueue(): Observable<Unit> =
|
||||
playQueueStatePublisher.observeOn(AndroidSchedulers.mainThread())
|
||||
|
||||
override fun observeAuthFailure(): Observable<Unit> {
|
||||
return authFailurePublisher.observeOn(AndroidSchedulers.mainThread())
|
||||
}
|
||||
override fun observeAuthFailure(): Observable<Unit> =
|
||||
authFailurePublisher.observeOn(AndroidSchedulers.mainThread())
|
||||
|
||||
override fun attach() {
|
||||
service.addClient(client)
|
||||
@ -404,13 +397,12 @@ class RemoteDataProvider(private val service: WebSocketService) : IDataProvider
|
||||
}
|
||||
}
|
||||
|
||||
private fun mapState(state: WebSocketService.State): IDataProvider.State {
|
||||
return when (state) {
|
||||
private fun mapState(state: WebSocketService.State): IDataProvider.State =
|
||||
when (state) {
|
||||
WebSocketService.State.Disconnected -> IDataProvider.State.Disconnected
|
||||
WebSocketService.State.Connecting -> IDataProvider.State.Connecting
|
||||
WebSocketService.State.Connected -> IDataProvider.State.Connected
|
||||
}
|
||||
}
|
||||
|
||||
companion object {
|
||||
private fun createTrackListSubquery(categoryType: String, categoryId: Long, filter: String): JSONObject {
|
||||
|
@ -1,7 +1,7 @@
|
||||
package io.casey.musikcube.remote.model.impl.remote
|
||||
package io.casey.musikcube.remote.service.websocket.model.impl.remote
|
||||
|
||||
import io.casey.musikcube.remote.service.websocket.model.IPlaylist
|
||||
import io.casey.musikcube.remote.service.websocket.Messages
|
||||
import io.casey.musikcube.remote.service.websocket.model.IPlaylist
|
||||
import org.json.JSONObject
|
||||
|
||||
class RemotePlaylist(private val json: JSONObject) : IPlaylist {
|
||||
|
@ -1,8 +1,8 @@
|
||||
package io.casey.musikcube.remote.model.impl.remote
|
||||
package io.casey.musikcube.remote.service.websocket.model.impl.remote
|
||||
|
||||
import io.casey.musikcube.remote.service.websocket.model.ITrack
|
||||
import io.casey.musikcube.remote.service.playback.impl.remote.Metadata
|
||||
import io.casey.musikcube.remote.service.websocket.Messages
|
||||
import io.casey.musikcube.remote.service.websocket.model.ITrack
|
||||
import org.json.JSONObject
|
||||
|
||||
class RemoteTrack(val json: JSONObject) : ITrack {
|
||||
|
@ -32,11 +32,11 @@ import io.casey.musikcube.remote.ui.playqueue.activity.PlayQueueActivity
|
||||
import io.casey.musikcube.remote.ui.settings.activity.SettingsActivity
|
||||
import io.casey.musikcube.remote.ui.settings.constants.Prefs
|
||||
import io.casey.musikcube.remote.ui.shared.activity.BaseActivity
|
||||
import io.casey.musikcube.remote.ui.shared.mixin.DataProviderMixin
|
||||
import io.casey.musikcube.remote.ui.shared.mixin.PlaybackMixin
|
||||
import io.casey.musikcube.remote.ui.shared.extension.getColorCompat
|
||||
import io.casey.musikcube.remote.ui.shared.extension.setCheckWithoutEvent
|
||||
import io.casey.musikcube.remote.ui.shared.extension.showSnackbar
|
||||
import io.casey.musikcube.remote.ui.shared.mixin.DataProviderMixin
|
||||
import io.casey.musikcube.remote.ui.shared.mixin.PlaybackMixin
|
||||
import io.casey.musikcube.remote.ui.shared.util.Duration
|
||||
import io.casey.musikcube.remote.ui.shared.util.UpdateCheck
|
||||
import io.casey.musikcube.remote.ui.tracks.activity.TrackListActivity
|
||||
|
@ -3,41 +3,52 @@ package io.casey.musikcube.remote.ui.playqueue.activity
|
||||
import android.content.Context
|
||||
import android.content.Intent
|
||||
import android.os.Bundle
|
||||
import android.support.v7.widget.RecyclerView
|
||||
import android.view.LayoutInflater
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import android.widget.TextView
|
||||
import com.simplecityapps.recyclerview_fastscroll.views.FastScrollRecyclerView
|
||||
import io.casey.musikcube.remote.R
|
||||
import io.casey.musikcube.remote.service.websocket.model.IDataProvider
|
||||
import io.casey.musikcube.remote.service.websocket.model.ITrack
|
||||
import io.casey.musikcube.remote.ui.playqueue.adapter.PlayQueueAdapter
|
||||
import io.casey.musikcube.remote.ui.shared.activity.BaseActivity
|
||||
import io.casey.musikcube.remote.ui.shared.extension.*
|
||||
import io.casey.musikcube.remote.ui.shared.extension.addTransportFragment
|
||||
import io.casey.musikcube.remote.ui.shared.extension.enableUpNavigation
|
||||
import io.casey.musikcube.remote.ui.shared.extension.setTitleFromIntent
|
||||
import io.casey.musikcube.remote.ui.shared.extension.setupDefaultRecyclerView
|
||||
import io.casey.musikcube.remote.ui.shared.mixin.DataProviderMixin
|
||||
import io.casey.musikcube.remote.ui.shared.mixin.ItemContextMenuMixin
|
||||
import io.casey.musikcube.remote.ui.shared.mixin.PlaybackMixin
|
||||
import io.casey.musikcube.remote.ui.shared.model.TrackListSlidingWindow
|
||||
import io.casey.musikcube.remote.ui.shared.view.EmptyListView
|
||||
import io.reactivex.rxkotlin.subscribeBy
|
||||
|
||||
class PlayQueueActivity : BaseActivity() {
|
||||
private var adapter: Adapter = Adapter()
|
||||
private var offlineQueue: Boolean = false
|
||||
private lateinit var data: DataProviderMixin
|
||||
private lateinit var playback: PlaybackMixin
|
||||
private lateinit var tracks: TrackListSlidingWindow
|
||||
private lateinit var adapter: PlayQueueAdapter
|
||||
private lateinit var emptyView: EmptyListView
|
||||
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
component.inject(this)
|
||||
|
||||
data = mixin(DataProviderMixin())
|
||||
playback = mixin(PlaybackMixin(playbackEvents))
|
||||
mixin(ItemContextMenuMixin(this))
|
||||
|
||||
super.onCreate(savedInstanceState)
|
||||
|
||||
setContentView(R.layout.recycler_view_activity)
|
||||
|
||||
val queryFactory = playback.service.playlistQueryFactory
|
||||
offlineQueue = playback.service.playlistQueryFactory.offline()
|
||||
|
||||
val recyclerView = findViewById<FastScrollRecyclerView>(R.id.recycler_view)
|
||||
tracks = TrackListSlidingWindow(recyclerView, data.provider, queryFactory)
|
||||
tracks.setInitialPosition(intent.getIntExtra(EXTRA_PLAYING_INDEX, -1))
|
||||
tracks.setOnMetadataLoadedListener(slidingWindowListener)
|
||||
adapter = PlayQueueAdapter(tracks, playback, adapterListener)
|
||||
|
||||
setupDefaultRecyclerView(recyclerView, adapter)
|
||||
|
||||
emptyView = findViewById(R.id.empty_list_view)
|
||||
@ -45,13 +56,6 @@ class PlayQueueActivity : BaseActivity() {
|
||||
emptyView.emptyMessage = getString(R.string.play_queue_empty)
|
||||
emptyView.alternateView = recyclerView
|
||||
|
||||
val queryFactory = playback.service.playlistQueryFactory
|
||||
offlineQueue = playback.service.playlistQueryFactory.offline()
|
||||
|
||||
tracks = TrackListSlidingWindow(recyclerView, data.provider, queryFactory)
|
||||
tracks.setInitialPosition(intent.getIntExtra(EXTRA_PLAYING_INDEX, -1))
|
||||
tracks.setOnMetadataLoadedListener(slidingWindowListener)
|
||||
|
||||
data.provider.observeState().subscribeBy(
|
||||
onNext = { states ->
|
||||
if (states.first == IDataProvider.State.Connected) {
|
||||
@ -84,9 +88,12 @@ class PlayQueueActivity : BaseActivity() {
|
||||
}
|
||||
}
|
||||
|
||||
private val onItemClickListener = View.OnClickListener { v ->
|
||||
if (v.tag is Int) {
|
||||
playback.service.playAt(v.tag as Int)
|
||||
private val adapterListener = object: PlayQueueAdapter.EventListener {
|
||||
override fun onItemClicked(position: Int) =
|
||||
playback.service.playAt(position)
|
||||
|
||||
override fun onActionClicked(view: View, value: ITrack) {
|
||||
mixin(ItemContextMenuMixin::class.java)?.showForTrack(value, view)
|
||||
}
|
||||
}
|
||||
|
||||
@ -97,61 +104,11 @@ class PlayQueueActivity : BaseActivity() {
|
||||
adapter.notifyDataSetChanged()
|
||||
}
|
||||
|
||||
private inner class ViewHolder internal constructor(itemView: View) : RecyclerView.ViewHolder(itemView) {
|
||||
private val title: TextView = itemView.findViewById(R.id.title)
|
||||
private val subtitle: TextView = itemView.findViewById(R.id.subtitle)
|
||||
private val trackNum: TextView = itemView.findViewById(R.id.track_num)
|
||||
|
||||
internal fun bind(track: ITrack?, position: Int) {
|
||||
trackNum.text = (position + 1).toString()
|
||||
itemView.tag = position
|
||||
var titleColor = R.color.theme_foreground
|
||||
var subtitleColor = R.color.theme_disabled_foreground
|
||||
|
||||
if (track == null) {
|
||||
title.text = "-"
|
||||
subtitle.text = "-"
|
||||
}
|
||||
else {
|
||||
val playing = playback.service.playingTrack
|
||||
val entryExternalId = track.externalId
|
||||
val playingExternalId = playing.externalId
|
||||
|
||||
if (entryExternalId == playingExternalId) {
|
||||
titleColor = R.color.theme_green
|
||||
subtitleColor = R.color.theme_yellow
|
||||
}
|
||||
|
||||
title.text = fallback(track.title, "-")
|
||||
subtitle.text = fallback(track.albumArtist, "-")
|
||||
}
|
||||
|
||||
title.setTextColor(getColorCompat(titleColor))
|
||||
subtitle.setTextColor(getColorCompat(subtitleColor))
|
||||
}
|
||||
}
|
||||
|
||||
private inner class Adapter : RecyclerView.Adapter<ViewHolder>() {
|
||||
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
|
||||
val inflater = LayoutInflater.from(parent.context)
|
||||
val view = inflater.inflate(R.layout.play_queue_row, parent, false)
|
||||
view.setOnClickListener(onItemClickListener)
|
||||
return ViewHolder(view)
|
||||
}
|
||||
|
||||
override fun onBindViewHolder(holder: ViewHolder, position: Int) {
|
||||
holder.bind(tracks.getTrack(position), position)
|
||||
}
|
||||
|
||||
override fun getItemCount(): Int = tracks.count
|
||||
}
|
||||
|
||||
private val slidingWindowListener = object : TrackListSlidingWindow.OnMetadataLoadedListener {
|
||||
override fun onReloaded(count: Int) {
|
||||
override fun onReloaded(count: Int) =
|
||||
emptyView.update(data.provider.state, count)
|
||||
}
|
||||
|
||||
override fun onMetadataLoaded(offset: Int, count: Int) {}
|
||||
override fun onMetadataLoaded(offset: Int, count: Int) = Unit
|
||||
}
|
||||
|
||||
companion object {
|
||||
|
@ -0,0 +1,75 @@
|
||||
package io.casey.musikcube.remote.ui.playqueue.adapter
|
||||
|
||||
import android.support.v7.widget.RecyclerView
|
||||
import android.view.LayoutInflater
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import android.widget.TextView
|
||||
import io.casey.musikcube.remote.R
|
||||
import io.casey.musikcube.remote.service.websocket.model.ITrack
|
||||
import io.casey.musikcube.remote.ui.shared.extension.fallback
|
||||
import io.casey.musikcube.remote.ui.shared.extension.getColorCompat
|
||||
import io.casey.musikcube.remote.ui.shared.mixin.PlaybackMixin
|
||||
import io.casey.musikcube.remote.ui.shared.model.TrackListSlidingWindow
|
||||
|
||||
class PlayQueueAdapter(val tracks: TrackListSlidingWindow,
|
||||
val playback: PlaybackMixin,
|
||||
val listener: EventListener): RecyclerView.Adapter<PlayQueueAdapter.ViewHolder>()
|
||||
{
|
||||
interface EventListener {
|
||||
fun onItemClicked(position: Int)
|
||||
fun onActionClicked(view: View, value: ITrack)
|
||||
}
|
||||
|
||||
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
|
||||
val inflater = LayoutInflater.from(parent.context)
|
||||
val view = inflater.inflate(R.layout.play_queue_row, parent, false)
|
||||
val action = view.findViewById<View>(R.id.action)
|
||||
view.setOnClickListener{ v -> listener.onItemClicked(v.tag as Int) }
|
||||
action.setOnClickListener{ v -> listener.onActionClicked(v, v.tag as ITrack) }
|
||||
return ViewHolder(view)
|
||||
}
|
||||
|
||||
override fun onBindViewHolder(holder: ViewHolder, position: Int) {
|
||||
holder.bind(tracks.getTrack(position), position)
|
||||
}
|
||||
|
||||
override fun getItemCount(): Int = tracks.count
|
||||
|
||||
inner class ViewHolder internal constructor(itemView: View) : RecyclerView.ViewHolder(itemView) {
|
||||
private val title = itemView.findViewById<TextView>(R.id.title)
|
||||
private val subtitle = itemView.findViewById<TextView>(R.id.subtitle)
|
||||
private val trackNum = itemView.findViewById<TextView>(R.id.track_num)
|
||||
private val action = itemView.findViewById<View>(R.id.action)
|
||||
|
||||
internal fun bind(track: ITrack?, position: Int) {
|
||||
trackNum.text = (position + 1).toString()
|
||||
itemView.tag = position
|
||||
action.tag = track
|
||||
|
||||
var titleColor = R.color.theme_foreground
|
||||
var subtitleColor = R.color.theme_disabled_foreground
|
||||
|
||||
if (track == null) {
|
||||
title.text = "-"
|
||||
subtitle.text = "-"
|
||||
}
|
||||
else {
|
||||
val playing = playback.service.playingTrack
|
||||
val entryExternalId = track.externalId
|
||||
val playingExternalId = playing.externalId
|
||||
|
||||
if (entryExternalId == playingExternalId) {
|
||||
titleColor = R.color.theme_green
|
||||
subtitleColor = R.color.theme_yellow
|
||||
}
|
||||
|
||||
title.text = fallback(track.title, "-")
|
||||
subtitle.text = fallback(track.albumArtist, "-")
|
||||
}
|
||||
|
||||
title.setTextColor(getColorCompat(titleColor))
|
||||
subtitle.setTextColor(getColorCompat(subtitleColor))
|
||||
}
|
||||
}
|
||||
}
|
@ -20,8 +20,8 @@ import com.uacf.taskrunner.Tasks
|
||||
import io.casey.musikcube.remote.Application
|
||||
import io.casey.musikcube.remote.R
|
||||
import io.casey.musikcube.remote.ui.settings.model.Connection
|
||||
import io.casey.musikcube.remote.ui.shared.extension.*
|
||||
import io.casey.musikcube.remote.ui.shared.activity.BaseActivity
|
||||
import io.casey.musikcube.remote.ui.shared.extension.*
|
||||
|
||||
private val EXTRA_CONNECTION = "extra_connection"
|
||||
|
||||
|
@ -14,7 +14,6 @@ import android.support.v7.widget.RecyclerView
|
||||
import android.support.v7.widget.SearchView
|
||||
import android.view.Menu
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import android.view.inputmethod.InputMethodManager
|
||||
import android.widget.CheckBox
|
||||
import android.widget.CompoundButton
|
||||
|
@ -7,7 +7,6 @@ import android.support.v7.app.AppCompatActivity
|
||||
import io.casey.musikcube.remote.framework.IMixin
|
||||
import io.casey.musikcube.remote.framework.MixinSet
|
||||
import io.casey.musikcube.remote.framework.ViewModel
|
||||
import io.casey.musikcube.remote.ui.shared.mixin.ItemContextMenuMixin
|
||||
import io.casey.musikcube.remote.ui.shared.mixin.ViewModelMixin
|
||||
|
||||
open class BaseDialogFragment: DialogFragment(), ViewModel.Provider {
|
||||
|
@ -8,9 +8,10 @@ import io.casey.musikcube.remote.service.websocket.model.IDataProvider
|
||||
import io.casey.musikcube.remote.service.websocket.model.ITrack
|
||||
import io.reactivex.Observable
|
||||
import io.reactivex.disposables.CompositeDisposable
|
||||
import io.reactivex.rxkotlin.subscribeBy
|
||||
|
||||
class TrackListSlidingWindow(private val recyclerView: FastScrollRecyclerView,
|
||||
val dataProvider: IDataProvider,
|
||||
private val dataProvider: IDataProvider,
|
||||
private val queryFactory: TrackListSlidingWindow.QueryFactory)
|
||||
{
|
||||
private var scrollState = RecyclerView.SCROLL_STATE_IDLE
|
||||
@ -29,9 +30,7 @@ class TrackListSlidingWindow(private val recyclerView: FastScrollRecyclerView,
|
||||
}
|
||||
|
||||
private val cache = object : LinkedHashMap<Int, CacheEntry>() {
|
||||
override fun removeEldestEntry(eldest: MutableMap.MutableEntry<Int, CacheEntry>): Boolean {
|
||||
return size >= MAX_SIZE
|
||||
}
|
||||
override fun removeEldestEntry(eldest: MutableMap.MutableEntry<Int, CacheEntry>): Boolean = size >= MAX_SIZE
|
||||
}
|
||||
|
||||
interface OnMetadataLoadedListener {
|
||||
@ -74,20 +73,20 @@ class TrackListSlidingWindow(private val recyclerView: FastScrollRecyclerView,
|
||||
val countObservable = queryFactory.count()
|
||||
|
||||
if (countObservable != null) {
|
||||
countObservable.subscribe(
|
||||
{ newCount ->
|
||||
count = newCount
|
||||
countObservable.subscribeBy(
|
||||
onNext = { newCount ->
|
||||
count = newCount
|
||||
|
||||
if (initialPosition != -1) {
|
||||
recyclerView.scrollToPosition(initialPosition)
|
||||
initialPosition = -1
|
||||
}
|
||||
if (initialPosition != -1) {
|
||||
recyclerView.scrollToPosition(initialPosition)
|
||||
initialPosition = -1
|
||||
}
|
||||
|
||||
loadedListener?.onReloaded(count)
|
||||
},
|
||||
{ _ ->
|
||||
Log.d("TrackListSlidingWindow", "message send failed, likely canceled")
|
||||
})
|
||||
loadedListener?.onReloaded(count)
|
||||
},
|
||||
onError = { _ ->
|
||||
Log.d("TrackListSlidingWindow", "message send failed, likely canceled")
|
||||
})
|
||||
|
||||
queried = true
|
||||
}
|
||||
@ -127,7 +126,7 @@ class TrackListSlidingWindow(private val recyclerView: FastScrollRecyclerView,
|
||||
fun getTrack(index: Int): ITrack? {
|
||||
val track = cache[index]
|
||||
|
||||
if (track?.dirty ?: true) {
|
||||
if (track == null || track.dirty) {
|
||||
if (scrollState == RecyclerView.SCROLL_STATE_IDLE) {
|
||||
getPageAround(index)
|
||||
}
|
||||
@ -167,8 +166,8 @@ class TrackListSlidingWindow(private val recyclerView: FastScrollRecyclerView,
|
||||
queryOffset = offset
|
||||
queryLimit = limit
|
||||
|
||||
pageRequest.subscribe(
|
||||
{ response ->
|
||||
pageRequest.subscribeBy(
|
||||
onNext = { response ->
|
||||
queryLimit = -1
|
||||
queryOffset = queryLimit
|
||||
|
||||
@ -183,23 +182,20 @@ class TrackListSlidingWindow(private val recyclerView: FastScrollRecyclerView,
|
||||
notifyAdapterChanged()
|
||||
notifyMetadataLoaded(offset, i)
|
||||
},
|
||||
{ _ ->
|
||||
onError = { _ ->
|
||||
Log.d("TrackListSlidingWindow", "message send failed, likely canceled")
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
private fun notifyAdapterChanged() {
|
||||
private fun notifyAdapterChanged() =
|
||||
recyclerView.adapter.notifyDataSetChanged()
|
||||
}
|
||||
|
||||
private fun notifyMetadataLoaded(offset: Int, count: Int) {
|
||||
private fun notifyMetadataLoaded(offset: Int, count: Int) =
|
||||
loadedListener?.onMetadataLoaded(offset, count)
|
||||
}
|
||||
|
||||
private fun scrolling(): Boolean {
|
||||
return scrollState != RecyclerView.SCROLL_STATE_IDLE || fastScrollerActive
|
||||
}
|
||||
private fun scrolling(): Boolean =
|
||||
scrollState != RecyclerView.SCROLL_STATE_IDLE || fastScrollerActive
|
||||
|
||||
private val recyclerViewScrollListener = object : RecyclerView.OnScrollListener() {
|
||||
override fun onScrollStateChanged(recyclerView: RecyclerView?, newState: Int) {
|
||||
|
@ -5,9 +5,11 @@ import android.util.LruCache
|
||||
import io.casey.musikcube.remote.Application
|
||||
import io.casey.musikcube.remote.service.websocket.model.IAlbum
|
||||
import io.casey.musikcube.remote.service.websocket.model.ITrack
|
||||
import io.casey.musikcube.remote.util.Strings
|
||||
import io.casey.musikcube.remote.ui.settings.constants.Prefs
|
||||
import okhttp3.*
|
||||
import io.casey.musikcube.remote.util.Strings
|
||||
import okhttp3.OkHttpClient
|
||||
import okhttp3.Request
|
||||
import okhttp3.Response
|
||||
import org.json.JSONException
|
||||
import org.json.JSONObject
|
||||
import java.io.IOException
|
||||
|
@ -9,14 +9,14 @@ import android.widget.FrameLayout
|
||||
import android.widget.TextView
|
||||
import io.casey.musikcube.remote.Application
|
||||
import io.casey.musikcube.remote.R
|
||||
import io.casey.musikcube.remote.service.websocket.model.IDataProvider
|
||||
import io.casey.musikcube.remote.injection.DaggerViewComponent
|
||||
import io.casey.musikcube.remote.injection.DataModule
|
||||
import io.casey.musikcube.remote.service.playback.PlaybackServiceFactory
|
||||
import io.casey.musikcube.remote.service.playback.impl.streaming.StreamingPlaybackService
|
||||
import io.casey.musikcube.remote.ui.tracks.activity.TrackListActivity
|
||||
import io.casey.musikcube.remote.ui.shared.extension.setVisible
|
||||
import io.casey.musikcube.remote.service.websocket.WebSocketService
|
||||
import io.casey.musikcube.remote.service.websocket.model.IDataProvider
|
||||
import io.casey.musikcube.remote.ui.shared.extension.setVisible
|
||||
import io.casey.musikcube.remote.ui.tracks.activity.TrackListActivity
|
||||
import javax.inject.Inject
|
||||
import io.casey.musikcube.remote.service.websocket.WebSocketService.State as WebSocketState
|
||||
|
||||
|
@ -6,7 +6,6 @@ import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import android.widget.TextView
|
||||
import io.casey.musikcube.remote.R
|
||||
import io.casey.musikcube.remote.service.playback.IPlaybackService
|
||||
import io.casey.musikcube.remote.service.websocket.model.ITrack
|
||||
import io.casey.musikcube.remote.ui.shared.extension.fallback
|
||||
import io.casey.musikcube.remote.ui.shared.extension.getColorCompat
|
||||
|
@ -1,28 +1,30 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<RelativeLayout
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:orientation="vertical"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:background="?android:selectableItemBackground"
|
||||
android:minHeight="52dp"
|
||||
android:padding="8dp" >
|
||||
android:padding="8dp">
|
||||
|
||||
<TextView
|
||||
android:id="@+id/track_num"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_centerVertical="true"
|
||||
android:layout_marginLeft="8dp"
|
||||
android:layout_marginRight="12dp"
|
||||
android:layout_alignParentLeft="true"
|
||||
android:layout_marginStart="8dp"
|
||||
android:layout_marginEnd="12dp"
|
||||
android:layout_alignParentStart="true"
|
||||
android:textColor="@color/theme_disabled_foreground"
|
||||
android:text="1" />
|
||||
tools:text="1" />
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_toRightOf="@id/track_num"
|
||||
android:layout_centerVertical="true"
|
||||
android:layout_toEndOf="@id/track_num"
|
||||
android:layout_toStartOf="@+id/action"
|
||||
android:orientation="vertical">
|
||||
|
||||
<TextView
|
||||
@ -34,7 +36,7 @@
|
||||
android:maxLines="1"
|
||||
android:ellipsize="end"
|
||||
android:textColor="@color/theme_foreground"
|
||||
android:text="title"/>
|
||||
tools:text="title"/>
|
||||
|
||||
<TextView
|
||||
android:textSize="12dp"
|
||||
@ -46,9 +48,20 @@
|
||||
android:maxLines="1"
|
||||
android:ellipsize="end"
|
||||
android:textColor="@color/theme_disabled_foreground"
|
||||
android:text="subtitle"/>
|
||||
tools:text="subtitle"/>
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/action"
|
||||
android:background="?android:selectableItemBackground"
|
||||
android:src="@drawable/ic_overflow"
|
||||
android:scaleType="center"
|
||||
android:padding="4dp"
|
||||
android:layout_centerVertical="true"
|
||||
android:layout_alignParentEnd="true"
|
||||
android:layout_width="36dp"
|
||||
android:layout_height="36dp"
|
||||
android:gravity="center"/>
|
||||
|
||||
</RelativeLayout>
|
Loading…
Reference in New Issue
Block a user