1
0
mirror of https://github.com/TeamNewPipe/NewPipe synced 2025-01-09 08:50:34 +00:00

Migrate about channel fragment to Jetpack Compose

This commit is contained in:
Isira Seneviratne 2024-09-01 16:54:12 +05:30
parent de6285b1e2
commit 2653787fe1
7 changed files with 133 additions and 121 deletions

View File

@ -0,0 +1,36 @@
package org.schabi.newpipe.fragments.list.channel
import android.os.Bundle
import android.view.LayoutInflater
import android.view.ViewGroup
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Surface
import androidx.core.os.bundleOf
import androidx.fragment.app.Fragment
import androidx.fragment.compose.content
import org.schabi.newpipe.extractor.channel.ChannelInfo
import org.schabi.newpipe.ktx.serializable
import org.schabi.newpipe.ui.components.channel.AboutChannelSection
import org.schabi.newpipe.ui.theme.AppTheme
import org.schabi.newpipe.util.KEY_INFO
class AboutChannelFragment : Fragment() {
override fun onCreateView(
inflater: LayoutInflater,
container: ViewGroup?,
savedInstanceState: Bundle?
) = content {
AppTheme {
Surface(color = MaterialTheme.colorScheme.background) {
AboutChannelSection(requireArguments().serializable(KEY_INFO)!!)
}
}
}
companion object {
@JvmStatic
fun getInstance(channelInfo: ChannelInfo) = AboutChannelFragment().apply {
arguments = bundleOf(KEY_INFO to channelInfo)
}
}
}

View File

@ -1,94 +0,0 @@
package org.schabi.newpipe.fragments.list.channel;
import static org.schabi.newpipe.extractor.stream.StreamExtractor.UNKNOWN_SUBSCRIBER_COUNT;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.widget.LinearLayout;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import org.schabi.newpipe.R;
import org.schabi.newpipe.extractor.StreamingService;
import org.schabi.newpipe.extractor.channel.ChannelInfo;
import org.schabi.newpipe.extractor.stream.Description;
import org.schabi.newpipe.fragments.detail.BaseDescriptionFragment;
import org.schabi.newpipe.util.DeviceUtils;
import org.schabi.newpipe.util.Localization;
import java.util.List;
import icepick.State;
public class ChannelAboutFragment extends BaseDescriptionFragment {
@State
protected ChannelInfo channelInfo;
ChannelAboutFragment(@NonNull final ChannelInfo channelInfo) {
this.channelInfo = channelInfo;
}
public ChannelAboutFragment() {
// keep empty constructor for IcePick when resuming fragment from memory
}
@Override
protected void initViews(final View rootView, final Bundle savedInstanceState) {
super.initViews(rootView, savedInstanceState);
binding.constraintLayout.setPadding(0, DeviceUtils.dpToPx(8, requireContext()), 0, 0);
}
@Nullable
@Override
protected Description getDescription() {
return new Description(channelInfo.getDescription(), Description.PLAIN_TEXT);
}
@NonNull
@Override
protected StreamingService getService() {
return channelInfo.getService();
}
@Override
protected int getServiceId() {
return channelInfo.getServiceId();
}
@Nullable
@Override
protected String getStreamUrl() {
return null;
}
@NonNull
@Override
public List<String> getTags() {
return channelInfo.getTags();
}
@Override
protected void setupMetadata(final LayoutInflater inflater,
final LinearLayout layout) {
// There is no upload date available for channels, so hide the relevant UI element
binding.detailUploadDateView.setVisibility(View.GONE);
if (channelInfo == null) {
return;
}
if (channelInfo.getSubscriberCount() != UNKNOWN_SUBSCRIBER_COUNT) {
addMetadataItem(inflater, layout, false, R.string.metadata_subscribers,
Localization.localizeNumber(
requireContext(),
channelInfo.getSubscriberCount()));
}
addImagesMetadataItem(inflater, layout, R.string.metadata_avatars,
channelInfo.getAvatars());
addImagesMetadataItem(inflater, layout, R.string.metadata_banners,
channelInfo.getBanners());
}
}

View File

@ -481,7 +481,7 @@ public class ChannelFragment extends BaseStateFragment<ChannelInfo>
if (ChannelTabHelper.showChannelTab(
context, preferences, R.string.show_channel_tabs_about)) {
tabAdapter.addFragment(
new ChannelAboutFragment(currentInfo),
AboutChannelFragment.getInstance(currentInfo),
context.getString(R.string.channel_tab_about));
}
}

View File

