mirror of
https://github.com/libre-tube/LibreTube.git
synced 2024-12-14 14:20:30 +05:30
Layout and skip+prev functionality
This commit is contained in:
parent
c3645cb4d2
commit
59697caebf
@ -8,7 +8,7 @@ object IntentData {
|
||||
const val timeStamp = "timeStamp"
|
||||
const val position = "position"
|
||||
const val fileName = "fileName"
|
||||
const val openQueueOnce = "openQueue"
|
||||
const val keepQueue = "keepQueue"
|
||||
const val playlistType = "playlistType"
|
||||
const val openAudioPlayer = "openAudioPlayer"
|
||||
}
|
||||
|
@ -93,7 +93,6 @@ object PreferenceKeys {
|
||||
* Background mode
|
||||
*/
|
||||
const val BACKGROUND_PLAYBACK_SPEED = "background_playback_speed"
|
||||
const val NOTIFICATION_OPEN_QUEUE = "notification_open_queue"
|
||||
|
||||
/**
|
||||
* Notifications
|
||||
|
@ -341,8 +341,8 @@ class MainActivity : BaseActivity() {
|
||||
}
|
||||
// Handover back press to `BackPressedDispatcher`
|
||||
else if (binding.bottomNav.menu.children.none {
|
||||
it.itemId == navController.currentDestination?.id
|
||||
}
|
||||
it.itemId == navController.currentDestination?.id
|
||||
}
|
||||
) {
|
||||
this@MainActivity.onBackPressedDispatcher.onBackPressed()
|
||||
}
|
||||
@ -391,6 +391,11 @@ class MainActivity : BaseActivity() {
|
||||
startActivity(intent)
|
||||
}
|
||||
|
||||
if (intent?.getBooleanExtra(IntentData.openAudioPlayer, false) == true) {
|
||||
navController.navigate(R.id.audioPlayerFragment)
|
||||
return
|
||||
}
|
||||
|
||||
intent?.getStringExtra(IntentData.channelId)?.let {
|
||||
navController.navigate(
|
||||
R.id.channelFragment,
|
||||
@ -412,6 +417,7 @@ class MainActivity : BaseActivity() {
|
||||
intent?.getStringExtra(IntentData.videoId)?.let {
|
||||
loadVideo(it, intent?.getLongExtra(IntentData.timeStamp, 0L))
|
||||
}
|
||||
|
||||
when (intent?.getStringExtra("fragmentToOpen")) {
|
||||
"home" ->
|
||||
navController.navigate(R.id.homeFragment)
|
||||
@ -422,10 +428,6 @@ class MainActivity : BaseActivity() {
|
||||
"library" ->
|
||||
navController.navigate(R.id.libraryFragment)
|
||||
}
|
||||
if (intent?.getBooleanExtra(IntentData.openQueueOnce, false) == true) {
|
||||
PlayingQueueSheet()
|
||||
.show(supportFragmentManager)
|
||||
}
|
||||
}
|
||||
|
||||
private fun loadVideo(videoId: String, timeStamp: Long?) {
|
||||
|
@ -0,0 +1,67 @@
|
||||
package com.github.libretube.ui.fragments
|
||||
|
||||
import android.os.Bundle
|
||||
import android.view.LayoutInflater
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import com.github.libretube.api.obj.StreamItem
|
||||
import com.github.libretube.databinding.FragmentAudioPlayerBinding
|
||||
import com.github.libretube.extensions.toID
|
||||
import com.github.libretube.ui.base.BaseFragment
|
||||
import com.github.libretube.util.ImageHelper
|
||||
import com.github.libretube.util.NavigationHelper
|
||||
import com.github.libretube.util.PlayingQueue
|
||||
|
||||
class AudioPlayerFragment : BaseFragment() {
|
||||
private lateinit var binding: FragmentAudioPlayerBinding
|
||||
private val onTrackChangeListener: (StreamItem) -> Unit = {
|
||||
updateStreamInfo()
|
||||
}
|
||||
|
||||
override fun onCreateView(
|
||||
inflater: LayoutInflater,
|
||||
container: ViewGroup?,
|
||||
savedInstanceState: Bundle?
|
||||
): View {
|
||||
binding = FragmentAudioPlayerBinding.inflate(layoutInflater)
|
||||
return binding.root
|
||||
}
|
||||
|
||||
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
||||
super.onViewCreated(view, savedInstanceState)
|
||||
|
||||
binding.prev.setOnClickListener {
|
||||
val currentIndex = PlayingQueue.currentIndex()
|
||||
PlayingQueue.onQueueItemSelected(currentIndex - 1)
|
||||
}
|
||||
|
||||
binding.next.setOnClickListener {
|
||||
val currentIndex = PlayingQueue.currentIndex()
|
||||
PlayingQueue.onQueueItemSelected(currentIndex + 1)
|
||||
}
|
||||
|
||||
PlayingQueue.addOnTrackChangedListener(onTrackChangeListener)
|
||||
|
||||
updateStreamInfo()
|
||||
}
|
||||
|
||||
private fun updateStreamInfo() {
|
||||
val current = PlayingQueue.getCurrent()
|
||||
current ?: return
|
||||
|
||||
binding.title.text = current.title
|
||||
binding.uploader.text = current.uploaderName
|
||||
binding.uploader.setOnClickListener {
|
||||
NavigationHelper.navigateChannel(requireContext(), current.uploaderUrl?.toID())
|
||||
}
|
||||
|
||||
ImageHelper.loadImage(current.thumbnail, binding.thumbnail)
|
||||
}
|
||||
|
||||
override fun onDestroy() {
|
||||
super.onDestroy()
|
||||
|
||||
// unregister the listener
|
||||
PlayingQueue.removeOnTrackChangedListener(onTrackChangeListener)
|
||||
}
|
||||
}
|
@ -75,11 +75,7 @@ class NowPlayingNotification(
|
||||
// that's the only way to launch back into the previous activity (e.g. the player view
|
||||
val intent = Intent(context, MainActivity::class.java).apply {
|
||||
if (isBackgroundPlayerNotification) {
|
||||
if (PreferenceHelper.getBoolean(PreferenceKeys.NOTIFICATION_OPEN_QUEUE, true)) {
|
||||
putExtra(IntentData.openQueueOnce, true)
|
||||
} else {
|
||||
putExtra(IntentData.videoId, videoId)
|
||||
}
|
||||
putExtra(IntentData.openAudioPlayer, true)
|
||||
addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP)
|
||||
}
|
||||
}
|
||||
|
@ -13,7 +13,16 @@ import kotlinx.coroutines.launch
|
||||
object PlayingQueue {
|
||||
private val queue = mutableListOf<StreamItem>()
|
||||
private var currentStream: StreamItem? = null
|
||||
|
||||
/**
|
||||
* Listener that gets called when the user selects an item from the queue
|
||||
*/
|
||||
private var onQueueTapListener: (StreamItem) -> Unit = {}
|
||||
|
||||
/**
|
||||
* Listener that gets called when the current playing video changes
|
||||
*/
|
||||
private val onTrackChangedListeners: MutableList<(StreamItem) -> Unit> = mutableListOf()
|
||||
var repeatQueue: Boolean = false
|
||||
|
||||
fun add(vararg streamItem: StreamItem) {
|
||||
@ -58,6 +67,9 @@ object PlayingQueue {
|
||||
|
||||
fun updateCurrent(streamItem: StreamItem) {
|
||||
currentStream = streamItem
|
||||
onTrackChangedListeners.forEach {
|
||||
it.invoke(streamItem)
|
||||
}
|
||||
if (!contains(streamItem)) queue.add(streamItem)
|
||||
}
|
||||
|
||||
@ -77,6 +89,8 @@ object PlayingQueue {
|
||||
}
|
||||
}
|
||||
|
||||
fun getCurrent(): StreamItem? = currentStream
|
||||
|
||||
fun contains(streamItem: StreamItem) = queue.any { it.url?.toID() == streamItem.url?.toID() }
|
||||
|
||||
// only returns a copy of the queue, no write access
|
||||
@ -162,9 +176,18 @@ object PlayingQueue {
|
||||
onQueueTapListener = listener
|
||||
}
|
||||
|
||||
fun addOnTrackChangedListener(listener: (StreamItem) -> Unit) {
|
||||
onTrackChangedListeners.add(listener)
|
||||
}
|
||||
|
||||
fun removeOnTrackChangedListener(listener: (StreamItem) -> Unit) {
|
||||
onTrackChangedListeners.remove(listener)
|
||||
}
|
||||
|
||||
fun resetToDefaults() {
|
||||
repeatQueue = false
|
||||
onQueueTapListener = {}
|
||||
onTrackChangedListeners.clear()
|
||||
queue.clear()
|
||||
}
|
||||
}
|
||||
|
99
app/src/main/res/layout/fragment_audio_player.xml
Normal file
99
app/src/main/res/layout/fragment_audio_player.xml
Normal file
@ -0,0 +1,99 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:orientation="vertical">
|
||||
|
||||
<FrameLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="0dp"
|
||||
android:layout_weight="1">
|
||||
|
||||
<com.google.android.material.imageview.ShapeableImageView
|
||||
android:id="@+id/thumbnail"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="center"
|
||||
android:layout_marginHorizontal="20dp"
|
||||
android:layout_marginVertical="10dp"
|
||||
android:adjustViewBounds="true"
|
||||
android:scaleType="fitCenter"
|
||||
app:shapeAppearanceOverlay="@style/ShapeAppearance.Material3.Corner.Small"
|
||||
tools:src="@tools:sample/backgrounds/scenic" />
|
||||
|
||||
</FrameLayout>
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_margin="20dp"
|
||||
android:orientation="vertical">
|
||||
|
||||
<TextView
|
||||
android:id="@+id/title"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="center"
|
||||
android:ellipsize="marquee"
|
||||
android:marqueeRepeatLimit="marquee_forever"
|
||||
android:scrollHorizontally="true"
|
||||
android:singleLine="true"
|
||||
android:textSize="20sp" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/uploader"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="center"
|
||||
android:layout_marginTop="10dp" />
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
<com.google.android.material.slider.Slider
|
||||
android:id="@+id/time_bar"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
app:labelBehavior="gone"
|
||||
android:layout_marginHorizontal="20dp" />
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="center"
|
||||
android:layout_marginVertical="50dp">
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/prev"
|
||||
android:layout_width="48dp"
|
||||
android:layout_height="48dp"
|
||||
android:layout_gravity="center"
|
||||
android:layout_marginHorizontal="20dp"
|
||||
android:background="?attr/selectableItemBackgroundBorderless"
|
||||
android:src="@drawable/ic_prev" />
|
||||
|
||||
<com.google.android.material.button.MaterialButton
|
||||
android:id="@+id/play_pause"
|
||||
android:layout_width="72dp"
|
||||
android:layout_height="72dp"
|
||||
android:insetLeft="0dp"
|
||||
android:insetTop="0dp"
|
||||
android:insetRight="0dp"
|
||||
android:insetBottom="0dp"
|
||||
app:icon="@drawable/ic_play"
|
||||
app:iconSize="24dp"
|
||||
app:shapeAppearanceOverlay="@style/ShapeAppearance.Material3.Corner.Full" />
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/next"
|
||||
android:layout_width="48dp"
|
||||
android:layout_height="48dp"
|
||||
android:layout_gravity="center"
|
||||
android:layout_marginHorizontal="20dp"
|
||||
android:background="?attr/selectableItemBackgroundBorderless"
|
||||
android:src="@drawable/ic_next" />
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
</LinearLayout>
|
@ -54,4 +54,9 @@
|
||||
android:name="com.github.libretube.ui.fragments.DownloadsFragment"
|
||||
android:label="@string/downloads"
|
||||
tools:layout="@layout/fragment_downloads" />
|
||||
<fragment
|
||||
android:id="@+id/audioPlayerFragment"
|
||||
android:name="com.github.libretube.ui.fragments.AudioPlayerFragment"
|
||||
android:label="@string/audio_player"
|
||||
tools:layout="@layout/fragment_audio_player" />
|
||||
</navigation>
|
@ -430,6 +430,7 @@
|
||||
<string name="pause">Pause</string>
|
||||
<string name="alternative_pip_controls">Alternative PiP controls</string>
|
||||
<string name="alternative_pip_controls_summary">Show audio only and skip controls in PiP instead of forward and rewind</string>
|
||||
<string name="audio_player">Audio player</string>
|
||||
|
||||
<!-- Notification channel strings -->
|
||||
<string name="download_channel_name">Download Service</string>
|
||||
|
@ -89,12 +89,6 @@
|
||||
app:valueFrom="0.2"
|
||||
app:valueTo="4.0" />
|
||||
|
||||
<SwitchPreferenceCompat
|
||||
android:defaultValue="true"
|
||||
android:icon="@drawable/ic_grid"
|
||||
android:title="@string/open_queue_from_notification"
|
||||
app:key="notification_open_queue" />
|
||||
|
||||
</PreferenceCategory>
|
||||
|
||||
</PreferenceScreen>
|
Loading…
Reference in New Issue
Block a user