refactor(repo,vm): drop local relay persistence and viewmodel state
Removes the local_relay SharedPrefs entry, KeyRepository's localRelayFlow / save/get/load helpers, and RelayViewModel's local-relay state and update methods. StartupCoordinator no longer wires the relay pool to localRelayFlow. reloadPrefs clears the orphaned local_relay key on account switch.
This commit is contained in:
@@ -55,7 +55,7 @@ class BlossomRepository(private val context: Context, pubkeyHex: String? = null)
|
||||
|
||||
// In-memory reset only. `prefs` is shared with KeyRepository
|
||||
// (`wisp_prefs_{pubkey}`), so `prefs.edit().clear()` would also wipe
|
||||
// `local_relay`, `relays`, `dm_relays`, etc. `reload(newPubkey)` below
|
||||
// `relays`, `dm_relays`, etc. `reload(newPubkey)` below
|
||||
// repoints to the new account's file.
|
||||
fun clear() {
|
||||
_servers.value = listOf(Blossom.DEFAULT_SERVER)
|
||||
|
||||
@@ -8,7 +8,6 @@ import com.wisp.app.nostr.Keys
|
||||
import com.wisp.app.nostr.Nip19
|
||||
import com.wisp.app.nostr.hexToByteArray
|
||||
import com.wisp.app.nostr.toHex
|
||||
import com.wisp.app.relay.LocalRelayConfig
|
||||
import com.wisp.app.relay.RelayConfig
|
||||
import kotlinx.coroutines.flow.MutableStateFlow
|
||||
import kotlinx.coroutines.flow.StateFlow
|
||||
@@ -63,9 +62,6 @@ class KeyRepository(private val context: Context) {
|
||||
private val _blockedRelays = MutableStateFlow(loadBlockedRelays())
|
||||
val blockedRelaysFlow: StateFlow<List<String>> = _blockedRelays
|
||||
|
||||
private val _localRelay = MutableStateFlow(loadLocalRelay())
|
||||
val localRelayFlow: StateFlow<LocalRelayConfig?> = _localRelay
|
||||
|
||||
// Strong reference to prevent GC — listener syncs flows when prefs change from any instance
|
||||
private val prefsListener = SharedPreferences.OnSharedPreferenceChangeListener { _, key ->
|
||||
when (key) {
|
||||
@@ -73,7 +69,6 @@ class KeyRepository(private val context: Context) {
|
||||
"dm_relays" -> _dmRelays.value = loadDmRelays()
|
||||
"search_relays" -> _searchRelays.value = loadSearchRelays()
|
||||
"blocked_relays" -> _blockedRelays.value = loadBlockedRelays()
|
||||
"local_relay" -> _localRelay.value = loadLocalRelay()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -324,7 +319,7 @@ class KeyRepository(private val context: Context) {
|
||||
_dmRelays.value = loadDmRelays()
|
||||
_searchRelays.value = loadSearchRelays()
|
||||
_blockedRelays.value = loadBlockedRelays()
|
||||
_localRelay.value = loadLocalRelay()
|
||||
prefs.edit().remove("local_relay").apply()
|
||||
}
|
||||
|
||||
fun saveRelays(relays: List<RelayConfig>) {
|
||||
@@ -379,22 +374,6 @@ class KeyRepository(private val context: Context) {
|
||||
return try { json.decodeFromString(str) } catch (_: Exception) { emptyList() }
|
||||
}
|
||||
|
||||
fun saveLocalRelay(config: LocalRelayConfig?) {
|
||||
if (config != null) {
|
||||
prefs.edit().putString("local_relay", json.encodeToString(config)).apply()
|
||||
} else {
|
||||
prefs.edit().remove("local_relay").apply()
|
||||
}
|
||||
_localRelay.value = config
|
||||
}
|
||||
|
||||
fun getLocalRelay(): LocalRelayConfig? = _localRelay.value
|
||||
|
||||
private fun loadLocalRelay(): LocalRelayConfig? {
|
||||
val str = prefs.getString("local_relay", null) ?: return null
|
||||
return try { json.decodeFromString(str) } catch (_: Exception) { null }
|
||||
}
|
||||
|
||||
fun isOnboardingComplete(): Boolean {
|
||||
if (prefs.getBoolean("onboarding_done", false)) return true
|
||||
// Migration for existing users who had the app before onboarding was added:
|
||||
|
||||
@@ -9,8 +9,6 @@ import com.wisp.app.nostr.Nip51
|
||||
import com.wisp.app.nostr.Nip65
|
||||
import com.wisp.app.nostr.NostrEvent
|
||||
import com.wisp.app.nostr.NostrSigner
|
||||
import com.wisp.app.relay.LocalRelayConfig
|
||||
import com.wisp.app.relay.LocalRelayWritePolicy
|
||||
import com.wisp.app.relay.RelayConfig
|
||||
import com.wisp.app.relay.RelayPool
|
||||
import com.wisp.app.relay.RelaySetType
|
||||
@@ -30,7 +28,6 @@ class RelayViewModel(app: Application) : AndroidViewModel(app) {
|
||||
val dmRelays: StateFlow<List<String>> = keyRepo.dmRelaysFlow
|
||||
val searchRelays: StateFlow<List<String>> = keyRepo.searchRelaysFlow
|
||||
val blockedRelays: StateFlow<List<String>> = keyRepo.blockedRelaysFlow
|
||||
val localRelay: StateFlow<LocalRelayConfig?> = keyRepo.localRelayFlow
|
||||
|
||||
/** Re-point prefs at the current user's file so flows pick up their relay data. */
|
||||
fun reload() {
|
||||
@@ -52,36 +49,26 @@ class RelayViewModel(app: Application) : AndroidViewModel(app) {
|
||||
fun addRelay(): Boolean {
|
||||
val url = _newRelayUrl.value.trim().trimEnd('/')
|
||||
if (url.isBlank()) return false
|
||||
if (!RelayConfig.isValidUrl(url)) return false
|
||||
|
||||
when (_selectedTab.value) {
|
||||
RelaySetType.LOCAL -> {
|
||||
if (!RelayConfig.isLocalRelayUrl(url)) return false
|
||||
if (localRelay.value != null) return false
|
||||
keyRepo.saveLocalRelay(LocalRelayConfig(url))
|
||||
RelaySetType.GENERAL -> {
|
||||
if (relays.value.any { it.url == url }) return false
|
||||
keyRepo.saveRelays(relays.value + RelayConfig(url))
|
||||
}
|
||||
else -> {
|
||||
if (!RelayConfig.isValidUrl(url)) return false
|
||||
when (_selectedTab.value) {
|
||||
RelaySetType.GENERAL -> {
|
||||
if (relays.value.any { it.url == url }) return false
|
||||
keyRepo.saveRelays(relays.value + RelayConfig(url))
|
||||
}
|
||||
RelaySetType.DM -> {
|
||||
if (url in dmRelays.value) return false
|
||||
keyRepo.saveDmRelays(dmRelays.value + url)
|
||||
}
|
||||
RelaySetType.SEARCH -> {
|
||||
if (url in searchRelays.value) return false
|
||||
keyRepo.saveSearchRelays(searchRelays.value + url)
|
||||
}
|
||||
RelaySetType.BLOCKED -> {
|
||||
if (url in blockedRelays.value) return false
|
||||
val updated = blockedRelays.value + url
|
||||
keyRepo.saveBlockedRelays(updated)
|
||||
relayPool?.updateBlockedUrls(updated)
|
||||
}
|
||||
else -> {}
|
||||
}
|
||||
RelaySetType.DM -> {
|
||||
if (url in dmRelays.value) return false
|
||||
keyRepo.saveDmRelays(dmRelays.value + url)
|
||||
}
|
||||
RelaySetType.SEARCH -> {
|
||||
if (url in searchRelays.value) return false
|
||||
keyRepo.saveSearchRelays(searchRelays.value + url)
|
||||
}
|
||||
RelaySetType.BLOCKED -> {
|
||||
if (url in blockedRelays.value) return false
|
||||
val updated = blockedRelays.value + url
|
||||
keyRepo.saveBlockedRelays(updated)
|
||||
relayPool?.updateBlockedUrls(updated)
|
||||
}
|
||||
}
|
||||
_newRelayUrl.value = ""
|
||||
@@ -104,9 +91,6 @@ class RelayViewModel(app: Application) : AndroidViewModel(app) {
|
||||
keyRepo.saveBlockedRelays(updated)
|
||||
relayPool?.updateBlockedUrls(updated)
|
||||
}
|
||||
RelaySetType.LOCAL -> {
|
||||
keyRepo.saveLocalRelay(null)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -131,46 +115,26 @@ class RelayViewModel(app: Application) : AndroidViewModel(app) {
|
||||
keyRepo.saveRelays(updated)
|
||||
}
|
||||
|
||||
fun toggleLocalRelayEnabled() {
|
||||
val current = localRelay.value ?: return
|
||||
keyRepo.saveLocalRelay(current.copy(enabled = !current.enabled))
|
||||
}
|
||||
|
||||
fun updateLocalRelayPolicy(writePolicy: LocalRelayWritePolicy) {
|
||||
val current = localRelay.value ?: return
|
||||
keyRepo.saveLocalRelay(current.copy(writePolicy = writePolicy))
|
||||
}
|
||||
|
||||
fun updateLocalRelayKinds(kinds: Set<Int>) {
|
||||
val current = localRelay.value ?: return
|
||||
keyRepo.saveLocalRelay(current.copy(kinds = kinds))
|
||||
}
|
||||
|
||||
fun publishRelayList(relayPool: RelayPool, signer: NostrSigner? = null): Boolean {
|
||||
val s = signer ?: keyRepo.getKeypair()?.let { LocalSigner(it.privkey, it.pubkey) } ?: return false
|
||||
return try {
|
||||
val tab = _selectedTab.value
|
||||
val tags: List<List<String>>
|
||||
val kind: Int
|
||||
val kind: Int = tab.eventKind
|
||||
|
||||
when (tab) {
|
||||
RelaySetType.GENERAL -> {
|
||||
tags = Nip65.buildRelayTags(relays.value)
|
||||
kind = tab.eventKind
|
||||
}
|
||||
RelaySetType.DM -> {
|
||||
tags = Nip51.buildRelaySetTags(dmRelays.value)
|
||||
kind = tab.eventKind
|
||||
}
|
||||
RelaySetType.SEARCH -> {
|
||||
tags = Nip51.buildRelaySetTags(searchRelays.value)
|
||||
kind = tab.eventKind
|
||||
}
|
||||
RelaySetType.BLOCKED -> {
|
||||
tags = Nip51.buildRelaySetTags(blockedRelays.value)
|
||||
kind = tab.eventKind
|
||||
}
|
||||
RelaySetType.LOCAL -> return false // Local relays are never published
|
||||
}
|
||||
|
||||
viewModelScope.launch {
|
||||
|
||||
@@ -227,16 +227,6 @@ class StartupCoordinator(
|
||||
relayPool.updateDmRelays(dmRelays)
|
||||
eventRepo.dmRelayUrls = dmRelays.toSet()
|
||||
|
||||
// Connect local relay if configured
|
||||
relayPool.updateLocalRelay(keyRepo.getLocalRelay(), getUserPubkey())
|
||||
|
||||
// Observe local relay config changes
|
||||
scope.launch {
|
||||
keyRepo.localRelayFlow.drop(1).collectLatest { config ->
|
||||
relayPool.updateLocalRelay(config, getUserPubkey())
|
||||
}
|
||||
}
|
||||
|
||||
scope.launch {
|
||||
relayInfoRepo.prefetchAll(initialRelays.map { it.url })
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user