diff --git a/src/musikdroid/app/src/main/java/io/casey/musikcube/remote/injection/ViewComponent.kt b/src/musikdroid/app/src/main/java/io/casey/musikcube/remote/injection/ViewComponent.kt index 344b6f653..51e43774b 100644 --- a/src/musikdroid/app/src/main/java/io/casey/musikcube/remote/injection/ViewComponent.kt +++ b/src/musikdroid/app/src/main/java/io/casey/musikcube/remote/injection/ViewComponent.kt @@ -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) diff --git a/src/musikdroid/app/src/main/java/io/casey/musikcube/remote/ui/albums/fragment/AlbumBrowseFragment.kt b/src/musikdroid/app/src/main/java/io/casey/musikcube/remote/ui/albums/fragment/AlbumBrowseFragment.kt index 7f90e62f5..53ea5a4f6 100644 --- a/src/musikdroid/app/src/main/java/io/casey/musikcube/remote/ui/albums/fragment/AlbumBrowseFragment.kt +++ b/src/musikdroid/app/src/main/java/io/casey/musikcube/remote/ui/albums/fragment/AlbumBrowseFragment.kt @@ -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) { diff --git a/src/musikdroid/app/src/main/java/io/casey/musikcube/remote/ui/browse/activity/BrowseActivity.kt b/src/musikdroid/app/src/main/java/io/casey/musikcube/remote/ui/browse/activity/BrowseActivity.kt index 7c2f6f62b..0c9e1896b 100644 --- a/src/musikdroid/app/src/main/java/io/casey/musikcube/remote/ui/browse/activity/BrowseActivity.kt +++ b/src/musikdroid/app/src/main/java/io/casey/musikcube/remote/ui/browse/activity/BrowseActivity.kt @@ -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() diff --git a/src/musikdroid/app/src/main/java/io/casey/musikcube/remote/ui/browse/adapter/BrowseFragmentAdapter.kt b/src/musikdroid/app/src/main/java/io/casey/musikcube/remote/ui/browse/adapter/BrowseFragmentAdapter.kt index afbe299da..400db8f14 100644 --- a/src/musikdroid/app/src/main/java/io/casey/musikcube/remote/ui/browse/adapter/BrowseFragmentAdapter.kt +++ b/src/musikdroid/app/src/main/java/io/casey/musikcube/remote/ui/browse/adapter/BrowseFragmentAdapter.kt @@ -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, diff --git a/src/musikdroid/app/src/main/java/io/casey/musikcube/remote/ui/category/activity/CategoryBrowseActivity.kt b/src/musikdroid/app/src/main/java/io/casey/musikcube/remote/ui/category/activity/CategoryBrowseActivity.kt index c46a6c0c0..83376c928 100644 --- a/src/musikdroid/app/src/main/java/io/casey/musikcube/remote/ui/category/activity/CategoryBrowseActivity.kt +++ b/src/musikdroid/app/src/main/java/io/casey/musikcube/remote/ui/category/activity/CategoryBrowseActivity.kt @@ -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() diff --git a/src/musikdroid/app/src/main/java/io/casey/musikcube/remote/ui/category/fragment/CategoryBrowseFragment.kt b/src/musikdroid/app/src/main/java/io/casey/musikcube/remote/ui/category/fragment/CategoryBrowseFragment.kt index 19ac6aaa6..56a5e3ea3 100644 --- a/src/musikdroid/app/src/main/java/io/casey/musikcube/remote/ui/category/fragment/CategoryBrowseFragment.kt +++ b/src/musikdroid/app/src/main/java/io/casey/musikcube/remote/ui/category/fragment/CategoryBrowseFragment.kt @@ -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)) } } } diff --git a/src/musikdroid/app/src/main/java/io/casey/musikcube/remote/ui/navigation/Navigate.kt b/src/musikdroid/app/src/main/java/io/casey/musikcube/remote/ui/navigation/Navigate.kt new file mode 100644 index 000000000..a88a906bc --- /dev/null +++ b/src/musikdroid/app/src/main/java/io/casey/musikcube/remote/ui/navigation/Navigate.kt @@ -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)) + } + } +} \ No newline at end of file diff --git a/src/musikdroid/app/src/main/java/io/casey/musikcube/remote/ui/navigation/Transition.kt b/src/musikdroid/app/src/main/java/io/casey/musikcube/remote/ui/navigation/Transition.kt new file mode 100644 index 000000000..1539e9e2b --- /dev/null +++ b/src/musikdroid/app/src/main/java/io/casey/musikcube/remote/ui/navigation/Transition.kt @@ -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 + } +} \ No newline at end of file diff --git a/src/musikdroid/app/src/main/java/io/casey/musikcube/remote/ui/playqueue/activity/PlayQueueActivity.kt b/src/musikdroid/app/src/main/java/io/casey/musikcube/remote/ui/playqueue/activity/PlayQueueActivity.kt index 1e82f2a87..983f8475c 100644 --- a/src/musikdroid/app/src/main/java/io/casey/musikcube/remote/ui/playqueue/activity/PlayQueueActivity.kt +++ b/src/musikdroid/app/src/main/java/io/casey/musikcube/remote/ui/playqueue/activity/PlayQueueActivity.kt @@ -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(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) } } } diff --git a/src/musikdroid/app/src/main/java/io/casey/musikcube/remote/ui/playqueue/constant/PlayQueue.kt b/src/musikdroid/app/src/main/java/io/casey/musikcube/remote/ui/playqueue/constant/PlayQueue.kt new file mode 100644 index 000000000..223718866 --- /dev/null +++ b/src/musikdroid/app/src/main/java/io/casey/musikcube/remote/ui/playqueue/constant/PlayQueue.kt @@ -0,0 +1,7 @@ +package io.casey.musikcube.remote.ui.playqueue.constant + +object PlayQueue { + object Extra { + const val PLAYING_INDEX = "extra_playing_index" + } +} \ No newline at end of file diff --git a/src/musikdroid/app/src/main/java/io/casey/musikcube/remote/ui/playqueue/fragment/PlayQueueFragment.kt b/src/musikdroid/app/src/main/java/io/casey/musikcube/remote/ui/playqueue/fragment/PlayQueueFragment.kt new file mode 100644 index 000000000..020530c0f --- /dev/null +++ b/src/musikdroid/app/src/main/java/io/casey/musikcube/remote/ui/playqueue/fragment/PlayQueueFragment.kt @@ -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(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) + } + } + } +} \ No newline at end of file diff --git a/src/musikdroid/app/src/main/java/io/casey/musikcube/remote/ui/settings/activity/RemoteSettingsActivity.kt b/src/musikdroid/app/src/main/java/io/casey/musikcube/remote/ui/settings/activity/RemoteSettingsActivity.kt index 67ebb785b..f3ef65ca2 100644 --- a/src/musikdroid/app/src/main/java/io/casey/musikcube/remote/ui/settings/activity/RemoteSettingsActivity.kt +++ b/src/musikdroid/app/src/main/java/io/casey/musikcube/remote/ui/settings/activity/RemoteSettingsActivity.kt @@ -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 diff --git a/src/musikdroid/app/src/main/java/io/casey/musikcube/remote/ui/settings/activity/SettingsActivity.kt b/src/musikdroid/app/src/main/java/io/casey/musikcube/remote/ui/settings/activity/SettingsActivity.kt index c119d8aa2..19df923b5 100644 --- a/src/musikdroid/app/src/main/java/io/casey/musikcube/remote/ui/settings/activity/SettingsActivity.kt +++ b/src/musikdroid/app/src/main/java/io/casey/musikcube/remote/ui/settings/activity/SettingsActivity.kt @@ -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 diff --git a/src/musikdroid/app/src/main/java/io/casey/musikcube/remote/ui/shared/activity/BaseActivity.kt b/src/musikdroid/app/src/main/java/io/casey/musikcube/remote/ui/shared/activity/BaseActivity.kt index 65a312c2e..924e6f263 100644 --- a/src/musikdroid/app/src/main/java/io/casey/musikcube/remote/ui/shared/activity/BaseActivity.kt +++ b/src/musikdroid/app/src/main/java/io/casey/musikcube/remote/ui/shared/activity/BaseActivity.kt @@ -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 diff --git a/src/musikdroid/app/src/main/java/io/casey/musikcube/remote/ui/shared/activity/FragmentActivityWithTransport.kt b/src/musikdroid/app/src/main/java/io/casey/musikcube/remote/ui/shared/activity/FragmentActivityWithTransport.kt index b9a4f0235..db4d2b65d 100644 --- a/src/musikdroid/app/src/main/java/io/casey/musikcube/remote/ui/shared/activity/FragmentActivityWithTransport.kt +++ b/src/musikdroid/app/src/main/java/io/casey/musikcube/remote/ui/shared/activity/FragmentActivityWithTransport.kt @@ -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) } \ No newline at end of file diff --git a/src/musikdroid/app/src/main/java/io/casey/musikcube/remote/ui/shared/constant/Shared.kt b/src/musikdroid/app/src/main/java/io/casey/musikcube/remote/ui/shared/constant/Shared.kt index 3bc525fed..f865974ec 100644 --- a/src/musikdroid/app/src/main/java/io/casey/musikcube/remote/ui/shared/constant/Shared.kt +++ b/src/musikdroid/app/src/main/java/io/casey/musikcube/remote/ui/shared/constant/Shared.kt @@ -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" } } \ No newline at end of file diff --git a/src/musikdroid/app/src/main/java/io/casey/musikcube/remote/ui/shared/extension/Extensions.kt b/src/musikdroid/app/src/main/java/io/casey/musikcube/remote/ui/shared/extension/Extensions.kt index af6225fdc..94e5d5fde 100644 --- a/src/musikdroid/app/src/main/java/io/casey/musikcube/remote/ui/shared/extension/Extensions.kt +++ b/src/musikdroid/app/src/main/java/io/casey/musikcube/remote/ui/shared/extension/Extensions.kt @@ -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 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 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 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 T.withToolbar(): T { @@ -360,10 +415,6 @@ fun View.setVisible(visible: Boolean) { this.visibility = if (visible) View.VISIBLE else View.GONE } -inline fun 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("") + } diff --git a/src/musikdroid/app/src/main/java/io/casey/musikcube/remote/ui/shared/fragment/BaseFragment.kt b/src/musikdroid/app/src/main/java/io/casey/musikcube/remote/ui/shared/fragment/BaseFragment.kt index 803109068..1211192a0 100644 --- a/src/musikdroid/app/src/main/java/io/casey/musikcube/remote/ui/shared/fragment/BaseFragment.kt +++ b/src/musikdroid/app/src/main/java/io/casey/musikcube/remote/ui/shared/fragment/BaseFragment.kt @@ -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 { diff --git a/src/musikdroid/app/src/main/java/io/casey/musikcube/remote/ui/shared/fragment/TransportFragment.kt b/src/musikdroid/app/src/main/java/io/casey/musikcube/remote/ui/shared/fragment/TransportFragment.kt index ae7165c6d..a8368f9d9 100644 --- a/src/musikdroid/app/src/main/java/io/casey/musikcube/remote/ui/shared/fragment/TransportFragment.kt +++ b/src/musikdroid/app/src/main/java/io/casey/musikcube/remote/ui/shared/fragment/TransportFragment.kt @@ -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) } } } diff --git a/src/musikdroid/app/src/main/java/io/casey/musikcube/remote/ui/shared/mixin/ItemContextMenuMixin.kt b/src/musikdroid/app/src/main/java/io/casey/musikcube/remote/ui/shared/mixin/ItemContextMenuMixin.kt index 28f73feee..2bd4fdbea 100644 --- a/src/musikdroid/app/src/main/java/io/casey/musikcube/remote/ui/shared/mixin/ItemContextMenuMixin.kt +++ b/src/musikdroid/app/src/main/java/io/casey/musikcube/remote/ui/shared/mixin/ItemContextMenuMixin.kt @@ -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) { @@ -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 diff --git a/src/musikdroid/app/src/main/java/io/casey/musikcube/remote/ui/tracks/activity/EditPlaylistActivity.kt b/src/musikdroid/app/src/main/java/io/casey/musikcube/remote/ui/tracks/activity/EditPlaylistActivity.kt index 36478ea89..5d1a47f0d 100644 --- a/src/musikdroid/app/src/main/java/io/casey/musikcube/remote/ui/tracks/activity/EditPlaylistActivity.kt +++ b/src/musikdroid/app/src/main/java/io/casey/musikcube/remote/ui/tracks/activity/EditPlaylistActivity.kt @@ -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( diff --git a/src/musikdroid/app/src/main/java/io/casey/musikcube/remote/ui/tracks/activity/TrackListActivity.kt b/src/musikdroid/app/src/main/java/io/casey/musikcube/remote/ui/tracks/activity/TrackListActivity.kt index a458d45c3..a880f3763 100644 --- a/src/musikdroid/app/src/main/java/io/casey/musikcube/remote/ui/tracks/activity/TrackListActivity.kt +++ b/src/musikdroid/app/src/main/java/io/casey/musikcube/remote/ui/tracks/activity/TrackListActivity.kt @@ -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)) } } } diff --git a/src/musikdroid/app/src/main/java/io/casey/musikcube/remote/ui/tracks/fragment/TrackListFragment.kt b/src/musikdroid/app/src/main/java/io/casey/musikcube/remote/ui/tracks/fragment/TrackListFragment.kt index dd6b90489..45d349723 100644 --- a/src/musikdroid/app/src/main/java/io/casey/musikcube/remote/ui/tracks/fragment/TrackListFragment.kt +++ b/src/musikdroid/app/src/main/java/io/casey/musikcube/remote/ui/tracks/fragment/TrackListFragment.kt @@ -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 diff --git a/src/musikdroid/app/src/main/res/anim/slide_up.xml b/src/musikdroid/app/src/main/res/anim/slide_up.xml index ac183e5ba..4dd79d902 100644 --- a/src/musikdroid/app/src/main/res/anim/slide_up.xml +++ b/src/musikdroid/app/src/main/res/anim/slide_up.xml @@ -1,6 +1,6 @@ diff --git a/src/musikdroid/app/src/main/res/anim/stay_put.xml b/src/musikdroid/app/src/main/res/anim/stay_put_250.xml similarity index 81% rename from src/musikdroid/app/src/main/res/anim/stay_put.xml rename to src/musikdroid/app/src/main/res/anim/stay_put_250.xml index 74967b989..f5e2cd329 100644 --- a/src/musikdroid/app/src/main/res/anim/stay_put.xml +++ b/src/musikdroid/app/src/main/res/anim/stay_put_250.xml @@ -1,6 +1,6 @@ \ No newline at end of file diff --git a/src/musikdroid/app/src/main/res/anim/stay_put_350.xml b/src/musikdroid/app/src/main/res/anim/stay_put_350.xml new file mode 100644 index 000000000..ab7b417fd --- /dev/null +++ b/src/musikdroid/app/src/main/res/anim/stay_put_350.xml @@ -0,0 +1,6 @@ + + + \ No newline at end of file