mirror of
				https://github.com/TeamNewPipe/NewPipe
				synced 2025-11-04 09: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)
 | 
			
		||||
}
 | 
			
		||||
		Reference in New Issue
	
	Block a user