Skip to content

Commit

Permalink
Add stream segments to player
Browse files Browse the repository at this point in the history
  • Loading branch information
vkay94 committed Jan 12, 2021
1 parent a6c09e2 commit cb5f692
Show file tree
Hide file tree
Showing 12 changed files with 402 additions and 32 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ public FlingBehavior(final Context context, final AttributeSet attrs) {
private boolean allowScroll = true;
private final Rect globalRect = new Rect();
private final List<Integer> skipInterceptionOfElements = Arrays.asList(
R.id.playQueuePanel, R.id.playbackSeekBar,
R.id.itemsListPanel, R.id.playbackSeekBar,
R.id.playPauseButton, R.id.playPreviousButton, R.id.playNextButton);

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2287,7 +2287,7 @@ public void onStateChanged(@NonNull final View bottomSheet, final int newState)
// Re-enable clicks
setOverlayElementsClickable(true);
if (player != null) {
player.onQueueClosed();
player.onItemsListClosed();
}
setOverlayLook(appBarLayout, behavior, 0);
break;
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
package org.schabi.newpipe.info_list

import android.util.Log
import com.xwray.groupie.GroupAdapter
import com.xwray.groupie.GroupieViewHolder
import org.schabi.newpipe.extractor.stream.StreamInfo
import kotlin.math.max

/**
* Custom RecyclerView.Adapter/GroupieAdapter for [StreamSegmentItem] for handling selection state.
*/
class StreamSegmentAdapter(
private val listener: StreamSegmentListener
) : GroupAdapter<GroupieViewHolder>() {

var currentIndex: Int = 0
private set

/**
* Returns `true` if the provided [StreamInfo] contains segments, `false` otherwise.
*/
fun setItems(info: StreamInfo): Boolean {
if (info.streamSegments.isNotEmpty()) {
clear()
addAll(info.streamSegments.map { StreamSegmentItem(it, listener) })
return true
}
return false
}

fun selectSegment(segment: StreamSegmentItem) {
unSelectCurrentSegment()
currentIndex = max(0, getAdapterPosition(segment))
segment.isSelected = true
segment.notifyChanged(StreamSegmentItem.PAYLOAD_SELECT)
}

fun selectSegmentAt(position: Int) {
try {
selectSegment(getGroupAtAdapterPosition(position) as StreamSegmentItem)
} catch (e: IndexOutOfBoundsException) {
// Just to make sure that getGroupAtAdapterPosition doesn't close the app
// Shouldn't happen since setItems is always called before select-methods but just in case
currentIndex = 0
Log.e("StreamSegmentAdapter", "selectSegmentAt: ${e.message}")
}
}

private fun unSelectCurrentSegment() {
try {
val segmentItem = getGroupAtAdapterPosition(currentIndex) as StreamSegmentItem
currentIndex = 0
segmentItem.isSelected = false
segmentItem.notifyChanged(StreamSegmentItem.PAYLOAD_SELECT)
} catch (e: IndexOutOfBoundsException) {
// Just to make sure that getGroupAtAdapterPosition doesn't close the app
// Shouldn't happen since setItems is always called before select-methods but just in case
currentIndex = 0
Log.e("StreamSegmentAdapter", "unSelectCurrentSegment: ${e.message}")
}
}

interface StreamSegmentListener {
fun onItemClick(item: StreamSegmentItem, secondsInMillis: Long)
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
package org.schabi.newpipe.info_list

import android.widget.ImageView
import android.widget.TextView
import com.nostra13.universalimageloader.core.ImageLoader
import com.xwray.groupie.GroupieViewHolder
import com.xwray.groupie.Item
import org.schabi.newpipe.R
import org.schabi.newpipe.extractor.stream.StreamSegment
import org.schabi.newpipe.util.ImageDisplayConstants
import java.util.concurrent.TimeUnit

class StreamSegmentItem(
private val item: StreamSegment,
private val onClick: StreamSegmentAdapter.StreamSegmentListener
) : Item<GroupieViewHolder>() {

companion object {
const val PAYLOAD_SELECT = 1
}

var isSelected = false

override fun bind(viewHolder: GroupieViewHolder, position: Int) {
item.previewUrl?.let {
ImageLoader.getInstance().displayImage(
it, viewHolder.root.findViewById<ImageView>(R.id.previewImage),
ImageDisplayConstants.DISPLAY_THUMBNAIL_OPTIONS
)
}
viewHolder.root.findViewById<TextView>(R.id.textViewTitle).text = item.title
viewHolder.root.findViewById<TextView>(R.id.textViewStartSeconds).text =
secondsToString(item.startTimeSeconds.toLong())
viewHolder.root.setOnClickListener { onClick.onItemClick(this, item.startTimeSeconds * 1000L) }
viewHolder.root.isSelected = isSelected
}

override fun bind(viewHolder: GroupieViewHolder, position: Int, payloads: MutableList<Any>) {
if (payloads.contains(PAYLOAD_SELECT)) {
viewHolder.root.isSelected = isSelected
return
}
super.bind(viewHolder, position, payloads)
}

private fun secondsToString(seconds: Long): String {
val hours = TimeUnit.SECONDS.toHours(seconds)
val minutes = TimeUnit.SECONDS.toMinutes(seconds)
.minus(TimeUnit.HOURS.toMinutes(hours))
val sec = seconds
.minus(TimeUnit.HOURS.toSeconds(hours))
.minus(TimeUnit.MINUTES.toSeconds(minutes))

return if (hours == 0L) String.format("%02d:%02d", minutes, sec)
else String.format("%d:%02d:%02d", hours, minutes, sec)
}

override fun getLayout() = R.layout.item_stream_segment
}
Original file line number Diff line number Diff line change
Expand Up @@ -153,7 +153,7 @@ public void stop(final boolean autoplayEnabled) {
// Android TV will handle back button in case controls will be visible
// (one more additional unneeded click while the player is hidden)
playerImpl.hideControls(0, 0);
playerImpl.onQueueClosed();
playerImpl.onItemsListClosed();
// Notification shows information about old stream but if a user selects
// a stream from backStack it's not actual anymore
// So we should hide the notification at all.
Expand Down
Loading

0 comments on commit cb5f692

Please sign in to comment.