feat(media): wire encrypted media, server settings, and server preferences

- ChatPane: display ChatFileAttachment for encrypted file header events
- DesktopPreferences: add blossom server list persistence
- Settings: add MediaServerSettings section above relay settings
- ComposeNoteDialog: use preferred blossom server from preferences

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
nrobi144
2026-03-16 12:23:57 +02:00
parent e654d48cdf
commit 7773844d2f
4 changed files with 40 additions and 9 deletions
@@ -68,4 +68,17 @@ object DesktopPreferences {
set(value) {
prefs.put(KEY_LAYOUT_MODE, value)
}
private const val KEY_BLOSSOM_SERVERS = "blossom_servers"
private const val DEFAULT_BLOSSOM_SERVER = "https://blossom.primal.net"
var blossomServers: List<String>
get() {
val raw = prefs.get(KEY_BLOSSOM_SERVERS, DEFAULT_BLOSSOM_SERVER)
return if (raw.isBlank()) emptyList() else raw.split(",")
}
set(value) = prefs.put(KEY_BLOSSOM_SERVERS, value.joinToString(","))
val preferredBlossomServer: String
get() = blossomServers.firstOrNull() ?: DEFAULT_BLOSSOM_SERVER
}
@@ -91,6 +91,7 @@ import com.vitorpamplona.amethyst.desktop.ui.deck.DeckState
import com.vitorpamplona.amethyst.desktop.ui.deck.SinglePaneLayout
import com.vitorpamplona.amethyst.desktop.ui.profile.ProfileInfoCard
import com.vitorpamplona.amethyst.desktop.ui.relay.RelayStatusCard
import com.vitorpamplona.amethyst.desktop.ui.settings.MediaServerSettings
import com.vitorpamplona.quartz.nip01Core.relay.normalizer.RelayUrlNormalizer
import com.vitorpamplona.quartz.nip47WalletConnect.Nip47WalletConnect
import kotlinx.coroutines.CoroutineScope
@@ -877,6 +878,15 @@ fun RelaySettingsScreen(
HorizontalDivider()
Spacer(Modifier.height(24.dp))
// Media Server Settings
MediaServerSettings(
initialServers = DesktopPreferences.blossomServers,
onServersChanged = { DesktopPreferences.blossomServers = it },
)
Spacer(Modifier.height(24.dp))
HorizontalDivider()
Spacer(Modifier.height(24.dp))
// Developer Settings Section (only in debug mode)
if (DebugConfig.isDebugMode) {
com.vitorpamplona.amethyst.desktop.ui
@@ -46,6 +46,7 @@ import androidx.compose.ui.Modifier
import androidx.compose.ui.unit.dp
import androidx.compose.ui.window.Dialog
import com.vitorpamplona.amethyst.commons.model.nip10TextNotes.PublishAction
import com.vitorpamplona.amethyst.desktop.DesktopPreferences
import com.vitorpamplona.amethyst.desktop.account.AccountState
import com.vitorpamplona.amethyst.desktop.network.DesktopRelayConnectionManager
import com.vitorpamplona.amethyst.desktop.service.upload.DesktopUploadOrchestrator
@@ -58,8 +59,6 @@ import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext
import java.io.File
private const val DEFAULT_BLOSSOM_SERVER = "https://blossom.primal.net"
@Composable
fun ComposeNoteDialog(
onDismiss: () -> Unit,
@@ -189,7 +188,7 @@ fun ComposeNoteDialog(
orchestrator.upload(
file = file,
alt = null,
serverBaseUrl = DEFAULT_BLOSSOM_SERVER,
serverBaseUrl = DesktopPreferences.preferredBlossomServer,
signer = account.signer,
)
uploadTracker.onSuccess(result)
@@ -92,6 +92,7 @@ import com.vitorpamplona.quartz.nip01Core.hints.EventHintBundle
import com.vitorpamplona.quartz.nip04Dm.messages.PrivateDmEvent
import com.vitorpamplona.quartz.nip17Dm.NIP17Factory
import com.vitorpamplona.quartz.nip17Dm.base.ChatroomKey
import com.vitorpamplona.quartz.nip17Dm.files.ChatMessageEncryptedFileHeaderEvent
import kotlinx.coroutines.launch
private val isMacOS = System.getProperty("os.name").lowercase().contains("mac")
@@ -436,12 +437,20 @@ private fun MessageWithReactions(
}
},
) { _ ->
SelectionContainer {
Text(
text = decryptedContent ?: "",
style = MaterialTheme.typography.bodyMedium,
color = MaterialTheme.colorScheme.onSurface,
)
when (note.event) {
is ChatMessageEncryptedFileHeaderEvent -> {
ChatFileAttachment(event = note.event as ChatMessageEncryptedFileHeaderEvent)
}
else -> {
SelectionContainer {
Text(
text = decryptedContent ?: "",
style = MaterialTheme.typography.bodyMedium,
color = MaterialTheme.colorScheme.onSurface,
)
}
}
}
}
}