Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
35 commits
Select commit Hold shift + click to select a range
14ec5c0
Added "Show Replies"
golfinq Oct 13, 2021
fe5c8e2
Changed "Show Replies" to Resource
golfinq Oct 14, 2021
82e3772
Remove redundant string resource
golfinq Oct 15, 2021
07bf1ec
Fixed behavior when scrolling
golfinq Oct 15, 2021
fc7695e
Moved downloading and reply code to new class
golfinq Oct 20, 2021
c3aa73b
Non-Blocking Downloading and Showing
golfinq Oct 22, 2021
394655c
Fix some style issues
DUOLabs333 May 27, 2022
c183969
Add setInfoItemList to RepliesHandler.java
DUOLabs333 May 27, 2022
b9468ec
Replace {set,get}RepliesOpen with just assignment statements
DUOLabs333 May 27, 2022
9933fef
Fix style errors
DUOLabs333 May 27, 2022
8693af1
Replaced {set,get}RepliesOpen with directly getting the replies
DUOLabs333 May 27, 2022
3cc4444
Fix style errors
DUOLabs333 May 27, 2022
951530c
Fix line being too long
DUOLabs333 May 27, 2022
6a037ce
Fix line being too long
DUOLabs333 May 27, 2022
b058ab1
Fix line splitting issue
DUOLabs333 May 27, 2022
fb1c856
Removed info and trying something out
DUOLabs333 May 27, 2022
c6ff73d
Replace TextView with NewPipeTextView, change showReplies text, and n…
DUOLabs333 May 27, 2022
89b4c57
Don't download comments by default
DUOLabs333 May 27, 2022
a2d4b5c
Remove unused import android.widget.TextView
DUOLabs333 May 27, 2022
ddf2010
Use org.schabi.newpipe.views.NewPipeTextView
DUOLabs333 May 27, 2022
22e72b9
Use org.schabi.newpipe.views.NewPipeTextView instead of TextView in l…
DUOLabs333 May 27, 2022
cf7aeb4
Fix TextView import in CommentsInfoItemHolder.java
DUOLabs333 May 27, 2022
6efec1f
Remove channel_details strings from strings.xml
DUOLabs333 May 27, 2022
6649784
Remove testing from CI for faster iteration (remember to revert later
DUOLabs333 May 27, 2022
6800dd7
Change showReplies default text
DUOLabs333 May 27, 2022
005573b
Add back show_replies in strings.xml
DUOLabs333 May 27, 2022
3eedd5b
Trying something
DUOLabs333 May 27, 2022
3693402
Try something else
DUOLabs333 May 27, 2022
a59bc0c
Try something else
DUOLabs333 May 27, 2022
645e140
Fix Replies toggle
DUOLabs333 May 28, 2022
943a629
Make onSubscribe a no-op to fix compiling error
DUOLabs333 Jun 7, 2022
d9e02b1
Add push to comment-replies as a workflow trigger
DUOLabs333 Jun 7, 2022
572cd15
Fix style errors
DUOLabs333 Jun 7, 2022
028e7ab
Fix style errors
DUOLabs333 Jun 7, 2022
8f63646
Last commit that works
DUOLabs333 Jun 8, 2022
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
65 changes: 4 additions & 61 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ on:
branches:
- dev
- master
- comment-replies
paths-ignore:
- 'README.md'
- 'doc/**'
Expand Down Expand Up @@ -47,71 +48,13 @@ jobs:
distribution: "temurin"
cache: 'gradle'

- name: Build debug APK and run jvm tests
run: ./gradlew assembleDebug lintDebug testDebugUnitTest --stacktrace -DskipFormatKtlint
- name: Build debug APK
run: ./gradlew assembleDebug --stacktrace -DskipFormatKtlint

- name: Upload APK
uses: actions/upload-artifact@v3
with:
name: app
path: app/build/outputs/apk/debug/*.apk

test-android:
# macos has hardware acceleration. See android-emulator-runner action
runs-on: macos-latest
timeout-minutes: 20
strategy:
matrix:
# api-level 19 is min sdk, but throws errors related to desugaring
api-level: [ 21, 29 ]
steps:
- uses: actions/checkout@v3

- name: set up JDK 11
uses: actions/setup-java@v3
with:
java-version: 11
distribution: "temurin"
cache: 'gradle'

- name: Run android tests
uses: reactivecircus/android-emulator-runner@v2
with:
api-level: ${{ matrix.api-level }}
# workaround to emulator bug: https://github.com/ReactiveCircus/android-emulator-runner/issues/160
emulator-build: 7425822
script: ./gradlew connectedCheck --stacktrace

- name: Upload test report when tests fail # because the printed out stacktrace (console) is too short, see also #7553
uses: actions/upload-artifact@v3
if: failure()
with:
name: android-test-report-api${{ matrix.api-level }}
path: app/build/reports/androidTests/connected/**

sonar:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
with:
fetch-depth: 0 # Shallow clones should be disabled for a better relevancy of analysis

- name: Set up JDK 11
uses: actions/setup-java@v3
with:
java-version: 11 # Sonar requires JDK 11
distribution: "temurin"
cache: 'gradle'

- name: Cache SonarCloud packages
uses: actions/cache@v3
with:
path: ~/.sonar/cache
key: ${{ runner.os }}-sonar
restore-keys: ${{ runner.os }}-sonar

- name: Build and analyze
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} # Needed to get PR information, if any
SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }}
run: ./gradlew build sonarqube --info

Original file line number Diff line number Diff line change
Expand Up @@ -149,6 +149,11 @@ public void addInfoItemList(@Nullable final List<? extends InfoItem> data) {
}
}

public void setInfoItemList(final List<? extends InfoItem> data) {
infoItemList.clear();
infoItemList.addAll(data);
notifyDataSetChanged();
}
public void clearStreamItemList() {
if (infoItemList.isEmpty()) {
return;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
import android.view.ViewGroup;
import android.widget.ImageView;
import android.widget.TextView;
import androidx.recyclerview.widget.RecyclerView;

import org.schabi.newpipe.R;
import org.schabi.newpipe.extractor.InfoItem;
Expand Down Expand Up @@ -35,13 +36,16 @@ public class CommentsInfoItemHolder extends CommentsMiniInfoItemHolder {
public final TextView itemTitleView;
private final ImageView itemHeartView;
private final ImageView itemPinnedView;

private final RepliesHandler repliesHandler;
public CommentsInfoItemHolder(final InfoItemBuilder infoItemBuilder, final ViewGroup parent) {
super(infoItemBuilder, R.layout.list_comments_item, parent);

itemTitleView = itemView.findViewById(R.id.itemTitleView);
itemHeartView = itemView.findViewById(R.id.detail_heart_image_view);
itemPinnedView = itemView.findViewById(R.id.detail_pinned_view);
final TextView showReplies = itemView.findViewById(R.id.showReplies);
final RecyclerView repliesView = itemView.findViewById(R.id.replyRecycleView);
repliesHandler = new RepliesHandler(showReplies, repliesView);
}

@Override
Expand All @@ -53,11 +57,9 @@ public void updateFromItem(final InfoItem infoItem,
return;
}
final CommentsInfoItem item = (CommentsInfoItem) infoItem;

itemTitleView.setText(item.getUploaderName());

itemHeartView.setVisibility(item.isHeartedByUploader() ? View.VISIBLE : View.GONE);

itemPinnedView.setVisibility(item.isPinned() ? View.VISIBLE : View.GONE);
repliesHandler.checkForReplies(item);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,190 @@
package org.schabi.newpipe.info_list.holder;

import android.annotation.SuppressLint;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;

import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView;

import org.schabi.newpipe.extractor.ListExtractor;
import org.schabi.newpipe.extractor.comments.CommentsInfo;
import org.schabi.newpipe.extractor.comments.CommentsInfoItem;
import org.schabi.newpipe.info_list.InfoListAdapter;
import org.schabi.newpipe.util.ExtractorHelper;

import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
import java.util.concurrent.Callable;

import io.reactivex.rxjava3.android.schedulers.AndroidSchedulers;
import io.reactivex.rxjava3.annotations.NonNull;
import io.reactivex.rxjava3.core.Single;
import io.reactivex.rxjava3.core.SingleObserver;
import io.reactivex.rxjava3.disposables.Disposable;
import io.reactivex.rxjava3.schedulers.Schedulers;

public class RepliesHandler {
private final List<CommentsInfoItem> cachedReplies;
private final TextView showReplies;
private final RecyclerView repliesView;

public RepliesHandler(final TextView showReplies, final RecyclerView recyclerView) {
this.repliesView = recyclerView;
repliesView.setAdapter(new InfoListAdapter(repliesView.getContext()));
repliesView.setLayoutManager(new LinearLayoutManager(repliesView.getContext()));

this.showReplies = showReplies;
this.cachedReplies = new ArrayList<>();
}

static class GetMoreItemsCallable implements
Callable<ListExtractor.InfoItemsPage<CommentsInfoItem>> {
private CommentsInfo parentCommentInfo;
private CommentsInfoItem parentInfoItem;

public void setCallableParameters(
final CommentsInfo commentInfo, final CommentsInfoItem infoItem) {
parentCommentInfo = commentInfo;
parentInfoItem = infoItem;
}

@Override
public ListExtractor.InfoItemsPage<CommentsInfoItem> call() throws Exception {
return CommentsInfo.getMoreItems(parentCommentInfo, parentInfoItem.getReplies());
}
}

private Single<ListExtractor.InfoItemsPage<CommentsInfoItem>>
repliesSingle(final CommentsInfo parentCommentInfo,
final CommentsInfoItem parentInfoItem) {

final GetMoreItemsCallable getMoreItems = new GetMoreItemsCallable();
getMoreItems.setCallableParameters(parentCommentInfo, parentInfoItem);
return Single.fromCallable(getMoreItems);

}

private SingleObserver<ListExtractor.InfoItemsPage<CommentsInfoItem>>
repliesObserver(final CommentsInfoItem parentInfoItem) {

return new SingleObserver<ListExtractor.InfoItemsPage<CommentsInfoItem>>() {

@SuppressLint("SetTextI18n")
@Override
public void onSubscribe(@NonNull final Disposable d) {
showReplies.setText("Collapse");
}

@Override
public void onSuccess(@NonNull final
ListExtractor.InfoItemsPage<CommentsInfoItem>
commentsInfoItemInfoItemsPage) {

final List<CommentsInfoItem> actualList
= commentsInfoItemInfoItemsPage.getItems();

cachedReplies.addAll(actualList);
addRepliesToUI(parentInfoItem);
}

@SuppressLint("SetTextI18n")
@Override
public void onError(@NonNull final Throwable e) {
showReplies.setText("Error getting replies");
}
};
}

private SingleObserver<CommentsInfo>
repliesInfoObserver(final CommentsInfoItem parentInfoItem) {

return new SingleObserver<CommentsInfo>() {
@Override

public void onSubscribe(@NonNull final Disposable d) {

}
@Override
public void onSuccess(@NonNull final CommentsInfo commentsInfo) {
final Single<ListExtractor.InfoItemsPage<CommentsInfoItem>>
getRepliesInfoSingle =
repliesSingle(commentsInfo, parentInfoItem);

final SingleObserver<ListExtractor.InfoItemsPage<CommentsInfoItem>>
getRepliesInfoObserver = repliesObserver(parentInfoItem);

getRepliesInfoSingle
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(getRepliesInfoObserver);
}

@SuppressLint("SetTextI18n")
@Override
public void onError(@NonNull final Throwable e) {
showReplies.setText("Error getting replies");
}
};
}


public void addRepliesToUI(final CommentsInfoItem parentInfoItem) {
((InfoListAdapter) Objects.requireNonNull(repliesView.getAdapter()))
.setInfoItemList(cachedReplies);

final ViewGroup.MarginLayoutParams params =
(ViewGroup.MarginLayoutParams) repliesView.getLayoutParams();
params.topMargin = 45;

repliesView.setMinimumHeight(100);
repliesView.setHasFixedSize(true);
repliesView.setVisibility(View.VISIBLE);
}

public void downloadReplies(final CommentsInfoItem parentInfoItem) {

final Single<CommentsInfo> parentInfoSingle = ExtractorHelper.getCommentsInfo(
parentInfoItem.getServiceId(),
parentInfoItem.getUrl(),
false
);

final SingleObserver<CommentsInfo> singleInfoRepliesInfoObserver
= repliesInfoObserver(parentInfoItem);

parentInfoSingle
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(singleInfoRepliesInfoObserver);
}

public void addReplies(final CommentsInfoItem parentInfoItem) {
if (parentInfoItem.getReplies() == null) {
return;
}

if (cachedReplies.isEmpty()) {
downloadReplies(parentInfoItem);
addRepliesToUI(parentInfoItem);
showReplies.setText("Collapse");
} else {
cachedReplies.clear();
repliesView.setVisibility(View.GONE);
showReplies.setText("Show Replies");
}
}

public void checkForReplies(final CommentsInfoItem item) {
if (item.getReplies() == null) {
repliesView.setVisibility(View.GONE);
showReplies.setVisibility(View.GONE);
} else {
repliesView.setVisibility(View.GONE);
showReplies.setVisibility(View.VISIBLE);
showReplies.setOnClickListener(v -> addReplies(item));
}
}
}
30 changes: 30 additions & 0 deletions app/src/main/res/layout/list_comments_item.xml
Original file line number Diff line number Diff line change
Expand Up @@ -136,4 +136,34 @@
android:textSize="@dimen/video_item_search_upload_date_text_size"
tools:text="1 year ago" />

<org.schabi.newpipe.views.NewPipeTextView
android:id="@+id/showReplies"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="@+id/itemCommentContentView"
android:layout_alignEnd="@+id/itemCommentContentView"
android:layout_alignBottom="@+id/itemPublishedTime"
android:layout_marginStart="21dp"
android:layout_marginTop="0sp"
android:layout_marginEnd="0sp"
android:layout_marginBottom="0sp"
android:layout_toEndOf="@+id/itemPublishedTime"
android:text="@string/show_replies"
android:textAppearance="@style/TextAppearance.AppCompat.Small"
android:textSize="@dimen/video_item_search_upload_date_text_size" />

<androidx.recyclerview.widget.RecyclerView
android:id="@+id/replyRecycleView"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_below="@+id/showReplies"
android:layout_alignStart="@+id/itemCommentContentView"
android:layout_alignEnd="@+id/itemCommentContentView"
android:layout_marginStart="0dp"
android:layout_marginTop="0dp"
android:layout_marginEnd="0dp"
android:layout_marginBottom="0dp">

</androidx.recyclerview.widget.RecyclerView>

</RelativeLayout>
3 changes: 2 additions & 1 deletion app/src/main/res/values/strings.xml
Original file line number Diff line number Diff line change
Expand Up @@ -740,4 +740,5 @@
<string name="you_successfully_subscribed">You now subscribed to this channel</string>
<string name="enumeration_comma">,</string>
<string name="toggle_all">Toggle all</string>
</resources>
<string name="show_replies">Show Replies</string>
</resources>