Uniform localizing view counts
This commit is contained in:
parent
b50db477a1
commit
4b90295aab
@ -1424,14 +1424,9 @@ class VideoDetailFragment :
|
||||
}
|
||||
|
||||
if (info.viewCount >= 0) {
|
||||
binding.detailViewCountView.text =
|
||||
if (info.streamType == StreamType.AUDIO_LIVE_STREAM) {
|
||||
Localization.listeningCount(activity, info.viewCount)
|
||||
} else if (info.streamType == StreamType.LIVE_STREAM) {
|
||||
Localization.localizeWatchingCount(activity, info.viewCount)
|
||||
} else {
|
||||
Localization.localizeViewCount(activity, info.viewCount)
|
||||
}
|
||||
binding.detailViewCountView.text = Localization.localizeViewCount(
|
||||
activity, false, info.streamType, info.viewCount
|
||||
)
|
||||
binding.detailViewCountView.visibility = View.VISIBLE
|
||||
} else {
|
||||
binding.detailViewCountView.visibility = View.GONE
|
||||
|
||||
@ -7,7 +7,6 @@ import android.widget.TextView;
|
||||
import org.schabi.newpipe.R;
|
||||
import org.schabi.newpipe.extractor.InfoItem;
|
||||
import org.schabi.newpipe.extractor.stream.StreamInfoItem;
|
||||
import org.schabi.newpipe.extractor.stream.StreamType;
|
||||
import org.schabi.newpipe.info_list.InfoItemBuilder;
|
||||
import org.schabi.newpipe.local.history.HistoryRecordManager;
|
||||
import org.schabi.newpipe.util.Localization;
|
||||
@ -65,16 +64,8 @@ public class StreamInfoItemHolder extends StreamMiniInfoItemHolder {
|
||||
private String getStreamInfoDetailLine(final StreamInfoItem infoItem) {
|
||||
String viewsAndDate = "";
|
||||
if (infoItem.getViewCount() >= 0) {
|
||||
if (infoItem.getStreamType().equals(StreamType.AUDIO_LIVE_STREAM)) {
|
||||
viewsAndDate = Localization
|
||||
.listeningCount(itemBuilder.getContext(), infoItem.getViewCount());
|
||||
} else if (infoItem.getStreamType().equals(StreamType.LIVE_STREAM)) {
|
||||
viewsAndDate = Localization
|
||||
.shortWatchingCount(itemBuilder.getContext(), infoItem.getViewCount());
|
||||
} else {
|
||||
viewsAndDate = Localization
|
||||
.shortViewCount(itemBuilder.getContext(), infoItem.getViewCount());
|
||||
}
|
||||
viewsAndDate = Localization.localizeViewCount(itemBuilder.getContext(), true,
|
||||
infoItem.getStreamType(), infoItem.getViewCount());
|
||||
}
|
||||
|
||||
final String uploadDate = Localization.relativeTimeOrTextual(itemBuilder.getContext(),
|
||||
|
||||
@ -1,7 +1,6 @@
|
||||
package org.schabi.newpipe.local.feed.item
|
||||
|
||||
import android.content.Context
|
||||
import android.text.TextUtils
|
||||
import android.view.View
|
||||
import androidx.core.content.ContextCompat
|
||||
import androidx.preference.PreferenceManager
|
||||
@ -117,23 +116,16 @@ data class StreamItem(
|
||||
}
|
||||
|
||||
private fun getStreamInfoDetailLine(context: Context): String {
|
||||
var viewsAndDate = ""
|
||||
val viewCount = stream.viewCount
|
||||
if (viewCount != null && viewCount >= 0) {
|
||||
viewsAndDate = when (stream.streamType) {
|
||||
AUDIO_LIVE_STREAM -> Localization.listeningCount(context, viewCount)
|
||||
LIVE_STREAM -> Localization.shortWatchingCount(context, viewCount)
|
||||
else -> Localization.shortViewCount(context, viewCount)
|
||||
}
|
||||
}
|
||||
val views = stream.viewCount
|
||||
?.takeIf { it >= 0 }
|
||||
?.let { Localization.localizeViewCount(context, true, stream.streamType, it) }
|
||||
?: ""
|
||||
|
||||
val uploadDate = getFormattedRelativeUploadDate(context)
|
||||
return when {
|
||||
!TextUtils.isEmpty(uploadDate) -> when {
|
||||
viewsAndDate.isEmpty() -> uploadDate!!
|
||||
else -> Localization.concatenateStrings(viewsAndDate, uploadDate)
|
||||
}
|
||||
|
||||
else -> viewsAndDate
|
||||
uploadDate.isNullOrEmpty() -> views
|
||||
views.isEmpty() -> uploadDate
|
||||
else -> Localization.concatenateStrings(views, uploadDate)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -73,7 +73,7 @@ public class LocalStatisticStreamItemHolder extends LocalItemHolder {
|
||||
final DateTimeFormatter dateTimeFormatter) {
|
||||
return Localization.concatenateStrings(
|
||||
// watchCount
|
||||
Localization.shortViewCount(itemBuilder.getContext(), entry.getWatchCount()),
|
||||
Localization.localizeWatchCount(itemBuilder.getContext(), entry.getWatchCount()),
|
||||
dateTimeFormatter.format(entry.getLatestAccessDate()),
|
||||
// serviceName
|
||||
ServiceHelper.getNameOfServiceById(entry.getStreamEntity().getServiceId()));
|
||||
|
||||
@ -37,16 +37,10 @@ internal fun getStreamInfoDetail(stream: StreamInfoItem): String {
|
||||
val context = LocalContext.current
|
||||
|
||||
return rememberSaveable(stream) {
|
||||
val count = stream.viewCount
|
||||
val views = if (count >= 0) {
|
||||
when (stream.streamType) {
|
||||
StreamType.AUDIO_LIVE_STREAM -> Localization.listeningCount(context, count)
|
||||
StreamType.LIVE_STREAM -> Localization.shortWatchingCount(context, count)
|
||||
else -> Localization.shortViewCount(context, count)
|
||||
}
|
||||
} else {
|
||||
""
|
||||
}
|
||||
val views = stream.viewCount
|
||||
.takeIf { it >= 0 }
|
||||
?.let { Localization.localizeViewCount(context, true, stream.streamType, it) }
|
||||
?: ""
|
||||
val date =
|
||||
Localization.relativeTimeOrTextual(context, stream.uploadDate, stream.textualUploadDate)
|
||||
|
||||
|
||||
@ -72,6 +72,7 @@ import androidx.compose.ui.tooling.preview.datasource.LoremIpsum
|
||||
import androidx.compose.ui.unit.dp
|
||||
import coil3.compose.AsyncImage
|
||||
import org.schabi.newpipe.R
|
||||
import org.schabi.newpipe.extractor.stream.StreamType
|
||||
import org.schabi.newpipe.ktx.popFirst
|
||||
import org.schabi.newpipe.ui.components.menu.LongPressAction.Type.EnqueueNext
|
||||
import org.schabi.newpipe.ui.components.menu.LongPressAction.Type.ShowChannelDetails
|
||||
@ -441,7 +442,9 @@ fun getSubtitleAnnotatedString(
|
||||
append(uploadDate)
|
||||
}
|
||||
|
||||
val viewCount = item.viewCount?.let { Localization.localizeViewCount(ctx, it) }
|
||||
val viewCount = item.viewCount?.let {
|
||||
Localization.localizeViewCount(ctx, true, item.streamType, it)
|
||||
}
|
||||
if (!viewCount.isNullOrBlank()) {
|
||||
if (shouldAddSeparator) {
|
||||
append(Localization.DOT_SEPARATOR)
|
||||
@ -545,6 +548,7 @@ private class LongPressablePreviews : CollectionPreviewParameterProvider<LongPre
|
||||
uploader = "Blender",
|
||||
uploaderUrl = "https://www.youtube.com/@BlenderOfficial",
|
||||
viewCount = 8765432,
|
||||
streamType = null,
|
||||
uploadDate = Either.left("16 years ago"),
|
||||
decoration = LongPressable.Decoration.Playlist(12),
|
||||
),
|
||||
@ -555,6 +559,7 @@ private class LongPressablePreviews : CollectionPreviewParameterProvider<LongPre
|
||||
uploader = "Blender",
|
||||
uploaderUrl = "https://www.youtube.com/@BlenderOfficial",
|
||||
viewCount = 8765432,
|
||||
streamType = StreamType.VIDEO_STREAM,
|
||||
uploadDate = Either.left("16 years ago"),
|
||||
decoration = LongPressable.Decoration.Duration(500),
|
||||
),
|
||||
@ -565,6 +570,7 @@ private class LongPressablePreviews : CollectionPreviewParameterProvider<LongPre
|
||||
uploader = null,
|
||||
uploaderUrl = "https://www.youtube.com/@BlenderOfficial",
|
||||
viewCount = null,
|
||||
streamType = null,
|
||||
uploadDate = null,
|
||||
decoration = null,
|
||||
),
|
||||
@ -575,6 +581,7 @@ private class LongPressablePreviews : CollectionPreviewParameterProvider<LongPre
|
||||
uploader = null,
|
||||
uploaderUrl = null,
|
||||
viewCount = null,
|
||||
streamType = StreamType.AUDIO_STREAM,
|
||||
uploadDate = null,
|
||||
decoration = LongPressable.Decoration.Duration(500),
|
||||
),
|
||||
@ -585,6 +592,7 @@ private class LongPressablePreviews : CollectionPreviewParameterProvider<LongPre
|
||||
uploader = null,
|
||||
uploaderUrl = null,
|
||||
viewCount = null,
|
||||
streamType = StreamType.LIVE_STREAM,
|
||||
uploadDate = null,
|
||||
decoration = LongPressable.Decoration.Live,
|
||||
),
|
||||
@ -595,6 +603,7 @@ private class LongPressablePreviews : CollectionPreviewParameterProvider<LongPre
|
||||
uploader = null,
|
||||
uploaderUrl = null,
|
||||
viewCount = null,
|
||||
streamType = StreamType.AUDIO_LIVE_STREAM,
|
||||
uploadDate = Either.right(OffsetDateTime.now().minusSeconds(12)),
|
||||
decoration = LongPressable.Decoration.Playlist(1500),
|
||||
),
|
||||
|
||||
@ -23,6 +23,7 @@ data class LongPressable(
|
||||
val uploader: String?,
|
||||
val uploaderUrl: String?,
|
||||
val viewCount: Long?,
|
||||
val streamType: StreamType?, // only used to format the view count properly
|
||||
val uploadDate: Either<String, OffsetDateTime>?,
|
||||
val decoration: Decoration?,
|
||||
) {
|
||||
@ -50,6 +51,7 @@ data class LongPressable(
|
||||
uploader = item.uploaderName?.takeIf { it.isNotBlank() },
|
||||
uploaderUrl = item.uploaderUrl?.takeIf { it.isNotBlank() },
|
||||
viewCount = item.viewCount.takeIf { it >= 0 },
|
||||
streamType = item.streamType,
|
||||
uploadDate = item.uploadDate?.let { Either.right(it.offsetDateTime()) }
|
||||
?: item.textualUploadDate?.let { Either.left(it) },
|
||||
decoration = Decoration.from(item.streamType, item.duration),
|
||||
@ -63,6 +65,7 @@ data class LongPressable(
|
||||
uploader = item.uploader.takeIf { it.isNotBlank() },
|
||||
uploaderUrl = item.uploaderUrl?.takeIf { it.isNotBlank() },
|
||||
viewCount = item.viewCount?.takeIf { it >= 0 },
|
||||
streamType = item.streamType,
|
||||
uploadDate = item.uploadDate?.let { Either.right(it) }
|
||||
?: item.textualUploadDate?.let { Either.left(it) },
|
||||
decoration = Decoration.from(item.streamType, item.duration),
|
||||
@ -77,6 +80,7 @@ data class LongPressable(
|
||||
uploader = null,
|
||||
uploaderUrl = null,
|
||||
viewCount = null,
|
||||
streamType = null,
|
||||
uploadDate = null,
|
||||
decoration = Decoration.Playlist(item.streamCount),
|
||||
)
|
||||
@ -89,6 +93,7 @@ data class LongPressable(
|
||||
uploader = item.uploader,
|
||||
uploaderUrl = null,
|
||||
viewCount = null,
|
||||
streamType = null,
|
||||
uploadDate = null,
|
||||
decoration = Decoration.Playlist(
|
||||
item.streamCount ?: ListExtractor.ITEM_COUNT_UNKNOWN
|
||||
@ -103,6 +108,7 @@ data class LongPressable(
|
||||
uploader = null,
|
||||
uploaderUrl = item.url?.takeIf { it.isNotBlank() },
|
||||
viewCount = null,
|
||||
streamType = null,
|
||||
uploadDate = null,
|
||||
decoration = null,
|
||||
)
|
||||
@ -115,6 +121,7 @@ data class LongPressable(
|
||||
uploader = item.uploaderName.takeIf { it.isNotBlank() },
|
||||
uploaderUrl = item.uploaderUrl?.takeIf { it.isNotBlank() },
|
||||
viewCount = null,
|
||||
streamType = null,
|
||||
uploadDate = null,
|
||||
decoration = Decoration.Playlist(item.streamCount),
|
||||
)
|
||||
|
||||
@ -31,6 +31,7 @@ import org.schabi.newpipe.extractor.localization.ContentCountry;
|
||||
import org.schabi.newpipe.extractor.localization.DateWrapper;
|
||||
import org.schabi.newpipe.extractor.stream.AudioStream;
|
||||
import org.schabi.newpipe.extractor.stream.AudioTrackType;
|
||||
import org.schabi.newpipe.extractor.stream.StreamType;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import java.math.RoundingMode;
|
||||
@ -183,9 +184,50 @@ public final class Localization {
|
||||
return context.getString(R.string.upload_date_text, formatDate(offsetDateTime));
|
||||
}
|
||||
|
||||
public static String localizeViewCount(@NonNull final Context context, final long viewCount) {
|
||||
/**
|
||||
* Localizes the number of views of a stream reported by the service,
|
||||
* with different words based on the stream type.
|
||||
*
|
||||
* @param context the Android context
|
||||
* @param shortForm whether the number of views should be formatted in a short approximated form
|
||||
* @param streamType influences the accompanying text, i.e. views/watching/listening
|
||||
* @param viewCount the number of views reported by the service to localize
|
||||
* @return the formatted and localized view count
|
||||
*/
|
||||
public static String localizeViewCount(@NonNull final Context context,
|
||||
final boolean shortForm,
|
||||
@Nullable final StreamType streamType,
|
||||
final long viewCount) {
|
||||
final String localizedNumber;
|
||||
if (shortForm) {
|
||||
localizedNumber = shortCount(context, viewCount);
|
||||
} else {
|
||||
localizedNumber = localizeNumber(viewCount);
|
||||
}
|
||||
|
||||
if (streamType == StreamType.AUDIO_LIVE_STREAM) {
|
||||
return getQuantity(context, R.plurals.listening, R.string.no_one_listening, viewCount,
|
||||
localizedNumber);
|
||||
} else if (streamType == StreamType.LIVE_STREAM) {
|
||||
return getQuantity(context, R.plurals.watching, R.string.no_one_watching, viewCount,
|
||||
localizedNumber);
|
||||
} else {
|
||||
return getQuantity(context, R.plurals.views, R.string.no_views, viewCount,
|
||||
localizedNumber);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Localizes the number of times the user watched a video that they have in the history.
|
||||
*
|
||||
* @param context the Android context
|
||||
* @param viewCount the number of times (stored in the database) the user watched a video
|
||||
* @return the formatted and localized watch count
|
||||
*/
|
||||
public static String localizeWatchCount(@NonNull final Context context,
|
||||
final long viewCount) {
|
||||
return getQuantity(context, R.plurals.views, R.string.no_views, viewCount,
|
||||
localizeNumber(viewCount));
|
||||
shortCount(context, viewCount));
|
||||
}
|
||||
|
||||
public static String localizeStreamCount(@NonNull final Context context,
|
||||
@ -217,12 +259,6 @@ public final class Localization {
|
||||
}
|
||||
}
|
||||
|
||||
public static String localizeWatchingCount(@NonNull final Context context,
|
||||
final long watchingCount) {
|
||||
return getQuantity(context, R.plurals.watching, R.string.no_one_watching, watchingCount,
|
||||
localizeNumber(watchingCount));
|
||||
}
|
||||
|
||||
public static String shortCount(@NonNull final Context context, final long count) {
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
|
||||
return CompactDecimalFormat.getInstance(getAppLocale(),
|
||||
@ -250,22 +286,6 @@ public final class Localization {
|
||||
}
|
||||
}
|
||||
|
||||
public static String listeningCount(@NonNull final Context context, final long listeningCount) {
|
||||
return getQuantity(context, R.plurals.listening, R.string.no_one_listening, listeningCount,
|
||||
shortCount(context, listeningCount));
|
||||
}
|
||||
|
||||
public static String shortWatchingCount(@NonNull final Context context,
|
||||
final long watchingCount) {
|
||||
return getQuantity(context, R.plurals.watching, R.string.no_one_watching, watchingCount,
|
||||
shortCount(context, watchingCount));
|
||||
}
|
||||
|
||||
public static String shortViewCount(@NonNull final Context context, final long viewCount) {
|
||||
return getQuantity(context, R.plurals.views, R.string.no_views, viewCount,
|
||||
shortCount(context, viewCount));
|
||||
}
|
||||
|
||||
public static String shortSubscriberCount(@NonNull final Context context,
|
||||
final long subscriberCount) {
|
||||
return getQuantity(context, R.plurals.subscribers, R.string.no_subscribers, subscriberCount,
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user