kopia lustrzana https://github.com/vitorpamplona/amethyst
Upgrades the RelayPoolStatus to a Flow
rodzic
6a3206b938
commit
db740f4747
|
@ -1,9 +1,13 @@
|
|||
package com.vitorpamplona.amethyst.service.relays
|
||||
|
||||
import androidx.lifecycle.LiveData
|
||||
import androidx.compose.runtime.Immutable
|
||||
import com.vitorpamplona.amethyst.service.checkNotInMainThread
|
||||
import com.vitorpamplona.quartz.events.Event
|
||||
import com.vitorpamplona.quartz.events.EventInterface
|
||||
import kotlinx.coroutines.channels.BufferOverflow
|
||||
import kotlinx.coroutines.flow.MutableSharedFlow
|
||||
import kotlinx.coroutines.flow.SharedFlow
|
||||
import kotlinx.coroutines.flow.asSharedFlow
|
||||
|
||||
/**
|
||||
* RelayPool manages the connection to multiple Relays and lets consumers deal with simple events.
|
||||
|
@ -12,6 +16,11 @@ object RelayPool : Relay.Listener {
|
|||
private var relays = listOf<Relay>()
|
||||
private var listeners = setOf<Listener>()
|
||||
|
||||
// Backing property to avoid flow emissions from other classes
|
||||
private var _lastStatus = RelayPoolStatus(0, 0)
|
||||
private val _statusFlow = MutableSharedFlow<RelayPoolStatus>(1, 1, onBufferOverflow = BufferOverflow.DROP_OLDEST)
|
||||
val statusFlow: SharedFlow<RelayPoolStatus> = _statusFlow.asSharedFlow()
|
||||
|
||||
fun availableRelays(): Int {
|
||||
return relays.size
|
||||
}
|
||||
|
@ -76,11 +85,13 @@ object RelayPool : Relay.Listener {
|
|||
fun addRelay(relay: Relay) {
|
||||
relay.register(this)
|
||||
relays += relay
|
||||
updateStatus()
|
||||
}
|
||||
|
||||
fun removeRelay(relay: Relay) {
|
||||
relay.unregister(this)
|
||||
relays = relays.minus(relay)
|
||||
updateStatus()
|
||||
}
|
||||
|
||||
fun register(listener: Listener) {
|
||||
|
@ -109,12 +120,14 @@ object RelayPool : Relay.Listener {
|
|||
|
||||
override fun onError(relay: Relay, subscriptionId: String, error: Error) {
|
||||
listeners.forEach { it.onError(error, subscriptionId, relay) }
|
||||
refreshObservers()
|
||||
updateStatus()
|
||||
}
|
||||
|
||||
override fun onRelayStateChange(relay: Relay, type: Relay.Type, channel: String?) {
|
||||
listeners.forEach { it.onRelayStateChange(type, relay, channel) }
|
||||
refreshObservers()
|
||||
if (type != Relay.Type.EOSE) {
|
||||
updateStatus()
|
||||
}
|
||||
}
|
||||
|
||||
override fun onSendResponse(relay: Relay, eventId: String, success: Boolean, message: String) {
|
||||
|
@ -125,18 +138,15 @@ object RelayPool : Relay.Listener {
|
|||
listeners.forEach { it.onAuth(relay, challenge) }
|
||||
}
|
||||
|
||||
// Observers line up here.
|
||||
val live: RelayPoolLiveData = RelayPoolLiveData(this)
|
||||
|
||||
private fun refreshObservers() {
|
||||
live.refresh()
|
||||
private fun updateStatus() {
|
||||
val connected = connectedRelays()
|
||||
val available = availableRelays()
|
||||
if (_lastStatus.connected != connected || _lastStatus.available != available) {
|
||||
_lastStatus = RelayPoolStatus(connected, available)
|
||||
_statusFlow.tryEmit(_lastStatus)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class RelayPoolLiveData(val relays: RelayPool) : LiveData<RelayPoolState>(RelayPoolState(relays)) {
|
||||
fun refresh() {
|
||||
postValue(RelayPoolState(relays))
|
||||
}
|
||||
}
|
||||
|
||||
class RelayPoolState(val relays: RelayPool)
|
||||
@Immutable
|
||||
data class RelayPoolStatus(val connected: Int, val available: Int, val isConnected: Boolean = connected > 0)
|
||||
|
|
|
@ -40,6 +40,7 @@ import androidx.compose.material.icons.filled.Send
|
|||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.LaunchedEffect
|
||||
import androidx.compose.runtime.MutableState
|
||||
import androidx.compose.runtime.collectAsState
|
||||
import androidx.compose.runtime.derivedStateOf
|
||||
import androidx.compose.runtime.getValue
|
||||
import androidx.compose.runtime.livedata.observeAsState
|
||||
|
@ -63,7 +64,6 @@ import androidx.compose.ui.text.style.TextOverflow
|
|||
import androidx.compose.ui.unit.dp
|
||||
import androidx.compose.ui.unit.sp
|
||||
import androidx.lifecycle.map
|
||||
import androidx.lifecycle.viewmodel.compose.viewModel
|
||||
import coil.compose.AsyncImage
|
||||
import com.vitorpamplona.amethyst.BuildConfig
|
||||
import com.vitorpamplona.amethyst.LocalPreferences
|
||||
|
@ -72,11 +72,12 @@ import com.vitorpamplona.amethyst.ServiceManager
|
|||
import com.vitorpamplona.amethyst.model.Account
|
||||
import com.vitorpamplona.amethyst.model.User
|
||||
import com.vitorpamplona.amethyst.service.HttpClient
|
||||
import com.vitorpamplona.amethyst.service.relays.RelayPool
|
||||
import com.vitorpamplona.amethyst.service.relays.RelayPoolStatus
|
||||
import com.vitorpamplona.amethyst.ui.actions.NewRelayListView
|
||||
import com.vitorpamplona.amethyst.ui.components.CreateTextWithEmoji
|
||||
import com.vitorpamplona.amethyst.ui.components.RobohashAsyncImageProxy
|
||||
import com.vitorpamplona.amethyst.ui.note.LoadStatuses
|
||||
import com.vitorpamplona.amethyst.ui.screen.RelayPoolViewModel
|
||||
import com.vitorpamplona.amethyst.ui.screen.loggedIn.AccountBackupDialog
|
||||
import com.vitorpamplona.amethyst.ui.screen.loggedIn.AccountViewModel
|
||||
import com.vitorpamplona.amethyst.ui.screen.loggedIn.ConnectOrbotDialog
|
||||
|
@ -454,7 +455,6 @@ fun ListContent(
|
|||
}
|
||||
|
||||
val coroutineScope = rememberCoroutineScope()
|
||||
val relayViewModel: RelayPoolViewModel = viewModel { RelayPoolViewModel() }
|
||||
var wantsToEditRelays by remember {
|
||||
mutableStateOf(false)
|
||||
}
|
||||
|
@ -490,7 +490,7 @@ fun ListContent(
|
|||
)
|
||||
|
||||
IconRowRelays(
|
||||
relayViewModel = relayViewModel,
|
||||
accountViewModel = accountViewModel,
|
||||
onClick = {
|
||||
coroutineScope.launch {
|
||||
scaffoldState.drawerState.close()
|
||||
|
@ -633,27 +633,37 @@ private fun enableTor(
|
|||
}
|
||||
|
||||
@Composable
|
||||
private fun RelayStatus(
|
||||
relayViewModel: RelayPoolViewModel
|
||||
) {
|
||||
val connectedRelaysText by relayViewModel.connectionStatus.observeAsState("--/--")
|
||||
val isConnected by relayViewModel.isConnected.observeAsState(false)
|
||||
private fun RelayStatus(accountViewModel: AccountViewModel) {
|
||||
val connectedRelaysText by RelayPool.statusFlow.collectAsState(initial = RelayPoolStatus(0, 0))
|
||||
|
||||
RenderRelayStatus(connectedRelaysText, isConnected)
|
||||
RenderRelayStatus(connectedRelaysText)
|
||||
}
|
||||
|
||||
@Composable
|
||||
private fun RenderRelayStatus(
|
||||
connectedRelaysText: String,
|
||||
isConnected: Boolean
|
||||
relayPool: RelayPoolStatus
|
||||
) {
|
||||
val text by remember(relayPool) {
|
||||
derivedStateOf {
|
||||
"${relayPool.connected}/${relayPool.available}"
|
||||
}
|
||||
}
|
||||
|
||||
val placeHolder = MaterialTheme.colors.placeholderText
|
||||
|
||||
val color by remember(relayPool) {
|
||||
derivedStateOf {
|
||||
if (relayPool.isConnected) {
|
||||
placeHolder
|
||||
} else {
|
||||
Color.Red
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Text(
|
||||
text = connectedRelaysText,
|
||||
color = if (isConnected) {
|
||||
MaterialTheme.colors.placeholderText
|
||||
} else {
|
||||
Color.Red
|
||||
},
|
||||
text = text,
|
||||
color = color,
|
||||
style = MaterialTheme.typography.subtitle1
|
||||
)
|
||||
}
|
||||
|
@ -709,7 +719,7 @@ fun IconRow(title: String, icon: Int, tint: Color, onClick: () -> Unit, onLongCl
|
|||
}
|
||||
|
||||
@Composable
|
||||
fun IconRowRelays(relayViewModel: RelayPoolViewModel, onClick: () -> Unit) {
|
||||
fun IconRowRelays(accountViewModel: AccountViewModel, onClick: () -> Unit) {
|
||||
Row(
|
||||
modifier = Modifier
|
||||
.fillMaxWidth()
|
||||
|
@ -736,7 +746,7 @@ fun IconRowRelays(relayViewModel: RelayPoolViewModel, onClick: () -> Unit) {
|
|||
|
||||
Spacer(modifier = Modifier.width(Size16dp))
|
||||
|
||||
RelayStatus(relayViewModel = relayViewModel)
|
||||
RelayStatus(accountViewModel = accountViewModel)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,20 +0,0 @@
|
|||
package com.vitorpamplona.amethyst.ui.screen
|
||||
|
||||
import androidx.compose.runtime.Stable
|
||||
import androidx.lifecycle.ViewModel
|
||||
import androidx.lifecycle.distinctUntilChanged
|
||||
import androidx.lifecycle.map
|
||||
import com.vitorpamplona.amethyst.service.relays.RelayPool
|
||||
|
||||
@Stable
|
||||
class RelayPoolViewModel : ViewModel() {
|
||||
val connectionStatus = RelayPool.live.map {
|
||||
val connectedRelays = it.relays.connectedRelays()
|
||||
val availableRelays = it.relays.availableRelays()
|
||||
"$connectedRelays/$availableRelays"
|
||||
}.distinctUntilChanged()
|
||||
|
||||
val isConnected = RelayPool.live.map {
|
||||
it.relays.connectedRelays() > 0
|
||||
}.distinctUntilChanged()
|
||||
}
|
Ładowanie…
Reference in New Issue