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:
parent
de6285b1e2
commit
2653787fe1
@ -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)
|
||||
}
|
||||
}
|
||||
}
|
@ -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());
|
||||
}
|
||||
}
|
@ -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));
|
||||
}
|
||||
}
|
||||
|
@ -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)
|
||||
}
|
||||
}
|
||||
}
|
@ -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>,
|
||||
|
@ -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)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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
|
||||
|
Loading…
Reference in New Issue
Block a user