Skip to content

Commit a240aed

Browse files
committed
Implement live chat polling in CommentsViewModel
1 parent 9c3b4dc commit a240aed

1 file changed

Lines changed: 58 additions & 5 deletions

File tree

Lines changed: 58 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,44 +1,97 @@
11
package org.schabi.newpipe.viewmodels
22

3+
import android.util.Log
34
import androidx.lifecycle.SavedStateHandle
45
import androidx.lifecycle.ViewModel
56
import androidx.lifecycle.viewModelScope
67
import androidx.paging.Pager
78
import androidx.paging.PagingConfig
9+
import androidx.paging.PagingData
810
import androidx.paging.cachedIn
911
import kotlinx.coroutines.Dispatchers
1012
import kotlinx.coroutines.ExperimentalCoroutinesApi
13+
import kotlinx.coroutines.delay
14+
import kotlinx.coroutines.flow.Flow
1115
import kotlinx.coroutines.flow.SharingStarted
1216
import kotlinx.coroutines.flow.filterIsInstance
1317
import kotlinx.coroutines.flow.flatMapLatest
18+
import kotlinx.coroutines.flow.flow
1419
import kotlinx.coroutines.flow.flowOn
1520
import kotlinx.coroutines.flow.map
1621
import kotlinx.coroutines.flow.stateIn
22+
import org.schabi.newpipe.extractor.NewPipe
1723
import org.schabi.newpipe.extractor.comments.CommentsInfo
24+
import org.schabi.newpipe.extractor.comments.CommentsInfoItem
1825
import org.schabi.newpipe.paging.CommentsSource
1926
import org.schabi.newpipe.ui.components.video.comment.CommentInfo
2027
import org.schabi.newpipe.util.KEY_URL
2128
import org.schabi.newpipe.viewmodels.util.Resource
2229

2330
class CommentsViewModel(savedStateHandle: SavedStateHandle) : ViewModel() {
31+
companion object {
32+
private const val TAG = "CommentsViewModel"
33+
}
34+
2435
val uiState = savedStateHandle.getStateFlow(KEY_URL, "")
2536
.map {
2637
try {
27-
Resource.Success(CommentInfo(CommentsInfo.getInfo(it)))
38+
val info = CommentsInfo.getInfo(it)
39+
Log.i(
40+
TAG,
41+
"Loaded CommentsInfo: disabled=${info.isCommentsDisabled}, " +
42+
"liveChat=${info.isLiveChat}, items=${info.relatedItems.size}, " +
43+
"nextPage=${info.nextPage != null}"
44+
)
45+
Resource.Success(CommentInfo(info))
2846
} catch (e: Exception) {
47+
Log.e(TAG, "Failed to load comments", e)
2948
Resource.Error(e)
3049
}
3150
}
3251
.flowOn(Dispatchers.IO)
3352
.stateIn(viewModelScope, SharingStarted.WhileSubscribed(), Resource.Loading)
3453

54+
// Live chat via PagingData (broken approach)
3555
@OptIn(ExperimentalCoroutinesApi::class)
36-
val comments = uiState
56+
val comments: Flow<PagingData<CommentsInfoItem>> = uiState
3757
.filterIsInstance<Resource.Success<CommentInfo>>()
3858
.flatMapLatest {
39-
Pager(PagingConfig(pageSize = 20, enablePlaceholders = false)) {
40-
CommentsSource(it.data)
41-
}.flow
59+
val info = it.data
60+
Log.i(TAG, "flatMapLatest: isLiveChat=${info.isLiveChat}, items=${info.comments.size}")
61+
if (info.isLiveChat) {
62+
liveChatPagingData(info)
63+
} else {
64+
Pager(PagingConfig(pageSize = 20, enablePlaceholders = false)) {
65+
CommentsSource(info)
66+
}.flow
67+
}
4268
}
4369
.cachedIn(viewModelScope)
70+
71+
private fun liveChatPagingData(info: CommentInfo): Flow<PagingData<CommentsInfoItem>> = flow {
72+
val allItems = info.comments.toMutableList()
73+
emit(PagingData.from(allItems))
74+
var nextPage = info.nextPage
75+
while (true) {
76+
delay(3000)
77+
if (nextPage == null) {
78+
Log.d(TAG, "liveChatPolling: nextPage is null, skipping")
79+
continue
80+
}
81+
try {
82+
Log.d(TAG, "liveChatPolling: fetching more items...")
83+
val result = CommentsInfo.getMoreItems(
84+
NewPipe.getService(info.serviceId),
85+
info.url,
86+
nextPage
87+
)
88+
Log.i(TAG, "liveChatPolling: fetched ${result.items.size} items")
89+
allItems.addAll(result.items)
90+
emit(PagingData.from(allItems))
91+
nextPage = result.nextPage
92+
} catch (e: Exception) {
93+
Log.e(TAG, "liveChatPolling: failed to fetch more items", e)
94+
}
95+
}
96+
}
4497
}

0 commit comments

Comments
 (0)