mirror of
https://github.com/vitorpamplona/amethyst.git
synced 2024-09-29 16:30:49 +00:00
Capturing EOSE events and keeping messages within relay limits (10 subscriptions and 10 REQ events at a time)
This commit is contained in:
parent
fb73308995
commit
a82f260142
@ -51,7 +51,7 @@ class Note(val idHex: String) {
|
|||||||
this.mentions = mentions
|
this.mentions = mentions
|
||||||
this.replyTo = replyTo
|
this.replyTo = replyTo
|
||||||
|
|
||||||
invalidateData(live)
|
live.invalidateData()
|
||||||
}
|
}
|
||||||
|
|
||||||
fun formattedDateTime(timestamp: Long): String {
|
fun formattedDateTime(timestamp: Long): String {
|
||||||
@ -83,22 +83,22 @@ class Note(val idHex: String) {
|
|||||||
|
|
||||||
fun addReply(note: Note) {
|
fun addReply(note: Note) {
|
||||||
if (replies.add(note))
|
if (replies.add(note))
|
||||||
invalidateData(liveReplies)
|
liveReplies.invalidateData()
|
||||||
}
|
}
|
||||||
|
|
||||||
fun addBoost(note: Note) {
|
fun addBoost(note: Note) {
|
||||||
if (boosts.add(note))
|
if (boosts.add(note))
|
||||||
invalidateData(liveBoosts)
|
liveBoosts.invalidateData()
|
||||||
}
|
}
|
||||||
|
|
||||||
fun addReaction(note: Note) {
|
fun addReaction(note: Note) {
|
||||||
if (reactions.add(note))
|
if (reactions.add(note))
|
||||||
invalidateData(liveReactions)
|
liveReactions.invalidateData()
|
||||||
}
|
}
|
||||||
|
|
||||||
fun addReport(note: Note) {
|
fun addReport(note: Note) {
|
||||||
if (reports.add(note))
|
if (reports.add(note))
|
||||||
invalidateData(liveReports)
|
liveReports.invalidateData()
|
||||||
}
|
}
|
||||||
|
|
||||||
fun isReactedBy(user: User): Boolean {
|
fun isReactedBy(user: User): Boolean {
|
||||||
@ -155,24 +155,24 @@ class Note(val idHex: String) {
|
|||||||
val liveBoosts: NoteLiveData = NoteLiveData(this)
|
val liveBoosts: NoteLiveData = NoteLiveData(this)
|
||||||
val liveReplies: NoteLiveData = NoteLiveData(this)
|
val liveReplies: NoteLiveData = NoteLiveData(this)
|
||||||
val liveReports: NoteLiveData = NoteLiveData(this)
|
val liveReports: NoteLiveData = NoteLiveData(this)
|
||||||
|
}
|
||||||
|
|
||||||
|
class NoteLiveData(val note: Note): LiveData<NoteState>(NoteState(note)) {
|
||||||
// Refreshes observers in batches.
|
// Refreshes observers in batches.
|
||||||
var handlerWaiting = false
|
var handlerWaiting = false
|
||||||
@Synchronized
|
@Synchronized
|
||||||
fun invalidateData(live: NoteLiveData) {
|
fun invalidateData() {
|
||||||
if (handlerWaiting) return
|
if (handlerWaiting) return
|
||||||
|
|
||||||
handlerWaiting = true
|
handlerWaiting = true
|
||||||
val scope = CoroutineScope(Job() + Dispatchers.Default)
|
val scope = CoroutineScope(Job() + Dispatchers.Default)
|
||||||
scope.launch {
|
scope.launch {
|
||||||
delay(100)
|
delay(100)
|
||||||
live.refresh()
|
refresh()
|
||||||
handlerWaiting = false
|
handlerWaiting = false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
class NoteLiveData(val note: Note): LiveData<NoteState>(NoteState(note)) {
|
|
||||||
fun refresh() {
|
fun refresh() {
|
||||||
postValue(NoteState(note))
|
postValue(NoteState(note))
|
||||||
}
|
}
|
||||||
|
@ -43,6 +43,9 @@ class User(val pubkeyHex: String) {
|
|||||||
val reports = Collections.synchronizedSet(mutableSetOf<Note>())
|
val reports = Collections.synchronizedSet(mutableSetOf<Note>())
|
||||||
val relaysBeingUsed = Collections.synchronizedMap(mutableMapOf<String, RelayInfo>())
|
val relaysBeingUsed = Collections.synchronizedMap(mutableMapOf<String, RelayInfo>())
|
||||||
|
|
||||||
|
var latestMetadataRequestEOSE: Long? = null
|
||||||
|
var latestReportRequestEOSE: Long? = null
|
||||||
|
|
||||||
fun toBestDisplayName(): String {
|
fun toBestDisplayName(): String {
|
||||||
return bestDisplayName() ?: bestUsername() ?: pubkeyDisplayHex
|
return bestDisplayName() ?: bestUsername() ?: pubkeyDisplayHex
|
||||||
}
|
}
|
||||||
@ -64,8 +67,8 @@ class User(val pubkeyHex: String) {
|
|||||||
follows.add(user)
|
follows.add(user)
|
||||||
user.followers.add(this)
|
user.followers.add(this)
|
||||||
|
|
||||||
invalidateData(liveFollows)
|
liveFollows.invalidateData()
|
||||||
user.invalidateData(liveFollows)
|
user.liveFollows.invalidateData()
|
||||||
|
|
||||||
listeners.forEach {
|
listeners.forEach {
|
||||||
it.onFollowsChange()
|
it.onFollowsChange()
|
||||||
@ -75,8 +78,8 @@ class User(val pubkeyHex: String) {
|
|||||||
follows.remove(user)
|
follows.remove(user)
|
||||||
user.followers.remove(this)
|
user.followers.remove(this)
|
||||||
|
|
||||||
invalidateData(liveFollows)
|
liveFollows.invalidateData()
|
||||||
user.invalidateData(liveFollows)
|
user.liveFollows.invalidateData()
|
||||||
|
|
||||||
updateSubscribers {
|
updateSubscribers {
|
||||||
it.onFollowsChange()
|
it.onFollowsChange()
|
||||||
@ -91,7 +94,7 @@ class User(val pubkeyHex: String) {
|
|||||||
fun addReport(note: Note) {
|
fun addReport(note: Note) {
|
||||||
if (reports.add(note)) {
|
if (reports.add(note)) {
|
||||||
updateSubscribers { it.onNewReports() }
|
updateSubscribers { it.onNewReports() }
|
||||||
invalidateData(liveReports)
|
liveReports.invalidateData()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -118,7 +121,7 @@ class User(val pubkeyHex: String) {
|
|||||||
|
|
||||||
fun addMessage(user: User, msg: Note) {
|
fun addMessage(user: User, msg: Note) {
|
||||||
getOrCreateChannel(user).add(msg)
|
getOrCreateChannel(user).add(msg)
|
||||||
invalidateData(liveMessages)
|
liveMessages.invalidateData()
|
||||||
updateSubscribers { it.onNewMessage() }
|
updateSubscribers { it.onNewMessage() }
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -140,7 +143,7 @@ class User(val pubkeyHex: String) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
updateSubscribers { it.onNewRelayInfo() }
|
updateSubscribers { it.onNewRelayInfo() }
|
||||||
invalidateData(liveRelayInfo)
|
liveRelayInfo.invalidateData()
|
||||||
}
|
}
|
||||||
|
|
||||||
fun updateFollows(newFollows: Set<User>, updateAt: Long) {
|
fun updateFollows(newFollows: Set<User>, updateAt: Long) {
|
||||||
@ -168,14 +171,14 @@ class User(val pubkeyHex: String) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
invalidateData(liveRelays)
|
liveRelays.invalidateData()
|
||||||
}
|
}
|
||||||
|
|
||||||
fun updateUserInfo(newUserInfo: UserMetadata, updateAt: Long) {
|
fun updateUserInfo(newUserInfo: UserMetadata, updateAt: Long) {
|
||||||
info = newUserInfo
|
info = newUserInfo
|
||||||
updatedMetadataAt = updateAt
|
updatedMetadataAt = updateAt
|
||||||
|
|
||||||
invalidateData(liveMetadata)
|
liveMetadata.invalidateData()
|
||||||
}
|
}
|
||||||
|
|
||||||
fun isFollowing(user: User): Boolean {
|
fun isFollowing(user: User): Boolean {
|
||||||
@ -248,21 +251,6 @@ class User(val pubkeyHex: String) {
|
|||||||
val liveRelays: UserLiveData = UserLiveData(this)
|
val liveRelays: UserLiveData = UserLiveData(this)
|
||||||
val liveRelayInfo: UserLiveData = UserLiveData(this)
|
val liveRelayInfo: UserLiveData = UserLiveData(this)
|
||||||
val liveMetadata: UserLiveData = UserLiveData(this)
|
val liveMetadata: UserLiveData = UserLiveData(this)
|
||||||
|
|
||||||
// Refreshes observers in batches.
|
|
||||||
var handlerWaiting = false
|
|
||||||
@Synchronized
|
|
||||||
fun invalidateData(live: UserLiveData) {
|
|
||||||
if (handlerWaiting) return
|
|
||||||
|
|
||||||
handlerWaiting = true
|
|
||||||
val scope = CoroutineScope(Job() + Dispatchers.Main)
|
|
||||||
scope.launch {
|
|
||||||
delay(100)
|
|
||||||
live.refresh()
|
|
||||||
handlerWaiting = false
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
class UserMetadata {
|
class UserMetadata {
|
||||||
@ -291,7 +279,23 @@ class UserMetadata {
|
|||||||
}
|
}
|
||||||
|
|
||||||
class UserLiveData(val user: User): LiveData<UserState>(UserState(user)) {
|
class UserLiveData(val user: User): LiveData<UserState>(UserState(user)) {
|
||||||
fun refresh() {
|
|
||||||
|
// Refreshes observers in batches.
|
||||||
|
var handlerWaiting = false
|
||||||
|
@Synchronized
|
||||||
|
fun invalidateData() {
|
||||||
|
if (handlerWaiting) return
|
||||||
|
|
||||||
|
handlerWaiting = true
|
||||||
|
val scope = CoroutineScope(Job() + Dispatchers.Main)
|
||||||
|
scope.launch {
|
||||||
|
delay(100)
|
||||||
|
refresh()
|
||||||
|
handlerWaiting = false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun refresh() {
|
||||||
postValue(UserState(user))
|
postValue(UserState(user))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -4,12 +4,12 @@ import java.util.UUID
|
|||||||
import nostr.postr.JsonFilter
|
import nostr.postr.JsonFilter
|
||||||
|
|
||||||
data class Channel (
|
data class Channel (
|
||||||
val id: String = UUID.randomUUID().toString().substring(0,4)
|
val id: String = UUID.randomUUID().toString().substring(0,4),
|
||||||
|
val onEOSE: ((Long) -> Unit)? = null
|
||||||
) {
|
) {
|
||||||
var filter: List<JsonFilter>? = null // Inactive when null
|
var filter: List<JsonFilter>? = null // Inactive when null
|
||||||
private var lastEOSE: Long? = null
|
|
||||||
|
|
||||||
fun updateEOSE(l: Long) {
|
fun updateEOSE(l: Long) {
|
||||||
lastEOSE = l
|
onEOSE?.let { it(l) }
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -17,7 +17,7 @@ object NostrAccountDataSource: NostrDataSource<Note>("AccountData") {
|
|||||||
return JsonFilter(
|
return JsonFilter(
|
||||||
kinds = listOf(ContactListEvent.kind),
|
kinds = listOf(ContactListEvent.kind),
|
||||||
authors = listOf(account.userProfile().pubkeyHex),
|
authors = listOf(account.userProfile().pubkeyHex),
|
||||||
limit = 5
|
limit = 1
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -25,12 +25,16 @@ 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 = 5
|
limit = 1
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
val accountMetadataChannel = requestNewChannel()
|
fun createNotificationFilter() = JsonFilter(
|
||||||
val accountContactListChannel = requestNewChannel()
|
tags = mapOf("p" to listOf(account.userProfile().pubkeyHex)),
|
||||||
|
limit = 100
|
||||||
|
)
|
||||||
|
|
||||||
|
val accountChannel = requestNewChannel()
|
||||||
|
|
||||||
override fun feed(): List<Note> {
|
override fun feed(): List<Note> {
|
||||||
val user = account.userProfile()
|
val user = account.userProfile()
|
||||||
@ -49,10 +53,10 @@ object NostrAccountDataSource: NostrDataSource<Note>("AccountData") {
|
|||||||
|
|
||||||
override fun updateChannelFilters() {
|
override fun updateChannelFilters() {
|
||||||
// gets everthing about the user logged in
|
// gets everthing about the user logged in
|
||||||
val newAccountMetadataFilter = createAccountMetadataFilter()
|
accountChannel.filter = listOf(
|
||||||
accountMetadataChannel.filter = listOf(newAccountMetadataFilter).ifEmpty { null }
|
createAccountMetadataFilter(),
|
||||||
|
createAccountContactListFilter(),
|
||||||
val newAccountContactListEvent = createAccountContactListFilter()
|
createNotificationFilter()
|
||||||
accountContactListChannel.filter = listOf(newAccountContactListEvent).ifEmpty { null }
|
).ifEmpty { null }
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -28,8 +28,7 @@ object NostrChatRoomDataSource: NostrDataSource<Note>("ChatroomFeed") {
|
|||||||
tags = withUser?.let { mapOf("p" to listOf(it.pubkeyHex)) }
|
tags = withUser?.let { mapOf("p" to listOf(it.pubkeyHex)) }
|
||||||
)
|
)
|
||||||
|
|
||||||
val incomingChannel = requestNewChannel()
|
val inandoutChannel = requestNewChannel()
|
||||||
val outgoingChannel = requestNewChannel()
|
|
||||||
|
|
||||||
// returns the last Note of each user.
|
// returns the last Note of each user.
|
||||||
override fun feed(): List<Note> {
|
override fun feed(): List<Note> {
|
||||||
@ -43,7 +42,6 @@ object NostrChatRoomDataSource: NostrDataSource<Note>("ChatroomFeed") {
|
|||||||
}
|
}
|
||||||
|
|
||||||
override fun updateChannelFilters() {
|
override fun updateChannelFilters() {
|
||||||
incomingChannel.filter = listOf(createMessagesToMeFilter()).ifEmpty { null }
|
inandoutChannel.filter = listOf(createMessagesToMeFilter(), createMessagesFromMeFilter()).ifEmpty { null }
|
||||||
outgoingChannel.filter = listOf(createMessagesFromMeFilter()).ifEmpty { null }
|
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -52,14 +52,7 @@ object NostrChatroomListDataSource: NostrDataSource<Note>("MailBoxFeed") {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
val incomingChannel = requestNewChannel()
|
val chatroomListChannel = requestNewChannel()
|
||||||
val outgoingChannel = requestNewChannel()
|
|
||||||
|
|
||||||
val myChannelsChannel = requestNewChannel()
|
|
||||||
val myChannelsInfoChannel = requestNewChannel()
|
|
||||||
val myChannelsMessagesChannel = requestNewChannel()
|
|
||||||
|
|
||||||
val myChannelsCreatedbyMeChannel = requestNewChannel()
|
|
||||||
|
|
||||||
// returns the last Note of each user.
|
// returns the last Note of each user.
|
||||||
override fun feed(): List<Note> {
|
override fun feed(): List<Note> {
|
||||||
@ -85,12 +78,16 @@ object NostrChatroomListDataSource: NostrDataSource<Note>("MailBoxFeed") {
|
|||||||
}
|
}
|
||||||
|
|
||||||
override fun updateChannelFilters() {
|
override fun updateChannelFilters() {
|
||||||
incomingChannel.filter = listOf(createMessagesToMeFilter()).ifEmpty { null }
|
val list = listOf(
|
||||||
outgoingChannel.filter = listOf(createMessagesFromMeFilter()).ifEmpty { null }
|
createMessagesToMeFilter(),
|
||||||
myChannelsChannel.filter = listOf(createMyChannelsFilter()).ifEmpty { null }
|
createMessagesFromMeFilter(),
|
||||||
myChannelsInfoChannel.filter = createLastChannelInfoFilter().ifEmpty { null }
|
createMyChannelsFilter()
|
||||||
myChannelsMessagesChannel.filter = createLastMessageOfEachChannelFilter().ifEmpty { null }
|
)
|
||||||
|
|
||||||
//myChannelsCreatedbyMeChannel.filter = listOf(createChannelsCreatedbyMeFilter()).ifEmpty { null }
|
chatroomListChannel.filter = listOfNotNull(
|
||||||
|
list,
|
||||||
|
createLastChannelInfoFilter(),
|
||||||
|
createLastMessageOfEachChannelFilter()
|
||||||
|
).flatten().ifEmpty { null }
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -2,6 +2,7 @@ package com.vitorpamplona.amethyst.service
|
|||||||
|
|
||||||
import android.os.Handler
|
import android.os.Handler
|
||||||
import android.os.Looper
|
import android.os.Looper
|
||||||
|
import android.util.Log
|
||||||
import com.vitorpamplona.amethyst.model.LocalCache
|
import com.vitorpamplona.amethyst.model.LocalCache
|
||||||
import com.vitorpamplona.amethyst.model.Note
|
import com.vitorpamplona.amethyst.model.Note
|
||||||
import com.vitorpamplona.amethyst.model.UrlCachedPreviewer
|
import com.vitorpamplona.amethyst.model.UrlCachedPreviewer
|
||||||
@ -88,7 +89,7 @@ abstract class NostrDataSource<T>(val debugName: String) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
override fun onError(error: Error, subscriptionId: String, relay: Relay) {
|
override fun onError(error: Error, subscriptionId: String, relay: Relay) {
|
||||||
//Log.e("ERROR", "Relay ${relay.url}: ${error.message}")
|
Log.e("ERROR", "Relay ${relay.url}: ${error.message}")
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onRelayStateChange(type: Relay.Type, relay: Relay, channel: String?) {
|
override fun onRelayStateChange(type: Relay.Type, relay: Relay, channel: String?) {
|
||||||
@ -145,8 +146,8 @@ abstract class NostrDataSource<T>(val debugName: String) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fun requestNewChannel(): Channel {
|
fun requestNewChannel(onEOSE: ((Long) -> Unit)? = null): Channel {
|
||||||
val newChannel = Channel(debugName+UUID.randomUUID().toString().substring(0,4))
|
val newChannel = Channel(debugName+UUID.randomUUID().toString().substring(0,4), onEOSE)
|
||||||
channels.add(newChannel)
|
channels.add(newChannel)
|
||||||
channelIds.add(newChannel.id)
|
channelIds.add(newChannel.id)
|
||||||
return newChannel
|
return newChannel
|
||||||
|
@ -4,11 +4,7 @@ import com.vitorpamplona.amethyst.model.Account
|
|||||||
import com.vitorpamplona.amethyst.model.LocalCache
|
import com.vitorpamplona.amethyst.model.LocalCache
|
||||||
import com.vitorpamplona.amethyst.model.Note
|
import com.vitorpamplona.amethyst.model.Note
|
||||||
import com.vitorpamplona.amethyst.model.User
|
import com.vitorpamplona.amethyst.model.User
|
||||||
import com.vitorpamplona.amethyst.model.UserState
|
|
||||||
import com.vitorpamplona.amethyst.service.model.RepostEvent
|
import com.vitorpamplona.amethyst.service.model.RepostEvent
|
||||||
import com.vitorpamplona.amethyst.service.relays.Client
|
|
||||||
import com.vitorpamplona.amethyst.service.relays.Relay
|
|
||||||
import com.vitorpamplona.amethyst.service.relays.RelayPool
|
|
||||||
import nostr.postr.JsonFilter
|
import nostr.postr.JsonFilter
|
||||||
import nostr.postr.events.TextNoteEvent
|
import nostr.postr.events.TextNoteEvent
|
||||||
import nostr.postr.toHex
|
import nostr.postr.toHex
|
||||||
|
@ -12,13 +12,6 @@ import nostr.postr.JsonFilter
|
|||||||
object NostrNotificationDataSource: NostrDataSource<Note>("NotificationFeed") {
|
object NostrNotificationDataSource: NostrDataSource<Note>("NotificationFeed") {
|
||||||
lateinit var account: Account
|
lateinit var account: Account
|
||||||
|
|
||||||
fun createNotificationFilter() = JsonFilter(
|
|
||||||
tags = mapOf("p" to listOf(account.userProfile().pubkeyHex)),
|
|
||||||
limit = 100
|
|
||||||
)
|
|
||||||
|
|
||||||
val notificationChannel = requestNewChannel()
|
|
||||||
|
|
||||||
override fun feed(): List<Note> {
|
override fun feed(): List<Note> {
|
||||||
val set = account.userProfile().taggedPosts
|
val set = account.userProfile().taggedPosts
|
||||||
val filtered = synchronized(set) {
|
val filtered = synchronized(set) {
|
||||||
@ -31,7 +24,5 @@ object NostrNotificationDataSource: NostrDataSource<Note>("NotificationFeed") {
|
|||||||
}.sortedBy { it.event?.createdAt }.reversed()
|
}.sortedBy { it.event?.createdAt }.reversed()
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun updateChannelFilters() {
|
override fun updateChannelFilters() {}
|
||||||
notificationChannel.filter = listOf(createNotificationFilter()).ifEmpty { null }
|
|
||||||
}
|
|
||||||
}
|
}
|
@ -46,8 +46,7 @@ object NostrSingleChannelDataSource: NostrDataSource<Note>("SingleChannelFeed")
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
val repliesAndReactionsChannel = requestNewChannel()
|
val singleChannelChannel = requestNewChannel()
|
||||||
val loadEventsChannel = requestNewChannel()
|
|
||||||
|
|
||||||
override fun feed(): List<Note> {
|
override fun feed(): List<Note> {
|
||||||
return emptyList()
|
return emptyList()
|
||||||
@ -57,8 +56,7 @@ object NostrSingleChannelDataSource: NostrDataSource<Note>("SingleChannelFeed")
|
|||||||
val reactions = createRepliesAndReactionsFilter()
|
val reactions = createRepliesAndReactionsFilter()
|
||||||
val missing = createLoadEventsIfNotLoadedFilter()
|
val missing = createLoadEventsIfNotLoadedFilter()
|
||||||
|
|
||||||
repliesAndReactionsChannel.filter = listOfNotNull(reactions).ifEmpty { null }
|
singleChannelChannel.filter = listOfNotNull(reactions, missing).ifEmpty { null }
|
||||||
loadEventsChannel.filter = listOfNotNull(missing).ifEmpty { null }
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fun add(eventId: String) {
|
fun add(eventId: String) {
|
||||||
|
@ -60,8 +60,7 @@ object NostrSingleEventDataSource: NostrDataSource<Note>("SingleEventFeed") {
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
val repliesAndReactionsChannel = requestNewChannel()
|
val singleEventChannel = requestNewChannel()
|
||||||
val loadEventsChannel = requestNewChannel()
|
|
||||||
|
|
||||||
override fun feed(): List<Note> {
|
override fun feed(): List<Note> {
|
||||||
return synchronized(eventsToWatch) {
|
return synchronized(eventsToWatch) {
|
||||||
@ -75,8 +74,7 @@ object NostrSingleEventDataSource: NostrDataSource<Note>("SingleEventFeed") {
|
|||||||
val reactions = createRepliesAndReactionsFilter()
|
val reactions = createRepliesAndReactionsFilter()
|
||||||
val missing = createLoadEventsIfNotLoadedFilter()
|
val missing = createLoadEventsIfNotLoadedFilter()
|
||||||
|
|
||||||
repliesAndReactionsChannel.filter = listOfNotNull(reactions).ifEmpty { null }
|
singleEventChannel.filter = listOfNotNull(reactions, missing).ifEmpty { null }
|
||||||
loadEventsChannel.filter = listOfNotNull(missing).ifEmpty { null }
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fun add(eventId: String) {
|
fun add(eventId: String) {
|
||||||
|
@ -34,8 +34,11 @@ object NostrSingleUserDataSource: NostrDataSource<User>("SingleUserFeed") {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
val userChannel = requestNewChannel()
|
val userChannel = requestNewChannel(){
|
||||||
val userReportChannel = requestNewChannel()
|
// Many relays operate with limits in the amount of filters.
|
||||||
|
// As information comes, the filters will be rotated to get more data.
|
||||||
|
invalidateFilters()
|
||||||
|
}
|
||||||
|
|
||||||
override fun feed(): List<User> {
|
override fun feed(): List<User> {
|
||||||
return synchronized(usersToWatch) {
|
return synchronized(usersToWatch) {
|
||||||
@ -46,8 +49,7 @@ object NostrSingleUserDataSource: NostrDataSource<User>("SingleUserFeed") {
|
|||||||
}
|
}
|
||||||
|
|
||||||
override fun updateChannelFilters() {
|
override fun updateChannelFilters() {
|
||||||
userChannel.filter = createUserFilter()
|
userChannel.filter = listOfNotNull(createUserFilter()).flatten()
|
||||||
userReportChannel.filter = createUserReportFilter()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fun add(userId: String) {
|
fun add(userId: String) {
|
||||||
|
@ -43,7 +43,6 @@ object NostrThreadDataSource: NostrDataSource<Note>("SingleThreadFeed") {
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
val repliesAndReactionsChannel = requestNewChannel()
|
|
||||||
val loadEventsChannel = requestNewChannel()
|
val loadEventsChannel = requestNewChannel()
|
||||||
|
|
||||||
override fun feed(): List<Note> {
|
override fun feed(): List<Note> {
|
||||||
@ -55,8 +54,7 @@ object NostrThreadDataSource: NostrDataSource<Note>("SingleThreadFeed") {
|
|||||||
}
|
}
|
||||||
|
|
||||||
override fun updateChannelFilters() {
|
override fun updateChannelFilters() {
|
||||||
repliesAndReactionsChannel.filter = listOfNotNull(createRepliesAndReactionsFilter()).ifEmpty { null }
|
loadEventsChannel.filter = listOfNotNull(createLoadEventsIfNotLoadedFilter(), createRepliesAndReactionsFilter()).ifEmpty { null }
|
||||||
loadEventsChannel.filter = listOfNotNull(createLoadEventsIfNotLoadedFilter()).ifEmpty { null }
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fun searchRoot(note: Note, testedNotes: MutableSet<Note> = mutableSetOf()): Note? {
|
fun searchRoot(note: Note, testedNotes: MutableSet<Note> = mutableSetOf()): Note? {
|
||||||
|
@ -6,6 +6,7 @@ import com.vitorpamplona.amethyst.model.Note
|
|||||||
import com.vitorpamplona.amethyst.model.User
|
import com.vitorpamplona.amethyst.model.User
|
||||||
import com.vitorpamplona.amethyst.model.toByteArray
|
import com.vitorpamplona.amethyst.model.toByteArray
|
||||||
import nostr.postr.JsonFilter
|
import nostr.postr.JsonFilter
|
||||||
|
import nostr.postr.events.ContactListEvent
|
||||||
import nostr.postr.events.MetadataEvent
|
import nostr.postr.events.MetadataEvent
|
||||||
import nostr.postr.events.TextNoteEvent
|
import nostr.postr.events.TextNoteEvent
|
||||||
|
|
||||||
@ -34,8 +35,20 @@ object NostrUserProfileDataSource: NostrDataSource<Note>("UserProfileFeed") {
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun createFollowFilter(): JsonFilter {
|
||||||
|
return JsonFilter(
|
||||||
|
kinds = listOf(ContactListEvent.kind),
|
||||||
|
authors = listOf(user!!.pubkeyHex),
|
||||||
|
limit = 1
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun createFollowersFilter() = JsonFilter(
|
||||||
|
kinds = listOf(ContactListEvent.kind),
|
||||||
|
tags = mapOf("p" to listOf(user!!.pubkeyHex))
|
||||||
|
)
|
||||||
|
|
||||||
val userInfoChannel = requestNewChannel()
|
val userInfoChannel = requestNewChannel()
|
||||||
val notesChannel = requestNewChannel()
|
|
||||||
|
|
||||||
override fun feed(): List<Note> {
|
override fun feed(): List<Note> {
|
||||||
val notes = user?.notes ?: return emptyList()
|
val notes = user?.notes ?: return emptyList()
|
||||||
@ -46,7 +59,11 @@ object NostrUserProfileDataSource: NostrDataSource<Note>("UserProfileFeed") {
|
|||||||
}
|
}
|
||||||
|
|
||||||
override fun updateChannelFilters() {
|
override fun updateChannelFilters() {
|
||||||
userInfoChannel.filter = listOf(createUserInfoFilter()).ifEmpty { null }
|
userInfoChannel.filter = listOf(
|
||||||
notesChannel.filter = listOf(createUserPostsFilter()).ifEmpty { null }
|
createUserInfoFilter(),
|
||||||
|
createUserPostsFilter(),
|
||||||
|
createFollowFilter(),
|
||||||
|
createFollowersFilter()
|
||||||
|
).ifEmpty { null }
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -15,13 +15,6 @@ object NostrUserProfileFollowersDataSource: NostrDataSource<User>("UserProfileFo
|
|||||||
resetFilters()
|
resetFilters()
|
||||||
}
|
}
|
||||||
|
|
||||||
fun createFollowersFilter() = JsonFilter(
|
|
||||||
kinds = listOf(ContactListEvent.kind),
|
|
||||||
tags = mapOf("p" to listOf(user!!.pubkeyHex))
|
|
||||||
)
|
|
||||||
|
|
||||||
val followerChannel = requestNewChannel()
|
|
||||||
|
|
||||||
override fun feed(): List<User> {
|
override fun feed(): List<User> {
|
||||||
val followers = user?.followers ?: emptyList()
|
val followers = user?.followers ?: emptyList()
|
||||||
|
|
||||||
@ -30,7 +23,5 @@ object NostrUserProfileFollowersDataSource: NostrDataSource<User>("UserProfileFo
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun updateChannelFilters() {
|
override fun updateChannelFilters() {}
|
||||||
followerChannel.filter = listOf(createFollowersFilter()).ifEmpty { null }
|
|
||||||
}
|
|
||||||
}
|
}
|
@ -15,16 +15,6 @@ object NostrUserProfileFollowsDataSource: NostrDataSource<User>("UserProfileFoll
|
|||||||
resetFilters()
|
resetFilters()
|
||||||
}
|
}
|
||||||
|
|
||||||
fun createFollowFilter(): JsonFilter {
|
|
||||||
return JsonFilter(
|
|
||||||
kinds = listOf(ContactListEvent.kind),
|
|
||||||
authors = listOf(user!!.pubkeyHex),
|
|
||||||
limit = 1
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
val followChannel = requestNewChannel()
|
|
||||||
|
|
||||||
override fun feed(): List<User> {
|
override fun feed(): List<User> {
|
||||||
val follows = user?.follows ?: emptyList()
|
val follows = user?.follows ?: emptyList()
|
||||||
|
|
||||||
@ -33,7 +23,5 @@ object NostrUserProfileFollowsDataSource: NostrDataSource<User>("UserProfileFoll
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun updateChannelFilters() {
|
override fun updateChannelFilters() {}
|
||||||
followChannel.filter = listOf(createFollowFilter()).ifEmpty { null }
|
|
||||||
}
|
|
||||||
}
|
}
|
@ -143,7 +143,7 @@ class Relay(
|
|||||||
val filters = Client.getSubscriptionFilters(requestId)
|
val filters = Client.getSubscriptionFilters(requestId)
|
||||||
if (filters.isNotEmpty()) {
|
if (filters.isNotEmpty()) {
|
||||||
val request =
|
val request =
|
||||||
"""["REQ","$requestId",${filters.joinToString(",") { it.toJson() }}]"""
|
"""["REQ","$requestId",${filters.take(10).joinToString(",") { it.toJson() }}]"""
|
||||||
//println("FILTERSSENT ${url} " + """["REQ","$requestId",${filters.joinToString(",") { it.toJson() }}]""")
|
//println("FILTERSSENT ${url} " + """["REQ","$requestId",${filters.joinToString(",") { it.toJson() }}]""")
|
||||||
socket?.send(request)
|
socket?.send(request)
|
||||||
}
|
}
|
||||||
|
@ -9,14 +9,9 @@ import androidx.compose.material.TabRow
|
|||||||
import androidx.compose.material.TabRowDefaults
|
import androidx.compose.material.TabRowDefaults
|
||||||
import androidx.compose.material.Text
|
import androidx.compose.material.Text
|
||||||
import androidx.compose.runtime.Composable
|
import androidx.compose.runtime.Composable
|
||||||
import androidx.compose.runtime.DisposableEffect
|
|
||||||
import androidx.compose.runtime.LaunchedEffect
|
import androidx.compose.runtime.LaunchedEffect
|
||||||
import androidx.compose.runtime.getValue
|
|
||||||
import androidx.compose.runtime.livedata.observeAsState
|
|
||||||
import androidx.compose.runtime.remember
|
|
||||||
import androidx.compose.runtime.rememberCoroutineScope
|
import androidx.compose.runtime.rememberCoroutineScope
|
||||||
import androidx.compose.ui.Modifier
|
import androidx.compose.ui.Modifier
|
||||||
import androidx.compose.ui.platform.LocalContext
|
|
||||||
import androidx.compose.ui.unit.dp
|
import androidx.compose.ui.unit.dp
|
||||||
import androidx.lifecycle.viewmodel.compose.viewModel
|
import androidx.lifecycle.viewmodel.compose.viewModel
|
||||||
import androidx.navigation.NavController
|
import androidx.navigation.NavController
|
||||||
@ -24,15 +19,8 @@ import com.google.accompanist.pager.ExperimentalPagerApi
|
|||||||
import com.google.accompanist.pager.HorizontalPager
|
import com.google.accompanist.pager.HorizontalPager
|
||||||
import com.google.accompanist.pager.pagerTabIndicatorOffset
|
import com.google.accompanist.pager.pagerTabIndicatorOffset
|
||||||
import com.google.accompanist.pager.rememberPagerState
|
import com.google.accompanist.pager.rememberPagerState
|
||||||
import com.vitorpamplona.amethyst.NotificationCache
|
|
||||||
import com.vitorpamplona.amethyst.service.NostrHomeDataSource
|
|
||||||
import com.vitorpamplona.amethyst.service.NostrUserProfileDataSource
|
|
||||||
import com.vitorpamplona.amethyst.service.NostrUserProfileFollowersDataSource
|
|
||||||
import com.vitorpamplona.amethyst.service.NostrUserProfileFollowsDataSource
|
|
||||||
import com.vitorpamplona.amethyst.ui.navigation.Route
|
import com.vitorpamplona.amethyst.ui.navigation.Route
|
||||||
import com.vitorpamplona.amethyst.ui.navigation.Routes
|
|
||||||
import com.vitorpamplona.amethyst.ui.screen.loggedIn.AccountViewModel
|
import com.vitorpamplona.amethyst.ui.screen.loggedIn.AccountViewModel
|
||||||
import java.lang.System.currentTimeMillis
|
|
||||||
import kotlinx.coroutines.launch
|
import kotlinx.coroutines.launch
|
||||||
|
|
||||||
@OptIn(ExperimentalPagerApi::class)
|
@OptIn(ExperimentalPagerApi::class)
|
||||||
|
Loading…
Reference in New Issue
Block a user