mirror of
https://gitlab.futo.org/videostreaming/grayjay.git
synced 2025-04-20 03:24:50 +00:00
Added support for long-press gesture to open options menu.
This commit is contained in:
parent
116dc90d21
commit
d34cb0f9c1
9 changed files with 111 additions and 25 deletions
|
@ -27,6 +27,7 @@ import com.futo.platformplayer.views.adapters.InsertedViewHolder
|
|||
import com.futo.platformplayer.views.adapters.PreviewNestedVideoViewHolder
|
||||
import com.futo.platformplayer.views.adapters.PreviewVideoViewHolder
|
||||
import com.futo.platformplayer.views.overlays.slideup.SlideUpMenuItem
|
||||
import com.futo.platformplayer.views.overlays.slideup.SlideUpMenuOverlay
|
||||
import kotlin.math.floor
|
||||
|
||||
abstract class ContentFeedView<TFragment> : FeedView<TFragment, IPlatformContent, IPlatformContent, IPager<IPlatformContent>, ContentPreviewViewHolder> where TFragment : MainFragment {
|
||||
|
@ -37,6 +38,7 @@ abstract class ContentFeedView<TFragment> : FeedView<TFragment, IPlatformContent
|
|||
private var _previewsEnabled: Boolean = true;
|
||||
override val visibleThreshold: Int get() = if (feedStyle == FeedStyle.PREVIEW) { 5 } else { 10 };
|
||||
protected lateinit var headerView: LinearLayout;
|
||||
private var _videoOptionsOverlay: SlideUpMenuOverlay? = null;
|
||||
|
||||
constructor(fragment: TFragment, inflater: LayoutInflater, cachedRecyclerData: RecyclerData<InsertedViewAdapterWithLoader<ContentPreviewViewHolder>, LinearLayoutManager, IPager<IPlatformContent>, IPlatformContent, IPlatformContent, InsertedViewHolder<ContentPreviewViewHolder>>? = null) : super(fragment, inflater, cachedRecyclerData) {
|
||||
|
||||
|
@ -70,26 +72,8 @@ abstract class ContentFeedView<TFragment> : FeedView<TFragment, IPlatformContent
|
|||
adapter.onChannelClicked.subscribe(this) { fragment.navigate<ChannelFragment>(it) };
|
||||
adapter.onAddToClicked.subscribe(this) { content ->
|
||||
//TODO: Reconstruct search video from detail if search is null
|
||||
_overlayContainer.let {
|
||||
if(content is IPlatformVideo)
|
||||
UISlideOverlays.showVideoOptionsOverlay(content, it, SlideUpMenuItem(context, R.drawable.ic_visibility_off, context.getString(R.string.hide), context.getString(R.string.hide_from_home), "hide",
|
||||
{ StateMeta.instance.addHiddenVideo(content.url);
|
||||
if (fragment is HomeFragment) {
|
||||
val removeIndex = recyclerData.results.indexOf(content);
|
||||
if (removeIndex >= 0) {
|
||||
recyclerData.results.removeAt(removeIndex);
|
||||
recyclerData.adapter.notifyItemRemoved(recyclerData.adapter.childToParentPosition(removeIndex));
|
||||
}
|
||||
}
|
||||
}),
|
||||
SlideUpMenuItem(context, R.drawable.ic_playlist, context.getString(R.string.play_feed_as_queue), context.getString(R.string.play_entire_feed), "playFeed",
|
||||
{
|
||||
val newQueue = listOf(content) + recyclerData.results
|
||||
.filterIsInstance<IPlatformVideo>()
|
||||
.filter { it != content };
|
||||
StatePlayer.instance.setQueue(newQueue, StatePlayer.TYPE_QUEUE, "Feed Queue", true, false);
|
||||
})
|
||||
);
|
||||
if(content is IPlatformVideo) {
|
||||
showVideoOptionsOverlay(content)
|
||||
}
|
||||
};
|
||||
adapter.onAddToQueueClicked.subscribe(this) {
|
||||
|
@ -99,6 +83,50 @@ abstract class ContentFeedView<TFragment> : FeedView<TFragment, IPlatformContent
|
|||
UIDialogs.toast(context, context.getString(R.string.queued) + " [$name]", false);
|
||||
}
|
||||
};
|
||||
adapter.onLongPress.subscribe(this) {
|
||||
if (it is IPlatformVideo) {
|
||||
showVideoOptionsOverlay(it)
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
fun onBackPressed(): Boolean {
|
||||
val videoOptionsOverlay = _videoOptionsOverlay
|
||||
if (videoOptionsOverlay != null) {
|
||||
if (videoOptionsOverlay.isVisible) {
|
||||
videoOptionsOverlay.hide();
|
||||
_videoOptionsOverlay = null
|
||||
return true;
|
||||
}
|
||||
|
||||
_videoOptionsOverlay = null
|
||||
return false
|
||||
}
|
||||
|
||||
return false
|
||||
}
|
||||
|
||||
private fun showVideoOptionsOverlay(content: IPlatformVideo) {
|
||||
_overlayContainer.let {
|
||||
_videoOptionsOverlay = UISlideOverlays.showVideoOptionsOverlay(content, it, SlideUpMenuItem(context, R.drawable.ic_visibility_off, context.getString(R.string.hide), context.getString(R.string.hide_from_home), "hide",
|
||||
{ StateMeta.instance.addHiddenVideo(content.url);
|
||||
if (fragment is HomeFragment) {
|
||||
val removeIndex = recyclerData.results.indexOf(content);
|
||||
if (removeIndex >= 0) {
|
||||
recyclerData.results.removeAt(removeIndex);
|
||||
recyclerData.adapter.notifyItemRemoved(recyclerData.adapter.childToParentPosition(removeIndex));
|
||||
}
|
||||
}
|
||||
}),
|
||||
SlideUpMenuItem(context, R.drawable.ic_playlist, context.getString(R.string.play_feed_as_queue), context.getString(R.string.play_entire_feed), "playFeed",
|
||||
{
|
||||
val newQueue = listOf(content) + recyclerData.results
|
||||
.filterIsInstance<IPlatformVideo>()
|
||||
.filter { it != content };
|
||||
StatePlayer.instance.setQueue(newQueue, StatePlayer.TYPE_QUEUE, "Feed Queue", true, false);
|
||||
})
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
private fun detachAdapterEvents() {
|
||||
|
@ -108,6 +136,7 @@ abstract class ContentFeedView<TFragment> : FeedView<TFragment, IPlatformContent
|
|||
adapter.onChannelClicked.remove(this);
|
||||
adapter.onAddToClicked.remove(this);
|
||||
adapter.onAddToQueueClicked.remove(this);
|
||||
adapter.onLongPress.remove(this);
|
||||
}
|
||||
|
||||
override fun onRestoreCachedData(cachedData: RecyclerData<InsertedViewAdapterWithLoader<ContentPreviewViewHolder>, LinearLayoutManager, IPager<IPlatformContent>, IPlatformContent, IPlatformContent, InsertedViewHolder<ContentPreviewViewHolder>>) {
|
||||
|
|
|
@ -62,6 +62,13 @@ class ContentSearchResultsFragment : MainFragment() {
|
|||
_view = null;
|
||||
}
|
||||
|
||||
override fun onBackPressed(): Boolean {
|
||||
if (_view?.onBackPressed() == true)
|
||||
return true
|
||||
|
||||
return super.onBackPressed()
|
||||
}
|
||||
|
||||
fun setPreviewsEnabled(previewsEnabled: Boolean) {
|
||||
_view?.setPreviewsEnabled(previewsEnabled && Settings.instance.search.previewFeedItems);
|
||||
}
|
||||
|
|
|
@ -66,6 +66,13 @@ class HomeFragment : MainFragment() {
|
|||
return view;
|
||||
}
|
||||
|
||||
override fun onBackPressed(): Boolean {
|
||||
if (_view?.onBackPressed() == true)
|
||||
return true
|
||||
|
||||
return super.onBackPressed()
|
||||
}
|
||||
|
||||
override fun onDestroyMainView() {
|
||||
super.onDestroyMainView();
|
||||
|
||||
|
|
|
@ -44,6 +44,13 @@ class PlaylistSearchResultsFragment : MainFragment() {
|
|||
return view;
|
||||
}
|
||||
|
||||
override fun onBackPressed(): Boolean {
|
||||
if (_view?.onBackPressed() == true)
|
||||
return true
|
||||
|
||||
return super.onBackPressed()
|
||||
}
|
||||
|
||||
override fun onDestroyMainView() {
|
||||
super.onDestroyMainView();
|
||||
_view?.cleanup();
|
||||
|
|
|
@ -80,6 +80,13 @@ class SubscriptionsFeedFragment : MainFragment() {
|
|||
}
|
||||
}
|
||||
|
||||
override fun onBackPressed(): Boolean {
|
||||
if (_view?.onBackPressed() == true)
|
||||
return true
|
||||
|
||||
return super.onBackPressed()
|
||||
}
|
||||
|
||||
fun setPreviewsEnabled(previewsEnabled: Boolean) {
|
||||
_view?.setPreviewsEnabled(previewsEnabled && Settings.instance.subscriptions.previewFeedItems);
|
||||
}
|
||||
|
|
|
@ -32,6 +32,7 @@ class PreviewContentListAdapter : InsertedViewAdapterWithLoader<ContentPreviewVi
|
|||
val onChannelClicked = Event1<PlatformAuthorLink>();
|
||||
val onAddToClicked = Event1<IPlatformContent>();
|
||||
val onAddToQueueClicked = Event1<IPlatformContent>();
|
||||
val onLongPress = Event1<IPlatformContent>();
|
||||
|
||||
private var _taskLoadContent = TaskHandler<Pair<ContentPreviewViewHolder, IPlatformContent>, Pair<ContentPreviewViewHolder, IPlatformContentDetails>>(
|
||||
StateApp.instance.scopeGetter, { (viewHolder, video) ->
|
||||
|
@ -93,6 +94,7 @@ class PreviewContentListAdapter : InsertedViewAdapterWithLoader<ContentPreviewVi
|
|||
this.onChannelClicked.subscribe(this@PreviewContentListAdapter.onChannelClicked::emit);
|
||||
this.onAddToClicked.subscribe(this@PreviewContentListAdapter.onAddToClicked::emit);
|
||||
this.onAddToQueueClicked.subscribe(this@PreviewContentListAdapter.onAddToQueueClicked::emit);
|
||||
this.onLongPress.subscribe(this@PreviewContentListAdapter.onLongPress::emit);
|
||||
};
|
||||
private fun createPlaylistViewHolder(viewGroup: ViewGroup): PreviewPlaylistViewHolder = PreviewPlaylistViewHolder(viewGroup, _feedStyle).apply {
|
||||
this.onPlaylistClicked.subscribe { this@PreviewContentListAdapter.onContentClicked.emit(it, 0L) };
|
||||
|
|
|
@ -68,6 +68,7 @@ open class PreviewVideoView : LinearLayout {
|
|||
};
|
||||
|
||||
val onVideoClicked = Event2<IPlatformVideo, Long>();
|
||||
val onLongPress = Event1<IPlatformVideo>();
|
||||
val onChannelClicked = Event1<PlatformAuthorLink>();
|
||||
val onAddToClicked = Event1<IPlatformVideo>();
|
||||
val onAddToQueueClicked = Event1<IPlatformVideo>();
|
||||
|
@ -119,7 +120,13 @@ open class PreviewVideoView : LinearLayout {
|
|||
|
||||
this._exoPlayer = exoPlayer
|
||||
|
||||
setOnClickListener { onOpenClicked() };
|
||||
setOnLongClickListener {
|
||||
onLongPress()
|
||||
true
|
||||
};
|
||||
setOnClickListener {
|
||||
onOpenClicked()
|
||||
};
|
||||
_imageChannel.setOnClickListener { currentVideo?.let { onChannelClicked.emit(it.author) } };
|
||||
_textChannelName.setOnClickListener { currentVideo?.let { onChannelClicked.emit(it.author) } };
|
||||
_textVideoMetadata.setOnClickListener { currentVideo?.let { onChannelClicked.emit(it.author) } };
|
||||
|
@ -145,6 +152,12 @@ open class PreviewVideoView : LinearLayout {
|
|||
}
|
||||
}
|
||||
|
||||
protected open fun onLongPress() {
|
||||
currentVideo?.let {
|
||||
onLongPress.emit(it);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
open fun bind(content: IPlatformContent) {
|
||||
_taskLoadProfile.cancel();
|
||||
|
|
|
@ -17,6 +17,7 @@ class PreviewVideoViewHolder : ContentPreviewViewHolder {
|
|||
val onChannelClicked = Event1<PlatformAuthorLink>();
|
||||
val onAddToClicked = Event1<IPlatformVideo>();
|
||||
val onAddToQueueClicked = Event1<IPlatformVideo>();
|
||||
val onLongPress = Event1<IPlatformVideo>();
|
||||
|
||||
//val context: Context;
|
||||
val currentVideo: IPlatformVideo? get() = view.currentVideo;
|
||||
|
@ -30,6 +31,7 @@ class PreviewVideoViewHolder : ContentPreviewViewHolder {
|
|||
view.onChannelClicked.subscribe(onChannelClicked::emit);
|
||||
view.onAddToClicked.subscribe(onAddToClicked::emit);
|
||||
view.onAddToQueueClicked.subscribe(onAddToQueueClicked::emit);
|
||||
view.onLongPress.subscribe(onLongPress::emit);
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -134,6 +134,10 @@ class SlideUpMenuOverlay : RelativeLayout {
|
|||
}
|
||||
|
||||
fun show(){
|
||||
if (isVisible) {
|
||||
return;
|
||||
}
|
||||
|
||||
isVisible = true;
|
||||
_container?.post {
|
||||
_container?.visibility = View.VISIBLE;
|
||||
|
@ -146,8 +150,8 @@ class SlideUpMenuOverlay : RelativeLayout {
|
|||
_viewBackground.alpha = 0f;
|
||||
|
||||
val animations = arrayListOf<Animator>();
|
||||
animations.add(ObjectAnimator.ofFloat(_viewBackground, "alpha", 0.0f, 1.0f).setDuration(500));
|
||||
animations.add(ObjectAnimator.ofFloat(_viewOverlayContainer, "translationY", _viewOverlayContainer.measuredHeight.toFloat(), 0.0f).setDuration(500));
|
||||
animations.add(ObjectAnimator.ofFloat(_viewBackground, "alpha", 0.0f, 1.0f).setDuration(ANIMATION_DURATION_MS));
|
||||
animations.add(ObjectAnimator.ofFloat(_viewOverlayContainer, "translationY", _viewOverlayContainer.measuredHeight.toFloat(), 0.0f).setDuration(ANIMATION_DURATION_MS));
|
||||
|
||||
val animatorSet = AnimatorSet();
|
||||
animatorSet.playTogether(animations);
|
||||
|
@ -159,11 +163,15 @@ class SlideUpMenuOverlay : RelativeLayout {
|
|||
}
|
||||
|
||||
fun hide(animate: Boolean = true){
|
||||
if (!isVisible) {
|
||||
return
|
||||
}
|
||||
|
||||
isVisible = false;
|
||||
if (_animated && animate) {
|
||||
val animations = arrayListOf<Animator>();
|
||||
animations.add(ObjectAnimator.ofFloat(_viewBackground, "alpha", 1.0f, 0.0f).setDuration(500));
|
||||
animations.add(ObjectAnimator.ofFloat(_viewOverlayContainer, "translationY", 0.0f, _viewOverlayContainer.measuredHeight.toFloat()).setDuration(500));
|
||||
animations.add(ObjectAnimator.ofFloat(_viewBackground, "alpha", 1.0f, 0.0f).setDuration(ANIMATION_DURATION_MS));
|
||||
animations.add(ObjectAnimator.ofFloat(_viewOverlayContainer, "translationY", 0.0f, _viewOverlayContainer.measuredHeight.toFloat()).setDuration(ANIMATION_DURATION_MS));
|
||||
|
||||
val animatorSet = AnimatorSet();
|
||||
animatorSet.doOnEnd {
|
||||
|
@ -180,4 +188,8 @@ class SlideUpMenuOverlay : RelativeLayout {
|
|||
_container?.visibility = View.GONE;
|
||||
}
|
||||
}
|
||||
|
||||
companion object {
|
||||
private const val ANIMATION_DURATION_MS = 350L
|
||||
}
|
||||
}
|
Loading…
Add table
Reference in a new issue