From 997267bad1867a12d23d99d54c5ac214995d324f Mon Sep 17 00:00:00 2001 From: Stypox Date: Sun, 28 Mar 2021 23:17:20 +0200 Subject: [PATCH 1/6] Show video metadata below the decription --- .../fragments/detail/DescriptionFragment.java | 103 +++++++++++++++++- .../main/res/layout/fragment_description.xml | 22 +++- app/src/main/res/layout/item_metadata.xml | 44 ++++++++ app/src/main/res/values/strings.xml | 15 ++- 4 files changed, 177 insertions(+), 7 deletions(-) create mode 100644 app/src/main/res/layout/item_metadata.xml diff --git a/app/src/main/java/org/schabi/newpipe/fragments/detail/DescriptionFragment.java b/app/src/main/java/org/schabi/newpipe/fragments/detail/DescriptionFragment.java index b4424928f..b44841fdb 100644 --- a/app/src/main/java/org/schabi/newpipe/fragments/detail/DescriptionFragment.java +++ b/app/src/main/java/org/schabi/newpipe/fragments/detail/DescriptionFragment.java @@ -4,14 +4,18 @@ import android.os.Bundle; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; +import android.widget.LinearLayout; import android.widget.TextView; import androidx.annotation.NonNull; import androidx.annotation.Nullable; +import androidx.annotation.StringRes; import androidx.core.text.HtmlCompat; import org.schabi.newpipe.BaseFragment; +import org.schabi.newpipe.R; import org.schabi.newpipe.databinding.FragmentDescriptionBinding; +import org.schabi.newpipe.databinding.ItemMetadataBinding; import org.schabi.newpipe.extractor.stream.Description; import org.schabi.newpipe.extractor.stream.StreamInfo; import org.schabi.newpipe.util.Localization; @@ -21,6 +25,8 @@ import icepick.State; import io.reactivex.rxjava3.disposables.Disposable; import static android.text.TextUtils.isEmpty; +import static org.schabi.newpipe.extractor.stream.StreamExtractor.NO_AGE_LIMIT; +import static org.schabi.newpipe.extractor.utils.Utils.isBlank; public class DescriptionFragment extends BaseFragment { @@ -45,6 +51,7 @@ public class DescriptionFragment extends BaseFragment { if (streamInfo != null) { setupUploadDate(binding.detailUploadDateView); setupDescription(binding.detailDescriptionView); + setupMetadata(inflater, binding.detailMetadataLayout); } return binding.getRoot(); } @@ -70,7 +77,7 @@ public class DescriptionFragment extends BaseFragment { final Description description = streamInfo.getDescription(); if (description == null || isEmpty(description.getContent()) || description == Description.emptyDescription) { - descriptionTextView.setText(""); + descriptionTextView.setVisibility(View.GONE); return; } @@ -90,4 +97,98 @@ public class DescriptionFragment extends BaseFragment { break; } } + + private void setupMetadata(final LayoutInflater inflater, + final LinearLayout layout) { + addMetadataItem(inflater, layout, false, + R.string.metadata_category, streamInfo.getCategory()); + + addTagsMetadataItem(inflater, layout); + + addMetadataItem(inflater, layout, false, + R.string.metadata_licence, streamInfo.getLicence()); + + addPrivacyMetadataItem(inflater, layout); + + if (streamInfo.getAgeLimit() != NO_AGE_LIMIT) { + addMetadataItem(inflater, layout, false, + R.string.metadata_age_limit, String.valueOf(streamInfo.getAgeLimit())); + } + + if (streamInfo.getLanguageInfo() != null) { + addMetadataItem(inflater, layout, false, + R.string.metadata_language, streamInfo.getLanguageInfo().getDisplayLanguage()); + } + + addMetadataItem(inflater, layout, true, + R.string.metadata_support, streamInfo.getSupportInfo()); + addMetadataItem(inflater, layout, true, + R.string.metadata_host, streamInfo.getHost()); + addMetadataItem(inflater, layout, true, + R.string.metadata_thumbnail_url, streamInfo.getThumbnailUrl()); + } + + private void addMetadataItem(final LayoutInflater inflater, + final LinearLayout layout, + final boolean linkifyContent, + @StringRes final int type, + @Nullable final String content) { + if (isBlank(content)) { + return; + } + + final ItemMetadataBinding binding = ItemMetadataBinding.inflate(inflater, layout, false); + binding.metadataTypeView.setText(type); + + if (linkifyContent) { + TextLinkifier.createLinksFromPlainText(layout.getContext(), content, + binding.metadataContentView); + } else { + binding.metadataContentView.setText(content); + } + + layout.addView(binding.getRoot()); + } + + private void addTagsMetadataItem(final LayoutInflater inflater, final LinearLayout layout) { + if (streamInfo.getTags() != null && !streamInfo.getTags().isEmpty()) { + final StringBuilder tags = new StringBuilder(); + for (int i = 0; i < streamInfo.getTags().size(); ++i) { + if (i != 0) { + tags.append(", "); + } + tags.append(streamInfo.getTags().get(i)); + } + + addMetadataItem(inflater, layout, false, R.string.metadata_tags, tags.toString()); + } + } + + private void addPrivacyMetadataItem(final LayoutInflater inflater, final LinearLayout layout) { + if (streamInfo.getPrivacy() != null) { + @StringRes final int contentRes; + switch (streamInfo.getPrivacy()) { + case PUBLIC: + contentRes = R.string.metadata_privacy_public; + break; + case UNLISTED: + contentRes = R.string.metadata_privacy_unlisted; + break; + case PRIVATE: + contentRes = R.string.metadata_privacy_private; + break; + case INTERNAL: + contentRes = R.string.metadata_privacy_internal; + break; + case OTHER: default: + contentRes = 0; + break; + } + + if (contentRes != 0) { + addMetadataItem(inflater, layout, false, + R.string.metadata_privacy, layout.getContext().getString(contentRes)); + } + } + } } diff --git a/app/src/main/res/layout/fragment_description.xml b/app/src/main/res/layout/fragment_description.xml index e3845e892..e079e41fe 100644 --- a/app/src/main/res/layout/fragment_description.xml +++ b/app/src/main/res/layout/fragment_description.xml @@ -2,10 +2,10 @@ + android:layout_height="wrap_content" + android:orientation="vertical" + android:scrollbars="vertical"> + + diff --git a/app/src/main/res/layout/item_metadata.xml b/app/src/main/res/layout/item_metadata.xml new file mode 100644 index 000000000..441b916e8 --- /dev/null +++ b/app/src/main/res/layout/item_metadata.xml @@ -0,0 +1,44 @@ + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index b8ca33c87..f614b6b64 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -716,4 +716,17 @@ Select your favorite night theme — %s You can select your favorite night theme below Download has started - \ No newline at end of file + Category + Tags + Licence + Privacy + Age limit + Language + Support + Host + Thumbnail URL + Public + Unlisted + Private + Internal + From d0d5373be927f19f0ab1e5d8fe55b99bcb76ccec Mon Sep 17 00:00:00 2001 From: Stypox Date: Wed, 31 Mar 2021 21:29:59 +0200 Subject: [PATCH 2/6] Allow copying metadata to clipboard --- .../schabi/newpipe/fragments/detail/DescriptionFragment.java | 5 +++++ app/src/main/res/layout/item_metadata.xml | 4 ++-- 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/app/src/main/java/org/schabi/newpipe/fragments/detail/DescriptionFragment.java b/app/src/main/java/org/schabi/newpipe/fragments/detail/DescriptionFragment.java index b44841fdb..df16ee7f4 100644 --- a/app/src/main/java/org/schabi/newpipe/fragments/detail/DescriptionFragment.java +++ b/app/src/main/java/org/schabi/newpipe/fragments/detail/DescriptionFragment.java @@ -19,6 +19,7 @@ import org.schabi.newpipe.databinding.ItemMetadataBinding; import org.schabi.newpipe.extractor.stream.Description; import org.schabi.newpipe.extractor.stream.StreamInfo; import org.schabi.newpipe.util.Localization; +import org.schabi.newpipe.util.ShareUtils; import org.schabi.newpipe.util.TextLinkifier; import icepick.State; @@ -139,6 +140,10 @@ public class DescriptionFragment extends BaseFragment { final ItemMetadataBinding binding = ItemMetadataBinding.inflate(inflater, layout, false); binding.metadataTypeView.setText(type); + binding.metadataTypeView.setOnLongClickListener(v -> { + ShareUtils.copyToClipboard(requireContext(), content); + return true; + }); if (linkifyContent) { TextLinkifier.createLinksFromPlainText(layout.getContext(), content, diff --git a/app/src/main/res/layout/item_metadata.xml b/app/src/main/res/layout/item_metadata.xml index 441b916e8..4da962d5c 100644 --- a/app/src/main/res/layout/item_metadata.xml +++ b/app/src/main/res/layout/item_metadata.xml @@ -15,10 +15,10 @@ Date: Thu, 1 Apr 2021 16:43:31 +0200 Subject: [PATCH 3/6] Add button to allow selecting text in the description Since now selection is disabled by default, this fixes #5453 --- .../fragments/detail/DescriptionFragment.java | 86 ++++++++++++++----- .../main/res/drawable-night/ic_select_all.xml | 10 +++ app/src/main/res/drawable/ic_select_all.xml | 10 +++ .../main/res/layout/fragment_description.xml | 56 ++++++++++-- app/src/main/res/values/strings.xml | 3 + 5 files changed, 136 insertions(+), 29 deletions(-) create mode 100644 app/src/main/res/drawable-night/ic_select_all.xml create mode 100644 app/src/main/res/drawable/ic_select_all.xml diff --git a/app/src/main/java/org/schabi/newpipe/fragments/detail/DescriptionFragment.java b/app/src/main/java/org/schabi/newpipe/fragments/detail/DescriptionFragment.java index df16ee7f4..034738d37 100644 --- a/app/src/main/java/org/schabi/newpipe/fragments/detail/DescriptionFragment.java +++ b/app/src/main/java/org/schabi/newpipe/fragments/detail/DescriptionFragment.java @@ -5,11 +5,11 @@ import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; import android.widget.LinearLayout; -import android.widget.TextView; import androidx.annotation.NonNull; import androidx.annotation.Nullable; import androidx.annotation.StringRes; +import androidx.appcompat.widget.TooltipCompat; import androidx.core.text.HtmlCompat; import org.schabi.newpipe.BaseFragment; @@ -35,6 +35,7 @@ public class DescriptionFragment extends BaseFragment { StreamInfo streamInfo = null; @Nullable Disposable descriptionDisposable = null; + FragmentDescriptionBinding binding; public DescriptionFragment() { } @@ -47,11 +48,10 @@ public class DescriptionFragment extends BaseFragment { public View onCreateView(@NonNull final LayoutInflater inflater, @Nullable final ViewGroup container, @Nullable final Bundle savedInstanceState) { - final FragmentDescriptionBinding binding = - FragmentDescriptionBinding.inflate(inflater, container, false); + binding = FragmentDescriptionBinding.inflate(inflater, container, false); if (streamInfo != null) { - setupUploadDate(binding.detailUploadDateView); - setupDescription(binding.detailDescriptionView); + setupUploadDate(); + setupDescription(); setupMetadata(inflater, binding.detailMetadataLayout); } return binding.getRoot(); @@ -65,40 +65,82 @@ public class DescriptionFragment extends BaseFragment { } } - private void setupUploadDate(final TextView uploadDateTextView) { + + private void setupUploadDate() { if (streamInfo.getUploadDate() != null) { - uploadDateTextView.setText(Localization + binding.detailUploadDateView.setText(Localization .localizeUploadDate(activity, streamInfo.getUploadDate().offsetDateTime())); } else { - uploadDateTextView.setVisibility(View.GONE); + binding.detailUploadDateView.setVisibility(View.GONE); } } - private void setupDescription(final TextView descriptionTextView) { + + private void setupDescription() { final Description description = streamInfo.getDescription(); if (description == null || isEmpty(description.getContent()) || description == Description.emptyDescription) { - descriptionTextView.setVisibility(View.GONE); + binding.detailDescriptionView.setVisibility(View.GONE); + binding.detailSelectDescriptionButton.setVisibility(View.GONE); return; } + // start with disabled state. This also loads description content (!) + disableDescriptionSelection(); + + binding.detailSelectDescriptionButton.setOnClickListener(v -> { + if (binding.detailDescriptionNoteView.getVisibility() == View.VISIBLE) { + disableDescriptionSelection(); + } else { + // enable selection only when button is clicked to prevent flickering + enableDescriptionSelection(); + } + }); + } + + private void enableDescriptionSelection() { + binding.detailDescriptionNoteView.setVisibility(View.VISIBLE); + binding.detailDescriptionView.setTextIsSelectable(true); + + final String buttonLabel = getString(R.string.description_select_disable); + binding.detailSelectDescriptionButton.setContentDescription(buttonLabel); + TooltipCompat.setTooltipText(binding.detailSelectDescriptionButton, buttonLabel); + binding.detailSelectDescriptionButton.setImageResource(R.drawable.ic_close); + } + + private void disableDescriptionSelection() { + // show description content again, otherwise some links are not clickable + loadDescriptionContent(); + + binding.detailDescriptionNoteView.setVisibility(View.GONE); + binding.detailDescriptionView.setTextIsSelectable(false); + + final String buttonLabel = getString(R.string.description_select_enable); + binding.detailSelectDescriptionButton.setContentDescription(buttonLabel); + TooltipCompat.setTooltipText(binding.detailSelectDescriptionButton, buttonLabel); + binding.detailSelectDescriptionButton.setImageResource(R.drawable.ic_select_all); + } + + private void loadDescriptionContent() { + final Description description = streamInfo.getDescription(); switch (description.getType()) { case Description.HTML: descriptionDisposable = TextLinkifier.createLinksFromHtmlBlock(requireContext(), - description.getContent(), descriptionTextView, + description.getContent(), binding.detailDescriptionView, HtmlCompat.FROM_HTML_MODE_LEGACY); break; case Description.MARKDOWN: descriptionDisposable = TextLinkifier.createLinksFromMarkdownText(requireContext(), - description.getContent(), descriptionTextView); + description.getContent(), binding.detailDescriptionView); break; case Description.PLAIN_TEXT: default: descriptionDisposable = TextLinkifier.createLinksFromPlainText(requireContext(), - description.getContent(), descriptionTextView); + description.getContent(), binding.detailDescriptionView); break; } } + private void setupMetadata(final LayoutInflater inflater, final LinearLayout layout) { addMetadataItem(inflater, layout, false, @@ -138,21 +180,23 @@ public class DescriptionFragment extends BaseFragment { return; } - final ItemMetadataBinding binding = ItemMetadataBinding.inflate(inflater, layout, false); - binding.metadataTypeView.setText(type); - binding.metadataTypeView.setOnLongClickListener(v -> { + final ItemMetadataBinding itemBinding + = ItemMetadataBinding.inflate(inflater, layout, false); + + itemBinding.metadataTypeView.setText(type); + itemBinding.metadataTypeView.setOnLongClickListener(v -> { ShareUtils.copyToClipboard(requireContext(), content); return true; }); if (linkifyContent) { - TextLinkifier.createLinksFromPlainText(layout.getContext(), content, - binding.metadataContentView); + TextLinkifier.createLinksFromPlainText(requireContext(), + content, itemBinding.metadataContentView); } else { - binding.metadataContentView.setText(content); + itemBinding.metadataContentView.setText(content); } - layout.addView(binding.getRoot()); + layout.addView(itemBinding.getRoot()); } private void addTagsMetadataItem(final LayoutInflater inflater, final LinearLayout layout) { @@ -192,7 +236,7 @@ public class DescriptionFragment extends BaseFragment { if (contentRes != 0) { addMetadataItem(inflater, layout, false, - R.string.metadata_privacy, layout.getContext().getString(contentRes)); + R.string.metadata_privacy, getString(contentRes)); } } } diff --git a/app/src/main/res/drawable-night/ic_select_all.xml b/app/src/main/res/drawable-night/ic_select_all.xml new file mode 100644 index 000000000..157734911 --- /dev/null +++ b/app/src/main/res/drawable-night/ic_select_all.xml @@ -0,0 +1,10 @@ + + + diff --git a/app/src/main/res/drawable/ic_select_all.xml b/app/src/main/res/drawable/ic_select_all.xml new file mode 100644 index 000000000..e8693d51b --- /dev/null +++ b/app/src/main/res/drawable/ic_select_all.xml @@ -0,0 +1,10 @@ + + + diff --git a/app/src/main/res/layout/fragment_description.xml b/app/src/main/res/layout/fragment_description.xml index e079e41fe..e4622a85f 100644 --- a/app/src/main/res/layout/fragment_description.xml +++ b/app/src/main/res/layout/fragment_description.xml @@ -9,7 +9,8 @@ + android:layout_height="wrap_content" + android:animateLayoutChanges="true"> + + + + + + Select your favorite night theme — %s You can select your favorite night theme below Download has started + You can now select text inside the description. Note that the page may flicker and links may not be clickable while in selection mode. + Enable selecting text in the description + Disable selecting text in the description Category Tags Licence From 14256137e8ac2ed871b355a8e5bd7ab9ffc44465 Mon Sep 17 00:00:00 2001 From: Stypox Date: Wed, 2 Jun 2021 16:09:21 +0200 Subject: [PATCH 4/6] Use chips to show tags in metadata section Clicking on chips opens the search fragment Long clicking copies to clipboard --- .../fragments/detail/DescriptionFragment.java | 34 +++++++++++--- app/src/main/res/layout/chip.xml | 9 ++++ .../main/res/layout/fragment_description.xml | 4 +- app/src/main/res/layout/item_metadata.xml | 14 +++--- .../main/res/layout/item_metadata_tags.xml | 45 +++++++++++++++++++ 5 files changed, 89 insertions(+), 17 deletions(-) create mode 100644 app/src/main/res/layout/chip.xml create mode 100644 app/src/main/res/layout/item_metadata_tags.xml diff --git a/app/src/main/java/org/schabi/newpipe/fragments/detail/DescriptionFragment.java b/app/src/main/java/org/schabi/newpipe/fragments/detail/DescriptionFragment.java index 034738d37..bbff26cc4 100644 --- a/app/src/main/java/org/schabi/newpipe/fragments/detail/DescriptionFragment.java +++ b/app/src/main/java/org/schabi/newpipe/fragments/detail/DescriptionFragment.java @@ -12,13 +12,17 @@ import androidx.annotation.StringRes; import androidx.appcompat.widget.TooltipCompat; import androidx.core.text.HtmlCompat; +import com.google.android.material.chip.Chip; + import org.schabi.newpipe.BaseFragment; import org.schabi.newpipe.R; import org.schabi.newpipe.databinding.FragmentDescriptionBinding; import org.schabi.newpipe.databinding.ItemMetadataBinding; +import org.schabi.newpipe.databinding.ItemMetadataTagsBinding; import org.schabi.newpipe.extractor.stream.Description; import org.schabi.newpipe.extractor.stream.StreamInfo; import org.schabi.newpipe.util.Localization; +import org.schabi.newpipe.util.NavigationHelper; import org.schabi.newpipe.util.ShareUtils; import org.schabi.newpipe.util.TextLinkifier; @@ -201,18 +205,34 @@ public class DescriptionFragment extends BaseFragment { private void addTagsMetadataItem(final LayoutInflater inflater, final LinearLayout layout) { if (streamInfo.getTags() != null && !streamInfo.getTags().isEmpty()) { - final StringBuilder tags = new StringBuilder(); - for (int i = 0; i < streamInfo.getTags().size(); ++i) { - if (i != 0) { - tags.append(", "); - } - tags.append(streamInfo.getTags().get(i)); + final ItemMetadataTagsBinding itemBinding + = ItemMetadataTagsBinding.inflate(inflater, layout, false); + + for (final String tag : streamInfo.getTags()) { + final Chip chip = (Chip) inflater.inflate(R.layout.chip, + itemBinding.metadataTagsChips, false); + chip.setText(tag); + chip.setOnClickListener(this::onTagClick); + chip.setOnLongClickListener(this::onTagLongClick); + itemBinding.metadataTagsChips.addView(chip); } - addMetadataItem(inflater, layout, false, R.string.metadata_tags, tags.toString()); + layout.addView(itemBinding.getRoot()); } } + private void onTagClick(final View chip) { + if (getParentFragment() != null) { + NavigationHelper.openSearchFragment(getParentFragment().getParentFragmentManager(), + streamInfo.getServiceId(), ((Chip) chip).getText().toString()); + } + } + + private boolean onTagLongClick(final View chip) { + ShareUtils.copyToClipboard(requireContext(), ((Chip) chip).getText().toString()); + return true; + } + private void addPrivacyMetadataItem(final LayoutInflater inflater, final LinearLayout layout) { if (streamInfo.getPrivacy() != null) { @StringRes final int contentRes; diff --git a/app/src/main/res/layout/chip.xml b/app/src/main/res/layout/chip.xml new file mode 100644 index 000000000..f7a55fdf3 --- /dev/null +++ b/app/src/main/res/layout/chip.xml @@ -0,0 +1,9 @@ + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/fragment_description.xml b/app/src/main/res/layout/fragment_description.xml index e4622a85f..c44b88cb6 100644 --- a/app/src/main/res/layout/fragment_description.xml +++ b/app/src/main/res/layout/fragment_description.xml @@ -88,9 +88,9 @@ android:layout_width="0dp" android:layout_height="wrap_content" android:layout_marginStart="16dp" - android:layout_marginTop="8dp" + android:layout_marginTop="10dp" android:layout_marginEnd="16dp" - android:layout_marginBottom="16dp" + android:layout_marginBottom="10dp" android:orientation="vertical" app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintEnd_toEndOf="parent" diff --git a/app/src/main/res/layout/item_metadata.xml b/app/src/main/res/layout/item_metadata.xml index 4da962d5c..b9015e603 100644 --- a/app/src/main/res/layout/item_metadata.xml +++ b/app/src/main/res/layout/item_metadata.xml @@ -1,23 +1,23 @@ + android:paddingTop="6dp" + android:paddingBottom="6dp"> + app:layout_constraintGuide_percent="0.23" /> - \ No newline at end of file diff --git a/app/src/main/res/layout/item_metadata_tags.xml b/app/src/main/res/layout/item_metadata_tags.xml new file mode 100644 index 000000000..cd0b8c42d --- /dev/null +++ b/app/src/main/res/layout/item_metadata_tags.xml @@ -0,0 +1,45 @@ + + + + + + + + + + + + \ No newline at end of file From d025ef11f8e72f083fd91c8436a29c438f384bc0 Mon Sep 17 00:00:00 2001 From: Stypox Date: Wed, 2 Jun 2021 16:15:53 +0200 Subject: [PATCH 5/6] Sort tags in metadata section --- .../newpipe/fragments/detail/DescriptionFragment.java | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/app/src/main/java/org/schabi/newpipe/fragments/detail/DescriptionFragment.java b/app/src/main/java/org/schabi/newpipe/fragments/detail/DescriptionFragment.java index bbff26cc4..5f1cbc365 100644 --- a/app/src/main/java/org/schabi/newpipe/fragments/detail/DescriptionFragment.java +++ b/app/src/main/java/org/schabi/newpipe/fragments/detail/DescriptionFragment.java @@ -26,6 +26,10 @@ import org.schabi.newpipe.util.NavigationHelper; import org.schabi.newpipe.util.ShareUtils; import org.schabi.newpipe.util.TextLinkifier; +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; + import icepick.State; import io.reactivex.rxjava3.disposables.Disposable; @@ -208,7 +212,9 @@ public class DescriptionFragment extends BaseFragment { final ItemMetadataTagsBinding itemBinding = ItemMetadataTagsBinding.inflate(inflater, layout, false); - for (final String tag : streamInfo.getTags()) { + final List tags = new ArrayList<>(streamInfo.getTags()); + Collections.sort(tags); + for (final String tag : tags) { final Chip chip = (Chip) inflater.inflate(R.layout.chip, itemBinding.metadataTagsChips, false); chip.setText(tag); From 9e94c81ef2b34b19a975384d872d3d97263cb3cb Mon Sep 17 00:00:00 2001 From: Stypox Date: Wed, 2 Jun 2021 21:19:57 +0200 Subject: [PATCH 6/6] Always show scrollbars for metadata tags --- app/src/main/res/layout/item_metadata_tags.xml | 1 + 1 file changed, 1 insertion(+) diff --git a/app/src/main/res/layout/item_metadata_tags.xml b/app/src/main/res/layout/item_metadata_tags.xml index cd0b8c42d..d887c9e28 100644 --- a/app/src/main/res/layout/item_metadata_tags.xml +++ b/app/src/main/res/layout/item_metadata_tags.xml @@ -30,6 +30,7 @@ android:layout_marginStart="16dp" android:layout_marginTop="-8dp" android:layout_marginBottom="-8dp" + android:fadeScrollbars="false" app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintEnd_toEndOf="parent" app:layout_constraintStart_toStartOf="@+id/guideline"