diff --git a/amethyst/src/main/AndroidManifest.xml b/amethyst/src/main/AndroidManifest.xml index 19e6f5db7..acb9adec2 100644 --- a/amethyst/src/main/AndroidManifest.xml +++ b/amethyst/src/main/AndroidManifest.xml @@ -219,7 +219,7 @@ tools:ignore="DiscouragedApi" /> diff --git a/amethyst/src/main/java/com/vitorpamplona/amethyst/model/nip53NestsServers/NestsServerListState.kt b/amethyst/src/main/java/com/vitorpamplona/amethyst/model/nip53NestsServers/NestsServerListState.kt index cd2a5d190..7331ee48c 100644 --- a/amethyst/src/main/java/com/vitorpamplona/amethyst/model/nip53NestsServers/NestsServerListState.kt +++ b/amethyst/src/main/java/com/vitorpamplona/amethyst/model/nip53NestsServers/NestsServerListState.kt @@ -46,7 +46,7 @@ import kotlinx.coroutines.flow.stateIn * - [saveNestsServersList] — build + sign a new replaceable kind 10112 * event (preserving prior tags' alt etc.) * - * The list is consumed by `CreateAudioRoomViewModel` to default the + * The list is consumed by `CreateNestViewModel` to default the * "MoQ service URL" / "MoQ endpoint URL" fields when starting a new * space, and by the Settings screen for edit / add / remove. */ diff --git a/amethyst/src/main/java/com/vitorpamplona/amethyst/service/audiorooms/AudioRoomForegroundService.kt b/amethyst/src/main/java/com/vitorpamplona/amethyst/service/nests/NestForegroundService.kt similarity index 89% rename from amethyst/src/main/java/com/vitorpamplona/amethyst/service/audiorooms/AudioRoomForegroundService.kt rename to amethyst/src/main/java/com/vitorpamplona/amethyst/service/nests/NestForegroundService.kt index 1ab269889..f1de44d8e 100644 --- a/amethyst/src/main/java/com/vitorpamplona/amethyst/service/audiorooms/AudioRoomForegroundService.kt +++ b/amethyst/src/main/java/com/vitorpamplona/amethyst/service/nests/NestForegroundService.kt @@ -18,7 +18,7 @@ * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -package com.vitorpamplona.amethyst.service.audiorooms +package com.vitorpamplona.amethyst.service.nests import android.app.Notification import android.app.NotificationChannel @@ -43,7 +43,7 @@ import com.vitorpamplona.amethyst.ui.MainActivity * * Scope decisions: * - The service does NOT own the MoQ session / decoder / player. Those - * live in `AudioRoomViewModel`. This service exists to keep the process + * live in `NestViewModel`. This service exists to keep the process * alive while audio is in flight; the VM still drives all wire activity. * - Foreground type is `mediaPlayback`; if the user starts broadcasting, * the screen calls [promoteToMicrophone] which re-`startForeground`s @@ -54,7 +54,7 @@ import com.vitorpamplona.amethyst.ui.MainActivity * full-screen activity). The service uses a shared notification id so * start/promote/stop is idempotent. */ -class AudioRoomForegroundService : Service() { +class NestForegroundService : Service() { private var wakeLock: PowerManager.WakeLock? = null private var promoted = false private var audioFocusRequest: android.media.AudioFocusRequest? = null @@ -169,25 +169,25 @@ class AudioRoomForegroundService : Service() { PendingIntent.getService( this, 1, - Intent(this, AudioRoomForegroundService::class.java).apply { action = ACTION_STOP }, + Intent(this, NestForegroundService::class.java).apply { action = ACTION_STOP }, PendingIntent.FLAG_IMMUTABLE or PendingIntent.FLAG_UPDATE_CURRENT, ) val title = if (promoted) { - getString(R.string.audio_room_notification_broadcasting) + getString(R.string.nest_notification_broadcasting) } else { - getString(R.string.audio_room_notification_listening) + getString(R.string.nest_notification_listening) } return NotificationCompat .Builder(this, CHANNEL_ID) .setContentTitle(title) - .setContentText(getString(R.string.audio_room_notification_text)) + .setContentText(getString(R.string.nest_notification_text)) .setSmallIcon(R.drawable.amethyst) .setOngoing(true) .setContentIntent(openIntent) - .addAction(0, getString(R.string.audio_room_notification_stop), stopIntent) + .addAction(0, getString(R.string.nest_notification_stop), stopIntent) .setCategory(NotificationCompat.CATEGORY_CALL) .build() } @@ -198,10 +198,10 @@ class AudioRoomForegroundService : Service() { mgr.createNotificationChannel( NotificationChannel( CHANNEL_ID, - getString(R.string.audio_room_notification_channel), + getString(R.string.nest_notification_channel), NotificationManager.IMPORTANCE_LOW, ).apply { - description = getString(R.string.audio_room_notification_channel_description) + description = getString(R.string.nest_notification_channel_description) setShowBadge(false) }, ) @@ -218,10 +218,10 @@ class AudioRoomForegroundService : Service() { override fun onBind(intent: Intent?): IBinder? = null companion object { - private const val CHANNEL_ID = "audio_room_foreground" + private const val CHANNEL_ID = "nest_foreground" private const val NOTIFICATION_ID = 0xA0D10 - private const val ACTION_PROMOTE_TO_MIC = "com.vitorpamplona.amethyst.audio_room.PROMOTE_MIC" - private const val ACTION_STOP = "com.vitorpamplona.amethyst.audio_room.STOP" + private const val ACTION_PROMOTE_TO_MIC = "com.vitorpamplona.amethyst.nest.PROMOTE_MIC" + private const val ACTION_STOP = "com.vitorpamplona.amethyst.nest.STOP" // 4-hour hard cap — long enough for typical audio-room sessions // (2-3 h podcasts / panels) plus headroom, short enough to release @@ -233,7 +233,7 @@ class AudioRoomForegroundService : Service() { fun startListening(context: Context) { ContextCompat.startForegroundService( context, - Intent(context, AudioRoomForegroundService::class.java), + Intent(context, NestForegroundService::class.java), ) } @@ -245,7 +245,7 @@ class AudioRoomForegroundService : Service() { fun promoteToMicrophone(context: Context) { ContextCompat.startForegroundService( context, - Intent(context, AudioRoomForegroundService::class.java).apply { + Intent(context, NestForegroundService::class.java).apply { action = ACTION_PROMOTE_TO_MIC }, ) @@ -253,7 +253,7 @@ class AudioRoomForegroundService : Service() { /** Stop and remove the foreground notification. Idempotent. */ fun stop(context: Context) { - context.stopService(Intent(context, AudioRoomForegroundService::class.java)) + context.stopService(Intent(context, NestForegroundService::class.java)) } } } diff --git a/amethyst/src/main/java/com/vitorpamplona/amethyst/service/relayClient/reqCommand/RelaySubscriptionsCoordinator.kt b/amethyst/src/main/java/com/vitorpamplona/amethyst/service/relayClient/reqCommand/RelaySubscriptionsCoordinator.kt index 9482638b7..c96d80a77 100644 --- a/amethyst/src/main/java/com/vitorpamplona/amethyst/service/relayClient/reqCommand/RelaySubscriptionsCoordinator.kt +++ b/amethyst/src/main/java/com/vitorpamplona/amethyst/service/relayClient/reqCommand/RelaySubscriptionsCoordinator.kt @@ -28,11 +28,6 @@ import com.vitorpamplona.amethyst.service.relayClient.reqCommand.nwc.NWCPaymentF import com.vitorpamplona.amethyst.service.relayClient.reqCommand.user.UserFinderFilterAssembler import com.vitorpamplona.amethyst.service.relayClient.searchCommand.SearchFilterAssembler import com.vitorpamplona.amethyst.ui.screen.loggedIn.articles.datasource.ArticlesFilterAssembler -import com.vitorpamplona.amethyst.ui.screen.loggedIn.audiorooms.datasource.AudioRoomsFilterAssembler -import com.vitorpamplona.amethyst.ui.screen.loggedIn.audiorooms.datasource.RoomAdminCommandsFilterAssembler -import com.vitorpamplona.amethyst.ui.screen.loggedIn.audiorooms.datasource.RoomChatFilterAssembler -import com.vitorpamplona.amethyst.ui.screen.loggedIn.audiorooms.datasource.RoomPresenceFilterAssembler -import com.vitorpamplona.amethyst.ui.screen.loggedIn.audiorooms.datasource.RoomReactionsFilterAssembler import com.vitorpamplona.amethyst.ui.screen.loggedIn.badges.datasource.BadgesFilterAssembler import com.vitorpamplona.amethyst.ui.screen.loggedIn.badges.profile.datasource.ProfileBadgesFilterAssembler import com.vitorpamplona.amethyst.ui.screen.loggedIn.chats.privateDM.datasource.ChatroomFilterAssembler @@ -50,6 +45,11 @@ import com.vitorpamplona.amethyst.ui.screen.loggedIn.hashtag.datasource.HashtagF import com.vitorpamplona.amethyst.ui.screen.loggedIn.home.datasource.HomeFilterAssembler import com.vitorpamplona.amethyst.ui.screen.loggedIn.livestreams.datasource.LiveStreamsFilterAssembler import com.vitorpamplona.amethyst.ui.screen.loggedIn.longs.datasource.LongsFilterAssembler +import com.vitorpamplona.amethyst.ui.screen.loggedIn.nests.datasource.NestsFilterAssembler +import com.vitorpamplona.amethyst.ui.screen.loggedIn.nests.datasource.RoomAdminCommandsFilterAssembler +import com.vitorpamplona.amethyst.ui.screen.loggedIn.nests.datasource.RoomChatFilterAssembler +import com.vitorpamplona.amethyst.ui.screen.loggedIn.nests.datasource.RoomPresenceFilterAssembler +import com.vitorpamplona.amethyst.ui.screen.loggedIn.nests.datasource.RoomReactionsFilterAssembler import com.vitorpamplona.amethyst.ui.screen.loggedIn.pictures.datasource.PicturesFilterAssembler import com.vitorpamplona.amethyst.ui.screen.loggedIn.polls.datasource.PollsFilterAssembler import com.vitorpamplona.amethyst.ui.screen.loggedIn.products.datasource.ProductsFilterAssembler @@ -110,7 +110,7 @@ class RelaySubscriptionsCoordinator( val shorts = ShortsFilterAssembler(client) val publicChats = PublicChatsFilterAssembler(client) val liveStreams = LiveStreamsFilterAssembler(client) - val audioRooms = AudioRoomsFilterAssembler(client) + val nests = NestsFilterAssembler(client) val roomPresence = RoomPresenceFilterAssembler(client) val roomChat = RoomChatFilterAssembler(client) val roomReactions = RoomReactionsFilterAssembler(client) @@ -139,7 +139,7 @@ class RelaySubscriptionsCoordinator( publicChats, followPacksList, liveStreams, - audioRooms, + nests, longs, articles, badges, diff --git a/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/feeds/RememberForeverStates.kt b/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/feeds/RememberForeverStates.kt index fd105237f..452845798 100644 --- a/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/feeds/RememberForeverStates.kt +++ b/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/feeds/RememberForeverStates.kt @@ -67,7 +67,7 @@ object ScrollStateKeys { const val PUBLIC_CHATS_SCREEN = "PublicChatsFeed" const val FOLLOW_PACKS_SCREEN = "FollowPacksFeed" const val LIVE_STREAMS_SCREEN = "LiveStreamsFeed" - const val AUDIO_ROOMS_SCREEN = "AudioRoomsFeed" + const val NESTS_SCREEN = "NestsFeed" const val LONGS_SCREEN = "LongsFeed" const val ARTICLES_SCREEN = "ArticlesFeed" diff --git a/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/navigation/AppNavigation.kt b/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/navigation/AppNavigation.kt index 85268ee02..69c66edcf 100644 --- a/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/navigation/AppNavigation.kt +++ b/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/navigation/AppNavigation.kt @@ -63,7 +63,6 @@ import com.vitorpamplona.amethyst.ui.screen.AccountSessionManager import com.vitorpamplona.amethyst.ui.screen.loggedIn.AccountSwitcherAndLeftDrawerLayout import com.vitorpamplona.amethyst.ui.screen.loggedIn.AccountViewModel import com.vitorpamplona.amethyst.ui.screen.loggedIn.articles.ArticlesScreen -import com.vitorpamplona.amethyst.ui.screen.loggedIn.audiorooms.AudioRoomsScreen import com.vitorpamplona.amethyst.ui.screen.loggedIn.badges.BadgesScreen import com.vitorpamplona.amethyst.ui.screen.loggedIn.badges.award.AwardBadgeScreen import com.vitorpamplona.amethyst.ui.screen.loggedIn.badges.profile.ProfileBadgesScreen @@ -128,6 +127,7 @@ import com.vitorpamplona.amethyst.ui.screen.loggedIn.lists.list.metadata.PeopleL import com.vitorpamplona.amethyst.ui.screen.loggedIn.lists.memberEdit.FollowListAndPackAndUserScreen import com.vitorpamplona.amethyst.ui.screen.loggedIn.livestreams.LiveStreamsScreen import com.vitorpamplona.amethyst.ui.screen.loggedIn.longs.LongsScreen +import com.vitorpamplona.amethyst.ui.screen.loggedIn.nests.NestsScreen import com.vitorpamplona.amethyst.ui.screen.loggedIn.newUser.ImportFollowListPickFollowsScreen import com.vitorpamplona.amethyst.ui.screen.loggedIn.newUser.ImportFollowListSelectUserScreen import com.vitorpamplona.amethyst.ui.screen.loggedIn.notifications.NotificationScreen @@ -245,7 +245,7 @@ fun BuildNavigation( composableFromEnd { PublicChatsScreen(accountViewModel, nav) } composableFromEnd { FollowPacksScreen(accountViewModel, nav) } composableFromEnd { LiveStreamsScreen(accountViewModel, nav) } - composableFromEnd { AudioRoomsScreen(accountViewModel, nav) } + composableFromEnd { NestsScreen(accountViewModel, nav) } composableFromEnd { LongsScreen(accountViewModel, nav) } composableFromEnd { ArticlesScreen(accountViewModel, nav) } composableFromEnd { NewHlsVideoScreen(accountViewModel, nav) } diff --git a/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/navigation/bottombars/NavBarItem.kt b/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/navigation/bottombars/NavBarItem.kt index edaa94f58..85bf299b7 100644 --- a/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/navigation/bottombars/NavBarItem.kt +++ b/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/navigation/bottombars/NavBarItem.kt @@ -54,7 +54,7 @@ enum class NavBarItem { PUBLIC_CHATS, FOLLOW_PACKS, LIVE_STREAMS, - AUDIO_ROOMS, + NESTS, LONGS, POLLS, BADGES, @@ -212,12 +212,12 @@ val NavBarCatalog: Map = icon = MaterialSymbols.Sensors, resolveRoute = { Route.LiveStreams }, ), - NavBarItem.AUDIO_ROOMS to + NavBarItem.NESTS to NavBarItemDef( - id = NavBarItem.AUDIO_ROOMS, - labelRes = R.string.audio_rooms, + id = NavBarItem.NESTS, + labelRes = R.string.nests, icon = MaterialSymbols.Mic, - resolveRoute = { Route.AudioRooms }, + resolveRoute = { Route.Nests }, ), NavBarItem.LONGS to NavBarItemDef( @@ -305,7 +305,7 @@ val DrawerFeedsItems: List = NavBarItem.PUBLIC_CHATS, NavBarItem.FOLLOW_PACKS, NavBarItem.LIVE_STREAMS, - if (isDebug) NavBarItem.AUDIO_ROOMS else null, + if (isDebug) NavBarItem.NESTS else null, NavBarItem.LONGS, NavBarItem.POLLS, NavBarItem.BADGES, diff --git a/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/navigation/routes/Routes.kt b/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/navigation/routes/Routes.kt index 32371da62..bf8742969 100644 --- a/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/navigation/routes/Routes.kt +++ b/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/navigation/routes/Routes.kt @@ -89,7 +89,7 @@ sealed class Route { @Serializable object LiveStreams : Route() - @Serializable object AudioRooms : Route() + @Serializable object Nests : Route() @Serializable object Longs : Route() diff --git a/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/note/types/MeetingSpace.kt b/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/note/types/MeetingSpace.kt index cd212331a..a6aaa9c1f 100644 --- a/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/note/types/MeetingSpace.kt +++ b/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/note/types/MeetingSpace.kt @@ -175,7 +175,7 @@ fun RenderMeetingSpaceEventInner( ListenToRecordingButton(url = it, accountViewModel = accountViewModel) } } else { - com.vitorpamplona.amethyst.ui.screen.loggedIn.audiorooms.room.JoinAudioRoomButton( + com.vitorpamplona.amethyst.ui.screen.loggedIn.nests.room.JoinNestButton( event = noteEvent, accountViewModel = accountViewModel, ) @@ -196,7 +196,7 @@ private fun ListenToRecordingButton( accountViewModel: AccountViewModel, ) { val context = androidx.compose.ui.platform.LocalContext.current - val noAppMessage = stringRes(R.string.audio_room_no_app_to_open_link) + val noAppMessage = stringRes(R.string.nest_no_app_to_open_link) androidx.compose.material3.OutlinedButton(onClick = { val launched = runCatching { @@ -208,13 +208,13 @@ private fun ListenToRecordingButton( }.isSuccess if (!launched) { accountViewModel.toastManager.toast( - R.string.audio_room_chat_send_failed_title, + R.string.nest_chat_send_failed_title, noAppMessage, user = null, ) } }) { - Text(stringRes(R.string.audio_room_listen_to_recording)) + Text(stringRes(R.string.nest_listen_to_recording)) } } diff --git a/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/AccountFeedContentStates.kt b/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/AccountFeedContentStates.kt index fb08a3e52..8c9e821b9 100644 --- a/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/AccountFeedContentStates.kt +++ b/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/AccountFeedContentStates.kt @@ -28,7 +28,6 @@ import com.vitorpamplona.amethyst.service.checkNotInMainThread import com.vitorpamplona.amethyst.ui.feeds.ChannelFeedContentState import com.vitorpamplona.amethyst.ui.screen.TopNavFilterState import com.vitorpamplona.amethyst.ui.screen.loggedIn.articles.dal.ArticlesFeedFilter -import com.vitorpamplona.amethyst.ui.screen.loggedIn.audiorooms.dal.AudioRoomsFeedFilter import com.vitorpamplona.amethyst.ui.screen.loggedIn.badges.dal.BadgesFeedFilter import com.vitorpamplona.amethyst.ui.screen.loggedIn.chats.rooms.dal.ChatroomListKnownFeedFilter import com.vitorpamplona.amethyst.ui.screen.loggedIn.chats.rooms.dal.ChatroomListNewFeedFilter @@ -48,6 +47,7 @@ import com.vitorpamplona.amethyst.ui.screen.loggedIn.home.dal.HomeLiveFilter import com.vitorpamplona.amethyst.ui.screen.loggedIn.home.dal.HomeNewThreadFeedFilter import com.vitorpamplona.amethyst.ui.screen.loggedIn.livestreams.dal.LiveStreamsFeedFilter import com.vitorpamplona.amethyst.ui.screen.loggedIn.longs.dal.LongsFeedFilter +import com.vitorpamplona.amethyst.ui.screen.loggedIn.nests.dal.NestsFeedFilter import com.vitorpamplona.amethyst.ui.screen.loggedIn.notifications.CardFeedContentState import com.vitorpamplona.amethyst.ui.screen.loggedIn.notifications.NotificationSummaryState import com.vitorpamplona.amethyst.ui.screen.loggedIn.notifications.OpenPollsState @@ -101,7 +101,7 @@ class AccountFeedContentStates( val publicChatsFeed = FeedContentState(PublicChatsFeedFilter(account), scope, LocalCache) val followPacksFeed = FeedContentState(FollowPacksFeedFilter(account), scope, LocalCache) val liveStreamsFeed = FeedContentState(LiveStreamsFeedFilter(account), scope, LocalCache) - val audioRoomsFeed = FeedContentState(AudioRoomsFeedFilter(account), scope, LocalCache) + val nestsFeed = FeedContentState(NestsFeedFilter(account), scope, LocalCache) val longsFeed = FeedContentState(LongsFeedFilter(account), scope, LocalCache) val articlesFeed = FeedContentState(ArticlesFeedFilter(account), scope, LocalCache) @@ -168,7 +168,7 @@ class AccountFeedContentStates( publicChatsFeed.updateFeedWith(newNotes) followPacksFeed.updateFeedWith(newNotes) liveStreamsFeed.updateFeedWith(newNotes) - audioRoomsFeed.updateFeedWith(newNotes) + nestsFeed.updateFeedWith(newNotes) longsFeed.updateFeedWith(newNotes) articlesFeed.updateFeedWith(newNotes) @@ -215,7 +215,7 @@ class AccountFeedContentStates( publicChatsFeed.deleteFromFeed(newNotes) followPacksFeed.deleteFromFeed(newNotes) liveStreamsFeed.deleteFromFeed(newNotes) - audioRoomsFeed.deleteFromFeed(newNotes) + nestsFeed.deleteFromFeed(newNotes) longsFeed.deleteFromFeed(newNotes) articlesFeed.deleteFromFeed(newNotes) diff --git a/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/AccountViewModel.kt b/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/AccountViewModel.kt index 6b9fe0313..775e046f3 100644 --- a/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/AccountViewModel.kt +++ b/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/AccountViewModel.kt @@ -1574,7 +1574,7 @@ class AccountViewModel( callManager.dispose() com.vitorpamplona.amethyst.service.call.CallSessionBridge .clear() - com.vitorpamplona.amethyst.ui.screen.loggedIn.audiorooms.room.AudioRoomBridge + com.vitorpamplona.amethyst.ui.screen.loggedIn.nests.room.NestBridge .clear() feedStates.destroy() super.onCleared() diff --git a/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/chats/publicChannels/nip53LiveActivities/ChannelView.kt b/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/chats/publicChannels/nip53LiveActivities/ChannelView.kt index 3a649734e..630cb78aa 100644 --- a/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/chats/publicChannels/nip53LiveActivities/ChannelView.kt +++ b/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/chats/publicChannels/nip53LiveActivities/ChannelView.kt @@ -35,7 +35,6 @@ import com.vitorpamplona.amethyst.ui.feeds.WatchLifecycleAndUpdateModel import com.vitorpamplona.amethyst.ui.navigation.navs.INav import com.vitorpamplona.amethyst.ui.note.LoadLiveActivityChannel import com.vitorpamplona.amethyst.ui.screen.loggedIn.AccountViewModel -import com.vitorpamplona.amethyst.ui.screen.loggedIn.audiorooms.room.AudioRoomJoinCard import com.vitorpamplona.amethyst.ui.screen.loggedIn.chats.feed.RefreshingChatroomFeedView import com.vitorpamplona.amethyst.ui.screen.loggedIn.chats.publicChannels.dal.ChannelFeedViewModel import com.vitorpamplona.amethyst.ui.screen.loggedIn.chats.publicChannels.datasource.ChannelFilterAssemblerSubscription @@ -43,6 +42,7 @@ import com.vitorpamplona.amethyst.ui.screen.loggedIn.chats.publicChannels.nip53L import com.vitorpamplona.amethyst.ui.screen.loggedIn.chats.publicChannels.nip53LiveActivities.header.LiveStreamTopZappers import com.vitorpamplona.amethyst.ui.screen.loggedIn.chats.publicChannels.send.ChannelNewMessageViewModel import com.vitorpamplona.amethyst.ui.screen.loggedIn.chats.publicChannels.send.EditFieldRow +import com.vitorpamplona.amethyst.ui.screen.loggedIn.nests.room.NestJoinCard import com.vitorpamplona.amethyst.ui.theme.DoubleVertSpacer import com.vitorpamplona.quartz.nip01Core.core.Address @@ -130,7 +130,7 @@ fun LiveActivityChannelView( .weight(1f, true), ) { ShowVideoStreaming(channel, accountViewModel) - AudioRoomJoinCard(channel, accountViewModel) + NestJoinCard(channel, accountViewModel) LiveStreamTopZappers(channel, accountViewModel, nav) LiveStreamGoalHeader(channel, accountViewModel, nav) RefreshingChatroomFeedView( diff --git a/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/home/live/RenderLiveActivityBubble.kt b/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/home/live/RenderLiveActivityBubble.kt index 0945e8d47..045df9371 100644 --- a/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/home/live/RenderLiveActivityBubble.kt +++ b/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/home/live/RenderLiveActivityBubble.kt @@ -38,8 +38,8 @@ import com.vitorpamplona.amethyst.ui.navigation.navs.INav import com.vitorpamplona.amethyst.ui.navigation.routes.routeFor import com.vitorpamplona.amethyst.ui.note.Gallery import com.vitorpamplona.amethyst.ui.screen.loggedIn.AccountViewModel -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.screen.loggedIn.nests.room.NestActivity +import com.vitorpamplona.amethyst.ui.screen.loggedIn.nests.room.NestBridge import com.vitorpamplona.amethyst.ui.theme.StdHorzSpacer import com.vitorpamplona.quartz.nip53LiveActivities.meetingSpaces.MeetingSpaceEvent @@ -55,7 +55,7 @@ fun RenderLiveActivityBubble( // LiveActivitiesEvent), so toBestDisplayName() would fall back // to the truncated bech32. Read the kind-30312 addressable // directly when the channel's address points to one and use the - // room name + a launch path that goes straight to AudioRoomActivity. + // room name + a launch path that goes straight to NestActivity. val meetingEvent = remember(channel.address) { if (channel.address.kind == MeetingSpaceEvent.KIND) { @@ -73,8 +73,8 @@ fun RenderLiveActivityBubble( val endpoint = meetingEvent.endpoint() val dTag = meetingEvent.address().dTag if (!service.isNullOrBlank() && !endpoint.isNullOrBlank() && dTag.isNotBlank()) { - AudioRoomBridge.set(accountViewModel) - AudioRoomActivity.launch( + NestBridge.set(accountViewModel) + NestActivity.launch( context = context, addressValue = meetingEvent.address().toValue(), authBaseUrl = service, diff --git a/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/audiorooms/AudioRoomsFeedLoaded.kt b/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/nests/NestsFeedLoaded.kt similarity index 90% rename from amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/audiorooms/AudioRoomsFeedLoaded.kt rename to amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/nests/NestsFeedLoaded.kt index 04e8518fa..e1b9d5c6b 100644 --- a/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/audiorooms/AudioRoomsFeedLoaded.kt +++ b/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/nests/NestsFeedLoaded.kt @@ -18,7 +18,7 @@ * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -package com.vitorpamplona.amethyst.ui.screen.loggedIn.audiorooms +package com.vitorpamplona.amethyst.ui.screen.loggedIn.nests import androidx.compose.foundation.ExperimentalFoundationApi import androidx.compose.foundation.clickable @@ -41,9 +41,9 @@ import com.vitorpamplona.amethyst.ui.layouts.rememberFeedContentPadding import com.vitorpamplona.amethyst.ui.navigation.navs.INav import com.vitorpamplona.amethyst.ui.navigation.routes.routeFor import com.vitorpamplona.amethyst.ui.screen.loggedIn.AccountViewModel -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.screen.loggedIn.discover.nip53LiveActivities.RenderLiveActivityThumb +import com.vitorpamplona.amethyst.ui.screen.loggedIn.nests.room.NestActivity +import com.vitorpamplona.amethyst.ui.screen.loggedIn.nests.room.NestBridge import com.vitorpamplona.amethyst.ui.theme.DividerThickness import com.vitorpamplona.amethyst.ui.theme.FeedPadding import com.vitorpamplona.amethyst.ui.theme.StdPadding @@ -51,7 +51,7 @@ import com.vitorpamplona.quartz.nip53LiveActivities.meetingSpaces.MeetingSpaceEv @OptIn(ExperimentalFoundationApi::class) @Composable -fun AudioRoomsFeedLoaded( +fun NestsFeedLoaded( loaded: FeedState.Loaded, listState: LazyListState, accountViewModel: AccountViewModel, @@ -65,7 +65,7 @@ fun AudioRoomsFeedLoaded( ) { itemsIndexed(items.list, key = { _, item -> item.idHex }) { _, item -> Row(Modifier.fillMaxWidth().animateItem()) { - AudioRoomFeedCard( + NestFeedCard( baseNote = item, modifier = Modifier.fillMaxWidth(), accountViewModel = accountViewModel, @@ -82,12 +82,12 @@ fun AudioRoomsFeedLoaded( /** * Audio-rooms list card. Mirrors [RenderLiveActivityThumb] visually but - * routes a tap straight into [AudioRoomActivity] when the underlying event + * routes a tap straight into [NestActivity] when the underlying event * is a [MeetingSpaceEvent], instead of the thread view that the generic * `ChannelCardCompose` → `ClickableNote` chain would otherwise open. */ @Composable -private fun AudioRoomFeedCard( +private fun NestFeedCard( baseNote: Note, modifier: Modifier, accountViewModel: AccountViewModel, @@ -103,8 +103,8 @@ private fun AudioRoomFeedCard( val endpoint = meetingEvent.endpoint() val dTag = meetingEvent.address().dTag if (!service.isNullOrBlank() && !endpoint.isNullOrBlank() && dTag.isNotBlank()) { - AudioRoomBridge.set(accountViewModel) - AudioRoomActivity.launch( + NestBridge.set(accountViewModel) + NestActivity.launch( context = context, addressValue = meetingEvent.address().toValue(), authBaseUrl = service, diff --git a/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/audiorooms/AudioRoomsScreen.kt b/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/nests/NestsScreen.kt similarity index 73% rename from amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/audiorooms/AudioRoomsScreen.kt rename to amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/nests/NestsScreen.kt index c91515440..a5f8080e8 100644 --- a/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/audiorooms/AudioRoomsScreen.kt +++ b/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/nests/NestsScreen.kt @@ -18,7 +18,7 @@ * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -package com.vitorpamplona.amethyst.ui.screen.loggedIn.audiorooms +package com.vitorpamplona.amethyst.ui.screen.loggedIn.nests import androidx.compose.foundation.shape.CircleShape import androidx.compose.material3.AlertDialog @@ -46,32 +46,32 @@ import com.vitorpamplona.amethyst.ui.navigation.bottombars.AppBottomBar import com.vitorpamplona.amethyst.ui.navigation.navs.INav import com.vitorpamplona.amethyst.ui.navigation.routes.Route import com.vitorpamplona.amethyst.ui.screen.loggedIn.AccountViewModel -import com.vitorpamplona.amethyst.ui.screen.loggedIn.audiorooms.create.CreateAudioRoomSheet -import com.vitorpamplona.amethyst.ui.screen.loggedIn.audiorooms.create.CreateAudioRoomViewModel -import com.vitorpamplona.amethyst.ui.screen.loggedIn.audiorooms.datasource.AudioRoomsFilterAssemblerSubscription +import com.vitorpamplona.amethyst.ui.screen.loggedIn.nests.create.CreateNestSheet +import com.vitorpamplona.amethyst.ui.screen.loggedIn.nests.create.CreateNestViewModel +import com.vitorpamplona.amethyst.ui.screen.loggedIn.nests.datasource.NestsFilterAssemblerSubscription import com.vitorpamplona.amethyst.ui.stringRes @Composable -fun AudioRoomsScreen( +fun NestsScreen( accountViewModel: AccountViewModel, nav: INav, ) { - AudioRoomsScreen( - audioRoomsFeedContentState = accountViewModel.feedStates.audioRoomsFeed, + NestsScreen( + nestsFeedContentState = accountViewModel.feedStates.nestsFeed, accountViewModel = accountViewModel, nav = nav, ) } @Composable -fun AudioRoomsScreen( - audioRoomsFeedContentState: FeedContentState, +fun NestsScreen( + nestsFeedContentState: FeedContentState, accountViewModel: AccountViewModel, nav: INav, ) { - WatchLifecycleAndUpdateModel(audioRoomsFeedContentState) - WatchAccountForAudioRoomsScreen(audioRoomsFeedState = audioRoomsFeedContentState, accountViewModel = accountViewModel) - AudioRoomsFilterAssemblerSubscription(accountViewModel) + WatchLifecycleAndUpdateModel(nestsFeedContentState) + WatchAccountForNestsScreen(nestsFeedState = nestsFeedContentState, accountViewModel = accountViewModel) + NestsFilterAssemblerSubscription(accountViewModel) val nestsServers by accountViewModel.account.nestsServers.flow .collectAsStateWithLifecycle() @@ -81,12 +81,12 @@ fun AudioRoomsScreen( DisappearingScaffold( isInvertedLayout = false, topBar = { - AudioRoomsTopBar(accountViewModel, nav) + NestsTopBar(accountViewModel, nav) }, bottomBar = { - AppBottomBar(Route.AudioRooms, accountViewModel) { route -> - if (route == Route.AudioRooms) { - audioRoomsFeedContentState.sendToTop() + AppBottomBar(Route.Nests, accountViewModel) { route -> + if (route == Route.Nests) { + nestsFeedContentState.sendToTop() } else { nav.navBottomBar(route) } @@ -105,22 +105,22 @@ fun AudioRoomsScreen( ) { Icon( symbol = MaterialSymbols.Add, - contentDescription = stringRes(R.string.audio_room_create_fab), + contentDescription = stringRes(R.string.nest_create_fab), ) } }, accountViewModel = accountViewModel, ) { - RefresheableBox(audioRoomsFeedContentState, true) { - SaveableFeedContentState(audioRoomsFeedContentState, scrollStateKey = ScrollStateKeys.AUDIO_ROOMS_SCREEN) { listState -> + RefresheableBox(nestsFeedContentState, true) { + SaveableFeedContentState(nestsFeedContentState, scrollStateKey = ScrollStateKeys.NESTS_SCREEN) { listState -> RenderFeedContentState( - feedContentState = audioRoomsFeedContentState, + feedContentState = nestsFeedContentState, accountViewModel = accountViewModel, listState = listState, nav = nav, - routeForLastRead = "AudioRoomsFeed", + routeForLastRead = "NestsFeed", onLoaded = { loaded -> - AudioRoomsFeedLoaded( + NestsFeedLoaded( loaded = loaded, listState = listState, accountViewModel = accountViewModel, @@ -134,20 +134,20 @@ fun AudioRoomsScreen( if (showSetupDialog) { SetUpAudioServerDialog( - defaultUrl = CreateAudioRoomViewModel.DEFAULT_SERVICE_URL, + defaultUrl = CreateNestViewModel.DEFAULT_SERVICE_URL, onDismiss = { showSetupDialog = false }, onConfirm = { showSetupDialog = false accountViewModel.launchSigner { try { accountViewModel.account.sendNestsServersList( - listOf(CreateAudioRoomViewModel.DEFAULT_SERVICE_URL), + listOf(CreateNestViewModel.DEFAULT_SERVICE_URL), ) showCreateSheet = true } catch (_: Throwable) { accountViewModel.toastManager.toast( - R.string.audio_rooms, - R.string.audio_room_no_server_save_failed, + R.string.nests, + R.string.nest_no_server_save_failed, ) } } @@ -156,7 +156,7 @@ fun AudioRoomsScreen( } if (showCreateSheet) { - CreateAudioRoomSheet( + CreateNestSheet( accountViewModel = accountViewModel, onDismiss = { showCreateSheet = false }, ) @@ -171,24 +171,24 @@ private fun SetUpAudioServerDialog( ) { AlertDialog( onDismissRequest = onDismiss, - title = { Text(stringRes(R.string.audio_room_no_server_title)) }, - text = { Text(stringRes(R.string.audio_room_no_server_body, defaultUrl)) }, + title = { Text(stringRes(R.string.nest_no_server_title)) }, + text = { Text(stringRes(R.string.nest_no_server_body, defaultUrl)) }, confirmButton = { TextButton(onClick = onConfirm) { - Text(stringRes(R.string.audio_room_no_server_use_default)) + Text(stringRes(R.string.nest_no_server_use_default)) } }, dismissButton = { TextButton(onClick = onDismiss) { - Text(stringRes(R.string.audio_room_no_server_cancel)) + Text(stringRes(R.string.nest_no_server_cancel)) } }, ) } @Composable -fun WatchAccountForAudioRoomsScreen( - audioRoomsFeedState: FeedContentState, +fun WatchAccountForNestsScreen( + nestsFeedState: FeedContentState, accountViewModel: AccountViewModel, ) { val listState by accountViewModel.account.liveLiveStreamsFollowLists.collectAsStateWithLifecycle() @@ -201,6 +201,6 @@ fun WatchAccountForAudioRoomsScreen( .collectAsStateWithLifecycle() LaunchedEffect(accountViewModel, listState, hiddenUsers) { - audioRoomsFeedState.checkKeysInvalidateDataAndSendToTop() + nestsFeedState.checkKeysInvalidateDataAndSendToTop() } } diff --git a/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/audiorooms/AudioRoomsTopBar.kt b/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/nests/NestsTopBar.kt similarity index 94% rename from amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/audiorooms/AudioRoomsTopBar.kt rename to amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/nests/NestsTopBar.kt index c76315864..e4e8221bd 100644 --- a/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/audiorooms/AudioRoomsTopBar.kt +++ b/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/nests/NestsTopBar.kt @@ -18,7 +18,7 @@ * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -package com.vitorpamplona.amethyst.ui.screen.loggedIn.audiorooms +package com.vitorpamplona.amethyst.ui.screen.loggedIn.nests import androidx.compose.runtime.Composable import androidx.compose.runtime.getValue @@ -34,7 +34,7 @@ import com.vitorpamplona.amethyst.ui.screen.loggedIn.AccountViewModel import com.vitorpamplona.amethyst.ui.stringRes @Composable -fun AudioRoomsTopBar( +fun NestsTopBar( accountViewModel: AccountViewModel, nav: INav, ) { @@ -42,7 +42,7 @@ fun AudioRoomsTopBar( val list by accountViewModel.account.settings.defaultLiveStreamsFollowList .collectAsStateWithLifecycle() - AudioRoomsTopNavFilterBar( + NestsTopNavFilterBar( followListsModel = accountViewModel.feedStates.feedListOptions, listName = list, accountViewModel = accountViewModel, @@ -52,7 +52,7 @@ fun AudioRoomsTopBar( } @Composable -private fun AudioRoomsTopNavFilterBar( +private fun NestsTopNavFilterBar( followListsModel: TopNavFilterState, listName: TopFilter, accountViewModel: AccountViewModel, diff --git a/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/audiorooms/create/CreateAudioRoomSheet.kt b/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/nests/create/CreateNestSheet.kt similarity index 86% rename from amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/audiorooms/create/CreateAudioRoomSheet.kt rename to amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/nests/create/CreateNestSheet.kt index 38eb464d4..604df59e0 100644 --- a/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/audiorooms/create/CreateAudioRoomSheet.kt +++ b/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/nests/create/CreateNestSheet.kt @@ -18,7 +18,7 @@ * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -package com.vitorpamplona.amethyst.ui.screen.loggedIn.audiorooms.create +package com.vitorpamplona.amethyst.ui.screen.loggedIn.nests.create import androidx.compose.foundation.layout.Arrangement import androidx.compose.foundation.layout.Column @@ -54,32 +54,32 @@ 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.screen.loggedIn.nests.NestsScreen +import com.vitorpamplona.amethyst.ui.screen.loggedIn.nests.room.NestActivity +import com.vitorpamplona.amethyst.ui.screen.loggedIn.nests.room.NestBridge import com.vitorpamplona.amethyst.ui.stringRes import kotlinx.coroutines.launch /** * Bottom sheet that lets the logged-in user start a new NIP-53 kind 30312 - * audio room. On submit, [CreateAudioRoomViewModel] builds and signs the + * audio room. On submit, [CreateNestViewModel] builds and signs the * MeetingSpaceEvent (with the user as `host`), broadcasts it to the - * account's relays, and then launches [AudioRoomActivity] against the + * account's relays, and then launches [NestActivity] against the * fresh address — the user lands inside the room as host with the * Talk button enabled. * * Hidden by default; surfaced by the "Start space" FAB on - * [AudioRoomsScreen]. + * [NestsScreen]. */ @OptIn(ExperimentalMaterial3Api::class) @Composable -fun CreateAudioRoomSheet( +fun CreateNestSheet( accountViewModel: AccountViewModel, onDismiss: () -> Unit, ) { val viewModelKey = remember(accountViewModel) { accountViewModel.account.userProfile().pubkeyHex } - val viewModel: CreateAudioRoomViewModel = - viewModel(key = "CreateAudioRoom-$viewModelKey") + val viewModel: CreateNestViewModel = + viewModel(key = "CreateNest-$viewModelKey") LaunchedEffect(viewModel) { viewModel.bindAccountIfMissing(accountViewModel) } val state by viewModel.state.collectAsState() @@ -96,14 +96,14 @@ fun CreateAudioRoomSheet( verticalArrangement = Arrangement.spacedBy(8.dp), ) { Text( - text = stringRes(R.string.audio_room_create_title), + text = stringRes(R.string.nest_create_title), style = MaterialTheme.typography.titleLarge, ) OutlinedTextField( value = state.roomName, onValueChange = viewModel::onRoomNameChange, - label = { Text(stringRes(R.string.audio_room_create_field_room)) }, + label = { Text(stringRes(R.string.nest_create_field_room)) }, singleLine = true, isError = state.error != null && state.roomName.isBlank(), modifier = Modifier.fillMaxWidth(), @@ -112,7 +112,7 @@ fun CreateAudioRoomSheet( OutlinedTextField( value = state.summary, onValueChange = viewModel::onSummaryChange, - label = { Text(stringRes(R.string.audio_room_create_field_summary)) }, + label = { Text(stringRes(R.string.nest_create_field_summary)) }, modifier = Modifier.fillMaxWidth(), keyboardOptions = KeyboardOptions(capitalization = KeyboardCapitalization.Sentences), ) @@ -120,27 +120,27 @@ fun CreateAudioRoomSheet( OutlinedTextField( value = state.serviceUrl, onValueChange = viewModel::onServiceUrlChange, - label = { Text(stringRes(R.string.audio_room_create_field_service)) }, + label = { Text(stringRes(R.string.nest_create_field_service)) }, singleLine = true, isError = state.error != null && state.serviceUrl.isBlank(), - supportingText = { Text(stringRes(R.string.audio_room_create_field_service_hint)) }, + supportingText = { Text(stringRes(R.string.nest_create_field_service_hint)) }, modifier = Modifier.fillMaxWidth(), ) OutlinedTextField( value = state.endpointUrl, onValueChange = viewModel::onEndpointUrlChange, - label = { Text(stringRes(R.string.audio_room_create_field_endpoint)) }, + label = { Text(stringRes(R.string.nest_create_field_endpoint)) }, singleLine = true, isError = state.error != null && state.endpointUrl.isBlank(), - supportingText = { Text(stringRes(R.string.audio_room_create_field_endpoint_hint)) }, + supportingText = { Text(stringRes(R.string.nest_create_field_endpoint_hint)) }, modifier = Modifier.fillMaxWidth(), ) OutlinedTextField( value = state.imageUrl, onValueChange = viewModel::onImageUrlChange, - label = { Text(stringRes(R.string.audio_room_create_field_image)) }, + label = { Text(stringRes(R.string.nest_create_field_image)) }, singleLine = true, modifier = Modifier.fillMaxWidth(), ) @@ -157,7 +157,7 @@ fun CreateAudioRoomSheet( onCheckedChange = viewModel::onScheduledToggle, ) Spacer(Modifier.width(8.dp)) - Text(stringRes(R.string.audio_room_create_schedule_toggle)) + Text(stringRes(R.string.nest_create_schedule_toggle)) } if (state.scheduled) { ScheduleStartPicker( @@ -181,7 +181,7 @@ fun CreateAudioRoomSheet( horizontalArrangement = Arrangement.End, ) { TextButton(onClick = onDismiss, enabled = !state.isPublishing) { - Text(stringRes(R.string.audio_room_create_cancel)) + Text(stringRes(R.string.nest_create_cancel)) } Spacer(Modifier.width(8.dp)) Button( @@ -189,10 +189,10 @@ fun CreateAudioRoomSheet( scope.launch { val launchInfo = viewModel.publishAndBuildLaunchInfo() ?: return@launch // Hand the active AccountViewModel to the - // separately-tasked AudioRoomActivity (mirrors + // separately-tasked NestActivity (mirrors // the join-card flow). - AudioRoomBridge.set(accountViewModel) - AudioRoomActivity.launch( + NestBridge.set(accountViewModel) + NestActivity.launch( context = context, addressValue = launchInfo.addressValue, authBaseUrl = launchInfo.authBaseUrl, @@ -212,7 +212,7 @@ fun CreateAudioRoomSheet( strokeWidth = 2.dp, ) } else { - Text(stringRes(R.string.audio_room_create_submit)) + Text(stringRes(R.string.nest_create_submit)) } } } @@ -238,7 +238,7 @@ private fun ScheduleStartPicker( val pretty = if (unixSeconds <= 0L) { - stringRes(R.string.audio_room_create_when) + stringRes(R.string.nest_create_when) } else { val instant = java.util.Date(unixSeconds * 1000L) java.text.DateFormat @@ -302,7 +302,7 @@ private fun ScheduleStartPicker( resetPickersToCommitted() showDate = false }) { - Text(stringRes(R.string.audio_room_create_cancel)) + Text(stringRes(R.string.nest_create_cancel)) } }, ) { @@ -312,7 +312,7 @@ private fun ScheduleStartPicker( if (showTime) { androidx.compose.material3.TimePickerDialog( - title = { Text(stringRes(R.string.audio_room_create_when)) }, + title = { Text(stringRes(R.string.nest_create_when)) }, onDismissRequest = { resetPickersToCommitted() showTime = false @@ -340,14 +340,14 @@ private fun ScheduleStartPicker( onChange(localSeconds - offsetSec) } showTime = false - }) { Text(stringRes(R.string.audio_room_create_submit)) } + }) { Text(stringRes(R.string.nest_create_submit)) } }, dismissButton = { TextButton(onClick = { resetPickersToCommitted() showTime = false }) { - Text(stringRes(R.string.audio_room_create_cancel)) + Text(stringRes(R.string.nest_create_cancel)) } }, ) { diff --git a/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/audiorooms/create/CreateAudioRoomViewModel.kt b/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/nests/create/CreateNestViewModel.kt similarity index 95% rename from amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/audiorooms/create/CreateAudioRoomViewModel.kt rename to amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/nests/create/CreateNestViewModel.kt index a047168ff..01b14831b 100644 --- a/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/audiorooms/create/CreateAudioRoomViewModel.kt +++ b/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/nests/create/CreateNestViewModel.kt @@ -18,11 +18,11 @@ * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -package com.vitorpamplona.amethyst.ui.screen.loggedIn.audiorooms.create +package com.vitorpamplona.amethyst.ui.screen.loggedIn.nests.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.amethyst.ui.screen.loggedIn.nests.room.NestActivity import com.vitorpamplona.quartz.nip53LiveActivities.meetingSpaces.MeetingSpaceEvent import com.vitorpamplona.quartz.nip53LiveActivities.meetingSpaces.endpoint import com.vitorpamplona.quartz.nip53LiveActivities.meetingSpaces.image @@ -37,16 +37,16 @@ import kotlinx.coroutines.flow.asStateFlow import kotlinx.coroutines.flow.update /** - * Backing ViewModel for [CreateAudioRoomSheet]. Holds form state, runs + * Backing ViewModel for [CreateNestSheet]. 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 [AudioRoomActivity]. + * the launch parameters for [NestActivity]. * * 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 * their own moq-rs / moq-auth pair. */ -class CreateAudioRoomViewModel : ViewModel() { +class CreateNestViewModel : ViewModel() { /** Lazily bound on first composition; the sheet calls [bindAccountIfMissing]. */ @Volatile private var account: AccountViewModel? = null @@ -91,7 +91,7 @@ class CreateAudioRoomViewModel : ViewModel() { /** * Build the kind-30312 event, sign + broadcast it, and return the - * launch info the sheet needs to start [AudioRoomActivity]. Returns + * launch info the sheet needs to start [NestActivity]. Returns * null on validation or network failure (with [FormState.error] * set so the UI can render it). */ @@ -222,7 +222,7 @@ class CreateAudioRoomViewModel : ViewModel() { } /** - * Captured fields needed to launch [AudioRoomActivity]. Mirrors the + * Captured fields needed to launch [NestActivity]. Mirrors the * `EXTRA_*` set the activity expects; pulled out here so the sheet * is a thin renderer. */ diff --git a/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/audiorooms/dal/AudioRoomsFeedFilter.kt b/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/nests/dal/NestsFeedFilter.kt similarity index 98% rename from amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/audiorooms/dal/AudioRoomsFeedFilter.kt rename to amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/nests/dal/NestsFeedFilter.kt index e38167b7b..691bdfeaa 100644 --- a/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/audiorooms/dal/AudioRoomsFeedFilter.kt +++ b/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/nests/dal/NestsFeedFilter.kt @@ -18,7 +18,7 @@ * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -package com.vitorpamplona.amethyst.ui.screen.loggedIn.audiorooms.dal +package com.vitorpamplona.amethyst.ui.screen.loggedIn.nests.dal import com.vitorpamplona.amethyst.model.Account import com.vitorpamplona.amethyst.model.LocalCache @@ -45,7 +45,7 @@ import com.vitorpamplona.quartz.nip53LiveActivities.meetingSpaces.tags.StatusTag * to MeetingSpaceEvent (30312) and MeetingRoomEvent (30313) so that the * Clubhouse-style audio-room surface is independent of video live streams. */ -class AudioRoomsFeedFilter( +class NestsFeedFilter( val account: Account, ) : AdditiveFeedFilter() { override fun feedKey(): String = account.userProfile().pubkeyHex + "-" + followList().code diff --git a/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/audiorooms/datasource/AudioRoomsFilterAssembler.kt b/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/nests/datasource/NestsFilterAssembler.kt similarity index 88% rename from amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/audiorooms/datasource/AudioRoomsFilterAssembler.kt rename to amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/nests/datasource/NestsFilterAssembler.kt index 7345e132e..a05c0d070 100644 --- a/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/audiorooms/datasource/AudioRoomsFilterAssembler.kt +++ b/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/nests/datasource/NestsFilterAssembler.kt @@ -18,7 +18,7 @@ * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -package com.vitorpamplona.amethyst.ui.screen.loggedIn.audiorooms.datasource +package com.vitorpamplona.amethyst.ui.screen.loggedIn.nests.datasource import androidx.compose.runtime.Stable import com.vitorpamplona.amethyst.commons.relayClient.composeSubscriptionManagers.ComposeSubscriptionManager @@ -27,19 +27,19 @@ import com.vitorpamplona.amethyst.ui.screen.loggedIn.AccountFeedContentStates import com.vitorpamplona.quartz.nip01Core.relay.client.INostrClient import kotlinx.coroutines.CoroutineScope -class AudioRoomsQueryState( +class NestsQueryState( val account: Account, val feedStates: AccountFeedContentStates, val scope: CoroutineScope, ) @Stable -class AudioRoomsFilterAssembler( +class NestsFilterAssembler( client: INostrClient, -) : ComposeSubscriptionManager() { +) : ComposeSubscriptionManager() { val group = listOf( - AudioRoomsSubAssembler(client, ::allKeys), + NestsSubAssembler(client, ::allKeys), ) override fun invalidateKeys() = invalidateFilters() diff --git a/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/audiorooms/datasource/AudioRoomsFilterAssemblerSubscription.kt b/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/nests/datasource/NestsFilterAssemblerSubscription.kt similarity index 78% rename from amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/audiorooms/datasource/AudioRoomsFilterAssemblerSubscription.kt rename to amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/nests/datasource/NestsFilterAssemblerSubscription.kt index 9e536a8f1..6aef84671 100644 --- a/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/audiorooms/datasource/AudioRoomsFilterAssemblerSubscription.kt +++ b/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/nests/datasource/NestsFilterAssemblerSubscription.kt @@ -18,7 +18,7 @@ * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -package com.vitorpamplona.amethyst.ui.screen.loggedIn.audiorooms.datasource +package com.vitorpamplona.amethyst.ui.screen.loggedIn.nests.datasource import androidx.compose.runtime.Composable import androidx.compose.runtime.remember @@ -27,21 +27,21 @@ import com.vitorpamplona.amethyst.commons.relayClient.subscriptions.KeyDataSourc import com.vitorpamplona.amethyst.ui.screen.loggedIn.AccountViewModel @Composable -fun AudioRoomsFilterAssemblerSubscription(accountViewModel: AccountViewModel) { - AudioRoomsFilterAssemblerSubscription( - accountViewModel.dataSources().audioRooms, +fun NestsFilterAssemblerSubscription(accountViewModel: AccountViewModel) { + NestsFilterAssemblerSubscription( + accountViewModel.dataSources().nests, accountViewModel, ) } @Composable -fun AudioRoomsFilterAssemblerSubscription( - dataSource: AudioRoomsFilterAssembler, +fun NestsFilterAssemblerSubscription( + dataSource: NestsFilterAssembler, accountViewModel: AccountViewModel, ) { val state = remember(accountViewModel.account) { - AudioRoomsQueryState(accountViewModel.account, accountViewModel.feedStates, accountViewModel.viewModelScope) + NestsQueryState(accountViewModel.account, accountViewModel.feedStates, accountViewModel.viewModelScope) } KeyDataSourceSubscription(state, dataSource) diff --git a/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/audiorooms/datasource/AudioRoomsSubAssembler.kt b/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/nests/datasource/NestsSubAssembler.kt similarity index 77% rename from amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/audiorooms/datasource/AudioRoomsSubAssembler.kt rename to amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/nests/datasource/NestsSubAssembler.kt index 867e5e1f9..0a84d03eb 100644 --- a/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/audiorooms/datasource/AudioRoomsSubAssembler.kt +++ b/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/nests/datasource/NestsSubAssembler.kt @@ -18,7 +18,7 @@ * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -package com.vitorpamplona.amethyst.ui.screen.loggedIn.audiorooms.datasource +package com.vitorpamplona.amethyst.ui.screen.loggedIn.nests.datasource import com.vitorpamplona.amethyst.model.TopFilter import com.vitorpamplona.amethyst.model.User @@ -41,34 +41,34 @@ import kotlinx.coroutines.launch * sharing the wire filter avoids duplicate REQs on relays when both the Live * Streams and Audio Rooms screens are open for the same user. */ -class AudioRoomsSubAssembler( +class NestsSubAssembler( client: INostrClient, - allKeys: () -> Set, -) : PerUserAndFollowListEoseManager(client, allKeys) { + allKeys: () -> Set, +) : PerUserAndFollowListEoseManager(client, allKeys) { override fun updateFilter( - key: AudioRoomsQueryState, + key: NestsQueryState, since: SincePerRelayMap?, ): List { val feedSettings = key.followsPerRelay() - return makeLiveActivitiesFilter(feedSettings, since, key.feedStates.audioRoomsFeed.lastNoteCreatedAtIfFilled()) + return makeLiveActivitiesFilter(feedSettings, since, key.feedStates.nestsFeed.lastNoteCreatedAtIfFilled()) } - override fun user(key: AudioRoomsQueryState) = key.account.userProfile() + override fun user(key: NestsQueryState) = key.account.userProfile() - override fun list(key: AudioRoomsQueryState) = key.listName() + override fun list(key: NestsQueryState) = key.listName() - fun AudioRoomsQueryState.listNameFlow() = account.settings.defaultLiveStreamsFollowList + fun NestsQueryState.listNameFlow() = account.settings.defaultLiveStreamsFollowList - fun AudioRoomsQueryState.listName() = listNameFlow().value + fun NestsQueryState.listName() = listNameFlow().value - fun AudioRoomsQueryState.followsPerRelayFlow() = account.liveLiveStreamsFollowListsPerRelay + fun NestsQueryState.followsPerRelayFlow() = account.liveLiveStreamsFollowListsPerRelay - fun AudioRoomsQueryState.followsPerRelay() = followsPerRelayFlow().value + fun NestsQueryState.followsPerRelay() = followsPerRelayFlow().value private val userJobMap = mutableMapOf>() @OptIn(FlowPreview::class) - override fun newSub(key: AudioRoomsQueryState): Subscription { + override fun newSub(key: NestsQueryState): Subscription { val user = user(key) userJobMap[user]?.forEach { it.cancel() } userJobMap[user] = @@ -84,7 +84,7 @@ class AudioRoomsSubAssembler( } }, key.account.scope.launch(Dispatchers.IO) { - key.feedStates.audioRoomsFeed.lastNoteCreatedAtWhenFullyLoaded.sample(5000).collectLatest { + key.feedStates.nestsFeed.lastNoteCreatedAtWhenFullyLoaded.sample(5000).collectLatest { invalidateFilters() } }, diff --git a/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/audiorooms/datasource/RoomAdminCommandsFilterAssembler.kt b/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/nests/datasource/RoomAdminCommandsFilterAssembler.kt similarity index 96% rename from amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/audiorooms/datasource/RoomAdminCommandsFilterAssembler.kt rename to amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/nests/datasource/RoomAdminCommandsFilterAssembler.kt index 2d5e4f4b4..23976e70a 100644 --- a/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/audiorooms/datasource/RoomAdminCommandsFilterAssembler.kt +++ b/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/nests/datasource/RoomAdminCommandsFilterAssembler.kt @@ -18,7 +18,7 @@ * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -package com.vitorpamplona.amethyst.ui.screen.loggedIn.audiorooms.datasource +package com.vitorpamplona.amethyst.ui.screen.loggedIn.nests.datasource import androidx.compose.runtime.Composable import androidx.compose.runtime.Stable @@ -29,7 +29,7 @@ import com.vitorpamplona.amethyst.model.Account import com.vitorpamplona.amethyst.service.relayClient.eoseManagers.PerUniqueIdEoseManager import com.vitorpamplona.amethyst.service.relays.SincePerRelayMap import com.vitorpamplona.amethyst.ui.screen.loggedIn.AccountViewModel -import com.vitorpamplona.quartz.experimental.audiorooms.admin.AdminCommandEvent +import com.vitorpamplona.quartz.experimental.nests.admin.AdminCommandEvent import com.vitorpamplona.quartz.nip01Core.relay.client.INostrClient import com.vitorpamplona.quartz.nip01Core.relay.client.pool.RelayBasedFilter import com.vitorpamplona.quartz.nip01Core.relay.filters.Filter diff --git a/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/audiorooms/datasource/RoomChatFilterAssembler.kt b/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/nests/datasource/RoomChatFilterAssembler.kt similarity index 96% rename from amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/audiorooms/datasource/RoomChatFilterAssembler.kt rename to amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/nests/datasource/RoomChatFilterAssembler.kt index 17076d15b..54ab65073 100644 --- a/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/audiorooms/datasource/RoomChatFilterAssembler.kt +++ b/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/nests/datasource/RoomChatFilterAssembler.kt @@ -18,7 +18,7 @@ * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -package com.vitorpamplona.amethyst.ui.screen.loggedIn.audiorooms.datasource +package com.vitorpamplona.amethyst.ui.screen.loggedIn.nests.datasource import androidx.compose.runtime.Composable import androidx.compose.runtime.Stable @@ -49,7 +49,7 @@ class RoomChatQueryState( * REQs `kinds=[1311], #a=[roomATag]` against the user's outbox * relays so the chat panel sees every message tagged for this * room. Events arrive in [com.vitorpamplona.amethyst.model.LocalCache]; - * the room screen pipes them into `AudioRoomViewModel.onChatEvent`. + * the room screen pipes them into `NestViewModel.onChatEvent`. */ class RoomChatFilterSubAssembler( client: INostrClient, diff --git a/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/audiorooms/datasource/RoomPresenceFilterAssembler.kt b/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/nests/datasource/RoomPresenceFilterAssembler.kt similarity index 97% rename from amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/audiorooms/datasource/RoomPresenceFilterAssembler.kt rename to amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/nests/datasource/RoomPresenceFilterAssembler.kt index 48fc4f8f1..dcdc8b5ad 100644 --- a/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/audiorooms/datasource/RoomPresenceFilterAssembler.kt +++ b/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/nests/datasource/RoomPresenceFilterAssembler.kt @@ -18,7 +18,7 @@ * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -package com.vitorpamplona.amethyst.ui.screen.loggedIn.audiorooms.datasource +package com.vitorpamplona.amethyst.ui.screen.loggedIn.nests.datasource import androidx.compose.runtime.Stable import com.vitorpamplona.amethyst.commons.relayClient.composeSubscriptionManagers.ComposeSubscriptionManager @@ -47,7 +47,7 @@ class RoomPresenceQueryState( * already talks to. The events arrive in [com.vitorpamplona.amethyst.model.LocalCache] * via the normal client pipeline; the room screen observes them * with `LocalCache.observeEvents(...)` and feeds each event into - * `AudioRoomViewModel.onPresenceEvent`. + * `NestViewModel.onPresenceEvent`. * * One assembler instance services every audio-room screen — the * `key` (= room a-tag) keeps overlapping screens (in unlikely diff --git a/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/audiorooms/datasource/RoomPresenceFilterAssemblerSubscription.kt b/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/nests/datasource/RoomPresenceFilterAssemblerSubscription.kt similarity index 96% rename from amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/audiorooms/datasource/RoomPresenceFilterAssemblerSubscription.kt rename to amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/nests/datasource/RoomPresenceFilterAssemblerSubscription.kt index a97fe0b32..64c9a75cc 100644 --- a/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/audiorooms/datasource/RoomPresenceFilterAssemblerSubscription.kt +++ b/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/nests/datasource/RoomPresenceFilterAssemblerSubscription.kt @@ -18,7 +18,7 @@ * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -package com.vitorpamplona.amethyst.ui.screen.loggedIn.audiorooms.datasource +package com.vitorpamplona.amethyst.ui.screen.loggedIn.nests.datasource import androidx.compose.runtime.Composable import androidx.compose.runtime.remember diff --git a/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/audiorooms/datasource/RoomReactionsFilterAssembler.kt b/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/nests/datasource/RoomReactionsFilterAssembler.kt similarity index 98% rename from amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/audiorooms/datasource/RoomReactionsFilterAssembler.kt rename to amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/nests/datasource/RoomReactionsFilterAssembler.kt index 2ab0b1738..ff19c5e99 100644 --- a/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/audiorooms/datasource/RoomReactionsFilterAssembler.kt +++ b/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/nests/datasource/RoomReactionsFilterAssembler.kt @@ -18,7 +18,7 @@ * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -package com.vitorpamplona.amethyst.ui.screen.loggedIn.audiorooms.datasource +package com.vitorpamplona.amethyst.ui.screen.loggedIn.nests.datasource import androidx.compose.runtime.Composable import androidx.compose.runtime.Stable diff --git a/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/audiorooms/room/EditAudioRoomSheet.kt b/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/nests/room/EditNestSheet.kt similarity index 85% rename from amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/audiorooms/room/EditAudioRoomSheet.kt rename to amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/nests/room/EditNestSheet.kt index 14dd4d8f8..507ef68f8 100644 --- a/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/audiorooms/room/EditAudioRoomSheet.kt +++ b/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/nests/room/EditNestSheet.kt @@ -18,7 +18,7 @@ * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -package com.vitorpamplona.amethyst.ui.screen.loggedIn.audiorooms.room +package com.vitorpamplona.amethyst.ui.screen.loggedIn.nests.room import androidx.compose.foundation.layout.Arrangement import androidx.compose.foundation.layout.Column @@ -63,18 +63,18 @@ import kotlinx.coroutines.launch * original), or closes the room with a destructive button. * * Visibility gating (host-only) is the caller's job; - * [EditAudioRoomViewModel] preserves every promoted participant + * [EditNestViewModel] preserves every promoted participant * verbatim, so a save MUST NOT silently demote anyone. */ @OptIn(ExperimentalMaterial3Api::class) @Composable -fun EditAudioRoomSheet( +fun EditNestSheet( accountViewModel: AccountViewModel, event: MeetingSpaceEvent, onDismiss: () -> Unit, ) { - val key = remember(event) { "EditAudioRoom-${event.dTag()}" } - val viewModel: EditAudioRoomViewModel = viewModel(key = key) + val key = remember(event) { "EditNest-${event.dTag()}" } + val viewModel: EditNestViewModel = viewModel(key = key) LaunchedEffect(viewModel, event) { viewModel.bind(accountViewModel, event) } val state by viewModel.state.collectAsState() @@ -85,8 +85,8 @@ fun EditAudioRoomSheet( if (confirmCloseOpen) { androidx.compose.material3.AlertDialog( onDismissRequest = { confirmCloseOpen = false }, - title = { Text(stringRes(R.string.audio_room_close_room_confirm_title)) }, - text = { Text(stringRes(R.string.audio_room_close_room_confirm_body)) }, + title = { Text(stringRes(R.string.nest_close_room_confirm_title)) }, + text = { Text(stringRes(R.string.nest_close_room_confirm_body)) }, confirmButton = { TextButton( colors = ButtonDefaults.textButtonColors(contentColor = MaterialTheme.colorScheme.error), @@ -97,12 +97,12 @@ fun EditAudioRoomSheet( } }, ) { - Text(stringRes(R.string.audio_room_close_room_confirm_action)) + Text(stringRes(R.string.nest_close_room_confirm_action)) } }, dismissButton = { TextButton(onClick = { confirmCloseOpen = false }) { - Text(stringRes(R.string.audio_room_create_cancel)) + Text(stringRes(R.string.nest_create_cancel)) } }, ) @@ -113,41 +113,41 @@ fun EditAudioRoomSheet( verticalArrangement = Arrangement.spacedBy(8.dp), ) { Text( - text = stringRes(R.string.audio_room_edit_title), + text = stringRes(R.string.nest_edit_title), style = MaterialTheme.typography.titleLarge, ) OutlinedTextField( value = state.roomName, onValueChange = viewModel::setRoomName, - label = { Text(stringRes(R.string.audio_room_create_field_room)) }, + label = { Text(stringRes(R.string.nest_create_field_room)) }, singleLine = true, modifier = Modifier.fillMaxWidth(), ) OutlinedTextField( value = state.summary, onValueChange = viewModel::setSummary, - label = { Text(stringRes(R.string.audio_room_create_field_summary)) }, + label = { Text(stringRes(R.string.nest_create_field_summary)) }, modifier = Modifier.fillMaxWidth(), ) OutlinedTextField( value = state.serviceUrl, onValueChange = viewModel::setServiceUrl, - label = { Text(stringRes(R.string.audio_room_create_field_service)) }, + label = { Text(stringRes(R.string.nest_create_field_service)) }, singleLine = true, modifier = Modifier.fillMaxWidth(), ) OutlinedTextField( value = state.endpointUrl, onValueChange = viewModel::setEndpointUrl, - label = { Text(stringRes(R.string.audio_room_create_field_endpoint)) }, + label = { Text(stringRes(R.string.nest_create_field_endpoint)) }, singleLine = true, modifier = Modifier.fillMaxWidth(), ) OutlinedTextField( value = state.imageUrl, onValueChange = viewModel::setImageUrl, - label = { Text(stringRes(R.string.audio_room_create_field_image)) }, + label = { Text(stringRes(R.string.nest_create_field_image)) }, singleLine = true, modifier = Modifier.fillMaxWidth(), ) @@ -171,11 +171,11 @@ fun EditAudioRoomSheet( colors = ButtonDefaults.textButtonColors(contentColor = MaterialTheme.colorScheme.error), onClick = { confirmCloseOpen = true }, ) { - Text(stringRes(R.string.audio_room_close_action)) + Text(stringRes(R.string.nest_close_action)) } Row { TextButton(onClick = onDismiss, enabled = !state.isPublishing) { - Text(stringRes(R.string.audio_room_create_cancel)) + Text(stringRes(R.string.nest_create_cancel)) } Spacer(Modifier.width(8.dp)) Button( @@ -189,7 +189,7 @@ fun EditAudioRoomSheet( if (state.isPublishing) { CircularProgressIndicator(modifier = Modifier.size(18.dp), strokeWidth = 2.dp) } else { - Text(stringRes(R.string.audio_room_edit_save)) + Text(stringRes(R.string.nest_edit_save)) } } } diff --git a/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/audiorooms/room/EditAudioRoomViewModel.kt b/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/nests/room/EditNestViewModel.kt similarity index 97% rename from amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/audiorooms/room/EditAudioRoomViewModel.kt rename to amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/nests/room/EditNestViewModel.kt index e2487025e..6e2c982db 100644 --- a/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/audiorooms/room/EditAudioRoomViewModel.kt +++ b/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/nests/room/EditNestViewModel.kt @@ -18,7 +18,7 @@ * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -package com.vitorpamplona.amethyst.ui.screen.loggedIn.audiorooms.room +package com.vitorpamplona.amethyst.ui.screen.loggedIn.nests.room import androidx.lifecycle.ViewModel import com.vitorpamplona.amethyst.ui.screen.loggedIn.AccountViewModel @@ -36,7 +36,7 @@ import kotlinx.coroutines.flow.asStateFlow import kotlinx.coroutines.flow.update /** - * Backing ViewModel for [EditAudioRoomSheet]. Loads the existing + * Backing ViewModel for [EditNestSheet]. Loads the existing * [MeetingSpaceEvent], lets the host edit room name / summary / * image / endpoint, then republishes kind-30312 with the SAME `d` * tag so the relay treats it as a replacement of the original. @@ -49,7 +49,7 @@ import kotlinx.coroutines.flow.update * speakers or admins who were promoted in a previous version of * the event (audit risk note in the Tier-1 plan). */ -class EditAudioRoomViewModel : ViewModel() { +class EditNestViewModel : ViewModel() { @Volatile private var account: AccountViewModel? = null @Volatile private var original: MeetingSpaceEvent? = null diff --git a/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/audiorooms/room/HandRaiseQueueSection.kt b/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/nests/room/HandRaiseQueueSection.kt similarity index 93% rename from amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/audiorooms/room/HandRaiseQueueSection.kt rename to amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/nests/room/HandRaiseQueueSection.kt index edcf06019..dc74bab13 100644 --- a/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/audiorooms/room/HandRaiseQueueSection.kt +++ b/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/nests/room/HandRaiseQueueSection.kt @@ -18,7 +18,7 @@ * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -package com.vitorpamplona.amethyst.ui.screen.loggedIn.audiorooms.room +package com.vitorpamplona.amethyst.ui.screen.loggedIn.nests.room import androidx.compose.foundation.layout.Arrangement import androidx.compose.foundation.layout.Column @@ -38,7 +38,7 @@ import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.unit.dp import com.vitorpamplona.amethyst.R -import com.vitorpamplona.amethyst.commons.viewmodels.AudioRoomViewModel +import com.vitorpamplona.amethyst.commons.viewmodels.NestViewModel import com.vitorpamplona.amethyst.ui.note.ClickableUserPicture import com.vitorpamplona.amethyst.ui.screen.loggedIn.AccountViewModel import com.vitorpamplona.amethyst.ui.stringRes @@ -62,7 +62,7 @@ import kotlinx.coroutines.launch @Composable internal fun HandRaiseQueueSection( event: MeetingSpaceEvent, - viewModel: AudioRoomViewModel, + viewModel: NestViewModel, accountViewModel: AccountViewModel, modifier: Modifier = Modifier, ) { @@ -83,7 +83,7 @@ internal fun HandRaiseQueueSection( val scope = rememberCoroutineScope() Column(modifier = modifier.fillMaxWidth().padding(top = 12.dp)) { Text( - text = stringRes(R.string.audio_room_hand_raise_queue_title), + text = stringRes(R.string.nest_hand_raise_queue_title), style = MaterialTheme.typography.labelMedium, color = MaterialTheme.colorScheme.onSurfaceVariant, ) @@ -112,7 +112,7 @@ internal fun HandRaiseQueueSection( } }, ) { - Text(stringRes(R.string.audio_room_hand_raise_approve)) + Text(stringRes(R.string.nest_hand_raise_approve)) } } } diff --git a/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/audiorooms/room/AudioRoomActivity.kt b/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/nests/room/NestActivity.kt similarity index 90% rename from amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/audiorooms/room/AudioRoomActivity.kt rename to amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/nests/room/NestActivity.kt index b46a3a105..08e42af7e 100644 --- a/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/audiorooms/room/AudioRoomActivity.kt +++ b/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/nests/room/NestActivity.kt @@ -18,7 +18,7 @@ * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -package com.vitorpamplona.amethyst.ui.screen.loggedIn.audiorooms.room +package com.vitorpamplona.amethyst.ui.screen.loggedIn.nests.room import android.app.PendingIntent import android.app.PictureInPictureParams @@ -43,7 +43,7 @@ import kotlinx.coroutines.flow.asSharedFlow /** * Standalone activity that owns the lifetime of an audio-room session. The - * lobby ([AudioRoomJoinCard]) launches this activity when the user taps + * lobby ([NestJoinCard]) launches this activity when the user taps * "Join audio room"; finishing it tears down the MoQ session, the * broadcaster (if any), and the foreground notification. * @@ -52,11 +52,11 @@ import kotlinx.coroutines.flow.asSharedFlow * keep the speakers visible while doing other things. Mute / leave are * exposed via the system PIP overlay as [RemoteAction]s. * - * AccountViewModel arrives via [AudioRoomBridge] — same pattern as + * AccountViewModel arrives via [NestBridge] — same pattern as * [com.vitorpamplona.amethyst.ui.call.CallActivity] uses for * `CallSessionBridge`. */ -class AudioRoomActivity : AppCompatActivity() { +class NestActivity : AppCompatActivity() { private val isInPipMode = mutableStateOf(false) private val isMuted = mutableStateOf(false) private val isConnected = mutableStateOf(false) @@ -96,7 +96,7 @@ class AudioRoomActivity : AppCompatActivity() { override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) - val accountViewModel = AudioRoomBridge.accountViewModel + val accountViewModel = NestBridge.accountViewModel val addressValue = intent.getStringExtra(EXTRA_ADDRESS) val authBaseUrl = intent.getStringExtra(EXTRA_AUTH_BASE_URL) val endpoint = intent.getStringExtra(EXTRA_ENDPOINT) @@ -145,7 +145,7 @@ class AudioRoomActivity : AppCompatActivity() { setContent { AmethystTheme { - AudioRoomActivityContent( + NestActivityContent( addressValue = addressValue, room = com.vitorpamplona.nestsclient.NestsRoomConfig( @@ -211,7 +211,7 @@ class AudioRoomActivity : AppCompatActivity() { PictureInPictureParams .Builder() // Landscape ratio — the PIP layout is a horizontal row of - // avatars under a title (see AudioRoomPipScreen), which 9:16 + // avatars under a title (see NestPipScreen), which 9:16 // squeezed into a sliver. 16:9 fits the row and the room name. .setAspectRatio(Rational(16, 9)) .setActions(buildPipActions()) @@ -233,13 +233,13 @@ class AudioRoomActivity : AppCompatActivity() { PendingIntent.FLAG_IMMUTABLE or PendingIntent.FLAG_UPDATE_CURRENT, ) val muteIconRes = if (isMuted.value) R.drawable.ic_mic_off else R.drawable.ic_mic_on - val muteLabel = getString(if (isMuted.value) R.string.audio_room_unmute else R.string.audio_room_mute) + val muteLabel = getString(if (isMuted.value) R.string.nest_unmute else R.string.nest_mute) return listOf( RemoteAction(Icon.createWithResource(this, muteIconRes), muteLabel, muteLabel, muteIntent), RemoteAction( Icon.createWithResource(this, R.drawable.ic_call_end), - getString(R.string.audio_room_leave), - getString(R.string.audio_room_leave), + getString(R.string.nest_leave), + getString(R.string.nest_leave), leaveIntent, ), ) @@ -251,14 +251,14 @@ class AudioRoomActivity : AppCompatActivity() { } companion object { - const val EXTRA_ADDRESS = "com.vitorpamplona.amethyst.AUDIO_ROOM_ADDRESS" - const val EXTRA_AUTH_BASE_URL = "com.vitorpamplona.amethyst.AUDIO_ROOM_AUTH_BASE_URL" - const val EXTRA_ENDPOINT = "com.vitorpamplona.amethyst.AUDIO_ROOM_ENDPOINT" - const val EXTRA_HOST_PUBKEY = "com.vitorpamplona.amethyst.AUDIO_ROOM_HOST_PUBKEY" - const val EXTRA_ROOM_ID = "com.vitorpamplona.amethyst.AUDIO_ROOM_ROOM_ID" - const val EXTRA_KIND = "com.vitorpamplona.amethyst.AUDIO_ROOM_KIND" - private const val ACTION_PIP_TOGGLE_MUTE = "com.vitorpamplona.amethyst.AUDIO_ROOM_PIP_MUTE" - private const val ACTION_PIP_LEAVE = "com.vitorpamplona.amethyst.AUDIO_ROOM_PIP_LEAVE" + const val EXTRA_ADDRESS = "com.vitorpamplona.amethyst.NEST_ADDRESS" + const val EXTRA_AUTH_BASE_URL = "com.vitorpamplona.amethyst.NEST_AUTH_BASE_URL" + const val EXTRA_ENDPOINT = "com.vitorpamplona.amethyst.NEST_ENDPOINT" + const val EXTRA_HOST_PUBKEY = "com.vitorpamplona.amethyst.NEST_HOST_PUBKEY" + const val EXTRA_ROOM_ID = "com.vitorpamplona.amethyst.NEST_ROOM_ID" + const val EXTRA_KIND = "com.vitorpamplona.amethyst.NEST_KIND" + private const val ACTION_PIP_TOGGLE_MUTE = "com.vitorpamplona.amethyst.NEST_PIP_MUTE" + private const val ACTION_PIP_LEAVE = "com.vitorpamplona.amethyst.NEST_PIP_LEAVE" private const val PIP_MUTE_REQ = 0x6A001 private const val PIP_LEAVE_REQ = 0x6A002 @@ -272,7 +272,7 @@ class AudioRoomActivity : AppCompatActivity() { kind: Int, ) { context.startActivity( - Intent(context, AudioRoomActivity::class.java).apply { + Intent(context, NestActivity::class.java).apply { addFlags(Intent.FLAG_ACTIVITY_NEW_TASK) putExtra(EXTRA_ADDRESS, addressValue) putExtra(EXTRA_AUTH_BASE_URL, authBaseUrl) diff --git a/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/audiorooms/room/AudioRoomActivityContent.kt b/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/nests/room/NestActivityContent.kt similarity index 92% rename from amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/audiorooms/room/AudioRoomActivityContent.kt rename to amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/nests/room/NestActivityContent.kt index d54ea0328..a2174b444 100644 --- a/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/audiorooms/room/AudioRoomActivityContent.kt +++ b/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/nests/room/NestActivityContent.kt @@ -18,7 +18,7 @@ * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -package com.vitorpamplona.amethyst.ui.screen.loggedIn.audiorooms.room +package com.vitorpamplona.amethyst.ui.screen.loggedIn.nests.room import androidx.compose.runtime.Composable import androidx.compose.runtime.DisposableEffect @@ -32,18 +32,18 @@ import androidx.compose.runtime.saveable.rememberSaveable import androidx.compose.runtime.setValue import androidx.compose.ui.platform.LocalContext import androidx.lifecycle.viewmodel.compose.viewModel -import com.vitorpamplona.amethyst.commons.viewmodels.AudioRoomViewModel import com.vitorpamplona.amethyst.commons.viewmodels.BroadcastUiState import com.vitorpamplona.amethyst.commons.viewmodels.ConnectionUiState +import com.vitorpamplona.amethyst.commons.viewmodels.NestViewModel import com.vitorpamplona.amethyst.model.LocalCache -import com.vitorpamplona.amethyst.service.audiorooms.AudioRoomForegroundService +import com.vitorpamplona.amethyst.service.nests.NestForegroundService import com.vitorpamplona.amethyst.ui.note.LoadAddressableNote import com.vitorpamplona.amethyst.ui.screen.loggedIn.AccountViewModel -import com.vitorpamplona.amethyst.ui.screen.loggedIn.audiorooms.datasource.RoomAdminCommandsFilterAssemblerSubscription -import com.vitorpamplona.amethyst.ui.screen.loggedIn.audiorooms.datasource.RoomChatFilterAssemblerSubscription -import com.vitorpamplona.amethyst.ui.screen.loggedIn.audiorooms.datasource.RoomPresenceFilterAssemblerSubscription -import com.vitorpamplona.amethyst.ui.screen.loggedIn.audiorooms.datasource.RoomReactionsFilterAssemblerSubscription -import com.vitorpamplona.quartz.experimental.audiorooms.admin.AdminCommandEvent +import com.vitorpamplona.amethyst.ui.screen.loggedIn.nests.datasource.RoomAdminCommandsFilterAssemblerSubscription +import com.vitorpamplona.amethyst.ui.screen.loggedIn.nests.datasource.RoomChatFilterAssemblerSubscription +import com.vitorpamplona.amethyst.ui.screen.loggedIn.nests.datasource.RoomPresenceFilterAssemblerSubscription +import com.vitorpamplona.amethyst.ui.screen.loggedIn.nests.datasource.RoomReactionsFilterAssemblerSubscription +import com.vitorpamplona.quartz.experimental.nests.admin.AdminCommandEvent import com.vitorpamplona.quartz.nip01Core.core.Address import com.vitorpamplona.quartz.nip01Core.relay.filters.Filter import com.vitorpamplona.quartz.nip25Reactions.ReactionEvent @@ -58,16 +58,16 @@ import kotlinx.coroutines.isActive import kotlinx.coroutines.launch /** - * Top-level composable for [AudioRoomActivity]. Observes the room event + + * Top-level composable for [NestActivity]. Observes the room event + * VM, auto-connects on entry, runs the kind-10312 presence loop, drives * the foreground service, and flips between full-screen and PIP layouts. * - * The [AudioRoomActivity] supplies [isInPipMode] (a Compose state observed + * The [NestActivity] supplies [isInPipMode] (a Compose state observed * via the activity's `mutableStateOf`) and [onLeave] which finishes the * activity. Everything else is local to this composable's scope. */ @Composable -internal fun AudioRoomActivityContent( +internal fun NestActivityContent( addressValue: String, room: com.vitorpamplona.nestsclient.NestsRoomConfig, accountViewModel: AccountViewModel, @@ -88,7 +88,7 @@ internal fun AudioRoomActivityContent( LoadAddressableNote(parsedAddress, accountViewModel) { addressableNote -> addressableNote ?: return@LoadAddressableNote val event = addressableNote.event as? MeetingSpaceEvent ?: return@LoadAddressableNote - AudioRoomActivityBody( + NestActivityBody( event = event, roomNote = addressableNote, room = room, @@ -103,7 +103,7 @@ internal fun AudioRoomActivityContent( } @Composable -private fun AudioRoomActivityBody( +private fun NestActivityBody( event: MeetingSpaceEvent, roomNote: com.vitorpamplona.amethyst.model.AddressableNote, room: com.vitorpamplona.nestsclient.NestsRoomConfig, @@ -127,12 +127,12 @@ private fun AudioRoomActivityBody( val account = accountViewModel.account val signer = account.signer - val viewModel: AudioRoomViewModel = + val viewModel: NestViewModel = viewModel( key = "${room.authBaseUrl}|${room.roomId}", factory = remember(room, signer) { - AudioRoomViewModelFactory( + NestViewModelFactory( signer = signer, room = room, ) @@ -343,22 +343,22 @@ private fun AudioRoomActivityBody( val isBroadcasting = ui.broadcast is BroadcastUiState.Broadcasting LaunchedEffect(isLive, isBroadcasting) { when { - isLive && isBroadcasting -> AudioRoomForegroundService.promoteToMicrophone(context) - isLive -> AudioRoomForegroundService.startListening(context) - else -> AudioRoomForegroundService.stop(context) + isLive && isBroadcasting -> NestForegroundService.promoteToMicrophone(context) + isLive -> NestForegroundService.startListening(context) + else -> NestForegroundService.stop(context) } } - DisposableEffect(Unit) { onDispose { AudioRoomForegroundService.stop(context) } } + DisposableEffect(Unit) { onDispose { NestForegroundService.stop(context) } } if (isInPipMode) { - AudioRoomPipScreen( + NestPipScreen( title = event.room(), onStage = onStage, ui = ui, accountViewModel = accountViewModel, ) } else { - AudioRoomFullScreen( + NestFullScreen( event = event, roomNote = roomNote, onStage = onStage, diff --git a/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/audiorooms/room/AudioRoomBridge.kt b/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/nests/room/NestBridge.kt similarity index 88% rename from amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/audiorooms/room/AudioRoomBridge.kt rename to amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/nests/room/NestBridge.kt index e3c8ccc1a..e36ac9bff 100644 --- a/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/audiorooms/room/AudioRoomBridge.kt +++ b/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/nests/room/NestBridge.kt @@ -18,21 +18,21 @@ * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -package com.vitorpamplona.amethyst.ui.screen.loggedIn.audiorooms.room +package com.vitorpamplona.amethyst.ui.screen.loggedIn.nests.room import com.vitorpamplona.amethyst.ui.screen.loggedIn.AccountViewModel /** * Process-level singleton that hands the active [AccountViewModel] from the - * main activity to [AudioRoomActivity]. Mirrors the + * main activity to [NestActivity]. Mirrors the * [com.vitorpamplona.amethyst.service.call.CallSessionBridge] pattern so a * separately-tasked Activity in the same process can reach the logged-in * account without serialising a `NostrSigner` through an Intent extra. * - * Set immediately before `startActivity(Intent(..., AudioRoomActivity::class))` + * Set immediately before `startActivity(Intent(..., NestActivity::class))` * is called and cleared on logout / account switch. */ -object AudioRoomBridge { +object NestBridge { @Volatile var accountViewModel: AccountViewModel? = null private set diff --git a/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/audiorooms/room/AudioRoomChatPanel.kt b/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/nests/room/NestChatPanel.kt similarity index 93% rename from amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/audiorooms/room/AudioRoomChatPanel.kt rename to amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/nests/room/NestChatPanel.kt index 7d9692ef5..465d9fcbe 100644 --- a/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/audiorooms/room/AudioRoomChatPanel.kt +++ b/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/nests/room/NestChatPanel.kt @@ -18,7 +18,7 @@ * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -package com.vitorpamplona.amethyst.ui.screen.loggedIn.audiorooms.room +package com.vitorpamplona.amethyst.ui.screen.loggedIn.nests.room import androidx.compose.foundation.layout.Arrangement import androidx.compose.foundation.layout.Column @@ -49,7 +49,7 @@ import androidx.compose.ui.Modifier import androidx.compose.ui.text.font.FontWeight import androidx.compose.ui.unit.dp import com.vitorpamplona.amethyst.R -import com.vitorpamplona.amethyst.commons.viewmodels.AudioRoomViewModel +import com.vitorpamplona.amethyst.commons.viewmodels.NestViewModel import com.vitorpamplona.amethyst.ui.note.ClickableUserPicture import com.vitorpamplona.amethyst.ui.note.UsernameDisplay import com.vitorpamplona.amethyst.ui.screen.loggedIn.AccountViewModel @@ -63,15 +63,15 @@ import kotlinx.coroutines.launch /** * Live-chat panel (T1 #2) — renders the kind-1311 transcript for * the room and provides a send field. Messages flow from - * [AudioRoomViewModel.chat] (populated by the LocalCache observer - * in [AudioRoomActivityContent]); send routes through + * [NestViewModel.chat] (populated by the LocalCache observer + * in [NestActivityContent]); send routes through * `account.signAndComputeBroadcast` directly so the VM stays free * of platform / signing dependencies. */ @Composable -internal fun AudioRoomChatPanel( +internal fun NestChatPanel( roomATag: ATag, - viewModel: AudioRoomViewModel, + viewModel: NestViewModel, accountViewModel: AccountViewModel, modifier: Modifier = Modifier, ) { @@ -100,7 +100,7 @@ internal fun AudioRoomChatPanel( Column(modifier = modifier.fillMaxWidth()) { if (messages.isEmpty()) { Text( - text = stringRes(R.string.audio_room_chat_empty), + text = stringRes(R.string.nest_chat_empty), style = MaterialTheme.typography.bodySmall, color = MaterialTheme.colorScheme.onSurfaceVariant, modifier = Modifier.padding(vertical = 12.dp), @@ -178,7 +178,7 @@ private fun ChatComposer( value = draft, onValueChange = { draft = it }, modifier = Modifier.weight(1f), - placeholder = { Text(stringRes(R.string.audio_room_chat_placeholder)) }, + placeholder = { Text(stringRes(R.string.nest_chat_placeholder)) }, singleLine = false, maxLines = 4, enabled = !isSending, @@ -212,7 +212,7 @@ private fun ChatComposer( ?: result.exceptionOrNull()?.let { it::class.simpleName } ?: "unknown error" accountViewModel.toastManager.toast( - R.string.audio_room_chat_send_failed_title, + R.string.nest_chat_send_failed_title, why, user = null, ) @@ -220,7 +220,7 @@ private fun ChatComposer( } }, ) { - Text(stringRes(R.string.audio_room_chat_send)) + Text(stringRes(R.string.nest_chat_send)) } } } diff --git a/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/audiorooms/room/AudioRoomCommon.kt b/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/nests/room/NestCommon.kt similarity index 96% rename from amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/audiorooms/room/AudioRoomCommon.kt rename to amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/nests/room/NestCommon.kt index d635f840a..d7e62a4a9 100644 --- a/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/audiorooms/room/AudioRoomCommon.kt +++ b/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/nests/room/NestCommon.kt @@ -18,7 +18,7 @@ * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -package com.vitorpamplona.amethyst.ui.screen.loggedIn.audiorooms.room +package com.vitorpamplona.amethyst.ui.screen.loggedIn.nests.room import androidx.compose.foundation.border import androidx.compose.foundation.layout.Arrangement @@ -99,7 +99,7 @@ internal fun StagePeopleRow( @Composable internal fun connectingLabel(connection: ConnectionUiState.Connecting): String = when (connection.step) { - ConnectionUiState.Step.ResolvingRoom -> stringRes(R.string.audio_room_connecting_resolving) - ConnectionUiState.Step.OpeningTransport -> stringRes(R.string.audio_room_connecting_transport) - ConnectionUiState.Step.MoqHandshake -> stringRes(R.string.audio_room_connecting_handshake) + ConnectionUiState.Step.ResolvingRoom -> stringRes(R.string.nest_connecting_resolving) + ConnectionUiState.Step.OpeningTransport -> stringRes(R.string.nest_connecting_transport) + ConnectionUiState.Step.MoqHandshake -> stringRes(R.string.nest_connecting_handshake) } diff --git a/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/audiorooms/room/AudioRoomFullScreen.kt b/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/nests/room/NestFullScreen.kt similarity index 87% rename from amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/audiorooms/room/AudioRoomFullScreen.kt rename to amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/nests/room/NestFullScreen.kt index de7f0d7af..6124e6d2c 100644 --- a/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/audiorooms/room/AudioRoomFullScreen.kt +++ b/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/nests/room/NestFullScreen.kt @@ -18,7 +18,7 @@ * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -package com.vitorpamplona.amethyst.ui.screen.loggedIn.audiorooms.room +package com.vitorpamplona.amethyst.ui.screen.loggedIn.nests.room import android.Manifest import android.content.pm.PackageManager @@ -58,10 +58,10 @@ import androidx.core.content.ContextCompat 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.commons.viewmodels.AudioRoomUiState -import com.vitorpamplona.amethyst.commons.viewmodels.AudioRoomViewModel import com.vitorpamplona.amethyst.commons.viewmodels.BroadcastUiState import com.vitorpamplona.amethyst.commons.viewmodels.ConnectionUiState +import com.vitorpamplona.amethyst.commons.viewmodels.NestUiState +import com.vitorpamplona.amethyst.commons.viewmodels.NestViewModel import com.vitorpamplona.amethyst.commons.viewmodels.RoomTheme import com.vitorpamplona.amethyst.ui.screen.loggedIn.AccountViewModel import com.vitorpamplona.amethyst.ui.stringRes @@ -73,28 +73,28 @@ import com.vitorpamplona.quartz.nip53LiveActivities.streaming.tags.ParticipantTa import kotlinx.coroutines.launch /** - * Full-screen layout for [AudioRoomActivity]. Renders title + summary, + * Full-screen layout for [NestActivity]. Renders title + summary, * host/speaker/audience rows (with active-speaker rings), connection chip * + mute, talk row (when allowed), hand-raise, and a Leave button that * finishes the activity. * - * The PIP variant lives in [AudioRoomPipScreen]; the activity flips + * The PIP variant lives in [NestPipScreen]; the activity flips * between them based on `isInPipMode`. */ @Composable -internal fun AudioRoomFullScreen( +internal fun NestFullScreen( event: MeetingSpaceEvent, roomNote: com.vitorpamplona.amethyst.model.AddressableNote, onStage: List, - viewModel: AudioRoomViewModel, - ui: AudioRoomUiState, + viewModel: NestViewModel, + ui: NestUiState, accountViewModel: AccountViewModel, handRaised: Boolean, onHandRaisedChange: (Boolean) -> Unit, onLeave: () -> Unit, ) { val roomTheme = androidx.compose.runtime.remember(event) { RoomTheme.from(event) } - AudioRoomThemedScope(theme = roomTheme, accountViewModel = accountViewModel) { + NestThemedScope(theme = roomTheme, accountViewModel = accountViewModel) { Column( modifier = Modifier @@ -126,7 +126,7 @@ internal fun AudioRoomFullScreen( androidx.compose.material3.IconButton(onClick = { showHostMenu = true }) { Icon( symbol = MaterialSymbols.MoreVert, - contentDescription = stringRes(R.string.audio_room_overflow_menu), + contentDescription = stringRes(R.string.nest_overflow_menu), ) } val context = androidx.compose.ui.platform.LocalContext.current @@ -135,7 +135,7 @@ internal fun AudioRoomFullScreen( onDismissRequest = { showHostMenu = false }, ) { androidx.compose.material3.DropdownMenuItem( - text = { Text(stringRes(R.string.audio_room_share_action)) }, + text = { Text(stringRes(R.string.nest_share_action)) }, onClick = { showHostMenu = false shareRoomNaddr(context, event) @@ -143,7 +143,7 @@ internal fun AudioRoomFullScreen( ) if (isHost) { androidx.compose.material3.DropdownMenuItem( - text = { Text(stringRes(R.string.audio_room_edit_title)) }, + text = { Text(stringRes(R.string.nest_edit_title)) }, onClick = { showHostMenu = false showEditSheet = true @@ -154,7 +154,7 @@ internal fun AudioRoomFullScreen( } } if (showEditSheet) { - EditAudioRoomSheet( + EditNestSheet( accountViewModel = accountViewModel, event = event, onDismiss = { showEditSheet = false }, @@ -178,7 +178,7 @@ internal fun AudioRoomFullScreen( Text( text = androidx.compose.ui.res.pluralStringResource( - R.plurals.audio_room_listener_count, + R.plurals.nest_listener_count, listenerCount, listenerCount, ), @@ -211,8 +211,8 @@ internal fun AudioRoomFullScreen( grid = participantGrid, speakingNow = ui.speakingNow, accountViewModel = accountViewModel, - onStageLabel = stringRes(R.string.audio_room_stage), - audienceLabel = stringRes(R.string.audio_room_audience), + onStageLabel = stringRes(R.string.nest_stage), + audienceLabel = stringRes(R.string.nest_audience), reactionsByPubkey = reactionsByPubkey, connectingSpeakers = ui.connectingSpeakers, onLongPressParticipant = onLongPressParticipant, @@ -257,12 +257,12 @@ internal fun AudioRoomFullScreen( symbol = MaterialSymbols.PanTool, contentDescription = stringRes( - if (handRaised) R.string.audio_room_lower_hand else R.string.audio_room_raise_hand, + if (handRaised) R.string.nest_lower_hand else R.string.nest_raise_hand, ), ) } OutlinedButton(onClick = { showReactionPicker = true }) { - Text(stringRes(R.string.audio_room_reactions_button)) + Text(stringRes(R.string.nest_reactions_button)) } OutlinedButton( onClick = { @@ -273,7 +273,7 @@ internal fun AudioRoomFullScreen( } }, ) { - Text(stringRes(R.string.audio_room_leave)) + Text(stringRes(R.string.nest_leave)) } } if (showReactionPicker) { @@ -288,8 +288,8 @@ internal fun AudioRoomFullScreen( if (showHostLeaveConfirm) { AlertDialog( onDismissRequest = { showHostLeaveConfirm = false }, - title = { Text(stringRes(R.string.audio_room_leave_host_title)) }, - text = { Text(stringRes(R.string.audio_room_leave_host_body)) }, + title = { Text(stringRes(R.string.nest_leave_host_title)) }, + text = { Text(stringRes(R.string.nest_leave_host_body)) }, confirmButton = { TextButton( colors = ButtonDefaults.textButtonColors(contentColor = MaterialTheme.colorScheme.error), @@ -299,15 +299,15 @@ internal fun AudioRoomFullScreen( val ok = closeMeetingSpace(accountViewModel, event) if (!ok) { accountViewModel.toastManager.toast( - R.string.audio_rooms, - R.string.audio_room_leave_host_close_failed, + R.string.nests, + R.string.nest_leave_host_close_failed, ) } onLeave() } }, ) { - Text(stringRes(R.string.audio_room_leave_host_close)) + Text(stringRes(R.string.nest_leave_host_close)) } }, dismissButton = { @@ -317,13 +317,13 @@ internal fun AudioRoomFullScreen( onLeave() }, ) { - Text(stringRes(R.string.audio_room_leave_host_just_leave)) + Text(stringRes(R.string.nest_leave_host_just_leave)) } }, ) } - AudioRoomChatPanel( + NestChatPanel( roomATag = ATag( kind = event.kind, @@ -341,8 +341,8 @@ internal fun AudioRoomFullScreen( @Composable private fun ConnectionRow( - viewModel: AudioRoomViewModel, - ui: AudioRoomUiState, + viewModel: NestViewModel, + ui: NestUiState, ) { Row( modifier = Modifier.fillMaxWidth().padding(top = 12.dp), @@ -352,7 +352,7 @@ private fun ConnectionRow( when (val connection = ui.connection) { is ConnectionUiState.Idle, is ConnectionUiState.Closed -> { Button(onClick = { viewModel.connect() }) { - Text(stringRes(R.string.audio_room_connect)) + Text(stringRes(R.string.nest_connect)) } } @@ -373,7 +373,7 @@ private fun ConnectionRow( AssistChip( onClick = {}, enabled = false, - label = { Text(stringRes(R.string.audio_room_reconnecting)) }, + label = { Text(stringRes(R.string.nest_reconnecting)) }, ) } @@ -381,7 +381,7 @@ private fun ConnectionRow( AssistChip( onClick = {}, enabled = false, - label = { Text(stringRes(R.string.audio_room_connected)) }, + label = { Text(stringRes(R.string.nest_connected)) }, colors = AssistChipDefaults.assistChipColors( disabledLabelColor = MaterialTheme.colorScheme.primary, @@ -395,7 +395,7 @@ private fun ConnectionRow( symbol = if (ui.isMuted) MaterialSymbols.AutoMirrored.VolumeOff else MaterialSymbols.AutoMirrored.VolumeUp, contentDescription = stringRes( - if (ui.isMuted) R.string.audio_room_unmute else R.string.audio_room_mute, + if (ui.isMuted) R.string.nest_unmute else R.string.nest_mute, ), ) } @@ -403,13 +403,13 @@ private fun ConnectionRow( is ConnectionUiState.Failed -> { Text( - text = stringRes(R.string.audio_room_audio_failed, connection.reason), + text = stringRes(R.string.nest_audio_failed, connection.reason), style = MaterialTheme.typography.bodySmall, color = MaterialTheme.colorScheme.error, modifier = Modifier.weight(1f, fill = false), ) Button(onClick = { viewModel.connect() }) { - Text(stringRes(R.string.audio_room_connect)) + Text(stringRes(R.string.nest_connect)) } } } @@ -418,8 +418,8 @@ private fun ConnectionRow( @Composable private fun TalkRow( - viewModel: AudioRoomViewModel, - ui: AudioRoomUiState, + viewModel: NestViewModel, + ui: NestUiState, speakerPubkeyHex: String, ) { // Render whenever the user can act on broadcast state. The @@ -472,11 +472,11 @@ private fun TalkRow( permissionLauncher.launch(Manifest.permission.RECORD_AUDIO) } }) { - Text(stringRes(R.string.audio_room_talk)) + Text(stringRes(R.string.nest_talk)) } if (showDenialWarning) { Text( - text = stringRes(R.string.audio_room_record_permission_required), + text = stringRes(R.string.nest_record_permission_required), style = MaterialTheme.typography.bodySmall, color = MaterialTheme.colorScheme.error, ) @@ -497,7 +497,7 @@ private fun TalkRow( ) } }) { - Text(stringRes(R.string.audio_room_open_settings)) + Text(stringRes(R.string.nest_open_settings)) } } } @@ -506,7 +506,7 @@ private fun TalkRow( AssistChip( onClick = {}, enabled = false, - label = { Text(stringRes(R.string.audio_room_broadcast_connecting)) }, + label = { Text(stringRes(R.string.nest_broadcast_connecting)) }, ) } @@ -514,7 +514,7 @@ private fun TalkRow( AssistChip( onClick = {}, enabled = false, - label = { Text(stringRes(R.string.audio_room_broadcasting)) }, + label = { Text(stringRes(R.string.nest_broadcasting)) }, colors = AssistChipDefaults.assistChipColors( disabledLabelColor = MaterialTheme.colorScheme.error, @@ -528,24 +528,24 @@ private fun TalkRow( symbol = if (broadcast.isMuted) MaterialSymbols.AutoMirrored.VolumeOff else MaterialSymbols.AutoMirrored.VolumeUp, contentDescription = stringRes( - if (broadcast.isMuted) R.string.audio_room_mic_unmute else R.string.audio_room_mic_mute, + if (broadcast.isMuted) R.string.nest_mic_unmute else R.string.nest_mic_mute, ), ) } OutlinedButton(onClick = { viewModel.stopBroadcast() }) { - Text(stringRes(R.string.audio_room_stop_talking)) + Text(stringRes(R.string.nest_stop_talking)) } } is BroadcastUiState.Failed -> { Text( - text = stringRes(R.string.audio_room_broadcast_failed, broadcast.reason), + text = stringRes(R.string.nest_broadcast_failed, broadcast.reason), style = MaterialTheme.typography.bodySmall, color = MaterialTheme.colorScheme.error, modifier = Modifier.weight(1f, fill = false), ) Button(onClick = { viewModel.startBroadcast(speakerPubkeyHex) }) { - Text(stringRes(R.string.audio_room_talk)) + Text(stringRes(R.string.nest_talk)) } } } @@ -557,9 +557,9 @@ private fun TalkRow( * other field verbatim (room name, summary, image, service, endpoint, * participants). Returns true on success. * - * Reuses [EditAudioRoomViewModel.buildEditTemplate] so the close-on-leave + * Reuses [EditNestViewModel.buildEditTemplate] so the close-on-leave * path emits the same shape as the explicit Edit → Close room action. - * Decoupled from [EditAudioRoomViewModel] state so the host's unsaved + * Decoupled from [EditNestViewModel] state so the host's unsaved * edits in the Edit sheet (if any) cannot accidentally leak into the * close payload. */ @@ -568,7 +568,7 @@ private suspend fun closeMeetingSpace( event: MeetingSpaceEvent, ): Boolean { val verbatim = - EditAudioRoomViewModel.FormState( + EditNestViewModel.FormState( dTag = event.dTag(), roomName = event.room().orEmpty(), summary = event.summary().orEmpty(), @@ -580,7 +580,7 @@ private suspend fun closeMeetingSpace( ) return try { val template = - EditAudioRoomViewModel.buildEditTemplate(event, verbatim, StatusTag.STATUS.CLOSED) + EditNestViewModel.buildEditTemplate(event, verbatim, StatusTag.STATUS.CLOSED) accountViewModel.account.signAndComputeBroadcast(template) true } catch (_: Throwable) { diff --git a/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/audiorooms/room/AudioRoomJoinCard.kt b/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/nests/room/NestJoinCard.kt similarity index 92% rename from amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/audiorooms/room/AudioRoomJoinCard.kt rename to amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/nests/room/NestJoinCard.kt index f84fc64c7..e2610da9a 100644 --- a/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/audiorooms/room/AudioRoomJoinCard.kt +++ b/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/nests/room/NestJoinCard.kt @@ -18,7 +18,7 @@ * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -package com.vitorpamplona.amethyst.ui.screen.loggedIn.audiorooms.room +package com.vitorpamplona.amethyst.ui.screen.loggedIn.nests.room import androidx.compose.foundation.layout.Arrangement import androidx.compose.foundation.layout.Column @@ -47,7 +47,7 @@ import com.vitorpamplona.quartz.nip53LiveActivities.meetingSpaces.MeetingSpaceEv /** * Lobby card rendered in [com.vitorpamplona.amethyst.ui.screen.loggedIn.chats.publicChannels.nip53LiveActivities.ChannelView] * for NIP-53 kind 30312 meeting-space events. Shows the room title + - * summary + a "Join audio room" button that launches [AudioRoomActivity]. + * summary + a "Join audio room" button that launches [NestActivity]. * * The lobby is intentionally thin: no audio session, no presence event, no * hand-raise. All of that lives behind the Join button so the on-the-wire @@ -57,19 +57,19 @@ import com.vitorpamplona.quartz.nip53LiveActivities.meetingSpaces.MeetingSpaceEv * non-nests servers we can't connect to. */ @Composable -fun AudioRoomJoinCard( +fun NestJoinCard( baseChannel: LiveActivitiesChannel, accountViewModel: AccountViewModel, ) { LoadAddressableNote(baseChannel.address, accountViewModel) { addressableNote -> addressableNote ?: return@LoadAddressableNote val event = addressableNote.event as? MeetingSpaceEvent ?: return@LoadAddressableNote - AudioRoomJoinCardContent(event, accountViewModel) + NestJoinCardContent(event, accountViewModel) } } @Composable -private fun AudioRoomJoinCardContent( +private fun NestJoinCardContent( event: MeetingSpaceEvent, accountViewModel: AccountViewModel, ) { @@ -107,7 +107,7 @@ private fun AudioRoomJoinCardContent( horizontalArrangement = Arrangement.End, verticalAlignment = Alignment.CenterVertically, ) { - JoinAudioRoomButton(event = event, accountViewModel = accountViewModel) + JoinNestButton(event = event, accountViewModel = accountViewModel) } } } @@ -123,7 +123,7 @@ private fun AudioRoomJoinCardContent( * the audio plane. */ @Composable -fun JoinAudioRoomButton( +fun JoinNestButton( event: MeetingSpaceEvent, accountViewModel: AccountViewModel, ) { @@ -138,8 +138,8 @@ fun JoinAudioRoomButton( val kind = event.kind Button(onClick = { - AudioRoomBridge.set(accountViewModel) - AudioRoomActivity.launch( + NestBridge.set(accountViewModel) + NestActivity.launch( context = context, addressValue = addressValue, authBaseUrl = serviceBase, @@ -149,6 +149,6 @@ fun JoinAudioRoomButton( kind = kind, ) }) { - Text(stringRes(R.string.audio_room_join)) + Text(stringRes(R.string.nest_join)) } } diff --git a/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/audiorooms/room/AudioRoomPipScreen.kt b/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/nests/room/NestPipScreen.kt similarity index 94% rename from amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/audiorooms/room/AudioRoomPipScreen.kt rename to amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/nests/room/NestPipScreen.kt index 5c993c3e2..622fe9261 100644 --- a/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/audiorooms/room/AudioRoomPipScreen.kt +++ b/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/nests/room/NestPipScreen.kt @@ -18,7 +18,7 @@ * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -package com.vitorpamplona.amethyst.ui.screen.loggedIn.audiorooms.room +package com.vitorpamplona.amethyst.ui.screen.loggedIn.nests.room import androidx.compose.foundation.background import androidx.compose.foundation.border @@ -36,7 +36,7 @@ import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.text.style.TextOverflow import androidx.compose.ui.unit.dp -import com.vitorpamplona.amethyst.commons.viewmodels.AudioRoomUiState +import com.vitorpamplona.amethyst.commons.viewmodels.NestUiState import com.vitorpamplona.amethyst.ui.note.ClickableUserPicture import com.vitorpamplona.amethyst.ui.screen.loggedIn.AccountViewModel import com.vitorpamplona.amethyst.ui.theme.Size35dp @@ -46,13 +46,13 @@ import com.vitorpamplona.quartz.nip53LiveActivities.streaming.tags.ParticipantTa * Compact PIP layout. Shows up to four "on stage" speakers with a ring on * whoever is actively delivering audio, plus the room title. The mute / * leave actions live in the system PIP overlay as RemoteActions — see - * [AudioRoomActivity.buildPipActions]. + * [NestActivity.buildPipActions]. */ @Composable -internal fun AudioRoomPipScreen( +internal fun NestPipScreen( title: String?, onStage: List, - ui: AudioRoomUiState, + ui: NestUiState, accountViewModel: AccountViewModel, ) { val ringColor = MaterialTheme.colorScheme.primary diff --git a/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/audiorooms/room/AudioRoomThemedScope.kt b/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/nests/room/NestThemedScope.kt similarity index 98% rename from amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/audiorooms/room/AudioRoomThemedScope.kt rename to amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/nests/room/NestThemedScope.kt index dc75f8ff9..cacfecf01 100644 --- a/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/audiorooms/room/AudioRoomThemedScope.kt +++ b/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/nests/room/NestThemedScope.kt @@ -18,7 +18,7 @@ * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -package com.vitorpamplona.amethyst.ui.screen.loggedIn.audiorooms.room +package com.vitorpamplona.amethyst.ui.screen.loggedIn.nests.room import androidx.compose.foundation.background import androidx.compose.foundation.layout.Box @@ -55,7 +55,7 @@ import kotlinx.coroutines.withContext * passthrough Box. */ @Composable -internal fun AudioRoomThemedScope( +internal fun NestThemedScope( theme: RoomTheme, accountViewModel: AccountViewModel, content: @Composable () -> Unit, diff --git a/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/audiorooms/room/AudioRoomViewModelFactory.kt b/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/nests/room/NestViewModelFactory.kt similarity index 89% rename from amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/audiorooms/room/AudioRoomViewModelFactory.kt rename to amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/nests/room/NestViewModelFactory.kt index da255bd9c..59a10a17e 100644 --- a/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/audiorooms/room/AudioRoomViewModelFactory.kt +++ b/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/nests/room/NestViewModelFactory.kt @@ -18,11 +18,11 @@ * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -package com.vitorpamplona.amethyst.ui.screen.loggedIn.audiorooms.room +package com.vitorpamplona.amethyst.ui.screen.loggedIn.nests.room import androidx.lifecycle.ViewModel import androidx.lifecycle.ViewModelProvider -import com.vitorpamplona.amethyst.commons.viewmodels.AudioRoomViewModel +import com.vitorpamplona.amethyst.commons.viewmodels.NestViewModel import com.vitorpamplona.nestsclient.NestsRoomConfig import com.vitorpamplona.nestsclient.OkHttpNestsClient import com.vitorpamplona.nestsclient.audio.AudioRecordCapture @@ -33,19 +33,19 @@ import com.vitorpamplona.nestsclient.transport.QuicWebTransportFactory import com.vitorpamplona.quartz.nip01Core.signers.NostrSigner /** - * Android-side Factory for [AudioRoomViewModel]. The ViewModel itself lives + * Android-side Factory for [NestViewModel]. The ViewModel itself lives * in `commons/` so a future desktop port can reuse the orchestration once * Compose Desktop has WebTransport; this factory binds it to the Android * actuals (OkHttp HTTP, pure-Kotlin QUIC, MediaCodec Opus, AudioTrack + * AudioRecord on the speaker side). */ -internal class AudioRoomViewModelFactory( +internal class NestViewModelFactory( private val signer: NostrSigner, private val room: NestsRoomConfig, ) : ViewModelProvider.Factory { @Suppress("UNCHECKED_CAST") override fun create(modelClass: Class): T = - AudioRoomViewModel( + NestViewModel( httpClient = OkHttpNestsClient(), transport = QuicWebTransportFactory(), decoderFactory = { MediaCodecOpusDecoder() }, diff --git a/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/audiorooms/room/ParticipantHostActionsSheet.kt b/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/nests/room/ParticipantHostActionsSheet.kt similarity index 91% rename from amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/audiorooms/room/ParticipantHostActionsSheet.kt rename to amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/nests/room/ParticipantHostActionsSheet.kt index 87f4dbb86..67d7abf46 100644 --- a/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/audiorooms/room/ParticipantHostActionsSheet.kt +++ b/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/nests/room/ParticipantHostActionsSheet.kt @@ -18,7 +18,7 @@ * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -package com.vitorpamplona.amethyst.ui.screen.loggedIn.audiorooms.room +package com.vitorpamplona.amethyst.ui.screen.loggedIn.nests.room import androidx.compose.foundation.clickable import androidx.compose.foundation.layout.Arrangement @@ -49,7 +49,7 @@ import com.vitorpamplona.amethyst.ui.note.ZapCustomDialog import com.vitorpamplona.amethyst.ui.note.payViaIntent import com.vitorpamplona.amethyst.ui.screen.loggedIn.AccountViewModel import com.vitorpamplona.amethyst.ui.stringRes -import com.vitorpamplona.quartz.experimental.audiorooms.admin.AdminCommandEvent +import com.vitorpamplona.quartz.experimental.nests.admin.AdminCommandEvent import com.vitorpamplona.quartz.nip01Core.metadata.MetadataEvent import com.vitorpamplona.quartz.nip01Core.tags.aTag.ATag import com.vitorpamplona.quartz.nip19Bech32.entities.NPub @@ -134,7 +134,7 @@ internal fun ParticipantHostActionsSheet( ) } Spacer(Modifier.height(8.dp)) - // View Profile — AudioRoomActivity is a separate Android + // View Profile — NestActivity is a separate Android // Activity without its own nav stack, so the deep-link // path goes through MainActivity. Launching `nostr:npub1...` // via ACTION_VIEW lets the existing MainActivity URI @@ -145,8 +145,8 @@ internal fun ParticipantHostActionsSheet( // audio-room foreground service keeps audio alive while // the user is on the profile screen. val context = LocalContext.current - val noAppMessage = stringRes(R.string.audio_room_no_app_to_open_link) - ActionRow(stringRes(R.string.audio_room_participant_view_profile)) { + val noAppMessage = stringRes(R.string.nest_no_app_to_open_link) + ActionRow(stringRes(R.string.nest_participant_view_profile)) { val npub = NPub.create(target) val launched = runCatching { @@ -165,7 +165,7 @@ internal fun ParticipantHostActionsSheet( }.isSuccess if (!launched) { accountViewModel.toastManager.toast( - R.string.audio_room_chat_send_failed_title, + R.string.nest_chat_send_failed_title, noAppMessage, user = null, ) @@ -180,7 +180,7 @@ internal fun ParticipantHostActionsSheet( // the profile screen rather than wired into a non-nav-host // ModalBottomSheet. var showZapDialog by rememberSaveable { mutableStateOf(false) } - ActionRow(stringRes(R.string.audio_room_participant_zap)) { + ActionRow(stringRes(R.string.nest_participant_zap)) { showZapDialog = true } if (showZapDialog) { @@ -191,7 +191,7 @@ internal fun ParticipantHostActionsSheet( } // Pre-resolved at composition because callbacks below run // outside a @Composable scope (stringRes is composable-only). - val splitUnsupportedMsg = stringRes(R.string.audio_room_participant_zap_split_unsupported) + val splitUnsupportedMsg = stringRes(R.string.nest_participant_zap_split_unsupported) ZapCustomDialog( onZapStarts = {}, onClose = { @@ -229,9 +229,9 @@ internal fun ParticipantHostActionsSheet( text = stringRes( if (isFollowing) { - R.string.audio_room_participant_unfollow + R.string.nest_participant_unfollow } else { - R.string.audio_room_participant_follow + R.string.nest_participant_follow }, ), ) { @@ -242,9 +242,9 @@ internal fun ParticipantHostActionsSheet( text = stringRes( if (isHidden) { - R.string.audio_room_participant_unmute + R.string.nest_participant_unmute } else { - R.string.audio_room_participant_mute + R.string.nest_participant_mute }, ), ) { @@ -255,16 +255,16 @@ internal fun ParticipantHostActionsSheet( // Host-only rows. if (isLocalUserHost && target != event.pubKey) { Spacer(Modifier.height(4.dp)) - ActionRow(stringRes(R.string.audio_room_promote_speaker)) { + ActionRow(stringRes(R.string.nest_promote_speaker)) { broadcast(RoomParticipantActions.setRole(event, target, ROLE.SPEAKER)) onDismiss() } - ActionRow(stringRes(R.string.audio_room_demote_listener)) { + ActionRow(stringRes(R.string.nest_demote_listener)) { broadcast(RoomParticipantActions.demoteToListener(event, target)) onDismiss() } ActionRow( - text = stringRes(R.string.audio_room_kick_action), + text = stringRes(R.string.nest_kick_action), color = MaterialTheme.colorScheme.error, ) { broadcast(AdminCommandEvent.kick(roomATag, target)) diff --git a/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/audiorooms/room/ParticipantsGrid.kt b/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/nests/room/ParticipantsGrid.kt similarity index 99% rename from amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/audiorooms/room/ParticipantsGrid.kt rename to amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/nests/room/ParticipantsGrid.kt index 27a9cc72b..3ef5ebae5 100644 --- a/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/audiorooms/room/ParticipantsGrid.kt +++ b/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/nests/room/ParticipantsGrid.kt @@ -18,7 +18,7 @@ * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -package com.vitorpamplona.amethyst.ui.screen.loggedIn.audiorooms.room +package com.vitorpamplona.amethyst.ui.screen.loggedIn.nests.room import androidx.compose.foundation.border import androidx.compose.foundation.layout.Arrangement diff --git a/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/audiorooms/room/RoomFontLoader.kt b/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/nests/room/RoomFontLoader.kt similarity index 98% rename from amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/audiorooms/room/RoomFontLoader.kt rename to amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/nests/room/RoomFontLoader.kt index a9ed37409..7386757ce 100644 --- a/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/audiorooms/room/RoomFontLoader.kt +++ b/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/nests/room/RoomFontLoader.kt @@ -18,7 +18,7 @@ * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -package com.vitorpamplona.amethyst.ui.screen.loggedIn.audiorooms.room +package com.vitorpamplona.amethyst.ui.screen.loggedIn.nests.room import android.content.Context import androidx.compose.ui.text.font.Font diff --git a/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/audiorooms/room/RoomParticipantActions.kt b/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/nests/room/RoomParticipantActions.kt similarity index 97% rename from amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/audiorooms/room/RoomParticipantActions.kt rename to amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/nests/room/RoomParticipantActions.kt index a54910a0c..2836f9566 100644 --- a/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/audiorooms/room/RoomParticipantActions.kt +++ b/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/nests/room/RoomParticipantActions.kt @@ -18,7 +18,7 @@ * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -package com.vitorpamplona.amethyst.ui.screen.loggedIn.audiorooms.room +package com.vitorpamplona.amethyst.ui.screen.loggedIn.nests.room import com.vitorpamplona.quartz.nip01Core.signers.EventTemplate import com.vitorpamplona.quartz.nip53LiveActivities.meetingSpaces.MeetingSpaceEvent @@ -37,7 +37,7 @@ import com.vitorpamplona.quartz.nip53LiveActivities.streaming.tags.ROLE * * Extracted out of the screen Composable so they can be unit-tested * without an AccountViewModel / signer (the sign+broadcast path is - * the only side effect, mirroring [EditAudioRoomViewModel.buildEditTemplate]). + * the only side effect, mirroring [EditNestViewModel.buildEditTemplate]). * * Risk-mitigation: each builder reads ALL participants from * [original] and rebuilds the list with one row mutated; never diff --git a/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/audiorooms/room/RoomReactionPickerSheet.kt b/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/nests/room/RoomReactionPickerSheet.kt similarity index 96% rename from amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/audiorooms/room/RoomReactionPickerSheet.kt rename to amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/nests/room/RoomReactionPickerSheet.kt index 08d4f0752..054221c54 100644 --- a/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/audiorooms/room/RoomReactionPickerSheet.kt +++ b/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/nests/room/RoomReactionPickerSheet.kt @@ -18,7 +18,7 @@ * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -package com.vitorpamplona.amethyst.ui.screen.loggedIn.audiorooms.room +package com.vitorpamplona.amethyst.ui.screen.loggedIn.nests.room import androidx.compose.foundation.clickable import androidx.compose.foundation.layout.Arrangement @@ -66,7 +66,7 @@ internal fun RoomReactionPickerSheet( ) { Column(modifier = Modifier.fillMaxWidth().padding(horizontal = 16.dp, vertical = 12.dp)) { Text( - text = stringRes(R.string.audio_room_reactions_title), + text = stringRes(R.string.nest_reactions_title), style = MaterialTheme.typography.titleSmall, modifier = Modifier.fillMaxWidth(), textAlign = TextAlign.Center, diff --git a/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/audiorooms/room/SpeakerReactionOverlay.kt b/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/nests/room/SpeakerReactionOverlay.kt similarity index 95% rename from amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/audiorooms/room/SpeakerReactionOverlay.kt rename to amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/nests/room/SpeakerReactionOverlay.kt index f41bc94df..2b39fe39f 100644 --- a/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/audiorooms/room/SpeakerReactionOverlay.kt +++ b/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/nests/room/SpeakerReactionOverlay.kt @@ -18,7 +18,7 @@ * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -package com.vitorpamplona.amethyst.ui.screen.loggedIn.audiorooms.room +package com.vitorpamplona.amethyst.ui.screen.loggedIn.nests.room import androidx.compose.foundation.layout.Arrangement import androidx.compose.foundation.layout.Row @@ -38,7 +38,7 @@ import com.vitorpamplona.amethyst.commons.viewmodels.RoomReaction * * Hides itself when there are no reactions in the window — the * 30-s sliding-window aggregator in - * [com.vitorpamplona.amethyst.commons.viewmodels.AudioRoomViewModel.recentReactions] + * [com.vitorpamplona.amethyst.commons.viewmodels.NestViewModel.recentReactions] * drops stale entries on the 1-s tick. */ @Composable diff --git a/amethyst/src/main/res/values-cs-rCZ/strings.xml b/amethyst/src/main/res/values-cs-rCZ/strings.xml index b8cd9fe6b..29f7c66fe 100644 --- a/amethyst/src/main/res/values-cs-rCZ/strings.xml +++ b/amethyst/src/main/res/values-cs-rCZ/strings.xml @@ -456,11 +456,11 @@ Veřejné chaty Seznamy sledování Živé vysílání - Audio místnosti - Pódium - Publikum - Přihlásit se - Dát ruku dolů + Audio místnosti + Pódium + Publikum + Přihlásit se + Dát ruku dolů Videa Články Soukromé záložky diff --git a/amethyst/src/main/res/values-de-rDE/strings.xml b/amethyst/src/main/res/values-de-rDE/strings.xml index 88ceeea32..1a95a0613 100644 --- a/amethyst/src/main/res/values-de-rDE/strings.xml +++ b/amethyst/src/main/res/values-de-rDE/strings.xml @@ -462,11 +462,11 @@ anz der Bedingungen ist erforderlich Öffentliche Chats Follow-Pakete Live-Streams - Audioräume - Bühne - Publikum - Hand heben - Hand senken + Audioräume + Bühne + Publikum + Hand heben + Hand senken Videos Artikel Private Lesezeichen diff --git a/amethyst/src/main/res/values-hi-rIN/strings.xml b/amethyst/src/main/res/values-hi-rIN/strings.xml index d15a5fdd5..ebf606d4a 100644 --- a/amethyst/src/main/res/values-hi-rIN/strings.xml +++ b/amethyst/src/main/res/values-hi-rIN/strings.xml @@ -458,11 +458,11 @@ सार्वजनिक चर्चा अनुचरण पोटलियाँ सीधा प्रसारण - ध्वनि शाला - मंच - श्रोतागण - हाथ उठाएँ - हाथ नीचे करें + ध्वनि शाला + मंच + श्रोतागण + हाथ उठाएँ + हाथ नीचे करें चलचित्र लेख निजी स्मर्तव्य diff --git a/amethyst/src/main/res/values-hu-rHU/strings.xml b/amethyst/src/main/res/values-hu-rHU/strings.xml index 22672f68f..6ebed89e3 100644 --- a/amethyst/src/main/res/values-hu-rHU/strings.xml +++ b/amethyst/src/main/res/values-hu-rHU/strings.xml @@ -458,11 +458,11 @@ Nyilvános csevegések Követési csomagok Élő közvetítések - Hangszobák - Állapot - Közönség - Kéz felemelése - Kéz leengedése + Hangszobák + Állapot + Közönség + Kéz felemelése + Kéz leengedése Videók Cikkek Privát könyvjelzők diff --git a/amethyst/src/main/res/values-pl-rPL/strings.xml b/amethyst/src/main/res/values-pl-rPL/strings.xml index 0fb7202c8..9f5109a0a 100644 --- a/amethyst/src/main/res/values-pl-rPL/strings.xml +++ b/amethyst/src/main/res/values-pl-rPL/strings.xml @@ -455,11 +455,11 @@ Czaty publiczne Pakiety subskrybentów Transmisje na żywo - Pokoje audio - Scena - Publiczność - Podnieś rękę - Opuść rękę + Pokoje audio + Scena + Publiczność + Podnieś rękę + Opuść rękę Filmy wideo Artykuły Prywatne Zakładki diff --git a/amethyst/src/main/res/values-pt-rBR/strings.xml b/amethyst/src/main/res/values-pt-rBR/strings.xml index 65dd266db..7d5258142 100644 --- a/amethyst/src/main/res/values-pt-rBR/strings.xml +++ b/amethyst/src/main/res/values-pt-rBR/strings.xml @@ -456,11 +456,11 @@ Chats públicos Pacotes de seguidos Transmissões ao vivo - Salas de áudio - Palco - Plateia - Levantar mão - Abaixar mão + Salas de áudio + Palco + Plateia + Levantar mão + Abaixar mão Vídeos Artigos Itens Salvos Privados diff --git a/amethyst/src/main/res/values-sl-rSI/strings.xml b/amethyst/src/main/res/values-sl-rSI/strings.xml index ed0b2e170..391fad54d 100644 --- a/amethyst/src/main/res/values-sl-rSI/strings.xml +++ b/amethyst/src/main/res/values-sl-rSI/strings.xml @@ -469,11 +469,11 @@ Za podpisovanje se je potrebno prijaviti s privatnim ključem Javni klepeti Paketi sledenih Posnetki v živo - Zvočne sobe - Prizorišče - Občinstvo - Dvigni roko - Spusti roko + Zvočne sobe + Prizorišče + Občinstvo + Dvigni roko + Spusti roko Videoposnetki Članki Privatni zaznamki diff --git a/amethyst/src/main/res/values-sv-rSE/strings.xml b/amethyst/src/main/res/values-sv-rSE/strings.xml index 3959559cb..f6625578a 100644 --- a/amethyst/src/main/res/values-sv-rSE/strings.xml +++ b/amethyst/src/main/res/values-sv-rSE/strings.xml @@ -456,11 +456,11 @@ Offentliga chattar Följpaket Livesändningar - Ljudrum - Scen - Publik - Räck upp handen - Sänk handen + Ljudrum + Scen + Publik + Räck upp handen + Sänk handen Videor Artiklar Privata Bokmärken diff --git a/amethyst/src/main/res/values-zh-rCN/strings.xml b/amethyst/src/main/res/values-zh-rCN/strings.xml index d0389a336..f0a505d31 100644 --- a/amethyst/src/main/res/values-zh-rCN/strings.xml +++ b/amethyst/src/main/res/values-zh-rCN/strings.xml @@ -458,11 +458,11 @@ 公共聊天 关注包 直播 - 音频室 - 阶段 - 观众 - 举手 - 放下手 + 音频室 + 阶段 + 观众 + 举手 + 放下手 视频 文章 私人书签 diff --git a/amethyst/src/main/res/values/strings.xml b/amethyst/src/main/res/values/strings.xml index c4565defc..5faa6fc6a 100644 --- a/amethyst/src/main/res/values/strings.xml +++ b/amethyst/src/main/res/values/strings.xml @@ -488,107 +488,107 @@ Public Chats Follow Packs Live Streams - Audio Rooms - Stage - Audience - Raise hand - Lower hand - Connect audio - Disconnect - Mute - Unmute - Connecting… - Resolving room - Opening transport - Negotiating audio - Audio connected - Reconnecting… - Listen to recording - Couldn\'t send message - No app installed to open this link. - Close this room? - All attendees will be disconnected. The room will show as CLOSED in the feed. - Close room - Pick a future start time. - Audio failed: %1$s - Audio is not available for this room - Talk - Stop talking - Mute mic - Unmute mic - Going live… - Live - Broadcast failed: %1$s - Microphone access is required to talk in this room. - Open settings - Audio rooms - Keeps audio playing while a room is open. - Audio room connected - Audio room — Live - Tap to return. - Stop - Join audio room - Leave - End this audio room? - You\'re the host. Closing the room will disconnect everyone. Choose \"Just leave\" if you want to come back later — the room will auto-close after 8 hours of inactivity. - Close room - Just leave - Couldn\'t mark room as closed. Leaving anyway — room will auto-close. - + Nests + Stage + Audience + Raise hand + Lower hand + Connect audio + Disconnect + Mute + Unmute + Connecting… + Resolving room + Opening transport + Negotiating audio + Audio connected + Reconnecting… + Listen to recording + Couldn\'t send message + No app installed to open this link. + Close this room? + All attendees will be disconnected. The room will show as CLOSED in the feed. + Close room + Pick a future start time. + Audio failed: %1$s + Audio is not available for this room + Talk + Stop talking + Mute mic + Unmute mic + Going live… + Live + Broadcast failed: %1$s + Microphone access is required to talk in this room. + Open settings + Nests + Keeps audio playing while a room is open. + Nest connected + Nest — Live + Tap to return. + Stop + Join nest + Leave + End this nest? + You\'re the host. Closing the room will disconnect everyone. Choose \"Just leave\" if you want to come back later — the room will auto-close after 8 hours of inactivity. + Close room + Just leave + Couldn\'t mark room as closed. Leaving anyway — room will auto-close. + %1$d listener %1$d listeners - Send - Say something… - No messages yet. Be the first to chat. - React - React - Edit room - Save - Close room - Room actions - Raised hands - Approve - Promote to speaker - Demote to listener - Kick - View profile - Send zap - Split zaps are not supported from inside an audio room. Open the profile screen to send. - Follow - Unfollow - Mute - Unmute - Share room - Start space - Set up an audio server - You haven\'t picked an audio server yet. Add %1$s to your server list and continue?\n\nYou can change this later in Settings. - Use default - Cancel - Couldn\'t save your audio server list. Try again. - Start a new audio room - Room name - What\'s it about? - MoQ service URL - Auth sidecar — defaults to nostrnests.com - MoQ relay endpoint - WebTransport URL — usually the same host - Cover image URL (optional) - Cancel - Start space - Schedule for later - Pick a start time - Audio-room servers - Choose which MoQ host servers Amethyst publishes your audio rooms to. The first entry is used by default when you start a new space. + Send + Say something… + No messages yet. Be the first to chat. + React + React + Edit room + Save + Close room + Room actions + Raised hands + Approve + Promote to speaker + Demote to listener + Kick + View profile + Send zap + Split zaps are not supported from inside a nest. Open the profile screen to send. + Follow + Unfollow + Mute + Unmute + Share room + Start space + Set up a nest server + You haven\'t picked a nest server yet. Add %1$s to your server list and continue?\n\nYou can change this later in Settings. + Use default + Cancel + Couldn\'t save your nest server list. Try again. + Start a new nest + Room name + What\'s it about? + MoQ service URL + Auth sidecar — defaults to nostrnests.com + MoQ relay endpoint + WebTransport URL — usually the same host + Cover image URL (optional) + Cancel + Start space + Schedule for later + Pick a start time + Nest servers + Choose which MoQ host servers Amethyst publishes your nests to. The first entry is used by default when you start a new space. Your servers Saved as a kind-10112 replaceable event so other clients can read your preference. - Add an audio-room server + Add a nest server Recommended servers Built-in suggestions you can add to your list with one tap. Use Amethyst defaults Add server Remove server - No audio-room servers yet. Add one below or pick a recommended server. + No nest servers yet. Add one below or pick a recommended server. Videos Articles Private Bookmarks @@ -2141,7 +2141,7 @@ Profile Badges Blocked Relays Blossom Servers - Audio-room (Nests) Servers + Nests Servers Blossom Auth Broadcast Relays Bookmark List diff --git a/amethyst/src/test/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/audiorooms/room/EditAudioRoomViewModelTest.kt b/amethyst/src/test/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/nests/room/EditNestViewModelTest.kt similarity index 91% rename from amethyst/src/test/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/audiorooms/room/EditAudioRoomViewModelTest.kt rename to amethyst/src/test/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/nests/room/EditNestViewModelTest.kt index cf2469d72..ced91114e 100644 --- a/amethyst/src/test/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/audiorooms/room/EditAudioRoomViewModelTest.kt +++ b/amethyst/src/test/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/nests/room/EditNestViewModelTest.kt @@ -18,7 +18,7 @@ * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -package com.vitorpamplona.amethyst.ui.screen.loggedIn.audiorooms.room +package com.vitorpamplona.amethyst.ui.screen.loggedIn.nests.room import com.vitorpamplona.quartz.nip53LiveActivities.meetingSpaces.MeetingSpaceEvent import com.vitorpamplona.quartz.nip53LiveActivities.meetingSpaces.tags.StatusTag @@ -27,7 +27,7 @@ import org.junit.Assert.assertNull import org.junit.Assert.assertTrue import org.junit.Test -class EditAudioRoomViewModelTest { +class EditNestViewModelTest { private val host = "a".repeat(64) private val speakerA = "b".repeat(64) private val speakerB = "c".repeat(64) @@ -68,7 +68,7 @@ class EditAudioRoomViewModelTest { imageUrl: String = "", endpointUrl: String = "https://moq.example.com", serviceUrl: String = "https://auth.example.com", - ) = EditAudioRoomViewModel.FormState( + ) = EditNestViewModel.FormState( dTag = dTag, roomName = roomName, summary = summary, @@ -85,7 +85,7 @@ class EditAudioRoomViewModelTest { val newForm = form(dTag = "rt-42", roomName = "New name", summary = "New summary") val template = - EditAudioRoomViewModel.buildEditTemplate(src, newForm, StatusTag.STATUS.OPEN) + EditNestViewModel.buildEditTemplate(src, newForm, StatusTag.STATUS.OPEN) // Same d-tag → same address → relay treats as replacement. val dTag = template.tags.firstOrNull { it.firstOrNull() == "d" }?.getOrNull(1) @@ -113,7 +113,7 @@ class EditAudioRoomViewModelTest { val newForm = form(dTag = "rt-1", roomName = "Renamed") val template = - EditAudioRoomViewModel.buildEditTemplate(src, newForm, StatusTag.STATUS.OPEN) + EditNestViewModel.buildEditTemplate(src, newForm, StatusTag.STATUS.OPEN) val pTagPubkeys = template.tags.filter { it.firstOrNull() == "p" }.map { it[1] } // Host plus two speakers — none can be lost on a rename. @@ -129,7 +129,7 @@ class EditAudioRoomViewModelTest { val sameForm = form(dTag = "rt-99", roomName = src.room().orEmpty()) val template = - EditAudioRoomViewModel.buildEditTemplate(src, sameForm, StatusTag.STATUS.CLOSED) + EditNestViewModel.buildEditTemplate(src, sameForm, StatusTag.STATUS.CLOSED) val statusTag = template.tags.firstOrNull { it.firstOrNull() == "status" }?.getOrNull(1) assertEquals(StatusTag.STATUS.CLOSED.code, statusTag) @@ -143,7 +143,7 @@ class EditAudioRoomViewModelTest { val emptied = form(dTag = "rt-1", roomName = "X", summary = " ", imageUrl = "") val template = - EditAudioRoomViewModel.buildEditTemplate(src, emptied, StatusTag.STATUS.OPEN) + EditNestViewModel.buildEditTemplate(src, emptied, StatusTag.STATUS.OPEN) // Blank inputs MUST NOT carry over from the original; otherwise // a "delete the summary" edit would silently fail. diff --git a/amethyst/src/test/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/audiorooms/room/RoomParticipantActionsTest.kt b/amethyst/src/test/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/nests/room/RoomParticipantActionsTest.kt similarity index 98% rename from amethyst/src/test/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/audiorooms/room/RoomParticipantActionsTest.kt rename to amethyst/src/test/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/nests/room/RoomParticipantActionsTest.kt index 5bef9ee45..f7e3b892b 100644 --- a/amethyst/src/test/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/audiorooms/room/RoomParticipantActionsTest.kt +++ b/amethyst/src/test/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/nests/room/RoomParticipantActionsTest.kt @@ -18,7 +18,7 @@ * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -package com.vitorpamplona.amethyst.ui.screen.loggedIn.audiorooms.room +package com.vitorpamplona.amethyst.ui.screen.loggedIn.nests.room import com.vitorpamplona.quartz.nip53LiveActivities.meetingSpaces.MeetingSpaceEvent import com.vitorpamplona.quartz.nip53LiveActivities.streaming.tags.ROLE diff --git a/commons/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/viewmodels/AudioRoomViewModel.kt b/commons/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/viewmodels/NestViewModel.kt similarity index 97% rename from commons/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/viewmodels/AudioRoomViewModel.kt rename to commons/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/viewmodels/NestViewModel.kt index 7b3d20d2c..b1932500e 100644 --- a/commons/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/viewmodels/AudioRoomViewModel.kt +++ b/commons/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/viewmodels/NestViewModel.kt @@ -33,7 +33,7 @@ import com.vitorpamplona.nestsclient.NestsSpeaker import com.vitorpamplona.nestsclient.NestsSpeakerState import com.vitorpamplona.nestsclient.audio.AudioCapture import com.vitorpamplona.nestsclient.audio.AudioPlayer -import com.vitorpamplona.nestsclient.audio.AudioRoomPlayer +import com.vitorpamplona.nestsclient.audio.NestPlayer import com.vitorpamplona.nestsclient.audio.OpusDecoder import com.vitorpamplona.nestsclient.audio.OpusEncoder import com.vitorpamplona.nestsclient.connectNestsSpeaker @@ -60,7 +60,7 @@ import kotlin.coroutines.cancellation.CancellationException * Per-screen state holder for a NIP-53 audio-room. * * Owns one [NestsListener] for the lifetime of the screen and one - * [AudioRoomPlayer] per active speaker subscription. The screen tells the + * [NestPlayer] per active speaker subscription. The screen tells the * VM which speakers it cares about via [updateSpeakers]; subscribe / play * happen automatically once the listener is [NestsListenerState.Connected]. * @@ -90,7 +90,7 @@ import kotlin.coroutines.cancellation.CancellationException * via `viewModelScope.launch(Dispatchers.Main.immediate) { ... }` first. */ @Stable -class AudioRoomViewModel( +class NestViewModel( private val httpClient: NestsClient, private val transport: WebTransportFactory, private val decoderFactory: () -> OpusDecoder, @@ -116,8 +116,8 @@ class AudioRoomViewModel( @OptIn(kotlinx.coroutines.DelicateCoroutinesApi::class) private val cleanupScope: CoroutineScope = GlobalScope, ) : ViewModel() { - private val _uiState = MutableStateFlow(AudioRoomUiState()) - val uiState: StateFlow = _uiState.asStateFlow() + private val _uiState = MutableStateFlow(NestUiState()) + val uiState: StateFlow = _uiState.asStateFlow() /** * Listener-side aggregation of every peer's most recent kind-10312 @@ -292,7 +292,7 @@ class AudioRoomViewModel( /** * Toggle whether we hold a speaker slot. Tier-2's "leave the stage" * tap flips this to `false`; the next kind-10312 heartbeat picks up - * the change via [AudioRoomUiState.onStageNow]. Does NOT stop a + * the change via [NestUiState.onStageNow]. Does NOT stop a * running broadcast — UI / caller is expected to call * [BroadcastHandle.close] separately when leaving the stage. */ @@ -674,7 +674,7 @@ class AudioRoomViewModel( /** * Stop the per-speaker player + fire-and-forget UNSUBSCRIBE on the VM - * scope. Both `AudioRoomPlayer.stop()` and `SubscribeHandle.unsubscribe()` + * scope. Both `NestPlayer.stop()` and `SubscribeHandle.unsubscribe()` * are suspend, so we route them through one coroutine instead of two. */ private fun closeSubscription(slot: ActiveSubscription) { @@ -766,7 +766,7 @@ class AudioRoomViewModel( } try { val isMuted = _uiState.value.isMuted - val roomPlayer = AudioRoomPlayer(decoder, player, viewModelScope) + val roomPlayer = NestPlayer(decoder, player, viewModelScope) // Apply current mute state before play() opens the device so the // first frame respects it. player.setMutedSafe(isMuted) @@ -834,7 +834,7 @@ class AudioRoomViewModel( // listener.close() below tears down the MoQ session and drops // every active subscription, so we don't need to call // unsubscribe() per-handle here — but we DO need to await each - // AudioRoomPlayer.stop() so the native MediaCodec / AudioTrack + // NestPlayer.stop() so the native MediaCodec / AudioTrack // is released after its decode loop has unwound. val scope = if (finalCleanup) cleanupScope else viewModelScope val players = activeSubscriptions.values.map { it.detach().first } @@ -912,7 +912,7 @@ class AudioRoomViewModel( val pubkey: String, ) { private var handle: SubscribeHandle? = null - private var roomPlayer: AudioRoomPlayer? = null + private var roomPlayer: NestPlayer? = null var player: AudioPlayer? = null private set var isPlaying: Boolean = false @@ -920,7 +920,7 @@ class AudioRoomViewModel( fun attach( handle: SubscribeHandle, - roomPlayer: AudioRoomPlayer, + roomPlayer: NestPlayer, player: AudioPlayer, ) { this.handle = handle @@ -931,12 +931,12 @@ class AudioRoomViewModel( /** * Hand the player + handle back to the caller's coroutine scope — - * `AudioRoomPlayer.stop()` and `SubscribeHandle.unsubscribe()` are + * `NestPlayer.stop()` and `SubscribeHandle.unsubscribe()` are * both suspend, and the caller has the right scope to await them * (so native MediaCodec/AudioTrack release runs after the decode * loop has unwound, per audit MoQ #11/#12). */ - fun detach(): Pair { + fun detach(): Pair { isPlaying = false val p = roomPlayer val h = handle @@ -951,7 +951,7 @@ class AudioRoomViewModel( } } - // Platform-specific Factory lives in `amethyst/.../audiorooms/room/`, + // Platform-specific Factory lives in `amethyst/.../nests/room/`, // not commonMain — the lifecycle KMP `ViewModelProvider.Factory` // signature has been migrating between releases; a thin Android-side // factory keeps that churn out of shared code. @@ -1006,7 +1006,7 @@ private fun AudioPlayer.setMutedSafe(muted: Boolean) { } @Immutable -data class AudioRoomUiState( +data class NestUiState( val connection: ConnectionUiState = ConnectionUiState.Idle, val isMuted: Boolean = false, /** Pubkeys we have an open MoQ subscription for. */ @@ -1025,11 +1025,11 @@ data class AudioRoomUiState( * speaker subsequently goes quiet. Cleared on speaker removal. */ val connectingSpeakers: ImmutableSet = persistentSetOf(), - /** Speaker / publisher state — only relevant when [AudioRoomViewModel.canBroadcast]. */ + /** Speaker / publisher state — only relevant when [NestViewModel.canBroadcast]. */ val broadcast: BroadcastUiState = BroadcastUiState.Idle, /** * `true` when we hold a speaker slot vs being pure audience. Defaults - * to `true` for users with [AudioRoomViewModel.canBroadcast]; the + * to `true` for users with [NestViewModel.canBroadcast]; the * "leave the stage" tap (Tier 2) flips it to `false`. Drives the * `["onstage", "0|1"]` tag on emitted kind-10312 presence events. */ @@ -1076,7 +1076,7 @@ const val SPEAKING_TIMEOUT_MS: Long = 250L /** * How long a kind-7 reaction stays in - * [AudioRoomViewModel.recentReactions] before the eviction sweep + * [NestViewModel.recentReactions] before the eviction sweep * drops it. Matches the duration of the floating-up animation in the * SpeakerReactionOverlay. */ diff --git a/commons/src/commonTest/kotlin/com/vitorpamplona/amethyst/commons/viewmodels/AudioRoomViewModelTest.kt b/commons/src/commonTest/kotlin/com/vitorpamplona/amethyst/commons/viewmodels/NestViewModelTest.kt similarity index 95% rename from commons/src/commonTest/kotlin/com/vitorpamplona/amethyst/commons/viewmodels/AudioRoomViewModelTest.kt rename to commons/src/commonTest/kotlin/com/vitorpamplona/amethyst/commons/viewmodels/NestViewModelTest.kt index 662a0a793..fd1798ba9 100644 --- a/commons/src/commonTest/kotlin/com/vitorpamplona/amethyst/commons/viewmodels/AudioRoomViewModelTest.kt +++ b/commons/src/commonTest/kotlin/com/vitorpamplona/amethyst/commons/viewmodels/NestViewModelTest.kt @@ -54,7 +54,7 @@ import kotlin.test.assertIs import kotlin.test.assertTrue /** - * Drives [AudioRoomViewModel] with a fake [NestsListenerConnector] and + * Drives [NestViewModel] with a fake [NestsListenerConnector] and * verifies its state-flow transitions: * - connect() shows Connecting before the underlying connector returns * - listener emits Connected → uiState collapses to Connected @@ -62,13 +62,13 @@ import kotlin.test.assertTrue * - setMuted updates uiState and propagates to active subscriptions * - disconnect() returns to Idle and tears down the listener * - * Subscribe-side (subscribeSpeaker → AudioRoomPlayer.play) is exercised via + * Subscribe-side (subscribeSpeaker → NestPlayer.play) is exercised via * the existing nestsClient tests; the cross-module audio glue would need * an internal SubscribeHandle constructor that's intentionally not visible * here. */ @OptIn(ExperimentalCoroutinesApi::class) -class AudioRoomViewModelTest { +class NestViewModelTest { @BeforeTest fun setupMainDispatcher() { Dispatchers.setMain(UnconfinedTestDispatcher()) @@ -143,7 +143,7 @@ class AudioRoomViewModelTest { // Defaults to true so a freshly-joined speaker advertises // onstage=1 on the first heartbeat (the heartbeat in - // AudioRoomActivityContent reads this as the tag value). + // NestActivityContent reads this as the tag value). assertTrue(vm.uiState.value.onStageNow) vm.setOnStage(false) assertFalse(vm.uiState.value.onStageNow) @@ -332,20 +332,20 @@ class AudioRoomViewModelTest { @Test fun publishingNowDerivesFromBroadcastStateAndMute() { // Idle / connecting / failed: never publishing. - assertFalse(AudioRoomUiState().publishingNow) - assertFalse(AudioRoomUiState(broadcast = BroadcastUiState.Connecting).publishingNow) - assertFalse(AudioRoomUiState(broadcast = BroadcastUiState.Failed("boom")).publishingNow) + assertFalse(NestUiState().publishingNow) + assertFalse(NestUiState(broadcast = BroadcastUiState.Connecting).publishingNow) + assertFalse(NestUiState(broadcast = BroadcastUiState.Failed("boom")).publishingNow) // Broadcasting unmuted: publishing. assertTrue( - AudioRoomUiState(broadcast = BroadcastUiState.Broadcasting(isMuted = false)).publishingNow, + NestUiState(broadcast = BroadcastUiState.Broadcasting(isMuted = false)).publishingNow, ) // Broadcasting muted: NOT publishing — matches the wire-tag // semantics ("publishing=1" means actually pushing packets, // not "hold a slot but silenced"). assertFalse( - AudioRoomUiState(broadcast = BroadcastUiState.Broadcasting(isMuted = true)).publishingNow, + NestUiState(broadcast = BroadcastUiState.Broadcasting(isMuted = true)).publishingNow, ) } @@ -425,8 +425,8 @@ class AudioRoomViewModelTest { ) } - private fun TestScope.newViewModel(connect: suspend (CoroutineScope) -> NestsListener): AudioRoomViewModel = - AudioRoomViewModel( + private fun TestScope.newViewModel(connect: suspend (CoroutineScope) -> NestsListener): NestViewModel = + NestViewModel( httpClient = NoopNestsClient, transport = NoopWebTransportFactory, decoderFactory = { NoopOpusDecoder }, @@ -452,7 +452,7 @@ class AudioRoomViewModelTest { mutable.value = s } - override suspend fun subscribeSpeaker(speakerPubkeyHex: String): SubscribeHandle = error("subscribeSpeaker not exercised in these tests — see AudioRoomPlayerTest in :nestsClient") + override suspend fun subscribeSpeaker(speakerPubkeyHex: String): SubscribeHandle = error("subscribeSpeaker not exercised in these tests — see NestPlayerTest in :nestsClient") override suspend fun close() { closeCallCount++ diff --git a/nestsClient/src/commonMain/kotlin/com/vitorpamplona/nestsclient/MoqLiteNestsListener.kt b/nestsClient/src/commonMain/kotlin/com/vitorpamplona/nestsclient/MoqLiteNestsListener.kt index 01db9a504..07a1be7ef 100644 --- a/nestsClient/src/commonMain/kotlin/com/vitorpamplona/nestsclient/MoqLiteNestsListener.kt +++ b/nestsClient/src/commonMain/kotlin/com/vitorpamplona/nestsclient/MoqLiteNestsListener.kt @@ -38,7 +38,7 @@ import java.util.concurrent.atomic.AtomicLong * Moq-lite-backed [NestsListener]. Wraps a connected [MoqLiteSession] * and exposes the same listener API the IETF [DefaultNestsListener] * does, so [connectNestsListener] can swap the framing layer without - * changing the public surface that [com.vitorpamplona.amethyst.commons.viewmodels.AudioRoomViewModel] + * changing the public surface that [com.vitorpamplona.amethyst.commons.viewmodels.NestViewModel] * and downstream UI consume. * * Subscription mapping per the audio-rooms NIP draft + nests JS diff --git a/nestsClient/src/commonMain/kotlin/com/vitorpamplona/nestsclient/MoqLiteNestsSpeaker.kt b/nestsClient/src/commonMain/kotlin/com/vitorpamplona/nestsclient/MoqLiteNestsSpeaker.kt index 4e37e980c..1d6a36c5e 100644 --- a/nestsClient/src/commonMain/kotlin/com/vitorpamplona/nestsclient/MoqLiteNestsSpeaker.kt +++ b/nestsClient/src/commonMain/kotlin/com/vitorpamplona/nestsclient/MoqLiteNestsSpeaker.kt @@ -21,7 +21,7 @@ package com.vitorpamplona.nestsclient import com.vitorpamplona.nestsclient.audio.AudioCapture -import com.vitorpamplona.nestsclient.audio.AudioRoomMoqLiteBroadcaster +import com.vitorpamplona.nestsclient.audio.NestMoqLiteBroadcaster import com.vitorpamplona.nestsclient.audio.OpusEncoder import com.vitorpamplona.nestsclient.moq.lite.MoqLitePublisherHandle import com.vitorpamplona.nestsclient.moq.lite.MoqLiteSession @@ -76,7 +76,7 @@ class MoqLiteNestsSpeaker internal constructor( throw t } val broadcaster = - AudioRoomMoqLiteBroadcaster( + NestMoqLiteBroadcaster( capture = captureFactory(), encoder = encoderFactory(), publisher = publisher, @@ -139,7 +139,7 @@ class MoqLiteNestsSpeaker internal constructor( } internal class MoqLiteBroadcastHandle( - private val broadcaster: AudioRoomMoqLiteBroadcaster, + private val broadcaster: NestMoqLiteBroadcaster, private val publisher: MoqLitePublisherHandle, private val parent: MoqLiteNestsSpeaker, ) : BroadcastHandle { diff --git a/nestsClient/src/commonMain/kotlin/com/vitorpamplona/nestsclient/NestsSpeaker.kt b/nestsClient/src/commonMain/kotlin/com/vitorpamplona/nestsclient/NestsSpeaker.kt index 0e59cb7cd..28d15a9d7 100644 --- a/nestsClient/src/commonMain/kotlin/com/vitorpamplona/nestsclient/NestsSpeaker.kt +++ b/nestsClient/src/commonMain/kotlin/com/vitorpamplona/nestsclient/NestsSpeaker.kt @@ -21,7 +21,7 @@ package com.vitorpamplona.nestsclient import com.vitorpamplona.nestsclient.audio.AudioCapture -import com.vitorpamplona.nestsclient.audio.AudioRoomBroadcaster +import com.vitorpamplona.nestsclient.audio.NestBroadcaster import com.vitorpamplona.nestsclient.audio.OpusEncoder import com.vitorpamplona.nestsclient.moq.MoqProtocolException import com.vitorpamplona.nestsclient.moq.MoqSession @@ -133,7 +133,7 @@ sealed class NestsSpeakerState { * unit-test suite (`NestsSpeakerTest`) and for any future IETF * MoQ-transport target. * - * Wraps a connected [MoqSession] and plumbs an [AudioRoomBroadcaster] + * Wraps a connected [MoqSession] and plumbs an [NestBroadcaster] * through it on [startBroadcasting]. Construction does NOT open the * transport. */ @@ -168,7 +168,7 @@ class DefaultNestsSpeaker internal constructor( throw t } val broadcaster = - AudioRoomBroadcaster( + NestBroadcaster( capture = captureFactory(), encoder = encoderFactory(), publisher = publisher, @@ -236,7 +236,7 @@ class DefaultNestsSpeaker internal constructor( } internal class DefaultBroadcastHandle( - private val broadcaster: AudioRoomBroadcaster, + private val broadcaster: NestBroadcaster, private val announce: MoqSession.AnnounceHandle, private val parent: DefaultNestsSpeaker, ) : BroadcastHandle { diff --git a/nestsClient/src/commonMain/kotlin/com/vitorpamplona/nestsclient/audio/AudioRoomBroadcaster.kt b/nestsClient/src/commonMain/kotlin/com/vitorpamplona/nestsclient/audio/NestBroadcaster.kt similarity index 96% rename from nestsClient/src/commonMain/kotlin/com/vitorpamplona/nestsclient/audio/AudioRoomBroadcaster.kt rename to nestsClient/src/commonMain/kotlin/com/vitorpamplona/nestsclient/audio/NestBroadcaster.kt index 45cddbd77..7875bd6a5 100644 --- a/nestsClient/src/commonMain/kotlin/com/vitorpamplona/nestsclient/audio/AudioRoomBroadcaster.kt +++ b/nestsClient/src/commonMain/kotlin/com/vitorpamplona/nestsclient/audio/NestBroadcaster.kt @@ -28,7 +28,7 @@ import kotlinx.coroutines.cancelAndJoin import kotlinx.coroutines.launch /** - * Inverse of [AudioRoomPlayer]: pulls PCM from an [AudioCapture], runs it + * Inverse of [NestPlayer]: pulls PCM from an [AudioCapture], runs it * through an [OpusEncoder], and pushes the resulting Opus packets into a * [MoqSession.TrackPublisher] as MoQ OBJECT_DATAGRAMs. * @@ -46,7 +46,7 @@ import kotlinx.coroutines.launch * Encode failures are reported via [onError] but do NOT tear the loop down — * one bad frame shouldn't end the broadcast. */ -class AudioRoomBroadcaster( +class NestBroadcaster( private val capture: AudioCapture, private val encoder: OpusEncoder, private val publisher: MoqSession.TrackPublisher, @@ -66,8 +66,8 @@ class AudioRoomBroadcaster( * surface it to the user. */ fun start(onError: (AudioException) -> Unit = { /* swallow */ }) { - check(!stopped) { "AudioRoomBroadcaster already stopped" } - check(job == null) { "AudioRoomBroadcaster.start already called" } + check(!stopped) { "NestBroadcaster already stopped" } + check(job == null) { "NestBroadcaster.start already called" } // Audit round-2 MoQ #7: capture.start() can throw before we have // a job. Mark stopped + propagate so a half-started capture isn't diff --git a/nestsClient/src/commonMain/kotlin/com/vitorpamplona/nestsclient/audio/AudioRoomMoqLiteBroadcaster.kt b/nestsClient/src/commonMain/kotlin/com/vitorpamplona/nestsclient/audio/NestMoqLiteBroadcaster.kt similarity index 95% rename from nestsClient/src/commonMain/kotlin/com/vitorpamplona/nestsclient/audio/AudioRoomMoqLiteBroadcaster.kt rename to nestsClient/src/commonMain/kotlin/com/vitorpamplona/nestsclient/audio/NestMoqLiteBroadcaster.kt index e08e51c2e..276d51440 100644 --- a/nestsClient/src/commonMain/kotlin/com/vitorpamplona/nestsclient/audio/AudioRoomMoqLiteBroadcaster.kt +++ b/nestsClient/src/commonMain/kotlin/com/vitorpamplona/nestsclient/audio/NestMoqLiteBroadcaster.kt @@ -28,7 +28,7 @@ import kotlinx.coroutines.cancelAndJoin import kotlinx.coroutines.launch /** - * Mirror of [AudioRoomBroadcaster] but driving a moq-lite + * Mirror of [NestBroadcaster] but driving a moq-lite * [MoqLitePublisherHandle] instead of an IETF `MoqSession.TrackPublisher`. * Keeps the IETF broadcaster intact for the IETF unit-test suite while * letting the production speaker path use moq-lite. @@ -36,7 +36,7 @@ import kotlinx.coroutines.launch * Lifecycle and audit comments mirror the IETF version 1:1 — only the * sink type changes. */ -class AudioRoomMoqLiteBroadcaster( +class NestMoqLiteBroadcaster( private val capture: AudioCapture, private val encoder: OpusEncoder, private val publisher: MoqLitePublisherHandle, @@ -55,8 +55,8 @@ class AudioRoomMoqLiteBroadcaster( * the exception propagates. */ fun start(onError: (AudioException) -> Unit = { /* swallow */ }) { - check(!stopped) { "AudioRoomMoqLiteBroadcaster already stopped" } - check(job == null) { "AudioRoomMoqLiteBroadcaster.start already called" } + check(!stopped) { "NestMoqLiteBroadcaster already stopped" } + check(job == null) { "NestMoqLiteBroadcaster.start already called" } try { capture.start() diff --git a/nestsClient/src/commonMain/kotlin/com/vitorpamplona/nestsclient/audio/AudioRoomPlayer.kt b/nestsClient/src/commonMain/kotlin/com/vitorpamplona/nestsclient/audio/NestPlayer.kt similarity index 95% rename from nestsClient/src/commonMain/kotlin/com/vitorpamplona/nestsclient/audio/AudioRoomPlayer.kt rename to nestsClient/src/commonMain/kotlin/com/vitorpamplona/nestsclient/audio/NestPlayer.kt index f74af9267..8d2dc934f 100644 --- a/nestsClient/src/commonMain/kotlin/com/vitorpamplona/nestsclient/audio/AudioRoomPlayer.kt +++ b/nestsClient/src/commonMain/kotlin/com/vitorpamplona/nestsclient/audio/NestPlayer.kt @@ -33,7 +33,7 @@ import kotlinx.coroutines.launch * through an [OpusDecoder] into an [AudioPlayer]. * * Single-track. To play multiple speakers in a room, instantiate one - * [AudioRoomPlayer] per [com.vitorpamplona.nestsclient.moq.SubscribeHandle]; + * [NestPlayer] per [com.vitorpamplona.nestsclient.moq.SubscribeHandle]; * each owns its own decoder (Opus state is per-track). * * Lifecycle: @@ -41,7 +41,7 @@ import kotlinx.coroutines.launch * - [stop] cancels the decode loop, stops the player, and releases the * decoder. Idempotent. */ -class AudioRoomPlayer( +class NestPlayer( private val decoder: OpusDecoder, private val player: AudioPlayer, private val scope: CoroutineScope, @@ -61,8 +61,8 @@ class AudioRoomPlayer( objects: Flow, onError: (AudioException) -> Unit = { /* swallow */ }, ) { - check(!stopped) { "AudioRoomPlayer already stopped" } - check(job == null) { "AudioRoomPlayer.play already called" } + check(!stopped) { "NestPlayer already stopped" } + check(job == null) { "NestPlayer.play already called" } player.start() job = diff --git a/nestsClient/src/commonTest/kotlin/com/vitorpamplona/nestsclient/audio/AudioRoomBroadcasterTest.kt b/nestsClient/src/commonTest/kotlin/com/vitorpamplona/nestsclient/audio/NestBroadcasterTest.kt similarity index 93% rename from nestsClient/src/commonTest/kotlin/com/vitorpamplona/nestsclient/audio/AudioRoomBroadcasterTest.kt rename to nestsClient/src/commonTest/kotlin/com/vitorpamplona/nestsclient/audio/NestBroadcasterTest.kt index 7fe42e86d..d339f5944 100644 --- a/nestsClient/src/commonTest/kotlin/com/vitorpamplona/nestsclient/audio/AudioRoomBroadcasterTest.kt +++ b/nestsClient/src/commonTest/kotlin/com/vitorpamplona/nestsclient/audio/NestBroadcasterTest.kt @@ -28,14 +28,14 @@ import kotlin.test.assertContentEquals import kotlin.test.assertEquals import kotlin.test.assertTrue -class AudioRoomBroadcasterTest { +class NestBroadcasterTest { @Test fun pcm_frames_flow_through_encoder_into_publisher_in_order() = runTest { val capture = ScriptedCapture(listOf(shortArrayOf(1), shortArrayOf(2), shortArrayOf(3))) val encoder = ScriptedEncoder(prefix = byteArrayOf(0xAA.toByte())) val publisher = RecordingPublisher("track") - val broadcaster = AudioRoomBroadcaster(capture, encoder, publisher, backgroundScope) + val broadcaster = NestBroadcaster(capture, encoder, publisher, backgroundScope) broadcaster.start() // Capture exhausts after 3 frames (readFrame returns null) so the @@ -61,7 +61,7 @@ class AudioRoomBroadcasterTest { val capture = ScriptedCapture(listOf(shortArrayOf(1), shortArrayOf(2), shortArrayOf(3))) val encoder = ScriptedEncoder(prefix = byteArrayOf(0xBB.toByte())) val publisher = RecordingPublisher("track") - val broadcaster = AudioRoomBroadcaster(capture, encoder, publisher, backgroundScope) + val broadcaster = NestBroadcaster(capture, encoder, publisher, backgroundScope) broadcaster.setMuted(true) broadcaster.start() @@ -81,7 +81,7 @@ class AudioRoomBroadcasterTest { val capture = ScriptedCapture(listOf(shortArrayOf(1), shortArrayOf(2))) val encoder = ScriptedEncoder(prefix = byteArrayOf(0xCC.toByte()), warmupSkips = 1) val publisher = RecordingPublisher("track") - val broadcaster = AudioRoomBroadcaster(capture, encoder, publisher, backgroundScope) + val broadcaster = NestBroadcaster(capture, encoder, publisher, backgroundScope) broadcaster.start() capture.awaitDrained() @@ -100,7 +100,7 @@ class AudioRoomBroadcasterTest { val capture = ScriptedCapture(listOf(shortArrayOf(1), shortArrayOf(2), shortArrayOf(3))) val encoder = ScriptedEncoder(prefix = byteArrayOf(0xDD.toByte()), failOnNthCall = 1) val publisher = RecordingPublisher("track") - val broadcaster = AudioRoomBroadcaster(capture, encoder, publisher, backgroundScope) + val broadcaster = NestBroadcaster(capture, encoder, publisher, backgroundScope) val errors = mutableListOf() broadcaster.start { errors.add(it) } @@ -117,7 +117,7 @@ class AudioRoomBroadcasterTest { val capture = ScriptedCapture(listOf(shortArrayOf(1))) val encoder = ScriptedEncoder(prefix = byteArrayOf(0xEE.toByte())) val publisher = RecordingPublisher("track") - val broadcaster = AudioRoomBroadcaster(capture, encoder, publisher, backgroundScope) + val broadcaster = NestBroadcaster(capture, encoder, publisher, backgroundScope) broadcaster.start() capture.awaitDrained() diff --git a/nestsClient/src/commonTest/kotlin/com/vitorpamplona/nestsclient/audio/AudioRoomPlayerTest.kt b/nestsClient/src/commonTest/kotlin/com/vitorpamplona/nestsclient/audio/NestPlayerTest.kt similarity index 95% rename from nestsClient/src/commonTest/kotlin/com/vitorpamplona/nestsclient/audio/AudioRoomPlayerTest.kt rename to nestsClient/src/commonTest/kotlin/com/vitorpamplona/nestsclient/audio/NestPlayerTest.kt index 9023bb887..2f5de48ef 100644 --- a/nestsClient/src/commonTest/kotlin/com/vitorpamplona/nestsclient/audio/AudioRoomPlayerTest.kt +++ b/nestsClient/src/commonTest/kotlin/com/vitorpamplona/nestsclient/audio/NestPlayerTest.kt @@ -31,7 +31,7 @@ import kotlin.test.assertEquals import kotlin.test.assertFailsWith import kotlin.test.assertTrue -class AudioRoomPlayerTest { +class NestPlayerTest { @Test fun every_object_payload_is_decoded_and_enqueued_in_order() = runTest { @@ -45,7 +45,7 @@ class AudioRoomPlayerTest { moqObject(byteArrayOf(0x04, 0x05, 0x06)), ) - val sut = AudioRoomPlayer(decoder, player, this) + val sut = NestPlayer(decoder, player, this) sut.play(objects) testScheduler.advanceUntilIdle() @@ -83,7 +83,7 @@ class AudioRoomPlayerTest { moqObject(byteArrayOf(0x02)), ) - val sut = AudioRoomPlayer(decoder, player, this) + val sut = NestPlayer(decoder, player, this) sut.play(objects, onError = { errors.add(it) }) testScheduler.advanceUntilIdle() @@ -102,7 +102,7 @@ class AudioRoomPlayerTest { runTest { val decoder = FakeOpusDecoder { byteToShorts(it) } val player = FakeAudioPlayer() - val sut = AudioRoomPlayer(decoder, player, this) + val sut = NestPlayer(decoder, player, this) sut.play(flowOf()) testScheduler.advanceUntilIdle() sut.stop() @@ -115,7 +115,7 @@ class AudioRoomPlayerTest { fun play_cannot_be_called_twice_on_the_same_instance() = runTest { val sut = - AudioRoomPlayer( + NestPlayer( FakeOpusDecoder { byteToShorts(it) }, FakeAudioPlayer(), this, @@ -129,7 +129,7 @@ class AudioRoomPlayerTest { fun play_after_stop_is_rejected() = runTest { val sut = - AudioRoomPlayer( + NestPlayer( FakeOpusDecoder { byteToShorts(it) }, FakeAudioPlayer(), this, @@ -143,7 +143,7 @@ class AudioRoomPlayerTest { runTest { val decoder = FakeOpusDecoder { ShortArray(0) } val player = FakeAudioPlayer() - val sut = AudioRoomPlayer(decoder, player, this) + val sut = NestPlayer(decoder, player, this) sut.play(flowOf(moqObject(byteArrayOf(0x01)))) testScheduler.advanceUntilIdle() assertEquals(0, player.queued.size) @@ -157,7 +157,7 @@ class AudioRoomPlayerTest { val decoder = FakeOpusDecoder { byteToShorts(it) } val player = FakeAudioPlayer() - val sut = AudioRoomPlayer(decoder, player, this) + val sut = NestPlayer(decoder, player, this) sut.play(channel.receiveAsFlow()) testScheduler.runCurrent() diff --git a/nestsClient/src/jvmTest/kotlin/com/vitorpamplona/nestsclient/interop/NostrNestsMuteInteropTest.kt b/nestsClient/src/jvmTest/kotlin/com/vitorpamplona/nestsclient/interop/NostrNestsMuteInteropTest.kt index 5913cb2e4..c12b6b633 100644 --- a/nestsClient/src/jvmTest/kotlin/com/vitorpamplona/nestsclient/interop/NostrNestsMuteInteropTest.kt +++ b/nestsClient/src/jvmTest/kotlin/com/vitorpamplona/nestsclient/interop/NostrNestsMuteInteropTest.kt @@ -51,7 +51,7 @@ import kotlin.test.fail * - the broadcaster keeps the capture pump running while muted (so * unmute is sample-accurate) * - frames pushed during mute do NOT reach subscribers (`if (muted) - * continue` in [com.vitorpamplona.nestsclient.audio.AudioRoomMoqLiteBroadcaster]) + * continue` in [com.vitorpamplona.nestsclient.audio.NestMoqLiteBroadcaster]) * - frames pushed before / after the muted window DO reach * subscribers, with the muted ones missing entirely (no silent * placeholder frames) diff --git a/nestsClient/src/jvmTest/kotlin/com/vitorpamplona/nestsclient/interop/NostrNestsRoundTripInteropTest.kt b/nestsClient/src/jvmTest/kotlin/com/vitorpamplona/nestsclient/interop/NostrNestsRoundTripInteropTest.kt index 027fb8572..15a68f876 100644 --- a/nestsClient/src/jvmTest/kotlin/com/vitorpamplona/nestsclient/interop/NostrNestsRoundTripInteropTest.kt +++ b/nestsClient/src/jvmTest/kotlin/com/vitorpamplona/nestsclient/interop/NostrNestsRoundTripInteropTest.kt @@ -23,7 +23,7 @@ package com.vitorpamplona.nestsclient.interop import com.vitorpamplona.nestsclient.NestsRoomConfig import com.vitorpamplona.nestsclient.OkHttpNestsClient import com.vitorpamplona.nestsclient.audio.AudioCapture -import com.vitorpamplona.nestsclient.audio.AudioRoomMoqLiteBroadcaster +import com.vitorpamplona.nestsclient.audio.NestMoqLiteBroadcaster import com.vitorpamplona.nestsclient.audio.OpusEncoder import com.vitorpamplona.nestsclient.connectNestsListener import com.vitorpamplona.nestsclient.connectNestsSpeaker @@ -57,7 +57,7 @@ import kotlin.test.fail * (`MoqLitePublisherHandle`), the listener subscribes by speaker * pubkey (`broadcast=pubkey`, `track="audio/data"`), the speaker * pushes deterministic Opus-shaped payloads through the - * [AudioRoomMoqLiteBroadcaster] pipeline, and the listener collects + * [NestMoqLiteBroadcaster] pipeline, and the listener collects * them via [SubscribeHandle.objects] (which the moq-lite adapter * wraps over `MoqLiteFrame` so existing decoder / player code keeps * working). diff --git a/quartz/src/commonMain/kotlin/com/vitorpamplona/quartz/experimental/audiorooms/admin/AdminCommandEvent.kt b/quartz/src/commonMain/kotlin/com/vitorpamplona/quartz/experimental/nests/admin/AdminCommandEvent.kt similarity index 98% rename from quartz/src/commonMain/kotlin/com/vitorpamplona/quartz/experimental/audiorooms/admin/AdminCommandEvent.kt rename to quartz/src/commonMain/kotlin/com/vitorpamplona/quartz/experimental/nests/admin/AdminCommandEvent.kt index e5e7b9a7c..0c04bd355 100644 --- a/quartz/src/commonMain/kotlin/com/vitorpamplona/quartz/experimental/audiorooms/admin/AdminCommandEvent.kt +++ b/quartz/src/commonMain/kotlin/com/vitorpamplona/quartz/experimental/nests/admin/AdminCommandEvent.kt @@ -18,7 +18,7 @@ * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -package com.vitorpamplona.quartz.experimental.audiorooms.admin +package com.vitorpamplona.quartz.experimental.nests.admin import androidx.compose.runtime.Immutable import com.vitorpamplona.quartz.nip01Core.core.Event diff --git a/quartz/src/commonMain/kotlin/com/vitorpamplona/quartz/nip53LiveActivities/nestsServers/NestsServersEvent.kt b/quartz/src/commonMain/kotlin/com/vitorpamplona/quartz/nip53LiveActivities/nestsServers/NestsServersEvent.kt index 3dc19e1ff..b38277b18 100644 --- a/quartz/src/commonMain/kotlin/com/vitorpamplona/quartz/nip53LiveActivities/nestsServers/NestsServersEvent.kt +++ b/quartz/src/commonMain/kotlin/com/vitorpamplona/quartz/nip53LiveActivities/nestsServers/NestsServersEvent.kt @@ -50,7 +50,7 @@ import com.vitorpamplona.quartz.utils.TimeUtils * } * * The `server` URL points at the moq-rs / moq-auth deployment's base - * URL — Amethyst's `CreateAudioRoomSheet` uses it for both the + * URL — Amethyst's `CreateNestSheet` uses it for both the * `service` (auth sidecar) and `endpoint` (WebTransport relay) tags * on the kind-30312 event, since nostrnests's reference deployment * co-locates them. A future revision can split the two into separate diff --git a/quartz/src/commonMain/kotlin/com/vitorpamplona/quartz/utils/EventFactory.kt b/quartz/src/commonMain/kotlin/com/vitorpamplona/quartz/utils/EventFactory.kt index 86136e116..d3b80ffe7 100644 --- a/quartz/src/commonMain/kotlin/com/vitorpamplona/quartz/utils/EventFactory.kt +++ b/quartz/src/commonMain/kotlin/com/vitorpamplona/quartz/utils/EventFactory.kt @@ -28,7 +28,6 @@ import com.vitorpamplona.quartz.experimental.attestations.recommendation.Attesto import com.vitorpamplona.quartz.experimental.attestations.request.AttestationRequestEvent import com.vitorpamplona.quartz.experimental.audio.header.AudioHeaderEvent import com.vitorpamplona.quartz.experimental.audio.track.AudioTrackEvent -import com.vitorpamplona.quartz.experimental.audiorooms.admin.AdminCommandEvent import com.vitorpamplona.quartz.experimental.edits.TextNoteModificationEvent import com.vitorpamplona.quartz.experimental.ephemChat.chat.EphemeralChatEvent import com.vitorpamplona.quartz.experimental.ephemChat.list.EphemeralChatListEvent @@ -36,6 +35,7 @@ import com.vitorpamplona.quartz.experimental.interactiveStories.InteractiveStory import com.vitorpamplona.quartz.experimental.interactiveStories.InteractiveStoryReadingStateEvent import com.vitorpamplona.quartz.experimental.interactiveStories.InteractiveStorySceneEvent import com.vitorpamplona.quartz.experimental.medical.FhirResourceEvent +import com.vitorpamplona.quartz.experimental.nests.admin.AdminCommandEvent import com.vitorpamplona.quartz.experimental.nip82SoftwareApps.application.SoftwareApplicationEvent import com.vitorpamplona.quartz.experimental.nip82SoftwareApps.asset.SoftwareAssetEvent import com.vitorpamplona.quartz.experimental.nip95.data.FileStorageEvent diff --git a/quartz/src/commonTest/kotlin/com/vitorpamplona/quartz/experimental/audiorooms/admin/AdminCommandEventTest.kt b/quartz/src/commonTest/kotlin/com/vitorpamplona/quartz/experimental/nests/admin/AdminCommandEventTest.kt similarity index 98% rename from quartz/src/commonTest/kotlin/com/vitorpamplona/quartz/experimental/audiorooms/admin/AdminCommandEventTest.kt rename to quartz/src/commonTest/kotlin/com/vitorpamplona/quartz/experimental/nests/admin/AdminCommandEventTest.kt index 5a7f83687..2367bfc94 100644 --- a/quartz/src/commonTest/kotlin/com/vitorpamplona/quartz/experimental/audiorooms/admin/AdminCommandEventTest.kt +++ b/quartz/src/commonTest/kotlin/com/vitorpamplona/quartz/experimental/nests/admin/AdminCommandEventTest.kt @@ -18,7 +18,7 @@ * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -package com.vitorpamplona.quartz.experimental.audiorooms.admin +package com.vitorpamplona.quartz.experimental.nests.admin import com.vitorpamplona.quartz.nip01Core.tags.aTag.ATag import kotlin.test.Test