Skip to content

Commit

Permalink
Add button to allow selecting text in the description
Browse files Browse the repository at this point in the history
Since now selection is disabled by default, this fixes #5453
  • Loading branch information
Stypox committed Apr 1, 2021
1 parent 447af3b commit c2b86c3
Show file tree
Hide file tree
Showing 7 changed files with 142 additions and 29 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,11 @@
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;
Expand All @@ -21,6 +21,7 @@
import org.schabi.newpipe.util.Localization;
import org.schabi.newpipe.util.ShareUtils;
import org.schabi.newpipe.util.TextLinkifier;
import org.schabi.newpipe.util.ThemeHelper;

import icepick.State;
import io.reactivex.rxjava3.disposables.Disposable;
Expand All @@ -35,6 +36,7 @@ public class DescriptionFragment extends BaseFragment {
StreamInfo streamInfo = null;
@Nullable
Disposable descriptionDisposable = null;
FragmentDescriptionBinding binding;

public DescriptionFragment() {
}
Expand All @@ -47,11 +49,10 @@ public DescriptionFragment(final StreamInfo streamInfo) {
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();
Expand All @@ -65,40 +66,84 @@ public void onDestroy() {
}
}

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(
ThemeHelper.resolveResourceIdFromAttr(requireContext(), R.attr.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(
ThemeHelper.resolveResourceIdFromAttr(requireContext(), R.attr.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,
Expand Down Expand Up @@ -138,21 +183,23 @@ private void addMetadataItem(final LayoutInflater inflater,
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) {
Expand Down Expand Up @@ -192,7 +239,7 @@ private void addPrivacyMetadataItem(final LayoutInflater inflater, final LinearL

if (contentRes != 0) {
addMetadataItem(inflater, layout, false,
R.string.metadata_privacy, layout.getContext().getString(contentRes));
R.string.metadata_privacy, getString(contentRes));
}
}
}
Expand Down
10 changes: 10 additions & 0 deletions app/src/main/res/drawable/ic_select_all_black_24dp.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportWidth="24"
android:viewportHeight="24"
android:tint="#000000">
<path
android:fillColor="#000000"
android:pathData="M3,5h2L5,3c-1.1,0 -2,0.9 -2,2zM3,13h2v-2L3,11v2zM7,21h2v-2L7,19v2zM3,9h2L5,7L3,7v2zM13,3h-2v2h2L13,3zM19,3v2h2c0,-1.1 -0.9,-2 -2,-2zM5,21v-2L3,19c0,1.1 0.9,2 2,2zM3,17h2v-2L3,15v2zM9,3L7,3v2h2L9,3zM11,21h2v-2h-2v2zM19,13h2v-2h-2v2zM19,21c1.1,0 2,-0.9 2,-2h-2v2zM19,9h2L21,7h-2v2zM19,17h2v-2h-2v2zM15,21h2v-2h-2v2zM15,5h2L17,3h-2v2zM7,17h10L17,7L7,7v10zM9,9h6v6L9,15L9,9z"/>
</vector>
10 changes: 10 additions & 0 deletions app/src/main/res/drawable/ic_select_all_white_24dp.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportWidth="24"
android:viewportHeight="24"
android:tint="#ffffff">
<path
android:fillColor="#ffffff"
android:pathData="M3,5h2L5,3c-1.1,0 -2,0.9 -2,2zM3,13h2v-2L3,11v2zM7,21h2v-2L7,19v2zM3,9h2L5,7L3,7v2zM13,3h-2v2h2L13,3zM19,3v2h2c0,-1.1 -0.9,-2 -2,-2zM5,21v-2L3,19c0,1.1 0.9,2 2,2zM3,17h2v-2L3,15v2zM9,3L7,3v2h2L9,3zM11,21h2v-2h-2v2zM19,13h2v-2h-2v2zM19,21c1.1,0 2,-0.9 2,-2h-2v2zM19,9h2L21,7h-2v2zM19,17h2v-2h-2v2zM15,21h2v-2h-2v2zM15,5h2L17,3h-2v2zM7,17h10L17,7L7,7v10zM9,9h6v6L9,15L9,9z"/>
</vector>
56 changes: 48 additions & 8 deletions app/src/main/res/layout/fragment_description.xml
Original file line number Diff line number Diff line change
Expand Up @@ -9,38 +9,78 @@

<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="wrap_content">
android:layout_height="wrap_content"
android:animateLayoutChanges="true">

<TextView
android:id="@+id/detail_upload_date_view"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginStart="16dp"
android:layout_marginTop="6dp"
android:layout_marginEnd="16dp"
android:layout_marginEnd="8dp"
android:textAppearance="?android:attr/textAppearanceMedium"
android:textSize="@dimen/video_item_detail_upload_date_text_size"
android:textStyle="bold"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="0.0"
app:layout_constraintEnd_toStartOf="@+id/detail_select_description_button"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
tools:text="Published on Oct 2, 2009" />

<ImageView
android:id="@+id/detail_select_description_button"
android:layout_width="0dp"
android:layout_height="0dp"
android:layout_marginEnd="16dp"
android:layout_marginBottom="2dp"
android:background="?attr/selectableItemBackgroundBorderless"
android:clickable="true"
android:contentDescription="@string/description_select_enable"
android:focusable="true"
android:padding="5dp"
app:layout_constraintBottom_toTopOf="@+id/barrier"
app:layout_constraintDimensionRatio="1"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:srcCompat="?attr/ic_select_all" />

<androidx.constraintlayout.widget.Barrier
android:id="@+id/barrier"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
app:barrierAllowsGoneWidgets="false"
app:barrierDirection="top"
app:constraint_referenced_ids="detail_description_note_view,detail_description_view" />

<TextView
android:id="@+id/detail_description_note_view"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginStart="16dp"
android:layout_marginTop="8dp"
android:layout_marginEnd="16dp"
android:gravity="center"
android:text="@string/description_select_note"
android:textSize="12sp"
android:textStyle="italic"
android:visibility="gone"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/detail_upload_date_view"
tools:visibility="visible" />

<TextView
android:id="@+id/detail_description_view"
android:layout_width="match_parent"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginStart="16dp"
android:layout_marginTop="8dp"
android:layout_marginEnd="16dp"
android:textAppearance="?android:attr/textAppearanceMedium"
android:textIsSelectable="true"
android:textSize="@dimen/video_item_detail_description_text_size"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/detail_upload_date_view"
app:layout_constraintVertical_bias="0.0"
app:layout_constraintTop_toBottomOf="@+id/detail_description_note_view"
tools:text="Description Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed a ultricies ex. Integer sit amet sodales risus. Duis non mi et urna pretium bibendum." />

<LinearLayout
Expand Down
1 change: 1 addition & 0 deletions app/src/main/res/values/attrs.xml
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,7 @@
<attr name="ic_help" format="reference" />
<attr name="ic_arrow_back" format="reference" />
<attr name="ic_live_tv" format="reference" />
<attr name="ic_select_all" format="reference" />

<attr name="progress_horizontal_drawable" format="reference" />
<!-- Can't refer to colors directly in drawable's xml-->
Expand Down
3 changes: 3 additions & 0 deletions app/src/main/res/values/strings.xml
Original file line number Diff line number Diff line change
Expand Up @@ -715,6 +715,9 @@
<string name="night_theme_summary">Select your favorite night theme — %s</string>
<string name="select_night_theme_toast">You can select your favorite night theme below</string>
<string name="download_has_started">Download has started</string>
<string name="description_select_note">You can now select text inside the description. Note that the page may flicker and links may not be clickable while in selection mode.</string>
<string name="description_select_enable">Enable selecting text in the description</string>
<string name="description_select_disable">Disable selecting text in the description</string>
<string name="metadata_category">Category</string>
<string name="metadata_tags">Tags</string>
<string name="metadata_licence">Licence</string>
Expand Down
2 changes: 2 additions & 0 deletions app/src/main/res/values/styles.xml
Original file line number Diff line number Diff line change
Expand Up @@ -99,6 +99,7 @@
<item name="ic_sort">@drawable/ic_sort_black_24dp</item>
<item name="ic_help">@drawable/ic_help_black_24dp</item>
<item name="ic_arrow_back">@drawable/ic_arrow_back_black_24dp</item>
<item name="ic_select_all">@drawable/ic_select_all_black_24dp</item>

<item name="separator_color">@color/light_separator_color</item>
<item name="contrast_background_color">@color/light_contrast_background_color</item>
Expand Down Expand Up @@ -209,6 +210,7 @@
<item name="ic_sort">@drawable/ic_sort_white_24dp</item>
<item name="ic_help">@drawable/ic_help_white_24dp</item>
<item name="ic_arrow_back">@drawable/ic_arrow_back_white_24dp</item>
<item name="ic_select_all">@drawable/ic_select_all_white_24dp</item>

<item name="separator_color">@color/dark_separator_color</item>
<item name="contrast_background_color">@color/dark_contrast_background_color</item>
Expand Down

0 comments on commit c2b86c3

Please sign in to comment.