mirror of
https://github.com/clangen/musikcube.git
synced 2025-03-29 19:20:28 +00:00
Merge pull request #247 from clangen/clangen/android_ui_3
Deeper down the rabbit hole...
This commit is contained in:
commit
bcec21dc28
@ -10,6 +10,7 @@ import io.casey.musikcube.remote.ui.category.fragment.CategoryBrowseFragment
|
||||
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.playqueue.fragment.PlayQueueFragment
|
||||
import io.casey.musikcube.remote.ui.settings.activity.ConnectionsActivity
|
||||
import io.casey.musikcube.remote.ui.settings.activity.RemoteEqActivity
|
||||
import io.casey.musikcube.remote.ui.settings.activity.RemoteSettingsActivity
|
||||
@ -38,9 +39,10 @@ interface ViewComponent {
|
||||
fun inject(activity: SettingsActivity)
|
||||
fun inject(activity: TrackListActivity)
|
||||
|
||||
fun inject(fragment: BaseFragment)
|
||||
fun inject(fragment: AlbumBrowseFragment)
|
||||
fun inject(fragment: BaseFragment)
|
||||
fun inject(fragment: CategoryBrowseFragment)
|
||||
fun inject(fragment: PlayQueueFragment)
|
||||
fun inject(fragment: TrackListFragment)
|
||||
|
||||
fun inject(view: EmptyListView)
|
||||
|
@ -9,11 +9,11 @@ import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import com.simplecityapps.recyclerview_fastscroll.views.FastScrollRecyclerView
|
||||
import io.casey.musikcube.remote.R
|
||||
import io.casey.musikcube.remote.service.playback.impl.remote.Metadata
|
||||
import io.casey.musikcube.remote.service.websocket.model.IAlbum
|
||||
import io.casey.musikcube.remote.service.websocket.model.IDataProvider
|
||||
import io.casey.musikcube.remote.ui.albums.adapter.AlbumBrowseAdapter
|
||||
import io.casey.musikcube.remote.ui.albums.constant.Album
|
||||
import io.casey.musikcube.remote.ui.navigation.Navigate
|
||||
import io.casey.musikcube.remote.ui.shared.activity.IFilterable
|
||||
import io.casey.musikcube.remote.ui.shared.activity.ITitleProvider
|
||||
import io.casey.musikcube.remote.ui.shared.activity.ITransportObserver
|
||||
@ -24,8 +24,6 @@ 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.view.EmptyListView
|
||||
import io.casey.musikcube.remote.ui.tracks.activity.TrackListActivity
|
||||
import io.casey.musikcube.remote.ui.tracks.fragment.TrackListFragment
|
||||
import io.casey.musikcube.remote.util.Debouncer
|
||||
import io.reactivex.rxkotlin.subscribeBy
|
||||
|
||||
@ -119,26 +117,7 @@ class AlbumBrowseFragment: BaseFragment(), IFilterable, ITitleProvider, ITranspo
|
||||
|
||||
private val eventListener = object: AlbumBrowseAdapter.EventListener {
|
||||
override fun onItemClicked(album: IAlbum) {
|
||||
when (pushContainerId > 0) {
|
||||
true ->
|
||||
pushWithToolbar(
|
||||
pushContainerId,
|
||||
"TracksForAlbum($album.id)",
|
||||
TrackListFragment.create(
|
||||
TrackListFragment.arguments(
|
||||
appCompatActivity,
|
||||
Metadata.Category.ALBUM,
|
||||
album.id,
|
||||
album.value))
|
||||
.pushTo(pushContainerId))
|
||||
false ->
|
||||
startActivity(
|
||||
TrackListActivity.getStartIntent(
|
||||
appCompatActivity,
|
||||
Metadata.Category.ALBUM,
|
||||
album.id,
|
||||
album.value))
|
||||
}
|
||||
Navigate.toAlbum(album, appCompatActivity, this@AlbumBrowseFragment)
|
||||
}
|
||||
|
||||
override fun onActionClicked(view: View, album: IAlbum) {
|
||||
|
@ -12,8 +12,8 @@ import io.casey.musikcube.remote.ui.shared.activity.BaseActivity
|
||||
import io.casey.musikcube.remote.ui.shared.activity.IBackHandler
|
||||
import io.casey.musikcube.remote.ui.shared.activity.ITransportObserver
|
||||
import io.casey.musikcube.remote.ui.shared.extension.enableUpNavigation
|
||||
import io.casey.musikcube.remote.ui.shared.extension.find
|
||||
import io.casey.musikcube.remote.ui.shared.extension.findFragment
|
||||
import io.casey.musikcube.remote.ui.shared.extension.pushTo
|
||||
import io.casey.musikcube.remote.ui.shared.fragment.TransportFragment
|
||||
|
||||
class BrowseActivity: BaseActivity() {
|
||||
@ -59,7 +59,9 @@ class BrowseActivity: BaseActivity() {
|
||||
BrowseFragment.TAG)
|
||||
.add(
|
||||
R.id.transport_container,
|
||||
TransportFragment.create(),
|
||||
TransportFragment
|
||||
.create()
|
||||
.pushTo(R.id.content_container),
|
||||
TransportFragment.TAG)
|
||||
.commit()
|
||||
|
||||
|
@ -6,15 +6,15 @@ import android.support.v4.app.FragmentManager
|
||||
import android.support.v4.app.FragmentPagerAdapter
|
||||
import android.view.ViewGroup
|
||||
import io.casey.musikcube.remote.R
|
||||
import io.casey.musikcube.remote.service.playback.impl.remote.Metadata
|
||||
import io.casey.musikcube.remote.ui.albums.fragment.AlbumBrowseFragment
|
||||
import io.casey.musikcube.remote.ui.category.constant.NavigationType
|
||||
import io.casey.musikcube.remote.ui.category.fragment.CategoryBrowseFragment
|
||||
import io.casey.musikcube.remote.ui.shared.activity.IFilterable
|
||||
import io.casey.musikcube.remote.ui.tracks.fragment.TrackListFragment
|
||||
import io.casey.musikcube.remote.service.playback.impl.remote.Metadata
|
||||
import io.casey.musikcube.remote.ui.shared.activity.ITransportObserver
|
||||
import io.casey.musikcube.remote.ui.shared.extension.pushTo
|
||||
import io.casey.musikcube.remote.ui.shared.fragment.BaseFragment
|
||||
import io.casey.musikcube.remote.ui.tracks.fragment.TrackListFragment
|
||||
|
||||
class BrowseFragmentAdapter(private val context: Context,
|
||||
fm: FragmentManager,
|
||||
|
@ -4,12 +4,10 @@ import android.content.Context
|
||||
import android.content.Intent
|
||||
import android.os.Bundle
|
||||
import android.view.Menu
|
||||
import io.casey.musikcube.remote.R
|
||||
import io.casey.musikcube.remote.ui.category.constant.Category
|
||||
import io.casey.musikcube.remote.ui.category.constant.NavigationType
|
||||
import io.casey.musikcube.remote.ui.category.fragment.CategoryBrowseFragment
|
||||
import io.casey.musikcube.remote.ui.shared.activity.FragmentActivityWithTransport
|
||||
import io.casey.musikcube.remote.ui.shared.extension.enableUpNavigation
|
||||
import io.casey.musikcube.remote.ui.shared.fragment.BaseFragment
|
||||
import io.casey.musikcube.remote.service.websocket.WebSocketService.State as SocketState
|
||||
|
||||
@ -17,12 +15,6 @@ class CategoryBrowseActivity: FragmentActivityWithTransport() {
|
||||
private val category
|
||||
get() = content as CategoryBrowseFragment
|
||||
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
super.onCreate(savedInstanceState)
|
||||
setContentView(R.layout.fragment_with_transport_activity)
|
||||
enableUpNavigation()
|
||||
}
|
||||
|
||||
override fun onCreateOptionsMenu(menu: Menu): Boolean = category.createOptionsMenu(menu)
|
||||
override fun setFilter(filter: String) = category.setFilter(filter)
|
||||
override fun onTransportChanged() = category.onTransportChanged()
|
||||
|
@ -15,11 +15,10 @@ import io.casey.musikcube.remote.R
|
||||
import io.casey.musikcube.remote.service.playback.impl.remote.Metadata
|
||||
import io.casey.musikcube.remote.service.websocket.model.ICategoryValue
|
||||
import io.casey.musikcube.remote.service.websocket.model.IDataProvider
|
||||
import io.casey.musikcube.remote.ui.albums.activity.AlbumBrowseActivity
|
||||
import io.casey.musikcube.remote.ui.albums.fragment.AlbumBrowseFragment
|
||||
import io.casey.musikcube.remote.ui.category.adapter.CategoryBrowseAdapter
|
||||
import io.casey.musikcube.remote.ui.category.constant.Category
|
||||
import io.casey.musikcube.remote.ui.category.constant.NavigationType
|
||||
import io.casey.musikcube.remote.ui.navigation.Navigate
|
||||
import io.casey.musikcube.remote.ui.shared.activity.IFabConsumer
|
||||
import io.casey.musikcube.remote.ui.shared.activity.IFilterable
|
||||
import io.casey.musikcube.remote.ui.shared.activity.ITitleProvider
|
||||
@ -31,8 +30,6 @@ 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.view.EmptyListView
|
||||
import io.casey.musikcube.remote.ui.tracks.activity.TrackListActivity
|
||||
import io.casey.musikcube.remote.ui.tracks.fragment.TrackListFragment
|
||||
import io.casey.musikcube.remote.util.Debouncer
|
||||
import io.reactivex.rxkotlin.subscribeBy
|
||||
|
||||
@ -192,33 +189,10 @@ class CategoryBrowseFragment: BaseFragment(), IFilterable, ITitleProvider, ITran
|
||||
}
|
||||
|
||||
private fun navigateToAlbums(entry: ICategoryValue) =
|
||||
when (pushContainerId > 0) {
|
||||
true ->
|
||||
this.pushWithToolbar(
|
||||
pushContainerId,
|
||||
"AlbumsBy($entry.value)",
|
||||
AlbumBrowseFragment
|
||||
.create(app, entry.type, entry.id, entry.value)
|
||||
.pushTo(pushContainerId))
|
||||
false ->
|
||||
startActivity(AlbumBrowseActivity
|
||||
.getStartIntent(appCompatActivity, category, entry))
|
||||
|
||||
}
|
||||
Navigate.toAlbums(category, entry, appCompatActivity, this)
|
||||
|
||||
private fun navigateToTracks(entry: ICategoryValue) =
|
||||
when (this.pushContainerId > 0) {
|
||||
true ->
|
||||
this.pushWithToolbar(
|
||||
this.pushContainerId,
|
||||
"TracksBy($entry.value)",
|
||||
TrackListFragment.create(TrackListFragment
|
||||
.arguments(appCompatActivity, entry.type, entry.id))
|
||||
.pushTo(pushContainerId))
|
||||
false ->
|
||||
startActivity(TrackListActivity.getStartIntent(
|
||||
appCompatActivity, category, entry.id, entry.value))
|
||||
}
|
||||
Navigate.toTracks(category, entry, appCompatActivity, this)
|
||||
|
||||
private fun navigateToSelect(id: Long, name: String) =
|
||||
appCompatActivity.run {
|
||||
@ -245,20 +219,27 @@ class CategoryBrowseFragment: BaseFragment(), IFilterable, ITitleProvider, ITran
|
||||
this.arguments = arguments
|
||||
}
|
||||
|
||||
fun create(context: Context,
|
||||
targetType: String,
|
||||
predicateType: String = "",
|
||||
predicateId: Long = -1,
|
||||
predicateValue: String = ""): CategoryBrowseFragment =
|
||||
create(arguments(context, targetType, predicateType, predicateId, predicateValue))
|
||||
|
||||
fun arguments(context: Context,
|
||||
category: String,
|
||||
predicateType: String = "",
|
||||
predicateId: Long = -1,
|
||||
predicateValue: String = ""): Bundle =
|
||||
targetType: String,
|
||||
sourceType: String = "",
|
||||
sourceId: Long = -1,
|
||||
sourceValue: String = ""): Bundle =
|
||||
Bundle().apply {
|
||||
putString(Category.Extra.CATEGORY, category)
|
||||
putString(Category.Extra.PREDICATE_TYPE, predicateType)
|
||||
putLong(Category.Extra.PREDICATE_ID, predicateId)
|
||||
if (predicateValue.isNotBlank() && Category.NAME_TO_RELATED_TITLE.containsKey(category)) {
|
||||
val format = Category.NAME_TO_RELATED_TITLE[category]
|
||||
putString(Category.Extra.CATEGORY, targetType)
|
||||
putString(Category.Extra.PREDICATE_TYPE, sourceType)
|
||||
putLong(Category.Extra.PREDICATE_ID, sourceId)
|
||||
if (sourceValue.isNotBlank() && Category.NAME_TO_RELATED_TITLE.containsKey(targetType)) {
|
||||
val format = Category.NAME_TO_RELATED_TITLE[targetType]
|
||||
when (format) {
|
||||
null -> throw IllegalArgumentException("unknown category $category")
|
||||
else -> putString(Shared.Extra.TITLE_OVERRIDE, context.getString(format, predicateValue))
|
||||
null -> throw IllegalArgumentException("unknown category $targetType")
|
||||
else -> putString(Shared.Extra.TITLE_OVERRIDE, context.getString(format, sourceValue))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -0,0 +1,193 @@
|
||||
package io.casey.musikcube.remote.ui.navigation
|
||||
|
||||
import android.content.Intent
|
||||
import android.support.v7.app.AppCompatActivity
|
||||
import io.casey.musikcube.remote.R
|
||||
import io.casey.musikcube.remote.service.playback.impl.remote.Metadata
|
||||
import io.casey.musikcube.remote.service.websocket.model.IAlbum
|
||||
import io.casey.musikcube.remote.service.websocket.model.ICategoryValue
|
||||
import io.casey.musikcube.remote.ui.albums.activity.AlbumBrowseActivity
|
||||
import io.casey.musikcube.remote.ui.albums.fragment.AlbumBrowseFragment
|
||||
import io.casey.musikcube.remote.ui.category.activity.CategoryBrowseActivity
|
||||
import io.casey.musikcube.remote.ui.category.constant.NavigationType
|
||||
import io.casey.musikcube.remote.ui.category.fragment.CategoryBrowseFragment
|
||||
import io.casey.musikcube.remote.ui.playqueue.activity.PlayQueueActivity
|
||||
import io.casey.musikcube.remote.ui.playqueue.fragment.PlayQueueFragment
|
||||
import io.casey.musikcube.remote.ui.shared.extension.*
|
||||
import io.casey.musikcube.remote.ui.shared.fragment.BaseFragment
|
||||
import io.casey.musikcube.remote.ui.tracks.activity.EditPlaylistActivity
|
||||
import io.casey.musikcube.remote.ui.tracks.activity.TrackListActivity
|
||||
import io.casey.musikcube.remote.ui.tracks.fragment.TrackListFragment
|
||||
|
||||
object Navigate {
|
||||
/*
|
||||
*
|
||||
* list of albums
|
||||
*
|
||||
*/
|
||||
fun toAlbums(categoryType: String,
|
||||
categoryEntry: ICategoryValue,
|
||||
activity: AppCompatActivity,
|
||||
fragment: BaseFragment? = null) =
|
||||
toAlbums(categoryType, categoryEntry.id, categoryEntry.value, activity, fragment)
|
||||
|
||||
fun toAlbums(categoryEntry: ICategoryValue,
|
||||
activity: AppCompatActivity,
|
||||
fragment: BaseFragment? = null) =
|
||||
toAlbums(categoryEntry.type, categoryEntry.id, categoryEntry.value, activity, fragment)
|
||||
|
||||
fun toAlbums(categoryType: String,
|
||||
categoryId: Long,
|
||||
categoryValue: String,
|
||||
activity: AppCompatActivity,
|
||||
fragment: BaseFragment? = null) =
|
||||
when (fragment != null && fragment.pushContainerId > 0) {
|
||||
true ->
|
||||
fragment.pushWithToolbar(
|
||||
fragment.pushContainerId,
|
||||
"AlbumsBy($categoryType-$categoryId-$categoryValue)",
|
||||
AlbumBrowseFragment.create(activity, categoryType, categoryId, categoryValue))
|
||||
false ->
|
||||
activity.startActivity(AlbumBrowseActivity
|
||||
.getStartIntent(activity, categoryType, categoryId, categoryValue))
|
||||
}
|
||||
|
||||
fun toAlbums(activity: AppCompatActivity,
|
||||
fragment: BaseFragment? = null) =
|
||||
when (fragment != null && fragment.pushContainerId > 0) {
|
||||
true ->
|
||||
fragment.pushWithToolbar(
|
||||
fragment.pushContainerId,
|
||||
"AllAlbums",
|
||||
AlbumBrowseFragment.create(activity),
|
||||
Transition.Vertical)
|
||||
false ->
|
||||
activity.startActivity(AlbumBrowseActivity.getStartIntent(activity))
|
||||
}
|
||||
|
||||
/*
|
||||
*
|
||||
* single album
|
||||
*
|
||||
*/
|
||||
|
||||
fun toAlbum(album: IAlbum,
|
||||
activity: AppCompatActivity,
|
||||
fragment: BaseFragment? = null) =
|
||||
when (fragment != null && fragment.pushContainerId > 0) {
|
||||
true ->
|
||||
fragment.pushWithToolbar(
|
||||
fragment.pushContainerId,
|
||||
"TracksForAlbum($album.id)",
|
||||
TrackListFragment.create(
|
||||
TrackListFragment.arguments(
|
||||
activity, Metadata.Category.ALBUM, album.id, album.value)))
|
||||
false ->
|
||||
activity.startActivity(
|
||||
TrackListActivity.getStartIntent(
|
||||
activity, Metadata.Category.ALBUM, album.id, album.value))
|
||||
}
|
||||
|
||||
/*
|
||||
*
|
||||
* list of categories
|
||||
*
|
||||
*/
|
||||
|
||||
fun toCategoryList(targetType: String,
|
||||
sourceType: String,
|
||||
sourceId: Long,
|
||||
sourceValue: String,
|
||||
activity: AppCompatActivity,
|
||||
fragment: BaseFragment? = null) =
|
||||
when (fragment != null && fragment.pushContainerId > 0) {
|
||||
true ->
|
||||
fragment.pushWithToolbar(
|
||||
fragment.pushContainerId,
|
||||
"${targetType}By($sourceType-$sourceId-$sourceValue)",
|
||||
CategoryBrowseFragment.create(activity, targetType, sourceType, sourceId, sourceValue))
|
||||
false ->
|
||||
activity.startActivity(CategoryBrowseActivity
|
||||
.getStartIntent(activity, targetType, sourceType, sourceId, sourceValue))
|
||||
}
|
||||
|
||||
/*
|
||||
*
|
||||
* playlist-related
|
||||
*
|
||||
*/
|
||||
|
||||
fun toPlaylistChooser(requestCode: Int,
|
||||
activity: AppCompatActivity,
|
||||
fragment: BaseFragment? = null) =
|
||||
CategoryBrowseActivity.getStartIntent(
|
||||
activity,
|
||||
Metadata.Category.PLAYLISTS,
|
||||
NavigationType.Select,
|
||||
activity.getString(R.string.playlist_edit_pick_playlist))
|
||||
.withoutTransport()
|
||||
.withTransitionType(Transition.Vertical)
|
||||
.apply {
|
||||
startActivityForResult(this, requestCode, activity, fragment)
|
||||
}
|
||||
|
||||
fun toPlaylistEditor(requestCode: Int,
|
||||
playlistName: String,
|
||||
playlistId: Long,
|
||||
activity: AppCompatActivity,
|
||||
fragment: BaseFragment? = null) =
|
||||
EditPlaylistActivity.getStartIntent(activity, playlistName, playlistId).apply {
|
||||
startActivityForResult(this, requestCode, activity, fragment)
|
||||
}
|
||||
|
||||
/*
|
||||
*
|
||||
* list of tracks
|
||||
*
|
||||
*/
|
||||
|
||||
fun toTracks(categoryType: String,
|
||||
categoryEntry: ICategoryValue,
|
||||
activity: AppCompatActivity,
|
||||
fragment: BaseFragment? = null) =
|
||||
toTracks(categoryType, categoryEntry.id, categoryEntry.value, activity, fragment)
|
||||
|
||||
fun toTracks(categoryEntry: ICategoryValue,
|
||||
activity: AppCompatActivity,
|
||||
fragment: BaseFragment? = null) =
|
||||
toTracks(categoryEntry.type, categoryEntry.id, categoryEntry.value, activity, fragment)
|
||||
|
||||
fun toTracks(categoryType: String,
|
||||
categoryId: Long,
|
||||
categoryValue: String,
|
||||
activity: AppCompatActivity,
|
||||
fragment: BaseFragment? = null) =
|
||||
when (fragment != null && fragment.pushContainerId > 0) {
|
||||
true ->
|
||||
fragment.pushWithToolbar(
|
||||
fragment.pushContainerId,
|
||||
"TracksBy($categoryType-$categoryId-$categoryValue)",
|
||||
TrackListFragment.create(TrackListFragment.arguments(
|
||||
activity, categoryType, categoryId, categoryValue)))
|
||||
false ->
|
||||
activity.startActivity(TrackListActivity.getStartIntent(
|
||||
activity, categoryType, categoryId, categoryValue))
|
||||
}
|
||||
|
||||
fun toPlayQueue(playingIndex: Int,
|
||||
activity: AppCompatActivity,
|
||||
fragment: BaseFragment? = null) {
|
||||
when (fragment != null && fragment.pushContainerId > 0) {
|
||||
true ->
|
||||
fragment.pushWithToolbar(
|
||||
fragment.pushContainerId,
|
||||
PlayQueueFragment.TAG,
|
||||
PlayQueueFragment.create(playingIndex),
|
||||
Transition.Vertical)
|
||||
false ->
|
||||
activity.startActivity(PlayQueueActivity
|
||||
.getStartIntent(activity, playingIndex)
|
||||
.addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP))
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,9 @@
|
||||
package io.casey.musikcube.remote.ui.navigation
|
||||
|
||||
enum class Transition {
|
||||
Horizontal, Vertical;
|
||||
companion object {
|
||||
fun from(name: String, fallback: Transition = Horizontal): Transition =
|
||||
values().firstOrNull { it.name == name } ?: fallback
|
||||
}
|
||||
}
|
@ -2,142 +2,27 @@ package io.casey.musikcube.remote.ui.playqueue.activity
|
||||
|
||||
import android.content.Context
|
||||
import android.content.Intent
|
||||
import android.os.Bundle
|
||||
import android.view.MenuItem
|
||||
import android.view.View
|
||||
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.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.DefaultSlidingWindow
|
||||
import io.casey.musikcube.remote.ui.shared.model.ITrackListSlidingWindow
|
||||
import io.casey.musikcube.remote.ui.shared.view.EmptyListView
|
||||
import io.reactivex.rxkotlin.subscribeBy
|
||||
import io.casey.musikcube.remote.ui.navigation.Transition
|
||||
import io.casey.musikcube.remote.ui.playqueue.constant.PlayQueue
|
||||
import io.casey.musikcube.remote.ui.playqueue.fragment.PlayQueueFragment
|
||||
import io.casey.musikcube.remote.ui.shared.activity.FragmentActivityWithTransport
|
||||
import io.casey.musikcube.remote.ui.shared.fragment.BaseFragment
|
||||
|
||||
class PlayQueueActivity : BaseActivity() {
|
||||
private var offlineQueue: Boolean = false
|
||||
private lateinit var data: DataProviderMixin
|
||||
private lateinit var playback: PlaybackMixin
|
||||
private lateinit var tracks: DefaultSlidingWindow
|
||||
private lateinit var adapter: PlayQueueAdapter
|
||||
private lateinit var emptyView: EmptyListView
|
||||
class PlayQueueActivity : FragmentActivityWithTransport() {
|
||||
override fun createContentFragment(): BaseFragment =
|
||||
PlayQueueFragment.create(extras.getInt(
|
||||
PlayQueue.Extra.PLAYING_INDEX, 0))
|
||||
|
||||
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 = DefaultSlidingWindow(recyclerView, data.provider, queryFactory)
|
||||
tracks.setInitialPosition(intent.getIntExtra(EXTRA_PLAYING_INDEX, -1))
|
||||
tracks.setOnMetadataLoadedListener(slidingWindowListener)
|
||||
adapter = PlayQueueAdapter(tracks, playback, prefs, adapterListener)
|
||||
|
||||
setupDefaultRecyclerView(recyclerView, adapter)
|
||||
|
||||
emptyView = findViewById(R.id.empty_list_view)
|
||||
emptyView.capability = EmptyListView.Capability.OfflineOk
|
||||
emptyView.emptyMessage = getString(R.string.play_queue_empty)
|
||||
emptyView.alternateView = recyclerView
|
||||
|
||||
setTitleFromIntent(R.string.play_queue_title)
|
||||
addTransportFragment()
|
||||
enableUpNavigation()
|
||||
}
|
||||
|
||||
override fun onPause() {
|
||||
super.onPause()
|
||||
this.tracks.pause()
|
||||
}
|
||||
|
||||
override fun onResume() {
|
||||
this.tracks.resume() /* needs to happen before */
|
||||
super.onResume()
|
||||
initObservers()
|
||||
if (offlineQueue) {
|
||||
tracks.requery()
|
||||
}
|
||||
}
|
||||
|
||||
override fun onOptionsItemSelected(item: MenuItem): Boolean {
|
||||
val result = super.onOptionsItemSelected(item)
|
||||
|
||||
if (item.itemId == android.R.id.home) {
|
||||
overridePendingTransition(R.anim.stay_put, R.anim.slide_down)
|
||||
}
|
||||
|
||||
return result
|
||||
}
|
||||
|
||||
override fun onBackPressed() {
|
||||
super.onBackPressed()
|
||||
overridePendingTransition(R.anim.stay_put, R.anim.slide_down)
|
||||
}
|
||||
override val contentFragmentTag: String =
|
||||
PlayQueueFragment.TAG
|
||||
|
||||
override val transitionType: Transition
|
||||
get() = Transition.Vertical
|
||||
|
||||
private fun initObservers() {
|
||||
disposables.add(data.provider.observeState().subscribeBy(
|
||||
onNext = { states ->
|
||||
if (states.first == IDataProvider.State.Connected) {
|
||||
tracks.requery()
|
||||
}
|
||||
else {
|
||||
emptyView.update(states.first, adapter.itemCount)
|
||||
}
|
||||
},
|
||||
onError = {
|
||||
}))
|
||||
}
|
||||
|
||||
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)
|
||||
}
|
||||
}
|
||||
|
||||
private val playbackEvents = {
|
||||
if (adapter.itemCount == 0) {
|
||||
tracks.requery()
|
||||
}
|
||||
adapter.notifyDataSetChanged()
|
||||
}
|
||||
|
||||
private val slidingWindowListener = object : ITrackListSlidingWindow.OnMetadataLoadedListener {
|
||||
override fun onReloaded(count: Int) =
|
||||
emptyView.update(data.provider.state, count)
|
||||
|
||||
override fun onMetadataLoaded(offset: Int, count: Int) = Unit
|
||||
}
|
||||
|
||||
companion object {
|
||||
private const val EXTRA_PLAYING_INDEX = "extra_playing_index"
|
||||
|
||||
fun getStartIntent(context: Context, playingIndex: Int): Intent {
|
||||
return Intent(context, PlayQueueActivity::class.java)
|
||||
.putExtra(EXTRA_PLAYING_INDEX, playingIndex)
|
||||
.putExtra(PlayQueue.Extra.PLAYING_INDEX, playingIndex)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -0,0 +1,7 @@
|
||||
package io.casey.musikcube.remote.ui.playqueue.constant
|
||||
|
||||
object PlayQueue {
|
||||
object Extra {
|
||||
const val PLAYING_INDEX = "extra_playing_index"
|
||||
}
|
||||
}
|
@ -0,0 +1,129 @@
|
||||
package io.casey.musikcube.remote.ui.playqueue.fragment
|
||||
|
||||
import android.os.Bundle
|
||||
import android.support.v4.view.ViewCompat
|
||||
import android.view.LayoutInflater
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
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.playqueue.constant.PlayQueue
|
||||
import io.casey.musikcube.remote.ui.shared.activity.ITitleProvider
|
||||
import io.casey.musikcube.remote.ui.shared.extension.elevation
|
||||
import io.casey.musikcube.remote.ui.shared.extension.getLayoutId
|
||||
import io.casey.musikcube.remote.ui.shared.extension.initToolbarIfNecessary
|
||||
import io.casey.musikcube.remote.ui.shared.extension.setupDefaultRecyclerView
|
||||
import io.casey.musikcube.remote.ui.shared.fragment.BaseFragment
|
||||
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.DefaultSlidingWindow
|
||||
import io.casey.musikcube.remote.ui.shared.model.ITrackListSlidingWindow
|
||||
import io.casey.musikcube.remote.ui.shared.view.EmptyListView
|
||||
import io.reactivex.rxkotlin.subscribeBy
|
||||
|
||||
class PlayQueueFragment: BaseFragment(), ITitleProvider {
|
||||
private var offlineQueue: Boolean = false
|
||||
private lateinit var data: DataProviderMixin
|
||||
private lateinit var playback: PlaybackMixin
|
||||
private lateinit var tracks: DefaultSlidingWindow
|
||||
private lateinit var adapter: PlayQueueAdapter
|
||||
private lateinit var emptyView: EmptyListView
|
||||
|
||||
override val title: String
|
||||
get() = getString(R.string.play_queue_title)
|
||||
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
component.inject(this)
|
||||
data = mixin(DataProviderMixin())
|
||||
playback = mixin(PlaybackMixin(playbackEvents))
|
||||
mixin(ItemContextMenuMixin(appCompatActivity, null, this))
|
||||
super.onCreate(savedInstanceState)
|
||||
}
|
||||
|
||||
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View =
|
||||
inflater.inflate(this.getLayoutId(), container, false).apply {
|
||||
ViewCompat.setElevation(this, extras.elevation)
|
||||
|
||||
val queryFactory = playback.service.playlistQueryFactory
|
||||
offlineQueue = playback.service.playlistQueryFactory.offline()
|
||||
|
||||
val recyclerView = findViewById<FastScrollRecyclerView>(R.id.recycler_view)
|
||||
tracks = DefaultSlidingWindow(recyclerView, data.provider, queryFactory)
|
||||
tracks.setInitialPosition(extras.getInt(PlayQueue.Extra.PLAYING_INDEX, -1))
|
||||
tracks.setOnMetadataLoadedListener(slidingWindowListener)
|
||||
adapter = PlayQueueAdapter(tracks, playback, prefs, adapterListener)
|
||||
|
||||
setupDefaultRecyclerView(recyclerView, adapter)
|
||||
initToolbarIfNecessary(appCompatActivity, this, searchMenu = false)
|
||||
|
||||
emptyView = findViewById(R.id.empty_list_view)
|
||||
emptyView.capability = EmptyListView.Capability.OfflineOk
|
||||
emptyView.emptyMessage = getString(R.string.play_queue_empty)
|
||||
emptyView.alternateView = recyclerView
|
||||
}
|
||||
|
||||
override fun onPause() {
|
||||
super.onPause()
|
||||
this.tracks.pause()
|
||||
}
|
||||
|
||||
override fun onResume() {
|
||||
this.tracks.resume() /* needs to happen before */
|
||||
super.onResume()
|
||||
if (offlineQueue) {
|
||||
tracks.requery()
|
||||
}
|
||||
}
|
||||
|
||||
override fun initObservables() {
|
||||
disposables.add(data.provider.observeState().subscribeBy(
|
||||
onNext = { states ->
|
||||
if (states.first == IDataProvider.State.Connected) {
|
||||
tracks.requery()
|
||||
}
|
||||
else {
|
||||
emptyView.update(states.first, adapter.itemCount)
|
||||
}
|
||||
},
|
||||
onError = {
|
||||
}))
|
||||
}
|
||||
|
||||
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)
|
||||
}
|
||||
}
|
||||
|
||||
private val playbackEvents = {
|
||||
if (adapter.itemCount == 0) {
|
||||
tracks.requery()
|
||||
}
|
||||
adapter.notifyDataSetChanged()
|
||||
}
|
||||
|
||||
private val slidingWindowListener = object : ITrackListSlidingWindow.OnMetadataLoadedListener {
|
||||
override fun onReloaded(count: Int) =
|
||||
emptyView.update(data.provider.state, count)
|
||||
|
||||
override fun onMetadataLoaded(offset: Int, count: Int) = Unit
|
||||
}
|
||||
|
||||
companion object {
|
||||
const val TAG = "PlayQueueFragment"
|
||||
|
||||
fun create(playingIndex: Int): PlayQueueFragment =
|
||||
PlayQueueFragment().apply {
|
||||
arguments = Bundle().apply {
|
||||
putInt(PlayQueue.Extra.PLAYING_INDEX, playingIndex)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -11,6 +11,7 @@ import io.casey.musikcube.remote.service.websocket.model.IDevice
|
||||
import io.casey.musikcube.remote.service.websocket.model.IOutput
|
||||
import io.casey.musikcube.remote.service.websocket.model.ReplayGainMode
|
||||
import io.casey.musikcube.remote.service.websocket.model.TransportType
|
||||
import io.casey.musikcube.remote.ui.navigation.Transition
|
||||
import io.casey.musikcube.remote.ui.settings.viewmodel.RemoteSettingsViewModel
|
||||
import io.casey.musikcube.remote.ui.shared.activity.BaseActivity
|
||||
import io.casey.musikcube.remote.ui.shared.mixin.DataProviderMixin
|
||||
|
@ -17,6 +17,7 @@ import com.uacf.taskrunner.Tasks
|
||||
import io.casey.musikcube.remote.R
|
||||
import io.casey.musikcube.remote.service.playback.PlayerWrapper
|
||||
import io.casey.musikcube.remote.service.playback.impl.streaming.StreamProxy
|
||||
import io.casey.musikcube.remote.ui.navigation.Transition
|
||||
import io.casey.musikcube.remote.ui.settings.constants.Prefs
|
||||
import io.casey.musikcube.remote.ui.settings.model.Connection
|
||||
import io.casey.musikcube.remote.ui.settings.model.ConnectionsDb
|
||||
|
@ -18,6 +18,7 @@ import io.casey.musikcube.remote.framework.MixinSet
|
||||
import io.casey.musikcube.remote.framework.ViewModel
|
||||
import io.casey.musikcube.remote.injection.DaggerViewComponent
|
||||
import io.casey.musikcube.remote.injection.ViewComponent
|
||||
import io.casey.musikcube.remote.ui.navigation.Transition
|
||||
import io.casey.musikcube.remote.ui.settings.constants.Prefs
|
||||
import io.casey.musikcube.remote.ui.shared.extension.*
|
||||
import io.casey.musikcube.remote.ui.shared.mixin.PlaybackMixin
|
||||
@ -26,10 +27,6 @@ import io.casey.musikcube.remote.ui.shared.mixin.ViewModelMixin
|
||||
import io.reactivex.disposables.CompositeDisposable
|
||||
|
||||
abstract class BaseActivity : AppCompatActivity(), ViewModel.Provider, Runner.TaskCallbacks {
|
||||
protected enum class Transition {
|
||||
Horizontal, Vertical
|
||||
}
|
||||
|
||||
protected var disposables = CompositeDisposable()
|
||||
private set
|
||||
|
||||
|
@ -5,13 +5,14 @@ import android.support.design.widget.FloatingActionButton
|
||||
import android.view.Menu
|
||||
import android.view.MenuItem
|
||||
import io.casey.musikcube.remote.R
|
||||
import io.casey.musikcube.remote.ui.navigation.Transition
|
||||
import io.casey.musikcube.remote.ui.shared.constant.Shared
|
||||
import io.casey.musikcube.remote.ui.shared.extension.*
|
||||
import io.casey.musikcube.remote.ui.shared.fragment.BaseFragment
|
||||
import io.casey.musikcube.remote.ui.shared.fragment.TransportFragment
|
||||
|
||||
abstract class FragmentActivityWithTransport: BaseActivity(), IFilterable {
|
||||
protected lateinit var transport: TransportFragment
|
||||
private set
|
||||
private var transport: TransportFragment? = null
|
||||
|
||||
protected lateinit var content: BaseFragment
|
||||
private set
|
||||
@ -30,7 +31,7 @@ abstract class FragmentActivityWithTransport: BaseActivity(), IFilterable {
|
||||
else -> restoreFragments()
|
||||
}
|
||||
|
||||
transport.modelChangedListener = {
|
||||
transport?.modelChangedListener = {
|
||||
onTransportChanged()
|
||||
}
|
||||
|
||||
@ -80,6 +81,9 @@ abstract class FragmentActivityWithTransport: BaseActivity(), IFilterable {
|
||||
setFilter(filter)
|
||||
} ?: Unit
|
||||
|
||||
override val transitionType: Transition
|
||||
get() = extras.transitionType
|
||||
|
||||
protected abstract fun createContentFragment(): BaseFragment
|
||||
protected abstract val contentFragmentTag: String
|
||||
|
||||
@ -89,14 +93,16 @@ abstract class FragmentActivityWithTransport: BaseActivity(), IFilterable {
|
||||
|
||||
private fun createFragments() {
|
||||
content = createContentFragment()
|
||||
.withToolbar()
|
||||
.withTitleOverride(this)
|
||||
transport = TransportFragment.create()
|
||||
supportFragmentManager
|
||||
.beginTransaction()
|
||||
.add(R.id.content_container, content, contentFragmentTag)
|
||||
.add(R.id.transport_container, transport, TransportFragment.TAG)
|
||||
.commit()
|
||||
.withToolbar().withTitleOverride(this)
|
||||
supportFragmentManager.beginTransaction().apply {
|
||||
add(R.id.content_container, content, contentFragmentTag)
|
||||
if (!withoutTransport) {
|
||||
transport = TransportFragment.create().apply {
|
||||
add(R.id.transport_container, this, TransportFragment.TAG)
|
||||
}
|
||||
}
|
||||
commit()
|
||||
}
|
||||
supportFragmentManager.executePendingTransactions()
|
||||
}
|
||||
|
||||
@ -104,4 +110,7 @@ abstract class FragmentActivityWithTransport: BaseActivity(), IFilterable {
|
||||
transport = findFragment(TransportFragment.TAG)
|
||||
content = findFragment(contentFragmentTag)
|
||||
}
|
||||
|
||||
private val withoutTransport
|
||||
get() = extras.getBoolean(Shared.Extra.WITHOUT_TRANSPORT, false)
|
||||
}
|
@ -2,9 +2,11 @@ package io.casey.musikcube.remote.ui.shared.constant
|
||||
|
||||
object Shared {
|
||||
object Extra {
|
||||
const val TITLE_OVERRIDE = "extra_title_override"
|
||||
const val WITH_TOOLBAR = "extra_with_toolbar"
|
||||
const val PUSH_CONTAINER_ID = "extra_push_container_id"
|
||||
const val ELEVATION = "extra_elevation"
|
||||
const val PUSH_CONTAINER_ID = "extra_push_container_id"
|
||||
const val TITLE_OVERRIDE = "extra_title_override"
|
||||
const val TRANSITION_TYPE = "extra_transition_type"
|
||||
const val WITH_TOOLBAR = "extra_with_toolbar"
|
||||
const val WITHOUT_TRANSPORT = "extra_without_transport"
|
||||
}
|
||||
}
|
@ -2,6 +2,7 @@ package io.casey.musikcube.remote.ui.shared.extension
|
||||
|
||||
import android.app.SearchManager
|
||||
import android.content.Context
|
||||
import android.content.Intent
|
||||
import android.content.SharedPreferences
|
||||
import android.os.Bundle
|
||||
import android.support.design.widget.Snackbar
|
||||
@ -22,6 +23,7 @@ import android.widget.EditText
|
||||
import android.widget.TextView
|
||||
import io.casey.musikcube.remote.Application
|
||||
import io.casey.musikcube.remote.R
|
||||
import io.casey.musikcube.remote.ui.navigation.Transition
|
||||
import io.casey.musikcube.remote.ui.settings.constants.Prefs
|
||||
import io.casey.musikcube.remote.ui.shared.activity.IFilterable
|
||||
import io.casey.musikcube.remote.ui.shared.activity.IMenuProvider
|
||||
@ -57,6 +59,10 @@ fun Toolbar.setTitleFromIntent(defaultTitle: String) {
|
||||
this.title = if (Strings.notEmpty(title)) title else defaultTitle
|
||||
}
|
||||
|
||||
fun Toolbar.setTitleFromIntent(stringId: Int) {
|
||||
this.setTitleFromIntent(context.getString(stringId))
|
||||
}
|
||||
|
||||
fun Toolbar.collapseActionViewIfExpanded(): Boolean {
|
||||
(menu.findItem(R.id.action_search)?.actionView as? SearchView)?.let {
|
||||
if (!it.isIconified) {
|
||||
@ -167,9 +173,9 @@ fun AppCompatActivity.showDialog(dialog: DialogFragment, tag: String) {
|
||||
dialog.show(this.supportFragmentManager, tag)
|
||||
}
|
||||
|
||||
fun AppCompatActivity.slideNextUp() = overridePendingTransition(R.anim.slide_up, R.anim.stay_put)
|
||||
fun AppCompatActivity.slideNextUp() = overridePendingTransition(R.anim.slide_up, R.anim.stay_put_350)
|
||||
|
||||
fun AppCompatActivity.slideThisDown() = overridePendingTransition(R.anim.stay_put, R.anim.slide_down)
|
||||
fun AppCompatActivity.slideThisDown() = overridePendingTransition(R.anim.stay_put_350, R.anim.slide_down)
|
||||
|
||||
fun AppCompatActivity.slideNextLeft() = overridePendingTransition(R.anim.slide_left, R.anim.slide_left_bg)
|
||||
|
||||
@ -179,6 +185,23 @@ inline fun <reified T> AppCompatActivity.findFragment(tag: String): T {
|
||||
return this.supportFragmentManager.find(tag)
|
||||
}
|
||||
|
||||
/*
|
||||
*
|
||||
* FragmentManager
|
||||
*
|
||||
*/
|
||||
val FragmentManager.topOfStack: String?
|
||||
get() {
|
||||
if (this.backStackEntryCount > 0) {
|
||||
return this.getBackStackEntryAt(this.backStackEntryCount - 1).name
|
||||
}
|
||||
return null
|
||||
}
|
||||
|
||||
inline fun <reified T> FragmentManager.find(tag: String): T {
|
||||
return findFragmentByTag(tag) as T
|
||||
}
|
||||
|
||||
/*
|
||||
*
|
||||
* Bundle
|
||||
@ -193,6 +216,25 @@ fun Bundle.withElevation(fm: FragmentManager): Bundle {
|
||||
val Bundle.elevation: Float
|
||||
get() = this.getFloat(Shared.Extra.ELEVATION, 0.0f)
|
||||
|
||||
/*
|
||||
*
|
||||
* Intent
|
||||
*
|
||||
*/
|
||||
|
||||
fun Intent.withoutTransport() =
|
||||
this.apply {
|
||||
putExtra(Shared.Extra.WITHOUT_TRANSPORT, true)
|
||||
}
|
||||
|
||||
fun Intent.withTransitionType(type: Transition) =
|
||||
this.apply {
|
||||
putExtra(Shared.Extra.TRANSITION_TYPE, type.name)
|
||||
}
|
||||
|
||||
val Bundle.transitionType
|
||||
get() = Transition.from(getString(Shared.Extra.TRANSITION_TYPE, ""))
|
||||
|
||||
/*
|
||||
*
|
||||
* BaseFragment
|
||||
@ -214,20 +256,33 @@ inline fun <reified T: BaseFragment> T.pushTo(other: BaseFragment): T {
|
||||
return this
|
||||
}
|
||||
|
||||
fun BaseFragment.pushWithToolbar(containerId: Int, backstackId: String, fragment: BaseFragment) {
|
||||
fun BaseFragment.pushWithToolbar(
|
||||
containerId: Int,
|
||||
backstackId: String,
|
||||
fragment: BaseFragment,
|
||||
transition: Transition = Transition.Horizontal) {
|
||||
fragment.pushTo(containerId)
|
||||
appCompatActivity.supportFragmentManager
|
||||
.beginTransaction()
|
||||
.setCustomAnimations(
|
||||
R.anim.slide_left, R.anim.slide_left_bg,
|
||||
R.anim.slide_right_bg, R.anim.slide_right)
|
||||
.replace(
|
||||
containerId,
|
||||
fragment
|
||||
.withToolbar()
|
||||
.addElevation(appCompatActivity.supportFragmentManager),
|
||||
backstackId)
|
||||
.addToBackStack(backstackId)
|
||||
.commit()
|
||||
.beginTransaction().apply {
|
||||
if (transition == Transition.Horizontal) {
|
||||
setCustomAnimations(
|
||||
R.anim.slide_left, R.anim.slide_left_bg,
|
||||
R.anim.slide_right_bg, R.anim.slide_right)
|
||||
}
|
||||
else {
|
||||
setCustomAnimations(
|
||||
R.anim.slide_up, R.anim.stay_put_350,
|
||||
R.anim.stay_put_350, R.anim.slide_down)
|
||||
}
|
||||
replace(
|
||||
containerId,
|
||||
fragment
|
||||
.withToolbar()
|
||||
.addElevation(appCompatActivity.supportFragmentManager),
|
||||
backstackId)
|
||||
addToBackStack(backstackId)
|
||||
commit()
|
||||
}
|
||||
}
|
||||
|
||||
inline fun <reified T: BaseFragment> T.withToolbar(): T {
|
||||
@ -360,10 +415,6 @@ fun View.setVisible(visible: Boolean) {
|
||||
this.visibility = if (visible) View.VISIBLE else View.GONE
|
||||
}
|
||||
|
||||
inline fun <reified T> FragmentManager.find(tag: String): T {
|
||||
return findFragmentByTag(tag) as T
|
||||
}
|
||||
|
||||
/*
|
||||
*
|
||||
* Colors
|
||||
@ -449,3 +500,16 @@ fun fallback(input: String?, fallback: String): String =
|
||||
|
||||
fun fallback(input: String?, fallback: Int): String =
|
||||
if (input.isNullOrEmpty()) Application.instance.getString(fallback) else input
|
||||
|
||||
fun startActivityForResult(intent: Intent,
|
||||
requestCode: Int,
|
||||
activity: AppCompatActivity?,
|
||||
fragment: BaseFragment? = null) =
|
||||
when {
|
||||
fragment != null ->
|
||||
fragment.startActivityForResult(intent, requestCode)
|
||||
activity != null ->
|
||||
activity.startActivityForResult(intent, requestCode)
|
||||
else ->
|
||||
throw IllegalArgumentException("")
|
||||
}
|
||||
|
@ -9,24 +9,23 @@ import android.support.v4.app.Fragment
|
||||
import android.support.v7.app.AppCompatActivity
|
||||
import android.support.v7.widget.Toolbar
|
||||
import android.view.View
|
||||
import android.view.animation.AlphaAnimation
|
||||
import android.view.animation.Animation
|
||||
import android.view.animation.AnimationUtils
|
||||
import io.casey.musikcube.remote.Application
|
||||
import io.casey.musikcube.remote.R
|
||||
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.injection.DaggerViewComponent
|
||||
import io.casey.musikcube.remote.injection.ViewComponent
|
||||
import io.casey.musikcube.remote.ui.settings.constants.Prefs
|
||||
import io.casey.musikcube.remote.ui.shared.activity.IBackHandler
|
||||
import io.casey.musikcube.remote.ui.shared.activity.ITitleProvider
|
||||
import io.casey.musikcube.remote.ui.shared.extension.collapseActionViewIfExpanded
|
||||
import io.casey.musikcube.remote.ui.shared.extension.setTitleFromIntent
|
||||
import io.casey.musikcube.remote.ui.shared.mixin.ViewModelMixin
|
||||
import io.reactivex.disposables.CompositeDisposable
|
||||
import android.view.animation.AlphaAnimation
|
||||
import android.view.animation.AnimationUtils
|
||||
import io.casey.musikcube.remote.R
|
||||
import io.casey.musikcube.remote.ui.shared.activity.IBackHandler
|
||||
import io.casey.musikcube.remote.ui.shared.extension.collapseActionViewIfExpanded
|
||||
import java.lang.Exception
|
||||
|
||||
|
||||
open class BaseFragment: Fragment(), ViewModel.Provider, IBackHandler {
|
||||
|
@ -1,6 +1,5 @@
|
||||
package io.casey.musikcube.remote.ui.shared.fragment
|
||||
|
||||
import android.content.Intent
|
||||
import android.os.Bundle
|
||||
import android.view.LayoutInflater
|
||||
import android.view.View
|
||||
@ -9,9 +8,11 @@ import android.widget.TextView
|
||||
import io.casey.musikcube.remote.R
|
||||
import io.casey.musikcube.remote.service.playback.PlaybackState
|
||||
import io.casey.musikcube.remote.ui.home.activity.MainActivity
|
||||
import io.casey.musikcube.remote.ui.playqueue.activity.PlayQueueActivity
|
||||
import io.casey.musikcube.remote.ui.navigation.Navigate
|
||||
import io.casey.musikcube.remote.ui.playqueue.fragment.PlayQueueFragment
|
||||
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.extension.topOfStack
|
||||
import io.casey.musikcube.remote.ui.shared.mixin.PlaybackMixin
|
||||
|
||||
class TransportFragment: BaseFragment() {
|
||||
@ -55,12 +56,8 @@ class TransportFragment: BaseFragment() {
|
||||
|
||||
titleBar?.setOnClickListener {
|
||||
if (playback.service.state != PlaybackState.Stopped) {
|
||||
activity?.let { a ->
|
||||
startActivity(PlayQueueActivity
|
||||
.getStartIntent(a, playback.service.queuePosition)
|
||||
.addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP))
|
||||
|
||||
a.overridePendingTransition(R.anim.slide_up, R.anim.stay_put)
|
||||
if (appCompatActivity.supportFragmentManager.topOfStack != PlayQueueFragment.TAG) {
|
||||
Navigate.toPlayQueue(playback.service.queuePosition, appCompatActivity, this)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -20,10 +20,8 @@ import io.casey.musikcube.remote.service.websocket.model.IAlbum
|
||||
import io.casey.musikcube.remote.service.websocket.model.ICategoryValue
|
||||
import io.casey.musikcube.remote.service.websocket.model.IDataProvider
|
||||
import io.casey.musikcube.remote.service.websocket.model.ITrack
|
||||
import io.casey.musikcube.remote.ui.albums.activity.AlbumBrowseActivity
|
||||
import io.casey.musikcube.remote.ui.category.activity.CategoryBrowseActivity
|
||||
import io.casey.musikcube.remote.ui.category.constant.Category
|
||||
import io.casey.musikcube.remote.ui.category.constant.NavigationType
|
||||
import io.casey.musikcube.remote.ui.navigation.Navigate
|
||||
import io.casey.musikcube.remote.ui.shared.extension.hideKeyboard
|
||||
import io.casey.musikcube.remote.ui.shared.extension.showErrorSnackbar
|
||||
import io.casey.musikcube.remote.ui.shared.extension.showKeyboard
|
||||
@ -31,7 +29,6 @@ import io.casey.musikcube.remote.ui.shared.extension.showSnackbar
|
||||
import io.casey.musikcube.remote.ui.shared.fragment.BaseDialogFragment
|
||||
import io.casey.musikcube.remote.ui.shared.fragment.BaseFragment
|
||||
import io.casey.musikcube.remote.ui.tracks.activity.EditPlaylistActivity
|
||||
import io.casey.musikcube.remote.ui.tracks.activity.TrackListActivity
|
||||
import io.reactivex.Observable
|
||||
import io.reactivex.rxkotlin.subscribeBy
|
||||
import javax.inject.Inject
|
||||
@ -159,8 +156,7 @@ class ItemContextMenuMixin(private val activity: AppCompatActivity,
|
||||
}
|
||||
|
||||
private fun viewPlaylist(playlistId: Long, playlistName: String): ((View) -> Unit) = { _ ->
|
||||
activity.startActivity(TrackListActivity.getStartIntent(
|
||||
activity, Metadata.Category.PLAYLISTS, playlistId, playlistName))
|
||||
Navigate.toTracks(Metadata.Category.PLAYLISTS, playlistId, playlistName, activity, fragment)
|
||||
}
|
||||
|
||||
private fun addWithErrorHandler(playlistId: Long, playlistName: String, observable: Observable<Boolean>) {
|
||||
@ -187,14 +183,7 @@ class ItemContextMenuMixin(private val activity: AppCompatActivity,
|
||||
private fun showPlaylistChooser(callback: (Long, String) -> Unit) {
|
||||
completion = callback
|
||||
pendingCode = REQUEST_ADD_TO_PLAYLIST
|
||||
|
||||
val intent = CategoryBrowseActivity.getStartIntent(
|
||||
activity,
|
||||
Metadata.Category.PLAYLISTS,
|
||||
NavigationType.Select,
|
||||
activity.getString(R.string.playlist_edit_pick_playlist))
|
||||
|
||||
startActivityForResult(intent, pendingCode)
|
||||
Navigate.toPlaylistChooser(pendingCode, activity, fragment)
|
||||
}
|
||||
|
||||
fun showForTrack(track: ITrack, anchorView: View) {
|
||||
@ -214,31 +203,31 @@ class ItemContextMenuMixin(private val activity: AppCompatActivity,
|
||||
}
|
||||
|
||||
popup.setOnMenuItemClickListener { item ->
|
||||
val intent: Intent? = when (item.itemId) {
|
||||
when (item.itemId) {
|
||||
R.id.menu_add_to_playlist -> {
|
||||
addToPlaylist(track)
|
||||
null
|
||||
}
|
||||
R.id.menu_remove_from_playlist -> {
|
||||
ConfirmRemoveFromPlaylistDialog.show(
|
||||
activity, this, categoryId, categoryValue, position, track)
|
||||
null
|
||||
}
|
||||
R.id.menu_show_artist_albums -> {
|
||||
AlbumBrowseActivity.getStartIntent(
|
||||
activity, Metadata.Category.ARTIST, track.artistId, track.artist)
|
||||
Navigate.toAlbums(
|
||||
Metadata.Category.ARTIST,
|
||||
track.artistId,
|
||||
track.artist,
|
||||
activity,
|
||||
fragment)
|
||||
}
|
||||
R.id.menu_show_artist_tracks -> {
|
||||
TrackListActivity.getStartIntent(
|
||||
activity, Metadata.Category.ARTIST, track.artistId, track.artist)
|
||||
Navigate.toTracks(
|
||||
Metadata.Category.ARTIST,
|
||||
track.artistId,
|
||||
track.artist,
|
||||
activity,
|
||||
fragment)
|
||||
}
|
||||
else -> null
|
||||
}
|
||||
|
||||
if (intent != null) {
|
||||
activity.startActivity(intent)
|
||||
}
|
||||
|
||||
true
|
||||
}
|
||||
|
||||
@ -255,8 +244,7 @@ class ItemContextMenuMixin(private val activity: AppCompatActivity,
|
||||
ConfirmDeletePlaylistDialog.show(activity, this, playlistName, playlistId)
|
||||
}
|
||||
R.id.menu_playlist_edit -> {
|
||||
startActivityForResult(EditPlaylistActivity.getStartIntent(
|
||||
activity, playlistName, playlistId), REQUEST_EDIT_PLAYLIST)
|
||||
Navigate.toPlaylistEditor(REQUEST_EDIT_PLAYLIST, playlistName, playlistId, activity, fragment)
|
||||
}
|
||||
R.id.menu_playlist_rename -> {
|
||||
EnterPlaylistNameDialog.showForRename(activity, this, playlistName, playlistId)
|
||||
@ -290,54 +278,57 @@ class ItemContextMenuMixin(private val activity: AppCompatActivity,
|
||||
popup.inflate(menuId)
|
||||
|
||||
popup.setOnMenuItemClickListener { item ->
|
||||
val intent: Intent? = when (item.itemId) {
|
||||
when (item.itemId) {
|
||||
R.id.menu_add_to_playlist -> {
|
||||
addToPlaylist(value)
|
||||
null
|
||||
}
|
||||
R.id.menu_show_artist_albums,
|
||||
R.id.menu_show_genre_albums -> {
|
||||
if (value is IAlbum) {
|
||||
AlbumBrowseActivity.getStartIntent(
|
||||
activity,
|
||||
Navigate.toAlbums(
|
||||
Metadata.Category.ALBUM_ARTIST,
|
||||
value.albumArtistId,
|
||||
value.albumArtist)
|
||||
value.albumArtist,
|
||||
activity,
|
||||
fragment)
|
||||
}
|
||||
else {
|
||||
AlbumBrowseActivity.getStartIntent(
|
||||
activity, value.type, value.id, value.value)
|
||||
Navigate.toAlbums(value, activity, fragment)
|
||||
}
|
||||
}
|
||||
R.id.menu_show_artist_tracks,
|
||||
R.id.menu_show_genre_tracks -> {
|
||||
if (value is IAlbum) {
|
||||
TrackListActivity.getStartIntent(
|
||||
activity,
|
||||
Navigate.toTracks(
|
||||
Metadata.Category.ALBUM_ARTIST,
|
||||
value.albumArtistId,
|
||||
value.albumArtist)
|
||||
value.albumArtist,
|
||||
activity,
|
||||
fragment)
|
||||
}
|
||||
else {
|
||||
TrackListActivity.getStartIntent(
|
||||
activity, value.type, value.id, value.value)
|
||||
Navigate.toTracks(value, activity, fragment)
|
||||
}
|
||||
}
|
||||
R.id.menu_show_artist_genres -> {
|
||||
CategoryBrowseActivity.getStartIntent(
|
||||
activity, Metadata.Category.GENRE, value.type, value.id, value.value)
|
||||
Navigate.toCategoryList(
|
||||
Metadata.Category.GENRE,
|
||||
value.type,
|
||||
value.id,
|
||||
value.value,
|
||||
activity,
|
||||
fragment)
|
||||
}
|
||||
R.id.menu_show_genre_artists -> {
|
||||
CategoryBrowseActivity.getStartIntent(
|
||||
activity, Metadata.Category.ARTIST, value.type, value.id, value.value)
|
||||
Navigate.toCategoryList(
|
||||
Metadata.Category.ARTIST,
|
||||
value.type,
|
||||
value.id,
|
||||
value.value,
|
||||
activity,
|
||||
fragment)
|
||||
}
|
||||
else -> null
|
||||
}
|
||||
|
||||
if (intent != null) {
|
||||
activity.startActivity(intent)
|
||||
}
|
||||
|
||||
true
|
||||
}
|
||||
|
||||
@ -387,13 +378,6 @@ class ItemContextMenuMixin(private val activity: AppCompatActivity,
|
||||
private fun showError(message: String) =
|
||||
showErrorSnackbar(activity.findViewById(android.R.id.content), message)
|
||||
|
||||
private fun startActivityForResult(intent: Intent, requestCode: Int) {
|
||||
when (fragment != null) {
|
||||
true -> fragment.startActivityForResult(intent, requestCode)
|
||||
false -> activity.startActivityForResult(intent, requestCode)
|
||||
}
|
||||
}
|
||||
|
||||
class ConfirmRemoveFromPlaylistDialog : BaseDialogFragment() {
|
||||
private lateinit var mixin: ItemContextMenuMixin
|
||||
|
||||
|
@ -12,6 +12,7 @@ import android.view.Menu
|
||||
import android.view.MenuItem
|
||||
import io.casey.musikcube.remote.R
|
||||
import io.casey.musikcube.remote.framework.ViewModel
|
||||
import io.casey.musikcube.remote.ui.navigation.Transition
|
||||
import io.casey.musikcube.remote.ui.shared.activity.BaseActivity
|
||||
import io.casey.musikcube.remote.ui.shared.extension.setupDefaultRecyclerView
|
||||
import io.casey.musikcube.remote.ui.shared.extension.showErrorSnackbar
|
||||
@ -84,6 +85,9 @@ class EditPlaylistActivity: BaseActivity() {
|
||||
return EditPlaylistViewModel(extras.getLong(EXTRA_PLAYLIST_ID, -1L)) as T
|
||||
}
|
||||
|
||||
override val transitionType: Transition
|
||||
get() = Transition.Vertical
|
||||
|
||||
private fun saveAndFinish() {
|
||||
if (viewModel.modified) {
|
||||
disposables.add(viewModel.save().subscribeBy(
|
||||
|
@ -37,13 +37,13 @@ class TrackListActivity: FragmentActivityWithTransport() {
|
||||
}
|
||||
|
||||
fun getStartIntent(context: Context,
|
||||
type: String = "",
|
||||
id: Long = 0,
|
||||
categoryType: String = "",
|
||||
categoryId: Long = 0,
|
||||
categoryValue: String = ""): Intent =
|
||||
Intent(context, TrackListActivity::class.java).apply {
|
||||
putExtra(
|
||||
Track.Extra.FRAGMENT_ARGUMENTS,
|
||||
TrackListFragment.arguments(context, type, id, categoryValue))
|
||||
TrackListFragment.arguments(context, categoryType, categoryId, categoryValue))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -12,7 +12,6 @@ import io.casey.musikcube.remote.service.playback.impl.remote.Metadata
|
||||
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.ITrackListQueryFactory
|
||||
import io.casey.musikcube.remote.ui.home.activity.MainActivity
|
||||
import io.casey.musikcube.remote.ui.shared.activity.IFilterable
|
||||
import io.casey.musikcube.remote.ui.shared.activity.IMenuProvider
|
||||
import io.casey.musikcube.remote.ui.shared.activity.ITitleProvider
|
||||
@ -258,9 +257,6 @@ class TrackListFragment: BaseFragment(), IFilterable, ITitleProvider, ITransport
|
||||
else {
|
||||
playback.service.playAll(position, lastFilter)
|
||||
}
|
||||
|
||||
startActivity(MainActivity.getStartIntent(appCompatActivity))
|
||||
appCompatActivity.finish() /* TODO: hmmm? */
|
||||
}
|
||||
|
||||
override fun onActionItemClick(view: View, track: ITrack, position: Int) {
|
||||
@ -278,11 +274,11 @@ class TrackListFragment: BaseFragment(), IFilterable, ITitleProvider, ITransport
|
||||
const val TAG = "TrackListFragment"
|
||||
|
||||
fun arguments(context: Context,
|
||||
type: String = "",
|
||||
id: Long = 0,
|
||||
categoryType: String = "",
|
||||
categoryId: Long = 0,
|
||||
categoryValue: String = ""): Bundle = Bundle().apply {
|
||||
putString(Track.Extra.CATEGORY_TYPE, type)
|
||||
putLong(Track.Extra.SELECTED_ID, id)
|
||||
putLong(Track.Extra.SELECTED_ID, categoryId)
|
||||
putString(Track.Extra.CATEGORY_TYPE, categoryType)
|
||||
putString(Track.Extra.CATEGORY_VALUE, categoryValue)
|
||||
if (Strings.notEmpty(categoryValue)) {
|
||||
putString(
|
||||
@ -291,15 +287,13 @@ class TrackListFragment: BaseFragment(), IFilterable, ITitleProvider, ITransport
|
||||
}
|
||||
}
|
||||
|
||||
fun create(intent: Intent?): TrackListFragment {
|
||||
return create(intent?.extras?.getBundle(Track.Extra.FRAGMENT_ARGUMENTS) ?: Bundle())
|
||||
}
|
||||
fun create(intent: Intent?): TrackListFragment =
|
||||
create(intent?.extras?.getBundle(Track.Extra.FRAGMENT_ARGUMENTS) ?: Bundle())
|
||||
|
||||
fun create(arguments: Bundle = Bundle()): TrackListFragment {
|
||||
return TrackListFragment().apply {
|
||||
fun create(arguments: Bundle = Bundle()): TrackListFragment =
|
||||
TrackListFragment().apply {
|
||||
this.arguments = arguments
|
||||
}
|
||||
}
|
||||
|
||||
private fun isValidCategory(categoryType: String?, categoryId: Long): Boolean =
|
||||
categoryType != null && categoryType.isNotEmpty() && categoryId != -1L
|
||||
|
@ -1,6 +1,6 @@
|
||||
<set xmlns:android="http://schemas.android.com/apk/res/android" >
|
||||
<translate
|
||||
android:duration="250"
|
||||
android:duration="350"
|
||||
android:interpolator="@android:anim/accelerate_interpolator"
|
||||
android:fromYDelta="100%"
|
||||
android:toYDelta="0" />
|
||||
|
@ -1,6 +1,6 @@
|
||||
<set xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<translate
|
||||
android:duration="250"
|
||||
android:fromYDelta="0%p"
|
||||
android:fromYDelta="0"
|
||||
android:toYDelta="0" />
|
||||
</set>
|
6
src/musikdroid/app/src/main/res/anim/stay_put_350.xml
Normal file
6
src/musikdroid/app/src/main/res/anim/stay_put_350.xml
Normal file
@ -0,0 +1,6 @@
|
||||
<set xmlns:android="http://schemas.android.com/apk/res/android" >
|
||||
<translate
|
||||
android:duration="350"
|
||||
android:fromYDelta="0"
|
||||
android:toYDelta="0" />
|
||||
</set>
|
Loading…
x
Reference in New Issue
Block a user