Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Display meta info about search query, stream creator or topic #4754

Merged
merged 2 commits into from
Dec 23, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
2 changes: 1 addition & 1 deletion app/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -179,7 +179,7 @@ dependencies {

// NewPipe dependencies
// You can use a local version by uncommenting a few lines in settings.gradle
implementation 'com.github.TeamNewPipe:NewPipeExtractor:85fa006214b003f21eacb76c445a167732f19981'
implementation 'com.github.TeamNewPipe:NewPipeExtractor:79b5aa9760da52020821b68e2af41a9238943304'
implementation "com.github.TeamNewPipe:nanojson:1d9e1aea9049fc9f85e68b43ba39fe7be1c1f751"

implementation "org.jsoup:jsoup:1.13.1"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@
import android.content.Context;
import android.content.res.ColorStateList;
import android.os.Bundle;
import androidx.preference.PreferenceManager;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.Menu;
Expand All @@ -19,6 +18,7 @@
import androidx.fragment.app.Fragment;
import androidx.fragment.app.FragmentManager;
import androidx.fragment.app.FragmentStatePagerAdapterMenuWorkaround;
import androidx.preference.PreferenceManager;
import androidx.viewpager.widget.ViewPager;

import com.google.android.material.tabs.TabLayout;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,6 @@
import android.os.Handler;
import android.os.Looper;
import android.provider.Settings;
import android.text.TextUtils;
import android.text.util.Linkify;
import android.util.DisplayMetrics;
import android.util.Log;
Expand Down Expand Up @@ -122,12 +121,14 @@
import io.reactivex.rxjava3.disposables.Disposable;
import io.reactivex.rxjava3.schedulers.Schedulers;

import static android.text.TextUtils.isEmpty;
import static org.schabi.newpipe.extractor.StreamingService.ServiceInfo.MediaCapability.COMMENTS;
import static org.schabi.newpipe.extractor.stream.StreamExtractor.NO_AGE_LIMIT;
import static org.schabi.newpipe.player.helper.PlayerHelper.globalScreenOrientationLocked;
import static org.schabi.newpipe.player.helper.PlayerHelper.isClearingQueueConfirmationRequired;
import static org.schabi.newpipe.player.playqueue.PlayQueueItem.RECOVERY_UNSET;
import static org.schabi.newpipe.util.AnimationUtils.animateView;
import static org.schabi.newpipe.util.ExtractorHelper.showMetaInfoInTextView;

public final class VideoDetailFragment
extends BaseStateFragment<StreamInfo>
Expand Down Expand Up @@ -218,6 +219,9 @@ public final class VideoDetailFragment
private TextView detailDurationView;
private TextView detailPositionView;

private View detailMetaInfoSeparator;
private TextView detailMetaInfoTextView;

private LinearLayout videoDescriptionRootLayout;
private TextView videoUploadDateView;
private TextView videoDescriptionView;
Expand Down Expand Up @@ -508,8 +512,8 @@ public void onClick(final View v) {
}
break;
case R.id.detail_uploader_root_layout:
if (TextUtils.isEmpty(currentInfo.getSubChannelUrl())) {
if (!TextUtils.isEmpty(currentInfo.getUploaderUrl())) {
if (isEmpty(currentInfo.getSubChannelUrl())) {
if (!isEmpty(currentInfo.getUploaderUrl())) {
openChannel(currentInfo.getUploaderUrl(), currentInfo.getUploaderName());
}

Expand Down Expand Up @@ -583,7 +587,7 @@ public boolean onLongClick(final View v) {
}
break;
case R.id.detail_uploader_root_layout:
if (TextUtils.isEmpty(currentInfo.getSubChannelUrl())) {
if (isEmpty(currentInfo.getSubChannelUrl())) {
Log.w(TAG,
"Can't open parent channel because we got no parent channel URL");
} else {
Expand Down Expand Up @@ -644,6 +648,9 @@ protected void initViews(final View rootView, final Bundle savedInstanceState) {
detailDurationView = rootView.findViewById(R.id.detail_duration_view);
detailPositionView = rootView.findViewById(R.id.detail_position_view);

detailMetaInfoSeparator = rootView.findViewById(R.id.detail_meta_info_separator);
detailMetaInfoTextView = rootView.findViewById(R.id.detail_meta_info_text_view);

videoDescriptionRootLayout = rootView.findViewById(R.id.detail_description_root_layout);
videoUploadDateView = rootView.findViewById(R.id.detail_upload_date_view);
videoDescriptionView = rootView.findViewById(R.id.detail_description_view);
Expand Down Expand Up @@ -748,7 +755,7 @@ private View.OnTouchListener getOnControlsTouchListener() {
private void initThumbnailViews(@NonNull final StreamInfo info) {
thumbnailImageView.setImageResource(R.drawable.dummy_thumbnail_dark);

if (!TextUtils.isEmpty(info.getThumbnailUrl())) {
if (!isEmpty(info.getThumbnailUrl())) {
final String infoServiceName = NewPipe.getNameOfService(info.getServiceId());
final ImageLoadingListener onFailListener = new SimpleImageLoadingListener() {
@Override
Expand All @@ -763,12 +770,12 @@ public void onLoadingFailed(final String imageUri, final View view,
ImageDisplayConstants.DISPLAY_THUMBNAIL_OPTIONS, onFailListener);
}

if (!TextUtils.isEmpty(info.getSubChannelAvatarUrl())) {
if (!isEmpty(info.getSubChannelAvatarUrl())) {
IMAGE_LOADER.displayImage(info.getSubChannelAvatarUrl(), subChannelThumb,
ImageDisplayConstants.DISPLAY_AVATAR_OPTIONS);
}

if (!TextUtils.isEmpty(info.getUploaderAvatarUrl())) {
if (!isEmpty(info.getUploaderAvatarUrl())) {
IMAGE_LOADER.displayImage(info.getUploaderAvatarUrl(), uploaderThumb,
ImageDisplayConstants.DISPLAY_AVATAR_OPTIONS);
}
Expand Down Expand Up @@ -1217,7 +1224,7 @@ private void makeDefaultHeightForVideoPlaceholder() {
}

private void prepareDescription(final Description description) {
if (description == null || TextUtils.isEmpty(description.getContent())
if (description == null || isEmpty(description.getContent())
|| description == Description.emptyDescription) {
return;
}
Expand Down Expand Up @@ -1462,9 +1469,9 @@ public void handleResult(@NonNull final StreamInfo info) {
animateView(thumbnailPlayButton, true, 200);
videoTitleTextView.setText(title);

if (!TextUtils.isEmpty(info.getSubChannelName())) {
if (!isEmpty(info.getSubChannelName())) {
displayBothUploaderAndSubChannel(info);
} else if (!TextUtils.isEmpty(info.getUploaderName())) {
} else if (!isEmpty(info.getUploaderName())) {
displayUploaderAsSubChannel(info);
} else {
uploaderTextView.setVisibility(View.GONE);
Expand Down Expand Up @@ -1559,6 +1566,8 @@ public void handleResult(@NonNull final StreamInfo info) {
prepareDescription(info.getDescription());
updateProgressInfo(info);
initThumbnailViews(info);
showMetaInfoInTextView(info.getMetaInfo(), detailMetaInfoTextView, detailMetaInfoSeparator);


if (player == null || player.isPlayerStopped()) {
updateOverlayData(info.getName(), info.getUploaderName(), info.getThumbnailUrl());
Expand Down Expand Up @@ -1610,7 +1619,7 @@ private void displayBothUploaderAndSubChannel(final StreamInfo info) {

subChannelThumb.setVisibility(View.VISIBLE);

if (!TextUtils.isEmpty(info.getUploaderName())) {
if (!isEmpty(info.getUploaderName())) {
uploaderTextView.setText(
String.format(getString(R.string.video_detail_by), info.getUploaderName()));
uploaderTextView.setVisibility(View.VISIBLE);
Expand Down Expand Up @@ -2305,10 +2314,10 @@ public void onSlide(@NonNull final View bottomSheet, final float slideOffset) {
private void updateOverlayData(@Nullable final String overlayTitle,
@Nullable final String uploader,
@Nullable final String thumbnailUrl) {
overlayTitleTextView.setText(TextUtils.isEmpty(overlayTitle) ? "" : overlayTitle);
overlayChannelTextView.setText(TextUtils.isEmpty(uploader) ? "" : uploader);
overlayTitleTextView.setText(isEmpty(title) ? "" : title);
overlayChannelTextView.setText(isEmpty(uploader) ? "" : uploader);
overlayThumbnailImageView.setImageResource(R.drawable.dummy_thumbnail_dark);
if (!TextUtils.isEmpty(thumbnailUrl)) {
if (!isEmpty(thumbnailUrl)) {
IMAGE_LOADER.displayImage(thumbnailUrl, overlayThumbnailImageView,
ImageDisplayConstants.DISPLAY_THUMBNAIL_OPTIONS, null);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@
import org.schabi.newpipe.database.history.model.SearchHistoryEntry;
import org.schabi.newpipe.extractor.InfoItem;
import org.schabi.newpipe.extractor.ListExtractor;
import org.schabi.newpipe.extractor.MetaInfo;
import org.schabi.newpipe.extractor.NewPipe;
import org.schabi.newpipe.extractor.Page;
import org.schabi.newpipe.extractor.StreamingService;
Expand Down Expand Up @@ -79,6 +80,7 @@
import static androidx.recyclerview.widget.ItemTouchHelper.Callback.makeMovementFlags;
import static java.util.Arrays.asList;
import static org.schabi.newpipe.util.AnimationUtils.animateView;
import static org.schabi.newpipe.util.ExtractorHelper.showMetaInfoInTextView;

public class SearchFragment extends BaseListFragment<SearchInfo, ListExtractor.InfoItemsPage<?>>
implements BackPressable {
Expand Down Expand Up @@ -129,6 +131,9 @@ public class SearchFragment extends BaseListFragment<SearchInfo, ListExtractor.I
@State
boolean isCorrectedSearch;

@State
MetaInfo[] metaInfo;

@State
boolean wasSearchFocused = false;

Expand All @@ -153,6 +158,8 @@ public class SearchFragment extends BaseListFragment<SearchInfo, ListExtractor.I
private View searchClear;

private TextView correctSuggestion;
private TextView metaInfoTextView;
private View metaInfoSeparator;

private View suggestionsPanel;
private boolean suggestionsPanelVisible = false;
Expand Down Expand Up @@ -269,6 +276,9 @@ public void onResume() {

handleSearchSuggestion();

showMetaInfoInTextView(metaInfo == null ? null : Arrays.asList(metaInfo),
metaInfoTextView, metaInfoSeparator);

if (suggestionDisposable == null || suggestionDisposable.isDisposed()) {
initSuggestionObserver();
}
Expand Down Expand Up @@ -353,6 +363,8 @@ public void onSwiped(@NonNull final RecyclerView.ViewHolder viewHolder, final in
searchClear = searchToolbarContainer.findViewById(R.id.toolbar_search_clear);

correctSuggestion = rootView.findViewById(R.id.correct_suggestion);
metaInfoTextView = rootView.findViewById(R.id.search_meta_info_text_view);
metaInfoSeparator = rootView.findViewById(R.id.search_meta_info_separator);
}

/*//////////////////////////////////////////////////////////////////////////
Expand Down Expand Up @@ -973,8 +985,14 @@ public void handleResult(@NonNull final SearchInfo result) {
searchSuggestion = result.getSearchSuggestion();
isCorrectedSearch = result.isCorrectedSearch();

// List<MetaInfo> cannot be bundled without creating some containers
metaInfo = new MetaInfo[result.getMetaInfo().size()];
metaInfo = result.getMetaInfo().toArray(metaInfo);

handleSearchSuggestion();

showMetaInfoInTextView(result.getMetaInfo(), metaInfoTextView, metaInfoSeparator);

lastSearchedString = searchString;
nextPage = result.getNextPage();

Expand Down
79 changes: 79 additions & 0 deletions app/src/main/java/org/schabi/newpipe/util/ExtractorHelper.java
Original file line number Diff line number Diff line change
Expand Up @@ -22,16 +22,24 @@
import android.content.Context;
import android.content.Intent;
import android.os.Handler;
import android.text.method.LinkMovementMethod;
import android.util.Log;
import android.view.View;
import android.widget.TextView;
import android.widget.Toast;

import androidx.annotation.Nullable;
import androidx.core.text.HtmlCompat;
import androidx.preference.PreferenceManager;

import org.schabi.newpipe.MainActivity;
import org.schabi.newpipe.R;
import org.schabi.newpipe.ReCaptchaActivity;
import org.schabi.newpipe.extractor.Info;
import org.schabi.newpipe.extractor.InfoItem;
import org.schabi.newpipe.extractor.ListExtractor.InfoItemsPage;
import org.schabi.newpipe.extractor.ListInfo;
import org.schabi.newpipe.extractor.MetaInfo;
import org.schabi.newpipe.extractor.NewPipe;
import org.schabi.newpipe.extractor.Page;
import org.schabi.newpipe.extractor.StreamingService;
Expand Down Expand Up @@ -60,6 +68,8 @@
import io.reactivex.rxjava3.core.Maybe;
import io.reactivex.rxjava3.core.Single;

import static org.schabi.newpipe.extractor.utils.Utils.isNullOrEmpty;

public final class ExtractorHelper {
private static final String TAG = ExtractorHelper.class.getSimpleName();
private static final InfoCache CACHE = InfoCache.getInstance();
Expand Down Expand Up @@ -306,4 +316,73 @@ public static void handleGeneralException(final Context context, final int servi
}
});
}

/**
* Formats the text contained in the meta info list as HTML and puts it into the text view,
* while also making the separator visible. If the list is null or empty, or the user chose not
* to see meta information, both the text view and the separator are hidden
* @param metaInfos a list of meta information, can be null or empty
* @param metaInfoTextView the text view in which to show the formatted HTML
* @param metaInfoSeparator another view to be shown or hidden accordingly to the text view
*/
public static void showMetaInfoInTextView(@Nullable final List<MetaInfo> metaInfos,
final TextView metaInfoTextView,
final View metaInfoSeparator) {
final Context context = metaInfoTextView.getContext();
final boolean showMetaInfo = PreferenceManager.getDefaultSharedPreferences(context)
.getBoolean(context.getString(R.string.show_meta_info_key), true);

if (!showMetaInfo || metaInfos == null || metaInfos.isEmpty()) {
metaInfoTextView.setVisibility(View.GONE);
metaInfoSeparator.setVisibility(View.GONE);

} else {
final StringBuilder stringBuilder = new StringBuilder();
for (final MetaInfo metaInfo : metaInfos) {
if (!isNullOrEmpty(metaInfo.getTitle())) {
stringBuilder.append("<b>").append(metaInfo.getTitle()).append("</b>")
.append(Localization.DOT_SEPARATOR);
}

String content = metaInfo.getContent().getContent().trim();
if (content.endsWith(".")) {
content = content.substring(0, content.length() - 1); // remove . at end
}
stringBuilder.append(content);

for (int i = 0; i < metaInfo.getUrls().size(); i++) {
if (i == 0) {
stringBuilder.append(Localization.DOT_SEPARATOR);
} else {
stringBuilder.append("<br/><br/>");
}

stringBuilder
.append("<a href=\"").append(metaInfo.getUrls().get(i)).append("\">")
.append(capitalizeIfAllUppercase(metaInfo.getUrlTexts().get(i).trim()))
.append("</a>");
}
}

metaInfoTextView.setText(HtmlCompat.fromHtml(stringBuilder.toString(),
HtmlCompat.FROM_HTML_SEPARATOR_LINE_BREAK_HEADING));
metaInfoTextView.setMovementMethod(LinkMovementMethod.getInstance());
metaInfoTextView.setVisibility(View.VISIBLE);
metaInfoSeparator.setVisibility(View.VISIBLE);
}
}

private static String capitalizeIfAllUppercase(final String text) {
for (int i = 0; i < text.length(); i++) {
if (Character.isLowerCase(text.charAt(i))) {
return text; // there is at least a lowercase letter -> not all uppercase
}
}

if (text.isEmpty()) {
return text;
} else {
return text.substring(0, 1).toUpperCase() + text.substring(1).toLowerCase();
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@

public final class Localization {

private static final String DOT_SEPARATOR = " • ";
public static final String DOT_SEPARATOR = " • ";
private static PrettyTime prettyTime;

private Localization() { }
Expand Down
17 changes: 17 additions & 0 deletions app/src/main/res/layout-large-land/fragment_video_detail.xml
Original file line number Diff line number Diff line change
Expand Up @@ -506,6 +506,23 @@

</LinearLayout>

<View
android:id="@+id/detail_meta_info_separator"
android:layout_width="match_parent"
android:layout_height="1px"
android:layout_marginLeft="8dp"
android:layout_marginRight="8dp"
android:background="?attr/separator_color" />

<TextView
android:id="@+id/detail_meta_info_text_view"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center"
android:padding="12dp"
android:textSize="@dimen/video_item_detail_description_text_size"
tools:text="Stream meta info with link" />

<View
android:layout_width="match_parent"
android:layout_height="1px"
Expand Down
Loading