style(audio-rooms): import-and-use instead of inline FQNs

Replace inline `com.vitorpamplona.…` references in code + KDoc with
imports + the short class name across the audio-rooms surface. KDoc
references that would have introduced an `ui` → `model` import cycle
(e.g. NestsServerListState referring to CreateAudioRoomViewModel) are
demoted to plain text instead of clickable `[Class]` links.

No behavioural change.
This commit is contained in:
Claude
2026-04-26 20:11:02 +00:00
parent 5f90588fe4
commit 1a26b23448
12 changed files with 49 additions and 41 deletions
@@ -175,6 +175,7 @@ import com.vitorpamplona.quartz.nip53LiveActivities.chat.LiveActivitiesChatMessa
import com.vitorpamplona.quartz.nip53LiveActivities.clip.LiveActivitiesClipEvent
import com.vitorpamplona.quartz.nip53LiveActivities.meetingSpaces.MeetingRoomEvent
import com.vitorpamplona.quartz.nip53LiveActivities.meetingSpaces.MeetingSpaceEvent
import com.vitorpamplona.quartz.nip53LiveActivities.nestsServers.NestsServersEvent
import com.vitorpamplona.quartz.nip53LiveActivities.presence.MeetingRoomPresenceEvent
import com.vitorpamplona.quartz.nip53LiveActivities.raid.LiveActivitiesRaidEvent
import com.vitorpamplona.quartz.nip53LiveActivities.streaming.LiveActivitiesEvent
@@ -2737,7 +2738,7 @@ object LocalCache : ILocalCache, ICacheProvider {
consumeBaseReplaceable(event, relay, wasVerified)
}
is com.vitorpamplona.quartz.nip53LiveActivities.nestsServers.NestsServersEvent -> {
is NestsServersEvent -> {
consumeBaseReplaceable(event, relay, wasVerified)
}
@@ -23,6 +23,7 @@ package com.vitorpamplona.amethyst.model.nip53NestsServers
import com.vitorpamplona.amethyst.commons.model.cache.ICacheProvider
import com.vitorpamplona.amethyst.model.Note
import com.vitorpamplona.amethyst.model.NoteState
import com.vitorpamplona.amethyst.model.nipB7Blossom.BlossomServerListState
import com.vitorpamplona.quartz.nip01Core.signers.NostrSigner
import com.vitorpamplona.quartz.nip53LiveActivities.nestsServers.NestsServersEvent
import kotlinx.coroutines.CoroutineScope
@@ -36,8 +37,7 @@ import kotlinx.coroutines.flow.stateIn
/**
* Per-account state for the user's preferred audio-room (NIP-53 / nests)
* MoQ host servers — kind 10112 [NestsServersEvent]. Mirror of
* [com.vitorpamplona.amethyst.model.nipB7Blossom.BlossomServerListState]
* for the nests use case.
* [BlossomServerListState] for the nests use case.
*
* Surfaces:
* - [flow] — current `List<String>` of saved server base URLs
@@ -46,10 +46,9 @@ import kotlinx.coroutines.flow.stateIn
* - [saveNestsServersList] — build + sign a new replaceable kind 10112
* event (preserving prior tags' alt etc.)
*
* The list is consumed by [com.vitorpamplona.amethyst.ui.screen.loggedIn.audiorooms.create.CreateAudioRoomViewModel]
* to default the "MoQ service URL" / "MoQ endpoint URL" fields when
* starting a new space, and by the Settings screen for edit / add /
* remove.
* The list is consumed by `CreateAudioRoomViewModel` to default the
* "MoQ service URL" / "MoQ endpoint URL" fields when starting a new
* space, and by the Settings screen for edit / add / remove.
*/
class NestsServerListState(
val signer: NostrSigner,
@@ -41,6 +41,7 @@ import com.vitorpamplona.quartz.nip51Lists.relayLists.IndexerRelayListEvent
import com.vitorpamplona.quartz.nip51Lists.relayLists.ProxyRelayListEvent
import com.vitorpamplona.quartz.nip51Lists.relayLists.RelayFeedsListEvent
import com.vitorpamplona.quartz.nip51Lists.relayLists.TrustedRelayListEvent
import com.vitorpamplona.quartz.nip53LiveActivities.nestsServers.NestsServersEvent
import com.vitorpamplona.quartz.nip65RelayList.AdvertisedRelayListEvent
import com.vitorpamplona.quartz.nip78AppData.AppSpecificDataEvent
import com.vitorpamplona.quartz.nip85TrustedAssertions.list.TrustProviderListEvent
@@ -58,7 +59,7 @@ val AccountInfoAndListsFromKeyKinds =
SearchRelayListEvent.KIND,
FileServersEvent.KIND,
BlossomServersEvent.KIND,
com.vitorpamplona.quartz.nip53LiveActivities.nestsServers.NestsServersEvent.KIND,
NestsServersEvent.KIND,
PrivateOutboxRelayListEvent.KIND,
)
@@ -37,6 +37,7 @@ import com.vitorpamplona.quartz.nip51Lists.relayLists.IndexerRelayListEvent
import com.vitorpamplona.quartz.nip51Lists.relayLists.ProxyRelayListEvent
import com.vitorpamplona.quartz.nip51Lists.relayLists.RelayFeedsListEvent
import com.vitorpamplona.quartz.nip51Lists.relayLists.TrustedRelayListEvent
import com.vitorpamplona.quartz.nip53LiveActivities.nestsServers.NestsServersEvent
import com.vitorpamplona.quartz.nip65RelayList.AdvertisedRelayListEvent
import com.vitorpamplona.quartz.nip85TrustedAssertions.list.TrustProviderListEvent
import com.vitorpamplona.quartz.nip96FileStorage.config.FileServersEvent
@@ -52,7 +53,7 @@ val BasicAccountInfoKinds =
SearchRelayListEvent.KIND,
FileServersEvent.KIND,
BlossomServersEvent.KIND,
com.vitorpamplona.quartz.nip53LiveActivities.nestsServers.NestsServersEvent.KIND,
NestsServersEvent.KIND,
)
val BasicAccountInfoKinds2 =
@@ -49,6 +49,7 @@ import androidx.lifecycle.viewmodel.compose.viewModel
import com.vitorpamplona.amethyst.R
import com.vitorpamplona.amethyst.commons.icons.symbols.Icon
import com.vitorpamplona.amethyst.commons.icons.symbols.MaterialSymbols
import com.vitorpamplona.amethyst.ui.actions.mediaServers.AllMediaServersScreen
import com.vitorpamplona.amethyst.ui.actions.mediaServers.MediaServerEditField
import com.vitorpamplona.amethyst.ui.navigation.navs.INav
import com.vitorpamplona.amethyst.ui.navigation.topbars.SavingTopBar
@@ -62,15 +63,16 @@ import com.vitorpamplona.amethyst.ui.theme.SettingsCategoryFirstModifier
import com.vitorpamplona.amethyst.ui.theme.SettingsCategorySpacingModifier
import com.vitorpamplona.amethyst.ui.theme.StdVertSpacer
import com.vitorpamplona.amethyst.ui.theme.grayText
import com.vitorpamplona.quartz.nip53LiveActivities.nestsServers.NestsServersEvent
/**
* Settings screen for the user's preferred audio-room (NIP-53 / nests)
* MoQ host servers — kind 10112 [com.vitorpamplona.quartz.nip53LiveActivities.nestsServers.NestsServersEvent].
* MoQ host servers — kind 10112 [NestsServersEvent].
*
* Mirrors [com.vitorpamplona.amethyst.ui.actions.mediaServers.AllMediaServersScreen]
* — top bar with Cancel / Save, list of saved servers with delete
* buttons, edit-field row to add a new one, and a "Use defaults" row
* for one-tap inclusion of `nostrnests.com`.
* Mirrors [AllMediaServersScreen] — top bar with Cancel / Save, list
* of saved servers with delete buttons, edit-field row to add a new
* one, and a "Use defaults" row for one-tap inclusion of
* `nostrnests.com`.
*
* Reachable from `Settings → Audio-room servers`.
*/
@@ -23,7 +23,9 @@ package com.vitorpamplona.amethyst.ui.actions.nestsServers
import androidx.compose.runtime.Stable
import androidx.lifecycle.ViewModel
import com.vitorpamplona.amethyst.model.Account
import com.vitorpamplona.amethyst.ui.actions.mediaServers.BlossomServersViewModel
import com.vitorpamplona.amethyst.ui.screen.loggedIn.AccountViewModel
import com.vitorpamplona.quartz.nip53LiveActivities.nestsServers.NestsServersEvent
import com.vitorpamplona.quartz.utils.Rfc3986
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.asStateFlow
@@ -31,10 +33,10 @@ import kotlinx.coroutines.flow.update
/**
* Edit-buffer for the user's audio-room (NIP-53 / nests) MoQ server
* list. Mirror of [com.vitorpamplona.amethyst.ui.actions.mediaServers.BlossomServersViewModel]
* scoped down to a plain `List<String>` of base URLs since nests
* servers don't have a "selected default" concept (clients pick the
* first entry when starting a new space).
* list. Mirror of [BlossomServersViewModel] scoped down to a plain
* `List<String>` of base URLs since nests servers don't have a
* "selected default" concept (clients pick the first entry when
* starting a new space).
*
* The flow:
* 1. [init] binds the [AccountViewModel].
@@ -42,8 +44,8 @@ import kotlinx.coroutines.flow.update
* [_servers] buffer.
* 3. [addServer] / [removeServer] / [removeAllServers] mutate the
* buffer, marking [isModified] = true.
* 4. [save] publishes a fresh kind-10112 [com.vitorpamplona.quartz.nip53LiveActivities.nestsServers.NestsServersEvent]
* via [Account.sendNestsServersList].
* 4. [save] publishes a fresh kind-10112 [NestsServersEvent] via
* [Account.sendNestsServersList].
*/
@Stable
class NestsServersViewModel : ViewModel() {
@@ -52,6 +52,7 @@ import androidx.compose.ui.unit.dp
import androidx.lifecycle.viewmodel.compose.viewModel
import com.vitorpamplona.amethyst.R
import com.vitorpamplona.amethyst.ui.screen.loggedIn.AccountViewModel
import com.vitorpamplona.amethyst.ui.screen.loggedIn.audiorooms.AudioRoomsScreen
import com.vitorpamplona.amethyst.ui.screen.loggedIn.audiorooms.room.AudioRoomActivity
import com.vitorpamplona.amethyst.ui.screen.loggedIn.audiorooms.room.AudioRoomBridge
import com.vitorpamplona.amethyst.ui.stringRes
@@ -66,7 +67,7 @@ import kotlinx.coroutines.launch
* Talk button enabled.
*
* Hidden by default; surfaced by the "Start space" FAB on
* [com.vitorpamplona.amethyst.ui.screen.loggedIn.audiorooms.AudioRoomsScreen].
* [AudioRoomsScreen].
*/
@OptIn(ExperimentalMaterial3Api::class)
@Composable
@@ -22,6 +22,7 @@ package com.vitorpamplona.amethyst.ui.screen.loggedIn.audiorooms.create
import androidx.lifecycle.ViewModel
import com.vitorpamplona.amethyst.ui.screen.loggedIn.AccountViewModel
import com.vitorpamplona.amethyst.ui.screen.loggedIn.audiorooms.room.AudioRoomActivity
import com.vitorpamplona.quartz.nip53LiveActivities.meetingSpaces.MeetingSpaceEvent
import com.vitorpamplona.quartz.nip53LiveActivities.meetingSpaces.endpoint
import com.vitorpamplona.quartz.nip53LiveActivities.meetingSpaces.image
@@ -38,7 +39,7 @@ import kotlinx.coroutines.flow.update
* Backing ViewModel for [CreateAudioRoomSheet]. Holds form state, runs
* [publishAndBuildLaunchInfo] which signs and broadcasts a NIP-53 kind
* 30312 [MeetingSpaceEvent] tagging the user as `host`, then returns
* the launch parameters for [com.vitorpamplona.amethyst.ui.screen.loggedIn.audiorooms.room.AudioRoomActivity].
* the launch parameters for [AudioRoomActivity].
*
* The defaults point at `nostrnests.com`'s public moq-rs deployment so a
* blank form produces a working room. The user can edit them to point at
@@ -200,6 +200,7 @@ import com.vitorpamplona.quartz.nip52Calendar.rsvp.CalendarRSVPEvent
import com.vitorpamplona.quartz.nip53LiveActivities.chat.LiveActivitiesChatMessageEvent
import com.vitorpamplona.quartz.nip53LiveActivities.meetingSpaces.MeetingRoomEvent
import com.vitorpamplona.quartz.nip53LiveActivities.meetingSpaces.MeetingSpaceEvent
import com.vitorpamplona.quartz.nip53LiveActivities.nestsServers.NestsServersEvent
import com.vitorpamplona.quartz.nip53LiveActivities.presence.MeetingRoomPresenceEvent
import com.vitorpamplona.quartz.nip53LiveActivities.streaming.LiveActivitiesEvent
import com.vitorpamplona.quartz.nip54Wiki.WikiNoteEvent
@@ -543,7 +544,7 @@ fun kindDisplayName(kind: Int): Int =
BadgeDefinitionEvent.KIND -> R.string.kind_badge_definitions
BlockedRelayListEvent.KIND -> R.string.kind_blocked_relays
BlossomServersEvent.KIND -> R.string.kind_blossom_servers
com.vitorpamplona.quartz.nip53LiveActivities.nestsServers.NestsServersEvent.KIND -> R.string.kind_nests_servers
NestsServersEvent.KIND -> R.string.kind_nests_servers
BlossomAuthorizationEvent.KIND -> R.string.kind_blossom_auth
BroadcastRelayListEvent.KIND -> R.string.kind_broadcast_relays
BookmarkListEvent.KIND -> R.string.kind_bookmark_list
@@ -23,8 +23,10 @@ package com.vitorpamplona.nestsclient
import com.vitorpamplona.nestsclient.audio.AudioCapture
import com.vitorpamplona.nestsclient.audio.OpusEncoder
import com.vitorpamplona.nestsclient.moq.SubscribeHandle
import com.vitorpamplona.nestsclient.moq.lite.MoqLiteSession
import com.vitorpamplona.nestsclient.transport.WebTransportException
import com.vitorpamplona.nestsclient.transport.WebTransportFactory
import com.vitorpamplona.nestsclient.transport.WebTransportSession
import com.vitorpamplona.quartz.nip01Core.signers.NostrSigner
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.flow.MutableStateFlow
@@ -35,14 +37,13 @@ import kotlinx.coroutines.flow.MutableStateFlow
*
* 1. Mint a JWT POST `<authBase>/auth` with NIP-98 + namespace body
* (see [NestsClient.mintToken]).
* 2. Open a [com.vitorpamplona.nestsclient.transport.WebTransportSession]
* against the [room.endpoint] via [transport]. The path is
* `/<moqNamespace>?jwt=<token>` moq-rs treats the URL path as
* `claims.root` and reads the JWT from `?jwt=`.
* 3. Wrap the WT session in a [com.vitorpamplona.nestsclient.moq.lite.MoqLiteSession].
* moq-lite Lite-03 has NO in-band SETUP message the WT handshake
* itself is the handshake, version is selected by the ALPN
* `moq-lite-03`.
* 2. Open a [WebTransportSession] against the [room.endpoint] via
* [transport]. The path is `/<moqNamespace>?jwt=<token>` moq-rs
* treats the URL path as `claims.root` and reads the JWT from
* `?jwt=`.
* 3. Wrap the WT session in a [MoqLiteSession]. moq-lite Lite-03 has
* NO in-band SETUP message the WT handshake itself is the
* handshake, version is selected by the ALPN `moq-lite-03`.
*
* The returned [NestsListener] is in state [NestsListenerState.Connected];
* if any step fails, the listener is returned in
@@ -110,8 +111,7 @@ suspend fun connectNestsListener(
// `moq-lite-03`.
val moq =
try {
com.vitorpamplona.nestsclient.moq.lite.MoqLiteSession
.client(webTransport, scope)
MoqLiteSession.client(webTransport, scope)
} catch (t: Throwable) {
runCatching { webTransport.close(0, "moq-lite session init failed") }
state.value = NestsListenerState.Failed("moq-lite session init failed: ${t.message}", t)
@@ -225,8 +225,7 @@ suspend fun connectNestsSpeaker(
// path — version is selected by the `moq-lite-03` ALPN.
val moq =
try {
com.vitorpamplona.nestsclient.moq.lite.MoqLiteSession
.client(webTransport, scope)
MoqLiteSession.client(webTransport, scope)
} catch (t: Throwable) {
runCatching { webTransport.close(0, "moq-lite session init failed") }
state.value = NestsSpeakerState.Failed("moq-lite session init failed: ${t.message}", t)
@@ -20,10 +20,12 @@
*/
package com.vitorpamplona.nestsclient
import com.vitorpamplona.nestsclient.moq.MoqProtocolException
import com.vitorpamplona.nestsclient.moq.MoqSession
import com.vitorpamplona.nestsclient.moq.SubscribeFilter
import com.vitorpamplona.nestsclient.moq.SubscribeHandle
import com.vitorpamplona.nestsclient.moq.TrackNamespace
import com.vitorpamplona.nestsclient.transport.WebTransportSession
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.StateFlow
import kotlinx.coroutines.flow.asStateFlow
@@ -45,8 +47,7 @@ interface NestsListener {
* Opus stream under the namespace `["nests", <roomId>]` with the
* speaker's pubkey hex as the track name.
*
* @throws com.vitorpamplona.nestsclient.moq.MoqProtocolException if the
* publisher rejects the subscription.
* @throws MoqProtocolException if the publisher rejects the subscription.
* @throws IllegalStateException if the listener is not in [NestsListenerState.Connected].
*/
suspend fun subscribeSpeaker(speakerPubkeyHex: String): SubscribeHandle
@@ -107,8 +108,7 @@ sealed class NestsListenerState {
* MoQ-transport target.
*
* Delegates to a [MoqSession] already set up on a
* [com.vitorpamplona.nestsclient.transport.WebTransportSession];
* construction does NOT open the transport.
* [WebTransportSession]; construction does NOT open the transport.
*/
class DefaultNestsListener internal constructor(
private val session: MoqSession,
@@ -23,6 +23,7 @@ package com.vitorpamplona.nestsclient
import com.vitorpamplona.nestsclient.audio.AudioCapture
import com.vitorpamplona.nestsclient.audio.AudioRoomBroadcaster
import com.vitorpamplona.nestsclient.audio.OpusEncoder
import com.vitorpamplona.nestsclient.moq.MoqProtocolException
import com.vitorpamplona.nestsclient.moq.MoqSession
import com.vitorpamplona.nestsclient.moq.TrackNamespace
import kotlinx.coroutines.CoroutineScope
@@ -52,8 +53,7 @@ interface NestsSpeaker {
*
* @throws IllegalStateException if a broadcast is already running on
* this speaker or the session is not [NestsSpeakerState.Connected].
* @throws com.vitorpamplona.nestsclient.moq.MoqProtocolException if the
* peer rejects the ANNOUNCE.
* @throws MoqProtocolException if the peer rejects the ANNOUNCE.
*/
suspend fun startBroadcasting(): BroadcastHandle