mirror of
https://github.com/TeamNewPipe/NewPipe
synced 2024-09-06 16:13:24 +00:00
Improve meta info layout and merge duplicate code
This commit is contained in:
parent
0a831ec84e
commit
19f9b4f502
|
@ -16,7 +16,6 @@ import android.os.Bundle;
|
|||
import android.os.Handler;
|
||||
import android.os.Looper;
|
||||
import android.provider.Settings;
|
||||
import android.text.method.LinkMovementMethod;
|
||||
import android.text.util.Linkify;
|
||||
import android.util.DisplayMetrics;
|
||||
import android.util.Log;
|
||||
|
@ -63,7 +62,6 @@ import org.schabi.newpipe.R;
|
|||
import org.schabi.newpipe.ReCaptchaActivity;
|
||||
import org.schabi.newpipe.download.DownloadDialog;
|
||||
import org.schabi.newpipe.extractor.InfoItem;
|
||||
import org.schabi.newpipe.extractor.MetaInfo;
|
||||
import org.schabi.newpipe.extractor.NewPipe;
|
||||
import org.schabi.newpipe.extractor.ServiceList;
|
||||
import org.schabi.newpipe.extractor.exceptions.ExtractionException;
|
||||
|
@ -126,11 +124,11 @@ 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.extractor.utils.Utils.isNullOrEmpty;
|
||||
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>
|
||||
|
@ -221,9 +219,8 @@ public final class VideoDetailFragment
|
|||
private TextView detailDurationView;
|
||||
private TextView detailPositionView;
|
||||
|
||||
private LinearLayout detailMetadataInfo;
|
||||
private View detailMetadataInfoSeparator;
|
||||
private TextView detailMetadataInfoText;
|
||||
private View detailMetaInfoSeparator;
|
||||
private TextView detailMetaInfoTextView;
|
||||
|
||||
private LinearLayout videoDescriptionRootLayout;
|
||||
private TextView videoUploadDateView;
|
||||
|
@ -651,9 +648,8 @@ public final class VideoDetailFragment
|
|||
detailDurationView = rootView.findViewById(R.id.detail_duration_view);
|
||||
detailPositionView = rootView.findViewById(R.id.detail_position_view);
|
||||
|
||||
detailMetadataInfo = rootView.findViewById(R.id.detail_metadata_info);
|
||||
detailMetadataInfoSeparator = rootView.findViewById(R.id.detail_metadata_info_separator);
|
||||
detailMetadataInfoText = rootView.findViewById(R.id.detail_metadata_info_text);
|
||||
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);
|
||||
|
@ -1258,42 +1254,6 @@ public final class VideoDetailFragment
|
|||
}
|
||||
}
|
||||
|
||||
private void setMetaInfo(final StreamInfo info) {
|
||||
final SharedPreferences sp = PreferenceManager.getDefaultSharedPreferences(
|
||||
requireContext());
|
||||
final boolean showMetaInfo = sp.getBoolean(
|
||||
requireContext().getString(R.string.show_meta_info_key), true);
|
||||
if (info.getMetaInfo().isEmpty() || !showMetaInfo) {
|
||||
detailMetadataInfo.setVisibility(View.GONE);
|
||||
detailMetadataInfoSeparator.setVisibility(View.GONE);
|
||||
} else {
|
||||
final List<MetaInfo> metaIfs = info.getMetaInfo();
|
||||
final StringBuilder stringBuilder = new StringBuilder();
|
||||
for (final MetaInfo mi: metaIfs) {
|
||||
if (!isNullOrEmpty(mi.getTitle())) {
|
||||
stringBuilder.append("<h2>").append(mi.getTitle()).append("</h2>");
|
||||
}
|
||||
stringBuilder.append(mi.getContent().getContent());
|
||||
for (int i = 0; i < mi.getUrls().size(); i++) {
|
||||
stringBuilder
|
||||
.append(" <a href=\"").append(mi.getUrls().get(i)).append("\">")
|
||||
.append(mi.getUrlTexts().get(i))
|
||||
.append("</a>");
|
||||
if (i < mi.getUrls().size() - 1 && mi.getUrls().size() > 1) {
|
||||
// append line break to all but the last URL if there are multiple URLs
|
||||
stringBuilder.append("<br>");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
detailMetadataInfoSeparator.setVisibility(View.VISIBLE);
|
||||
detailMetadataInfoText.setText(HtmlCompat.fromHtml(
|
||||
stringBuilder.toString(), HtmlCompat.FROM_HTML_SEPARATOR_LINE_BREAK_HEADING));
|
||||
detailMetadataInfoText.setMovementMethod(LinkMovementMethod.getInstance());
|
||||
detailMetadataInfo.setVisibility(View.VISIBLE);
|
||||
}
|
||||
}
|
||||
|
||||
private final ViewTreeObserver.OnPreDrawListener preDrawListener =
|
||||
new ViewTreeObserver.OnPreDrawListener() {
|
||||
@Override
|
||||
|
@ -1606,7 +1566,7 @@ public final class VideoDetailFragment
|
|||
prepareDescription(info.getDescription());
|
||||
updateProgressInfo(info);
|
||||
initThumbnailViews(info);
|
||||
setMetaInfo(info);
|
||||
showMetaInfoInTextView(info.getMetaInfo(), detailMetaInfoTextView, detailMetaInfoSeparator);
|
||||
|
||||
|
||||
if (player == null || player.isPlayerStopped()) {
|
||||
|
|
|
@ -9,7 +9,6 @@ import android.text.Editable;
|
|||
import android.text.Html;
|
||||
import android.text.TextUtils;
|
||||
import android.text.TextWatcher;
|
||||
import android.text.method.LinkMovementMethod;
|
||||
import android.util.Log;
|
||||
import android.view.KeyEvent;
|
||||
import android.view.LayoutInflater;
|
||||
|
@ -80,8 +79,8 @@ import io.reactivex.rxjava3.subjects.PublishSubject;
|
|||
|
||||
import static androidx.recyclerview.widget.ItemTouchHelper.Callback.makeMovementFlags;
|
||||
import static java.util.Arrays.asList;
|
||||
import static org.schabi.newpipe.extractor.utils.Utils.isNullOrEmpty;
|
||||
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 {
|
||||
|
@ -160,6 +159,7 @@ public class SearchFragment extends BaseListFragment<SearchInfo, ListExtractor.I
|
|||
|
||||
private TextView correctSuggestion;
|
||||
private TextView metaInfoTextView;
|
||||
private View metaInfoSeparator;
|
||||
|
||||
private View suggestionsPanel;
|
||||
private boolean suggestionsPanelVisible = false;
|
||||
|
@ -276,7 +276,8 @@ public class SearchFragment extends BaseListFragment<SearchInfo, ListExtractor.I
|
|||
|
||||
handleSearchSuggestion();
|
||||
|
||||
handleMetaInfo();
|
||||
showMetaInfoInTextView(metaInfo == null ? null : Arrays.asList(metaInfo),
|
||||
metaInfoTextView, metaInfoSeparator);
|
||||
|
||||
if (suggestionDisposable == null || suggestionDisposable.isDisposed()) {
|
||||
initSuggestionObserver();
|
||||
|
@ -362,7 +363,8 @@ public class SearchFragment extends BaseListFragment<SearchInfo, ListExtractor.I
|
|||
searchClear = searchToolbarContainer.findViewById(R.id.toolbar_search_clear);
|
||||
|
||||
correctSuggestion = rootView.findViewById(R.id.correct_suggestion);
|
||||
metaInfoTextView = rootView.findViewById(R.id.search_meta_info);
|
||||
metaInfoTextView = rootView.findViewById(R.id.search_meta_info_text_view);
|
||||
metaInfoSeparator = rootView.findViewById(R.id.search_meta_info_separator);
|
||||
}
|
||||
|
||||
/*//////////////////////////////////////////////////////////////////////////
|
||||
|
@ -988,7 +990,8 @@ public class SearchFragment extends BaseListFragment<SearchInfo, ListExtractor.I
|
|||
metaInfo = result.getMetaInfo().toArray(metaInfo);
|
||||
|
||||
handleSearchSuggestion();
|
||||
handleMetaInfo();
|
||||
|
||||
showMetaInfoInTextView(result.getMetaInfo(), metaInfoTextView, metaInfoSeparator);
|
||||
|
||||
lastSearchedString = searchString;
|
||||
nextPage = result.getNextPage();
|
||||
|
@ -1036,39 +1039,6 @@ public class SearchFragment extends BaseListFragment<SearchInfo, ListExtractor.I
|
|||
}
|
||||
}
|
||||
|
||||
private void handleMetaInfo() {
|
||||
final SharedPreferences sp = PreferenceManager.getDefaultSharedPreferences(
|
||||
requireContext());
|
||||
final boolean showMetaInfo = sp.getBoolean(
|
||||
requireContext().getString(R.string.show_meta_info_key), true);
|
||||
if (metaInfo == null || metaInfo.length == 0 || !showMetaInfo) {
|
||||
metaInfoTextView.setVisibility(View.GONE);
|
||||
} else {
|
||||
final StringBuilder stringBuilder = new StringBuilder();
|
||||
for (final MetaInfo mi: metaInfo) {
|
||||
if (!isNullOrEmpty(mi.getTitle())) {
|
||||
stringBuilder.append("<h2>").append(mi.getTitle()).append("</h2>");
|
||||
}
|
||||
stringBuilder.append(mi.getContent().getContent());
|
||||
for (int i = 0; i < mi.getUrls().size(); i++) {
|
||||
stringBuilder
|
||||
.append(" <a href=\"").append(mi.getUrls().get(i)).append("\">")
|
||||
.append(mi.getUrlTexts().get(i))
|
||||
.append("</a>");
|
||||
if (i < mi.getUrls().size() - 1 && mi.getUrls().size() > 1) {
|
||||
// append line break to all but the last URL if there are multiple URLs
|
||||
stringBuilder.append("<br>");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
metaInfoTextView.setText(HtmlCompat.fromHtml(
|
||||
stringBuilder.toString(), HtmlCompat.FROM_HTML_SEPARATOR_LINE_BREAK_HEADING));
|
||||
metaInfoTextView.setMovementMethod(LinkMovementMethod.getInstance());
|
||||
metaInfoTextView.setVisibility(View.VISIBLE);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void handleNextItems(final ListExtractor.InfoItemsPage<?> result) {
|
||||
showListFooter(false);
|
||||
|
|
|
@ -22,9 +22,16 @@ package org.schabi.newpipe.util;
|
|||
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;
|
||||
|
@ -32,6 +39,7 @@ 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;
|
||||
|
@ -60,6 +68,8 @@ import java.util.List;
|
|||
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();
|
||||
|
@ -306,4 +316,73 @@ public final class ExtractorHelper {
|
|||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 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();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -57,7 +57,7 @@ import java.util.Locale;
|
|||
|
||||
public final class Localization {
|
||||
|
||||
private static final String DOT_SEPARATOR = " • ";
|
||||
public static final String DOT_SEPARATOR = " • ";
|
||||
private static PrettyTime prettyTime;
|
||||
|
||||
private Localization() { }
|
||||
|
|
|
@ -507,36 +507,21 @@
|
|||
</LinearLayout>
|
||||
|
||||
<View
|
||||
android:id="@+id/detail_metadata_info_separator"
|
||||
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:layout_marginBottom="8dp"
|
||||
android:background="?attr/separator_color" />
|
||||
|
||||
<LinearLayout
|
||||
android:id="@+id/detail_metadata_info"
|
||||
<TextView
|
||||
android:id="@+id/detail_meta_info_text_view"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginLeft="12dp"
|
||||
android:layout_marginRight="12dp"
|
||||
android:layout_marginBottom="8dp"
|
||||
android:orientation="horizontal">
|
||||
|
||||
<ImageView
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="center_vertical"
|
||||
app:srcCompat="?attr/ic_info_outline" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/detail_metadata_info_text"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="8dp"
|
||||
tools:text="Stream meta info with link"/>
|
||||
</LinearLayout>
|
||||
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"
|
||||
|
|
|
@ -16,20 +16,29 @@
|
|||
tools:text="Showing results for lorem ipsum dolor sit amet consectetur adipisci elit" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/search_meta_info"
|
||||
android:id="@+id/search_meta_info_text_view"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_below="@id/correct_suggestion"
|
||||
android:gravity="center"
|
||||
android:padding="12dp"
|
||||
android:textSize="@dimen/search_suggestion_text_size"
|
||||
android:textSize="@dimen/video_item_detail_description_text_size"
|
||||
tools:text="Get the latest information from the WHO about coronavirus." />
|
||||
|
||||
<View
|
||||
android:id="@+id/search_meta_info_separator"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="1px"
|
||||
android:layout_below="@id/search_meta_info_text_view"
|
||||
android:layout_marginLeft="8dp"
|
||||
android:layout_marginRight="8dp"
|
||||
android:background="?attr/separator_color" />
|
||||
|
||||
<androidx.recyclerview.widget.RecyclerView
|
||||
android:id="@+id/items_list"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_below="@+id/search_meta_info"
|
||||
android:layout_below="@+id/search_meta_info_separator"
|
||||
android:scrollbars="vertical"
|
||||
app:layoutManager="LinearLayoutManager"
|
||||
tools:listitem="@layout/list_stream_item" />
|
||||
|
|
|
@ -492,37 +492,21 @@
|
|||
</LinearLayout>
|
||||
|
||||
<View
|
||||
android:id="@+id/detail_metadata_info_separator"
|
||||
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:layout_marginBottom="8dp"
|
||||
android:background="?attr/separator_color" />
|
||||
|
||||
<LinearLayout
|
||||
android:id="@+id/detail_metadata_info"
|
||||
<TextView
|
||||
android:id="@+id/detail_meta_info_text_view"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginLeft="12dp"
|
||||
android:layout_marginRight="12dp"
|
||||
android:layout_marginBottom="8dp"
|
||||
android:orientation="horizontal">
|
||||
|
||||
<ImageView
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="center_vertical"
|
||||
app:srcCompat="?attr/ic_info_outline" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/detail_metadata_info_text"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="8dp"
|
||||
tools:text="Stream meta info with link"/>
|
||||
|
||||
</LinearLayout>
|
||||
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"
|
||||
|
|
Loading…
Reference in a new issue