From d1c43f8147b4f0b397bee33b540e169084b8bc58 Mon Sep 17 00:00:00 2001 From: Vitor Pamplona Date: Thu, 14 Dec 2023 18:31:00 -0500 Subject: [PATCH] Avoiding the creation of new sets when looping through maps in User and Note --- .../com/vitorpamplona/amethyst/model/Note.kt | 76 ++++++++----------- .../com/vitorpamplona/amethyst/model/User.kt | 50 ++++++------ .../amethyst/service/NostrDataSource.kt | 4 +- .../amethyst/service/relays/Client.kt | 4 +- .../amethyst/ui/dal/ChannelFeedFilter.kt | 2 +- .../ui/dal/ChatroomListKnownFeedFilter.kt | 16 ++-- .../ui/dal/ChatroomListNewFeedFilter.kt | 13 ++-- .../amethyst/ui/navigation/Routes.kt | 5 +- 8 files changed, 79 insertions(+), 91 deletions(-) diff --git a/app/src/main/java/com/vitorpamplona/amethyst/model/Note.kt b/app/src/main/java/com/vitorpamplona/amethyst/model/Note.kt index 1e343e8e1..75151b5cc 100644 --- a/app/src/main/java/com/vitorpamplona/amethyst/model/Note.kt +++ b/app/src/main/java/com/vitorpamplona/amethyst/model/Note.kt @@ -287,7 +287,7 @@ open class Note(val idHex: String) { val tags = note.event?.tags() ?: emptyArray() val reaction = note.event?.content()?.firstFullCharOrEmoji(ImmutableListOfLists(tags)) ?: "+" - if (reaction in reactions.keys && reactions[reaction]?.contains(note) == true) { + if (reactions[reaction]?.contains(note) == true) { reactions[reaction]?.let { if (note in it) { val newList = it.minus(note) @@ -306,7 +306,7 @@ open class Note(val idHex: String) { fun removeReport(deleteNote: Note) { val author = deleteNote.author ?: return - if (author in reports.keys && reports[author]?.contains(deleteNote) == true) { + if (reports[author]?.contains(deleteNote) == true) { reports[author]?.let { reports = reports + Pair(author, it.minus(deleteNote)) liveSet?.innerReports?.invalidateData() @@ -327,12 +327,11 @@ open class Note(val idHex: String) { } fun removeZapPayment(note: Note) { - if (zapPayments[note] != null) { + if (zapPayments.containsKey(note)) { zapPayments = zapPayments.minus(note) liveSet?.innerZaps?.invalidateData() } else if (zapPayments.containsValue(note)) { - val toRemove = zapPayments.filterValues { it == note } - zapPayments = zapPayments.minus(toRemove.keys) + zapPayments = zapPayments.filterValues { it != note } liveSet?.innerZaps?.invalidateData() } } @@ -346,10 +345,7 @@ open class Note(val idHex: String) { @Synchronized private fun innerAddZap(zapRequest: Note, zap: Note?): Boolean { - if (zapRequest !in zaps.keys) { - zaps = zaps + Pair(zapRequest, zap) - return true - } else if (zaps[zapRequest] == null) { + if (zaps[zapRequest] == null) { zaps = zaps + Pair(zapRequest, zap) return true } @@ -359,13 +355,8 @@ open class Note(val idHex: String) { fun addZap(zapRequest: Note, zap: Note?) { checkNotInMainThread() - if (zapRequest !in zaps.keys) { - val inserted = innerAddZap(zapRequest, zap) - if (inserted) { - updateZapTotal() - liveSet?.innerZaps?.invalidateData() - } - } else if (zaps[zapRequest] == null) { + + if (zaps[zapRequest] == null) { val inserted = innerAddZap(zapRequest, zap) if (inserted) { updateZapTotal() @@ -376,10 +367,7 @@ open class Note(val idHex: String) { @Synchronized private fun innerAddZapPayment(zapPaymentRequest: Note, zapPayment: Note?): Boolean { - if (zapPaymentRequest !in zapPayments.keys) { - zapPayments = zapPayments + Pair(zapPaymentRequest, zapPayment) - return true - } else if (zapPayments[zapPaymentRequest] == null) { + if (zapPayments[zapPaymentRequest] == null) { zapPayments = zapPayments + Pair(zapPaymentRequest, zapPayment) return true } @@ -389,12 +377,7 @@ open class Note(val idHex: String) { fun addZapPayment(zapPaymentRequest: Note, zapPayment: Note?) { checkNotInMainThread() - if (zapPaymentRequest !in zapPayments.keys) { - val inserted = innerAddZapPayment(zapPaymentRequest, zapPayment) - if (inserted) { - liveSet?.innerZaps?.invalidateData() - } - } else if (zapPayments[zapPaymentRequest] == null) { + if (zapPayments[zapPaymentRequest] == null) { val inserted = innerAddZapPayment(zapPaymentRequest, zapPayment) if (inserted) { liveSet?.innerZaps?.invalidateData() @@ -406,11 +389,12 @@ open class Note(val idHex: String) { val tags = note.event?.tags() ?: emptyArray() val reaction = note.event?.content()?.firstFullCharOrEmoji(ImmutableListOfLists(tags)) ?: "+" - if (reaction !in reactions.keys) { + val listOfAuthors = reactions[reaction] + if (listOfAuthors == null) { reactions = reactions + Pair(reaction, listOf(note)) liveSet?.innerReactions?.invalidateData() - } else if (reactions[reaction]?.contains(note) == false) { - reactions = reactions + Pair(reaction, (reactions[reaction] ?: emptySet()) + note) + } else if (!listOfAuthors.contains(note)) { + reactions = reactions + Pair(reaction, listOfAuthors + note) liveSet?.innerReactions?.invalidateData() } } @@ -418,11 +402,13 @@ open class Note(val idHex: String) { fun addReport(note: Note) { val author = note.author ?: return - if (author !in reports.keys) { + val reportsByAuthor = reports[author] + + if (reportsByAuthor == null) { reports = reports + Pair(author, listOf(note)) liveSet?.innerReports?.invalidateData() - } else if (reports[author]?.contains(note) == false) { - reports = reports + Pair(author, (reports[author] ?: emptySet()) + note) + } else if (!reportsByAuthor.contains(note)) { + reports = reports + Pair(author, reportsByAuthor + note) liveSet?.innerReports?.invalidateData() } } @@ -523,17 +509,17 @@ open class Note(val idHex: String) { return reports[user]?.isNotEmpty() ?: false } - fun reportAuthorsBy(users: Set): List { - return reports.keys.filter { it.pubkeyHex in users } - } - fun countReportAuthorsBy(users: Set): Int { - return reports.keys.count { it.pubkeyHex in users } + return reports.count { it.key.pubkeyHex in users } } fun reportsBy(users: Set): List { - return reportAuthorsBy(users).mapNotNull { - reports[it] + return reports.mapNotNull { + if (it.key.pubkeyHex in users) { + it.value + } else { + null + } }.flatten() } @@ -541,8 +527,8 @@ open class Note(val idHex: String) { var sumOfAmounts = BigDecimal.ZERO // Regular Zap Receipts - zaps.values.forEach { - val noteEvent = it?.event + zaps.forEach { + val noteEvent = it?.value?.event if (noteEvent is LnZapEvent) { sumOfAmounts += noteEvent.amount ?: BigDecimal.ZERO } @@ -647,8 +633,8 @@ open class Note(val idHex: String) { val dayAgo = TimeUtils.oneDayAgo() return reports.isNotEmpty() || ( - author?.reports?.values?.any { - it.firstOrNull { (it.createdAt() ?: 0) > dayAgo } != null + author?.reports?.any { + it.value.firstOrNull { (it.createdAt() ?: 0) > dayAgo } != null } ?: false ) } @@ -863,7 +849,9 @@ class NoteLiveSet(u: Note) { }.distinctUntilChanged() val reactionCount = innerReactions.map { - it.note.reactions.values.sumOf { it.size } + var total = 0 + it.note.reactions.forEach { total += it.value.size } + total }.distinctUntilChanged() val boostCount = innerBoosts.map { diff --git a/app/src/main/java/com/vitorpamplona/amethyst/model/User.kt b/app/src/main/java/com/vitorpamplona/amethyst/model/User.kt index 618fee816..7d5cbfe5a 100644 --- a/app/src/main/java/com/vitorpamplona/amethyst/model/User.kt +++ b/app/src/main/java/com/vitorpamplona/amethyst/model/User.kt @@ -130,11 +130,12 @@ class User(val pubkeyHex: String) { fun addReport(note: Note) { val author = note.author ?: return - if (author !in reports.keys) { + val reportsBy = reports[author] + if (reportsBy == null) { reports = reports + Pair(author, setOf(note)) liveSet?.innerReports?.invalidateData() - } else if (reports[author]?.contains(note) == false) { - reports = reports + Pair(author, (reports[author] ?: emptySet()) + note) + } else if (!reportsBy.contains(note)) { + reports = reports + Pair(author, reportsBy + note) liveSet?.innerReports?.invalidateData() } } @@ -142,7 +143,7 @@ class User(val pubkeyHex: String) { fun removeReport(deleteNote: Note) { val author = deleteNote.author ?: return - if (author in reports.keys && reports[author]?.contains(deleteNote) == true) { + if (reports[author]?.contains(deleteNote) == true) { reports[author]?.let { reports = reports + Pair(author, it.minus(deleteNote)) liveSet?.innerReports?.invalidateData() @@ -151,48 +152,49 @@ class User(val pubkeyHex: String) { } fun addZap(zapRequest: Note, zap: Note?) { - if (zapRequest !in zaps.keys) { - zaps = zaps + Pair(zapRequest, zap) - liveSet?.innerZaps?.invalidateData() - } else if (zapRequest in zaps.keys && zaps[zapRequest] == null) { + if (zaps[zapRequest] == null) { zaps = zaps + Pair(zapRequest, zap) liveSet?.innerZaps?.invalidateData() } } fun removeZap(zapRequestOrZapEvent: Note) { - if (zapRequestOrZapEvent in zaps.keys) { + if (zaps.containsKey(zapRequestOrZapEvent)) { zaps = zaps.minus(zapRequestOrZapEvent) liveSet?.innerZaps?.invalidateData() - } else if (zapRequestOrZapEvent in zaps.values) { + } else if (zaps.containsValue(zapRequestOrZapEvent)) { zaps = zaps.filter { it.value != zapRequestOrZapEvent } liveSet?.innerZaps?.invalidateData() } } fun zappedAmount(): BigDecimal { - return zaps.mapNotNull { it.value?.event } - .filterIsInstance() - .mapNotNull { - it.amount - }.sumOf { it } + var amount = BigDecimal.ZERO + zaps.forEach { + val itemValue = (it.value?.event as? LnZapEvent)?.amount + if (itemValue != null) { + amount += itemValue + } + } + + return amount } fun reportsBy(user: User): Set { return reports[user] ?: emptySet() } - fun reportAuthorsBy(users: Set): List { - return reports.keys.filter { it.pubkeyHex in users } - } - fun countReportAuthorsBy(users: Set): Int { - return reports.keys.count { it.pubkeyHex in users } + return reports.count { it.key.pubkeyHex in users } } fun reportsBy(users: Set): List { - return reportAuthorsBy(users).mapNotNull { - reports[it] + return reports.mapNotNull { + if (it.key.pubkeyHex in users) { + it.value + } else { + null + } }.flatten() } @@ -314,7 +316,7 @@ class User(val pubkeyHex: String) { } suspend fun transientFollowerCount(): Int { - return LocalCache.users.values.count { it.latestContactList?.isTaggedUser(pubkeyHex) ?: false } + return LocalCache.users.count { it.value.latestContactList?.isTaggedUser(pubkeyHex) ?: false } } fun cachedFollowingKeySet(): Set { @@ -338,7 +340,7 @@ class User(val pubkeyHex: String) { } suspend fun cachedFollowerCount(): Int { - return LocalCache.users.values.count { it.latestContactList?.isTaggedUser(pubkeyHex) ?: false } + return LocalCache.users.count { it.value.latestContactList?.isTaggedUser(pubkeyHex) ?: false } } fun hasSentMessagesTo(key: ChatroomKey?): Boolean { diff --git a/app/src/main/java/com/vitorpamplona/amethyst/service/NostrDataSource.kt b/app/src/main/java/com/vitorpamplona/amethyst/service/NostrDataSource.kt index af88eb21c..699faea93 100644 --- a/app/src/main/java/com/vitorpamplona/amethyst/service/NostrDataSource.kt +++ b/app/src/main/java/com/vitorpamplona/amethyst/service/NostrDataSource.kt @@ -64,7 +64,7 @@ abstract class NostrDataSource(val debugName: String) { // Relay.Type.EOSE -> "sent all events it had stored." // }}") - if (type == Relay.StateType.EOSE && subscriptionId != null && subscriptionId in subscriptions.keys) { + if (type == Relay.StateType.EOSE && subscriptionId != null && subscriptions.containsKey(subscriptionId)) { markAsEOSE(subscriptionId, relay) } } @@ -177,7 +177,7 @@ abstract class NostrDataSource(val debugName: String) { subscriptions.values.forEach { updatedSubscription -> val updatedSubscriptionNewFilters = updatedSubscription.typedFilters - if (updatedSubscription.id in currentFilters.keys) { + if (currentFilters.containsKey(updatedSubscription.id)) { if (updatedSubscriptionNewFilters == null) { // was active and is not active anymore, just close. Client.close(updatedSubscription.id) diff --git a/app/src/main/java/com/vitorpamplona/amethyst/service/relays/Client.kt b/app/src/main/java/com/vitorpamplona/amethyst/service/relays/Client.kt index f07de6603..bd82ff2cd 100644 --- a/app/src/main/java/com/vitorpamplona/amethyst/service/relays/Client.kt +++ b/app/src/main/java/com/vitorpamplona/amethyst/service/relays/Client.kt @@ -213,8 +213,8 @@ object Client : RelayPool.Listener { listeners = listeners.minus(listener) } - fun allSubscriptions(): List { - return subscriptions.keys.toList() + fun allSubscriptions(): Set { + return subscriptions.keys } fun getSubscriptionFilters(subId: String): List { diff --git a/app/src/main/java/com/vitorpamplona/amethyst/ui/dal/ChannelFeedFilter.kt b/app/src/main/java/com/vitorpamplona/amethyst/ui/dal/ChannelFeedFilter.kt index 4f3493e67..8c31ab5da 100644 --- a/app/src/main/java/com/vitorpamplona/amethyst/ui/dal/ChannelFeedFilter.kt +++ b/app/src/main/java/com/vitorpamplona/amethyst/ui/dal/ChannelFeedFilter.kt @@ -21,7 +21,7 @@ class ChannelFeedFilter(val channel: Channel, val account: Account) : AdditiveFe override fun applyFilter(collection: Set): Set { return collection - .filter { it.idHex in channel.notes.keys && account.isAcceptable(it) } + .filter { channel.notes.containsKey(it.idHex) && account.isAcceptable(it) } .toSet() } diff --git a/app/src/main/java/com/vitorpamplona/amethyst/ui/dal/ChatroomListKnownFeedFilter.kt b/app/src/main/java/com/vitorpamplona/amethyst/ui/dal/ChatroomListKnownFeedFilter.kt index 2964850eb..83543f85e 100644 --- a/app/src/main/java/com/vitorpamplona/amethyst/ui/dal/ChatroomListKnownFeedFilter.kt +++ b/app/src/main/java/com/vitorpamplona/amethyst/ui/dal/ChatroomListKnownFeedFilter.kt @@ -20,19 +20,17 @@ class ChatroomListKnownFeedFilter(val account: Account) : AdditiveFeedFilter - privateChatrooms[it] - ?.roomMessages - ?.sortedWith(compareBy({ it.createdAt() }, { it.idHex })) - ?.lastOrNull { it.event != null } + it.value + .roomMessages + .sortedWith(compareBy({ it.createdAt() }, { it.idHex })) + .lastOrNull { it.event != null } } val publicChannels = account.selectedChatsFollowList().mapNotNull { diff --git a/app/src/main/java/com/vitorpamplona/amethyst/ui/dal/ChatroomListNewFeedFilter.kt b/app/src/main/java/com/vitorpamplona/amethyst/ui/dal/ChatroomListNewFeedFilter.kt index 7356b3544..ab3e48e6e 100644 --- a/app/src/main/java/com/vitorpamplona/amethyst/ui/dal/ChatroomListNewFeedFilter.kt +++ b/app/src/main/java/com/vitorpamplona/amethyst/ui/dal/ChatroomListNewFeedFilter.kt @@ -20,16 +20,15 @@ class ChatroomListNewFeedFilter(val account: Account) : AdditiveFeedFilter val followingKeySet = account.followingKeySet() val privateChatrooms = account.userProfile().privateChatrooms - val messagingWith = privateChatrooms.keys.filter { - privateChatrooms[it]?.senderIntersects(followingKeySet) == false && - !me.hasSentMessagesTo(it) && !account.isAllHidden(it.users) + val messagingWith = privateChatrooms.filter { + !it.value.senderIntersects(followingKeySet) && !me.hasSentMessagesTo(it.key) && !account.isAllHidden(it.key.users) } val privateMessages = messagingWith.mapNotNull { it -> - privateChatrooms[it] - ?.roomMessages - ?.sortedWith(compareBy({ it.createdAt() }, { it.idHex })) - ?.lastOrNull { it.event != null } + it.value + .roomMessages + .sortedWith(compareBy({ it.createdAt() }, { it.idHex })) + .lastOrNull { it.event != null } } return privateMessages diff --git a/app/src/main/java/com/vitorpamplona/amethyst/ui/navigation/Routes.kt b/app/src/main/java/com/vitorpamplona/amethyst/ui/navigation/Routes.kt index ae33c158e..da9b2e91e 100644 --- a/app/src/main/java/com/vitorpamplona/amethyst/ui/navigation/Routes.kt +++ b/app/src/main/java/com/vitorpamplona/amethyst/ui/navigation/Routes.kt @@ -335,8 +335,9 @@ private fun getRouteWithArguments( ): String? { var route = destination.route ?: return null arguments?.let { bundle -> - destination.arguments.keys.forEach { key -> - val value = destination.arguments[key]?.type?.get(bundle, key)?.toString() + destination.arguments.forEach { + val key = it.key + val value = it.value.type[bundle, key]?.toString() if (value == null) { val keyStart = route.indexOf("{$key}") // if it is a parameter, removes the complete segment `var={key}` and adjust connectors `#`, `&` or `&`