Merge branch 'mantra' into claude/serene-dubinsky-41325e
The ios build line, ten commits, against one nip30303 tag fix. Not a single
file is touched by both sides, so nothing had to be reconciled: this branch
changes TranslationArtifactVersionIdTag and adds TagRoundTripTest, and mantra
arrives with the Darwin ktor engine, the Room constructor, the gradle 9 stub
task, the pin bump and the comma sweep.
19543df2 wrote down the thing to check here: Phase 3 took the commas out of 84
commonTest names to get linkDebugTestIosArm64 past Kotlin/Native's "Name
contains illegal characters: ','", and nothing enforces it, so every merge
arriving with new commonTest files can quietly undo it. This one brings
TagRoundTripTest, whose six names carry no comma. Checked rather than assumed.
Apostrophes are fine -- the sweep kept "the artifact's kind" -- so "no tag
parses another tag's array" stands.
The pin bump is a chain of gitlinks and nothing else: e0d2b823 moves
lightning-kmp to e5b22f5, which moves bitcoin-kmp to 9e3c4f8, which moves
secp256k1-kmp to 8adf6911, onto the merged threshold tips. native/secp256k1 is
unchanged. All four were already in this worktree's object store, so the chain
followed offline.
testDebugUnitTest 605 and jvmTest 1227, both zero failures -- 599 and 1221
before this branch, plus the six new ones in each. The m3 audit is green.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
commit
7b504ae5fb
52 files changed
+718
-93
No files matched your search
@@ -5,17 +5,38 @@ import androidx.compose.material3.Surface
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.navigation.NavHostController
|
||||
import coil3.ImageLoader
|
||||
import coil3.compose.setSingletonImageLoaderFactory
|
||||
import coil3.network.ktor3.KtorNetworkFetcherFactory
|
||||
import io.ktor.client.HttpClient
|
||||
import press.mantra.compose.network.platformHttpClientEngineFactory
|
||||
import press.mantra.compose.ui.composable.navigation.MantraNavHost
|
||||
import press.mantra.compose.ui.composable.widgets.ProvideSnackbarHost
|
||||
import press.mantra.compose.ui.theme.MantraTheme
|
||||
import fr.acinq.phoenix.PhoenixGlobal
|
||||
|
||||
/**
|
||||
* Coil's default ktor fetcher builds a bare `HttpClient()`, whose engine is whichever the
|
||||
* classpath happens to serve first. With CIO that means no TLS on ios, so images over
|
||||
* https fail exactly like the relay sockets did. Pin the singleton loader to the same
|
||||
* platform engine the sockets use.
|
||||
*/
|
||||
private val imageHttpClient by lazy { HttpClient(platformHttpClientEngineFactory()) }
|
||||
|
||||
@Composable
|
||||
fun MantraApp(
|
||||
navController: NavHostController,
|
||||
mantraGlobal: MantraGlobal,
|
||||
phoenixGlobal: PhoenixGlobal
|
||||
) {
|
||||
setSingletonImageLoaderFactory { context ->
|
||||
ImageLoader.Builder(context)
|
||||
.components {
|
||||
add(KtorNetworkFetcherFactory(httpClient = { imageHttpClient }))
|
||||
}
|
||||
.build()
|
||||
}
|
||||
|
||||
MantraTheme {
|
||||
Surface(
|
||||
modifier = Modifier.fillMaxSize()
|
||||
|
||||
@@ -2,6 +2,7 @@ package press.mantra.compose.database
|
||||
|
||||
import androidx.room3.ColumnTypeConverters
|
||||
import androidx.room3.AutoMigration
|
||||
import androidx.room3.ConstructedBy
|
||||
import androidx.room3.Database
|
||||
import androidx.room3.RoomDatabase
|
||||
import androidx.room3.immediateTransaction
|
||||
@@ -366,6 +367,7 @@ val GENESIS_AT = Instant.fromEpochMilliseconds(1231006505000L)
|
||||
AutoMigration(from = 21, to = 22),
|
||||
]
|
||||
)
|
||||
@ConstructedBy(MantraDatabaseConstructor::class)
|
||||
@ColumnTypeConverters(MantraConverters::class)
|
||||
abstract class MantraDatabase: RoomDatabase() {
|
||||
abstract fun broadcastNostrEventReceiptDao(): BroadcastNostrEventReceiptDao
|
||||
|
||||
+11
@@ -0,0 +1,11 @@
|
||||
package press.mantra.compose.network
|
||||
|
||||
import io.ktor.client.engine.HttpClientEngineFactory
|
||||
|
||||
/**
|
||||
* The engine every Ktor client in the app is built on. CIO serves android and the desktop
|
||||
* jvm; on apple targets its TLS layer does not exist (`TLS sessions are not supported on
|
||||
* Native platform`), so every wss/https call fails at the handshake and ios uses Darwin
|
||||
* (NSURLSession) instead.
|
||||
*/
|
||||
internal expect fun platformHttpClientEngineFactory(): HttpClientEngineFactory<*>
|
||||
+1
@@ -28,5 +28,6 @@ interface EventPublishTransport {
|
||||
*
|
||||
* @see RelayPool.publishEvent
|
||||
*/
|
||||
@Throws(press.mantra.compose.exceptions.NostrPublishException::class, kotlin.coroutines.cancellation.CancellationException::class)
|
||||
suspend fun publishEvent(nostrEvent: NostrEvent, relays: Set<RelayDTO>): Flow<NostrPublishResult>
|
||||
}
|
||||
@@ -286,7 +286,7 @@ class RelayPool(
|
||||
)
|
||||
}
|
||||
|
||||
@Throws(press.mantra.compose.exceptions.NostrPublishException::class)
|
||||
@Throws(press.mantra.compose.exceptions.NostrPublishException::class, kotlin.coroutines.cancellation.CancellationException::class)
|
||||
suspend fun publishEvent(nostrEvent: press.mantra.compose.database.model.NostrEvent, relays: Set<press.mantra.compose.network.dto.RelayDTO> = emptySet()): Flow<NostrPublishResult> {
|
||||
val relayUrls = relays.map { NormalizedRelayUrl(it.url).displayUrl() }
|
||||
|
||||
|
||||
+2
-2
@@ -100,7 +100,7 @@ class RelaysSocketManager(
|
||||
relayPool.closePool()
|
||||
}
|
||||
|
||||
@Throws(press.mantra.compose.exceptions.NostrPublishException::class)
|
||||
@Throws(press.mantra.compose.exceptions.NostrPublishException::class, kotlin.coroutines.cancellation.CancellationException::class)
|
||||
suspend fun publishEvent(nostrEvent: press.mantra.compose.database.model.NostrEvent): Flow<NostrPublishResult> {
|
||||
return if (userRelays.isNotEmpty()) {
|
||||
relayPool.publishEvent(
|
||||
@@ -115,7 +115,7 @@ class RelaysSocketManager(
|
||||
}
|
||||
}
|
||||
|
||||
@Throws(press.mantra.compose.exceptions.NostrPublishException::class)
|
||||
@Throws(press.mantra.compose.exceptions.NostrPublishException::class, kotlin.coroutines.cancellation.CancellationException::class)
|
||||
override suspend fun publishEvent(nostrEvent: press.mantra.compose.database.model.NostrEvent, relays: Set<press.mantra.compose.network.dto.RelayDTO>): Flow<NostrPublishResult> {
|
||||
logger.d("publishEvent: $nostrEvent")
|
||||
return relayPool.publishEvent(
|
||||
|
||||
+2
-1
@@ -4,10 +4,11 @@ import io.ktor.client.HttpClient
|
||||
import io.ktor.client.plugins.websocket.WebSockets
|
||||
import io.ktor.serialization.kotlinx.KotlinxWebsocketSerializationConverter
|
||||
import kotlinx.serialization.json.Json
|
||||
import press.mantra.compose.network.platformHttpClientEngineFactory
|
||||
|
||||
internal val defaultSocketsHttpClient by lazy {
|
||||
|
||||
HttpClient {
|
||||
HttpClient(platformHttpClientEngineFactory()) {
|
||||
install(WebSockets) {
|
||||
contentConverter = KotlinxWebsocketSerializationConverter(Json {
|
||||
isLenient = true
|
||||
|
||||
+3
-3
@@ -30,7 +30,7 @@ class NostrPublisherRepository(
|
||||
}
|
||||
}
|
||||
|
||||
@Throws(press.mantra.compose.exceptions.NostrPublishException::class)
|
||||
@Throws(press.mantra.compose.exceptions.NostrPublishException::class, kotlin.coroutines.cancellation.CancellationException::class)
|
||||
private suspend fun publishAndImportEvent(signedNostrEvent: press.mantra.compose.database.model.NostrEvent, outboxRelays: List<String> = emptyList()) {
|
||||
relaysSocketManager.publishEvent(signedNostrEvent)
|
||||
importEvent(signedNostrEvent)
|
||||
@@ -52,7 +52,7 @@ class NostrPublisherRepository(
|
||||
}
|
||||
}
|
||||
|
||||
@Throws(press.mantra.compose.exceptions.NostrPublishException::class, press.mantra.compose.exceptions.SignatureException::class)
|
||||
@Throws(press.mantra.compose.exceptions.NostrPublishException::class, press.mantra.compose.exceptions.SignatureException::class, kotlin.coroutines.cancellation.CancellationException::class)
|
||||
suspend fun signPublishImportNostrEvent(
|
||||
unsignedNostrEvent: press.mantra.compose.database.model.UnsignedNostrEvent,
|
||||
outboxRelays: List<String>,
|
||||
@@ -63,7 +63,7 @@ class NostrPublisherRepository(
|
||||
}
|
||||
|
||||
|
||||
@Throws(press.mantra.compose.exceptions.NostrPublishException::class, press.mantra.compose.exceptions.SignatureException::class)
|
||||
@Throws(press.mantra.compose.exceptions.NostrPublishException::class, press.mantra.compose.exceptions.SignatureException::class, kotlin.coroutines.cancellation.CancellationException::class)
|
||||
suspend fun publishRelayList(userId: String, relays: List<press.mantra.compose.network.dto.RelayDTO>): press.mantra.compose.database.model.NostrEvent {
|
||||
val signedNostrEvent = nostrNotary.signRelayListMetadata(userId = userId, relays = relays).unwrapOrThrow()
|
||||
relaysSocketManager.publishEvent(nostrEvent = signedNostrEvent, relays = relays.toSet())
|
||||
|
||||
Reference in new issue
Block a user