mirror of
https://github.com/vitorpamplona/amethyst.git
synced 2026-10-05 11:18:24 +00:00
fix: clear the remaining compiler warnings in amethyst and desktopApp
Second half of the warning sweep, covering :amethyst (both flavors, all
build types, unit + instrumented tests), :desktopApp and :benchmark:
- GitReplyEvent (NIP-34 kind 1622) is deprecated in favour of NIP-22
comments, but events already on relays still arrive and still have to be
routed, rendered and surfaced. @Suppress("DEPRECATION") with that reason
at the five production sites and the coverage test that pins them.
- The four instrumented Compose tests move to
androidx.compose.ui.test.junit4.v2.createComposeRule. The v2 factory
returns the same ComposeContentTestRule, so mainClock, setContent and the
node assertions are unchanged; only the effect dispatcher differs.
- RelayAuthPromptBusTest / RelayAuthSessionGrantsTest: @OptIn for the
ExperimentalCoroutinesApi members (testScheduler.currentTime, runCurrent)
they already use, matching the annotation the file's other tests carry.
- MarmotFileUploader: drop a nullable alias of a non-null cipher, left
behind when the v2 reference stopped being conditional.
- LocalCacheSearchParityTest: hoist the Json format out of the loader.
- LivesSection: FlowRowOverflow and FlowRow's overflow parameter are
deprecated; the non-deprecated overload already clips beyond maxLines.
- HexBenchmark: drop a bare `null` expression statement from the measured
lambda.
Also fixes :commons:compileCommonMainKotlinMetadata, which did not compile
at all: shared code called BigDecimal.toLong(), which resolves in every
platform compilation (every actual is a Number) but not in the common
metadata one, where only the expect class's own members are visible.
`expect class BigDecimal : Number` cannot work — java.math.BigDecimal leaves
toByte()/toShort() abstract, so the JVM typealias fails the expect/actual
modality check — so the conversion is a top-level expect/actual extension
instead, with actuals next to each BigDecimal actual.
Verified warning- and error-free across the jvm, android (play/fdroid ×
debug/release/benchmark), linuxX64, and the common/jvmAndroid/native/apple/
ios metadata compilations. The apple actuals are checked by
compileAppleMainKotlinMetadata, which runs the frontend against the Apple
klibs without needing a macOS host.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_0123kXtseu4X18hL3GMDcdER
This commit is contained in:
+3
-2
@@ -31,7 +31,7 @@ import androidx.compose.ui.platform.LocalDensity
|
|||||||
import androidx.compose.ui.test.assertHeightIsAtLeast
|
import androidx.compose.ui.test.assertHeightIsAtLeast
|
||||||
import androidx.compose.ui.test.assertIsDisplayed
|
import androidx.compose.ui.test.assertIsDisplayed
|
||||||
import androidx.compose.ui.test.getUnclippedBoundsInRoot
|
import androidx.compose.ui.test.getUnclippedBoundsInRoot
|
||||||
import androidx.compose.ui.test.junit4.createComposeRule
|
import androidx.compose.ui.test.junit4.v2.createComposeRule
|
||||||
import androidx.compose.ui.test.onNodeWithText
|
import androidx.compose.ui.test.onNodeWithText
|
||||||
import androidx.compose.ui.unit.Density
|
import androidx.compose.ui.unit.Density
|
||||||
import androidx.compose.ui.unit.Dp
|
import androidx.compose.ui.unit.Dp
|
||||||
@@ -62,7 +62,8 @@ import org.junit.runner.RunWith
|
|||||||
*/
|
*/
|
||||||
@RunWith(AndroidJUnit4::class)
|
@RunWith(AndroidJUnit4::class)
|
||||||
class PlaybackErrorOverlayFitTest {
|
class PlaybackErrorOverlayFitTest {
|
||||||
@get:Rule val rule = createComposeRule()
|
@get:Rule
|
||||||
|
val rule = createComposeRule()
|
||||||
|
|
||||||
private val targetContext = InstrumentationRegistry.getInstrumentation().targetContext
|
private val targetContext = InstrumentationRegistry.getInstrumentation().targetContext
|
||||||
|
|
||||||
|
|||||||
+3
-2
@@ -27,7 +27,7 @@ import androidx.compose.ui.Modifier
|
|||||||
import androidx.compose.ui.layout.ContentScale
|
import androidx.compose.ui.layout.ContentScale
|
||||||
import androidx.compose.ui.layout.onGloballyPositioned
|
import androidx.compose.ui.layout.onGloballyPositioned
|
||||||
import androidx.compose.ui.layout.positionInRoot
|
import androidx.compose.ui.layout.positionInRoot
|
||||||
import androidx.compose.ui.test.junit4.createComposeRule
|
import androidx.compose.ui.test.junit4.v2.createComposeRule
|
||||||
import androidx.compose.ui.unit.dp
|
import androidx.compose.ui.unit.dp
|
||||||
import androidx.test.ext.junit.runners.AndroidJUnit4
|
import androidx.test.ext.junit.runners.AndroidJUnit4
|
||||||
import com.vitorpamplona.amethyst.service.playback.composable.audioSquare
|
import com.vitorpamplona.amethyst.service.playback.composable.audioSquare
|
||||||
@@ -50,7 +50,8 @@ import org.junit.runner.RunWith
|
|||||||
*/
|
*/
|
||||||
@RunWith(AndroidJUnit4::class)
|
@RunWith(AndroidJUnit4::class)
|
||||||
class AudioPlayerBoxOverflowTest {
|
class AudioPlayerBoxOverflowTest {
|
||||||
@get:Rule val rule = createComposeRule()
|
@get:Rule
|
||||||
|
val rule = createComposeRule()
|
||||||
|
|
||||||
private class Bounds {
|
private class Bounds {
|
||||||
var top = 0f
|
var top = 0f
|
||||||
|
|||||||
+3
-2
@@ -31,7 +31,7 @@ import androidx.compose.runtime.mutableIntStateOf
|
|||||||
import androidx.compose.runtime.setValue
|
import androidx.compose.runtime.setValue
|
||||||
import androidx.compose.ui.platform.LocalDensity
|
import androidx.compose.ui.platform.LocalDensity
|
||||||
import androidx.compose.ui.platform.LocalView
|
import androidx.compose.ui.platform.LocalView
|
||||||
import androidx.compose.ui.test.junit4.createComposeRule
|
import androidx.compose.ui.test.junit4.v2.createComposeRule
|
||||||
import androidx.core.graphics.Insets
|
import androidx.core.graphics.Insets
|
||||||
import androidx.core.view.OnApplyWindowInsetsListener
|
import androidx.core.view.OnApplyWindowInsetsListener
|
||||||
import androidx.core.view.WindowInsetsAnimationCompat
|
import androidx.core.view.WindowInsetsAnimationCompat
|
||||||
@@ -70,7 +70,8 @@ import org.junit.Test
|
|||||||
* fallback would silently start reading a dead value too.
|
* fallback would silently start reading a dead value too.
|
||||||
*/
|
*/
|
||||||
class ComposeImeInsetWedgeTest {
|
class ComposeImeInsetWedgeTest {
|
||||||
@get:Rule val rule = createComposeRule()
|
@get:Rule
|
||||||
|
val rule = createComposeRule()
|
||||||
|
|
||||||
private val keyboardHeight = 957
|
private val keyboardHeight = 957
|
||||||
|
|
||||||
|
|||||||
+1
-1
@@ -27,7 +27,7 @@ import androidx.compose.ui.Alignment
|
|||||||
import androidx.compose.ui.Modifier
|
import androidx.compose.ui.Modifier
|
||||||
import androidx.compose.ui.platform.testTag
|
import androidx.compose.ui.platform.testTag
|
||||||
import androidx.compose.ui.test.assertIsDisplayed
|
import androidx.compose.ui.test.assertIsDisplayed
|
||||||
import androidx.compose.ui.test.junit4.createComposeRule
|
import androidx.compose.ui.test.junit4.v2.createComposeRule
|
||||||
import androidx.compose.ui.test.onNodeWithTag
|
import androidx.compose.ui.test.onNodeWithTag
|
||||||
import androidx.test.ext.junit.runners.AndroidJUnit4
|
import androidx.test.ext.junit.runners.AndroidJUnit4
|
||||||
import com.vitorpamplona.amethyst.ui.actions.DeferredCrossfade
|
import com.vitorpamplona.amethyst.ui.actions.DeferredCrossfade
|
||||||
|
|||||||
+3
@@ -201,6 +201,9 @@ class EventNotificationConsumer(
|
|||||||
.onFailure { Log.d(TAG) { "Skipping non-decodable npub $npub: ${it.message}" } }
|
.onFailure { Log.d(TAG) { "Skipping non-decodable npub $npub: ${it.message}" } }
|
||||||
.getOrNull()
|
.getOrNull()
|
||||||
|
|
||||||
|
// GitReplyEvent (kind 1622) is deprecated in favour of NIP-22 comments, but
|
||||||
|
// events already on relays still arrive and still have to be routed.
|
||||||
|
@Suppress("DEPRECATION")
|
||||||
private suspend fun dispatchForAccount(
|
private suspend fun dispatchForAccount(
|
||||||
event: Event,
|
event: Event,
|
||||||
account: Account,
|
account: Account,
|
||||||
|
|||||||
+3
@@ -112,6 +112,9 @@ class NotificationDispatcher(
|
|||||||
// recipient account.
|
// recipient account.
|
||||||
// `internal` (was `private`) so the notification-kinds contract test
|
// `internal` (was `private`) so the notification-kinds contract test
|
||||||
// can pin the push-side kind set against the in-app feed's kind set.
|
// can pin the push-side kind set against the in-app feed's kind set.
|
||||||
|
// GitReplyEvent (kind 1622) is deprecated in favour of NIP-22 comments, but
|
||||||
|
// events already on relays still arrive and still have to be routed.
|
||||||
|
@Suppress("DEPRECATION")
|
||||||
internal val NOTIFICATION_KINDS: Set<Int> =
|
internal val NOTIFICATION_KINDS: Set<Int> =
|
||||||
setOf(
|
setOf(
|
||||||
// Direct-arrival
|
// Direct-arrival
|
||||||
|
|||||||
+3
@@ -81,6 +81,9 @@ object CodeNotification {
|
|||||||
event: GitPullRequestUpdateEvent,
|
event: GitPullRequestUpdateEvent,
|
||||||
) = post(context, account, event.id, event.createdAt, event.pubKey, R.string.app_notification_code_channel_message_pr_update, event.content)
|
) = post(context, account, event.id, event.createdAt, event.pubKey, R.string.app_notification_code_channel_message_pr_update, event.content)
|
||||||
|
|
||||||
|
// GitReplyEvent (kind 1622) is deprecated in favour of NIP-22 comments, but
|
||||||
|
// events already on relays still arrive and still have to be rendered.
|
||||||
|
@Suppress("DEPRECATION")
|
||||||
suspend fun notify(
|
suspend fun notify(
|
||||||
context: Context,
|
context: Context,
|
||||||
account: Account,
|
account: Account,
|
||||||
|
|||||||
+13
-16
@@ -119,7 +119,6 @@ class MarmotFileUploader(
|
|||||||
// imprecisely.
|
// imprecisely.
|
||||||
val canonicalMediaType = MarmotMediaType.canonicalize(mimeType) ?: GENERIC_MEDIA_TYPE
|
val canonicalMediaType = MarmotMediaType.canonicalize(mimeType) ?: GENERIC_MEDIA_TYPE
|
||||||
val cipher = EncryptedMediaV2Cipher(exporterSecret, canonicalMediaType, filename)
|
val cipher = EncryptedMediaV2Cipher(exporterSecret, canonicalMediaType, filename)
|
||||||
val v2Cipher = cipher
|
|
||||||
|
|
||||||
item.orchestrator.uploadEncrypted(
|
item.orchestrator.uploadEncrypted(
|
||||||
uri = media.uri,
|
uri = media.uri,
|
||||||
@@ -142,21 +141,19 @@ class MarmotFileUploader(
|
|||||||
// compression and metadata stripping — because that is what the
|
// compression and metadata stripping — because that is what the
|
||||||
// key was derived from.
|
// key was derived from.
|
||||||
val reference =
|
val reference =
|
||||||
v2Cipher?.let {
|
EncryptedMediaReferenceV2(
|
||||||
EncryptedMediaReferenceV2(
|
locators =
|
||||||
locators =
|
listOf(
|
||||||
listOf(
|
MediaLocatorV2(EncryptedMediaPolicyV2.INITIAL_LOCATOR_KIND, serverResult.url),
|
||||||
MediaLocatorV2(EncryptedMediaPolicyV2.INITIAL_LOCATOR_KIND, serverResult.url),
|
),
|
||||||
),
|
ciphertextSha256 = cipher.ciphertextSha256,
|
||||||
ciphertextSha256 = it.ciphertextSha256,
|
plaintextSha256 = cipher.plaintextSha256,
|
||||||
plaintextSha256 = it.plaintextSha256,
|
nonce = cipher.nonce,
|
||||||
nonce = it.nonce,
|
mediaType = cipher.mediaType,
|
||||||
mediaType = it.mediaType,
|
filename = filename,
|
||||||
filename = filename,
|
dim = serverResult.fileHeader.dim?.toString(),
|
||||||
dim = serverResult.fileHeader.dim?.toString(),
|
thumbhash = serverResult.fileHeader.thumbHash?.thumbhash,
|
||||||
thumbhash = serverResult.fileHeader.thumbHash?.thumbhash,
|
)
|
||||||
)
|
|
||||||
}
|
|
||||||
results.add(
|
results.add(
|
||||||
Mip04UploadResult(
|
Mip04UploadResult(
|
||||||
url = serverResult.url,
|
url = serverResult.url,
|
||||||
|
|||||||
+6
@@ -139,6 +139,9 @@ class NotificationFeedFilter(
|
|||||||
AttestationRequestEvent.KIND,
|
AttestationRequestEvent.KIND,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// GitReplyEvent (kind 1622) is deprecated in favour of NIP-22 comments, but
|
||||||
|
// events already on relays still arrive and still have to be routed.
|
||||||
|
@Suppress("DEPRECATION")
|
||||||
val NOTIFICATION_KINDS =
|
val NOTIFICATION_KINDS =
|
||||||
// Kinds that RENDER as a row on the Notifications tab. This is a
|
// Kinds that RENDER as a row on the Notifications tab. This is a
|
||||||
// display gate over whatever is already in LocalCache — it plays no
|
// display gate over whatever is already in LocalCache — it plays no
|
||||||
@@ -268,6 +271,9 @@ class NotificationFeedFilter(
|
|||||||
|
|
||||||
// Shared with EventNotificationConsumer so push notifications and the
|
// Shared with EventNotificationConsumer so push notifications and the
|
||||||
// in-app feed apply the same per-kind "is this event for me" rule.
|
// in-app feed apply the same per-kind "is this event for me" rule.
|
||||||
|
// GitReplyEvent (kind 1622) is deprecated in favour of NIP-22 comments, but
|
||||||
|
// events already on relays still arrive and still have to be routed.
|
||||||
|
@Suppress("DEPRECATION")
|
||||||
fun tagsAnEventByUser(
|
fun tagsAnEventByUser(
|
||||||
note: Note,
|
note: Note,
|
||||||
authorHex: HexKey,
|
authorHex: HexKey,
|
||||||
|
|||||||
+4
-1
@@ -47,6 +47,9 @@ import java.io.File
|
|||||||
*/
|
*/
|
||||||
class LocalCacheSearchParityTest {
|
class LocalCacheSearchParityTest {
|
||||||
companion object {
|
companion object {
|
||||||
|
/** Hoisted out of [loadCorpus]: building a Json format is expensive enough that the compiler warns on it. */
|
||||||
|
private val json = Json { ignoreUnknownKeys = true }
|
||||||
|
|
||||||
private lateinit var corpus: List<Event>
|
private lateinit var corpus: List<Event>
|
||||||
|
|
||||||
@BeforeClass
|
@BeforeClass
|
||||||
@@ -57,7 +60,7 @@ class LocalCacheSearchParityTest {
|
|||||||
.firstOrNull { it.isFile }
|
.firstOrNull { it.isFile }
|
||||||
?: error("tools/search-parity/fixture.json is missing; run tools/search-parity/fetch_fixtures.py")
|
?: error("tools/search-parity/fixture.json is missing; run tools/search-parity/fetch_fixtures.py")
|
||||||
|
|
||||||
val root = Json { ignoreUnknownKeys = true }.parseToJsonElement(file.readText()).jsonObject
|
val root = json.parseToJsonElement(file.readText()).jsonObject
|
||||||
corpus =
|
corpus =
|
||||||
root["cases"]!!
|
root["cases"]!!
|
||||||
.jsonArray
|
.jsonArray
|
||||||
|
|||||||
+1
@@ -153,6 +153,7 @@ class RelayAuthPromptBusTest {
|
|||||||
* answer already sitting in the deferred, so the relay it belongs to goes unauthenticated for that
|
* answer already sitting in the deferred, so the relay it belongs to goes unauthenticated for that
|
||||||
* long despite the user having answered. Marking it shown is what makes the answer land now.
|
* long despite the user having answered. Marking it shown is what makes the answer land now.
|
||||||
*/
|
*/
|
||||||
|
@OptIn(ExperimentalCoroutinesApi::class)
|
||||||
@Test
|
@Test
|
||||||
fun anAnswerFannedOutToAQueuedPromptLandsWithoutWaitingOutTheQueueWindow() =
|
fun anAnswerFannedOutToAQueuedPromptLandsWithoutWaitingOutTheQueueWindow() =
|
||||||
runTest {
|
runTest {
|
||||||
|
|||||||
+3
@@ -32,6 +32,7 @@ import com.vitorpamplona.amethyst.commons.relayauth.RelayAuthPermissionStore
|
|||||||
import com.vitorpamplona.amethyst.commons.relayauth.RelayAuthPolicy
|
import com.vitorpamplona.amethyst.commons.relayauth.RelayAuthPolicy
|
||||||
import com.vitorpamplona.amethyst.commons.relayauth.RelayAuthVerdict
|
import com.vitorpamplona.amethyst.commons.relayauth.RelayAuthVerdict
|
||||||
import kotlinx.coroutines.CompletableDeferred
|
import kotlinx.coroutines.CompletableDeferred
|
||||||
|
import kotlinx.coroutines.ExperimentalCoroutinesApi
|
||||||
import kotlinx.coroutines.launch
|
import kotlinx.coroutines.launch
|
||||||
import kotlinx.coroutines.test.runCurrent
|
import kotlinx.coroutines.test.runCurrent
|
||||||
import kotlinx.coroutines.test.runTest
|
import kotlinx.coroutines.test.runTest
|
||||||
@@ -185,6 +186,7 @@ class RelayAuthSessionGrantsTest {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@OptIn(ExperimentalCoroutinesApi::class)
|
||||||
@Test
|
@Test
|
||||||
fun promotingAGrantToAlwaysNeverOpensAGapThatRePrompts() =
|
fun promotingAGrantToAlwaysNeverOpensAGapThatRePrompts() =
|
||||||
runTest {
|
runTest {
|
||||||
@@ -205,6 +207,7 @@ class RelayAuthSessionGrantsTest {
|
|||||||
assertEquals(RelayAuthVerdict.ALLOW, ledger.decide(askable(relay)))
|
assertEquals(RelayAuthVerdict.ALLOW, ledger.decide(askable(relay)))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@OptIn(ExperimentalCoroutinesApi::class)
|
||||||
@Test
|
@Test
|
||||||
fun neverAllowStopsAuthenticatingBeforeItsWriteLands() =
|
fun neverAllowStopsAuthenticatingBeforeItsWriteLands() =
|
||||||
runTest {
|
runTest {
|
||||||
|
|||||||
+2
@@ -70,6 +70,7 @@ class Nip34NotificationCoverageTest {
|
|||||||
* A NIP-22 [com.vitorpamplona.quartz.nip22Comments.CommentEvent] handles
|
* A NIP-22 [com.vitorpamplona.quartz.nip22Comments.CommentEvent] handles
|
||||||
* modern comments through its own separate wiring.
|
* modern comments through its own separate wiring.
|
||||||
*/
|
*/
|
||||||
|
@Suppress("DEPRECATION")
|
||||||
private val nip34ParticipantKinds =
|
private val nip34ParticipantKinds =
|
||||||
setOf(
|
setOf(
|
||||||
GitPatchEvent.KIND,
|
GitPatchEvent.KIND,
|
||||||
@@ -131,6 +132,7 @@ class Nip34NotificationCoverageTest {
|
|||||||
* uppercase `E`. Asserting the wrong half passes the kind list while matching
|
* uppercase `E`. Asserting the wrong half passes the kind list while matching
|
||||||
* nothing on the wire.
|
* nothing on the wire.
|
||||||
*/
|
*/
|
||||||
|
@Suppress("DEPRECATION")
|
||||||
@Test
|
@Test
|
||||||
fun `status kinds are pulled by the lowercase-e engagement subscription`() {
|
fun `status kinds are pulled by the lowercase-e engagement subscription`() {
|
||||||
val eAnchoredActivityKinds =
|
val eAnchoredActivityKinds =
|
||||||
|
|||||||
@@ -136,7 +136,7 @@ class HexBenchmark {
|
|||||||
/** The pre-existing two-pass way to safely decode an id, for comparison with [hexDecode64OrNull]. */
|
/** The pre-existing two-pass way to safely decode an id, for comparison with [hexDecode64OrNull]. */
|
||||||
@Test
|
@Test
|
||||||
fun hexIsHex64ThenDecode() {
|
fun hexIsHex64ThenDecode() {
|
||||||
r.measureRepeated { if (Hex.isHex64(hex)) Hex.decode(hex) else null }
|
r.measureRepeated { if (Hex.isHex64(hex)) Hex.decode(hex) }
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
|||||||
+3
-2
@@ -33,6 +33,7 @@ import com.vitorpamplona.quartz.nip01Core.core.HexKey
|
|||||||
import com.vitorpamplona.quartz.nip57Zaps.LnZapEvent
|
import com.vitorpamplona.quartz.nip57Zaps.LnZapEvent
|
||||||
import com.vitorpamplona.quartz.nip57Zaps.LnZapRequestEvent
|
import com.vitorpamplona.quartz.nip57Zaps.LnZapRequestEvent
|
||||||
import com.vitorpamplona.quartz.nipB1Bolt12Zaps.zap.Bolt12ZapEvent
|
import com.vitorpamplona.quartz.nipB1Bolt12Zaps.zap.Bolt12ZapEvent
|
||||||
|
import com.vitorpamplona.quartz.utils.toLongValue
|
||||||
import kotlinx.coroutines.Dispatchers
|
import kotlinx.coroutines.Dispatchers
|
||||||
import kotlinx.coroutines.IO
|
import kotlinx.coroutines.IO
|
||||||
import kotlinx.coroutines.Job
|
import kotlinx.coroutines.Job
|
||||||
@@ -162,7 +163,7 @@ class LiveStreamTopZappersViewModel(
|
|||||||
when (val ev = note.event) {
|
when (val ev = note.event) {
|
||||||
is LnZapEvent -> {
|
is LnZapEvent -> {
|
||||||
val request = ev.zapRequest ?: return null
|
val request = ev.zapRequest ?: return null
|
||||||
val sats = ev.amount()?.toLong() ?: return null
|
val sats = ev.amount()?.toLongValue() ?: return null
|
||||||
ZapContribution(note.idHex, request.pubKey, request.isAnonTagged(), sats)
|
ZapContribution(note.idHex, request.pubKey, request.isAnonTagged(), sats)
|
||||||
}
|
}
|
||||||
is Bolt12ZapEvent -> {
|
is Bolt12ZapEvent -> {
|
||||||
@@ -178,7 +179,7 @@ class LiveStreamTopZappersViewModel(
|
|||||||
): ZapContribution? {
|
): ZapContribution? {
|
||||||
val receiptEv = receiptNote?.event as? LnZapEvent ?: return null
|
val receiptEv = receiptNote?.event as? LnZapEvent ?: return null
|
||||||
val request = zapRequestNote.event as? LnZapRequestEvent ?: return null
|
val request = zapRequestNote.event as? LnZapRequestEvent ?: return null
|
||||||
val sats = receiptEv.amount()?.toLong() ?: return null
|
val sats = receiptEv.amount()?.toLongValue() ?: return null
|
||||||
return ZapContribution(receiptNote.idHex, request.pubKey, request.isAnonTagged(), sats)
|
return ZapContribution(receiptNote.idHex, request.pubKey, request.isAnonTagged(), sats)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+2
-1
@@ -23,6 +23,7 @@ package com.vitorpamplona.amethyst.commons.viewmodels
|
|||||||
import androidx.compose.runtime.Immutable
|
import androidx.compose.runtime.Immutable
|
||||||
import com.vitorpamplona.quartz.nip57Zaps.LnZapEvent
|
import com.vitorpamplona.quartz.nip57Zaps.LnZapEvent
|
||||||
import com.vitorpamplona.quartz.nipB1Bolt12Zaps.zap.Bolt12ZapEvent
|
import com.vitorpamplona.quartz.nipB1Bolt12Zaps.zap.Bolt12ZapEvent
|
||||||
|
import com.vitorpamplona.quartz.utils.toLongValue
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* One in-flight kind-9735 zap to render as a floating overlay on the
|
* One in-flight kind-9735 zap to render as a floating overlay on the
|
||||||
@@ -59,7 +60,7 @@ data class RoomZap(
|
|||||||
eventId = event.id,
|
eventId = event.id,
|
||||||
sourcePubkey = event.zapRequest?.pubKey ?: event.pubKey,
|
sourcePubkey = event.zapRequest?.pubKey ?: event.pubKey,
|
||||||
targetPubkey = event.zappedAuthor().firstOrNull(),
|
targetPubkey = event.zappedAuthor().firstOrNull(),
|
||||||
amountSats = event.amount?.toLong(),
|
amountSats = event.amount?.toLongValue(),
|
||||||
createdAtSec = event.createdAt,
|
createdAtSec = event.createdAt,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|||||||
-2
@@ -27,7 +27,6 @@ import androidx.compose.foundation.layout.Box
|
|||||||
import androidx.compose.foundation.layout.Column
|
import androidx.compose.foundation.layout.Column
|
||||||
import androidx.compose.foundation.layout.ExperimentalLayoutApi
|
import androidx.compose.foundation.layout.ExperimentalLayoutApi
|
||||||
import androidx.compose.foundation.layout.FlowRow
|
import androidx.compose.foundation.layout.FlowRow
|
||||||
import androidx.compose.foundation.layout.FlowRowOverflow
|
|
||||||
import androidx.compose.foundation.layout.Row
|
import androidx.compose.foundation.layout.Row
|
||||||
import androidx.compose.foundation.layout.Spacer
|
import androidx.compose.foundation.layout.Spacer
|
||||||
import androidx.compose.foundation.layout.aspectRatio
|
import androidx.compose.foundation.layout.aspectRatio
|
||||||
@@ -146,7 +145,6 @@ fun LivesSection(
|
|||||||
horizontalArrangement = Arrangement.spacedBy(12.dp),
|
horizontalArrangement = Arrangement.spacedBy(12.dp),
|
||||||
verticalArrangement = Arrangement.spacedBy(12.dp),
|
verticalArrangement = Arrangement.spacedBy(12.dp),
|
||||||
maxLines = 2,
|
maxLines = 2,
|
||||||
overflow = FlowRowOverflow.Clip,
|
|
||||||
modifier = Modifier.fillMaxWidth(),
|
modifier = Modifier.fillMaxWidth(),
|
||||||
) {
|
) {
|
||||||
ranked.forEach { channel ->
|
ranked.forEach { channel ->
|
||||||
|
|||||||
@@ -0,0 +1,23 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2025 Vitor Pamplona
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||||
|
* this software and associated documentation files (the "Software"), to deal in
|
||||||
|
* the Software without restriction, including without limitation the rights to use,
|
||||||
|
* copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the
|
||||||
|
* Software, and to permit persons to whom the Software is furnished to do so,
|
||||||
|
* subject to the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice shall be included in all
|
||||||
|
* copies or substantial portions of the Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||||
|
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||||
|
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
|
||||||
|
* 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.utils
|
||||||
|
|
||||||
|
actual fun BigDecimal.toLongValue(): Long = toLong()
|
||||||
+1
-1
@@ -760,7 +760,7 @@ class MarmotInboundProcessor(
|
|||||||
val author = payloadAuthor(candidate.content.decodeToString())
|
val author = payloadAuthor(candidate.content.decodeToString())
|
||||||
val sender = candidate.senderAccount
|
val sender = candidate.senderAccount
|
||||||
val valid = author != null && sender != null && author == sender
|
val valid = author != null && sender != null && author == sender
|
||||||
if (valid && sender != null) {
|
if (valid) {
|
||||||
convergence.recordWitness(groupId, candidate.stateId, sender)
|
convergence.recordWitness(groupId, candidate.stateId, sender)
|
||||||
}
|
}
|
||||||
return GroupEventResult.AppMessageOnCandidateBranch(
|
return GroupEventResult.AppMessageOnCandidateBranch(
|
||||||
|
|||||||
+2
-2
@@ -561,7 +561,7 @@ class MarmotConvergenceEngine(
|
|||||||
|
|
||||||
return mutex.withLock {
|
return mutex.withLock {
|
||||||
val ctx = contexts[groupId] ?: return@withLock null
|
val ctx = contexts[groupId] ?: return@withLock null
|
||||||
if (rewound && selectedTipId != null) {
|
if (rewound) {
|
||||||
adoptBranch(ctx, graph, selectedTipId, inputs.baseId)
|
adoptBranch(ctx, graph, selectedTipId, inputs.baseId)
|
||||||
}
|
}
|
||||||
// Keep the states of branches that LOST but stay eligible: losing
|
// Keep the states of branches that LOST but stay eligible: losing
|
||||||
@@ -576,7 +576,7 @@ class MarmotConvergenceEngine(
|
|||||||
.forEach { tipId ->
|
.forEach { tipId ->
|
||||||
var cursor: String? = tipId
|
var cursor: String? = tipId
|
||||||
while (cursor != null && cursor !in canonical) {
|
while (cursor != null && cursor !in canonical) {
|
||||||
graph.statesById[cursor]?.let { ctx.candidateStates[cursor!!] = it }
|
graph.statesById[cursor]?.let { ctx.candidateStates[cursor] = it }
|
||||||
cursor = graph.parentOf[cursor]
|
cursor = graph.parentOf[cursor]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -23,3 +23,15 @@ package com.vitorpamplona.quartz.utils
|
|||||||
operator fun BigDecimal.plus(other: BigDecimal): BigDecimal = add(other)
|
operator fun BigDecimal.plus(other: BigDecimal): BigDecimal = add(other)
|
||||||
|
|
||||||
operator fun BigDecimal.minus(other: BigDecimal): BigDecimal = subtract(other)
|
operator fun BigDecimal.minus(other: BigDecimal): BigDecimal = subtract(other)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Truncate to a Long, the way Number.toLong() does on every platform.
|
||||||
|
*
|
||||||
|
* It has to be an expect *function* rather than a member of `expect class
|
||||||
|
* BigDecimal`: every actual is already a Number and so already has toLong(),
|
||||||
|
* but java.math.BigDecimal leaves toByte()/toShort() abstract, which makes
|
||||||
|
* `expect class BigDecimal : Number` impossible to actualize with the JVM
|
||||||
|
* typealias. Without this, `amount.toLong()` in shared code resolves only in
|
||||||
|
* the platform compilations and breaks `compileCommonMainKotlinMetadata`.
|
||||||
|
*/
|
||||||
|
expect fun BigDecimal.toLongValue(): Long
|
||||||
|
|||||||
+23
@@ -0,0 +1,23 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2025 Vitor Pamplona
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||||
|
* this software and associated documentation files (the "Software"), to deal in
|
||||||
|
* the Software without restriction, including without limitation the rights to use,
|
||||||
|
* copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the
|
||||||
|
* Software, and to permit persons to whom the Software is furnished to do so,
|
||||||
|
* subject to the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice shall be included in all
|
||||||
|
* copies or substantial portions of the Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||||
|
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||||
|
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
|
||||||
|
* 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.utils
|
||||||
|
|
||||||
|
actual fun BigDecimal.toLongValue(): Long = toLong()
|
||||||
@@ -0,0 +1,23 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2025 Vitor Pamplona
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||||
|
* this software and associated documentation files (the "Software"), to deal in
|
||||||
|
* the Software without restriction, including without limitation the rights to use,
|
||||||
|
* copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the
|
||||||
|
* Software, and to permit persons to whom the Software is furnished to do so,
|
||||||
|
* subject to the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice shall be included in all
|
||||||
|
* copies or substantial portions of the Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||||
|
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||||
|
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
|
||||||
|
* 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.utils
|
||||||
|
|
||||||
|
actual fun BigDecimal.toLongValue(): Long = toLong()
|
||||||
Reference in New Issue
Block a user