Merge pull request #247 from clangen/clangen/android_ui_3

Deeper down the rabbit hole...
This commit is contained in:
casey langen 2019-02-16 23:11:09 -08:00 committed by GitHub
commit bcec21dc28
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
26 changed files with 568 additions and 331 deletions

View File

@ -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)

View File

@ -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) {

View File

@ -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()

View File

@ -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,

View File

@ -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()

View File

@ -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))
}
}
}

View File

@ -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))
}
}
}

View File

@ -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
}
}

View File

@ -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)
}
}
}

View File

@ -0,0 +1,7 @@
package io.casey.musikcube.remote.ui.playqueue.constant
object PlayQueue {
object Extra {
const val PLAYING_INDEX = "extra_playing_index"
}
}

View File

@ -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)
}
}
}
}

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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)
}

View File

@ -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"
}
}

View File

@ -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("")
}

View File

@ -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 {

View File

@ -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)
}
}
}

View File

@ -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

View File

@ -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(

View File

@ -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))
}
}
}

View File

@ -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

View File

@ -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" />

View File

@ -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>

View 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>