Skip to content
This repository has been archived by the owner on Apr 14, 2024. It is now read-only.

Commit

Permalink
Merge pull request #83 from dluvian/relay-editor-improvements
Browse files Browse the repository at this point in the history
Relay editor improvements
  • Loading branch information
dluvian authored Feb 15, 2024
2 parents 30de83a + 3809638 commit 76fd3cf
Show file tree
Hide file tree
Showing 31 changed files with 328 additions and 81 deletions.
4 changes: 4 additions & 0 deletions app/src/main/java/com/dluvian/nozzle/AppContainer.kt
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ import com.dluvian.nozzle.data.profileFollower.ProfileFollower
import com.dluvian.nozzle.data.provider.IAccountProvider
import com.dluvian.nozzle.data.provider.IAutopilotProvider
import com.dluvian.nozzle.data.provider.IContactListProvider
import com.dluvian.nozzle.data.provider.IOnlineStatusProvider
import com.dluvian.nozzle.data.provider.IPostWithMetaProvider
import com.dluvian.nozzle.data.provider.IProfileWithMetaProvider
import com.dluvian.nozzle.data.provider.IRelayProvider
Expand All @@ -45,6 +46,7 @@ import com.dluvian.nozzle.data.provider.feed.impl.SearchFeedProvider
import com.dluvian.nozzle.data.provider.impl.AccountProvider
import com.dluvian.nozzle.data.provider.impl.AutopilotProvider
import com.dluvian.nozzle.data.provider.impl.ContactListProvider
import com.dluvian.nozzle.data.provider.impl.OnlineStatusProvider
import com.dluvian.nozzle.data.provider.impl.PostWithMetaProvider
import com.dluvian.nozzle.data.provider.impl.ProfileWithMetaProvider
import com.dluvian.nozzle.data.provider.impl.RelayProvider
Expand Down Expand Up @@ -226,4 +228,6 @@ class AppContainer(context: Context) {
simpleProfileProvider = simpleProfileProvider,
relayProvider = relayProvider
)

val onlineStatusProvider: IOnlineStatusProvider = OnlineStatusProvider(httpClient = httpClient)
}
5 changes: 5 additions & 0 deletions app/src/main/java/com/dluvian/nozzle/data/NozzleConstants.kt
Original file line number Diff line number Diff line change
Expand Up @@ -29,3 +29,8 @@ const val MAX_SQL_PARAMS = 250

// Max num of friends of friends
const val FRIEND_CIRCLE_LIMIT = 500


