amethyst/app/src/main/java/com/vitorpamplona/amethyst/ui/screen/FeedViewModel.kt

123 wiersze
4.3 KiB
Kotlin
Czysty Zwykły widok Historia

2023-01-11 18:31:20 +00:00
package com.vitorpamplona.amethyst.ui.screen
import android.util.Log
2023-01-11 18:31:20 +00:00
import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope
import com.vitorpamplona.amethyst.model.LocalCache
import com.vitorpamplona.amethyst.model.LocalCacheState
import com.vitorpamplona.amethyst.model.Note
2023-01-18 23:59:18 +00:00
import com.vitorpamplona.amethyst.service.NostrChannelDataSource
import com.vitorpamplona.amethyst.service.NostrChatRoomDataSource
import com.vitorpamplona.amethyst.service.NostrChatroomListDataSource
2023-01-11 18:31:20 +00:00
import com.vitorpamplona.amethyst.service.NostrDataSource
2023-01-18 23:59:18 +00:00
import com.vitorpamplona.amethyst.service.NostrGlobalDataSource
import com.vitorpamplona.amethyst.service.NostrHomeDataSource
import com.vitorpamplona.amethyst.service.NostrThreadDataSource
import com.vitorpamplona.amethyst.service.NostrUserProfileDataSource
2023-01-18 19:24:04 +00:00
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.Job
2023-01-11 18:31:20 +00:00
import kotlinx.coroutines.cancel
import kotlinx.coroutines.delay
2023-01-11 18:31:20 +00:00
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.asStateFlow
import kotlinx.coroutines.flow.update
import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext
2023-01-11 18:31:20 +00:00
2023-01-18 23:59:18 +00:00
class NostrChannelFeedViewModel: FeedViewModel(NostrChannelDataSource)
class NostrChatRoomFeedViewModel: FeedViewModel(NostrChatRoomDataSource)
class NostrHomeFeedViewModel: FeedViewModel(NostrHomeDataSource)
class NostrGlobalFeedViewModel: FeedViewModel(NostrGlobalDataSource)
class NostrThreadFeedViewModel: FeedViewModel(NostrThreadDataSource)
class NostrUserProfileFeedViewModel: FeedViewModel(NostrUserProfileDataSource)
2023-01-11 18:31:20 +00:00
2023-01-21 15:31:23 +00:00
class NostrChatroomListKnownFeedViewModel: FeedViewModel(NostrChatroomListDataSource) {
override fun newListFromDataSource(): List<Note> {
// Filter: all channels + PMs the account has replied to
return super.newListFromDataSource().filter {
val me = NostrChatroomListDataSource.account.userProfile()
it.channel != null || me.messages[it.author]?.firstOrNull { me == it.author } != null
}
}
}
class NostrChatroomListNewFeedViewModel: FeedViewModel(NostrChatroomListDataSource) {
override fun newListFromDataSource(): List<Note> {
// Filter: no channels + PMs the account has never replied to
return super.newListFromDataSource().filter {
val me = NostrChatroomListDataSource.account.userProfile()
it.channel == null && me.messages[it.author]?.firstOrNull { me == it.author } == null
}
}
}
2023-01-18 23:59:18 +00:00
abstract class FeedViewModel(val dataSource: NostrDataSource<Note>): ViewModel() {
2023-01-11 18:31:20 +00:00
private val _feedContent = MutableStateFlow<FeedState>(FeedState.Loading)
val feedContent = _feedContent.asStateFlow()
2023-01-21 15:31:23 +00:00
open fun newListFromDataSource(): List<Note> {
return dataSource.loadTop()
}
fun hardRefresh() {
dataSource.resetFilters()
}
2023-01-11 18:31:20 +00:00
fun refresh() {
viewModelScope.launch(Dispatchers.Default) {
2023-01-21 15:31:23 +00:00
val notes = newListFromDataSource()
val oldNotesState = feedContent.value
if (oldNotesState is FeedState.Loaded) {
if (notes != oldNotesState.feed) {
withContext(Dispatchers.Main) {
updateFeed(notes)
}
}
} else {
withContext(Dispatchers.Main) {
updateFeed(notes)
}
}
2023-01-11 18:31:20 +00:00
}
}
fun updateFeed(notes: List<Note>) {
if (notes.isEmpty()) {
_feedContent.update { FeedState.Empty }
} else {
_feedContent.update { FeedState.Loaded(notes) }
2023-01-11 18:31:20 +00:00
}
}
var handlerWaiting = false
fun invalidateData() {
synchronized(handlerWaiting) {
if (handlerWaiting) return
handlerWaiting = true
val scope = CoroutineScope(Job() + Dispatchers.Default)
scope.launch {
delay(100)
refresh()
handlerWaiting = false
}
}
}
2023-01-11 18:31:20 +00:00
private val cacheListener: (LocalCacheState) -> Unit = {
invalidateData()
2023-01-11 18:31:20 +00:00
}
init {
LocalCache.live.observeForever(cacheListener)
}
override fun onCleared() {
LocalCache.live.removeObserver(cacheListener)
dataSource.stop()
viewModelScope.cancel()
super.onCleared()
}
}