feat(media): add server selector to compose dialog; update testing plan

Server selector dropdown appears when files are attached, letting the
user choose which Blossom server to upload to. Updates testing plan:
Phase 2 & 3 all pass, Phase 9 audio tested with volume bug tracked.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
nrobi144
2026-03-18 14:26:47 +02:00
parent 836e024bd7
commit 1d1d32da0e
2 changed files with 88 additions and 23 deletions
@@ -98,6 +98,7 @@ fun ComposeNoteDialog(
val uploadTracker = remember { DesktopUploadTracker() }
val uploadState by uploadTracker.state.collectAsState()
val orchestrator = remember { DesktopUploadOrchestrator() }
var selectedServer by remember { mutableStateOf(DesktopPreferences.preferredBlossomServer) }
// Drag-and-drop state
var isDragOver by remember { mutableStateOf(false) }
@@ -192,6 +193,15 @@ fun ComposeNoteDialog(
onRemove = { attachedFiles.remove(it) },
)
// Server selector — shown when files are attached
if (attachedFiles.isNotEmpty()) {
Spacer(Modifier.height(4.dp))
ServerSelector(
selectedServer = selectedServer,
onServerSelected = { selectedServer = it },
)
}
Spacer(Modifier.height(4.dp))
// Character count
@@ -254,7 +264,7 @@ fun ComposeNoteDialog(
orchestrator.upload(
file = file,
alt = null,
serverBaseUrl = DesktopPreferences.preferredBlossomServer,
serverBaseUrl = selectedServer,
signer = account.signer,
)
uploadTracker.onSuccess(result)
@@ -317,6 +327,61 @@ private fun buildIMetaTags(results: List<UploadResult>): List<IMetaTag> =
IMetaTag(url = url, properties = props)
}
@Composable
private fun ServerSelector(
selectedServer: String,
onServerSelected: (String) -> Unit,
) {
val servers = DesktopPreferences.blossomServers
if (servers.size <= 1) {
// Only one server — just show label, no dropdown
Row(verticalAlignment = androidx.compose.ui.Alignment.CenterVertically) {
Text(
"Upload to: ",
style = MaterialTheme.typography.labelSmall,
color = MaterialTheme.colorScheme.onSurfaceVariant,
)
Text(
selectedServer,
style = MaterialTheme.typography.labelSmall,
color = MaterialTheme.colorScheme.primary,
)
}
return
}
var expanded by remember { mutableStateOf(false) }
Row(verticalAlignment = androidx.compose.ui.Alignment.CenterVertically) {
Text(
"Upload to: ",
style = MaterialTheme.typography.labelSmall,
color = MaterialTheme.colorScheme.onSurfaceVariant,
)
androidx.compose.foundation.layout.Box {
androidx.compose.material3.TextButton(onClick = { expanded = true }) {
Text(
selectedServer,
style = MaterialTheme.typography.labelSmall,
)
}
androidx.compose.material3.DropdownMenu(
expanded = expanded,
onDismissRequest = { expanded = false },
) {
servers.forEach { server ->
androidx.compose.material3.DropdownMenuItem(
text = { Text(server, style = MaterialTheme.typography.bodySmall) },
onClick = {
onServerSelected(server)
expanded = false
},
)
}
}
}
}
}
private suspend fun publishNote(
content: String,
account: AccountState.LoggedIn,