More Performant UpdateFollows
This commit is contained in:
@@ -17,6 +17,7 @@ import kotlinx.coroutines.delay
|
|||||||
import kotlinx.coroutines.launch
|
import kotlinx.coroutines.launch
|
||||||
import com.vitorpamplona.amethyst.service.relays.Relay
|
import com.vitorpamplona.amethyst.service.relays.Relay
|
||||||
import java.util.Date
|
import java.util.Date
|
||||||
|
import java.util.concurrent.atomic.AtomicBoolean
|
||||||
import java.util.regex.Matcher
|
import java.util.regex.Matcher
|
||||||
import java.util.regex.Pattern
|
import java.util.regex.Pattern
|
||||||
import nostr.postr.events.Event
|
import nostr.postr.events.Event
|
||||||
@@ -194,17 +195,19 @@ class Note(val idHex: String) {
|
|||||||
|
|
||||||
class NoteLiveData(val note: Note): LiveData<NoteState>(NoteState(note)) {
|
class NoteLiveData(val note: Note): LiveData<NoteState>(NoteState(note)) {
|
||||||
// Refreshes observers in batches.
|
// Refreshes observers in batches.
|
||||||
var handlerWaiting = false
|
var handlerWaiting = AtomicBoolean()
|
||||||
|
|
||||||
@Synchronized
|
@Synchronized
|
||||||
fun invalidateData() {
|
fun invalidateData() {
|
||||||
if (handlerWaiting) return
|
if (!hasActiveObservers()) return
|
||||||
|
if (handlerWaiting.getAndSet(true)) return
|
||||||
|
|
||||||
handlerWaiting = true
|
handlerWaiting.set(true)
|
||||||
val scope = CoroutineScope(Job() + Dispatchers.Default)
|
val scope = CoroutineScope(Job() + Dispatchers.Main)
|
||||||
scope.launch {
|
scope.launch {
|
||||||
delay(100)
|
delay(100)
|
||||||
refresh()
|
refresh()
|
||||||
handlerWaiting = false
|
handlerWaiting.set(false)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -10,6 +10,9 @@ import com.vitorpamplona.amethyst.ui.note.toShortenHex
|
|||||||
import fr.acinq.secp256k1.Hex
|
import fr.acinq.secp256k1.Hex
|
||||||
import java.util.Collections
|
import java.util.Collections
|
||||||
import java.util.concurrent.ConcurrentHashMap
|
import java.util.concurrent.ConcurrentHashMap
|
||||||
|
import java.util.concurrent.atomic.AtomicBoolean
|
||||||
|
import kotlin.time.ExperimentalTime
|
||||||
|
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
|
||||||
@@ -81,7 +84,11 @@ class User(val pubkeyHex: String) {
|
|||||||
liveFollows.invalidateData()
|
liveFollows.invalidateData()
|
||||||
user.liveFollows.invalidateData()
|
user.liveFollows.invalidateData()
|
||||||
|
|
||||||
listeners.forEach {
|
updateSubscribers {
|
||||||
|
it.onFollowsChange()
|
||||||
|
}
|
||||||
|
|
||||||
|
user.updateSubscribers {
|
||||||
it.onFollowsChange()
|
it.onFollowsChange()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -95,6 +102,40 @@ class User(val pubkeyHex: String) {
|
|||||||
updateSubscribers {
|
updateSubscribers {
|
||||||
it.onFollowsChange()
|
it.onFollowsChange()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
user.updateSubscribers {
|
||||||
|
it.onFollowsChange()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun follow(users: Set<User>, followedAt: Long) {
|
||||||
|
follows = follows + users
|
||||||
|
users.forEach {
|
||||||
|
it.followers = it.followers + this
|
||||||
|
it.liveFollows.invalidateData()
|
||||||
|
it.updateSubscribers {
|
||||||
|
it.onFollowsChange()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
liveFollows.invalidateData()
|
||||||
|
updateSubscribers {
|
||||||
|
it.onFollowsChange()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
fun unfollow(users: Set<User>) {
|
||||||
|
follows = follows - users
|
||||||
|
users.forEach {
|
||||||
|
it.followers = it.followers - this
|
||||||
|
it.liveFollows.invalidateData()
|
||||||
|
it.updateSubscribers {
|
||||||
|
it.onFollowsChange()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
liveFollows.invalidateData()
|
||||||
|
updateSubscribers {
|
||||||
|
it.onFollowsChange()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fun addTaggedPost(note: Note) {
|
fun addTaggedPost(note: Note) {
|
||||||
@@ -169,12 +210,8 @@ class User(val pubkeyHex: String) {
|
|||||||
val toBeAdded = newFollows - follows
|
val toBeAdded = newFollows - follows
|
||||||
val toBeRemoved = follows - newFollows
|
val toBeRemoved = follows - newFollows
|
||||||
|
|
||||||
toBeAdded.forEach {
|
follow(toBeAdded, updateAt)
|
||||||
follow(it, updateAt)
|
unfollow(toBeRemoved)
|
||||||
}
|
|
||||||
toBeRemoved.forEach {
|
|
||||||
unfollow(it)
|
|
||||||
}
|
|
||||||
|
|
||||||
updatedFollowsAt = updateAt
|
updatedFollowsAt = updateAt
|
||||||
}
|
}
|
||||||
@@ -239,19 +276,20 @@ class User(val pubkeyHex: String) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Refreshes observers in batches.
|
// Refreshes observers in batches.
|
||||||
var modelHandlerWaiting = false
|
var modelHandlerWaiting = AtomicBoolean()
|
||||||
|
|
||||||
@Synchronized
|
@Synchronized
|
||||||
fun updateSubscribers(on: (Listener) -> Unit) {
|
fun updateSubscribers(on: (Listener) -> Unit) {
|
||||||
if (modelHandlerWaiting) return
|
if (modelHandlerWaiting.getAndSet(true)) return
|
||||||
|
|
||||||
modelHandlerWaiting = true
|
modelHandlerWaiting.set(true)
|
||||||
val scope = CoroutineScope(Job() + Dispatchers.Default)
|
val scope = CoroutineScope(Job() + Dispatchers.Default)
|
||||||
scope.launch {
|
scope.launch {
|
||||||
delay(100)
|
delay(100)
|
||||||
listeners.forEach {
|
listeners.forEach {
|
||||||
on(it)
|
on(it)
|
||||||
}
|
}
|
||||||
modelHandlerWaiting = false
|
modelHandlerWaiting.set(false)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -292,17 +330,19 @@ class UserMetadata {
|
|||||||
class UserLiveData(val user: User): LiveData<UserState>(UserState(user)) {
|
class UserLiveData(val user: User): LiveData<UserState>(UserState(user)) {
|
||||||
|
|
||||||
// Refreshes observers in batches.
|
// Refreshes observers in batches.
|
||||||
var handlerWaiting = false
|
var handlerWaiting = AtomicBoolean()
|
||||||
|
|
||||||
@Synchronized
|
@Synchronized
|
||||||
fun invalidateData() {
|
fun invalidateData() {
|
||||||
if (handlerWaiting) return
|
if (!hasActiveObservers()) return
|
||||||
|
if (handlerWaiting.getAndSet(true)) return
|
||||||
|
|
||||||
handlerWaiting = true
|
handlerWaiting.set(true)
|
||||||
val scope = CoroutineScope(Job() + Dispatchers.Main)
|
val scope = CoroutineScope(Job() + Dispatchers.Main)
|
||||||
scope.launch {
|
scope.launch {
|
||||||
delay(100)
|
delay(100)
|
||||||
refresh()
|
refresh()
|
||||||
handlerWaiting = false
|
handlerWaiting.set(false)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user