mirror of
				https://github.com/TeamNewPipe/NewPipe
				synced 2025-10-31 07:13:00 +00:00 
			
		
		
		
	Convert comment replies views to Jetpack Compose
This commit is contained in:
		| @@ -106,7 +106,7 @@ android { | ||||
|     } | ||||
|  | ||||
|     composeOptions { | ||||
|         kotlinCompilerExtensionVersion = "1.5.3" | ||||
|         kotlinCompilerExtensionVersion = "1.5.13" | ||||
|     } | ||||
| } | ||||
|  | ||||
| @@ -267,7 +267,7 @@ dependencies { | ||||
|     implementation "com.github.lisawray.groupie:groupie-viewbinding:${groupieVersion}" | ||||
|  | ||||
|     // Image loading | ||||
|     implementation 'io.coil-kt:coil:2.7.0' | ||||
|     implementation 'io.coil-kt:coil-compose:2.7.0' | ||||
|  | ||||
|     // Markdown library for Android | ||||
|     implementation "io.noties.markwon:core:${markwonVersion}" | ||||
| @@ -289,7 +289,7 @@ dependencies { | ||||
|     implementation "org.ocpsoft.prettytime:prettytime:5.0.8.Final" | ||||
|  | ||||
|     // Jetpack Compose | ||||
|     implementation(platform('androidx.compose:compose-bom:2024.02.01')) | ||||
|     implementation(platform('androidx.compose:compose-bom:2024.05.00')) | ||||
|     implementation 'androidx.compose.material3:material3' | ||||
|     implementation 'androidx.activity:activity-compose' | ||||
|     implementation 'androidx.compose.ui:ui-tooling-preview' | ||||
|   | ||||
| @@ -0,0 +1,84 @@ | ||||
| package org.schabi.newpipe.fragments.list.comments | ||||
|  | ||||
| import androidx.compose.foundation.clickable | ||||
| 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.runtime.Composable | ||||
| import androidx.compose.runtime.getValue | ||||
| import androidx.compose.runtime.mutableStateOf | ||||
| import androidx.compose.runtime.saveable.rememberSaveable | ||||
| import androidx.compose.runtime.setValue | ||||
| 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.tooling.preview.Preview | ||||
| import androidx.compose.ui.unit.dp | ||||
| import androidx.fragment.app.FragmentActivity | ||||
| 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.util.NavigationHelper | ||||
| import org.schabi.newpipe.util.image.ImageStrategy | ||||
|  | ||||
| @Composable | ||||
| 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) | ||||
|                     } | ||||
|             ) | ||||
|         } | ||||
|  | ||||
|         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 | ||||
|             ) | ||||
|         } | ||||
|     } | ||||
| } | ||||
|  | ||||
| @Preview | ||||
| @Composable | ||||
| fun CommentPreview() { | ||||
|     val comment = CommentsInfoItem(1, "", "") | ||||
|     comment.commentText = Description("Hello world!", Description.PLAIN_TEXT) | ||||
|     comment.uploaderName = "Test" | ||||
|  | ||||
|     Comment(comment) | ||||
| } | ||||
| @@ -0,0 +1,121 @@ | ||||
| package org.schabi.newpipe.fragments.list.comments | ||||
|  | ||||
| import android.widget.TextView | ||||
| import androidx.compose.foundation.Image | ||||
| import androidx.compose.foundation.clickable | ||||
| import androidx.compose.foundation.layout.Column | ||||
| import androidx.compose.foundation.layout.Row | ||||
| import androidx.compose.foundation.layout.Spacer | ||||
| 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.runtime.Composable | ||||
| 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.compose.ui.viewinterop.AndroidView | ||||
| import androidx.core.text.HtmlCompat | ||||
| import androidx.core.text.method.LinkMovementMethodCompat | ||||
| import androidx.fragment.app.FragmentActivity | ||||
| import coil.compose.AsyncImage | ||||
| 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.util.Localization | ||||
| import org.schabi.newpipe.util.NavigationHelper | ||||
| import org.schabi.newpipe.util.ServiceHelper | ||||
| import org.schabi.newpipe.util.image.ImageStrategy | ||||
| import org.schabi.newpipe.util.text.TextLinkifier | ||||
|  | ||||
| @Composable | ||||
| fun CommentRepliesHeader(comment: CommentsInfoItem, disposables: CompositeDisposable) { | ||||
|     val context = LocalContext.current | ||||
|  | ||||
|     Column(modifier = Modifier.padding(all = 8.dp)) { | ||||
|         Row { | ||||
|             Row( | ||||
|                 modifier = Modifier | ||||
|                     .padding(all = 8.dp) | ||||
|                     .clickable { | ||||
|                         NavigationHelper.openCommentAuthorIfPresent( | ||||
|                             context as FragmentActivity, | ||||
|                             comment | ||||
|                         ) | ||||
|                     } | ||||
|             ) { | ||||
|                 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( | ||||
|                         text = Localization.relativeTimeOrTextual( | ||||
|                             context, comment.uploadDate, comment.textualUploadDate | ||||
|                         ) | ||||
|                     ) | ||||
|                 } | ||||
|             } | ||||
|  | ||||
|             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) | ||||
|                 ) | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         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 | ||||
| @Composable | ||||
| fun CommentRepliesHeaderPreview() { | ||||
|     val disposables = CompositeDisposable() | ||||
|     val comment = CommentsInfoItem(1, "", "") | ||||
|     comment.commentText = Description("Hello world!", Description.PLAIN_TEXT) | ||||
|     comment.uploaderName = "Test" | ||||
|     comment.textualUploadDate = "5 months ago" | ||||
|  | ||||
|     CommentRepliesHeader(comment, disposables) | ||||
| } | ||||
| @@ -1,7 +1,7 @@ | ||||
| // Top-level build file where you can add configuration options common to all sub-projects/modules. | ||||
|  | ||||
| buildscript { | ||||
|     ext.kotlin_version = '1.9.10' | ||||
|     ext.kotlin_version = '1.9.23' | ||||
|     repositories { | ||||
|         google() | ||||
|         mavenCentral() | ||||
|   | ||||
		Reference in New Issue
	
	Block a user
	 Isira Seneviratne
					Isira Seneviratne