mirror of
				https://github.com/TeamNewPipe/NewPipe
				synced 2025-11-04 01:03:00 +00:00 
			
		
		
		
	Use Fragment.content extension, improve comment composables
This commit is contained in:
		@@ -216,7 +216,7 @@ dependencies {
 | 
			
		||||
    implementation 'androidx.constraintlayout:constraintlayout:2.1.4'
 | 
			
		||||
    implementation 'androidx.core:core-ktx:1.12.0'
 | 
			
		||||
    implementation 'androidx.documentfile:documentfile:1.0.1'
 | 
			
		||||
    implementation 'androidx.fragment:fragment-ktx:1.6.2'
 | 
			
		||||
    implementation 'androidx.fragment:fragment-compose:1.8.2'
 | 
			
		||||
    implementation "androidx.lifecycle:lifecycle-livedata-ktx:${androidxLifecycleVersion}"
 | 
			
		||||
    implementation "androidx.lifecycle:lifecycle-viewmodel-ktx:${androidxLifecycleVersion}"
 | 
			
		||||
    implementation 'androidx.localbroadcastmanager:localbroadcastmanager:1.1.0'
 | 
			
		||||
 
 | 
			
		||||
@@ -3,28 +3,25 @@ package org.schabi.newpipe.fragments.list.comments
 | 
			
		||||
import android.os.Bundle
 | 
			
		||||
import android.view.LayoutInflater
 | 
			
		||||
import android.view.ViewGroup
 | 
			
		||||
import androidx.compose.ui.platform.ComposeView
 | 
			
		||||
import androidx.compose.ui.platform.ViewCompositionStrategy
 | 
			
		||||
import androidx.compose.material3.MaterialTheme
 | 
			
		||||
import androidx.compose.material3.Surface
 | 
			
		||||
import androidx.core.os.bundleOf
 | 
			
		||||
import androidx.fragment.app.Fragment
 | 
			
		||||
import androidx.lifecycle.viewmodel.compose.viewModel
 | 
			
		||||
import androidx.fragment.compose.content
 | 
			
		||||
import org.schabi.newpipe.ui.components.comment.CommentSection
 | 
			
		||||
import org.schabi.newpipe.ui.theme.AppTheme
 | 
			
		||||
import org.schabi.newpipe.util.KEY_SERVICE_ID
 | 
			
		||||
import org.schabi.newpipe.util.KEY_URL
 | 
			
		||||
import org.schabi.newpipe.viewmodels.CommentsViewModel
 | 
			
		||||
 | 
			
		||||
class CommentsFragment : Fragment() {
 | 
			
		||||
    override fun onCreateView(
 | 
			
		||||
        inflater: LayoutInflater,
 | 
			
		||||
        container: ViewGroup?,
 | 
			
		||||
        savedInstanceState: Bundle?
 | 
			
		||||
    ) = ComposeView(requireContext()).apply {
 | 
			
		||||
        setViewCompositionStrategy(ViewCompositionStrategy.DisposeOnViewTreeLifecycleDestroyed)
 | 
			
		||||
        setContent {
 | 
			
		||||
            val viewModel = viewModel<CommentsViewModel>()
 | 
			
		||||
            AppTheme {
 | 
			
		||||
                CommentSection(commentsFlow = viewModel.comments)
 | 
			
		||||
    ) = content {
 | 
			
		||||
        AppTheme {
 | 
			
		||||
            Surface(color = MaterialTheme.colorScheme.background) {
 | 
			
		||||
                CommentSection()
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 
 | 
			
		||||
@@ -2,14 +2,12 @@ package org.schabi.newpipe.fragments.list.videos
 | 
			
		||||
 | 
			
		||||
import android.os.Bundle
 | 
			
		||||
import android.view.LayoutInflater
 | 
			
		||||
import android.view.View
 | 
			
		||||
import android.view.ViewGroup
 | 
			
		||||
import androidx.compose.material3.MaterialTheme
 | 
			
		||||
import androidx.compose.material3.Surface
 | 
			
		||||
import androidx.compose.ui.platform.ComposeView
 | 
			
		||||
import androidx.compose.ui.platform.ViewCompositionStrategy
 | 
			
		||||
import androidx.core.os.bundleOf
 | 
			
		||||
import androidx.fragment.app.Fragment
 | 
			
		||||
import androidx.fragment.compose.content
 | 
			
		||||
import org.schabi.newpipe.extractor.stream.StreamInfo
 | 
			
		||||
import org.schabi.newpipe.ktx.serializable
 | 
			
		||||
import org.schabi.newpipe.ui.components.video.RelatedItems
 | 
			
		||||
@@ -21,15 +19,10 @@ class RelatedItemsFragment : Fragment() {
 | 
			
		||||
        inflater: LayoutInflater,
 | 
			
		||||
        container: ViewGroup?,
 | 
			
		||||
        savedInstanceState: Bundle?
 | 
			
		||||
    ): View {
 | 
			
		||||
        return ComposeView(requireContext()).apply {
 | 
			
		||||
            setViewCompositionStrategy(ViewCompositionStrategy.DisposeOnViewTreeLifecycleDestroyed)
 | 
			
		||||
            setContent {
 | 
			
		||||
                AppTheme {
 | 
			
		||||
                    Surface(color = MaterialTheme.colorScheme.background) {
 | 
			
		||||
                        RelatedItems(requireArguments().serializable<StreamInfo>(KEY_INFO)!!)
 | 
			
		||||
                    }
 | 
			
		||||
                }
 | 
			
		||||
    ) = content {
 | 
			
		||||
        AppTheme {
 | 
			
		||||
            Surface(color = MaterialTheme.colorScheme.background) {
 | 
			
		||||
                RelatedItems(requireArguments().serializable<StreamInfo>(KEY_INFO)!!)
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 
 | 
			
		||||
@@ -1,30 +1,24 @@
 | 
			
		||||
package org.schabi.newpipe.ui.components.comment
 | 
			
		||||
 | 
			
		||||
import android.content.res.Configuration
 | 
			
		||||
import androidx.compose.foundation.layout.Column
 | 
			
		||||
import androidx.compose.foundation.layout.fillMaxWidth
 | 
			
		||||
import androidx.compose.foundation.layout.padding
 | 
			
		||||
import androidx.compose.foundation.layout.wrapContentSize
 | 
			
		||||
import androidx.compose.foundation.lazy.LazyColumn
 | 
			
		||||
import androidx.compose.foundation.lazy.rememberLazyListState
 | 
			
		||||
import androidx.compose.material3.HorizontalDivider
 | 
			
		||||
import androidx.compose.material3.MaterialTheme
 | 
			
		||||
import androidx.compose.material3.Surface
 | 
			
		||||
import androidx.compose.material3.Text
 | 
			
		||||
import androidx.compose.runtime.Composable
 | 
			
		||||
import androidx.compose.runtime.derivedStateOf
 | 
			
		||||
import androidx.compose.runtime.getValue
 | 
			
		||||
import androidx.compose.runtime.remember
 | 
			
		||||
import androidx.compose.ui.Alignment
 | 
			
		||||
import androidx.compose.ui.Modifier
 | 
			
		||||
import androidx.compose.ui.input.nestedscroll.nestedScroll
 | 
			
		||||
import androidx.compose.ui.platform.rememberNestedScrollInteropConnection
 | 
			
		||||
import androidx.compose.ui.res.stringResource
 | 
			
		||||
import androidx.compose.ui.tooling.preview.Preview
 | 
			
		||||
import androidx.compose.ui.tooling.preview.PreviewParameter
 | 
			
		||||
import androidx.compose.ui.tooling.preview.PreviewParameterProvider
 | 
			
		||||
import androidx.compose.ui.unit.dp
 | 
			
		||||
import androidx.compose.ui.unit.sp
 | 
			
		||||
import androidx.lifecycle.viewmodel.compose.viewModel
 | 
			
		||||
import androidx.paging.LoadState
 | 
			
		||||
import androidx.paging.LoadStates
 | 
			
		||||
import androidx.paging.PagingData
 | 
			
		||||
@@ -37,66 +31,58 @@ import org.schabi.newpipe.extractor.comments.CommentsInfoItem
 | 
			
		||||
import org.schabi.newpipe.extractor.stream.Description
 | 
			
		||||
import org.schabi.newpipe.paging.CommentsDisabledException
 | 
			
		||||
import org.schabi.newpipe.ui.components.common.LoadingIndicator
 | 
			
		||||
import org.schabi.newpipe.ui.components.common.NoItemsMessage
 | 
			
		||||
import org.schabi.newpipe.ui.theme.AppTheme
 | 
			
		||||
import org.schabi.newpipe.viewmodels.CommentsViewModel
 | 
			
		||||
 | 
			
		||||
@Composable
 | 
			
		||||
fun CommentSection(commentsViewModel: CommentsViewModel = viewModel()) {
 | 
			
		||||
    CommentSection(commentsFlow = commentsViewModel.comments)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@Composable
 | 
			
		||||
fun CommentSection(
 | 
			
		||||
    parentComment: CommentsInfoItem? = null,
 | 
			
		||||
    commentsFlow: Flow<PagingData<CommentsInfoItem>>
 | 
			
		||||
) {
 | 
			
		||||
    Surface(color = MaterialTheme.colorScheme.background) {
 | 
			
		||||
        val comments = commentsFlow.collectAsLazyPagingItems()
 | 
			
		||||
        val itemCount by remember { derivedStateOf { comments.itemCount } }
 | 
			
		||||
        val nestedScrollInterop = rememberNestedScrollInteropConnection()
 | 
			
		||||
        val state = rememberLazyListState()
 | 
			
		||||
    val comments = commentsFlow.collectAsLazyPagingItems()
 | 
			
		||||
    val itemCount by remember { derivedStateOf { comments.itemCount } }
 | 
			
		||||
    val nestedScrollInterop = rememberNestedScrollInteropConnection()
 | 
			
		||||
    val state = rememberLazyListState()
 | 
			
		||||
 | 
			
		||||
        LazyColumnScrollbar(state = state) {
 | 
			
		||||
            LazyColumn(modifier = Modifier.nestedScroll(nestedScrollInterop), state = state) {
 | 
			
		||||
                if (parentComment != null) {
 | 
			
		||||
                    item {
 | 
			
		||||
                        CommentRepliesHeader(comment = parentComment)
 | 
			
		||||
                        HorizontalDivider(thickness = 1.dp)
 | 
			
		||||
    LazyColumnScrollbar(state = state) {
 | 
			
		||||
        LazyColumn(modifier = Modifier.nestedScroll(nestedScrollInterop), state = state) {
 | 
			
		||||
            if (parentComment != null) {
 | 
			
		||||
                item {
 | 
			
		||||
                    CommentRepliesHeader(comment = parentComment)
 | 
			
		||||
                    HorizontalDivider(thickness = 1.dp)
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            if (itemCount == 0) {
 | 
			
		||||
                item {
 | 
			
		||||
                    val refresh = comments.loadState.refresh
 | 
			
		||||
                    if (refresh is LoadState.Loading) {
 | 
			
		||||
                        LoadingIndicator(modifier = Modifier.padding(top = 8.dp))
 | 
			
		||||
                    } else {
 | 
			
		||||
                        val error = (refresh as? LoadState.Error)?.error
 | 
			
		||||
                        val message = if (error is CommentsDisabledException) {
 | 
			
		||||
                            R.string.comments_are_disabled
 | 
			
		||||
                        } else {
 | 
			
		||||
                            R.string.no_comments
 | 
			
		||||
                        }
 | 
			
		||||
                        NoItemsMessage(message)
 | 
			
		||||
                    }
 | 
			
		||||
                }
 | 
			
		||||
 | 
			
		||||
                if (itemCount == 0) {
 | 
			
		||||
                    item {
 | 
			
		||||
                        val refresh = comments.loadState.refresh
 | 
			
		||||
                        if (refresh is LoadState.Loading) {
 | 
			
		||||
                            LoadingIndicator(modifier = Modifier.padding(top = 8.dp))
 | 
			
		||||
                        } else {
 | 
			
		||||
                            NoCommentsMessage((refresh as? LoadState.Error)?.error)
 | 
			
		||||
                        }
 | 
			
		||||
                    }
 | 
			
		||||
                } else {
 | 
			
		||||
                    items(itemCount) {
 | 
			
		||||
                        Comment(comment = comments[it]!!)
 | 
			
		||||
                    }
 | 
			
		||||
            } else {
 | 
			
		||||
                items(itemCount) {
 | 
			
		||||
                    Comment(comment = comments[it]!!)
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@Composable
 | 
			
		||||
private fun NoCommentsMessage(error: Throwable?) {
 | 
			
		||||
    val message = if (error is CommentsDisabledException) {
 | 
			
		||||
        R.string.comments_are_disabled
 | 
			
		||||
    } else {
 | 
			
		||||
        R.string.no_comments
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    Column(
 | 
			
		||||
        modifier = Modifier
 | 
			
		||||
            .fillMaxWidth()
 | 
			
		||||
            .wrapContentSize(Alignment.Center),
 | 
			
		||||
        horizontalAlignment = Alignment.CenterHorizontally
 | 
			
		||||
    ) {
 | 
			
		||||
        Text(text = "(╯°-°)╯", fontSize = 35.sp)
 | 
			
		||||
        Text(text = stringResource(id = message), fontSize = 24.sp)
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
private class CommentDataProvider : PreviewParameterProvider<PagingData<CommentsInfoItem>> {
 | 
			
		||||
    private val notLoading = LoadState.NotLoading(true)
 | 
			
		||||
 | 
			
		||||
@@ -130,7 +116,9 @@ private fun CommentSectionPreview(
 | 
			
		||||
    @PreviewParameter(CommentDataProvider::class) pagingData: PagingData<CommentsInfoItem>
 | 
			
		||||
) {
 | 
			
		||||
    AppTheme {
 | 
			
		||||
        CommentSection(commentsFlow = flowOf(pagingData))
 | 
			
		||||
        Surface(color = MaterialTheme.colorScheme.background) {
 | 
			
		||||
            CommentSection(commentsFlow = flowOf(pagingData))
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@@ -154,6 +142,8 @@ private fun CommentRepliesPreview() {
 | 
			
		||||
    val flow = flowOf(PagingData.from(replies))
 | 
			
		||||
 | 
			
		||||
    AppTheme {
 | 
			
		||||
        CommentSection(parentComment = comment, commentsFlow = flow)
 | 
			
		||||
        Surface(color = MaterialTheme.colorScheme.background) {
 | 
			
		||||
            CommentSection(parentComment = comment, commentsFlow = flow)
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user