const val GOOD_PING_THRESHOLD = 250
const val PING_INTERVAL = 7_000L
const val PING_WAIT_TIME = 500L
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import com.dluvian.nozzle.data.room.entity.EventRelayEntity
import com.dluvian.nozzle.data.room.entity.Nip65Entity
import com.dluvian.nozzle.data.room.entity.ProfileEntity
import com.dluvian.nozzle.data.room.entity.ReactionEntity
import com.dluvian.nozzle.data.room.helper.Nip65Relay
import com.dluvian.nozzle.data.utils.JsonUtils.gson
import com.dluvian.nozzle.data.utils.TimeConstants
import com.dluvian.nozzle.data.utils.UrlUtils.removeTrailingSlashes
Expand Down Expand Up @@ -241,9 +242,11 @@ class EventProcessor(
event.getNip65Entries().map { entry ->
Nip65Entity(
pubkey = event.pubkey,
url = entry.url,
isRead = entry.isRead,
isWrite = entry.isWrite,
nip65Relay = Nip65Relay(
url = entry.url,
isRead = entry.isRead,
isWrite = entry.isWrite
),
createdAt = event.createdAt,
)
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
package com.dluvian.nozzle.data.provider

import com.dluvian.nozzle.model.OnlineStatus
import com.dluvian.nozzle.model.Relay
import kotlinx.coroutines.flow.Flow

interface IOnlineStatusProvider {
fun getOnlineStatuses(relays: Collection<Relay>): Flow<Map<Relay, OnlineStatus>>
}
Original file line number Diff line number Diff line change
Expand Up @@ -13,5 +13,5 @@ interface IRelayProvider {
suspend fun getReadRelaysOfPubkeys(pubkeys: Collection<String>): Map<Pubkey, List<Relay>>
suspend fun getWriteRelaysOfPubkey(pubkey: String): List<Relay>
suspend fun getWriteRelaysByPubkeys(pubkeys: Collection<Pubkey>): Map<Pubkey, List<Relay>>
suspend fun getRelaysOfContacts(): List<Relay>
suspend fun getPopularRelays(): List<Relay>
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
package com.dluvian.nozzle.data.provider.impl

import com.dluvian.nozzle.data.PING_INTERVAL
import com.dluvian.nozzle.data.PING_WAIT_TIME
import com.dluvian.nozzle.data.provider.IOnlineStatusProvider
import com.dluvian.nozzle.model.Offline
import com.dluvian.nozzle.model.Online
import com.dluvian.nozzle.model.OnlineStatus
import com.dluvian.nozzle.model.Relay
import com.dluvian.nozzle.model.Waiting
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.delay
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.flow
import kotlinx.coroutines.flow.flowOf
import kotlinx.coroutines.launch
import okhttp3.OkHttpClient
import okhttp3.Request
import java.util.Collections

class OnlineStatusProvider(private val httpClient: OkHttpClient) : IOnlineStatusProvider {
private val scope = CoroutineScope(Dispatchers.IO)
private val cache = Collections.synchronizedMap(mutableMapOf<Relay, OnlineStatus>())
override fun getOnlineStatuses(relays: Collection<Relay>): Flow<Map<Relay, OnlineStatus>> {
if (relays.isEmpty()) return flowOf(emptyMap())
val distinctRelays = relays.toSet()
return flow {
ping(relays = distinctRelays)
var lastPing = System.currentTimeMillis()

while (true) {
delay(PING_WAIT_TIME)
emit(distinctRelays.associateWith { cache[it] ?: Waiting })
val currentTime = System.currentTimeMillis()
if (currentTime - lastPing > PING_INTERVAL) {
lastPing = currentTime
ping(relays = distinctRelays)
}
}
}
}

private fun ping(relays: Set<Relay>) {
relays.forEach { relay ->
val request = Request.Builder()
.url(relay)
.build()
scope.launch {
cache[relay] = try {
httpClient.newCall(request).execute().use { response ->
val ping = response.receivedResponseAtMillis - response.sentRequestAtMillis
Online(ping = ping)
}
} catch (e: Exception) {
Offline
}
}
}
}
}
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package com.dluvian.nozzle.data.provider.impl

import com.dluvian.nozzle.data.MAX_LIST_LENGTH
import com.dluvian.nozzle.data.getDefaultRelays
import com.dluvian.nozzle.data.provider.IContactListProvider
import com.dluvian.nozzle.data.provider.IRelayProvider
Expand Down Expand Up @@ -67,10 +68,9 @@ class RelayProvider(
return dbResult
}

override suspend fun getRelaysOfContacts(): List<Relay> {
// TODO: Remove contactListProvider. Use account query
override suspend fun getPopularRelays(): List<Relay> {
val pubkeys = contactListProvider.listPersonalContactPubkeysOrDefault()
return nip65Dao.getRelaysOfPubkeys(pubkeys = pubkeys)
return nip65Dao.getRelaysOfPubkeys(pubkeys = pubkeys, limit = MAX_LIST_LENGTH)
}

private fun getDefaultNip65s() = getDefaultRelays()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,10 @@ import androidx.room.MapInfo
import androidx.room.OnConflictStrategy
import androidx.room.Query
import com.dluvian.nozzle.data.room.entity.EventRelayEntity
import com.dluvian.nozzle.model.CountedRelayUsage
import com.dluvian.nozzle.model.EventId
import com.dluvian.nozzle.model.NoteId
import com.dluvian.nozzle.model.Relay
import com.dluvian.nozzle.model.relay.CountedRelayUsage
import kotlinx.coroutines.flow.Flow


Expand Down
16 changes: 3 additions & 13 deletions app/src/main/java/com/dluvian/nozzle/data/room/dao/Nip65Dao.kt
Original file line number Diff line number Diff line change
Expand Up @@ -134,18 +134,8 @@ interface Nip65Dao {
"FROM nip65 " +
"WHERE pubkey IN (:pubkeys) " +
"GROUP BY url " +
"ORDER BY COUNT(url) DESC"
"ORDER BY COUNT(url) DESC " +
"LIMIT :limit"
)
suspend fun getRelaysOfPubkeys(pubkeys: Collection<String>): List<Relay>

// Query to get relay respectors
// @Query(
// "SELECT DISTINCT pubkey " +
// "FROM post " +
// "WHERE post.replyToId IS NOT NULL AND post.replyRelayHint IS NOT NULL " +
// "AND pubkey NOT IN (SELECT pubkey FROM post WHERE post.replyToId IS NOT NULL AND post.replyRelayHint IS NULL) " +
// "AND pubkey NOT IN (SELECT pubkey FROM post GROUP BY pubkey HAVING COUNT(post.id) < 5)"
// )
// suspend fun getGoodPubkeys(): List<Pubkey>

suspend fun getRelaysOfPubkeys(pubkeys: Collection<String>, limit: Int): List<Relay>
}
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
package com.dluvian.nozzle.data.room.entity

import androidx.room.Embedded
import androidx.room.Entity
import com.dluvian.nozzle.data.room.helper.Nip65Relay

@Entity(tableName = "nip65", primaryKeys = ["pubkey", "url"])
data class Nip65Entity(
val pubkey: String,
val url: String,
val isRead: Boolean,
val isWrite: Boolean,
@Embedded val nip65Relay: Nip65Relay,
val createdAt: Long,
)
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
package com.dluvian.nozzle.data.room.helper

import com.dluvian.nozzle.model.Relay

data class Nip65Relay(
val url: String,
val url: Relay,
val isRead: Boolean,
val isWrite: Boolean,
)
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,6 @@ import com.dluvian.nozzle.data.subscriber.ISubscriptionQueue
import com.dluvian.nozzle.data.utils.getMaxRelaysAndAddIfTooSmall
import com.dluvian.nozzle.data.utils.takeRandom80percent
import com.dluvian.nozzle.model.FeedInfo
import com.dluvian.nozzle.model.IdAndRelays
import com.dluvian.nozzle.model.NoteId
import com.dluvian.nozzle.model.PostWithMeta
import com.dluvian.nozzle.model.Pubkey
Expand All @@ -29,6 +28,7 @@ import com.dluvian.nozzle.model.feedFilter.RelayFilter
import com.dluvian.nozzle.model.nostr.Nevent
import com.dluvian.nozzle.model.nostr.Nprofile
import com.dluvian.nozzle.model.nostr.ReplyTo
import com.dluvian.nozzle.model.relay.IdAndRelays
import kotlinx.coroutines.delay

private const val TAG = "NozzleSubscriber"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ package com.dluvian.nozzle.data.utils

import com.dluvian.nozzle.data.MAX_RELAYS
import com.dluvian.nozzle.model.Relay
import com.dluvian.nozzle.model.RelaySelection
import com.dluvian.nozzle.model.relay.RelaySelection

fun toggleRelay(relays: List<RelaySelection>, index: Int): List<RelaySelection> {
return relays.mapIndexed { i, relay ->
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
package com.dluvian.nozzle.model

data class ItemWithOnlineStatus<T>(val item: T, val onlineStatus: OnlineStatus)
10 changes: 10 additions & 0 deletions app/src/main/java/com/dluvian/nozzle/model/OnlineStatus.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
package com.dluvian.nozzle.model

import androidx.compose.runtime.Immutable

@Immutable
sealed class OnlineStatus

data class Online(val ping: Long) : OnlineStatus()
data object Offline : OnlineStatus()
data object Waiting : OnlineStatus()
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
package com.dluvian.nozzle.model
package com.dluvian.nozzle.model.relay

data class CountedRelayUsage(val pubkey: String, val relayUrl: String, val numOfPosts: Int)
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
package com.dluvian.nozzle.model
package com.dluvian.nozzle.model.relay

data class IdAndRelays(val id: String, val relays: List<String>)
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
package com.dluvian.nozzle.model
package com.dluvian.nozzle.model.relay

import com.dluvian.nozzle.model.Relay

data class RelaySelection(
val relay: Relay,
Expand Down
1 change: 1 addition & 0 deletions app/src/main/java/com/dluvian/nozzle/ui/app/NozzleApp.kt
Original file line number Diff line number Diff line change
Expand Up @@ -157,6 +157,7 @@ fun NozzleApp(appContainer: AppContainer) {
nostrService = appContainer.nostrService,
relayProvider = appContainer.relayProvider,
pubkeyProvider = appContainer.keyManager,
onlineStatusProvider = appContainer.onlineStatusProvider,
nip65Dao = appContainer.roomDb.nip65Dao()
)
),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ import androidx.compose.ui.Modifier
import androidx.compose.ui.res.stringResource
import com.dluvian.nozzle.R
import com.dluvian.nozzle.model.PostWithMeta
import com.dluvian.nozzle.model.RelaySelection
import com.dluvian.nozzle.model.relay.RelaySelection
import com.dluvian.nozzle.ui.app.navigation.PostCardLambdas
import com.dluvian.nozzle.ui.components.buttons.ShowNewPostsButton
import com.dluvian.nozzle.ui.components.dropdown.RelayDropdown
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,8 @@ package com.dluvian.nozzle.ui.app.views.post

import androidx.compose.runtime.Immutable
import com.dluvian.nozzle.model.AnnotatedMentionedPost
import com.dluvian.nozzle.model.RelaySelection
import com.dluvian.nozzle.model.SimpleProfile
import com.dluvian.nozzle.model.relay.RelaySelection

@Immutable
data class PostViewModelState(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,9 +10,11 @@ fun RelayEditorRoute(
onGoBack: () -> Unit,
) {
val uiState by relayEditorViewModel.uiState.collectAsState()
val onlineStatuses by relayEditorViewModel.onlineStatuses.collectAsState()

RelayEditorScreen(
uiState = uiState,
onlineStatuses = onlineStatuses,
onSaveRelays = relayEditorViewModel.onSaveRelays,
onAddRelay = relayEditorViewModel.onAddRelay,
onDeleteRelay = relayEditorViewModel.onDeleteRelay,
Expand Down
Loading

0 comments on commit 76fd3cf

Please sign in to comment.