1
0
mirror of https://github.com/TeamNewPipe/NewPipe.git synced 2024-11-25 12:32:31 +01:00

Use Fragment.content extension, improve comment composables

This commit is contained in:
Isira Seneviratne 2024-08-26 19:23:50 +05:30
parent 3641698379
commit d3a6991fd4
4 changed files with 56 additions and 76 deletions

View File

@ -216,7 +216,7 @@ dependencies {
implementation 'androidx.constraintlayout:constraintlayout:2.1.4' implementation 'androidx.constraintlayout:constraintlayout:2.1.4'
implementation 'androidx.core:core-ktx:1.12.0' implementation 'androidx.core:core-ktx:1.12.0'
implementation 'androidx.documentfile:documentfile:1.0.1' 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-livedata-ktx:${androidxLifecycleVersion}"
implementation "androidx.lifecycle:lifecycle-viewmodel-ktx:${androidxLifecycleVersion}" implementation "androidx.lifecycle:lifecycle-viewmodel-ktx:${androidxLifecycleVersion}"
implementation 'androidx.localbroadcastmanager:localbroadcastmanager:1.1.0' implementation 'androidx.localbroadcastmanager:localbroadcastmanager:1.1.0'

View File

@ -3,28 +3,25 @@ package org.schabi.newpipe.fragments.list.comments
import android.os.Bundle import android.os.Bundle
import android.view.LayoutInflater import android.view.LayoutInflater
import android.view.ViewGroup import android.view.ViewGroup
import androidx.compose.ui.platform.ComposeView import androidx.compose.material3.MaterialTheme
import androidx.compose.ui.platform.ViewCompositionStrategy import androidx.compose.material3.Surface
import androidx.core.os.bundleOf import androidx.core.os.bundleOf
import androidx.fragment.app.Fragment 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.components.comment.CommentSection
import org.schabi.newpipe.ui.theme.AppTheme import org.schabi.newpipe.ui.theme.AppTheme
import org.schabi.newpipe.util.KEY_SERVICE_ID import org.schabi.newpipe.util.KEY_SERVICE_ID
import org.schabi.newpipe.util.KEY_URL import org.schabi.newpipe.util.KEY_URL
import org.schabi.newpipe.viewmodels.CommentsViewModel
class CommentsFragment : Fragment() { class CommentsFragment : Fragment() {
override fun onCreateView( override fun onCreateView(
inflater: LayoutInflater, inflater: LayoutInflater,
container: ViewGroup?, container: ViewGroup?,
savedInstanceState: Bundle? savedInstanceState: Bundle?
) = ComposeView(requireContext()).apply { ) = content {
setViewCompositionStrategy(ViewCompositionStrategy.DisposeOnViewTreeLifecycleDestroyed) AppTheme {
setContent { Surface(color = MaterialTheme.colorScheme.background) {
val viewModel = viewModel<CommentsViewModel>() CommentSection()
AppTheme {
CommentSection(commentsFlow = viewModel.comments)
} }
} }
} }

View File

@ -2,14 +2,12 @@ package org.schabi.newpipe.fragments.list.videos
import android.os.Bundle import android.os.Bundle
import android.view.LayoutInflater import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup import android.view.ViewGroup
import androidx.compose.material3.MaterialTheme import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Surface import androidx.compose.material3.Surface
import androidx.compose.ui.platform.ComposeView
import androidx.compose.ui.platform.ViewCompositionStrategy
import androidx.core.os.bundleOf import androidx.core.os.bundleOf
import androidx.fragment.app.Fragment import androidx.fragment.app.Fragment
import androidx.fragment.compose.content
import org.schabi.newpipe.extractor.stream.StreamInfo import org.schabi.newpipe.extractor.stream.StreamInfo
import org.schabi.newpipe.ktx.serializable import org.schabi.newpipe.ktx.serializable
import org.schabi.newpipe.ui.components.video.RelatedItems import org.schabi.newpipe.ui.components.video.RelatedItems
@ -21,15 +19,10 @@ class RelatedItemsFragment : Fragment() {
inflater: LayoutInflater, inflater: LayoutInflater,
container: ViewGroup?, container: ViewGroup?,
savedInstanceState: Bundle? savedInstanceState: Bundle?
): View { ) = content {
return ComposeView(requireContext()).apply { AppTheme {
setViewCompositionStrategy(ViewCompositionStrategy.DisposeOnViewTreeLifecycleDestroyed) Surface(color = MaterialTheme.colorScheme.background) {
setContent { RelatedItems(requireArguments().serializable<StreamInfo>(KEY_INFO)!!)
AppTheme {
Surface(color = MaterialTheme.colorScheme.background) {
RelatedItems(requireArguments().serializable<StreamInfo>(KEY_INFO)!!)
}
}
} }
} }
} }

View File

@ -1,30 +1,24 @@
package org.schabi.newpipe.ui.components.comment package org.schabi.newpipe.ui.components.comment
import android.content.res.Configuration 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.padding
import androidx.compose.foundation.layout.wrapContentSize
import androidx.compose.foundation.lazy.LazyColumn import androidx.compose.foundation.lazy.LazyColumn
import androidx.compose.foundation.lazy.rememberLazyListState import androidx.compose.foundation.lazy.rememberLazyListState
import androidx.compose.material3.HorizontalDivider import androidx.compose.material3.HorizontalDivider
import androidx.compose.material3.MaterialTheme import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Surface import androidx.compose.material3.Surface
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable import androidx.compose.runtime.Composable
import androidx.compose.runtime.derivedStateOf import androidx.compose.runtime.derivedStateOf
import androidx.compose.runtime.getValue import androidx.compose.runtime.getValue
import androidx.compose.runtime.remember import androidx.compose.runtime.remember
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier import androidx.compose.ui.Modifier
import androidx.compose.ui.input.nestedscroll.nestedScroll import androidx.compose.ui.input.nestedscroll.nestedScroll
import androidx.compose.ui.platform.rememberNestedScrollInteropConnection 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.Preview
import androidx.compose.ui.tooling.preview.PreviewParameter import androidx.compose.ui.tooling.preview.PreviewParameter
import androidx.compose.ui.tooling.preview.PreviewParameterProvider import androidx.compose.ui.tooling.preview.PreviewParameterProvider
import androidx.compose.ui.unit.dp 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.LoadState
import androidx.paging.LoadStates import androidx.paging.LoadStates
import androidx.paging.PagingData 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.extractor.stream.Description
import org.schabi.newpipe.paging.CommentsDisabledException import org.schabi.newpipe.paging.CommentsDisabledException
import org.schabi.newpipe.ui.components.common.LoadingIndicator 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.ui.theme.AppTheme
import org.schabi.newpipe.viewmodels.CommentsViewModel
@Composable
fun CommentSection(commentsViewModel: CommentsViewModel = viewModel()) {
CommentSection(commentsFlow = commentsViewModel.comments)
}
@Composable @Composable
fun CommentSection( fun CommentSection(
parentComment: CommentsInfoItem? = null, parentComment: CommentsInfoItem? = null,
commentsFlow: Flow<PagingData<CommentsInfoItem>> commentsFlow: Flow<PagingData<CommentsInfoItem>>
) { ) {
Surface(color = MaterialTheme.colorScheme.background) { val comments = commentsFlow.collectAsLazyPagingItems()
val comments = commentsFlow.collectAsLazyPagingItems() val itemCount by remember { derivedStateOf { comments.itemCount } }
val itemCount by remember { derivedStateOf { comments.itemCount } } val nestedScrollInterop = rememberNestedScrollInteropConnection()
val nestedScrollInterop = rememberNestedScrollInteropConnection() val state = rememberLazyListState()
val state = rememberLazyListState()
LazyColumnScrollbar(state = state) { LazyColumnScrollbar(state = state) {
LazyColumn(modifier = Modifier.nestedScroll(nestedScrollInterop), state = state) { LazyColumn(modifier = Modifier.nestedScroll(nestedScrollInterop), state = state) {
if (parentComment != null) { if (parentComment != null) {
item { item {
CommentRepliesHeader(comment = parentComment) CommentRepliesHeader(comment = parentComment)
HorizontalDivider(thickness = 1.dp) 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)
} }
} }
} else {
if (itemCount == 0) { items(itemCount) {
item { Comment(comment = comments[it]!!)
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]!!)
}
} }
} }
} }
} }
} }
@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 class CommentDataProvider : PreviewParameterProvider<PagingData<CommentsInfoItem>> {
private val notLoading = LoadState.NotLoading(true) private val notLoading = LoadState.NotLoading(true)
@ -130,7 +116,9 @@ private fun CommentSectionPreview(
@PreviewParameter(CommentDataProvider::class) pagingData: PagingData<CommentsInfoItem> @PreviewParameter(CommentDataProvider::class) pagingData: PagingData<CommentsInfoItem>
) { ) {
AppTheme { 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)) val flow = flowOf(PagingData.from(replies))
AppTheme { AppTheme {
CommentSection(parentComment = comment, commentsFlow = flow) Surface(color = MaterialTheme.colorScheme.background) {
CommentSection(parentComment = comment, commentsFlow = flow)
}
} }
} }