Convert comment replies views to Jetpack Compose

This commit is contained in:
Isira Seneviratne 2024-05-12 08:21:13 +05:30
parent d479f29e9b
commit 6fead0bccc
4 changed files with 209 additions and 3 deletions

View File

@ -106,7 +106,7 @@ android {
} }
composeOptions { composeOptions {
kotlinCompilerExtensionVersion = "1.5.3" kotlinCompilerExtensionVersion = "1.5.13"
} }
} }
@ -269,6 +269,7 @@ dependencies {
// Image loading // Image loading
//noinspection GradleDependency --> 2.8 is the last version, not 2.71828! //noinspection GradleDependency --> 2.8 is the last version, not 2.71828!
implementation "com.squareup.picasso:picasso:2.8" implementation "com.squareup.picasso:picasso:2.8"
implementation 'io.coil-kt:coil-compose:2.6.0'
// Markdown library for Android // Markdown library for Android
implementation "io.noties.markwon:core:${markwonVersion}" implementation "io.noties.markwon:core:${markwonVersion}"
@ -290,7 +291,7 @@ dependencies {
implementation "org.ocpsoft.prettytime:prettytime:5.0.7.Final" implementation "org.ocpsoft.prettytime:prettytime:5.0.7.Final"
// Jetpack Compose // 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.compose.material3:material3'
implementation 'androidx.activity:activity-compose' implementation 'androidx.activity:activity-compose'
implementation 'androidx.compose.ui:ui-tooling-preview' implementation 'androidx.compose.ui:ui-tooling-preview'

View File

@ -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)
}

View File

@ -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)
}

View File

@ -1,7 +1,7 @@
// Top-level build file where you can add configuration options common to all sub-projects/modules. // Top-level build file where you can add configuration options common to all sub-projects/modules.
buildscript { buildscript {
ext.kotlin_version = '1.9.10' ext.kotlin_version = '1.9.23'
repositories { repositories {
google() google()
mavenCentral() mavenCentral()