2023-01-11 18:31:20 +00:00
|
|
|
package com.vitorpamplona.amethyst.ui.screen
|
|
|
|
|
2023-01-27 22:28:59 +00:00
|
|
|
import androidx.compose.runtime.mutableStateOf
|
2023-01-11 18:31:20 +00:00
|
|
|
import androidx.lifecycle.ViewModel
|
|
|
|
import com.vitorpamplona.amethyst.model.LocalCache
|
|
|
|
import com.vitorpamplona.amethyst.model.LocalCacheState
|
|
|
|
import com.vitorpamplona.amethyst.model.Note
|
2023-02-18 18:06:53 +00:00
|
|
|
import com.vitorpamplona.amethyst.ui.dal.ChannelFeedFilter
|
|
|
|
import com.vitorpamplona.amethyst.ui.dal.ChatroomFeedFilter
|
|
|
|
import com.vitorpamplona.amethyst.ui.dal.ChatroomListKnownFeedFilter
|
|
|
|
import com.vitorpamplona.amethyst.ui.dal.ChatroomListNewFeedFilter
|
|
|
|
import com.vitorpamplona.amethyst.ui.dal.FeedFilter
|
|
|
|
import com.vitorpamplona.amethyst.ui.dal.GlobalFeedFilter
|
2023-03-15 21:02:49 +00:00
|
|
|
import com.vitorpamplona.amethyst.ui.dal.HashtagFeedFilter
|
2023-02-18 18:06:53 +00:00
|
|
|
import com.vitorpamplona.amethyst.ui.dal.HomeConversationsFeedFilter
|
|
|
|
import com.vitorpamplona.amethyst.ui.dal.HomeNewThreadFeedFilter
|
|
|
|
import com.vitorpamplona.amethyst.ui.dal.ThreadFeedFilter
|
2023-02-19 16:34:45 +00:00
|
|
|
import com.vitorpamplona.amethyst.ui.dal.UserProfileConversationsFeedFilter
|
|
|
|
import com.vitorpamplona.amethyst.ui.dal.UserProfileNewThreadFeedFilter
|
2023-02-19 00:20:39 +00:00
|
|
|
import com.vitorpamplona.amethyst.ui.dal.UserProfileReportsFeedFilter
|
2023-01-18 19:24:04 +00:00
|
|
|
import kotlinx.coroutines.CoroutineScope
|
|
|
|
import kotlinx.coroutines.Dispatchers
|
|
|
|
import kotlinx.coroutines.Job
|
2023-02-19 00:04:03 +00:00
|
|
|
import kotlinx.coroutines.NonCancellable
|
2023-01-19 13:41:48 +00:00
|
|
|
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
|
2023-02-19 00:04:03 +00:00
|
|
|
import kotlinx.coroutines.withContext
|
2023-03-07 18:46:44 +00:00
|
|
|
import java.util.concurrent.atomic.AtomicBoolean
|
2023-01-11 18:31:20 +00:00
|
|
|
|
2023-03-07 18:46:44 +00:00
|
|
|
class NostrChannelFeedViewModel : FeedViewModel(ChannelFeedFilter)
|
|
|
|
class NostrChatRoomFeedViewModel : FeedViewModel(ChatroomFeedFilter)
|
|
|
|
class NostrGlobalFeedViewModel : FeedViewModel(GlobalFeedFilter)
|
|
|
|
class NostrThreadFeedViewModel : FeedViewModel(ThreadFeedFilter)
|
2023-03-15 21:02:49 +00:00
|
|
|
class NostrHashtagFeedViewModel : FeedViewModel(HashtagFeedFilter)
|
2023-03-07 18:46:44 +00:00
|
|
|
class NostrUserProfileNewThreadsFeedViewModel : FeedViewModel(UserProfileNewThreadFeedFilter)
|
|
|
|
class NostrUserProfileConversationsFeedViewModel : FeedViewModel(UserProfileConversationsFeedFilter)
|
|
|
|
class NostrUserProfileReportFeedViewModel : FeedViewModel(UserProfileReportsFeedFilter)
|
|
|
|
class NostrChatroomListKnownFeedViewModel : FeedViewModel(ChatroomListKnownFeedFilter)
|
|
|
|
class NostrChatroomListNewFeedViewModel : FeedViewModel(ChatroomListNewFeedFilter)
|
|
|
|
class NostrHomeFeedViewModel : FeedViewModel(HomeNewThreadFeedFilter)
|
|
|
|
class NostrHomeRepliesFeedViewModel : FeedViewModel(HomeConversationsFeedFilter)
|
2023-01-25 02:28:34 +00:00
|
|
|
|
2023-03-07 18:46:44 +00:00
|
|
|
abstract class FeedViewModel(val localFilter: FeedFilter<Note>) : ViewModel() {
|
2023-01-11 18:31:20 +00:00
|
|
|
private val _feedContent = MutableStateFlow<FeedState>(FeedState.Loading)
|
|
|
|
val feedContent = _feedContent.asStateFlow()
|
|
|
|
|
2023-02-19 00:20:39 +00:00
|
|
|
fun newListFromDataSource(): List<Note> {
|
2023-02-18 18:06:53 +00:00
|
|
|
return localFilter.loadTop()
|
2023-01-21 16:37:57 +00:00
|
|
|
}
|
|
|
|
|
2023-01-11 18:31:20 +00:00
|
|
|
fun refresh() {
|
2023-02-14 16:01:08 +00:00
|
|
|
val scope = CoroutineScope(Job() + Dispatchers.Default)
|
|
|
|
scope.launch {
|
|
|
|
refreshSuspended()
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
fun refreshSuspended() {
|
|
|
|
val notes = newListFromDataSource()
|
|
|
|
|
|
|
|
val oldNotesState = feedContent.value
|
|
|
|
if (oldNotesState is FeedState.Loaded) {
|
2023-02-14 17:08:35 +00:00
|
|
|
// Using size as a proxy for has changed.
|
2023-03-04 00:40:26 +00:00
|
|
|
if (notes != oldNotesState.feed.value) {
|
2023-02-14 16:01:08 +00:00
|
|
|
updateFeed(notes)
|
2023-03-04 00:40:26 +00:00
|
|
|
}
|
2023-02-14 16:01:08 +00:00
|
|
|
} else {
|
|
|
|
updateFeed(notes)
|
2023-01-11 18:31:20 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2023-02-05 05:41:37 +00:00
|
|
|
private fun updateFeed(notes: List<Note>) {
|
2023-02-14 16:01:08 +00:00
|
|
|
val scope = CoroutineScope(Job() + Dispatchers.Main)
|
|
|
|
scope.launch {
|
|
|
|
val currentState = feedContent.value
|
|
|
|
if (notes.isEmpty()) {
|
|
|
|
_feedContent.update { FeedState.Empty }
|
|
|
|
} else if (currentState is FeedState.Loaded) {
|
|
|
|
// updates the current list
|
|
|
|
currentState.feed.value = notes
|
|
|
|
} else {
|
|
|
|
_feedContent.update { FeedState.Loaded(mutableStateOf(notes)) }
|
|
|
|
}
|
2023-01-11 18:31:20 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2023-02-05 05:41:37 +00:00
|
|
|
private var handlerWaiting = AtomicBoolean()
|
2023-03-01 01:10:52 +00:00
|
|
|
|
2023-02-18 18:06:53 +00:00
|
|
|
fun invalidateData() {
|
2023-02-06 23:15:37 +00:00
|
|
|
if (handlerWaiting.getAndSet(true)) return
|
|
|
|
|
|
|
|
val scope = CoroutineScope(Job() + Dispatchers.Default)
|
|
|
|
scope.launch {
|
2023-02-19 00:04:03 +00:00
|
|
|
try {
|
|
|
|
delay(50)
|
2023-03-02 14:34:42 +00:00
|
|
|
// adds the time to perform the refresh into this delay
|
|
|
|
// holding off new updates in case of heavy refresh routines.
|
|
|
|
refreshSuspended()
|
2023-02-19 00:04:03 +00:00
|
|
|
} finally {
|
|
|
|
withContext(NonCancellable) {
|
|
|
|
handlerWaiting.set(false)
|
|
|
|
}
|
|
|
|
}
|
2023-02-06 23:15:37 +00:00
|
|
|
}
|
2023-01-18 20:30:39 +00:00
|
|
|
}
|
|
|
|
|
2023-01-11 18:31:20 +00:00
|
|
|
private val cacheListener: (LocalCacheState) -> Unit = {
|
2023-01-18 20:30:39 +00:00
|
|
|
invalidateData()
|
2023-01-11 18:31:20 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
init {
|
|
|
|
LocalCache.live.observeForever(cacheListener)
|
|
|
|
}
|
|
|
|
|
|
|
|
override fun onCleared() {
|
|
|
|
LocalCache.live.removeObserver(cacheListener)
|
|
|
|
super.onCleared()
|
|
|
|
}
|
2023-03-07 18:46:44 +00:00
|
|
|
}
|