diff --git a/app/src/main/java/org/schabi/newpipe/fragments/list/channel/ChannelFragment.java b/app/src/main/java/org/schabi/newpipe/fragments/list/channel/ChannelFragment.java index 4cd8313fc..6e7473b1e 100644 --- a/app/src/main/java/org/schabi/newpipe/fragments/list/channel/ChannelFragment.java +++ b/app/src/main/java/org/schabi/newpipe/fragments/list/channel/ChannelFragment.java @@ -276,7 +276,7 @@ public class ChannelFragment extends BaseStateFragment { final String description = currentInfo.getDescription(); if (description != null && !description.isEmpty()) { tabAdapter.addFragment( - ChannelInfoFragment.getInstance(description), "Info"); + ChannelInfoFragment.getInstance(currentInfo), "Info"); } } } diff --git a/app/src/main/java/org/schabi/newpipe/fragments/list/channel/ChannelInfoFragment.java b/app/src/main/java/org/schabi/newpipe/fragments/list/channel/ChannelInfoFragment.java index c9273f528..2ab4ce419 100644 --- a/app/src/main/java/org/schabi/newpipe/fragments/list/channel/ChannelInfoFragment.java +++ b/app/src/main/java/org/schabi/newpipe/fragments/list/channel/ChannelInfoFragment.java @@ -1,22 +1,47 @@ package org.schabi.newpipe.fragments.list.channel; +import static org.schabi.newpipe.extractor.stream.StreamExtractor.UNKNOWN_SUBSCRIBER_COUNT; +import static org.schabi.newpipe.extractor.utils.Utils.isBlank; + +import android.content.Context; import android.os.Bundle; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; +import android.widget.LinearLayout; import androidx.annotation.NonNull; import androidx.annotation.Nullable; +import androidx.annotation.StringRes; + +import com.google.android.material.chip.Chip; import org.schabi.newpipe.BaseFragment; +import org.schabi.newpipe.R; import org.schabi.newpipe.databinding.FragmentChannelInfoBinding; +import org.schabi.newpipe.databinding.ItemMetadataBinding; +import org.schabi.newpipe.databinding.ItemMetadataTagsBinding; +import org.schabi.newpipe.extractor.channel.ChannelInfo; +import org.schabi.newpipe.util.Localization; +import org.schabi.newpipe.util.NavigationHelper; +import org.schabi.newpipe.util.external_communication.ShareUtils; +import org.schabi.newpipe.util.external_communication.TextLinkifier; + +import java.util.List; + +import icepick.State; +import io.reactivex.rxjava3.disposables.CompositeDisposable; public class ChannelInfoFragment extends BaseFragment { - private String description; + @State + protected ChannelInfo channelInfo; - public static ChannelInfoFragment getInstance(final String description) { + private final CompositeDisposable disposables = new CompositeDisposable(); + private FragmentChannelInfoBinding binding; + + public static ChannelInfoFragment getInstance(final ChannelInfo channelInfo) { final ChannelInfoFragment fragment = new ChannelInfoFragment(); - fragment.description = description; + fragment.channelInfo = channelInfo; return fragment; } @@ -28,11 +53,92 @@ public class ChannelInfoFragment extends BaseFragment { public View onCreateView(@NonNull final LayoutInflater inflater, @Nullable final ViewGroup container, final Bundle savedInstanceState) { - final FragmentChannelInfoBinding binding = - FragmentChannelInfoBinding.inflate(inflater, container, false); - binding.descriptionText.setText(description); - + binding = FragmentChannelInfoBinding.inflate(inflater, container, false); + loadDescription(); + setupMetadata(inflater, binding.detailMetadataLayout); return binding.getRoot(); } + @Override + public void onDestroy() { + super.onDestroy(); + disposables.clear(); + } + + private void loadDescription() { + final String description = channelInfo.getDescription(); + + if (description == null || description.isEmpty()) { + binding.descriptionTitle.setVisibility(View.GONE); + binding.descriptionView.setVisibility(View.GONE); + } else { + TextLinkifier.createLinksFromPlainText( + binding.descriptionView, description, null, disposables); + } + } + + private void setupMetadata(final LayoutInflater inflater, + final LinearLayout layout) { + Context context = getActivity(); + + if (channelInfo.getSubscriberCount() != UNKNOWN_SUBSCRIBER_COUNT) { + addMetadataItem(inflater, layout, R.string.metadata_subscribers, + Localization.localizeNumber(context, channelInfo.getSubscriberCount())); + } + + addTagsMetadataItem(inflater, layout); + } + + private void addMetadataItem(final LayoutInflater inflater, + final LinearLayout layout, + @StringRes final int type, + @Nullable final String content) { + if (isBlank(content)) { + return; + } + + final ItemMetadataBinding itemBinding = + ItemMetadataBinding.inflate(inflater, layout, false); + + itemBinding.metadataTypeView.setText(type); + itemBinding.metadataTypeView.setOnLongClickListener(v -> { + ShareUtils.copyToClipboard(requireContext(), content); + return true; + }); + + itemBinding.metadataContentView.setText(content); + + layout.addView(itemBinding.getRoot()); + } + + private void addTagsMetadataItem(final LayoutInflater inflater, final LinearLayout layout) { + final List tags = channelInfo.getTags(); + + if (!tags.isEmpty()) { + final var itemBinding = ItemMetadataTagsBinding.inflate(inflater, layout, false); + + tags.stream().sorted(String.CASE_INSENSITIVE_ORDER).forEach(tag -> { + 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); + }); + + layout.addView(itemBinding.getRoot()); + } + } + + private void onTagClick(final View chip) { + if (getParentFragment() != null) { + NavigationHelper.openSearchFragment(getParentFragment().getParentFragmentManager(), + channelInfo.getServiceId(), ((Chip) chip).getText().toString()); + } + } + + private boolean onTagLongClick(final View chip) { + ShareUtils.copyToClipboard(requireContext(), ((Chip) chip).getText().toString()); + return true; + } } diff --git a/app/src/main/java/org/schabi/newpipe/fragments/list/channel/ChannelTabFragment.java b/app/src/main/java/org/schabi/newpipe/fragments/list/channel/ChannelTabFragment.java index 21613d717..5a26371b7 100644 --- a/app/src/main/java/org/schabi/newpipe/fragments/list/channel/ChannelTabFragment.java +++ b/app/src/main/java/org/schabi/newpipe/fragments/list/channel/ChannelTabFragment.java @@ -2,8 +2,6 @@ package org.schabi.newpipe.fragments.list.channel; import android.os.Bundle; import android.view.LayoutInflater; -import android.view.Menu; -import android.view.MenuInflater; import android.view.View; import android.view.ViewGroup; diff --git a/app/src/main/res/layout/fragment_channel_info.xml b/app/src/main/res/layout/fragment_channel_info.xml index fbb8e355b..8cbadba1f 100644 --- a/app/src/main/res/layout/fragment_channel_info.xml +++ b/app/src/main/res/layout/fragment_channel_info.xml @@ -5,6 +5,19 @@ android:layout_width="match_parent" android:layout_height="match_parent"> + + + - --> + + + tools:layout_editor_absoluteX="0dp" + tools:text="Cupcake ipsum dolor sit amet I love. I love macaroon cake sweet topping jelly beans chocolate chupa chups candy canes. Marshmallow cake jelly fruitcake soufflé pie. Jelly jelly beans cupcake topping chocolate bar jelly pudding pastry sweet roll." + tools:visibility="visible" /> + + \ No newline at end of file diff --git a/app/src/main/res/values-de/strings.xml b/app/src/main/res/values-de/strings.xml index dfc26a4e2..c5260fa03 100644 --- a/app/src/main/res/values-de/strings.xml +++ b/app/src/main/res/values-de/strings.xml @@ -620,6 +620,7 @@ Vorschaubild-URL Server Unterstützung + Abonnenten Auswählen von Text in der Beschreibung deaktivieren Auswählen von Text in der Beschreibung aktivieren Du kannst nun Text innerhalb der Beschreibung auswählen. Beachte, dass die Seite flackern kann und Links im Auswahlmodus möglicherweise nicht anklickbar sind. diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index a37bfeb82..7d65807b7 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -758,6 +758,7 @@ Unlisted Private Internal + Subscribers Pinned comment Hearted by creator Open website