vc=65: metadata consistency across ChannelScreen + SearchScreen rows

vc=64 fixed RelatedRow's empty-metadata bug. ChannelVideoRow and
ResultRow had the same shape problem AND duplicated duration:

- ChannelVideoRow: showed 'N views · 0:42' which doubled with
  the VideoThumbnail's bottom-right duration badge. Stripped
  the duration text, added uploadDateRelative. Now reads
  'N views · 2 days ago' matching YT's channel page format.
- ResultRow: same duplicate-duration. Same fix. Search results
  now show 'N views · 2 days ago' under the uploader line.

All four video-row composables (FeedRow, RelatedRow,
ChannelVideoRow, ResultRow) now use the same leading-separator
buildString pattern: 'piece [· piece]*' that gracefully composes
whatever fields are populated. No more empty metadata lines, no
more duplicate duration.
This commit is contained in:
Kayos 2026-05-26 13:09:23 -07:00
parent 944fbd4335
commit 7156208c3c
3 changed files with 36 additions and 20 deletions

View file

@ -55,6 +55,6 @@ const val NEWPIPE_APPLICATION_ID_NEW = "net.newpipe.app"
// vc=19 / 0.1.0-AE — rust pipeline cutover. Extraction via
// strawcore-core (Sulkta-Coop/strawcore) via the UniFFI wrapper; no
// NewPipeExtractor in the runtime path.
const val STRAW_VERSION_CODE = 64
const val STRAW_VERSION_NAME = "0.1.0-BX"
const val STRAW_VERSION_CODE = 65
const val STRAW_VERSION_NAME = "0.1.0-BY"
const val STRAW_APPLICATION_ID = "com.sulkta.straw"

View file

@ -205,14 +205,21 @@ private fun ChannelVideoRow(
overflow = TextOverflow.Ellipsis,
)
Spacer(modifier = Modifier.height(2.dp))
Text(
text = buildString {
// Don't repeat duration here — VideoThumbnail's
// bottom-right badge already shows it. Add the upload
// date so the row reads 'N views · 2 days ago' the way
// YT renders it. vc=65 — Cobb caught the duplicate
// duration + missing date on the channel page.
val meta = buildString {
if (item.viewCount > 0) append("${formatCount(item.viewCount)} views")
if (item.durationSeconds > 0) {
if (item.uploadDateRelative.isNotBlank()) {
if (isNotEmpty()) append(" · ")
append(formatDuration(item.durationSeconds))
append(item.uploadDateRelative)
}
},
}
if (meta.isNotEmpty()) {
Text(
text = meta,
style = MaterialTheme.typography.bodySmall,
color = MaterialTheme.colorScheme.onSurfaceVariant,
maxLines = 1,
@ -220,4 +227,5 @@ private fun ChannelVideoRow(
}
}
}
}

View file

@ -247,13 +247,21 @@ private fun ResultRow(
else
Modifier.padding(vertical = 4.dp),
)
if (item.viewCount > 0 || item.durationSeconds > 0) {
Text(
text = buildString {
// Drop the duration here — VideoThumbnail's badge already
// renders it on the bottom-right of the thumbnail. Add the
// upload date instead so search results read like YT's
// own format. vc=65 — caught with the
// channel-page + related-row consistency pass.
val meta = buildString {
if (item.viewCount > 0) append(formatViews(item.viewCount))
if (item.viewCount > 0 && item.durationSeconds > 0) append(" · ")
if (item.durationSeconds > 0) append(formatDuration(item.durationSeconds))
},
if (item.uploadDateRelative.isNotBlank()) {
if (isNotEmpty()) append(" · ")
append(item.uploadDateRelative)
}
}
if (meta.isNotEmpty()) {
Text(
text = meta,
style = MaterialTheme.typography.bodySmall,
color = MaterialTheme.colorScheme.onSurfaceVariant,
maxLines = 1,