@ -0,0 +1,71 @@
package org.schabi.newpipe.ui.components.channel
import android.content.res.Configuration
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.padding
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Surface
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier
import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.unit.dp
import org.schabi.newpipe.R
import org.schabi.newpipe.extractor.channel.ChannelInfo
import org.schabi.newpipe.ui.components.metadata.ImageMetadataItem
import org.schabi.newpipe.ui.components.metadata.MetadataItem
import org.schabi.newpipe.ui.theme.AppTheme
import org.schabi.newpipe.util.Localization
import org.schabi.newpipe.util.NO_SERVICE_ID
import org.schabi.newpipe.util.image.ImageStrategy
@Composable
fun AboutChannelSection(channelInfo: ChannelInfo) {
// This tab currently holds little information, so a lazy column isn't needed here.
Column(
modifier = Modifier.padding(12.dp),
verticalArrangement = Arrangement.spacedBy(4.dp)
) {
val description = channelInfo.description
if (!description.isNullOrEmpty()) {
Text(text = description)
}
val count = channelInfo.subscriberCount
if (count != -1L) {
MetadataItem(
title = R.string.metadata_subscribers,
value = Localization.shortCount(LocalContext.current, count)
)
}
ImageStrategy.choosePreferredImage(channelInfo.avatars)?.let {
ImageMetadataItem(R.string.metadata_avatars, channelInfo.avatars, it)
}
ImageStrategy.choosePreferredImage(channelInfo.banners)?.let {
ImageMetadataItem(R.string.metadata_banners, channelInfo.banners, it)
}
if (channelInfo.tags.isNotEmpty()) {
TagsSection(channelInfo.serviceId, channelInfo.tags)
}
}
}
@Preview(name = "Light mode", uiMode = Configuration.UI_MODE_NIGHT_NO)
@Preview(name = "Dark mode", uiMode = Configuration.UI_MODE_NIGHT_YES)
@Composable
private fun AboutChannelSectionPreview() {
val info = ChannelInfo(NO_SERVICE_ID, "", "", "", "")
info.description = "This is an example description"
info.subscriberCount = 10
AppTheme {
Surface(color = MaterialTheme.colorScheme.background) {
AboutChannelSection(info)
}
}
}

View File

@ -3,7 +3,6 @@ package org.schabi.newpipe.ui.components.metadata
import android.content.Context
import android.content.res.Configuration
import androidx.annotation.StringRes
import androidx.compose.foundation.lazy.LazyListScope
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Surface
import androidx.compose.runtime.Composable
@ -38,14 +37,6 @@ fun ImageMetadataItem(
MetadataItem(title = title, value = imageLinks)
}
fun LazyListScope.imageMetadataItem(@StringRes title: Int, images: List<Image>) {
ImageStrategy.choosePreferredImage(images)?.let {
item {
ImageMetadataItem(title, images, it)
}
}
}
private fun convertImagesToLinks(
context: Context,
images: List<Image>,

View File

@ -6,7 +6,7 @@ import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.lazy.LazyListScope
import androidx.compose.foundation.layout.width
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Surface
import androidx.compose.material3.Text
@ -35,24 +35,13 @@ fun MetadataItem(@StringRes title: Int, value: AnnotatedString) {
verticalAlignment = Alignment.CenterVertically
) {
Text(
modifier = Modifier.weight(0.3f),
modifier = Modifier.width(96.dp),
textAlign = TextAlign.End,
text = stringResource(title).uppercase(),
text = stringResource(title),
fontWeight = FontWeight.Bold
)
Text(
modifier = Modifier.weight(0.7f),
text = value
)
}
}
fun LazyListScope.metadataItem(@StringRes title: Int, value: String) {
if (value.isNotEmpty()) {
item {
MetadataItem(title, value)
}
Text(text = value)
}
}

View File

@ -1,6 +1,7 @@
package org.schabi.newpipe.ui.components.video
import android.content.res.Configuration
import androidx.annotation.StringRes
import androidx.compose.animation.AnimatedVisibility
import androidx.compose.animation.expandVertically
import androidx.compose.animation.fadeIn
@ -15,6 +16,7 @@ import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.lazy.LazyColumn
import androidx.compose.foundation.lazy.LazyListScope
import androidx.compose.foundation.lazy.rememberLazyListState
import androidx.compose.foundation.text.selection.SelectionContainer
import androidx.compose.material3.ExperimentalMaterial3Api
@ -43,19 +45,20 @@ import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.unit.dp
import my.nanihadesuka.compose.LazyColumnScrollbar
import org.schabi.newpipe.R
import org.schabi.newpipe.extractor.Image
import org.schabi.newpipe.extractor.localization.DateWrapper
import org.schabi.newpipe.extractor.stream.Description
import org.schabi.newpipe.extractor.stream.StreamExtractor
import org.schabi.newpipe.extractor.stream.StreamInfo
import org.schabi.newpipe.extractor.stream.StreamType
import org.schabi.newpipe.ui.components.common.DescriptionText
import org.schabi.newpipe.ui.components.metadata.ImageMetadataItem
import org.schabi.newpipe.ui.components.metadata.MetadataItem
import org.schabi.newpipe.ui.components.metadata.TagsSection
import org.schabi.newpipe.ui.components.metadata.imageMetadataItem
import org.schabi.newpipe.ui.components.metadata.metadataItem
import org.schabi.newpipe.ui.theme.AppTheme
import org.schabi.newpipe.util.Localization
import org.schabi.newpipe.util.NO_SERVICE_ID
import org.schabi.newpipe.util.image.ImageStrategy
import java.time.OffsetDateTime
@OptIn(ExperimentalMaterial3Api::class)
@ -202,6 +205,22 @@ fun VideoDescriptionSection(streamInfo: StreamInfo) {
}
}
private fun LazyListScope.metadataItem(@StringRes title: Int, value: String) {
if (value.isNotEmpty()) {
item {
MetadataItem(title, value)
}
}
}
private fun LazyListScope.imageMetadataItem(@StringRes title: Int, images: List<Image>) {
ImageStrategy.choosePreferredImage(images)?.let {
item {
ImageMetadataItem(title, images, it)
}
}
}
@Preview(name = "Light mode", uiMode = Configuration.UI_MODE_NIGHT_NO)
@Preview(name = "Dark mode", uiMode = Configuration.UI_MODE_NIGHT_YES)
@Composable