mirror of
https://github.com/TeamNewPipe/NewPipe
synced 2024-12-23 16:40:32 +00:00
Use reply header composable in fragment
This commit is contained in:
parent
644a345b55
commit
e05d97732e
@ -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.getCommentsInfoItem();
|
||||
repliesFragment == null ? null : repliesFragment.commentsInfoItem;
|
||||
|
||||
// sometimes this function pops the backstack, other times it's handled by the system
|
||||
if (popBackStack) {
|
||||
|
@ -1,170 +1,104 @@
|
||||
package org.schabi.newpipe.fragments.list.comments;
|
||||
package org.schabi.newpipe.fragments.list.comments
|
||||
|
||||
import static org.schabi.newpipe.util.ServiceHelper.getServiceById;
|
||||
|
||||
import android.os.Bundle;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.constraintlayout.widget.ConstraintLayout;
|
||||
import androidx.core.text.HtmlCompat;
|
||||
|
||||
import org.schabi.newpipe.R;
|
||||
import org.schabi.newpipe.databinding.CommentRepliesHeaderBinding;
|
||||
import org.schabi.newpipe.error.UserAction;
|
||||
import org.schabi.newpipe.extractor.ListExtractor;
|
||||
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.util.DeviceUtils;
|
||||
import org.schabi.newpipe.util.ExtractorHelper;
|
||||
import org.schabi.newpipe.util.Localization;
|
||||
import org.schabi.newpipe.util.NavigationHelper;
|
||||
import org.schabi.newpipe.util.image.CoilHelper;
|
||||
import org.schabi.newpipe.util.image.ImageStrategy;
|
||||
import org.schabi.newpipe.util.text.TextLinkifier;
|
||||
|
||||
import java.util.Queue;
|
||||
import java.util.function.Supplier;
|
||||
|
||||
import icepick.State;
|
||||
import io.reactivex.rxjava3.core.Single;
|
||||
import io.reactivex.rxjava3.disposables.CompositeDisposable;
|
||||
|
||||
public final class CommentRepliesFragment
|
||||
extends BaseListInfoFragment<CommentsInfoItem, CommentRepliesInfo> {
|
||||
|
||||
public static final String TAG = CommentRepliesFragment.class.getSimpleName();
|
||||
import android.os.Bundle
|
||||
import android.view.LayoutInflater
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import androidx.compose.ui.platform.ComposeView
|
||||
import icepick.State
|
||||
import io.reactivex.rxjava3.core.Single
|
||||
import io.reactivex.rxjava3.disposables.CompositeDisposable
|
||||
import org.schabi.newpipe.R
|
||||
import org.schabi.newpipe.error.UserAction
|
||||
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.util.ExtractorHelper
|
||||
import org.schabi.newpipe.util.Localization
|
||||
import java.util.Queue
|
||||
import java.util.function.Supplier
|
||||
|
||||
class CommentRepliesFragment() : BaseListInfoFragment<CommentsInfoItem, CommentRepliesInfo>(UserAction.REQUESTED_COMMENT_REPLIES) {
|
||||
/**
|
||||
* @return the comment to which the replies are shown
|
||||
*/
|
||||
@State
|
||||
CommentsInfoItem commentsInfoItem; // the comment to show replies of
|
||||
private final CompositeDisposable disposables = new CompositeDisposable();
|
||||
lateinit var commentsInfoItem: CommentsInfoItem // the comment to show replies of
|
||||
private val disposables = CompositeDisposable()
|
||||
|
||||
|
||||
/*//////////////////////////////////////////////////////////////////////////
|
||||
// Constructors and lifecycle
|
||||
//////////////////////////////////////////////////////////////////////////*/
|
||||
|
||||
// only called by the Android framework, after which readFrom is called and restores all data
|
||||
public CommentRepliesFragment() {
|
||||
super(UserAction.REQUESTED_COMMENT_REPLIES);
|
||||
}
|
||||
|
||||
public CommentRepliesFragment(@NonNull final CommentsInfoItem commentsInfoItem) {
|
||||
this();
|
||||
this.commentsInfoItem = commentsInfoItem;
|
||||
constructor(commentsInfoItem: CommentsInfoItem) : this() {
|
||||
this.commentsInfoItem = commentsInfoItem
|
||||
// setting "" as title since the title will be properly set right after
|
||||
setInitialData(commentsInfoItem.getServiceId(), commentsInfoItem.getUrl(), "");
|
||||
setInitialData(commentsInfoItem.serviceId, commentsInfoItem.url, "")
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public View onCreateView(@NonNull final LayoutInflater inflater,
|
||||
@Nullable final ViewGroup container,
|
||||
@Nullable final Bundle savedInstanceState) {
|
||||
return inflater.inflate(R.layout.fragment_comments, container, false);
|
||||
override fun onCreateView(
|
||||
inflater: LayoutInflater,
|
||||
container: ViewGroup?,
|
||||
savedInstanceState: Bundle?
|
||||
): View {
|
||||
return inflater.inflate(R.layout.fragment_comments, container, false)
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDestroyView() {
|
||||
disposables.clear();
|
||||
super.onDestroyView();
|
||||
override fun onDestroyView() {
|
||||
disposables.clear()
|
||||
super.onDestroyView()
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Supplier<View> getListHeaderSupplier() {
|
||||
return () -> {
|
||||
final CommentRepliesHeaderBinding binding = CommentRepliesHeaderBinding
|
||||
.inflate(activity.getLayoutInflater(), itemsList, false);
|
||||
final CommentsInfoItem item = commentsInfoItem;
|
||||
|
||||
// load the author avatar
|
||||
CoilHelper.INSTANCE.loadAvatar(binding.authorAvatar, item.getUploaderAvatars());
|
||||
binding.authorAvatar.setVisibility(ImageStrategy.shouldLoadImages()
|
||||
? View.VISIBLE : View.GONE);
|
||||
|
||||
// setup author name and comment date
|
||||
binding.authorName.setText(item.getUploaderName());
|
||||
binding.uploadDate.setText(Localization.relativeTimeOrTextual(
|
||||
getContext(), item.getUploadDate(), item.getTextualUploadDate()));
|
||||
binding.authorTouchArea.setOnClickListener(
|
||||
v -> NavigationHelper.openCommentAuthorIfPresent(requireActivity(), item));
|
||||
|
||||
// setup like count, hearted and pinned
|
||||
binding.thumbsUpCount.setText(
|
||||
Localization.likeCount(requireContext(), item.getLikeCount()));
|
||||
// for heartImage goneMarginEnd was used, but there is no way to tell ConstraintLayout
|
||||
// not to use a different margin only when both the next two views are gone
|
||||
((ConstraintLayout.LayoutParams) binding.thumbsUpCount.getLayoutParams())
|
||||
.setMarginEnd(DeviceUtils.dpToPx(
|
||||
(item.isHeartedByUploader() || item.isPinned() ? 8 : 16),
|
||||
requireContext()));
|
||||
binding.heartImage.setVisibility(item.isHeartedByUploader() ? View.VISIBLE : View.GONE);
|
||||
binding.pinnedImage.setVisibility(item.isPinned() ? View.VISIBLE : View.GONE);
|
||||
|
||||
// setup comment content
|
||||
TextLinkifier.fromDescription(binding.commentContent, item.getCommentText(),
|
||||
HtmlCompat.FROM_HTML_MODE_LEGACY, getServiceById(item.getServiceId()),
|
||||
item.getUrl(), disposables, null);
|
||||
|
||||
return binding.getRoot();
|
||||
};
|
||||
override fun getListHeaderSupplier(): Supplier<View> {
|
||||
return Supplier {
|
||||
ComposeView(requireContext()).apply {
|
||||
setContent {
|
||||
CommentRepliesHeader(commentsInfoItem, disposables)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*//////////////////////////////////////////////////////////////////////////
|
||||
// State saving
|
||||
////////////////////////////////////////////////////////////////////////// */
|
||||
|
||||
@Override
|
||||
public void writeTo(final Queue<Object> objectsToSave) {
|
||||
super.writeTo(objectsToSave);
|
||||
objectsToSave.add(commentsInfoItem);
|
||||
override fun writeTo(objectsToSave: Queue<Any>) {
|
||||
super.writeTo(objectsToSave)
|
||||
objectsToSave.add(commentsInfoItem)
|
||||
}
|
||||
|
||||
@Override
|
||||
public void readFrom(@NonNull final Queue<Object> savedObjects) throws Exception {
|
||||
super.readFrom(savedObjects);
|
||||
commentsInfoItem = (CommentsInfoItem) savedObjects.poll();
|
||||
@Throws(Exception::class)
|
||||
override fun readFrom(savedObjects: Queue<Any>) {
|
||||
super.readFrom(savedObjects)
|
||||
commentsInfoItem = savedObjects.poll() as CommentsInfoItem
|
||||
}
|
||||
|
||||
|
||||
/*//////////////////////////////////////////////////////////////////////////
|
||||
// Data loading
|
||||
////////////////////////////////////////////////////////////////////////// */
|
||||
|
||||
@Override
|
||||
protected Single<CommentRepliesInfo> loadResult(final boolean forceLoad) {
|
||||
return Single.fromCallable(() -> new CommentRepliesInfo(commentsInfoItem,
|
||||
// the reply count string will be shown as the activity title
|
||||
Localization.replyCount(requireContext(), commentsInfoItem.getReplyCount())));
|
||||
override fun loadResult(forceLoad: Boolean): Single<CommentRepliesInfo> {
|
||||
return Single.fromCallable {
|
||||
CommentRepliesInfo(
|
||||
commentsInfoItem, // the reply count string will be shown as the activity title
|
||||
Localization.replyCount(requireContext(), commentsInfoItem.replyCount)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Single<ListExtractor.InfoItemsPage<CommentsInfoItem>> loadMoreItemsLogic() {
|
||||
override fun loadMoreItemsLogic(): Single<InfoItemsPage<CommentsInfoItem?>>? {
|
||||
// commentsInfoItem.getUrl() should contain the url of the original
|
||||
// ListInfo<CommentsInfoItem>, which should be the stream url
|
||||
return ExtractorHelper.getMoreCommentItems(
|
||||
serviceId, commentsInfoItem.getUrl(), currentNextPage);
|
||||
serviceId, commentsInfoItem.url, currentNextPage
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
/*//////////////////////////////////////////////////////////////////////////
|
||||
// Utils
|
||||
////////////////////////////////////////////////////////////////////////// */
|
||||
|
||||
@Override
|
||||
protected ItemViewMode getItemViewMode() {
|
||||
return ItemViewMode.LIST;
|
||||
override fun getItemViewMode(): ItemViewMode {
|
||||
return ItemViewMode.LIST
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the comment to which the replies are shown
|
||||
*/
|
||||
public CommentsInfoItem getCommentsInfoItem() {
|
||||
return commentsInfoItem;
|
||||
companion object {
|
||||
@JvmField
|
||||
val TAG: String = CommentRepliesFragment::class.java.simpleName
|
||||
}
|
||||
}
|
||||
|
@ -98,8 +98,8 @@ fun CommentRepliesHeader(comment: CommentsInfoItem, disposables: CompositeDispos
|
||||
},
|
||||
update = { view ->
|
||||
// setup comment content
|
||||
TextLinkifier.fromDescription(view, comment.commentText,
|
||||
HtmlCompat.FROM_HTML_MODE_LEGACY,
|
||||
TextLinkifier.fromDescription(
|
||||
view, comment.commentText, HtmlCompat.FROM_HTML_MODE_LEGACY,
|
||||
ServiceHelper.getServiceById(comment.serviceId), comment.url, disposables,
|
||||
null
|
||||
)
|
||||
|
@ -1,137 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content">
|
||||
|
||||
<com.google.android.material.imageview.ShapeableImageView
|
||||
android:id="@+id/authorAvatar"
|
||||
android:layout_width="42dp"
|
||||
android:layout_height="42dp"
|
||||
android:layout_marginStart="16dp"
|
||||
android:layout_marginTop="16dp"
|
||||
android:focusable="false"
|
||||
android:src="@drawable/placeholder_person"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent"
|
||||
app:shapeAppearance="@style/CircularImageView"
|
||||
tools:ignore="RtlHardcoded" />
|
||||
|
||||
<org.schabi.newpipe.views.NewPipeTextView
|
||||
android:id="@+id/authorName"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="8dp"
|
||||
android:layout_marginEnd="8dp"
|
||||
android:ellipsize="end"
|
||||
android:lines="1"
|
||||
android:textAppearance="?android:attr/textAppearanceLarge"
|
||||
android:textSize="16sp"
|
||||
app:layout_constraintBottom_toTopOf="@+id/uploadDate"
|
||||
app:layout_constraintEnd_toStartOf="@+id/thumbsUpImage"
|
||||
app:layout_constraintStart_toEndOf="@+id/authorAvatar"
|
||||
app:layout_constraintTop_toTopOf="@+id/authorAvatar"
|
||||
tools:text="@tools:sample/lorem/random" />
|
||||
|
||||
<org.schabi.newpipe.views.NewPipeTextView
|
||||
android:id="@+id/uploadDate"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="8dp"
|
||||
android:layout_marginEnd="8dp"
|
||||
android:ellipsize="end"
|
||||
android:lines="1"
|
||||
android:textAppearance="?android:attr/textAppearanceSmall"
|
||||
android:textSize="14sp"
|
||||
app:layout_constraintBottom_toBottomOf="@+id/authorAvatar"
|
||||
app:layout_constraintEnd_toStartOf="@+id/thumbsUpImage"
|
||||
app:layout_constraintStart_toEndOf="@+id/authorAvatar"
|
||||
app:layout_constraintTop_toBottomOf="@+id/authorName"
|
||||
tools:text="5 months ago" />
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/thumbsUpImage"
|
||||
android:layout_width="21sp"
|
||||
android:layout_height="21sp"
|
||||
android:layout_marginEnd="@dimen/video_item_detail_like_margin"
|
||||
android:contentDescription="@string/detail_likes_img_view_description"
|
||||
android:src="@drawable/ic_thumb_up"
|
||||
app:layout_constraintBottom_toBottomOf="@+id/authorAvatar"
|
||||
app:layout_constraintEnd_toStartOf="@+id/thumbsUpCount"
|
||||
app:layout_constraintTop_toTopOf="@+id/authorAvatar" />
|
||||
|
||||
<org.schabi.newpipe.views.NewPipeTextView
|
||||
android:id="@+id/thumbsUpCount"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginEnd="8dp"
|
||||
android:gravity="center"
|
||||
android:lines="1"
|
||||
android:textAppearance="?android:attr/textAppearanceMedium"
|
||||
android:textSize="14sp"
|
||||
app:layout_constraintBottom_toBottomOf="@+id/authorAvatar"
|
||||
app:layout_constraintEnd_toStartOf="@+id/heartImage"
|
||||
app:layout_constraintTop_toTopOf="@+id/authorAvatar"
|
||||
tools:text="12M" />
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/heartImage"
|
||||
android:layout_width="21sp"
|
||||
android:layout_height="21sp"
|
||||
android:layout_marginEnd="4dp"
|
||||
android:contentDescription="@string/detail_heart_img_view_description"
|
||||
android:src="@drawable/ic_heart"
|
||||
app:layout_constraintBottom_toBottomOf="@+id/authorAvatar"
|
||||
app:layout_constraintEnd_toStartOf="@+id/pinnedImage"
|
||||
app:layout_constraintTop_toTopOf="@+id/authorAvatar"
|
||||
app:layout_goneMarginEnd="16dp" />
|
||||
|
||||
<View
|
||||
android:id="@+id/authorTouchArea"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="0dp"
|
||||
android:layout_margin="8dp"
|
||||
android:background="?attr/selectableItemBackground"
|
||||
app:layout_constraintBottom_toTopOf="@+id/commentContent"
|
||||
app:layout_constraintEnd_toStartOf="@+id/thumbsUpImage"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent" />
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/pinnedImage"
|
||||
android:layout_width="21sp"
|
||||
android:layout_height="21sp"
|
||||
android:layout_marginEnd="16dp"
|
||||
android:contentDescription="@string/detail_pinned_comment_view_description"
|
||||
android:src="@drawable/ic_pin"
|
||||
app:layout_constraintBottom_toBottomOf="@+id/authorAvatar"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintTop_toTopOf="@+id/authorAvatar" />
|
||||
|
||||
<org.schabi.newpipe.views.NewPipeTextView
|
||||
android:id="@+id/commentContent"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="16dp"
|
||||
android:layout_marginTop="16dp"
|
||||
android:layout_marginEnd="16dp"
|
||||
android:textAppearance="?android:attr/textAppearanceLarge"
|
||||
android:textSize="14sp"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@+id/authorAvatar"
|
||||
tools:text="@tools:sample/lorem/random[10]" />
|
||||
|
||||
<View
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="1px"
|
||||
android:layout_marginTop="16dp"
|
||||
android:layout_marginBottom="8dp"
|
||||
android:background="?attr/separator_color"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@+id/commentContent" />
|
||||
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
Loading…
Reference in New Issue
Block a user