mirror of
https://github.com/vitorpamplona/amethyst.git
synced 2025-09-28 21:53:01 +02:00
- Only updates lists if they were changed.
- Refactoring RelayLists
This commit is contained in:
@@ -592,7 +592,7 @@ class Account(
|
|||||||
return keyPair.privKey != null || signer is NostrSignerExternal
|
return keyPair.privKey != null || signer is NostrSignerExternal
|
||||||
}
|
}
|
||||||
|
|
||||||
fun sendNewRelayList(relays: Map<String, ContactListEvent.ReadWrite>) {
|
fun sendKind3RelayList(relays: Map<String, ContactListEvent.ReadWrite>) {
|
||||||
if (!isWriteable()) return
|
if (!isWriteable()) return
|
||||||
|
|
||||||
val contactList = userProfile().latestContactList
|
val contactList = userProfile().latestContactList
|
||||||
@@ -2685,10 +2685,10 @@ class Account(
|
|||||||
.toSet()
|
.toSet()
|
||||||
}
|
}
|
||||||
|
|
||||||
fun saveRelayList(value: List<RelaySetupInfo>) {
|
fun saveKind3RelayList(value: List<RelaySetupInfo>) {
|
||||||
try {
|
try {
|
||||||
localRelays = value.toSet()
|
localRelays = value.toSet()
|
||||||
return sendNewRelayList(
|
return sendKind3RelayList(
|
||||||
value.associate { it.url to ContactListEvent.ReadWrite(it.read, it.write) },
|
value.associate { it.url to ContactListEvent.ReadWrite(it.read, it.write) },
|
||||||
)
|
)
|
||||||
} finally {
|
} finally {
|
||||||
|
@@ -0,0 +1,121 @@
|
|||||||
|
/**
|
||||||
|
* Copyright (c) 2024 Vitor Pamplona
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||||
|
* this software and associated documentation files (the "Software"), to deal in
|
||||||
|
* the Software without restriction, including without limitation the rights to use,
|
||||||
|
* copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the
|
||||||
|
* Software, and to permit persons to whom the Software is furnished to do so,
|
||||||
|
* subject to the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice shall be included in all
|
||||||
|
* copies or substantial portions of the Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||||
|
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||||
|
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
|
||||||
|
* AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||||
|
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||||
|
*/
|
||||||
|
package com.vitorpamplona.amethyst.ui.actions.relays
|
||||||
|
|
||||||
|
import androidx.lifecycle.ViewModel
|
||||||
|
import androidx.lifecycle.viewModelScope
|
||||||
|
import com.vitorpamplona.amethyst.model.Account
|
||||||
|
import com.vitorpamplona.amethyst.service.Nip11CachedRetriever
|
||||||
|
import com.vitorpamplona.amethyst.service.relays.RelayPool
|
||||||
|
import kotlinx.coroutines.Dispatchers
|
||||||
|
import kotlinx.coroutines.flow.MutableStateFlow
|
||||||
|
import kotlinx.coroutines.flow.asStateFlow
|
||||||
|
import kotlinx.coroutines.flow.update
|
||||||
|
import kotlinx.coroutines.launch
|
||||||
|
|
||||||
|
abstract class BasicRelaySetupInfoModel : ViewModel() {
|
||||||
|
lateinit var account: Account
|
||||||
|
|
||||||
|
private val _relays = MutableStateFlow<List<BasicRelaySetupInfo>>(emptyList())
|
||||||
|
val relays = _relays.asStateFlow()
|
||||||
|
|
||||||
|
var hasModified = false
|
||||||
|
|
||||||
|
fun load(account: Account) {
|
||||||
|
this.account = account
|
||||||
|
clear()
|
||||||
|
loadRelayDocuments()
|
||||||
|
}
|
||||||
|
|
||||||
|
abstract fun getRelayList(): List<String>?
|
||||||
|
|
||||||
|
abstract fun saveRelayList(urlList: List<String>)
|
||||||
|
|
||||||
|
fun create() {
|
||||||
|
if (hasModified) {
|
||||||
|
viewModelScope.launch(Dispatchers.IO) {
|
||||||
|
saveRelayList(_relays.value.map { it.url })
|
||||||
|
clear()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun loadRelayDocuments() {
|
||||||
|
viewModelScope.launch(Dispatchers.IO) {
|
||||||
|
_relays.value.forEach { item ->
|
||||||
|
Nip11CachedRetriever.loadRelayInfo(
|
||||||
|
dirtyUrl = item.url,
|
||||||
|
onInfo = {
|
||||||
|
togglePaidRelay(item, it.limitation?.payment_required ?: false)
|
||||||
|
},
|
||||||
|
onError = { url, errorCode, exceptionMessage -> },
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun clear() {
|
||||||
|
var hasModified = false
|
||||||
|
_relays.update {
|
||||||
|
val relayList = getRelayList() ?: emptyList()
|
||||||
|
|
||||||
|
relayList.map { relayUrl ->
|
||||||
|
val liveRelay = RelayPool.getRelay(relayUrl)
|
||||||
|
val errorCounter = liveRelay?.errorCounter ?: 0
|
||||||
|
val eventDownloadCounter = liveRelay?.eventDownloadCounterInBytes ?: 0
|
||||||
|
val eventUploadCounter = liveRelay?.eventUploadCounterInBytes ?: 0
|
||||||
|
val spamCounter = liveRelay?.spamCounter ?: 0
|
||||||
|
|
||||||
|
BasicRelaySetupInfo(
|
||||||
|
relayUrl,
|
||||||
|
errorCounter,
|
||||||
|
eventDownloadCounter,
|
||||||
|
eventUploadCounter,
|
||||||
|
spamCounter,
|
||||||
|
)
|
||||||
|
}.distinctBy { it.url }.sortedBy { it.downloadCountInBytes }.reversed()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun addRelay(relay: BasicRelaySetupInfo) {
|
||||||
|
if (relays.value.any { it.url == relay.url }) return
|
||||||
|
|
||||||
|
_relays.update { it.plus(relay) }
|
||||||
|
hasModified = true
|
||||||
|
}
|
||||||
|
|
||||||
|
fun deleteRelay(relay: BasicRelaySetupInfo) {
|
||||||
|
_relays.update { it.minus(relay) }
|
||||||
|
hasModified = true
|
||||||
|
}
|
||||||
|
|
||||||
|
fun deleteAll() {
|
||||||
|
_relays.update { relays -> emptyList() }
|
||||||
|
hasModified = true
|
||||||
|
}
|
||||||
|
|
||||||
|
fun togglePaidRelay(
|
||||||
|
relay: BasicRelaySetupInfo,
|
||||||
|
paid: Boolean,
|
||||||
|
) {
|
||||||
|
_relays.update { it.updated(relay, relay.copy(paidRelay = paid)) }
|
||||||
|
}
|
||||||
|
}
|
@@ -20,90 +20,12 @@
|
|||||||
*/
|
*/
|
||||||
package com.vitorpamplona.amethyst.ui.actions.relays
|
package com.vitorpamplona.amethyst.ui.actions.relays
|
||||||
|
|
||||||
import androidx.lifecycle.ViewModel
|
class DMRelayListViewModel : BasicRelaySetupInfoModel() {
|
||||||
import androidx.lifecycle.viewModelScope
|
override fun getRelayList(): List<String>? {
|
||||||
import com.vitorpamplona.amethyst.model.Account
|
return account.getDMRelayList()?.relays()
|
||||||
import com.vitorpamplona.amethyst.service.Nip11CachedRetriever
|
|
||||||
import com.vitorpamplona.amethyst.service.relays.RelayPool
|
|
||||||
import kotlinx.coroutines.Dispatchers
|
|
||||||
import kotlinx.coroutines.flow.MutableStateFlow
|
|
||||||
import kotlinx.coroutines.flow.asStateFlow
|
|
||||||
import kotlinx.coroutines.flow.update
|
|
||||||
import kotlinx.coroutines.launch
|
|
||||||
|
|
||||||
class DMRelayListViewModel : ViewModel() {
|
|
||||||
private lateinit var account: Account
|
|
||||||
|
|
||||||
private val _relays = MutableStateFlow<List<BasicRelaySetupInfo>>(emptyList())
|
|
||||||
val relays = _relays.asStateFlow()
|
|
||||||
|
|
||||||
fun load(account: Account) {
|
|
||||||
this.account = account
|
|
||||||
clear()
|
|
||||||
loadRelayDocuments()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fun create() {
|
override fun saveRelayList(urlList: List<String>) {
|
||||||
viewModelScope.launch(Dispatchers.IO) {
|
account.saveDMRelayList(urlList)
|
||||||
account.saveDMRelayList(_relays.value.map { it.url })
|
|
||||||
clear()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fun loadRelayDocuments() {
|
|
||||||
viewModelScope.launch(Dispatchers.IO) {
|
|
||||||
_relays.value.forEach { item ->
|
|
||||||
Nip11CachedRetriever.loadRelayInfo(
|
|
||||||
dirtyUrl = item.url,
|
|
||||||
onInfo = {
|
|
||||||
togglePaidRelay(item, it.limitation?.payment_required ?: false)
|
|
||||||
},
|
|
||||||
onError = { url, errorCode, exceptionMessage -> },
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fun clear() {
|
|
||||||
_relays.update {
|
|
||||||
val relayList = account.getDMRelayList()?.relays() ?: emptyList()
|
|
||||||
|
|
||||||
relayList.map { relayUrl ->
|
|
||||||
val liveRelay = RelayPool.getRelay(relayUrl)
|
|
||||||
val errorCounter = liveRelay?.errorCounter ?: 0
|
|
||||||
val eventDownloadCounter = liveRelay?.eventDownloadCounterInBytes ?: 0
|
|
||||||
val eventUploadCounter = liveRelay?.eventUploadCounterInBytes ?: 0
|
|
||||||
val spamCounter = liveRelay?.spamCounter ?: 0
|
|
||||||
|
|
||||||
BasicRelaySetupInfo(
|
|
||||||
relayUrl,
|
|
||||||
errorCounter,
|
|
||||||
eventDownloadCounter,
|
|
||||||
eventUploadCounter,
|
|
||||||
spamCounter,
|
|
||||||
)
|
|
||||||
}.distinctBy { it.url }.sortedBy { it.downloadCountInBytes }.reversed()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fun addRelay(relay: BasicRelaySetupInfo) {
|
|
||||||
if (relays.value.any { it.url == relay.url }) return
|
|
||||||
|
|
||||||
_relays.update { it.plus(relay) }
|
|
||||||
}
|
|
||||||
|
|
||||||
fun deleteRelay(relay: BasicRelaySetupInfo) {
|
|
||||||
_relays.update { it.minus(relay) }
|
|
||||||
}
|
|
||||||
|
|
||||||
fun deleteAll() {
|
|
||||||
_relays.update { relays -> emptyList() }
|
|
||||||
}
|
|
||||||
|
|
||||||
fun togglePaidRelay(
|
|
||||||
relay: BasicRelaySetupInfo,
|
|
||||||
paid: Boolean,
|
|
||||||
) {
|
|
||||||
_relays.update { it.updated(relay, relay.copy(paidRelay = paid)) }
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -41,6 +41,8 @@ class Kind3RelayListViewModel : ViewModel() {
|
|||||||
private val _relays = MutableStateFlow<List<RelaySetupInfo>>(emptyList())
|
private val _relays = MutableStateFlow<List<RelaySetupInfo>>(emptyList())
|
||||||
val relays = _relays.asStateFlow()
|
val relays = _relays.asStateFlow()
|
||||||
|
|
||||||
|
var hasModified = false
|
||||||
|
|
||||||
fun load(account: Account) {
|
fun load(account: Account) {
|
||||||
this.account = account
|
this.account = account
|
||||||
clear()
|
clear()
|
||||||
@@ -48,9 +50,9 @@ class Kind3RelayListViewModel : ViewModel() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fun create() {
|
fun create() {
|
||||||
relays.let {
|
if (hasModified) {
|
||||||
viewModelScope.launch(Dispatchers.IO) {
|
viewModelScope.launch(Dispatchers.IO) {
|
||||||
account.saveRelayList(it.value)
|
account.saveKind3RelayList(relays.value)
|
||||||
clear()
|
clear()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -71,6 +73,7 @@ class Kind3RelayListViewModel : ViewModel() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fun clear() {
|
fun clear() {
|
||||||
|
hasModified = false
|
||||||
_relays.update {
|
_relays.update {
|
||||||
var relayFile = account.userProfile().latestContactList?.relays()
|
var relayFile = account.userProfile().latestContactList?.relays()
|
||||||
|
|
||||||
@@ -140,47 +143,58 @@ class Kind3RelayListViewModel : ViewModel() {
|
|||||||
if (relays.value.any { it.url == relay.url }) return
|
if (relays.value.any { it.url == relay.url }) return
|
||||||
|
|
||||||
_relays.update { it.plus(relay) }
|
_relays.update { it.plus(relay) }
|
||||||
|
|
||||||
|
hasModified = true
|
||||||
}
|
}
|
||||||
|
|
||||||
fun deleteRelay(relay: RelaySetupInfo) {
|
fun deleteRelay(relay: RelaySetupInfo) {
|
||||||
_relays.update { it.minus(relay) }
|
_relays.update { it.minus(relay) }
|
||||||
|
hasModified = true
|
||||||
}
|
}
|
||||||
|
|
||||||
fun deleteAll() {
|
fun deleteAll() {
|
||||||
_relays.update { relays -> emptyList() }
|
_relays.update { relays -> emptyList() }
|
||||||
|
hasModified = true
|
||||||
}
|
}
|
||||||
|
|
||||||
fun toggleDownload(relay: RelaySetupInfo) {
|
fun toggleDownload(relay: RelaySetupInfo) {
|
||||||
_relays.update { it.updated(relay, relay.copy(read = !relay.read)) }
|
_relays.update { it.updated(relay, relay.copy(read = !relay.read)) }
|
||||||
|
hasModified = true
|
||||||
}
|
}
|
||||||
|
|
||||||
fun toggleUpload(relay: RelaySetupInfo) {
|
fun toggleUpload(relay: RelaySetupInfo) {
|
||||||
_relays.update { it.updated(relay, relay.copy(write = !relay.write)) }
|
_relays.update { it.updated(relay, relay.copy(write = !relay.write)) }
|
||||||
|
hasModified = true
|
||||||
}
|
}
|
||||||
|
|
||||||
fun toggleFollows(relay: RelaySetupInfo) {
|
fun toggleFollows(relay: RelaySetupInfo) {
|
||||||
val newTypes = togglePresenceInSet(relay.feedTypes, FeedType.FOLLOWS)
|
val newTypes = togglePresenceInSet(relay.feedTypes, FeedType.FOLLOWS)
|
||||||
_relays.update { it.updated(relay, relay.copy(feedTypes = newTypes)) }
|
_relays.update { it.updated(relay, relay.copy(feedTypes = newTypes)) }
|
||||||
|
hasModified = true
|
||||||
}
|
}
|
||||||
|
|
||||||
fun toggleMessages(relay: RelaySetupInfo) {
|
fun toggleMessages(relay: RelaySetupInfo) {
|
||||||
val newTypes = togglePresenceInSet(relay.feedTypes, FeedType.PRIVATE_DMS)
|
val newTypes = togglePresenceInSet(relay.feedTypes, FeedType.PRIVATE_DMS)
|
||||||
_relays.update { it.updated(relay, relay.copy(feedTypes = newTypes)) }
|
_relays.update { it.updated(relay, relay.copy(feedTypes = newTypes)) }
|
||||||
|
hasModified = true
|
||||||
}
|
}
|
||||||
|
|
||||||
fun togglePublicChats(relay: RelaySetupInfo) {
|
fun togglePublicChats(relay: RelaySetupInfo) {
|
||||||
val newTypes = togglePresenceInSet(relay.feedTypes, FeedType.PUBLIC_CHATS)
|
val newTypes = togglePresenceInSet(relay.feedTypes, FeedType.PUBLIC_CHATS)
|
||||||
_relays.update { it.updated(relay, relay.copy(feedTypes = newTypes)) }
|
_relays.update { it.updated(relay, relay.copy(feedTypes = newTypes)) }
|
||||||
|
hasModified = true
|
||||||
}
|
}
|
||||||
|
|
||||||
fun toggleGlobal(relay: RelaySetupInfo) {
|
fun toggleGlobal(relay: RelaySetupInfo) {
|
||||||
val newTypes = togglePresenceInSet(relay.feedTypes, FeedType.GLOBAL)
|
val newTypes = togglePresenceInSet(relay.feedTypes, FeedType.GLOBAL)
|
||||||
_relays.update { it.updated(relay, relay.copy(feedTypes = newTypes)) }
|
_relays.update { it.updated(relay, relay.copy(feedTypes = newTypes)) }
|
||||||
|
hasModified = true
|
||||||
}
|
}
|
||||||
|
|
||||||
fun toggleSearch(relay: RelaySetupInfo) {
|
fun toggleSearch(relay: RelaySetupInfo) {
|
||||||
val newTypes = togglePresenceInSet(relay.feedTypes, FeedType.SEARCH)
|
val newTypes = togglePresenceInSet(relay.feedTypes, FeedType.SEARCH)
|
||||||
_relays.update { it.updated(relay, relay.copy(feedTypes = newTypes)) }
|
_relays.update { it.updated(relay, relay.copy(feedTypes = newTypes)) }
|
||||||
|
hasModified = true
|
||||||
}
|
}
|
||||||
|
|
||||||
fun togglePaidRelay(
|
fun togglePaidRelay(
|
||||||
|
@@ -20,90 +20,12 @@
|
|||||||
*/
|
*/
|
||||||
package com.vitorpamplona.amethyst.ui.actions.relays
|
package com.vitorpamplona.amethyst.ui.actions.relays
|
||||||
|
|
||||||
import androidx.lifecycle.ViewModel
|
class LocalRelayListViewModel : BasicRelaySetupInfoModel() {
|
||||||
import androidx.lifecycle.viewModelScope
|
override fun getRelayList(): List<String>? {
|
||||||
import com.vitorpamplona.amethyst.model.Account
|
return account.localRelayServers.toList()
|
||||||
import com.vitorpamplona.amethyst.service.Nip11CachedRetriever
|
|
||||||
import com.vitorpamplona.amethyst.service.relays.RelayPool
|
|
||||||
import kotlinx.coroutines.Dispatchers
|
|
||||||
import kotlinx.coroutines.flow.MutableStateFlow
|
|
||||||
import kotlinx.coroutines.flow.asStateFlow
|
|
||||||
import kotlinx.coroutines.flow.update
|
|
||||||
import kotlinx.coroutines.launch
|
|
||||||
|
|
||||||
class LocalRelayListViewModel : ViewModel() {
|
|
||||||
private lateinit var account: Account
|
|
||||||
|
|
||||||
private val _relays = MutableStateFlow<List<BasicRelaySetupInfo>>(emptyList())
|
|
||||||
val relays = _relays.asStateFlow()
|
|
||||||
|
|
||||||
fun load(account: Account) {
|
|
||||||
this.account = account
|
|
||||||
clear()
|
|
||||||
loadRelayDocuments()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fun create() {
|
override fun saveRelayList(urlList: List<String>) {
|
||||||
viewModelScope.launch(Dispatchers.IO) {
|
account.updateLocalRelayServers(urlList.toSet())
|
||||||
account.updateLocalRelayServers(_relays.value.map { it.url }.toSet())
|
|
||||||
clear()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fun loadRelayDocuments() {
|
|
||||||
viewModelScope.launch(Dispatchers.IO) {
|
|
||||||
_relays.value.forEach { item ->
|
|
||||||
Nip11CachedRetriever.loadRelayInfo(
|
|
||||||
dirtyUrl = item.url,
|
|
||||||
onInfo = {
|
|
||||||
togglePaidRelay(item, it.limitation?.payment_required ?: false)
|
|
||||||
},
|
|
||||||
onError = { url, errorCode, exceptionMessage -> },
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fun clear() {
|
|
||||||
_relays.update {
|
|
||||||
val relayList = account.localRelayServers ?: emptyList()
|
|
||||||
|
|
||||||
relayList.map { relayUrl ->
|
|
||||||
val liveRelay = RelayPool.getRelay(relayUrl)
|
|
||||||
val errorCounter = liveRelay?.errorCounter ?: 0
|
|
||||||
val eventDownloadCounter = liveRelay?.eventDownloadCounterInBytes ?: 0
|
|
||||||
val eventUploadCounter = liveRelay?.eventUploadCounterInBytes ?: 0
|
|
||||||
val spamCounter = liveRelay?.spamCounter ?: 0
|
|
||||||
|
|
||||||
BasicRelaySetupInfo(
|
|
||||||
relayUrl,
|
|
||||||
errorCounter,
|
|
||||||
eventDownloadCounter,
|
|
||||||
eventUploadCounter,
|
|
||||||
spamCounter,
|
|
||||||
)
|
|
||||||
}.distinctBy { it.url }.sortedBy { it.downloadCountInBytes }.reversed()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fun addRelay(relay: BasicRelaySetupInfo) {
|
|
||||||
if (relays.value.any { it.url == relay.url }) return
|
|
||||||
|
|
||||||
_relays.update { it.plus(relay) }
|
|
||||||
}
|
|
||||||
|
|
||||||
fun deleteRelay(relay: BasicRelaySetupInfo) {
|
|
||||||
_relays.update { it.minus(relay) }
|
|
||||||
}
|
|
||||||
|
|
||||||
fun deleteAll() {
|
|
||||||
_relays.update { relays -> emptyList() }
|
|
||||||
}
|
|
||||||
|
|
||||||
fun togglePaidRelay(
|
|
||||||
relay: BasicRelaySetupInfo,
|
|
||||||
paid: Boolean,
|
|
||||||
) {
|
|
||||||
_relays.update { it.updated(relay, relay.copy(paidRelay = paid)) }
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -41,6 +41,8 @@ class Nip65RelayListViewModel : ViewModel() {
|
|||||||
private val _notificationRelays = MutableStateFlow<List<BasicRelaySetupInfo>>(emptyList())
|
private val _notificationRelays = MutableStateFlow<List<BasicRelaySetupInfo>>(emptyList())
|
||||||
val notificationRelays = _notificationRelays.asStateFlow()
|
val notificationRelays = _notificationRelays.asStateFlow()
|
||||||
|
|
||||||
|
var hasModified = false
|
||||||
|
|
||||||
fun load(account: Account) {
|
fun load(account: Account) {
|
||||||
this.account = account
|
this.account = account
|
||||||
clear()
|
clear()
|
||||||
@@ -48,26 +50,28 @@ class Nip65RelayListViewModel : ViewModel() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fun create() {
|
fun create() {
|
||||||
viewModelScope.launch(Dispatchers.IO) {
|
if (hasModified) {
|
||||||
val writes = _homeRelays.value.map { it.url }.toSet()
|
viewModelScope.launch(Dispatchers.IO) {
|
||||||
val reads = _notificationRelays.value.map { it.url }.toSet()
|
val writes = _homeRelays.value.map { it.url }.toSet()
|
||||||
|
val reads = _notificationRelays.value.map { it.url }.toSet()
|
||||||
|
|
||||||
val urls = writes.union(reads)
|
val urls = writes.union(reads)
|
||||||
|
|
||||||
account.sendNip65RelayList(
|
account.sendNip65RelayList(
|
||||||
urls.map {
|
urls.map {
|
||||||
val type =
|
val type =
|
||||||
if (writes.contains(it) && reads.contains(it)) {
|
if (writes.contains(it) && reads.contains(it)) {
|
||||||
AdvertisedRelayListEvent.AdvertisedRelayType.BOTH
|
AdvertisedRelayListEvent.AdvertisedRelayType.BOTH
|
||||||
} else if (writes.contains(it)) {
|
} else if (writes.contains(it)) {
|
||||||
AdvertisedRelayListEvent.AdvertisedRelayType.WRITE
|
AdvertisedRelayListEvent.AdvertisedRelayType.WRITE
|
||||||
} else {
|
} else {
|
||||||
AdvertisedRelayListEvent.AdvertisedRelayType.READ
|
AdvertisedRelayListEvent.AdvertisedRelayType.READ
|
||||||
}
|
}
|
||||||
AdvertisedRelayListEvent.AdvertisedRelayInfo(it, type)
|
AdvertisedRelayListEvent.AdvertisedRelayInfo(it, type)
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
clear()
|
clear()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -96,18 +100,19 @@ class Nip65RelayListViewModel : ViewModel() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fun clear() {
|
fun clear() {
|
||||||
|
hasModified = false
|
||||||
_homeRelays.update {
|
_homeRelays.update {
|
||||||
val relayList = account.getNIP65RelayList()?.relays() ?: emptyList()
|
val relayList = account.getNIP65RelayList()?.writeRelays() ?: emptyList()
|
||||||
|
|
||||||
relayList.filter { it.type == AdvertisedRelayListEvent.AdvertisedRelayType.BOTH || it.type == AdvertisedRelayListEvent.AdvertisedRelayType.WRITE }.map { relayUrl ->
|
relayList.map { relayUrl ->
|
||||||
val liveRelay = RelayPool.getRelay(relayUrl.relayUrl)
|
val liveRelay = RelayPool.getRelay(relayUrl)
|
||||||
val errorCounter = liveRelay?.errorCounter ?: 0
|
val errorCounter = liveRelay?.errorCounter ?: 0
|
||||||
val eventDownloadCounter = liveRelay?.eventDownloadCounterInBytes ?: 0
|
val eventDownloadCounter = liveRelay?.eventDownloadCounterInBytes ?: 0
|
||||||
val eventUploadCounter = liveRelay?.eventUploadCounterInBytes ?: 0
|
val eventUploadCounter = liveRelay?.eventUploadCounterInBytes ?: 0
|
||||||
val spamCounter = liveRelay?.spamCounter ?: 0
|
val spamCounter = liveRelay?.spamCounter ?: 0
|
||||||
|
|
||||||
BasicRelaySetupInfo(
|
BasicRelaySetupInfo(
|
||||||
relayUrl.relayUrl,
|
relayUrl,
|
||||||
errorCounter,
|
errorCounter,
|
||||||
eventDownloadCounter,
|
eventDownloadCounter,
|
||||||
eventUploadCounter,
|
eventUploadCounter,
|
||||||
@@ -117,17 +122,17 @@ class Nip65RelayListViewModel : ViewModel() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
_notificationRelays.update {
|
_notificationRelays.update {
|
||||||
val relayList = account.getNIP65RelayList()?.relays() ?: emptyList()
|
val relayList = account.getNIP65RelayList()?.readRelays() ?: emptyList()
|
||||||
|
|
||||||
relayList.filter { it.type == AdvertisedRelayListEvent.AdvertisedRelayType.BOTH || it.type == AdvertisedRelayListEvent.AdvertisedRelayType.READ }.map { relayUrl ->
|
relayList.map { relayUrl ->
|
||||||
val liveRelay = RelayPool.getRelay(relayUrl.relayUrl)
|
val liveRelay = RelayPool.getRelay(relayUrl)
|
||||||
val errorCounter = liveRelay?.errorCounter ?: 0
|
val errorCounter = liveRelay?.errorCounter ?: 0
|
||||||
val eventDownloadCounter = liveRelay?.eventDownloadCounterInBytes ?: 0
|
val eventDownloadCounter = liveRelay?.eventDownloadCounterInBytes ?: 0
|
||||||
val eventUploadCounter = liveRelay?.eventUploadCounterInBytes ?: 0
|
val eventUploadCounter = liveRelay?.eventUploadCounterInBytes ?: 0
|
||||||
val spamCounter = liveRelay?.spamCounter ?: 0
|
val spamCounter = liveRelay?.spamCounter ?: 0
|
||||||
|
|
||||||
BasicRelaySetupInfo(
|
BasicRelaySetupInfo(
|
||||||
relayUrl.relayUrl,
|
relayUrl,
|
||||||
errorCounter,
|
errorCounter,
|
||||||
eventDownloadCounter,
|
eventDownloadCounter,
|
||||||
eventUploadCounter,
|
eventUploadCounter,
|
||||||
@@ -141,14 +146,17 @@ class Nip65RelayListViewModel : ViewModel() {
|
|||||||
if (_homeRelays.value.any { it.url == relay.url }) return
|
if (_homeRelays.value.any { it.url == relay.url }) return
|
||||||
|
|
||||||
_homeRelays.update { it.plus(relay) }
|
_homeRelays.update { it.plus(relay) }
|
||||||
|
hasModified = true
|
||||||
}
|
}
|
||||||
|
|
||||||
fun deleteHomeRelay(relay: BasicRelaySetupInfo) {
|
fun deleteHomeRelay(relay: BasicRelaySetupInfo) {
|
||||||
_homeRelays.update { it.minus(relay) }
|
_homeRelays.update { it.minus(relay) }
|
||||||
|
hasModified = true
|
||||||
}
|
}
|
||||||
|
|
||||||
fun deleteHomeAll() {
|
fun deleteHomeAll() {
|
||||||
_homeRelays.update { relays -> emptyList() }
|
_homeRelays.update { relays -> emptyList() }
|
||||||
|
hasModified = true
|
||||||
}
|
}
|
||||||
|
|
||||||
fun toggleHomePaidRelay(
|
fun toggleHomePaidRelay(
|
||||||
@@ -162,14 +170,17 @@ class Nip65RelayListViewModel : ViewModel() {
|
|||||||
if (_notificationRelays.value.any { it.url == relay.url }) return
|
if (_notificationRelays.value.any { it.url == relay.url }) return
|
||||||
|
|
||||||
_notificationRelays.update { it.plus(relay) }
|
_notificationRelays.update { it.plus(relay) }
|
||||||
|
hasModified = true
|
||||||
}
|
}
|
||||||
|
|
||||||
fun deleteNotifRelay(relay: BasicRelaySetupInfo) {
|
fun deleteNotifRelay(relay: BasicRelaySetupInfo) {
|
||||||
_notificationRelays.update { it.minus(relay) }
|
_notificationRelays.update { it.minus(relay) }
|
||||||
|
hasModified = true
|
||||||
}
|
}
|
||||||
|
|
||||||
fun deleteNotifAll() {
|
fun deleteNotifAll() {
|
||||||
_notificationRelays.update { relays -> emptyList() }
|
_notificationRelays.update { relays -> emptyList() }
|
||||||
|
hasModified = true
|
||||||
}
|
}
|
||||||
|
|
||||||
fun toggleNotifPaidRelay(
|
fun toggleNotifPaidRelay(
|
||||||
|
@@ -20,90 +20,12 @@
|
|||||||
*/
|
*/
|
||||||
package com.vitorpamplona.amethyst.ui.actions.relays
|
package com.vitorpamplona.amethyst.ui.actions.relays
|
||||||
|
|
||||||
import androidx.lifecycle.ViewModel
|
class PrivateOutboxRelayListViewModel : BasicRelaySetupInfoModel() {
|
||||||
import androidx.lifecycle.viewModelScope
|
override fun getRelayList(): List<String>? {
|
||||||
import com.vitorpamplona.amethyst.model.Account
|
return account.getPrivateOutboxRelayList()?.relays()
|
||||||
import com.vitorpamplona.amethyst.service.Nip11CachedRetriever
|
|
||||||
import com.vitorpamplona.amethyst.service.relays.RelayPool
|
|
||||||
import kotlinx.coroutines.Dispatchers
|
|
||||||
import kotlinx.coroutines.flow.MutableStateFlow
|
|
||||||
import kotlinx.coroutines.flow.asStateFlow
|
|
||||||
import kotlinx.coroutines.flow.update
|
|
||||||
import kotlinx.coroutines.launch
|
|
||||||
|
|
||||||
class PrivateOutboxRelayListViewModel : ViewModel() {
|
|
||||||
private lateinit var account: Account
|
|
||||||
|
|
||||||
private val _relays = MutableStateFlow<List<BasicRelaySetupInfo>>(emptyList())
|
|
||||||
val relays = _relays.asStateFlow()
|
|
||||||
|
|
||||||
fun load(account: Account) {
|
|
||||||
this.account = account
|
|
||||||
clear()
|
|
||||||
loadRelayDocuments()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fun create() {
|
override fun saveRelayList(urlList: List<String>) {
|
||||||
viewModelScope.launch(Dispatchers.IO) {
|
account.savePrivateOutboxRelayList(urlList)
|
||||||
account.savePrivateOutboxRelayList(_relays.value.map { it.url })
|
|
||||||
clear()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fun loadRelayDocuments() {
|
|
||||||
viewModelScope.launch(Dispatchers.IO) {
|
|
||||||
_relays.value.forEach { item ->
|
|
||||||
Nip11CachedRetriever.loadRelayInfo(
|
|
||||||
dirtyUrl = item.url,
|
|
||||||
onInfo = {
|
|
||||||
togglePaidRelay(item, it.limitation?.payment_required ?: false)
|
|
||||||
},
|
|
||||||
onError = { url, errorCode, exceptionMessage -> },
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fun clear() {
|
|
||||||
_relays.update {
|
|
||||||
val relayList = account.getPrivateOutboxRelayList()?.relays() ?: emptyList()
|
|
||||||
|
|
||||||
relayList.map { relayUrl ->
|
|
||||||
val liveRelay = RelayPool.getRelay(relayUrl)
|
|
||||||
val errorCounter = liveRelay?.errorCounter ?: 0
|
|
||||||
val eventDownloadCounter = liveRelay?.eventDownloadCounterInBytes ?: 0
|
|
||||||
val eventUploadCounter = liveRelay?.eventUploadCounterInBytes ?: 0
|
|
||||||
val spamCounter = liveRelay?.spamCounter ?: 0
|
|
||||||
|
|
||||||
BasicRelaySetupInfo(
|
|
||||||
relayUrl,
|
|
||||||
errorCounter,
|
|
||||||
eventDownloadCounter,
|
|
||||||
eventUploadCounter,
|
|
||||||
spamCounter,
|
|
||||||
)
|
|
||||||
}.distinctBy { it.url }.sortedBy { it.downloadCountInBytes }.reversed()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fun addRelay(relay: BasicRelaySetupInfo) {
|
|
||||||
if (relays.value.any { it.url == relay.url }) return
|
|
||||||
|
|
||||||
_relays.update { it.plus(relay) }
|
|
||||||
}
|
|
||||||
|
|
||||||
fun deleteRelay(relay: BasicRelaySetupInfo) {
|
|
||||||
_relays.update { it.minus(relay) }
|
|
||||||
}
|
|
||||||
|
|
||||||
fun deleteAll() {
|
|
||||||
_relays.update { relays -> emptyList() }
|
|
||||||
}
|
|
||||||
|
|
||||||
fun togglePaidRelay(
|
|
||||||
relay: BasicRelaySetupInfo,
|
|
||||||
paid: Boolean,
|
|
||||||
) {
|
|
||||||
_relays.update { it.updated(relay, relay.copy(paidRelay = paid)) }
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -20,90 +20,12 @@
|
|||||||
*/
|
*/
|
||||||
package com.vitorpamplona.amethyst.ui.actions.relays
|
package com.vitorpamplona.amethyst.ui.actions.relays
|
||||||
|
|
||||||
import androidx.lifecycle.ViewModel
|
class SearchRelayListViewModel : BasicRelaySetupInfoModel() {
|
||||||
import androidx.lifecycle.viewModelScope
|
override fun getRelayList(): List<String>? {
|
||||||
import com.vitorpamplona.amethyst.model.Account
|
return account.getSearchRelayList()?.relays()
|
||||||
import com.vitorpamplona.amethyst.service.Nip11CachedRetriever
|
|
||||||
import com.vitorpamplona.amethyst.service.relays.RelayPool
|
|
||||||
import kotlinx.coroutines.Dispatchers
|
|
||||||
import kotlinx.coroutines.flow.MutableStateFlow
|
|
||||||
import kotlinx.coroutines.flow.asStateFlow
|
|
||||||
import kotlinx.coroutines.flow.update
|
|
||||||
import kotlinx.coroutines.launch
|
|
||||||
|
|
||||||
class SearchRelayListViewModel : ViewModel() {
|
|
||||||
private lateinit var account: Account
|
|
||||||
|
|
||||||
private val _relays = MutableStateFlow<List<BasicRelaySetupInfo>>(emptyList())
|
|
||||||
val relays = _relays.asStateFlow()
|
|
||||||
|
|
||||||
fun load(account: Account) {
|
|
||||||
this.account = account
|
|
||||||
clear()
|
|
||||||
loadRelayDocuments()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fun create() {
|
override fun saveRelayList(urlList: List<String>) {
|
||||||
viewModelScope.launch(Dispatchers.IO) {
|
account.saveSearchRelayList(urlList)
|
||||||
account.saveSearchRelayList(_relays.value.map { it.url })
|
|
||||||
clear()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fun loadRelayDocuments() {
|
|
||||||
viewModelScope.launch(Dispatchers.IO) {
|
|
||||||
_relays.value.forEach { item ->
|
|
||||||
Nip11CachedRetriever.loadRelayInfo(
|
|
||||||
dirtyUrl = item.url,
|
|
||||||
onInfo = {
|
|
||||||
togglePaidRelay(item, it.limitation?.payment_required ?: false)
|
|
||||||
},
|
|
||||||
onError = { url, errorCode, exceptionMessage -> },
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fun clear() {
|
|
||||||
_relays.update {
|
|
||||||
val relayList = account.getSearchRelayList()?.relays() ?: emptyList()
|
|
||||||
|
|
||||||
relayList.map { relayUrl ->
|
|
||||||
val liveRelay = RelayPool.getRelay(relayUrl)
|
|
||||||
val errorCounter = liveRelay?.errorCounter ?: 0
|
|
||||||
val eventDownloadCounter = liveRelay?.eventDownloadCounterInBytes ?: 0
|
|
||||||
val eventUploadCounter = liveRelay?.eventUploadCounterInBytes ?: 0
|
|
||||||
val spamCounter = liveRelay?.spamCounter ?: 0
|
|
||||||
|
|
||||||
BasicRelaySetupInfo(
|
|
||||||
relayUrl,
|
|
||||||
errorCounter,
|
|
||||||
eventDownloadCounter,
|
|
||||||
eventUploadCounter,
|
|
||||||
spamCounter,
|
|
||||||
)
|
|
||||||
}.distinctBy { it.url }.sortedBy { it.downloadCountInBytes }.reversed()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fun addRelay(relay: BasicRelaySetupInfo) {
|
|
||||||
if (relays.value.any { it.url == relay.url }) return
|
|
||||||
|
|
||||||
_relays.update { it.plus(relay) }
|
|
||||||
}
|
|
||||||
|
|
||||||
fun deleteRelay(relay: BasicRelaySetupInfo) {
|
|
||||||
_relays.update { it.minus(relay) }
|
|
||||||
}
|
|
||||||
|
|
||||||
fun deleteAll() {
|
|
||||||
_relays.update { relays -> emptyList() }
|
|
||||||
}
|
|
||||||
|
|
||||||
fun togglePaidRelay(
|
|
||||||
relay: BasicRelaySetupInfo,
|
|
||||||
paid: Boolean,
|
|
||||||
) {
|
|
||||||
_relays.update { it.updated(relay, relay.copy(paidRelay = paid)) }
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user