From bc3e43ac5891fdeacbcfcd9607ba280797fc45cd Mon Sep 17 00:00:00 2001 From: Stypox Date: Thu, 1 Apr 2021 16:43:31 +0200 Subject: [PATCH] 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