mirror of
				https://github.com/TeamNewPipe/NewPipe
				synced 2025-10-31 07:13:00 +00:00 
			
		
		
		
	Merge pull request #4754 from TeamNewPipe/meta_info
Display meta info about search query, stream creator or topic
This commit is contained in:
		| @@ -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" | ||||
|   | ||||
| @@ -3,7 +3,6 @@ package org.schabi.newpipe.fragments; | ||||
| 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; | ||||
| @@ -19,6 +18,7 @@ import androidx.appcompat.app.AppCompatActivity; | ||||
| 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; | ||||
|   | ||||
| @@ -16,7 +16,6 @@ import android.os.Bundle; | ||||
| 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; | ||||
| @@ -122,12 +121,14 @@ import io.reactivex.rxjava3.disposables.CompositeDisposable; | ||||
| 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> | ||||
| @@ -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; | ||||
| @@ -508,8 +512,8 @@ public final class VideoDetailFragment | ||||
|                 } | ||||
|                 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()); | ||||
|                     } | ||||
|  | ||||
| @@ -583,7 +587,7 @@ public final class VideoDetailFragment | ||||
|                 } | ||||
|                 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 { | ||||
| @@ -644,6 +648,9 @@ public final class VideoDetailFragment | ||||
|         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); | ||||
| @@ -748,7 +755,7 @@ public final class VideoDetailFragment | ||||
|     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 | ||||
| @@ -763,12 +770,12 @@ public final class VideoDetailFragment | ||||
|                     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); | ||||
|         } | ||||
| @@ -1217,7 +1224,7 @@ public final class VideoDetailFragment | ||||
|     } | ||||
|  | ||||
|     private void prepareDescription(final Description description) { | ||||
|         if (description == null || TextUtils.isEmpty(description.getContent()) | ||||
|         if (description == null || isEmpty(description.getContent()) | ||||
|                 || description == Description.emptyDescription) { | ||||
|             return; | ||||
|         } | ||||
| @@ -1462,9 +1469,9 @@ public final class VideoDetailFragment | ||||
|         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); | ||||
| @@ -1559,6 +1566,8 @@ public final class VideoDetailFragment | ||||
|         prepareDescription(info.getDescription()); | ||||
|         updateProgressInfo(info); | ||||
|         initThumbnailViews(info); | ||||
|         showMetaInfoInTextView(info.getMetaInfo(), detailMetaInfoTextView, detailMetaInfoSeparator); | ||||
|  | ||||
|  | ||||
|         if (player == null || player.isPlayerStopped()) { | ||||
|             updateOverlayData(info.getName(), info.getUploaderName(), info.getThumbnailUrl()); | ||||
| @@ -1610,7 +1619,7 @@ public final class VideoDetailFragment | ||||
|  | ||||
|         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); | ||||
| @@ -2305,10 +2314,10 @@ public final class VideoDetailFragment | ||||
|     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); | ||||
|         } | ||||
|   | ||||
| @@ -39,6 +39,7 @@ import org.schabi.newpipe.ReCaptchaActivity; | ||||
| 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; | ||||
| @@ -79,6 +80,7 @@ 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.util.AnimationUtils.animateView; | ||||
| import static org.schabi.newpipe.util.ExtractorHelper.showMetaInfoInTextView; | ||||
|  | ||||
| public class SearchFragment extends BaseListFragment<SearchInfo, ListExtractor.InfoItemsPage<?>> | ||||
|         implements BackPressable { | ||||
| @@ -129,6 +131,9 @@ public class SearchFragment extends BaseListFragment<SearchInfo, ListExtractor.I | ||||
|     @State | ||||
|     boolean isCorrectedSearch; | ||||
|  | ||||
|     @State | ||||
|     MetaInfo[] metaInfo; | ||||
|  | ||||
|     @State | ||||
|     boolean wasSearchFocused = false; | ||||
|  | ||||
| @@ -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; | ||||
| @@ -269,6 +276,9 @@ public class SearchFragment extends BaseListFragment<SearchInfo, ListExtractor.I | ||||
|  | ||||
|         handleSearchSuggestion(); | ||||
|  | ||||
|         showMetaInfoInTextView(metaInfo == null ? null : Arrays.asList(metaInfo), | ||||
|                     metaInfoTextView, metaInfoSeparator); | ||||
|  | ||||
|         if (suggestionDisposable == null || suggestionDisposable.isDisposed()) { | ||||
|             initSuggestionObserver(); | ||||
|         } | ||||
| @@ -353,6 +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_text_view); | ||||
|         metaInfoSeparator = rootView.findViewById(R.id.search_meta_info_separator); | ||||
|     } | ||||
|  | ||||
|     /*////////////////////////////////////////////////////////////////////////// | ||||
| @@ -973,8 +985,14 @@ public class SearchFragment extends BaseListFragment<SearchInfo, ListExtractor.I | ||||
|         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(); | ||||
|  | ||||
|   | ||||
| @@ -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() { } | ||||
|   | ||||
| @@ -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" | ||||
|   | ||||
| @@ -11,15 +11,34 @@ | ||||
|         android:layout_height="wrap_content" | ||||
|         android:layout_alignTop="@id/error_panel" | ||||
|         android:background="?attr/selectableItemBackground" | ||||
|         android:padding="10dp" | ||||
|         android:padding="12dp" | ||||
|         android:textSize="@dimen/search_suggestion_text_size" | ||||
|         tools:text="Showing results for lorem ipsum dolor sit amet consectetur adipisci elit" /> | ||||
|  | ||||
|     <TextView | ||||
|         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/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/correct_suggestion" | ||||
|         android:layout_below="@+id/search_meta_info_separator" | ||||
|         android:scrollbars="vertical" | ||||
|         app:layoutManager="LinearLayoutManager" | ||||
|         tools:listitem="@layout/list_stream_item" /> | ||||
|   | ||||
| @@ -491,6 +491,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" | ||||
|   | ||||
| @@ -197,6 +197,7 @@ | ||||
|     <string name="show_play_with_kodi_key" translatable="false">show_play_with_kodi</string> | ||||
|     <string name="show_next_video_key" translatable="false">show_next_video</string> | ||||
|     <string name="show_comments_key" translatable="false">show_comments</string> | ||||
|     <string name="show_meta_info_key" translatable="false">show_meta_info</string> | ||||
|     <string name="stream_info_selected_tab_key" translatable="false">stream_info_selected_tab</string> | ||||
|     <string name="show_hold_to_append_key" translatable="false">show_hold_to_append</string> | ||||
|     <string name="content_language_key" translatable="false">content_language</string> | ||||
|   | ||||
| @@ -93,6 +93,8 @@ | ||||
|     <string name="show_comments_title">Show comments</string> | ||||
|     <string name="show_comments_summary">Turn off to hide comments</string> | ||||
|     <string name="download_thumbnail_summary">Turn off to prevent loading thumbnails, saving data and memory usage. Changes clear both in-memory and on-disk image cache.</string> | ||||
|     <string name="show_meta_info_title">Show meta info</string> | ||||
|     <string name="show_meta_info_summary">Turn off to hide meta info boxes with additional information about the stream creator, stream content or a search request.</string> | ||||
|     <string name="thumbnail_cache_wipe_complete_notice">Image cache wiped</string> | ||||
|     <string name="metadata_cache_wipe_title">Wipe cached metadata</string> | ||||
|     <string name="metadata_cache_wipe_summary">Remove all cached webpage data</string> | ||||
|   | ||||
| @@ -85,6 +85,13 @@ | ||||
|         android:title="@string/show_comments_title" | ||||
|         app:iconSpaceReserved="false" /> | ||||
|  | ||||
|     <SwitchPreferenceCompat | ||||
|         android:defaultValue="true" | ||||
|         android:key="@string/show_meta_info_key" | ||||
|         android:summary="@string/show_meta_info_summary" | ||||
|         android:title="@string/show_meta_info_title" | ||||
|         app:iconSpaceReserved="false" /> | ||||
|  | ||||
|     <Preference | ||||
|         android:key="@string/import_data" | ||||
|         android:summary="@string/import_data_summary" | ||||
|   | ||||
		Reference in New Issue
	
	Block a user
	 Tobias Groza
					Tobias Groza