mirror of
https://github.com/vitorpamplona/amethyst.git
synced 2025-09-28 22:43:16 +02:00
Moving away from handlers and into coroutines.
This commit is contained in:
@@ -13,6 +13,7 @@ import java.util.Collections
|
|||||||
import kotlinx.coroutines.CoroutineScope
|
import kotlinx.coroutines.CoroutineScope
|
||||||
import kotlinx.coroutines.Dispatchers
|
import kotlinx.coroutines.Dispatchers
|
||||||
import kotlinx.coroutines.Job
|
import kotlinx.coroutines.Job
|
||||||
|
import kotlinx.coroutines.delay
|
||||||
import kotlinx.coroutines.launch
|
import kotlinx.coroutines.launch
|
||||||
import nostr.postr.events.Event
|
import nostr.postr.events.Event
|
||||||
|
|
||||||
@@ -99,17 +100,18 @@ class Note(val idHex: String) {
|
|||||||
val live: NoteLiveData = NoteLiveData(this)
|
val live: NoteLiveData = NoteLiveData(this)
|
||||||
|
|
||||||
// Refreshes observers in batches.
|
// Refreshes observers in batches.
|
||||||
val filterHandler = Handler(Looper.getMainLooper())
|
val scope = CoroutineScope(Job() + Dispatchers.Main)
|
||||||
var handlerWaiting = false
|
var handlerWaiting = false
|
||||||
@Synchronized
|
@Synchronized
|
||||||
fun invalidateData() {
|
fun invalidateData() {
|
||||||
if (handlerWaiting) return
|
if (handlerWaiting) return
|
||||||
|
|
||||||
handlerWaiting = true
|
handlerWaiting = true
|
||||||
filterHandler.postDelayed({
|
scope.launch {
|
||||||
|
delay(100)
|
||||||
live.refresh()
|
live.refresh()
|
||||||
handlerWaiting = false
|
handlerWaiting = false
|
||||||
}, 100)
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -120,19 +122,13 @@ class NoteLiveData(val note: Note): LiveData<NoteState>(NoteState(note)) {
|
|||||||
|
|
||||||
override fun onActive() {
|
override fun onActive() {
|
||||||
super.onActive()
|
super.onActive()
|
||||||
val scope = CoroutineScope(Job() + Dispatchers.Main)
|
|
||||||
scope.launch {
|
|
||||||
NostrSingleEventDataSource.add(note.idHex)
|
NostrSingleEventDataSource.add(note.idHex)
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
override fun onInactive() {
|
override fun onInactive() {
|
||||||
super.onInactive()
|
super.onInactive()
|
||||||
val scope = CoroutineScope(Job() + Dispatchers.Main)
|
|
||||||
scope.launch {
|
|
||||||
NostrSingleEventDataSource.remove(note.idHex)
|
NostrSingleEventDataSource.remove(note.idHex)
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
class NoteState(val note: Note)
|
class NoteState(val note: Note)
|
||||||
|
@@ -22,7 +22,7 @@ object UrlCachedPreviewer {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
val scope = CoroutineScope(Job() + Dispatchers.Main)
|
val scope = CoroutineScope(Job() + Dispatchers.IO)
|
||||||
scope.launch {
|
scope.launch {
|
||||||
BahaUrlPreview(url, object : IUrlPreviewCallback {
|
BahaUrlPreview(url, object : IUrlPreviewCallback {
|
||||||
override fun onComplete(urlInfo: UrlInfoItem) {
|
override fun onComplete(urlInfo: UrlInfoItem) {
|
||||||
|
@@ -11,6 +11,7 @@ import java.util.concurrent.ConcurrentHashMap
|
|||||||
import kotlinx.coroutines.CoroutineScope
|
import kotlinx.coroutines.CoroutineScope
|
||||||
import kotlinx.coroutines.Dispatchers
|
import kotlinx.coroutines.Dispatchers
|
||||||
import kotlinx.coroutines.Job
|
import kotlinx.coroutines.Job
|
||||||
|
import kotlinx.coroutines.delay
|
||||||
import kotlinx.coroutines.launch
|
import kotlinx.coroutines.launch
|
||||||
import nostr.postr.events.ContactListEvent
|
import nostr.postr.events.ContactListEvent
|
||||||
|
|
||||||
@@ -112,18 +113,18 @@ class User(val pubkey: ByteArray) {
|
|||||||
val live: UserLiveData = UserLiveData(this)
|
val live: UserLiveData = UserLiveData(this)
|
||||||
|
|
||||||
// Refreshes observers in batches.
|
// Refreshes observers in batches.
|
||||||
val filterHandler = Handler(Looper.getMainLooper())
|
val scope = CoroutineScope(Job() + Dispatchers.Main)
|
||||||
var handlerWaiting = false
|
var handlerWaiting = false
|
||||||
@Synchronized
|
@Synchronized
|
||||||
fun invalidateData() {
|
fun invalidateData() {
|
||||||
if (handlerWaiting) return
|
if (handlerWaiting) return
|
||||||
|
|
||||||
handlerWaiting = true
|
handlerWaiting = true
|
||||||
filterHandler.postDelayed({
|
scope.launch {
|
||||||
println("User Refresh")
|
delay(100)
|
||||||
live.refresh()
|
live.refresh()
|
||||||
handlerWaiting = false
|
handlerWaiting = false
|
||||||
}, 100)
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -153,25 +154,19 @@ class UserMetadata {
|
|||||||
}
|
}
|
||||||
|
|
||||||
class UserLiveData(val user: User): LiveData<UserState>(UserState(user)) {
|
class UserLiveData(val user: User): LiveData<UserState>(UserState(user)) {
|
||||||
val scope = CoroutineScope(Job() + Dispatchers.Main)
|
|
||||||
|
|
||||||
fun refresh() {
|
fun refresh() {
|
||||||
postValue(UserState(user))
|
postValue(UserState(user))
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onActive() {
|
override fun onActive() {
|
||||||
super.onActive()
|
super.onActive()
|
||||||
scope.launch {
|
|
||||||
NostrSingleUserDataSource.add(user.pubkeyHex)
|
NostrSingleUserDataSource.add(user.pubkeyHex)
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
override fun onInactive() {
|
override fun onInactive() {
|
||||||
super.onInactive()
|
super.onInactive()
|
||||||
scope.launch {
|
|
||||||
NostrSingleUserDataSource.remove(user.pubkeyHex)
|
NostrSingleUserDataSource.remove(user.pubkeyHex)
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
class UserState(val user: User)
|
class UserState(val user: User)
|
||||||
|
@@ -41,7 +41,7 @@ object NostrAccountDataSource: NostrDataSource<Note>("AccountData") {
|
|||||||
return JsonFilter(
|
return JsonFilter(
|
||||||
kinds = listOf(MetadataEvent.kind),
|
kinds = listOf(MetadataEvent.kind),
|
||||||
authors = listOf(account.userProfile().pubkeyHex),
|
authors = listOf(account.userProfile().pubkeyHex),
|
||||||
limit = 1
|
limit = 3
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -20,6 +20,7 @@ import kotlin.time.measureTimedValue
|
|||||||
import kotlinx.coroutines.CoroutineScope
|
import kotlinx.coroutines.CoroutineScope
|
||||||
import kotlinx.coroutines.Dispatchers
|
import kotlinx.coroutines.Dispatchers
|
||||||
import kotlinx.coroutines.Job
|
import kotlinx.coroutines.Job
|
||||||
|
import kotlinx.coroutines.delay
|
||||||
import kotlinx.coroutines.launch
|
import kotlinx.coroutines.launch
|
||||||
import nostr.postr.events.ContactListEvent
|
import nostr.postr.events.ContactListEvent
|
||||||
import nostr.postr.events.DeletionEvent
|
import nostr.postr.events.DeletionEvent
|
||||||
@@ -118,7 +119,7 @@ abstract class NostrDataSource<T>(val debugName: String) {
|
|||||||
val returningList = feed().take(100)
|
val returningList = feed().take(100)
|
||||||
|
|
||||||
// prepare previews
|
// prepare previews
|
||||||
val scope = CoroutineScope(Job() + Dispatchers.Main)
|
val scope = CoroutineScope(Job() + Dispatchers.IO)
|
||||||
scope.launch {
|
scope.launch {
|
||||||
loadPreviews(returningList)
|
loadPreviews(returningList)
|
||||||
}
|
}
|
||||||
@@ -147,17 +148,18 @@ abstract class NostrDataSource<T>(val debugName: String) {
|
|||||||
channelIds.remove(channel.id)
|
channelIds.remove(channel.id)
|
||||||
}
|
}
|
||||||
|
|
||||||
val filterHandler = Handler(Looper.getMainLooper())
|
val scope = CoroutineScope(Job() + Dispatchers.IO)
|
||||||
var handlerWaiting = false
|
var handlerWaiting = false
|
||||||
@Synchronized
|
@Synchronized
|
||||||
fun invalidateFilters() {
|
fun invalidateFilters() {
|
||||||
if (handlerWaiting) return
|
if (handlerWaiting) return
|
||||||
|
|
||||||
handlerWaiting = true
|
handlerWaiting = true
|
||||||
filterHandler.postDelayed({
|
scope.launch {
|
||||||
|
delay(200)
|
||||||
resetFilters()
|
resetFilters()
|
||||||
handlerWaiting = false
|
handlerWaiting = false
|
||||||
}, 200)
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fun resetFilters() {
|
fun resetFilters() {
|
||||||
|
@@ -16,7 +16,7 @@ object NostrSingleUserDataSource: NostrDataSource<Note>("SingleUserFeed") {
|
|||||||
JsonFilter(
|
JsonFilter(
|
||||||
kinds = listOf(MetadataEvent.kind),
|
kinds = listOf(MetadataEvent.kind),
|
||||||
authors = listOf(it.substring(0, 8)),
|
authors = listOf(it.substring(0, 8)),
|
||||||
limit = 1
|
limit = 10
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -49,7 +49,10 @@ fun DrawerContent(navController: NavHostController,
|
|||||||
accountViewModel: AccountViewModel,
|
accountViewModel: AccountViewModel,
|
||||||
accountStateViewModel: AccountStateViewModel) {
|
accountStateViewModel: AccountStateViewModel) {
|
||||||
|
|
||||||
val accountUserState by accountViewModel.userLiveData.observeAsState()
|
val accountState by accountViewModel.accountLiveData.observeAsState()
|
||||||
|
val account = accountState?.account ?: return
|
||||||
|
|
||||||
|
val accountUserState by account.userProfile().live.observeAsState()
|
||||||
val accountUser = accountUserState?.user
|
val accountUser = accountUserState?.user
|
||||||
|
|
||||||
Surface(
|
Surface(
|
||||||
@@ -64,14 +67,18 @@ fun DrawerContent(navController: NavHostController,
|
|||||||
model = banner,
|
model = banner,
|
||||||
contentDescription = "Profile Image",
|
contentDescription = "Profile Image",
|
||||||
contentScale = ContentScale.FillWidth,
|
contentScale = ContentScale.FillWidth,
|
||||||
modifier = Modifier.fillMaxWidth().height(150.dp)
|
modifier = Modifier
|
||||||
|
.fillMaxWidth()
|
||||||
|
.height(150.dp)
|
||||||
)
|
)
|
||||||
} else {
|
} else {
|
||||||
Image(
|
Image(
|
||||||
painter = painterResource(R.drawable.profile_banner),
|
painter = painterResource(R.drawable.profile_banner),
|
||||||
contentDescription = "Profile Banner",
|
contentDescription = "Profile Banner",
|
||||||
contentScale = ContentScale.FillWidth,
|
contentScale = ContentScale.FillWidth,
|
||||||
modifier = Modifier.fillMaxWidth().height(150.dp)
|
modifier = Modifier
|
||||||
|
.fillMaxWidth()
|
||||||
|
.height(150.dp)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -106,12 +113,15 @@ fun DrawerContent(navController: NavHostController,
|
|||||||
fun ProfileContent(accountUser: User?, modifier: Modifier = Modifier, scaffoldState: ScaffoldState, navController: NavController) {
|
fun ProfileContent(accountUser: User?, modifier: Modifier = Modifier, scaffoldState: ScaffoldState, navController: NavController) {
|
||||||
val coroutineScope = rememberCoroutineScope()
|
val coroutineScope = rememberCoroutineScope()
|
||||||
|
|
||||||
|
println("AAA " + accountUser?.profilePicture())
|
||||||
|
|
||||||
Column(modifier = modifier) {
|
Column(modifier = modifier) {
|
||||||
AsyncImage(
|
AsyncImage(
|
||||||
model = accountUser?.profilePicture() ?: "https://robohash.org/ohno.png",
|
model = accountUser?.profilePicture() ?: "https://robohash.org/ohno.png",
|
||||||
contentDescription = "Profile Image",
|
contentDescription = "Profile Image",
|
||||||
modifier = Modifier
|
modifier = Modifier
|
||||||
.width(100.dp).height(100.dp)
|
.width(100.dp)
|
||||||
|
.height(100.dp)
|
||||||
.clip(shape = CircleShape)
|
.clip(shape = CircleShape)
|
||||||
.border(3.dp, MaterialTheme.colors.background, CircleShape)
|
.border(3.dp, MaterialTheme.colors.background, CircleShape)
|
||||||
.background(MaterialTheme.colors.background)
|
.background(MaterialTheme.colors.background)
|
||||||
@@ -205,7 +215,8 @@ fun NavigationRow(navController: NavHostController, scaffoldState: ScaffoldState
|
|||||||
})
|
})
|
||||||
) {
|
) {
|
||||||
Row(
|
Row(
|
||||||
modifier = Modifier.fillMaxWidth()
|
modifier = Modifier
|
||||||
|
.fillMaxWidth()
|
||||||
.padding(vertical = 15.dp, horizontal = 25.dp),
|
.padding(vertical = 15.dp, horizontal = 25.dp),
|
||||||
verticalAlignment = Alignment.CenterVertically
|
verticalAlignment = Alignment.CenterVertically
|
||||||
) {
|
) {
|
||||||
|
@@ -14,6 +14,7 @@ import kotlinx.coroutines.CoroutineScope
|
|||||||
import kotlinx.coroutines.Dispatchers
|
import kotlinx.coroutines.Dispatchers
|
||||||
import kotlinx.coroutines.Job
|
import kotlinx.coroutines.Job
|
||||||
import kotlinx.coroutines.cancel
|
import kotlinx.coroutines.cancel
|
||||||
|
import kotlinx.coroutines.delay
|
||||||
import kotlinx.coroutines.flow.MutableStateFlow
|
import kotlinx.coroutines.flow.MutableStateFlow
|
||||||
import kotlinx.coroutines.flow.asStateFlow
|
import kotlinx.coroutines.flow.asStateFlow
|
||||||
import kotlinx.coroutines.flow.update
|
import kotlinx.coroutines.flow.update
|
||||||
@@ -26,8 +27,13 @@ class CardFeedViewModel(val dataSource: NostrDataSource<Note>): ViewModel() {
|
|||||||
private var lastNotes: List<Note>? = null
|
private var lastNotes: List<Note>? = null
|
||||||
|
|
||||||
fun refresh() {
|
fun refresh() {
|
||||||
val scope = CoroutineScope(Job() + Dispatchers.Main)
|
val scope = CoroutineScope(Job() + Dispatchers.IO)
|
||||||
scope.launch {
|
scope.launch {
|
||||||
|
refreshSuspended()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun refreshSuspended() {
|
||||||
val notes = dataSource.loadTop()
|
val notes = dataSource.loadTop()
|
||||||
|
|
||||||
val lastNotesCopy = lastNotes
|
val lastNotesCopy = lastNotes
|
||||||
@@ -45,7 +51,6 @@ class CardFeedViewModel(val dataSource: NostrDataSource<Note>): ViewModel() {
|
|||||||
updateFeed(cards)
|
updateFeed(cards)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
private fun convertToCard(notes: List<Note>): List<Card> {
|
private fun convertToCard(notes: List<Note>): List<Card> {
|
||||||
val reactionsPerEvent = mutableMapOf<Note, MutableList<Note>>()
|
val reactionsPerEvent = mutableMapOf<Note, MutableList<Note>>()
|
||||||
@@ -76,31 +81,28 @@ class CardFeedViewModel(val dataSource: NostrDataSource<Note>): ViewModel() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fun updateFeed(notes: List<Card>) {
|
fun updateFeed(notes: List<Card>) {
|
||||||
|
val scope = CoroutineScope(Job() + Dispatchers.Main)
|
||||||
|
scope.launch {
|
||||||
if (notes.isEmpty()) {
|
if (notes.isEmpty()) {
|
||||||
_feedContent.update { CardFeedState.Empty }
|
_feedContent.update { CardFeedState.Empty }
|
||||||
} else {
|
} else {
|
||||||
_feedContent.update { CardFeedState.Loaded(notes) }
|
_feedContent.update { CardFeedState.Loaded(notes) }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fun refreshCurrentList() {
|
|
||||||
val state = feedContent.value
|
|
||||||
if (state is CardFeedState.Loaded) {
|
|
||||||
_feedContent.update { CardFeedState.Loaded(state.feed) }
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
val filterHandler = Handler(Looper.getMainLooper())
|
val scope = CoroutineScope(Job() + Dispatchers.IO)
|
||||||
var handlerWaiting = false
|
var handlerWaiting = false
|
||||||
@Synchronized
|
@Synchronized
|
||||||
fun invalidateData() {
|
fun invalidateData() {
|
||||||
if (handlerWaiting) return
|
if (handlerWaiting) return
|
||||||
|
|
||||||
handlerWaiting = true
|
handlerWaiting = true
|
||||||
filterHandler.postDelayed({
|
scope.launch {
|
||||||
|
delay(100)
|
||||||
refresh()
|
refresh()
|
||||||
handlerWaiting = false
|
handlerWaiting = false
|
||||||
}, 100)
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private val cacheListener: (LocalCacheState) -> Unit = {
|
private val cacheListener: (LocalCacheState) -> Unit = {
|
||||||
|
@@ -23,6 +23,7 @@ import kotlinx.coroutines.CoroutineScope
|
|||||||
import kotlinx.coroutines.Dispatchers
|
import kotlinx.coroutines.Dispatchers
|
||||||
import kotlinx.coroutines.Job
|
import kotlinx.coroutines.Job
|
||||||
import kotlinx.coroutines.cancel
|
import kotlinx.coroutines.cancel
|
||||||
|
import kotlinx.coroutines.delay
|
||||||
import kotlinx.coroutines.flow.MutableStateFlow
|
import kotlinx.coroutines.flow.MutableStateFlow
|
||||||
import kotlinx.coroutines.flow.asStateFlow
|
import kotlinx.coroutines.flow.asStateFlow
|
||||||
import kotlinx.coroutines.flow.update
|
import kotlinx.coroutines.flow.update
|
||||||
@@ -42,8 +43,13 @@ abstract class FeedViewModel(val dataSource: NostrDataSource<Note>): ViewModel()
|
|||||||
val feedContent = _feedContent.asStateFlow()
|
val feedContent = _feedContent.asStateFlow()
|
||||||
|
|
||||||
fun refresh() {
|
fun refresh() {
|
||||||
val scope = CoroutineScope(Job() + Dispatchers.Main)
|
val scope = CoroutineScope(Job() + Dispatchers.IO)
|
||||||
scope.launch {
|
scope.launch {
|
||||||
|
refreshSuspended()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun refreshSuspended() {
|
||||||
val notes = dataSource.loadTop()
|
val notes = dataSource.loadTop()
|
||||||
|
|
||||||
val oldNotesState = feedContent.value
|
val oldNotesState = feedContent.value
|
||||||
@@ -55,15 +61,17 @@ abstract class FeedViewModel(val dataSource: NostrDataSource<Note>): ViewModel()
|
|||||||
updateFeed(notes)
|
updateFeed(notes)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
fun updateFeed(notes: List<Note>) {
|
fun updateFeed(notes: List<Note>) {
|
||||||
|
val scope = CoroutineScope(Job() + Dispatchers.Main)
|
||||||
|
scope.launch {
|
||||||
if (notes.isEmpty()) {
|
if (notes.isEmpty()) {
|
||||||
_feedContent.update { FeedState.Empty }
|
_feedContent.update { FeedState.Empty }
|
||||||
} else {
|
} else {
|
||||||
_feedContent.update { FeedState.Loaded(notes) }
|
_feedContent.update { FeedState.Loaded(notes) }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fun refreshCurrentList() {
|
fun refreshCurrentList() {
|
||||||
val state = feedContent.value
|
val state = feedContent.value
|
||||||
@@ -72,17 +80,18 @@ abstract class FeedViewModel(val dataSource: NostrDataSource<Note>): ViewModel()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
val filterHandler = Handler(Looper.getMainLooper())
|
val scope = CoroutineScope(Job() + Dispatchers.IO)
|
||||||
var handlerWaiting = false
|
var handlerWaiting = false
|
||||||
@Synchronized
|
@Synchronized
|
||||||
fun invalidateData() {
|
fun invalidateData() {
|
||||||
if (handlerWaiting) return
|
if (handlerWaiting) return
|
||||||
|
|
||||||
handlerWaiting = true
|
handlerWaiting = true
|
||||||
filterHandler.postDelayed({
|
scope.launch {
|
||||||
|
delay(100)
|
||||||
refresh()
|
refresh()
|
||||||
handlerWaiting = false
|
handlerWaiting = false
|
||||||
}, 100)
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private val cacheListener: (LocalCacheState) -> Unit = {
|
private val cacheListener: (LocalCacheState) -> Unit = {
|
||||||
|
@@ -14,6 +14,7 @@ import kotlinx.coroutines.CoroutineScope
|
|||||||
import kotlinx.coroutines.Dispatchers
|
import kotlinx.coroutines.Dispatchers
|
||||||
import kotlinx.coroutines.Job
|
import kotlinx.coroutines.Job
|
||||||
import kotlinx.coroutines.cancel
|
import kotlinx.coroutines.cancel
|
||||||
|
import kotlinx.coroutines.delay
|
||||||
import kotlinx.coroutines.flow.MutableStateFlow
|
import kotlinx.coroutines.flow.MutableStateFlow
|
||||||
import kotlinx.coroutines.flow.asStateFlow
|
import kotlinx.coroutines.flow.asStateFlow
|
||||||
import kotlinx.coroutines.flow.update
|
import kotlinx.coroutines.flow.update
|
||||||
@@ -32,8 +33,13 @@ open class UserFeedViewModel(val dataSource: NostrDataSource<User>): ViewModel()
|
|||||||
val feedContent = _feedContent.asStateFlow()
|
val feedContent = _feedContent.asStateFlow()
|
||||||
|
|
||||||
fun refresh() {
|
fun refresh() {
|
||||||
val scope = CoroutineScope(Job() + Dispatchers.Main)
|
val scope = CoroutineScope(Job() + Dispatchers.IO)
|
||||||
scope.launch {
|
scope.launch {
|
||||||
|
refreshSuspended()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun refreshSuspended() {
|
||||||
val notes = dataSource.loadTop()
|
val notes = dataSource.loadTop()
|
||||||
|
|
||||||
val oldNotesState = feedContent.value
|
val oldNotesState = feedContent.value
|
||||||
@@ -45,15 +51,17 @@ open class UserFeedViewModel(val dataSource: NostrDataSource<User>): ViewModel()
|
|||||||
updateFeed(notes)
|
updateFeed(notes)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
fun updateFeed(notes: List<User>) {
|
fun updateFeed(notes: List<User>) {
|
||||||
|
val scope = CoroutineScope(Job() + Dispatchers.Main)
|
||||||
|
scope.launch {
|
||||||
if (notes.isEmpty()) {
|
if (notes.isEmpty()) {
|
||||||
_feedContent.update { UserFeedState.Empty }
|
_feedContent.update { UserFeedState.Empty }
|
||||||
} else {
|
} else {
|
||||||
_feedContent.update { UserFeedState.Loaded(notes) }
|
_feedContent.update { UserFeedState.Loaded(notes) }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fun refreshCurrentList() {
|
fun refreshCurrentList() {
|
||||||
val state = feedContent.value
|
val state = feedContent.value
|
||||||
@@ -62,17 +70,18 @@ open class UserFeedViewModel(val dataSource: NostrDataSource<User>): ViewModel()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
val filterHandler = Handler(Looper.getMainLooper())
|
val scope = CoroutineScope(Job() + Dispatchers.IO)
|
||||||
var handlerWaiting = false
|
var handlerWaiting = false
|
||||||
@Synchronized
|
@Synchronized
|
||||||
fun invalidateData() {
|
fun invalidateData() {
|
||||||
if (handlerWaiting) return
|
if (handlerWaiting) return
|
||||||
|
|
||||||
handlerWaiting = true
|
handlerWaiting = true
|
||||||
filterHandler.postDelayed({
|
scope.launch {
|
||||||
|
delay(100)
|
||||||
refresh()
|
refresh()
|
||||||
handlerWaiting = false
|
handlerWaiting = false
|
||||||
}, 100)
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private val cacheListener: (LocalCacheState) -> Unit = {
|
private val cacheListener: (LocalCacheState) -> Unit = {
|
||||||
|
Reference in New Issue
Block a user