Removes the implementation of custom designs because our screens get too dark
This commit is contained in:
+206
-210
@@ -70,7 +70,6 @@ import com.vitorpamplona.amethyst.commons.viewmodels.BroadcastUiState
|
|||||||
import com.vitorpamplona.amethyst.commons.viewmodels.ConnectionUiState
|
import com.vitorpamplona.amethyst.commons.viewmodels.ConnectionUiState
|
||||||
import com.vitorpamplona.amethyst.commons.viewmodels.NestUiState
|
import com.vitorpamplona.amethyst.commons.viewmodels.NestUiState
|
||||||
import com.vitorpamplona.amethyst.commons.viewmodels.NestViewModel
|
import com.vitorpamplona.amethyst.commons.viewmodels.NestViewModel
|
||||||
import com.vitorpamplona.amethyst.commons.viewmodels.RoomTheme
|
|
||||||
import com.vitorpamplona.amethyst.commons.viewmodels.buildParticipantGrid
|
import com.vitorpamplona.amethyst.commons.viewmodels.buildParticipantGrid
|
||||||
import com.vitorpamplona.amethyst.ui.navigation.topbars.ShorterTopAppBar
|
import com.vitorpamplona.amethyst.ui.navigation.topbars.ShorterTopAppBar
|
||||||
import com.vitorpamplona.amethyst.ui.screen.loggedIn.AccountViewModel
|
import com.vitorpamplona.amethyst.ui.screen.loggedIn.AccountViewModel
|
||||||
@@ -103,228 +102,225 @@ internal fun NestFullScreen(
|
|||||||
onHandRaisedChange: (Boolean) -> Unit,
|
onHandRaisedChange: (Boolean) -> Unit,
|
||||||
onLeave: () -> Unit,
|
onLeave: () -> Unit,
|
||||||
) {
|
) {
|
||||||
val roomTheme = androidx.compose.runtime.remember(event) { RoomTheme.from(event) }
|
var showEditSheet by rememberSaveable { mutableStateOf(false) }
|
||||||
NestThemedScope(theme = roomTheme, accountViewModel = accountViewModel) {
|
var showHostMenu by rememberSaveable { mutableStateOf(false) }
|
||||||
var showEditSheet by rememberSaveable { mutableStateOf(false) }
|
var showHostLeaveConfirm by rememberSaveable { mutableStateOf(false) }
|
||||||
var showHostMenu by rememberSaveable { mutableStateOf(false) }
|
val isHost = accountViewModel.account.signer.pubKey == event.pubKey
|
||||||
var showHostLeaveConfirm by rememberSaveable { mutableStateOf(false) }
|
val leaveScope = rememberCoroutineScope()
|
||||||
val isHost = accountViewModel.account.signer.pubKey == event.pubKey
|
val topBarContext = LocalContext.current
|
||||||
val leaveScope = rememberCoroutineScope()
|
|
||||||
val topBarContext = LocalContext.current
|
|
||||||
|
|
||||||
// Scaffold owns safeDrawing insets via its `contentWindowInsets`
|
// Scaffold owns safeDrawing insets via its `contentWindowInsets`
|
||||||
// default, so we don't manage them manually anymore. The
|
// default, so we don't manage them manually anymore. The
|
||||||
// container is transparent because NestThemedScope's outer
|
// container is transparent because NestThemedScope's outer
|
||||||
// Surface already paints the themed background (and overlays
|
// Surface already paints the themed background (and overlays
|
||||||
// the optional `bg` image on top of it); painting again here
|
// the optional `bg` image on top of it); painting again here
|
||||||
// would double up.
|
// would double up.
|
||||||
Scaffold(
|
Scaffold(
|
||||||
modifier = Modifier.fillMaxSize(),
|
modifier = Modifier.fillMaxSize(),
|
||||||
containerColor = Color.Transparent,
|
containerColor = Color.Transparent,
|
||||||
topBar = {
|
topBar = {
|
||||||
NestTopAppBar(
|
NestTopAppBar(
|
||||||
title = event.room().orEmpty(),
|
title = event.room().orEmpty(),
|
||||||
isHost = isHost,
|
isHost = isHost,
|
||||||
showHostMenu = showHostMenu,
|
showHostMenu = showHostMenu,
|
||||||
onMenuOpen = { showHostMenu = true },
|
onMenuOpen = { showHostMenu = true },
|
||||||
onMenuDismiss = { showHostMenu = false },
|
onMenuDismiss = { showHostMenu = false },
|
||||||
onShare = {
|
onShare = {
|
||||||
showHostMenu = false
|
showHostMenu = false
|
||||||
shareRoomNaddr(topBarContext, event)
|
shareRoomNaddr(topBarContext, event)
|
||||||
},
|
},
|
||||||
onEdit = {
|
onEdit = {
|
||||||
showHostMenu = false
|
showHostMenu = false
|
||||||
showEditSheet = true
|
showEditSheet = true
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
},
|
},
|
||||||
) { padding ->
|
) { padding ->
|
||||||
// Inner column is just the two weighted siblings — top
|
// Inner column is just the two weighted siblings — top
|
||||||
// metadata (scrolls internally if overflow) and the chat
|
// metadata (scrolls internally if overflow) and the chat
|
||||||
// panel (takes the rest). Title and overflow menu live in
|
// panel (takes the rest). Title and overflow menu live in
|
||||||
// the TopAppBar above.
|
// the TopAppBar above.
|
||||||
|
Column(
|
||||||
|
modifier =
|
||||||
|
Modifier
|
||||||
|
.fillMaxSize()
|
||||||
|
.padding(padding),
|
||||||
|
) {
|
||||||
Column(
|
Column(
|
||||||
modifier =
|
modifier =
|
||||||
Modifier
|
Modifier
|
||||||
.fillMaxSize()
|
.weight(1f)
|
||||||
.padding(padding),
|
.verticalScroll(rememberScrollState())
|
||||||
|
.padding(horizontal = 16.dp),
|
||||||
) {
|
) {
|
||||||
Column(
|
event.summary()?.let {
|
||||||
modifier =
|
Text(
|
||||||
Modifier
|
text = it,
|
||||||
.weight(1f)
|
style = MaterialTheme.typography.bodyMedium,
|
||||||
.verticalScroll(rememberScrollState())
|
color = MaterialTheme.colorScheme.onSurfaceVariant,
|
||||||
.padding(horizontal = 16.dp),
|
|
||||||
) {
|
|
||||||
event.summary()?.let {
|
|
||||||
Text(
|
|
||||||
text = it,
|
|
||||||
style = MaterialTheme.typography.bodyMedium,
|
|
||||||
color = MaterialTheme.colorScheme.onSurfaceVariant,
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Listener counter — counts every active kind-10312 presence
|
|
||||||
// in the room. Hidden until the aggregator has at least one
|
|
||||||
// entry so the placeholder doesn't flash on entry.
|
|
||||||
val presences by viewModel.presences.collectAsState()
|
|
||||||
|
|
||||||
val reactionsByPubkey by viewModel.recentReactions.collectAsState()
|
|
||||||
var hostMenuTarget by rememberSaveable { mutableStateOf<String?>(null) }
|
|
||||||
// Long-press opens the participant context sheet for ANYONE
|
|
||||||
// (T2 #2). The sheet's own gating decides which rows to show
|
|
||||||
// (follow/mute always; promote/demote/kick host-only).
|
|
||||||
val onLongPressParticipant: ((String) -> Unit) = { target ->
|
|
||||||
if (target != accountViewModel.account.signer.pubKey) hostMenuTarget = target
|
|
||||||
}
|
|
||||||
// Tier-2 #1: replace the two LazyRow sections with a single
|
|
||||||
// pure-projection ParticipantGrid. The `absent` flag (member
|
|
||||||
// promoted in the kind-30312 but never emitted a kind-10312)
|
|
||||||
// greys out at 50 % alpha, matching nostrnests' web client.
|
|
||||||
val participantGrid =
|
|
||||||
androidx.compose.runtime.remember(event, presences) {
|
|
||||||
buildParticipantGrid(
|
|
||||||
participants = event.participants(),
|
|
||||||
presences = presences,
|
|
||||||
)
|
|
||||||
}
|
|
||||||
ParticipantsGrid(
|
|
||||||
grid = participantGrid,
|
|
||||||
speakingNow = ui.speakingNow,
|
|
||||||
accountViewModel = accountViewModel,
|
|
||||||
onStageLabel = stringRes(R.string.nest_stage),
|
|
||||||
audienceLabel = stringRes(R.string.nest_audience),
|
|
||||||
reactionsByPubkey = reactionsByPubkey,
|
|
||||||
connectingSpeakers = ui.connectingSpeakers,
|
|
||||||
onLongPressParticipant = onLongPressParticipant,
|
|
||||||
)
|
)
|
||||||
val speakerCatalogs by viewModel.speakerCatalogs.collectAsState()
|
|
||||||
hostMenuTarget?.let { target ->
|
|
||||||
ParticipantHostActionsSheet(
|
|
||||||
target = target,
|
|
||||||
event = event,
|
|
||||||
accountViewModel = accountViewModel,
|
|
||||||
onDismiss = { hostMenuTarget = null },
|
|
||||||
catalog = speakerCatalogs[target],
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
if (isHost) {
|
|
||||||
HandRaiseQueueSection(
|
|
||||||
event = event,
|
|
||||||
viewModel = viewModel,
|
|
||||||
accountViewModel = accountViewModel,
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
ConnectionRow(viewModel = viewModel, ui = ui)
|
|
||||||
|
|
||||||
val myPubkey = accountViewModel.account.signer.pubKey
|
|
||||||
if (viewModel.canBroadcast && onStage.any { it.pubKey == myPubkey }) {
|
|
||||||
TalkRow(viewModel = viewModel, ui = ui, speakerPubkeyHex = myPubkey)
|
|
||||||
}
|
|
||||||
|
|
||||||
var showReactionPicker by rememberSaveable { mutableStateOf(false) }
|
|
||||||
Row(
|
|
||||||
modifier = Modifier.fillMaxWidth().padding(top = 8.dp),
|
|
||||||
horizontalArrangement = Arrangement.SpaceBetween,
|
|
||||||
verticalAlignment = Alignment.CenterVertically,
|
|
||||||
) {
|
|
||||||
FilledTonalIconToggleButton(
|
|
||||||
checked = handRaised,
|
|
||||||
onCheckedChange = onHandRaisedChange,
|
|
||||||
) {
|
|
||||||
Icon(
|
|
||||||
symbol = MaterialSymbols.PanTool,
|
|
||||||
contentDescription =
|
|
||||||
stringRes(
|
|
||||||
if (handRaised) R.string.nest_lower_hand else R.string.nest_raise_hand,
|
|
||||||
),
|
|
||||||
)
|
|
||||||
}
|
|
||||||
OutlinedButton(onClick = { showReactionPicker = true }) {
|
|
||||||
Text(stringRes(R.string.nest_reactions_button))
|
|
||||||
}
|
|
||||||
OutlinedButton(
|
|
||||||
onClick = {
|
|
||||||
if (isHost) {
|
|
||||||
showHostLeaveConfirm = true
|
|
||||||
} else {
|
|
||||||
onLeave()
|
|
||||||
}
|
|
||||||
},
|
|
||||||
) {
|
|
||||||
Text(stringRes(R.string.nest_leave))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (showReactionPicker) {
|
|
||||||
RoomReactionPickerSheet(
|
|
||||||
onPick = { emoji ->
|
|
||||||
accountViewModel.reactToOrDelete(roomNote, emoji)
|
|
||||||
},
|
|
||||||
onDismiss = { showReactionPicker = false },
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
if (showHostLeaveConfirm) {
|
|
||||||
AlertDialog(
|
|
||||||
onDismissRequest = { showHostLeaveConfirm = false },
|
|
||||||
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),
|
|
||||||
onClick = {
|
|
||||||
showHostLeaveConfirm = false
|
|
||||||
leaveScope.launch {
|
|
||||||
val ok = closeMeetingSpace(accountViewModel, event)
|
|
||||||
if (!ok) {
|
|
||||||
accountViewModel.toastManager.toast(
|
|
||||||
R.string.nests,
|
|
||||||
R.string.nest_leave_host_close_failed,
|
|
||||||
)
|
|
||||||
}
|
|
||||||
onLeave()
|
|
||||||
}
|
|
||||||
},
|
|
||||||
) {
|
|
||||||
Text(stringRes(R.string.nest_leave_host_close))
|
|
||||||
}
|
|
||||||
},
|
|
||||||
dismissButton = {
|
|
||||||
TextButton(
|
|
||||||
onClick = {
|
|
||||||
showHostLeaveConfirm = false
|
|
||||||
onLeave()
|
|
||||||
},
|
|
||||||
) {
|
|
||||||
Text(stringRes(R.string.nest_leave_host_just_leave))
|
|
||||||
}
|
|
||||||
},
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
NestChatPanel(
|
// Listener counter — counts every active kind-10312 presence
|
||||||
event = event,
|
// in the room. Hidden until the aggregator has at least one
|
||||||
viewModel = viewModel,
|
// entry so the placeholder doesn't flash on entry.
|
||||||
accountViewModel = accountViewModel,
|
val presences by viewModel.presences.collectAsState()
|
||||||
modifier = Modifier.weight(1f),
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// EditNestSheet renders as a ModalBottomSheet — placement in
|
val reactionsByPubkey by viewModel.recentReactions.collectAsState()
|
||||||
// the tree doesn't affect layout, but keeping it adjacent to
|
var hostMenuTarget by rememberSaveable { mutableStateOf<String?>(null) }
|
||||||
// the Scaffold makes the dialog/sheet boundary obvious.
|
// Long-press opens the participant context sheet for ANYONE
|
||||||
if (showEditSheet) {
|
// (T2 #2). The sheet's own gating decides which rows to show
|
||||||
EditNestSheet(
|
// (follow/mute always; promote/demote/kick host-only).
|
||||||
accountViewModel = accountViewModel,
|
val onLongPressParticipant: ((String) -> Unit) = { target ->
|
||||||
|
if (target != accountViewModel.account.signer.pubKey) hostMenuTarget = target
|
||||||
|
}
|
||||||
|
// Tier-2 #1: replace the two LazyRow sections with a single
|
||||||
|
// pure-projection ParticipantGrid. The `absent` flag (member
|
||||||
|
// promoted in the kind-30312 but never emitted a kind-10312)
|
||||||
|
// greys out at 50 % alpha, matching nostrnests' web client.
|
||||||
|
val participantGrid =
|
||||||
|
androidx.compose.runtime.remember(event, presences) {
|
||||||
|
buildParticipantGrid(
|
||||||
|
participants = event.participants(),
|
||||||
|
presences = presences,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
ParticipantsGrid(
|
||||||
|
grid = participantGrid,
|
||||||
|
speakingNow = ui.speakingNow,
|
||||||
|
accountViewModel = accountViewModel,
|
||||||
|
onStageLabel = stringRes(R.string.nest_stage),
|
||||||
|
audienceLabel = stringRes(R.string.nest_audience),
|
||||||
|
reactionsByPubkey = reactionsByPubkey,
|
||||||
|
connectingSpeakers = ui.connectingSpeakers,
|
||||||
|
onLongPressParticipant = onLongPressParticipant,
|
||||||
|
)
|
||||||
|
val speakerCatalogs by viewModel.speakerCatalogs.collectAsState()
|
||||||
|
hostMenuTarget?.let { target ->
|
||||||
|
ParticipantHostActionsSheet(
|
||||||
|
target = target,
|
||||||
|
event = event,
|
||||||
|
accountViewModel = accountViewModel,
|
||||||
|
onDismiss = { hostMenuTarget = null },
|
||||||
|
catalog = speakerCatalogs[target],
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
if (isHost) {
|
||||||
|
HandRaiseQueueSection(
|
||||||
|
event = event,
|
||||||
|
viewModel = viewModel,
|
||||||
|
accountViewModel = accountViewModel,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
ConnectionRow(viewModel = viewModel, ui = ui)
|
||||||
|
|
||||||
|
val myPubkey = accountViewModel.account.signer.pubKey
|
||||||
|
if (viewModel.canBroadcast && onStage.any { it.pubKey == myPubkey }) {
|
||||||
|
TalkRow(viewModel = viewModel, ui = ui, speakerPubkeyHex = myPubkey)
|
||||||
|
}
|
||||||
|
|
||||||
|
var showReactionPicker by rememberSaveable { mutableStateOf(false) }
|
||||||
|
Row(
|
||||||
|
modifier = Modifier.fillMaxWidth().padding(top = 8.dp),
|
||||||
|
horizontalArrangement = Arrangement.SpaceBetween,
|
||||||
|
verticalAlignment = Alignment.CenterVertically,
|
||||||
|
) {
|
||||||
|
FilledTonalIconToggleButton(
|
||||||
|
checked = handRaised,
|
||||||
|
onCheckedChange = onHandRaisedChange,
|
||||||
|
) {
|
||||||
|
Icon(
|
||||||
|
symbol = MaterialSymbols.PanTool,
|
||||||
|
contentDescription =
|
||||||
|
stringRes(
|
||||||
|
if (handRaised) R.string.nest_lower_hand else R.string.nest_raise_hand,
|
||||||
|
),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
OutlinedButton(onClick = { showReactionPicker = true }) {
|
||||||
|
Text(stringRes(R.string.nest_reactions_button))
|
||||||
|
}
|
||||||
|
OutlinedButton(
|
||||||
|
onClick = {
|
||||||
|
if (isHost) {
|
||||||
|
showHostLeaveConfirm = true
|
||||||
|
} else {
|
||||||
|
onLeave()
|
||||||
|
}
|
||||||
|
},
|
||||||
|
) {
|
||||||
|
Text(stringRes(R.string.nest_leave))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (showReactionPicker) {
|
||||||
|
RoomReactionPickerSheet(
|
||||||
|
onPick = { emoji ->
|
||||||
|
accountViewModel.reactToOrDelete(roomNote, emoji)
|
||||||
|
},
|
||||||
|
onDismiss = { showReactionPicker = false },
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
if (showHostLeaveConfirm) {
|
||||||
|
AlertDialog(
|
||||||
|
onDismissRequest = { showHostLeaveConfirm = false },
|
||||||
|
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),
|
||||||
|
onClick = {
|
||||||
|
showHostLeaveConfirm = false
|
||||||
|
leaveScope.launch {
|
||||||
|
val ok = closeMeetingSpace(accountViewModel, event)
|
||||||
|
if (!ok) {
|
||||||
|
accountViewModel.toastManager.toast(
|
||||||
|
R.string.nests,
|
||||||
|
R.string.nest_leave_host_close_failed,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
onLeave()
|
||||||
|
}
|
||||||
|
},
|
||||||
|
) {
|
||||||
|
Text(stringRes(R.string.nest_leave_host_close))
|
||||||
|
}
|
||||||
|
},
|
||||||
|
dismissButton = {
|
||||||
|
TextButton(
|
||||||
|
onClick = {
|
||||||
|
showHostLeaveConfirm = false
|
||||||
|
onLeave()
|
||||||
|
},
|
||||||
|
) {
|
||||||
|
Text(stringRes(R.string.nest_leave_host_just_leave))
|
||||||
|
}
|
||||||
|
},
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
NestChatPanel(
|
||||||
event = event,
|
event = event,
|
||||||
onDismiss = { showEditSheet = false },
|
viewModel = viewModel,
|
||||||
|
accountViewModel = accountViewModel,
|
||||||
|
modifier = Modifier.weight(1f),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// EditNestSheet renders as a ModalBottomSheet — placement in
|
||||||
|
// the tree doesn't affect layout, but keeping it adjacent to
|
||||||
|
// the Scaffold makes the dialog/sheet boundary obvious.
|
||||||
|
if (showEditSheet) {
|
||||||
|
EditNestSheet(
|
||||||
|
accountViewModel = accountViewModel,
|
||||||
|
event = event,
|
||||||
|
onDismiss = { showEditSheet = false },
|
||||||
|
)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
Reference in New Issue
Block a user