mirror of
https://github.com/vitorpamplona/amethyst.git
synced 2025-06-29 13:00:40 +02:00
This commit is contained in:
@ -41,7 +41,7 @@ class User(val pubkeyHex: String) {
|
|||||||
val messages = ConcurrentHashMap<User, MutableSet<Note>>()
|
val messages = ConcurrentHashMap<User, MutableSet<Note>>()
|
||||||
|
|
||||||
val reports = Collections.synchronizedSet(mutableSetOf<Note>())
|
val reports = Collections.synchronizedSet(mutableSetOf<Note>())
|
||||||
val relaysBeingUsed = mutableMapOf<String, RelayInfo>()
|
val relaysBeingUsed = Collections.synchronizedMap(mutableMapOf<String, RelayInfo>())
|
||||||
|
|
||||||
fun toBestDisplayName(): String {
|
fun toBestDisplayName(): String {
|
||||||
return bestDisplayName() ?: bestUsername() ?: pubkeyDisplayHex
|
return bestDisplayName() ?: bestUsername() ?: pubkeyDisplayHex
|
||||||
@ -191,6 +191,18 @@ class User(val pubkeyHex: String) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun getRelayKeysBeingUsed(): Set<String> {
|
||||||
|
return synchronized(relaysBeingUsed) {
|
||||||
|
relaysBeingUsed.keys.toSet()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun getRelayValuesBeingUsed(): List<RelayInfo> {
|
||||||
|
return synchronized(relaysBeingUsed) {
|
||||||
|
relaysBeingUsed.values.toList()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fun hasSentMessagesTo(user: User?): Boolean {
|
fun hasSentMessagesTo(user: User?): Boolean {
|
||||||
val messagesToUser = messages[user] ?: return false
|
val messagesToUser = messages[user] ?: return false
|
||||||
|
|
||||||
|
@ -65,7 +65,7 @@ fun RelayCompose(
|
|||||||
}
|
}
|
||||||
|
|
||||||
Text(
|
Text(
|
||||||
"${relay.counter} events received",
|
"${relay.counter} posts received",
|
||||||
color = MaterialTheme.colors.onSurface.copy(alpha = 0.32f),
|
color = MaterialTheme.colors.onSurface.copy(alpha = 0.32f),
|
||||||
maxLines = 1,
|
maxLines = 1,
|
||||||
overflow = TextOverflow.Ellipsis
|
overflow = TextOverflow.Ellipsis
|
||||||
@ -73,12 +73,10 @@ fun RelayCompose(
|
|||||||
}
|
}
|
||||||
|
|
||||||
Column(modifier = Modifier.padding(start = 10.dp)) {
|
Column(modifier = Modifier.padding(start = 10.dp)) {
|
||||||
if (account.activeRelays()?.filter { it.url == relay.url }?.isEmpty() == true) {
|
if (account.activeRelays()?.none { it.url == relay.url } == true) {
|
||||||
AddRelayButton { onAddRelay() }
|
AddRelayButton { onAddRelay() }
|
||||||
} else {
|
} else {
|
||||||
RemoveRelayButton {
|
RemoveRelayButton { onRemoveRelay() }
|
||||||
onRemoveRelay()
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -23,12 +23,14 @@ import com.vitorpamplona.amethyst.model.User
|
|||||||
import com.vitorpamplona.amethyst.ui.actions.NewRelayListView
|
import com.vitorpamplona.amethyst.ui.actions.NewRelayListView
|
||||||
import com.vitorpamplona.amethyst.ui.note.RelayCompose
|
import com.vitorpamplona.amethyst.ui.note.RelayCompose
|
||||||
import com.vitorpamplona.amethyst.ui.screen.loggedIn.AccountViewModel
|
import com.vitorpamplona.amethyst.ui.screen.loggedIn.AccountViewModel
|
||||||
|
import kotlinx.coroutines.CoroutineScope
|
||||||
import kotlinx.coroutines.Dispatchers
|
import kotlinx.coroutines.Dispatchers
|
||||||
|
import kotlinx.coroutines.Job
|
||||||
|
import kotlinx.coroutines.delay
|
||||||
import kotlinx.coroutines.flow.MutableStateFlow
|
import kotlinx.coroutines.flow.MutableStateFlow
|
||||||
import kotlinx.coroutines.flow.asStateFlow
|
import kotlinx.coroutines.flow.asStateFlow
|
||||||
import kotlinx.coroutines.flow.update
|
import kotlinx.coroutines.flow.update
|
||||||
import kotlinx.coroutines.launch
|
import kotlinx.coroutines.launch
|
||||||
import kotlinx.coroutines.withContext
|
|
||||||
|
|
||||||
class RelayFeedViewModel: ViewModel() {
|
class RelayFeedViewModel: ViewModel() {
|
||||||
val order = compareByDescending<User.RelayInfo> { it.lastEvent }.thenByDescending { it.counter }.thenBy { it.url }
|
val order = compareByDescending<User.RelayInfo> { it.lastEvent }.thenByDescending { it.counter }.thenBy { it.url }
|
||||||
@ -39,29 +41,27 @@ class RelayFeedViewModel: ViewModel() {
|
|||||||
var currentUser: User? = null
|
var currentUser: User? = null
|
||||||
|
|
||||||
fun refresh() {
|
fun refresh() {
|
||||||
val beingUsed = currentUser?.relaysBeingUsed?.values?.toList() ?: emptyList()
|
viewModelScope.launch(Dispatchers.Default) {
|
||||||
val beingUsedSet = currentUser?.relaysBeingUsed?.keys ?: emptySet()
|
val beingUsed = currentUser?.getRelayValuesBeingUsed() ?: emptyList()
|
||||||
|
val beingUsedSet = currentUser?.getRelayKeysBeingUsed() ?: emptySet()
|
||||||
|
|
||||||
val newRelaysFromRecord = currentUser?.relays?.entries?.mapNotNull {
|
val newRelaysFromRecord = currentUser?.relays?.entries?.mapNotNull {
|
||||||
if (it.key !in beingUsedSet) {
|
if (it.key !in beingUsedSet) {
|
||||||
User.RelayInfo(it.key, 0, 0)
|
User.RelayInfo(it.key, 0, 0)
|
||||||
} else {
|
} else {
|
||||||
null
|
null
|
||||||
}
|
}
|
||||||
} ?: emptyList()
|
} ?: emptyList()
|
||||||
|
|
||||||
val newList = (beingUsed + newRelaysFromRecord).sortedWith(order)
|
val newList = (beingUsed + newRelaysFromRecord).sortedWith(order)
|
||||||
|
|
||||||
viewModelScope.launch {
|
_feedContent.update { newList }
|
||||||
withContext(Dispatchers.Main) {
|
|
||||||
_feedContent.update { newList }
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
inner class CacheListener: User.Listener() {
|
inner class CacheListener: User.Listener() {
|
||||||
override fun onNewRelayInfo() { refresh() }
|
override fun onNewRelayInfo() { invalidateData() }
|
||||||
override fun onRelayChange() { refresh() }
|
override fun onRelayChange() { invalidateData() }
|
||||||
}
|
}
|
||||||
|
|
||||||
val listener = CacheListener()
|
val listener = CacheListener()
|
||||||
@ -69,13 +69,31 @@ class RelayFeedViewModel: ViewModel() {
|
|||||||
fun subscribeTo(user: User) {
|
fun subscribeTo(user: User) {
|
||||||
currentUser = user
|
currentUser = user
|
||||||
user.subscribe(listener)
|
user.subscribe(listener)
|
||||||
refresh()
|
invalidateData()
|
||||||
}
|
}
|
||||||
|
|
||||||
fun unsubscribeTo(user: User) {
|
fun unsubscribeTo(user: User) {
|
||||||
user.unsubscribe(listener)
|
user.unsubscribe(listener)
|
||||||
currentUser = null
|
currentUser = null
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override fun onCleared() {
|
||||||
|
currentUser?.let { unsubscribeTo(it) }
|
||||||
|
}
|
||||||
|
|
||||||
|
var handlerWaiting = false
|
||||||
|
@Synchronized
|
||||||
|
fun invalidateData() {
|
||||||
|
if (handlerWaiting) return
|
||||||
|
|
||||||
|
handlerWaiting = true
|
||||||
|
val scope = CoroutineScope(Job() + Dispatchers.Default)
|
||||||
|
scope.launch {
|
||||||
|
delay(100)
|
||||||
|
refresh()
|
||||||
|
handlerWaiting = false
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
|
@ -39,6 +39,7 @@ import androidx.compose.material.icons.filled.Password
|
|||||||
import androidx.compose.material.icons.filled.Share
|
import androidx.compose.material.icons.filled.Share
|
||||||
import androidx.compose.runtime.Composable
|
import androidx.compose.runtime.Composable
|
||||||
import androidx.compose.runtime.DisposableEffect
|
import androidx.compose.runtime.DisposableEffect
|
||||||
|
import androidx.compose.runtime.LaunchedEffect
|
||||||
import androidx.compose.runtime.getValue
|
import androidx.compose.runtime.getValue
|
||||||
import androidx.compose.runtime.livedata.observeAsState
|
import androidx.compose.runtime.livedata.observeAsState
|
||||||
import androidx.compose.runtime.mutableStateOf
|
import androidx.compose.runtime.mutableStateOf
|
||||||
@ -170,7 +171,7 @@ fun ProfileScreen(userId: String?, accountViewModel: AccountViewModel, navContro
|
|||||||
0 -> TabNotes(user, accountViewModel, navController)
|
0 -> TabNotes(user, accountViewModel, navController)
|
||||||
1 -> TabFollows(user, accountViewModel, navController)
|
1 -> TabFollows(user, accountViewModel, navController)
|
||||||
2 -> TabFollowers(user, accountViewModel, navController)
|
2 -> TabFollowers(user, accountViewModel, navController)
|
||||||
3 -> TabRelays(user, accountViewModel, navController)
|
3 -> TabRelays(baseUser, accountViewModel, navController)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -358,11 +359,8 @@ fun TabFollowers(user: User, accountViewModel: AccountViewModel, navController:
|
|||||||
fun TabRelays(user: User, accountViewModel: AccountViewModel, navController: NavController) {
|
fun TabRelays(user: User, accountViewModel: AccountViewModel, navController: NavController) {
|
||||||
val feedViewModel: RelayFeedViewModel = viewModel()
|
val feedViewModel: RelayFeedViewModel = viewModel()
|
||||||
|
|
||||||
DisposableEffect(key1 = user) {
|
LaunchedEffect(key1 = user) {
|
||||||
feedViewModel.subscribeTo(user)
|
feedViewModel.subscribeTo(user)
|
||||||
onDispose {
|
|
||||||
feedViewModel.unsubscribeTo(user)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Column(Modifier.fillMaxHeight()) {
|
Column(Modifier.fillMaxHeight()) {
|
||||||
|
Reference in New Issue
Block a user