mirror of
https://github.com/libre-tube/LibreTube.git
synced 2025-04-29 08:20:32 +05:30
Merge pull request #5112 from Bnyro/master
refactor: make audio player more accessible and redesign
This commit is contained in:
commit
124bff117d
@ -32,4 +32,5 @@ object IntentData {
|
||||
const val url = "url"
|
||||
const val videoStats = "videoStats"
|
||||
const val bitmapUrl = "bitmapUrl"
|
||||
const val isCurrentlyPlaying = "isCurrentlyPlaying"
|
||||
}
|
||||
|
@ -27,7 +27,6 @@ import com.github.libretube.R
|
||||
import com.github.libretube.api.obj.StreamItem
|
||||
import com.github.libretube.constants.IntentData
|
||||
import com.github.libretube.databinding.FragmentAudioPlayerBinding
|
||||
import com.github.libretube.enums.ShareObjectType
|
||||
import com.github.libretube.extensions.normalize
|
||||
import com.github.libretube.extensions.seekBy
|
||||
import com.github.libretube.extensions.toID
|
||||
@ -37,11 +36,8 @@ import com.github.libretube.helpers.ImageHelper
|
||||
import com.github.libretube.helpers.NavigationHelper
|
||||
import com.github.libretube.helpers.PlayerHelper
|
||||
import com.github.libretube.helpers.ThemeHelper
|
||||
import com.github.libretube.obj.ShareData
|
||||
import com.github.libretube.services.OnlinePlayerService
|
||||
import com.github.libretube.ui.activities.MainActivity
|
||||
import com.github.libretube.ui.dialogs.DownloadDialog
|
||||
import com.github.libretube.ui.dialogs.ShareDialog
|
||||
import com.github.libretube.ui.interfaces.AudioPlayerOptions
|
||||
import com.github.libretube.ui.listeners.AudioPlayerThumbnailListener
|
||||
import com.github.libretube.ui.models.PlayerViewModel
|
||||
@ -168,28 +164,7 @@ class AudioPlayerFragment : Fragment(), AudioPlayerOptions {
|
||||
)
|
||||
}
|
||||
|
||||
binding.download.setOnClickListener {
|
||||
val videoId = PlayingQueue.getCurrent()?.url?.toID() ?: return@setOnClickListener
|
||||
|
||||
val newFragment = DownloadDialog()
|
||||
newFragment.arguments = bundleOf(IntentData.videoId to videoId)
|
||||
newFragment.show(childFragmentManager, DownloadDialog::class.java.name)
|
||||
}
|
||||
|
||||
binding.share.setOnClickListener {
|
||||
val currentVideo = PlayingQueue.getCurrent() ?: return@setOnClickListener
|
||||
|
||||
val bundle = bundleOf(
|
||||
IntentData.id to currentVideo.url!!.toID(),
|
||||
IntentData.shareObjectType to ShareObjectType.VIDEO,
|
||||
IntentData.shareData to ShareData(currentVideo = currentVideo.title)
|
||||
)
|
||||
val newShareDialog = ShareDialog()
|
||||
newShareDialog.arguments = bundle
|
||||
newShareDialog.show(childFragmentManager, null)
|
||||
}
|
||||
|
||||
binding.chapters.setOnClickListener {
|
||||
binding.openChapters.setOnClickListener {
|
||||
val playerService = playerService ?: return@setOnClickListener
|
||||
viewModel.chaptersLiveData.value = playerService.streams?.chapters.orEmpty()
|
||||
|
||||
@ -197,6 +172,12 @@ class AudioPlayerFragment : Fragment(), AudioPlayerOptions {
|
||||
.show(childFragmentManager)
|
||||
}
|
||||
|
||||
binding.close.setOnClickListener {
|
||||
activity?.unbindService(connection)
|
||||
BackgroundHelper.stopBackgroundPlay(requireContext())
|
||||
killFragment()
|
||||
}
|
||||
|
||||
binding.miniPlayerClose.setOnClickListener {
|
||||
activity?.unbindService(connection)
|
||||
BackgroundHelper.stopBackgroundPlay(requireContext())
|
||||
@ -214,6 +195,10 @@ class AudioPlayerFragment : Fragment(), AudioPlayerOptions {
|
||||
if (isPaused) playerService?.play() else playerService?.pause()
|
||||
}
|
||||
|
||||
binding.showMore.setOnClickListener {
|
||||
onLongTap()
|
||||
}
|
||||
|
||||
// load the stream info into the UI
|
||||
updateStreamInfo()
|
||||
|
||||
@ -371,7 +356,7 @@ class AudioPlayerFragment : Fragment(), AudioPlayerOptions {
|
||||
}
|
||||
playerService?.onNewVideo = { streams, videoId ->
|
||||
updateStreamInfo(streams.toStreamItem(videoId))
|
||||
_binding?.chapters?.isVisible = streams.chapters.isNotEmpty()
|
||||
_binding?.openChapters?.isVisible = streams.chapters.isNotEmpty()
|
||||
}
|
||||
initializeSeekBar()
|
||||
}
|
||||
@ -400,7 +385,12 @@ class AudioPlayerFragment : Fragment(), AudioPlayerOptions {
|
||||
override fun onLongTap() {
|
||||
val current = PlayingQueue.getCurrent() ?: return
|
||||
VideoOptionsBottomSheet()
|
||||
.apply { arguments = bundleOf(IntentData.shareData to current) }
|
||||
.apply {
|
||||
arguments = bundleOf(
|
||||
IntentData.streamItem to current,
|
||||
IntentData.isCurrentlyPlaying to true
|
||||
)
|
||||
}
|
||||
.show(childFragmentManager)
|
||||
}
|
||||
|
||||
|
@ -36,41 +36,17 @@ import kotlinx.coroutines.withContext
|
||||
*/
|
||||
class VideoOptionsBottomSheet : BaseBottomSheet() {
|
||||
private lateinit var streamItem: StreamItem
|
||||
private var isCurrentlyPlaying = false
|
||||
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
streamItem = arguments?.parcelable(IntentData.streamItem)!!
|
||||
isCurrentlyPlaying = arguments?.getBoolean(IntentData.isCurrentlyPlaying) ?: false
|
||||
|
||||
val videoId = streamItem.url?.toID() ?: return
|
||||
// List that stores the different menu options. In the future could be add more options here.
|
||||
val optionsList = mutableListOf(
|
||||
getString(R.string.playOnBackground)
|
||||
)
|
||||
|
||||
// Check whether the player is running and add queue options
|
||||
if (PlayingQueue.isNotEmpty()) {
|
||||
optionsList += getString(R.string.play_next)
|
||||
optionsList += getString(R.string.add_to_queue)
|
||||
}
|
||||
|
||||
// show the mark as watched or unwatched option if watch positions are enabled
|
||||
if (PlayerHelper.watchPositionsVideo || PlayerHelper.watchHistoryEnabled) {
|
||||
val watchPositionEntry = runBlocking(Dispatchers.IO) {
|
||||
DatabaseHolder.Database.watchPositionDao().findById(videoId)
|
||||
}
|
||||
val watchHistoryEntry = runBlocking(Dispatchers.IO) {
|
||||
DatabaseHolder.Database.watchHistoryDao().findById(videoId)
|
||||
}
|
||||
|
||||
if (streamItem.duration == null ||
|
||||
watchPositionEntry == null ||
|
||||
watchPositionEntry.position < streamItem.duration!! * 1000 * 0.9
|
||||
) {
|
||||
optionsList += getString(R.string.mark_as_watched)
|
||||
}
|
||||
|
||||
if (watchHistoryEntry != null || watchPositionEntry != null) {
|
||||
optionsList += getString(R.string.mark_as_unwatched)
|
||||
}
|
||||
val optionsList = mutableListOf<String>()
|
||||
if (!isCurrentlyPlaying) {
|
||||
optionsList += getOptionsForNotActivePlayback(videoId)
|
||||
}
|
||||
|
||||
optionsList += listOf(
|
||||
@ -155,6 +131,42 @@ class VideoOptionsBottomSheet : BaseBottomSheet() {
|
||||
super.onCreate(savedInstanceState)
|
||||
}
|
||||
|
||||
private fun getOptionsForNotActivePlayback(videoId: String): List<String> {
|
||||
// List that stores the different menu options. In the future could be add more options here.
|
||||
val optionsList = mutableListOf(
|
||||
getString(R.string.playOnBackground)
|
||||
)
|
||||
|
||||
// Check whether the player is running and add queue options
|
||||
if (PlayingQueue.isNotEmpty()) {
|
||||
optionsList += getString(R.string.play_next)
|
||||
optionsList += getString(R.string.add_to_queue)
|
||||
}
|
||||
|
||||
// show the mark as watched or unwatched option if watch positions are enabled
|
||||
if (PlayerHelper.watchPositionsVideo || PlayerHelper.watchHistoryEnabled) {
|
||||
val watchPositionEntry = runBlocking(Dispatchers.IO) {
|
||||
DatabaseHolder.Database.watchPositionDao().findById(videoId)
|
||||
}
|
||||
val watchHistoryEntry = runBlocking(Dispatchers.IO) {
|
||||
DatabaseHolder.Database.watchHistoryDao().findById(videoId)
|
||||
}
|
||||
|
||||
if (streamItem.duration == null ||
|
||||
watchPositionEntry == null ||
|
||||
watchPositionEntry.position < streamItem.duration!! * 1000 * 0.9
|
||||
) {
|
||||
optionsList += getString(R.string.mark_as_watched)
|
||||
}
|
||||
|
||||
if (watchHistoryEntry != null || watchPositionEntry != null) {
|
||||
optionsList += getString(R.string.mark_as_unwatched)
|
||||
}
|
||||
}
|
||||
|
||||
return optionsList
|
||||
}
|
||||
|
||||
companion object {
|
||||
const val VIDEO_OPTIONS_SHEET_REQUEST_KEY = "video_options_sheet_request_key"
|
||||
}
|
||||
|
@ -56,6 +56,22 @@
|
||||
app:track="@drawable/player_switch_track"
|
||||
app:trackTint="?colorControlNormal" />
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/open_video"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="center"
|
||||
android:layout_marginHorizontal="6dp"
|
||||
android:src="@drawable/ic_video" />
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/close"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="center"
|
||||
android:layout_marginHorizontal="6dp"
|
||||
android:src="@drawable/ic_close" />
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
<FrameLayout
|
||||
@ -259,53 +275,65 @@
|
||||
|
||||
<com.google.android.material.card.MaterialCardView
|
||||
style="@style/Widget.Material3.CardView.Elevated"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="center"
|
||||
android:layout_marginBottom="30dp"
|
||||
app:cardCornerRadius="18dp">
|
||||
android:layout_marginTop="30dp"
|
||||
app:shapeAppearanceOverlay="@style/CardOnlyBottomCorners">
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="wrap_content"
|
||||
<FrameLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="center"
|
||||
android:padding="15dp">
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/open_queue"
|
||||
style="@style/AudioPlayerButton"
|
||||
android:src="@drawable/ic_queue" />
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/playback_options"
|
||||
style="@style/AudioPlayerButton"
|
||||
android:layout_width="27dp"
|
||||
android:layout_height="27dp"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="start|center_vertical"
|
||||
android:background="?attr/selectableItemBackgroundBorderless"
|
||||
android:scaleX="0.9"
|
||||
android:scaleY="0.9"
|
||||
android:src="@drawable/ic_speed" />
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/open_video"
|
||||
style="@style/AudioPlayerButton"
|
||||
android:src="@drawable/ic_video" />
|
||||
<LinearLayout
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="center"
|
||||
android:orientation="horizontal">
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/download"
|
||||
style="@style/AudioPlayerButton"
|
||||
android:src="@drawable/ic_download" />
|
||||
android:id="@+id/open_chapters"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginEnd="10dp"
|
||||
android:background="?attr/selectableItemBackgroundBorderless"
|
||||
android:scaleX="0.9"
|
||||
android:scaleY="0.9"
|
||||
android:src="@drawable/ic_frame" />
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/share"
|
||||
style="@style/AudioPlayerButton"
|
||||
android:src="@drawable/ic_share" />
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/chapters"
|
||||
style="@style/AudioPlayerButton"
|
||||
android:src="@drawable/ic_frame"
|
||||
android:visibility="gone" />
|
||||
android:id="@+id/open_queue"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:background="?attr/selectableItemBackgroundBorderless"
|
||||
android:src="@drawable/ic_queue" />
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/show_more"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="end|center_vertical"
|
||||
android:background="?attr/selectableItemBackgroundBorderless"
|
||||
android:scaleX="0.9"
|
||||
android:scaleY="0.9"
|
||||
android:src="@drawable/ic_three_dots" />
|
||||
|
||||
</FrameLayout>
|
||||
|
||||
</com.google.android.material.card.MaterialCardView>
|
||||
|
||||
</LinearLayout>
|
||||
|
@ -196,6 +196,14 @@
|
||||
<item name="android:drawableTint" tools:targetApi="m">?android:attr/textColorPrimary</item>
|
||||
</style>
|
||||
|
||||
<style name="CardOnlyBottomCorners">
|
||||
<item name="cornerFamily">rounded</item>
|
||||
<item name="cornerSizeTopRight">0dp</item>
|
||||
<item name="cornerSizeTopLeft">0dp</item>
|
||||
<item name="cornerSizeBottomRight">18dp</item>
|
||||
<item name="cornerSizeBottomLeft">18dp</item>
|
||||
</style>
|
||||
|
||||
<style name="HomeCategoryTitle">
|
||||
|
||||
<item name="android:layout_width">match_parent</item>
|
||||
@ -209,16 +217,6 @@
|
||||
|
||||
</style>
|
||||
|
||||
<style name="AudioPlayerButton">
|
||||
|
||||
<item name="android:layout_width">30dp</item>
|
||||
<item name="android:layout_height">30dp</item>
|
||||
<item name="android:background">?attr/selectableItemBackgroundBorderless</item>
|
||||
<item name="android:layout_marginStart">10dp</item>
|
||||
<item name="android:layout_marginEnd">10dp</item>
|
||||
|
||||
</style>
|
||||
|
||||
<style name="TextViewMarquee">
|
||||
|
||||
<item name="android:singleLine">true</item>
|
||||
|
Loading…
x
Reference in New Issue
Block a user