channels: hide video-less channels, sort users by subscribers first
Video-less channels dropped out of the row build when the fast path switched to the video listing, and the previous commit wrongly merged the own empty channels back in — the user rule is the opposite: a channel (or a whole user row) with no videos renders at all; watching- only accounts must stay invisible. The own row only exists when the logged-in user owns at least one channel with videos. The ordering is now one rule on both levels — user rows by each row's channel sums, channels inside a row: subscribers, videos, views (desc). Settled order on the TV verified against the instance's real follower counts (kaylee 9, love 9, georg 6, yingfen 5, kinga 1 — georg's 211 videos only tie-break), with the own row first.
This commit is contained in:
parent
c0a7e94b14
commit
182650414c
1 changed files with 16 additions and 20 deletions
|
|
@ -75,10 +75,10 @@ import net.jeena.jtubetv.ui.screens.list.dpadCenterActivatable
|
||||||
/**
|
/**
|
||||||
* Channels, SmartTube-style: one row per LOCAL user.
|
* Channels, SmartTube-style: one row per LOCAL user.
|
||||||
*
|
*
|
||||||
* - Row 1: the logged-in user ("<display name>'s Channels"), then the other local
|
* - Row 1: the logged-in user ("<display name>'s Channels") — only when they own
|
||||||
* users sorted by videos / subscribers / plays (desc).
|
* at least one channel WITH videos; then the other local users, rows and
|
||||||
* - Each row: that user's channels, same ordering; channels with no videos simply
|
* channels alike sorted by subscribers / videos / views (desc).
|
||||||
* stay inside their user's row.
|
* - Channels with no videos never render (watching-only accounts), at any level.
|
||||||
* - Followed-instance channels at the end, grouped per platform.
|
* - Followed-instance channels at the end, grouped per platform.
|
||||||
*
|
*
|
||||||
* API limits (verified, PeerTube 8.3.1): the /video-channels and /accounts listings
|
* API limits (verified, PeerTube 8.3.1): the /video-channels and /accounts listings
|
||||||
|
|
@ -270,25 +270,20 @@ class ChannelsViewModel(private val store: TokenStore) : ViewModel() {
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun rebuildRowsInner(host: String?) {
|
private fun rebuildRowsInner(host: String?) {
|
||||||
val allLocals = allChannels.filter { it.host == host }
|
// Channels without videos don't exist on this screen: plenty of local
|
||||||
// The video-listing fast path cannot see channels with no videos at all —
|
// accounts are watching-only and their empty channels are pure noise if
|
||||||
// an account owning only such channels used to lose its row entirely
|
// rendered (user rule). This also covers the own row — it only renders
|
||||||
// (tvbot: the local tvbots channel exists, it just never uploaded). Merge
|
// when the logged-in user has at least one channel with videos, and the
|
||||||
// the logged-in user's own local channels in; the group sort below still
|
// group sort below still puts it first in that case.
|
||||||
// puts the own row first. The account-channels listing already carries
|
val locals = allChannels
|
||||||
// the full card shape (avatar/banners/followers), no extra calls.
|
.filter { it.host == host && statOf(it) > 0 }
|
||||||
var locals = allLocals
|
|
||||||
if (userChannels.isNotEmpty()) {
|
|
||||||
val missing = userChannels
|
|
||||||
.filter { it.host == host && allLocals.none { l -> l.name == it.name } }
|
|
||||||
if (missing.isNotEmpty()) locals = allLocals + missing
|
|
||||||
}
|
|
||||||
val ownNames = userChannels.map { c -> c.name }.toSet()
|
val ownNames = userChannels.map { c -> c.name }.toSet()
|
||||||
val byOwner = locals.groupBy { ownerKey(it) }
|
val byOwner = locals.groupBy { ownerKey(it) }
|
||||||
val groups = byOwner.values.map { row ->
|
val groups = byOwner.values.map { row ->
|
||||||
val sorted = row.sortedWith(
|
val sorted = row.sortedWith(
|
||||||
compareByDescending<VideoChannelDto> { statOf(it) }
|
// One ordering everywhere: subscribers, videos, views (desc).
|
||||||
.thenByDescending { it.followersCount }
|
compareByDescending<VideoChannelDto> { it.followersCount }
|
||||||
|
.thenByDescending { statOf(it) }
|
||||||
.thenByDescending { playsOf(it) },
|
.thenByDescending { playsOf(it) },
|
||||||
)
|
)
|
||||||
val own = row.firstOrNull { it.name in ownNames }
|
val own = row.firstOrNull { it.name in ownNames }
|
||||||
|
|
@ -301,8 +296,9 @@ class ChannelsViewModel(private val store: TokenStore) : ViewModel() {
|
||||||
}
|
}
|
||||||
userRows = groups.sortedWith(
|
userRows = groups.sortedWith(
|
||||||
compareByDescending<UserGroup> { g -> g.channels.any { it.name in ownNames } }
|
compareByDescending<UserGroup> { g -> g.channels.any { it.name in ownNames } }
|
||||||
|
.thenByDescending { g -> g.channels.sumOf { it.followersCount } }
|
||||||
.thenByDescending { g -> g.channels.sumOf { statsMap[it.name + "@" + it.host]?.videos ?: 0 } }
|
.thenByDescending { g -> g.channels.sumOf { statsMap[it.name + "@" + it.host]?.videos ?: 0 } }
|
||||||
.thenByDescending { g -> g.channels.sumOf { it.followersCount } },
|
.thenByDescending { g -> g.channels.sumOf { statsMap[it.name + "@" + it.host]?.plays ?: 0 } },
|
||||||
)
|
)
|
||||||
Log.w(
|
Log.w(
|
||||||
"JTube",
|
"JTube",
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue