refactor: remove callbacks on CommentsSheet

storing fragment callbacks in viewmodels is considered a bad practice because
view models survive longer than fragments
This commit is contained in:
Bnyro 2024-05-20 15:59:17 +02:00
parent 131d2a39cc
commit dc6563800f
7 changed files with 47 additions and 25 deletions

View File

@ -8,6 +8,7 @@ object IntentData {
const val videoIds = "videoIds"
const val channelId = "channelId"
const val channelName = "channelName"
const val channelAvatar = "channelAvatar"
const val playlistId = "playlistId"
const val timeStamp = "timeStamp"
const val playlistType = "playlistType"

View File

@ -47,7 +47,11 @@ class CommentPagingAdapter(
return
}
val args = bundleOf(IntentData.videoId to videoId, IntentData.comment to comment)
val args = bundleOf(
IntentData.videoId to videoId,
IntentData.comment to comment,
IntentData.channelAvatar to channelAvatar
)
fragment!!.parentFragmentManager.commit {
replace<CommentsRepliesFragment>(R.id.commentFragContainer, args = args)
addToBackStack(null)

View File

@ -5,15 +5,18 @@ import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.view.ViewTreeObserver
import androidx.core.os.bundleOf
import androidx.core.view.isVisible
import androidx.fragment.app.Fragment
import androidx.fragment.app.activityViewModels
import androidx.fragment.app.setFragmentResult
import androidx.lifecycle.Lifecycle
import androidx.lifecycle.lifecycleScope
import androidx.lifecycle.repeatOnLifecycle
import androidx.paging.LoadState
import androidx.recyclerview.widget.LinearLayoutManager
import com.github.libretube.R
import com.github.libretube.constants.IntentData
import com.github.libretube.databinding.FragmentCommentsBinding
import com.github.libretube.extensions.formatShort
import com.github.libretube.ui.adapters.CommentPagingAdapter
@ -68,10 +71,12 @@ class CommentsMainFragment : Fragment() {
val commentPagingAdapter = CommentPagingAdapter(
this,
viewModel.videoIdLiveData.value ?: return,
viewModel.channelAvatar ?: return,
handleLink = viewModel.handleLink
requireArguments().getString(IntentData.channelAvatar) ?: return,
handleLink = {
setFragmentResult(CommentsSheet.HANDLE_LINK_REQUEST_KEY, bundleOf(IntentData.url to it))
}
) {
viewModel.commentsSheetDismiss?.invoke()
setFragmentResult(CommentsSheet.DISMISS_SHEET_REQUEST_KEY, bundleOf())
}
binding.commentsRV.adapter = commentPagingAdapter

View File

@ -5,11 +5,13 @@ import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.view.ViewTreeObserver
import androidx.core.os.bundleOf
import androidx.core.view.isGone
import androidx.core.view.isVisible
import androidx.core.view.updatePadding
import androidx.fragment.app.Fragment
import androidx.fragment.app.activityViewModels
import androidx.fragment.app.setFragmentResult
import androidx.lifecycle.Lifecycle
import androidx.lifecycle.lifecycleScope
import androidx.lifecycle.repeatOnLifecycle
@ -60,13 +62,15 @@ class CommentsRepliesFragment : Fragment() {
val repliesAdapter = CommentPagingAdapter(
null,
videoId,
viewModel.channelAvatar,
requireArguments().getString(IntentData.channelAvatar) ?: return,
isRepliesAdapter = true,
handleLink = viewModel.handleLink
handleLink = {
setFragmentResult(CommentsSheet.HANDLE_LINK_REQUEST_KEY, bundleOf(IntentData.url to it))
}
) {
viewModel.commentsSheetDismiss?.invoke()
setFragmentResult(CommentsSheet.DISMISS_SHEET_REQUEST_KEY, bundleOf())
}
(parentFragment as CommentsSheet).updateFragmentInfo(
commentsSheet?.updateFragmentInfo(
true,
"${getString(R.string.replies)} (${comment.replyCount.formatShort()})"
)

View File

@ -525,14 +525,19 @@ class PlayerFragment : Fragment(), OnlinePlayerOptions {
exoPlayer.togglePlayPauseState()
}
activity?.supportFragmentManager
?.setFragmentResultListener(CommentsSheet.HANDLE_LINK_REQUEST_KEY, viewLifecycleOwner) { _, bundle ->
bundle.getString(IntentData.url)?.let { handleLink(it) }
}
binding.commentsToggle.setOnClickListener {
if (!this::streams.isInitialized) return@setOnClickListener
// set the max height to not cover the currently playing video
commentsViewModel.handleLink = this::handleLink
updateMaxSheetHeight()
commentsViewModel.videoIdLiveData.updateIfChanged(videoId)
commentsViewModel.channelAvatar = streams.uploaderAvatar
CommentsSheet().show(childFragmentManager)
CommentsSheet()
.apply { arguments = bundleOf(IntentData.channelAvatar to streams.uploaderAvatar) }
.show(childFragmentManager)
}
// FullScreen button trigger
@ -639,7 +644,7 @@ class PlayerFragment : Fragment(), OnlinePlayerOptions {
private fun updateMaxSheetHeight() {
val maxHeight = binding.root.height - binding.player.height
viewModel.maxSheetHeightPx = viewModel.maxSheetHeightPx
viewModel.maxSheetHeightPx = maxHeight
chaptersViewModel.maxSheetHeightPx = maxHeight
}
@ -1022,7 +1027,8 @@ class PlayerFragment : Fragment(), OnlinePlayerOptions {
playVideo()
// close comment bottom sheet if opened for next video
runCatching { commentsViewModel.commentsSheetDismiss?.invoke() }
activity?.supportFragmentManager?.fragments?.filterIsInstance<CommentsSheet>()
?.firstOrNull()?.dismiss()
}
@SuppressLint("SetTextI18n")

View File

@ -26,17 +26,12 @@ class CommentsViewModel : ViewModel() {
val commentSheetExpand = MutableLiveData<Boolean?>()
var channelAvatar: String? = null
var handleLink: ((url: String) -> Unit)? = null
private val _currentCommentsPosition = MutableLiveData(0)
val currentCommentsPosition: LiveData<Int> = _currentCommentsPosition
private val _currentRepliesPosition = MutableLiveData(0)
val currentRepliesPosition: LiveData<Int> = _currentRepliesPosition
var commentsSheetDismiss: (() -> Unit)? = null
fun setCommentSheetExpand(value: Boolean?) {
if (commentSheetExpand.value != value) {
commentSheetExpand.value = value

View File

@ -1,6 +1,5 @@
package com.github.libretube.ui.sheets
import android.content.DialogInterface
import android.os.Bundle
import android.view.LayoutInflater
import android.view.View
@ -9,6 +8,7 @@ import androidx.core.view.isVisible
import androidx.fragment.app.activityViewModels
import androidx.fragment.app.commit
import androidx.fragment.app.replace
import androidx.fragment.app.setFragmentResult
import com.github.libretube.R
import com.github.libretube.databinding.CommentsSheetBinding
import com.github.libretube.ui.fragments.CommentsMainFragment
@ -34,10 +34,17 @@ class CommentsSheet : UndimmedBottomSheet() {
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
commentsViewModel.commentsSheetDismiss = this::dismiss
val binding = binding
childFragmentManager.setFragmentResultListener(DISMISS_SHEET_REQUEST_KEY, viewLifecycleOwner) { _, _ ->
dismiss()
}
// forward requests to open links to the parent fragment
childFragmentManager.setFragmentResultListener(HANDLE_LINK_REQUEST_KEY, viewLifecycleOwner) { key, result ->
parentFragment?.setFragmentResult(key, result)
}
binding.btnBack.setOnClickListener {
if (childFragmentManager.backStackEntryCount > 0) {
childFragmentManager.popBackStack()
@ -47,7 +54,7 @@ class CommentsSheet : UndimmedBottomSheet() {
binding.btnClose.setOnClickListener { dismiss() }
childFragmentManager.commit {
replace<CommentsMainFragment>(R.id.commentFragContainer)
replace<CommentsMainFragment>(R.id.commentFragContainer, args = arguments)
}
commentsViewModel.setCommentSheetExpand(true)
@ -76,8 +83,8 @@ class CommentsSheet : UndimmedBottomSheet() {
binding.commentsTitle.text = title
}
override fun onDismiss(dialog: DialogInterface) {
super.onDismiss(dialog)
commentsViewModel.commentsSheetDismiss = null
companion object {
const val HANDLE_LINK_REQUEST_KEY = "handle_link_request_key"
const val DISMISS_SHEET_REQUEST_KEY = "dismiss_sheet_request_key"
}
}