mirror of
				https://github.com/TeamNewPipe/NewPipe
				synced 2025-10-30 23:03:00 +00:00 
			
		
		
		
	Added missing comment features, fixed theming
This commit is contained in:
		| @@ -871,7 +871,7 @@ public class MainActivity extends AppCompatActivity { | ||||
|         @Nullable final CommentRepliesFragment repliesFragment = | ||||
|                 (CommentRepliesFragment) fm.findFragmentByTag(CommentRepliesFragment.TAG); | ||||
|         @Nullable final CommentsInfoItem rootComment = | ||||
|                 repliesFragment == null ? null : repliesFragment.commentsInfoItem; | ||||
|                 repliesFragment == null ? null : repliesFragment.getCommentsInfoItem(); | ||||
|  | ||||
|         // sometimes this function pops the backstack, other times it's handled by the system | ||||
|         if (popBackStack) { | ||||
|   | ||||
| @@ -1,16 +1,19 @@ | ||||
| package org.schabi.newpipe.fragments.list.comments | ||||
|  | ||||
| import android.content.res.Configuration | ||||
| import androidx.compose.foundation.Image | ||||
| import androidx.compose.foundation.clickable | ||||
| import androidx.compose.foundation.layout.Arrangement | ||||
| import androidx.compose.foundation.layout.Column | ||||
| import androidx.compose.foundation.layout.Row | ||||
| import androidx.compose.foundation.layout.Spacer | ||||
| import androidx.compose.foundation.layout.height | ||||
| import androidx.compose.foundation.layout.padding | ||||
| import androidx.compose.foundation.layout.size | ||||
| import androidx.compose.foundation.layout.width | ||||
| import androidx.compose.foundation.shape.CircleShape | ||||
| import androidx.compose.material.MaterialTheme | ||||
| import androidx.compose.material.Text | ||||
| import androidx.compose.material3.MaterialTheme | ||||
| import androidx.compose.material3.Surface | ||||
| import androidx.compose.material3.Text | ||||
| import androidx.compose.runtime.Composable | ||||
| import androidx.compose.runtime.getValue | ||||
| import androidx.compose.runtime.mutableStateOf | ||||
| @@ -20,6 +23,7 @@ import androidx.compose.ui.Modifier | ||||
| import androidx.compose.ui.draw.clip | ||||
| import androidx.compose.ui.platform.LocalContext | ||||
| import androidx.compose.ui.res.painterResource | ||||
| import androidx.compose.ui.res.stringResource | ||||
| import androidx.compose.ui.tooling.preview.Preview | ||||
| import androidx.compose.ui.unit.dp | ||||
| import androidx.fragment.app.FragmentActivity | ||||
| @@ -27,6 +31,7 @@ import coil.compose.AsyncImage | ||||
| import org.schabi.newpipe.R | ||||
| import org.schabi.newpipe.extractor.comments.CommentsInfoItem | ||||
| import org.schabi.newpipe.extractor.stream.Description | ||||
| import org.schabi.newpipe.ui.theme.AppTheme | ||||
| import org.schabi.newpipe.util.NavigationHelper | ||||
| import org.schabi.newpipe.util.image.ImageStrategy | ||||
|  | ||||
| @@ -34,51 +39,93 @@ import org.schabi.newpipe.util.image.ImageStrategy | ||||
| fun Comment(comment: CommentsInfoItem) { | ||||
|     val context = LocalContext.current | ||||
|  | ||||
|     Row(modifier = Modifier.padding(all = 8.dp)) { | ||||
|         if (ImageStrategy.shouldLoadImages()) { | ||||
|             AsyncImage( | ||||
|                 model = ImageStrategy.choosePreferredImage(comment.uploaderAvatars), | ||||
|                 contentDescription = null, | ||||
|                 placeholder = painterResource(R.drawable.placeholder_person), | ||||
|                 error = painterResource(R.drawable.placeholder_person), | ||||
|                 modifier = Modifier | ||||
|                     .size(42.dp) | ||||
|                     .clip(CircleShape) | ||||
|                     .clickable { | ||||
|                         NavigationHelper.openCommentAuthorIfPresent(context as FragmentActivity, comment) | ||||
|     Surface(color = MaterialTheme.colorScheme.background) { | ||||
|         Row(modifier = Modifier.padding(all = 8.dp)) { | ||||
|             if (ImageStrategy.shouldLoadImages()) { | ||||
|                 AsyncImage( | ||||
|                     model = ImageStrategy.choosePreferredImage(comment.uploaderAvatars), | ||||
|                     contentDescription = null, | ||||
|                     placeholder = painterResource(R.drawable.placeholder_person), | ||||
|                     error = painterResource(R.drawable.placeholder_person), | ||||
|                     modifier = Modifier | ||||
|                         .size(42.dp) | ||||
|                         .clip(CircleShape) | ||||
|                         .clickable { | ||||
|                             NavigationHelper.openCommentAuthorIfPresent( | ||||
|                                 context as FragmentActivity, | ||||
|                                 comment | ||||
|                             ) | ||||
|                         } | ||||
|                 ) | ||||
|             } | ||||
|  | ||||
|             Spacer(modifier = Modifier.width(8.dp)) | ||||
|  | ||||
|             var isExpanded by rememberSaveable { mutableStateOf(false) } | ||||
|  | ||||
|             Column( | ||||
|                 modifier = Modifier.clickable { isExpanded = !isExpanded }, | ||||
|                 verticalArrangement = Arrangement.spacedBy(4.dp) | ||||
|             ) { | ||||
|                 Text( | ||||
|                     text = comment.uploaderName, | ||||
|                     color = MaterialTheme.colorScheme.secondary | ||||
|                 ) | ||||
|  | ||||
|                 Text( | ||||
|                     text = comment.commentText.content, | ||||
|                     // If the comment is expanded, we display all its content | ||||
|                     // otherwise we only display the first two lines | ||||
|                     maxLines = if (isExpanded) Int.MAX_VALUE else 2, | ||||
|                     style = MaterialTheme.typography.bodyMedium | ||||
|                 ) | ||||
|  | ||||
|                 Row(horizontalArrangement = Arrangement.spacedBy(8.dp)) { | ||||
|                     Image( | ||||
|                         painter = painterResource(R.drawable.ic_thumb_up), | ||||
|                         contentDescription = stringResource(R.string.detail_likes_img_view_description) | ||||
|                     ) | ||||
|                     Text(text = comment.likeCount.toString()) | ||||
|  | ||||
|                     if (comment.isHeartedByUploader) { | ||||
|                         Image( | ||||
|                             painter = painterResource(R.drawable.ic_heart), | ||||
|                             contentDescription = stringResource(R.string.detail_heart_img_view_description) | ||||
|                         ) | ||||
|                     } | ||||
|             ) | ||||
|  | ||||
|                     if (comment.isPinned) { | ||||
|                         Image( | ||||
|                             painter = painterResource(R.drawable.ic_pin), | ||||
|                             contentDescription = stringResource(R.string.detail_pinned_comment_view_description) | ||||
|                         ) | ||||
|                     } | ||||
|                 } | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         Spacer(modifier = Modifier.width(8.dp)) | ||||
|  | ||||
|         var isExpanded by rememberSaveable { mutableStateOf(false) } | ||||
|  | ||||
|         Column(modifier = Modifier.clickable { isExpanded = !isExpanded }) { | ||||
|             Text( | ||||
|                 text = comment.uploaderName, | ||||
|                 color = MaterialTheme.colors.secondary | ||||
|             ) | ||||
|  | ||||
|             Spacer(modifier = Modifier.height(4.dp)) | ||||
|  | ||||
|             Text( | ||||
|                 text = comment.commentText.content, | ||||
|                 // If the comment is expanded, we display all its content | ||||
|                 // otherwise we only display the first line | ||||
|                 maxLines = if (isExpanded) Int.MAX_VALUE else 1, | ||||
|                 style = MaterialTheme.typography.body2 | ||||
|             ) | ||||
|         } | ||||
|         // TODO: Add support for comment replies | ||||
|     } | ||||
| } | ||||
|  | ||||
| @Preview | ||||
| @Preview( | ||||
|     name = "Light mode", | ||||
|     uiMode = Configuration.UI_MODE_NIGHT_NO | ||||
| ) | ||||
| @Preview( | ||||
|     name = "Dark mode", | ||||
|     uiMode = Configuration.UI_MODE_NIGHT_YES | ||||
| ) | ||||
| @Composable | ||||
| fun CommentPreview() { | ||||
|     val comment = CommentsInfoItem(1, "", "") | ||||
|     comment.commentText = Description("Hello world!", Description.PLAIN_TEXT) | ||||
|     comment.uploaderName = "Test" | ||||
|     comment.likeCount = 100 | ||||
|     comment.isHeartedByUploader = true | ||||
|     comment.isPinned = true | ||||
|  | ||||
|     Comment(comment) | ||||
|     AppTheme { | ||||
|         Comment(comment) | ||||
|     } | ||||
| } | ||||
|   | ||||
| @@ -14,6 +14,7 @@ import org.schabi.newpipe.extractor.ListExtractor.InfoItemsPage | ||||
| import org.schabi.newpipe.extractor.comments.CommentsInfoItem | ||||
| import org.schabi.newpipe.fragments.list.BaseListInfoFragment | ||||
| import org.schabi.newpipe.info_list.ItemViewMode | ||||
| import org.schabi.newpipe.ui.theme.AppTheme | ||||
| import org.schabi.newpipe.util.ExtractorHelper | ||||
| import org.schabi.newpipe.util.Localization | ||||
| import java.util.Queue | ||||
| @@ -50,7 +51,9 @@ class CommentRepliesFragment() : BaseListInfoFragment<CommentsInfoItem, CommentR | ||||
|         return Supplier { | ||||
|             ComposeView(requireContext()).apply { | ||||
|                 setContent { | ||||
|                     CommentRepliesHeader(commentsInfoItem, disposables) | ||||
|                     AppTheme { | ||||
|                         CommentRepliesHeader(commentsInfoItem, disposables) | ||||
|                     } | ||||
|                 } | ||||
|             } | ||||
|         } | ||||
|   | ||||
| @@ -1,5 +1,6 @@ | ||||
| package org.schabi.newpipe.fragments.list.comments | ||||
|  | ||||
| import android.content.res.Configuration | ||||
| import android.widget.TextView | ||||
| import androidx.compose.foundation.Image | ||||
| import androidx.compose.foundation.clickable | ||||
| @@ -12,7 +13,9 @@ import androidx.compose.foundation.layout.padding | ||||
| import androidx.compose.foundation.layout.size | ||||
| import androidx.compose.foundation.layout.width | ||||
| import androidx.compose.foundation.shape.CircleShape | ||||
| import androidx.compose.material.Text | ||||
| import androidx.compose.material3.MaterialTheme | ||||
| import androidx.compose.material3.Surface | ||||
| import androidx.compose.material3.Text | ||||
| import androidx.compose.runtime.Composable | ||||
| import androidx.compose.ui.Alignment | ||||
| import androidx.compose.ui.Modifier | ||||
| @@ -31,6 +34,7 @@ import io.reactivex.rxjava3.disposables.CompositeDisposable | ||||
| import org.schabi.newpipe.R | ||||
| import org.schabi.newpipe.extractor.comments.CommentsInfoItem | ||||
| import org.schabi.newpipe.extractor.stream.Description | ||||
| import org.schabi.newpipe.ui.theme.AppTheme | ||||
| import org.schabi.newpipe.util.Localization | ||||
| import org.schabi.newpipe.util.NavigationHelper | ||||
| import org.schabi.newpipe.util.ServiceHelper | ||||
| @@ -41,94 +45,105 @@ import org.schabi.newpipe.util.text.TextLinkifier | ||||
| fun CommentRepliesHeader(comment: CommentsInfoItem, disposables: CompositeDisposable) { | ||||
|     val context = LocalContext.current | ||||
|  | ||||
|     Column(modifier = Modifier.padding(all = 8.dp)) { | ||||
|         Row( | ||||
|             modifier = Modifier.fillMaxWidth(), | ||||
|             verticalAlignment = Alignment.CenterVertically | ||||
|         ) { | ||||
|     Surface(color = MaterialTheme.colorScheme.background) { | ||||
|         Column(modifier = Modifier.padding(all = 8.dp)) { | ||||
|             Row( | ||||
|                 modifier = Modifier | ||||
|                     .padding(top = 8.dp, bottom = 8.dp, end = 8.dp) | ||||
|                     .clickable { | ||||
|                         NavigationHelper.openCommentAuthorIfPresent( | ||||
|                             context as FragmentActivity, | ||||
|                             comment | ||||
|                         ) | ||||
|                     }, | ||||
|                 modifier = Modifier.fillMaxWidth(), | ||||
|                 verticalAlignment = Alignment.CenterVertically | ||||
|             ) { | ||||
|                 if (ImageStrategy.shouldLoadImages()) { | ||||
|                     AsyncImage( | ||||
|                         model = ImageStrategy.choosePreferredImage(comment.uploaderAvatars), | ||||
|                         contentDescription = null, | ||||
|                         placeholder = painterResource(R.drawable.placeholder_person), | ||||
|                         error = painterResource(R.drawable.placeholder_person), | ||||
|                         modifier = Modifier | ||||
|                             .size(42.dp) | ||||
|                             .clip(CircleShape) | ||||
|                     ) | ||||
|                 Row( | ||||
|                     modifier = Modifier | ||||
|                         .padding(top = 8.dp, bottom = 8.dp, end = 8.dp) | ||||
|                         .clickable { | ||||
|                             NavigationHelper.openCommentAuthorIfPresent( | ||||
|                                 context as FragmentActivity, | ||||
|                                 comment | ||||
|                             ) | ||||
|                         }, | ||||
|                     verticalAlignment = Alignment.CenterVertically | ||||
|                 ) { | ||||
|                     if (ImageStrategy.shouldLoadImages()) { | ||||
|                         AsyncImage( | ||||
|                             model = ImageStrategy.choosePreferredImage(comment.uploaderAvatars), | ||||
|                             contentDescription = null, | ||||
|                             placeholder = painterResource(R.drawable.placeholder_person), | ||||
|                             error = painterResource(R.drawable.placeholder_person), | ||||
|                             modifier = Modifier | ||||
|                                 .size(42.dp) | ||||
|                                 .clip(CircleShape) | ||||
|                         ) | ||||
|                     } | ||||
|  | ||||
|                     Spacer(modifier = Modifier.width(8.dp)) | ||||
|  | ||||
|                     Column { | ||||
|                         Text(text = comment.uploaderName) | ||||
|  | ||||
|                         Text( | ||||
|                             color = MaterialTheme.colorScheme.secondary, | ||||
|                             style = MaterialTheme.typography.bodySmall, | ||||
|                             text = Localization.relativeTimeOrTextual( | ||||
|                                 context, comment.uploadDate, comment.textualUploadDate | ||||
|                             ) | ||||
|                         ) | ||||
|                     } | ||||
|                 } | ||||
|  | ||||
|                 Spacer(modifier = Modifier.width(8.dp)) | ||||
|                 Spacer(modifier = Modifier.weight(1f)) | ||||
|  | ||||
|                 Column { | ||||
|                     Text(text = comment.uploaderName) | ||||
|  | ||||
|                     Text( | ||||
|                         text = Localization.relativeTimeOrTextual( | ||||
|                             context, comment.uploadDate, comment.textualUploadDate | ||||
|                         ) | ||||
|                 Row( | ||||
|                     horizontalArrangement = Arrangement.spacedBy(8.dp), | ||||
|                     verticalAlignment = Alignment.CenterVertically | ||||
|                 ) { | ||||
|                     Image( | ||||
|                         painter = painterResource(R.drawable.ic_thumb_up), | ||||
|                         contentDescription = stringResource(R.string.detail_likes_img_view_description) | ||||
|                     ) | ||||
|                     Text(text = comment.likeCount.toString()) | ||||
|  | ||||
|                     if (comment.isHeartedByUploader) { | ||||
|                         Image( | ||||
|                             painter = painterResource(R.drawable.ic_heart), | ||||
|                             contentDescription = stringResource(R.string.detail_heart_img_view_description) | ||||
|                         ) | ||||
|                     } | ||||
|  | ||||
|                     if (comment.isPinned) { | ||||
|                         Image( | ||||
|                             painter = painterResource(R.drawable.ic_pin), | ||||
|                             contentDescription = stringResource(R.string.detail_pinned_comment_view_description) | ||||
|                         ) | ||||
|                     } | ||||
|                 } | ||||
|             } | ||||
|  | ||||
|             Spacer(modifier = Modifier.weight(1f)) | ||||
|  | ||||
|             Row( | ||||
|                 horizontalArrangement = Arrangement.spacedBy(8.dp), | ||||
|                 verticalAlignment = Alignment.CenterVertically | ||||
|             ) { | ||||
|                 Image( | ||||
|                     painter = painterResource(R.drawable.ic_thumb_up), | ||||
|                     contentDescription = stringResource(R.string.detail_likes_img_view_description) | ||||
|                 ) | ||||
|                 Text(text = comment.likeCount.toString()) | ||||
|  | ||||
|                 if (comment.isHeartedByUploader) { | ||||
|                     Image( | ||||
|                         painter = painterResource(R.drawable.ic_heart), | ||||
|                         contentDescription = stringResource(R.string.detail_heart_img_view_description) | ||||
|             AndroidView( | ||||
|                 factory = { context -> | ||||
|                     TextView(context).apply { | ||||
|                         movementMethod = LinkMovementMethodCompat.getInstance() | ||||
|                     } | ||||
|                 }, | ||||
|                 update = { view -> | ||||
|                     // setup comment content | ||||
|                     TextLinkifier.fromDescription( | ||||
|                         view, comment.commentText, HtmlCompat.FROM_HTML_MODE_LEGACY, | ||||
|                         ServiceHelper.getServiceById(comment.serviceId), comment.url, disposables, | ||||
|                         null | ||||
|                     ) | ||||
|                 } | ||||
|  | ||||
|                 if (comment.isPinned) { | ||||
|                     Image( | ||||
|                         painter = painterResource(R.drawable.ic_pin), | ||||
|                         contentDescription = stringResource(R.string.detail_pinned_comment_view_description) | ||||
|                     ) | ||||
|                 } | ||||
|             } | ||||
|             ) | ||||
|         } | ||||
|  | ||||
|         AndroidView( | ||||
|             factory = { context -> | ||||
|                 TextView(context).apply { | ||||
|                     movementMethod = LinkMovementMethodCompat.getInstance() | ||||
|                 } | ||||
|             }, | ||||
|             update = { view -> | ||||
|                 // setup comment content | ||||
|                 TextLinkifier.fromDescription( | ||||
|                     view, comment.commentText, HtmlCompat.FROM_HTML_MODE_LEGACY, | ||||
|                     ServiceHelper.getServiceById(comment.serviceId), comment.url, disposables, | ||||
|                     null | ||||
|                 ) | ||||
|             } | ||||
|         ) | ||||
|     } | ||||
| } | ||||
|  | ||||
| @Preview | ||||
| @Preview( | ||||
|     name = "Light mode", | ||||
|     uiMode = Configuration.UI_MODE_NIGHT_NO | ||||
| ) | ||||
| @Preview( | ||||
|     name = "Dark mode", | ||||
|     uiMode = Configuration.UI_MODE_NIGHT_YES | ||||
| ) | ||||
| @Composable | ||||
| fun CommentRepliesHeaderPreview() { | ||||
|     val disposables = CompositeDisposable() | ||||
| @@ -140,5 +155,7 @@ fun CommentRepliesHeaderPreview() { | ||||
|     comment.isPinned = true | ||||
|     comment.isHeartedByUploader = true | ||||
|  | ||||
|     CommentRepliesHeader(comment, disposables) | ||||
|     AppTheme { | ||||
|         CommentRepliesHeader(comment, disposables) | ||||
|     } | ||||
| } | ||||
|   | ||||
		Reference in New Issue
	
	Block a user
	 Isira Seneviratne
					Isira Seneviratne