Merge branch 'main' of https://github.com/vitorpamplona/amethyst into upstream-main

This commit is contained in:
KotlinGeekDev
2025-09-23 12:22:45 +01:00
1198 changed files with 12708 additions and 5211 deletions
+3
View File
@@ -339,6 +339,9 @@ dependencies {
// Cbor for cashuB format
implementation libs.kotlinx.serialization.cbor
// Kotlin serialization for the times where we need the Json tree and performance is not that important.
implementation(libs.kotlinx.serialization.json)
implementation libs.tor.android
implementation libs.jtorctl
@@ -24,8 +24,9 @@ import androidx.test.ext.junit.runners.AndroidJUnit4
import com.vitorpamplona.amethyst.service.cashu.CashuParser
import com.vitorpamplona.amethyst.service.cashu.CashuToken
import com.vitorpamplona.amethyst.ui.components.GenericLoadable
import junit.framework.TestCase.assertEquals
import kotlinx.collections.immutable.ImmutableList
import kotlinx.coroutines.runBlocking
import org.junit.Assert.assertEquals
import org.junit.Test
import org.junit.runner.RunWith
@@ -38,7 +39,7 @@ class CashuBTest {
@Test()
fun parseCashuA() {
runBlocking {
val parsed = (CashuParser().parse(cashuTokenA) as GenericLoadable.Loaded<List<CashuToken>>).loaded[0]
val parsed = (CashuParser().parse(cashuTokenA) as GenericLoadable.Loaded<ImmutableList<CashuToken>>).loaded[0]
assertEquals(cashuTokenA, parsed.token)
assertEquals("https://8333.space:3338", parsed.mint)
@@ -59,7 +60,7 @@ class CashuBTest {
@Test()
fun parseCashuB() =
runBlocking {
val parsed = (CashuParser().parse(cashuTokenB1) as GenericLoadable.Loaded<List<CashuToken>>).loaded
val parsed = (CashuParser().parse(cashuTokenB1) as GenericLoadable.Loaded<ImmutableList<CashuToken>>).loaded
assertEquals(cashuTokenB1, parsed[0].token)
assertEquals("http://localhost:3338", parsed[0].mint)
@@ -84,7 +85,7 @@ class CashuBTest {
@Test()
fun parseCashuB2() =
runBlocking {
val parsed = (CashuParser().parse(cashuTokenB2) as GenericLoadable.Loaded<List<CashuToken>>).loaded
val parsed = (CashuParser().parse(cashuTokenB2) as GenericLoadable.Loaded<ImmutableList<CashuToken>>).loaded
assertEquals(cashuTokenB2, parsed[0].token)
assertEquals("http://lbutlh5lfggq5r7xpiwhrajdl7sxpupgagazxl65w4c5cg72wtofasad.onion:3338", parsed[0].mint)
@@ -24,10 +24,10 @@ import androidx.test.ext.junit.runners.AndroidJUnit4
import com.vitorpamplona.amethyst.service.okhttp.EncryptedBlobInterceptor
import com.vitorpamplona.amethyst.service.okhttp.EncryptionKeyCache
import com.vitorpamplona.quartz.nip01Core.core.hexToByteArray
import com.vitorpamplona.quartz.nip17Dm.files.encryption.AESGCM
import junit.framework.TestCase.assertEquals
import com.vitorpamplona.quartz.utils.ciphers.AESGCM
import okhttp3.OkHttpClient
import okhttp3.Request
import org.junit.Assert.assertEquals
import org.junit.Test
import org.junit.runner.RunWith
@@ -41,7 +41,6 @@ import com.vitorpamplona.quartz.nip01Core.crypto.KeyPair
import com.vitorpamplona.quartz.nip01Core.signers.NostrSignerInternal
import com.vitorpamplona.quartz.nip98HttpAuth.HTTPAuthorizationEvent
import com.vitorpamplona.quartz.utils.sha256.sha256
import junit.framework.TestCase.assertEquals
import junit.framework.TestCase.fail
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
@@ -49,6 +48,7 @@ import kotlinx.coroutines.SupervisorJob
import kotlinx.coroutines.runBlocking
import okhttp3.OkHttpClient
import org.junit.Assert
import org.junit.Assert.assertEquals
import org.junit.Ignore
import org.junit.Test
import org.junit.runner.RunWith
@@ -247,13 +247,6 @@ class ImageUploadTesting {
testBase(ServerName("sovbit", "https://files.sovbit.host", ServerType.NIP96))
}
@Test()
@Ignore("Not Working anymore")
fun testVoidCat() =
runBlocking {
testBase(ServerName("void.cat", "https://void.cat", ServerType.NIP96))
}
@Test()
@Ignore("Returns invalid image size")
fun testNostrPic() =
@@ -21,17 +21,15 @@
package com.vitorpamplona.amethyst
import androidx.test.ext.junit.runners.AndroidJUnit4
import com.vitorpamplona.quartz.nip01Core.core.OptimizedJsonMapper
import com.vitorpamplona.quartz.nip01Core.crypto.KeyPair
import com.vitorpamplona.quartz.nip01Core.jackson.JsonMapper
import com.vitorpamplona.quartz.nip01Core.signers.NostrSignerInternal
import com.vitorpamplona.quartz.nip03Timestamp.OtsEvent
import com.vitorpamplona.quartz.nip03Timestamp.OtsResolver
import com.vitorpamplona.quartz.nip03Timestamp.ots.okhttp.OkHttpBitcoinExplorer
import com.vitorpamplona.quartz.nip03Timestamp.ots.okhttp.OkHttpCalendarBuilder
import com.vitorpamplona.quartz.nip03Timestamp.ots.okhttp.OtsBlockHeightCache
import junit.framework.TestCase.assertEquals
import com.vitorpamplona.quartz.nip03Timestamp.okhttp.OkHttpOtsResolverBuilder
import com.vitorpamplona.quartz.nip03Timestamp.ots.OtsBlockHeightCache
import kotlinx.coroutines.runBlocking
import okhttp3.OkHttpClient
import org.junit.Assert.assertEquals
import org.junit.Test
import org.junit.runner.RunWith
@@ -45,51 +43,50 @@ class OkHttpOtsTest {
val otsCache = OtsBlockHeightCache()
val resolver =
OtsResolver(
OkHttpBitcoinExplorer(
baseAPI = OkHttpBitcoinExplorer.MEMPOOL_API_URL,
client = OkHttpClient.Builder().build(),
cache = otsCache,
),
OkHttpCalendarBuilder { OkHttpClient.Builder().build() },
)
OkHttpOtsResolverBuilder(
otsCache,
) { OkHttpClient.Builder().build() }.build()
@Test
fun verifyNostrEvent() {
val ots = JsonMapper.fromJson(otsEvent) as OtsEvent
println(resolver.info(ots.otsByteArray()))
assertEquals(1707688818L, ots.verify(resolver))
}
fun verifyNostrEvent() =
runBlocking {
val ots = OptimizedJsonMapper.fromJson(otsEvent) as OtsEvent
println(resolver.info(ots.otsByteArray()))
assertEquals(1707688818L, ots.verify(resolver))
}
@Test
fun verifyNostrEvent2() {
val ots = JsonMapper.fromJson(otsEvent2) as OtsEvent
println(resolver.info(ots.otsByteArray()))
assertEquals(1706322179L, ots.verify(resolver))
}
fun verifyNostrEvent2() =
runBlocking {
val ots = OptimizedJsonMapper.fromJson(otsEvent2) as OtsEvent
println(resolver.info(ots.otsByteArray()))
assertEquals(1706322179L, ots.verify(resolver))
}
@Test
fun verifyNostrPendingEvent() {
val ots = JsonMapper.fromJson(otsPendingEvent) as OtsEvent
println(resolver.info(ots.otsByteArray()))
assertEquals(null, ots.verify(resolver))
}
fun verifyNostrPendingEvent() =
runBlocking {
val ots = OptimizedJsonMapper.fromJson(otsPendingEvent) as OtsEvent
println(resolver.info(ots.otsByteArray()))
assertEquals(null, ots.verify(resolver))
}
@Test
fun createOTSEventAndVerify() {
val signer = NostrSignerInternal(KeyPair())
fun createOTSEventAndVerify() =
runBlocking {
val signer = NostrSignerInternal(KeyPair())
val otsFile = OtsEvent.stamp(otsEvent2Digest, resolver)
val otsFile = OtsEvent.stamp(otsEvent2Digest, resolver)
val ots =
runBlocking {
signer.sign(OtsEvent.build(otsEvent2Digest, otsFile))
}
val ots =
runBlocking {
signer.sign(OtsEvent.build(otsEvent2Digest, otsFile))
}
println(ots.toJson())
println(resolver.info(ots.otsByteArray()))
println(ots.toJson())
println(resolver.info(ots.otsByteArray()))
// Should not be valid because we need to wait for confirmations
assertEquals(null, ots.verify(resolver))
}
// Should not be valid because we need to wait for confirmations
assertEquals(null, ots.verify(resolver))
}
}
@@ -28,24 +28,23 @@ import com.vitorpamplona.amethyst.model.LocalCache
import com.vitorpamplona.amethyst.service.location.LocationState
import com.vitorpamplona.amethyst.service.okhttp.OkHttpWebSocket
import com.vitorpamplona.amethyst.service.relayClient.reqCommand.nwc.NWCPaymentFilterAssembler
import com.vitorpamplona.amethyst.ui.screen.loggedIn.EmptyOtsResolverBuilder
import com.vitorpamplona.amethyst.ui.screen.loggedIn.threadview.dal.ThreadFeedFilter
import com.vitorpamplona.quartz.nip01Core.core.Event
import com.vitorpamplona.quartz.nip01Core.crypto.KeyPair
import com.vitorpamplona.quartz.nip01Core.jackson.JsonMapper
import com.vitorpamplona.quartz.nip01Core.crypto.verify
import com.vitorpamplona.quartz.nip01Core.jackson.JacksonMapper
import com.vitorpamplona.quartz.nip01Core.relay.client.NostrClient
import com.vitorpamplona.quartz.nip01Core.signers.NostrSignerInternal
import com.vitorpamplona.quartz.nip01Core.tags.addressables.ATag
import com.vitorpamplona.quartz.nip01Core.verify
import com.vitorpamplona.quartz.nip03Timestamp.ots.okhttp.OkHttpOtsResolverBuilder
import com.vitorpamplona.quartz.nip03Timestamp.ots.okhttp.OtsBlockHeightCache
import com.vitorpamplona.quartz.nip01Core.tags.aTag.ATag
import junit.framework.TestCase
import junit.framework.TestCase.assertEquals
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.SupervisorJob
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.runBlocking
import okhttp3.OkHttpClient
import org.junit.Assert.assertEquals
import org.junit.Test
import org.junit.runner.RunWith
@@ -53,43 +52,30 @@ import org.junit.runner.RunWith
class ThreadDualAxisChartAssemblerTest {
companion object {
val keyPair = KeyPair()
val scope = CoroutineScope(Dispatchers.IO + SupervisorJob())
val client =
NostrClient(
OkHttpWebSocket.Builder {
OkHttpClient
.Builder()
.followRedirects(true)
.followSslRedirects(true)
.build()
},
scope,
)
val account =
Account(
settings = AccountSettings(keyPair = keyPair),
signer = NostrSignerInternal(keyPair),
scope = CoroutineScope(Dispatchers.IO + SupervisorJob()),
geolocationFlow = MutableStateFlow<LocationState.LocationResult>(LocationState.LocationResult.Loading),
nwcFilterAssembler = NWCPaymentFilterAssembler(client),
otsResolverBuilder = EmptyOtsResolverBuilder,
cache = LocalCache,
client =
NostrClient(
OkHttpWebSocket.Builder {
OkHttpClient
.Builder()
.followRedirects(true)
.followSslRedirects(true)
.build()
},
CoroutineScope(Dispatchers.IO + SupervisorJob()),
),
nwcFilterAssembler =
NWCPaymentFilterAssembler(
NostrClient(
OkHttpWebSocket.Builder {
OkHttpClient
.Builder()
.followRedirects(true)
.followSslRedirects(true)
.build()
},
CoroutineScope(Dispatchers.IO + SupervisorJob()),
),
),
otsResolverBuilder =
OkHttpOtsResolverBuilder(
okHttpClient = { OkHttpClient.Builder().build() },
isTorActive = { false },
cache = OtsBlockHeightCache(),
),
client = client,
scope = scope,
)
val db =
@@ -171,7 +157,7 @@ class ThreadDualAxisChartAssemblerTest {
fun threadOrderTest() =
runBlocking {
val eventArray =
JsonMapper.mapper.readValue<ArrayList<Event>>(db) as List<Event> + Event.fromJson(header)
JacksonMapper.mapper.readValue<List<Event>>(db) + Event.fromJson(header)
var counter = 0
eventArray.forEach {
@@ -191,7 +177,7 @@ class ThreadDualAxisChartAssemblerTest {
val filter = ThreadFeedFilter(account, naddr.toTag())
val calculatedFeed = filter.feed()
val expecteedOrder =
val expectedOrder =
listOf(
"30023:6e468422dfb74a5738702a8823b9b28168abab8655faacb6853cd0ee15deee93:1680612926599",
"e15b386824fbfdcbf1b50b8860f03062cef534a3ea5339cc837536fb2a58465e",
@@ -233,8 +219,8 @@ class ThreadDualAxisChartAssemblerTest {
"7a18dda355525d468b31bba4fa947cba98cc19048d4a3099d5e9ba045d878c26",
)
for (i in expecteedOrder.indices) {
assertEquals(expecteedOrder[i], calculatedFeed[i].idHex)
for (i in expectedOrder.indices) {
assertEquals(expectedOrder[i], calculatedFeed[i].idHex)
}
}
}
@@ -21,7 +21,7 @@
package com.vitorpamplona.amethyst
import com.vitorpamplona.amethyst.ui.navigation.findParameterValue
import junit.framework.TestCase.assertEquals
import org.junit.Assert.assertEquals
import org.junit.Test
import java.net.URI
@@ -23,8 +23,8 @@ package com.vitorpamplona.amethyst.service.notifications
import android.content.Context
import android.content.pm.PackageManager
import android.os.Build
import android.util.Log
import com.vitorpamplona.amethyst.Amethyst
import com.vitorpamplona.quartz.utils.Log
import org.unifiedpush.android.connector.UnifiedPush
interface PushDistributorActions {
@@ -22,13 +22,13 @@ package com.vitorpamplona.amethyst.service.notifications
import android.app.NotificationManager
import android.content.Context
import android.util.Log
import android.util.LruCache
import androidx.core.content.ContextCompat
import com.vitorpamplona.amethyst.Amethyst
import com.vitorpamplona.amethyst.LocalPreferences
import com.vitorpamplona.quartz.nip01Core.core.Event
import com.vitorpamplona.quartz.nip59Giftwrap.wraps.GiftWrapEvent
import com.vitorpamplona.quartz.utils.Log
import kotlinx.coroutines.CancellationException
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch
@@ -22,7 +22,6 @@ package com.vitorpamplona.amethyst.ui.components
import android.Manifest
import android.os.Build
import android.util.Log
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.PaddingValues
import androidx.compose.foundation.layout.Row
@@ -64,6 +63,7 @@ import com.vitorpamplona.amethyst.ui.components.SpinnerSelectionDialog
import com.vitorpamplona.amethyst.ui.components.TitleExplainer
import com.vitorpamplona.amethyst.ui.screen.loggedIn.settings.SettingsRow
import com.vitorpamplona.amethyst.ui.stringRes
import com.vitorpamplona.quartz.utils.Log
import kotlinx.collections.immutable.ImmutableList
import kotlinx.collections.immutable.toImmutableList
@@ -28,7 +28,7 @@ import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color
import com.vitorpamplona.amethyst.ui.navigation.navs.INav
import com.vitorpamplona.amethyst.ui.screen.loggedIn.AccountViewModel
import com.vitorpamplona.quartz.nip02FollowList.ImmutableListOfLists
import com.vitorpamplona.quartz.nip01Core.core.ImmutableListOfLists
@Composable
fun TranslatableRichTextViewer(
@@ -21,8 +21,8 @@
package com.vitorpamplona.amethyst
import android.app.Application
import android.util.Log
import com.vitorpamplona.amethyst.service.logging.Logging
import com.vitorpamplona.quartz.utils.Log
class Amethyst : Application() {
companion object {
@@ -22,13 +22,13 @@ package com.vitorpamplona.amethyst
import android.content.ContentResolver
import android.content.Context
import android.util.Log
import androidx.security.crypto.EncryptedSharedPreferences
import coil3.disk.DiskCache
import coil3.memory.MemoryCache
import com.vitorpamplona.amethyst.model.LocalCache
import com.vitorpamplona.amethyst.model.accountsCache.AccountCacheState
import com.vitorpamplona.amethyst.model.nip03Timestamp.IncomingOtsEventVerifier
import com.vitorpamplona.amethyst.model.nip03Timestamp.TorAwareOkHttpOtsResolverBuilder
import com.vitorpamplona.amethyst.model.nip11RelayInfo.Nip11CachedRetriever
import com.vitorpamplona.amethyst.model.preferences.TorSharedPreferences
import com.vitorpamplona.amethyst.model.preferences.UiSharedPreferences
@@ -60,8 +60,8 @@ import com.vitorpamplona.amethyst.ui.tor.TorManager
import com.vitorpamplona.quartz.nip01Core.relay.client.INostrClient
import com.vitorpamplona.quartz.nip01Core.relay.client.NostrClient
import com.vitorpamplona.quartz.nip03Timestamp.VerificationStateCache
import com.vitorpamplona.quartz.nip03Timestamp.ots.okhttp.OkHttpOtsResolverBuilder
import com.vitorpamplona.quartz.nip03Timestamp.ots.okhttp.OtsBlockHeightCache
import com.vitorpamplona.quartz.nip03Timestamp.ots.OtsBlockHeightCache
import com.vitorpamplona.quartz.utils.Log
import kotlinx.coroutines.CoroutineExceptionHandler
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
@@ -146,8 +146,8 @@ class AppModules(
// Application-wide block height request cache
val otsBlockHeightCache by lazy { OtsBlockHeightCache() }
val otsResolverBuilder: OkHttpOtsResolverBuilder =
OkHttpOtsResolverBuilder(
val otsResolverBuilder: TorAwareOkHttpOtsResolverBuilder =
TorAwareOkHttpOtsResolverBuilder(
roleBasedHttpClientBuilder::okHttpClientForMoney,
roleBasedHttpClientBuilder::shouldUseTorForMoneyOperations,
otsBlockHeightCache,
@@ -24,9 +24,9 @@ import android.app.ActivityManager
import android.content.Context
import android.content.pm.ApplicationInfo
import android.os.Debug
import android.util.Log
import androidx.core.content.getSystemService
import com.vitorpamplona.amethyst.model.LocalCache
import com.vitorpamplona.quartz.utils.Log
import kotlin.time.DurationUnit
import kotlin.time.measureTimedValue
@@ -23,10 +23,8 @@ package com.vitorpamplona.amethyst
import android.annotation.SuppressLint
import android.content.Context
import android.content.SharedPreferences
import android.util.Log
import androidx.compose.runtime.Immutable
import androidx.core.content.edit
import com.fasterxml.jackson.module.kotlin.readValue
import com.vitorpamplona.amethyst.model.ALL_FOLLOWS
import com.vitorpamplona.amethyst.model.AccountSettings
import com.vitorpamplona.amethyst.model.GLOBAL_FOLLOWS
@@ -37,10 +35,11 @@ import com.vitorpamplona.amethyst.ui.actions.mediaServers.ServerName
import com.vitorpamplona.quartz.experimental.ephemChat.list.EphemeralChatListEvent
import com.vitorpamplona.quartz.nip01Core.core.Event
import com.vitorpamplona.quartz.nip01Core.core.HexKey
import com.vitorpamplona.quartz.nip01Core.core.JsonMapper
import com.vitorpamplona.quartz.nip01Core.core.OptimizedJsonMapper
import com.vitorpamplona.quartz.nip01Core.core.hexToByteArray
import com.vitorpamplona.quartz.nip01Core.core.toHexKey
import com.vitorpamplona.quartz.nip01Core.crypto.KeyPair
import com.vitorpamplona.quartz.nip01Core.jackson.JsonMapper
import com.vitorpamplona.quartz.nip01Core.metadata.MetadataEvent
import com.vitorpamplona.quartz.nip02FollowList.ContactListEvent
import com.vitorpamplona.quartz.nip17Dm.settings.ChatMessageRelayListEvent
@@ -57,13 +56,16 @@ import com.vitorpamplona.quartz.nip51Lists.relayLists.TrustedRelayListEvent
import com.vitorpamplona.quartz.nip65RelayList.AdvertisedRelayListEvent
import com.vitorpamplona.quartz.nip72ModCommunities.follow.CommunityListEvent
import com.vitorpamplona.quartz.nip78AppData.AppSpecificDataEvent
import com.vitorpamplona.quartz.utils.Log
import kotlinx.coroutines.CancellationException
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.sync.Mutex
import kotlinx.coroutines.sync.withLock
import kotlinx.coroutines.withContext
import kotlinx.serialization.Serializable
import java.io.File
import kotlin.jvm.java
// Release mode (!BuildConfig.DEBUG) always uses encrypted preferences
// To use plaintext SharedPreferences for debugging, set this to true
@@ -72,6 +74,7 @@ private const val DEBUG_PLAINTEXT_PREFERENCES = false
private const val DEBUG_PREFERENCES_NAME = "debug_prefs"
@Immutable
@Serializable
data class AccountInfo(
val npub: String,
val hasPrivKey: Boolean,
@@ -161,7 +164,7 @@ object LocalPreferences {
with(encryptedPreferences()) {
val newSystemOfAccounts =
getString(PrefKeys.ALL_ACCOUNT_INFO, "[]")?.let {
JsonMapper.mapper.readValue<List<AccountInfo>>(it)
JsonMapper.fromJson<List<AccountInfo>>(it)
}
if (!newSystemOfAccounts.isNullOrEmpty()) {
@@ -181,7 +184,9 @@ object LocalPreferences {
savedAccounts.emit(migrated)
edit { putString(PrefKeys.ALL_ACCOUNT_INFO, JsonMapper.mapper.writeValueAsString(savedAccounts.value)) }
edit {
putString(PrefKeys.ALL_ACCOUNT_INFO, JsonMapper.toJson(migrated))
}
}
}
}
@@ -201,7 +206,7 @@ object LocalPreferences {
.edit {
putString(
PrefKeys.ALL_ACCOUNT_INFO,
JsonMapper.mapper.writeValueAsString(accounts.filter { !it.isTransient }),
JsonMapper.toJson(accounts.filter { !it.isTransient }),
)
}
}
@@ -308,7 +313,7 @@ object LocalPreferences {
putString(
PrefKeys.DEFAULT_FILE_SERVER,
JsonMapper.mapper.writeValueAsString(settings.defaultFileServer),
JsonMapper.toJson(settings.defaultFileServer),
)
putString(PrefKeys.DEFAULT_HOME_FOLLOW_LIST, settings.defaultHomeFollowList.value)
putString(PrefKeys.DEFAULT_STORIES_FOLLOW_LIST, settings.defaultStoriesFollowList.value)
@@ -320,72 +325,16 @@ object LocalPreferences {
PrefKeys.DEFAULT_DISCOVERY_FOLLOW_LIST,
settings.defaultDiscoveryFollowList.value,
)
putString(
PrefKeys.ZAP_PAYMENT_REQUEST_SERVER,
JsonMapper.mapper.writeValueAsString(settings.zapPaymentRequest.value?.denormalize()),
)
if (settings.backupContactList != null) {
putString(
PrefKeys.LATEST_CONTACT_LIST,
JsonMapper.mapper.writeValueAsString(settings.backupContactList),
)
} else {
remove(PrefKeys.LATEST_CONTACT_LIST)
}
putOrRemove(PrefKeys.ZAP_PAYMENT_REQUEST_SERVER, settings.zapPaymentRequest.value?.denormalize())
if (settings.backupUserMetadata != null) {
putString(
PrefKeys.LATEST_USER_METADATA,
JsonMapper.mapper.writeValueAsString(settings.backupUserMetadata),
)
} else {
remove(PrefKeys.LATEST_USER_METADATA)
}
putOrRemove(PrefKeys.LATEST_CONTACT_LIST, settings.backupContactList)
if (settings.backupDMRelayList != null) {
putString(
PrefKeys.LATEST_DM_RELAY_LIST,
JsonMapper.mapper.writeValueAsString(settings.backupDMRelayList),
)
} else {
remove(PrefKeys.LATEST_DM_RELAY_LIST)
}
if (settings.backupNIP65RelayList != null) {
putString(
PrefKeys.LATEST_NIP65_RELAY_LIST,
JsonMapper.mapper.writeValueAsString(settings.backupNIP65RelayList),
)
} else {
remove(PrefKeys.LATEST_NIP65_RELAY_LIST)
}
if (settings.backupSearchRelayList != null) {
putString(
PrefKeys.LATEST_SEARCH_RELAY_LIST,
JsonMapper.mapper.writeValueAsString(settings.backupSearchRelayList),
)
} else {
remove(PrefKeys.LATEST_SEARCH_RELAY_LIST)
}
if (settings.backupBlockedRelayList != null) {
putString(
PrefKeys.LATEST_BLOCKED_RELAY_LIST,
JsonMapper.mapper.writeValueAsString(settings.backupBlockedRelayList),
)
} else {
remove(PrefKeys.LATEST_BLOCKED_RELAY_LIST)
}
if (settings.backupTrustedRelayList != null) {
putString(
PrefKeys.LATEST_TRUSTED_RELAY_LIST,
JsonMapper.mapper.writeValueAsString(settings.backupTrustedRelayList),
)
} else {
remove(PrefKeys.LATEST_TRUSTED_RELAY_LIST)
}
putOrRemove(PrefKeys.LATEST_USER_METADATA, settings.backupUserMetadata)
putOrRemove(PrefKeys.LATEST_DM_RELAY_LIST, settings.backupDMRelayList)
putOrRemove(PrefKeys.LATEST_NIP65_RELAY_LIST, settings.backupNIP65RelayList)
putOrRemove(PrefKeys.LATEST_SEARCH_RELAY_LIST, settings.backupSearchRelayList)
putOrRemove(PrefKeys.LATEST_BLOCKED_RELAY_LIST, settings.backupBlockedRelayList)
putOrRemove(PrefKeys.LATEST_TRUSTED_RELAY_LIST, settings.backupTrustedRelayList)
if (settings.localRelayServers.value.isNotEmpty()) {
putStringSet(PrefKeys.LOCAL_RELAY_SERVERS, settings.localRelayServers.value)
@@ -393,77 +342,15 @@ object LocalPreferences {
remove(PrefKeys.LOCAL_RELAY_SERVERS)
}
if (settings.backupMuteList != null) {
putString(
PrefKeys.LATEST_MUTE_LIST,
JsonMapper.mapper.writeValueAsString(settings.backupMuteList),
)
} else {
remove(PrefKeys.LATEST_MUTE_LIST)
}
putOrRemove(PrefKeys.LATEST_MUTE_LIST, settings.backupMuteList)
putOrRemove(PrefKeys.LATEST_PRIVATE_HOME_RELAY_LIST, settings.backupPrivateHomeRelayList)
putOrRemove(PrefKeys.LATEST_APP_SPECIFIC_DATA, settings.backupAppSpecificData)
if (settings.backupPrivateHomeRelayList != null) {
putString(
PrefKeys.LATEST_PRIVATE_HOME_RELAY_LIST,
JsonMapper.mapper.writeValueAsString(settings.backupPrivateHomeRelayList),
)
} else {
remove(PrefKeys.LATEST_PRIVATE_HOME_RELAY_LIST)
}
if (settings.backupAppSpecificData != null) {
putString(
PrefKeys.LATEST_APP_SPECIFIC_DATA,
JsonMapper.mapper.writeValueAsString(settings.backupAppSpecificData),
)
} else {
remove(PrefKeys.LATEST_APP_SPECIFIC_DATA)
}
if (settings.backupChannelList != null) {
putString(
PrefKeys.LATEST_CHANNEL_LIST,
JsonMapper.mapper.writeValueAsString(settings.backupChannelList),
)
} else {
remove(PrefKeys.LATEST_CHANNEL_LIST)
}
if (settings.backupCommunityList != null) {
putString(
PrefKeys.LATEST_COMMUNITY_LIST,
JsonMapper.mapper.writeValueAsString(settings.backupCommunityList),
)
} else {
remove(PrefKeys.LATEST_COMMUNITY_LIST)
}
if (settings.backupHashtagList != null) {
putString(
PrefKeys.LATEST_HASHTAG_LIST,
JsonMapper.mapper.writeValueAsString(settings.backupHashtagList),
)
} else {
remove(PrefKeys.LATEST_HASHTAG_LIST)
}
if (settings.backupGeohashList != null) {
putString(
PrefKeys.LATEST_GEOHASH_LIST,
JsonMapper.mapper.writeValueAsString(settings.backupGeohashList),
)
} else {
remove(PrefKeys.LATEST_GEOHASH_LIST)
}
if (settings.backupEphemeralChatList != null) {
putString(
PrefKeys.LATEST_EPHEMERAL_LIST,
JsonMapper.mapper.writeValueAsString(settings.backupEphemeralChatList),
)
} else {
remove(PrefKeys.LATEST_EPHEMERAL_LIST)
}
putOrRemove(PrefKeys.LATEST_CHANNEL_LIST, settings.backupChannelList)
putOrRemove(PrefKeys.LATEST_COMMUNITY_LIST, settings.backupCommunityList)
putOrRemove(PrefKeys.LATEST_HASHTAG_LIST, settings.backupHashtagList)
putOrRemove(PrefKeys.LATEST_GEOHASH_LIST, settings.backupGeohashList)
putOrRemove(PrefKeys.LATEST_EPHEMERAL_LIST, settings.backupEphemeralChatList)
putBoolean(PrefKeys.HIDE_DELETE_REQUEST_DIALOG, settings.hideDeleteRequestDialog)
putBoolean(PrefKeys.HIDE_NIP_17_WARNING_DIALOG, settings.hideNIP17WarningDialog)
@@ -480,13 +367,13 @@ object LocalPreferences {
putString(
PrefKeys.LAST_READ_PER_ROUTE,
JsonMapper.mapper.writeValueAsString(regularMap),
JsonMapper.toJson(regularMap),
)
putStringSet(PrefKeys.HAS_DONATED_IN_VERSION, settings.hasDonatedInVersion.value)
putString(
PrefKeys.PENDING_ATTESTATIONS,
JsonMapper.mapper.writeValueAsString(settings.pendingAttestations.value),
JsonMapper.toJson(settings.pendingAttestations.value),
)
}
}
@@ -502,7 +389,7 @@ object LocalPreferences {
) {
Log.d("LocalPreferences", "Saving to shared settings")
prefs.edit {
putString(PrefKeys.SHARED_SETTINGS, JsonMapper.mapper.writeValueAsString(sharedSettings))
putString(PrefKeys.SHARED_SETTINGS, JsonMapper.toJson(sharedSettings))
}
}
@@ -511,7 +398,7 @@ object LocalPreferences {
with(prefs) {
return try {
getString(PrefKeys.SHARED_SETTINGS, "{}")?.let {
JsonMapper.mapper.readValue<UiSettings>(it)
JsonMapper.fromJson<UiSettings>(it)
}
} catch (e: Throwable) {
if (e is CancellationException) throw e
@@ -643,7 +530,7 @@ object LocalPreferences {
return result
}
private inline fun <reified T> SharedPreferences.parseOrNull(key: String): T? {
private inline fun <reified T : Any> SharedPreferences.parseOrNull(key: String): T? {
val value = getString(key, null)
if (value.isNullOrEmpty() || value == "null") {
return null
@@ -652,7 +539,7 @@ object LocalPreferences {
if (T::class.java.isInstance(Event::class.java)) {
Event.fromJson(value) as T?
} else {
JsonMapper.mapper.readValue<T?>(value)
JsonMapper.fromJson<T>(value)
}
} catch (e: Throwable) {
if (e is CancellationException) throw e
@@ -674,4 +561,26 @@ object LocalPreferences {
null
}
}
fun SharedPreferences.Editor.putOrRemove(
key: String,
event: Any?,
) {
if (event != null) {
putString(key, JsonMapper.toJson(event))
} else {
remove(key)
}
}
fun SharedPreferences.Editor.putOrRemove(
key: String,
event: Event?,
) {
if (event != null) {
putString(key, OptimizedJsonMapper.toJson(event))
} else {
remove(key)
}
}
}
@@ -20,7 +20,6 @@
*/
package com.vitorpamplona.amethyst.model
import android.util.Log
import androidx.compose.runtime.Stable
import com.vitorpamplona.amethyst.BuildConfig
import com.vitorpamplona.amethyst.LocalPreferences
@@ -205,6 +204,7 @@ import com.vitorpamplona.quartz.nip94FileMetadata.tags.DimensionTag
import com.vitorpamplona.quartz.nip98HttpAuth.HTTPAuthorizationEvent
import com.vitorpamplona.quartz.nipA0VoiceMessages.VoiceEvent
import com.vitorpamplona.quartz.nipA0VoiceMessages.VoiceReplyEvent
import com.vitorpamplona.quartz.utils.Log
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.DelicateCoroutinesApi
import kotlinx.coroutines.Dispatchers
@@ -804,27 +804,27 @@ class Account(
}
}
fun broadcast(note: Note) {
note.event?.let {
if (it is WrappedEvent && it.host != null) {
suspend fun broadcast(note: Note) {
note.event?.let { noteEvent ->
if (noteEvent is WrappedEvent && noteEvent.host != null) {
// download the event and send it.
it.host?.let { host ->
client.downloadFirstEvent(
filters =
note.relays.associateWith { relay ->
listOf(
Filter(
ids = listOf(host.id),
),
)
},
onResponse = {
client.send(it, computeRelayListToBroadcast(it))
},
)
noteEvent.host?.let { host ->
client
.downloadFirstEvent(
filters =
note.relays.associateWith { relay ->
listOf(
Filter(
ids = listOf(host.id),
),
)
},
)?.let { downloadedEvent ->
client.send(downloadedEvent, computeRelayListToBroadcast(downloadedEvent))
}
}
} else {
client.send(it, computeRelayListToBroadcast(note))
client.send(noteEvent, computeRelayListToBroadcast(note))
}
}
}
@@ -23,6 +23,7 @@ package com.vitorpamplona.amethyst.model
import android.content.res.Resources
import androidx.core.os.ConfigurationCompat
import com.vitorpamplona.quartz.nip57Zaps.LnZapEvent
import kotlinx.serialization.Serializable
import java.util.Locale
val DefaultReactions =
@@ -47,6 +48,7 @@ fun getLanguagesSpokenByUser(): Set<String> {
return codedList
}
@Serializable
class AccountSyncedSettingsInternal(
val reactions: AccountReactionPreferencesInternal = AccountReactionPreferencesInternal(),
val zaps: AccountZapPreferencesInternal = AccountZapPreferencesInternal(),
@@ -54,21 +56,25 @@ class AccountSyncedSettingsInternal(
val security: AccountSecurityPreferencesInternal = AccountSecurityPreferencesInternal(),
)
@Serializable
class AccountReactionPreferencesInternal(
var reactionChoices: List<String> = DefaultReactions,
)
@Serializable
class AccountZapPreferencesInternal(
var zapAmountChoices: List<Long> = DefaultZapAmounts,
val defaultZapType: LnZapEvent.ZapType = LnZapEvent.ZapType.PUBLIC,
)
@Serializable
class AccountLanguagePreferencesInternal(
var dontTranslateFrom: Set<String> = getLanguagesSpokenByUser(),
var languagePreferences: Map<String, String> = mapOf(),
var translateTo: String = Locale.getDefault().language,
)
@Serializable
class AccountSecurityPreferencesInternal(
val showSensitiveContent: Boolean? = null,
var warnAboutPostsWithReports: Boolean = true,
@@ -20,18 +20,18 @@
*/
package com.vitorpamplona.amethyst.model
import android.util.Log
import android.util.LruCache
import com.vitorpamplona.amethyst.ui.note.njumpLink
import com.vitorpamplona.quartz.nip01Core.core.Address
import com.vitorpamplona.quartz.nip01Core.core.AddressableEvent
import com.vitorpamplona.quartz.nip01Core.core.Event
import com.vitorpamplona.quartz.nip01Core.core.HexKey
import com.vitorpamplona.quartz.nip01Core.relay.client.stats.RelayStats
import com.vitorpamplona.quartz.nip01Core.relay.normalizer.NormalizedRelayUrl
import com.vitorpamplona.quartz.nip01Core.tags.addressables.Address
import com.vitorpamplona.quartz.nip19Bech32.Nip19Parser
import com.vitorpamplona.quartz.nip19Bech32.entities.NAddress
import com.vitorpamplona.quartz.nip19Bech32.entities.NEvent
import com.vitorpamplona.quartz.utils.Log
import kotlinx.coroutines.flow.MutableStateFlow
data class Spammer(
@@ -65,7 +65,7 @@ class AntiSpamFilter {
// really long, make it ok.
// The idea here is to avoid considering repeated "@Bot, command" messages spam, while still
// blocking repeated "lnbc..." invoices or fishing urls
if (event.content.length < 180 && event.content.startsWith("nostr:") && Nip19Parser.nip19regex.matcher(event.content).find()) return false
if (event.content.length < 180 && event.content.startsWith("nostr:") && Nip19Parser.hasAny(event.content)) return false
// double list strategy:
// if duplicated, it goes into spam. 1000 spam messages are saved into the spam list.
@@ -25,7 +25,7 @@ import com.vitorpamplona.amethyst.ui.dal.DefaultFeedOrder
import com.vitorpamplona.amethyst.ui.dal.ListChange
import com.vitorpamplona.quartz.nip01Core.core.HexKey
import com.vitorpamplona.quartz.nip01Core.relay.normalizer.NormalizedRelayUrl
import com.vitorpamplona.quartz.utils.LargeCache
import com.vitorpamplona.quartz.utils.cache.LargeCache
import kotlinx.coroutines.channels.BufferOverflow
import kotlinx.coroutines.flow.MutableSharedFlow
import kotlinx.coroutines.flow.MutableStateFlow
@@ -51,7 +51,7 @@ import com.vitorpamplona.amethyst.ui.components.HashTag
import com.vitorpamplona.amethyst.ui.components.RenderRegular
import com.vitorpamplona.amethyst.ui.navigation.navs.EmptyNav
import com.vitorpamplona.amethyst.ui.theme.ThemeComparisonColumn
import com.vitorpamplona.quartz.nip02FollowList.EmptyTagList
import com.vitorpamplona.quartz.nip01Core.core.EmptyTagList
@Preview
@Composable
@@ -18,8 +18,9 @@
* 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
package com.vitorpamplona.amethyst.model
import com.vitorpamplona.quartz.utils.cache.CacheOperations
import java.lang.ref.WeakReference
import java.util.concurrent.ConcurrentSkipListMap
import java.util.function.BiConsumer
@@ -20,7 +20,6 @@
*/
package com.vitorpamplona.amethyst.model
import android.util.Log
import android.util.LruCache
import androidx.compose.runtime.Stable
import com.vitorpamplona.amethyst.Amethyst
@@ -52,12 +51,14 @@ import com.vitorpamplona.quartz.experimental.profileGallery.ProfileGalleryEntryE
import com.vitorpamplona.quartz.experimental.publicMessages.PublicMessageEvent
import com.vitorpamplona.quartz.experimental.relationshipStatus.ContactCardEvent
import com.vitorpamplona.quartz.experimental.zapPolls.PollNoteEvent
import com.vitorpamplona.quartz.nip01Core.checkSignature
import com.vitorpamplona.quartz.nip01Core.core.Address
import com.vitorpamplona.quartz.nip01Core.core.AddressableEvent
import com.vitorpamplona.quartz.nip01Core.core.BaseAddressableEvent
import com.vitorpamplona.quartz.nip01Core.core.Event
import com.vitorpamplona.quartz.nip01Core.core.HexKey
import com.vitorpamplona.quartz.nip01Core.core.tagValueContains
import com.vitorpamplona.quartz.nip01Core.crypto.checkSignature
import com.vitorpamplona.quartz.nip01Core.crypto.verify
import com.vitorpamplona.quartz.nip01Core.hints.AddressHintProvider
import com.vitorpamplona.quartz.nip01Core.hints.EventHintProvider
import com.vitorpamplona.quartz.nip01Core.hints.HintIndexer
@@ -66,16 +67,14 @@ import com.vitorpamplona.quartz.nip01Core.metadata.MetadataEvent
import com.vitorpamplona.quartz.nip01Core.relay.client.single.IRelayClient
import com.vitorpamplona.quartz.nip01Core.relay.normalizer.NormalizedRelayUrl
import com.vitorpamplona.quartz.nip01Core.relay.normalizer.isLocalHost
import com.vitorpamplona.quartz.nip01Core.tags.addressables.ATag
import com.vitorpamplona.quartz.nip01Core.tags.addressables.Address
import com.vitorpamplona.quartz.nip01Core.tags.addressables.taggedAddresses
import com.vitorpamplona.quartz.nip01Core.tags.aTag.ATag
import com.vitorpamplona.quartz.nip01Core.tags.aTag.taggedAddresses
import com.vitorpamplona.quartz.nip01Core.tags.events.ETag
import com.vitorpamplona.quartz.nip01Core.tags.events.GenericETag
import com.vitorpamplona.quartz.nip01Core.tags.events.forEachTaggedEventId
import com.vitorpamplona.quartz.nip01Core.tags.events.isTaggedEvent
import com.vitorpamplona.quartz.nip01Core.tags.events.taggedEvents
import com.vitorpamplona.quartz.nip01Core.tags.people.isTaggedUsers
import com.vitorpamplona.quartz.nip01Core.verify
import com.vitorpamplona.quartz.nip02FollowList.ContactListEvent
import com.vitorpamplona.quartz.nip03Timestamp.OtsEvent
import com.vitorpamplona.quartz.nip03Timestamp.VerificationState
@@ -184,9 +183,9 @@ import com.vitorpamplona.quartz.nipA0VoiceMessages.VoiceEvent
import com.vitorpamplona.quartz.nipA0VoiceMessages.VoiceReplyEvent
import com.vitorpamplona.quartz.nipB7Blossom.BlossomServersEvent
import com.vitorpamplona.quartz.utils.Hex
import com.vitorpamplona.quartz.utils.LargeCache
import com.vitorpamplona.quartz.utils.LargeSoftCache
import com.vitorpamplona.quartz.utils.Log
import com.vitorpamplona.quartz.utils.TimeUtils
import com.vitorpamplona.quartz.utils.cache.LargeCache
import kotlinx.collections.immutable.ImmutableList
import kotlinx.collections.immutable.toImmutableList
import kotlinx.coroutines.CancellationException
@@ -2164,7 +2163,7 @@ object LocalCache : ILocalCache {
.toImmutableList()
}
fun findEarliestOtsForNote(
suspend fun findEarliestOtsForNote(
note: Note,
otsVerifCache: VerificationStateCache,
): Long? {
@@ -2173,13 +2172,29 @@ object LocalCache : ILocalCache {
var minTime: Long? = null
val time = TimeUtils.now()
notes.forEach { _, item ->
val noteEvent = item.event
if ((noteEvent is OtsEvent && noteEvent.isTaggedEvent(note.idHex) && !noteEvent.isExpirationBefore(time))) {
(otsVerifCache.cacheVerify(noteEvent) as? VerificationState.Verified)?.verifiedTime?.let { stampedTime ->
if (minTime == null || stampedTime < (minTime ?: Long.MAX_VALUE)) {
minTime = stampedTime
val candidates =
notes.mapNotNull { _, item ->
val noteEvent = item.event
if ((noteEvent is OtsEvent && noteEvent.isTaggedEvent(note.idHex) && !noteEvent.isExpirationBefore(time))) {
val cachedTime = (otsVerifCache.justCache(noteEvent) as? VerificationState.Verified)?.verifiedTime
if (cachedTime != null) {
if (minTime == null || cachedTime < (minTime ?: Long.MAX_VALUE)) {
minTime = cachedTime
}
null
} else {
// tries to verify again
noteEvent
}
} else {
null
}
}
candidates.forEach { noteEvent ->
(otsVerifCache.cacheVerify(noteEvent) as? VerificationState.Verified)?.verifiedTime?.let { stampedTime ->
if (minTime == null || stampedTime < (minTime ?: Long.MAX_VALUE)) {
minTime = stampedTime
}
}
}
@@ -20,12 +20,13 @@
*/
package com.vitorpamplona.amethyst.model
import android.util.Log
import androidx.compose.runtime.Stable
import com.fasterxml.jackson.annotation.JsonSubTypes
import com.fasterxml.jackson.annotation.JsonTypeInfo
import com.fasterxml.jackson.databind.DeserializationFeature
import com.fasterxml.jackson.module.kotlin.jacksonObjectMapper
import com.fasterxml.jackson.module.kotlin.readValue
import com.vitorpamplona.quartz.utils.Log
import kotlinx.collections.immutable.ImmutableMap
import kotlinx.collections.immutable.persistentMapOf
import kotlinx.collections.immutable.toImmutableMap
@@ -160,7 +161,7 @@ fun parseResourceBundleOrNull(json: String): FhirElementDatabase? {
jacksonObjectMapper().configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false)
return try {
val resource = mapper.readValue(json, Resource::class.java)
val resource = mapper.readValue<Resource>(json)
val db =
when (resource) {
@@ -31,17 +31,17 @@ import com.vitorpamplona.amethyst.ui.note.toShortDisplay
import com.vitorpamplona.quartz.experimental.bounties.addedRewardValue
import com.vitorpamplona.quartz.experimental.bounties.hasAdditionalReward
import com.vitorpamplona.quartz.lightning.LnInvoiceUtil
import com.vitorpamplona.quartz.nip01Core.core.Address
import com.vitorpamplona.quartz.nip01Core.core.Event
import com.vitorpamplona.quartz.nip01Core.core.HexKey
import com.vitorpamplona.quartz.nip01Core.core.ImmutableListOfLists
import com.vitorpamplona.quartz.nip01Core.hints.EventHintBundle
import com.vitorpamplona.quartz.nip01Core.relay.normalizer.NormalizedRelayUrl
import com.vitorpamplona.quartz.nip01Core.tags.addressables.ATag
import com.vitorpamplona.quartz.nip01Core.tags.addressables.Address
import com.vitorpamplona.quartz.nip01Core.tags.aTag.ATag
import com.vitorpamplona.quartz.nip01Core.tags.events.ETag
import com.vitorpamplona.quartz.nip01Core.tags.events.EventReference
import com.vitorpamplona.quartz.nip01Core.tags.hashtags.anyHashTag
import com.vitorpamplona.quartz.nip01Core.tags.publishedAt.PublishedAtProvider
import com.vitorpamplona.quartz.nip02FollowList.ImmutableListOfLists
import com.vitorpamplona.quartz.nip10Notes.BaseThreadedEvent
import com.vitorpamplona.quartz.nip10Notes.tags.MarkedETag
import com.vitorpamplona.quartz.nip18Reposts.GenericRepostEvent
@@ -22,8 +22,8 @@ package com.vitorpamplona.amethyst.model
import androidx.compose.runtime.Stable
import com.vitorpamplona.amethyst.service.checkNotInMainThread
import com.vitorpamplona.quartz.nip01Core.core.Address
import com.vitorpamplona.quartz.nip01Core.core.AddressableEvent
import com.vitorpamplona.quartz.nip01Core.tags.addressables.Address
import com.vitorpamplona.quartz.nip18Reposts.GenericRepostEvent
import com.vitorpamplona.quartz.nip18Reposts.RepostEvent
import kotlinx.collections.immutable.ImmutableSet
@@ -22,8 +22,10 @@ package com.vitorpamplona.amethyst.model
import androidx.compose.runtime.Stable
import com.vitorpamplona.amethyst.R
import kotlinx.serialization.Serializable
@Stable
@Serializable
data class UiSettings(
val theme: ThemeType = ThemeType.SYSTEM,
val preferredLanguage: String? = null,
@@ -25,6 +25,7 @@ import androidx.compose.runtime.Stable
import com.vitorpamplona.amethyst.ui.note.toShortDisplay
import com.vitorpamplona.quartz.lightning.Lud06
import com.vitorpamplona.quartz.nip01Core.core.HexKey
import com.vitorpamplona.quartz.nip01Core.core.toImmutableListOfLists
import com.vitorpamplona.quartz.nip01Core.metadata.MetadataEvent
import com.vitorpamplona.quartz.nip01Core.metadata.UserMetadata
import com.vitorpamplona.quartz.nip01Core.relay.normalizer.NormalizedRelayUrl
@@ -33,7 +34,6 @@ import com.vitorpamplona.quartz.nip01Core.tags.hashtags.isTaggedHash
import com.vitorpamplona.quartz.nip01Core.tags.people.PTag
import com.vitorpamplona.quartz.nip01Core.tags.people.isTaggedUser
import com.vitorpamplona.quartz.nip02FollowList.ContactListEvent
import com.vitorpamplona.quartz.nip02FollowList.toImmutableListOfLists
import com.vitorpamplona.quartz.nip17Dm.settings.ChatMessageRelayListEvent
import com.vitorpamplona.quartz.nip19Bech32.entities.NProfile
import com.vitorpamplona.quartz.nip19Bech32.toNpub
@@ -21,7 +21,6 @@
package com.vitorpamplona.amethyst.model.accountsCache
import android.content.ContentResolver
import android.util.Log
import com.vitorpamplona.amethyst.model.Account
import com.vitorpamplona.amethyst.model.AccountSettings
import com.vitorpamplona.amethyst.model.LocalCache
@@ -34,6 +33,7 @@ import com.vitorpamplona.quartz.nip01Core.signers.NostrSigner
import com.vitorpamplona.quartz.nip01Core.signers.NostrSignerInternal
import com.vitorpamplona.quartz.nip03Timestamp.OtsResolverBuilder
import com.vitorpamplona.quartz.nip55AndroidSigner.client.NostrSignerExternal
import com.vitorpamplona.quartz.utils.Log
import kotlinx.coroutines.CoroutineExceptionHandler
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
@@ -20,7 +20,6 @@
*/
package com.vitorpamplona.amethyst.model.edits
import android.util.Log
import com.vitorpamplona.amethyst.model.AccountSettings
import com.vitorpamplona.amethyst.model.LocalCache
import com.vitorpamplona.amethyst.model.Note
@@ -28,6 +27,7 @@ import com.vitorpamplona.amethyst.model.NoteState
import com.vitorpamplona.quartz.nip01Core.relay.normalizer.NormalizedRelayUrl
import com.vitorpamplona.quartz.nip01Core.signers.NostrSigner
import com.vitorpamplona.quartz.nip37Drafts.privateOutbox.PrivateOutboxRelayListEvent
import com.vitorpamplona.quartz.utils.Log
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.DelicateCoroutinesApi
import kotlinx.coroutines.Dispatchers
@@ -20,7 +20,6 @@
*/
package com.vitorpamplona.amethyst.model.emphChat
import android.util.Log
import com.vitorpamplona.amethyst.model.AccountSettings
import com.vitorpamplona.amethyst.model.LocalCache
import com.vitorpamplona.amethyst.model.Note
@@ -28,6 +27,7 @@ import com.vitorpamplona.amethyst.model.NoteState
import com.vitorpamplona.quartz.experimental.ephemChat.chat.RoomId
import com.vitorpamplona.quartz.experimental.ephemChat.list.EphemeralChatListEvent
import com.vitorpamplona.quartz.nip01Core.signers.NostrSigner
import com.vitorpamplona.quartz.utils.Log
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.DelicateCoroutinesApi
import kotlinx.coroutines.Dispatchers
@@ -20,13 +20,13 @@
*/
package com.vitorpamplona.amethyst.model.nip01UserMetadata
import android.util.Log
import com.vitorpamplona.amethyst.model.AccountSettings
import com.vitorpamplona.amethyst.model.LocalCache
import com.vitorpamplona.amethyst.model.User
import com.vitorpamplona.amethyst.model.UserState
import com.vitorpamplona.quartz.nip01Core.metadata.MetadataEvent
import com.vitorpamplona.quartz.nip01Core.signers.NostrSigner
import com.vitorpamplona.quartz.utils.Log
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.DelicateCoroutinesApi
import kotlinx.coroutines.Dispatchers
@@ -20,7 +20,6 @@
*/
package com.vitorpamplona.amethyst.model.nip02FollowLists
import android.util.Log
import androidx.compose.runtime.Immutable
import com.vitorpamplona.amethyst.model.AccountSettings
import com.vitorpamplona.amethyst.model.LocalCache
@@ -32,6 +31,7 @@ import com.vitorpamplona.quartz.nip02FollowList.ContactListEvent
import com.vitorpamplona.quartz.nip02FollowList.tags.ContactTag
import com.vitorpamplona.quartz.nip73ExternalIds.location.GeohashId
import com.vitorpamplona.quartz.nip73ExternalIds.topics.HashtagId
import com.vitorpamplona.quartz.utils.Log
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.DelicateCoroutinesApi
import kotlinx.coroutines.Dispatchers
@@ -25,7 +25,9 @@ import com.vitorpamplona.amethyst.model.Note
import com.vitorpamplona.quartz.nip03Timestamp.OtsEvent
import com.vitorpamplona.quartz.nip03Timestamp.VerificationStateCache
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.flow.SharingStarted
import kotlinx.coroutines.flow.flowOn
import kotlinx.coroutines.flow.onEach
import kotlinx.coroutines.flow.stateIn
@@ -37,14 +39,17 @@ class IncomingOtsEventVerifier(
val verifying =
cache.live.newEventBundles
.onEach { newNotes ->
newNotes.forEach(::consume)
}.stateIn(
newNotes.forEach {
consume(it)
}
}.flowOn(Dispatchers.Default)
.stateIn(
scope,
SharingStarted.Eagerly,
null,
)
fun consume(note: Note) {
suspend fun consume(note: Note) {
note.event?.let { event ->
if (event is OtsEvent) {
otsVerifCache.cacheVerify(event)
@@ -20,7 +20,6 @@
*/
package com.vitorpamplona.amethyst.model.nip03Timestamp
import android.util.Log
import com.vitorpamplona.amethyst.model.AccountSettings
import com.vitorpamplona.amethyst.model.LocalCache
import com.vitorpamplona.amethyst.model.Note
@@ -28,6 +27,7 @@ import com.vitorpamplona.quartz.nip01Core.core.Event
import com.vitorpamplona.quartz.nip01Core.signers.NostrSigner
import com.vitorpamplona.quartz.nip03Timestamp.OtsEvent
import com.vitorpamplona.quartz.nip03Timestamp.OtsResolverBuilder
import com.vitorpamplona.quartz.utils.Log
import com.vitorpamplona.quartz.utils.TimeUtils
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.flow.update
@@ -85,7 +85,7 @@ class OtsState(
return settings.pendingAttestations.value[id] != null
}
fun timestamp(note: Note) {
suspend fun timestamp(note: Note) {
if (note.isDraft()) return
val id = note.event?.id ?: note.idHex
@@ -0,0 +1,54 @@
/**
* 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.amethyst.model.nip03Timestamp
import com.vitorpamplona.quartz.nip03Timestamp.OtsResolver
import com.vitorpamplona.quartz.nip03Timestamp.OtsResolverBuilder
import com.vitorpamplona.quartz.nip03Timestamp.okhttp.OkHttpBitcoinExplorer
import com.vitorpamplona.quartz.nip03Timestamp.okhttp.OkHttpCalendar
import com.vitorpamplona.quartz.nip03Timestamp.ots.OtsBlockHeightCache
import okhttp3.OkHttpClient
class TorAwareOkHttpOtsResolverBuilder(
val okHttpClient: (url: String) -> OkHttpClient,
val isTorActive: (url: String) -> Boolean,
val cache: OtsBlockHeightCache,
) : OtsResolverBuilder {
fun getAPI(usingTor: Boolean) =
if (usingTor) {
OkHttpBitcoinExplorer.Companion.MEMPOOL_API_URL
} else {
OkHttpBitcoinExplorer.Companion.BLOCKSTREAM_API_URL
}
override fun build(): OtsResolver =
OtsResolver(
explorer =
OkHttpBitcoinExplorer(
baseUrl = {
getAPI(usingTor = isTorActive(OkHttpBitcoinExplorer.Companion.MEMPOOL_API_URL))
},
client = okHttpClient(OkHttpBitcoinExplorer.Companion.MEMPOOL_API_URL),
cache = cache,
),
calendar = OkHttpCalendar(okHttpClient),
)
}
@@ -20,13 +20,13 @@
*/
package com.vitorpamplona.amethyst.model.nip11RelayInfo
import android.util.Log
import androidx.compose.runtime.Composable
import androidx.compose.runtime.State
import androidx.compose.runtime.produceState
import com.vitorpamplona.amethyst.Amethyst
import com.vitorpamplona.quartz.nip01Core.relay.normalizer.NormalizedRelayUrl
import com.vitorpamplona.quartz.nip11RelayInfo.Nip11RelayInformation
import com.vitorpamplona.quartz.utils.Log
@Composable
fun loadRelayInfo(relay: NormalizedRelayUrl): State<Nip11RelayInformation> = loadRelayInfo(relay, Amethyst.instance.nip11Cache)
@@ -20,10 +20,10 @@
*/
package com.vitorpamplona.amethyst.model.nip11RelayInfo
import android.util.Log
import com.vitorpamplona.quartz.nip01Core.relay.normalizer.NormalizedRelayUrl
import com.vitorpamplona.quartz.nip01Core.relay.normalizer.toHttp
import com.vitorpamplona.quartz.nip11RelayInfo.Nip11RelayInformation
import com.vitorpamplona.quartz.utils.Log
import kotlinx.coroutines.CancellationException
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.withContext
@@ -20,7 +20,6 @@
*/
package com.vitorpamplona.amethyst.model.nip17Dms
import android.util.Log
import com.vitorpamplona.amethyst.model.AccountSettings
import com.vitorpamplona.amethyst.model.LocalCache
import com.vitorpamplona.amethyst.model.Note
@@ -28,6 +27,7 @@ import com.vitorpamplona.amethyst.model.NoteState
import com.vitorpamplona.quartz.nip01Core.relay.normalizer.NormalizedRelayUrl
import com.vitorpamplona.quartz.nip01Core.signers.NostrSigner
import com.vitorpamplona.quartz.nip17Dm.settings.ChatMessageRelayListEvent
import com.vitorpamplona.quartz.utils.Log
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.DelicateCoroutinesApi
import kotlinx.coroutines.Dispatchers
@@ -25,10 +25,10 @@ import com.vitorpamplona.amethyst.model.Channel
import com.vitorpamplona.amethyst.model.Note
import com.vitorpamplona.amethyst.model.User
import com.vitorpamplona.amethyst.ui.note.toShortDisplay
import com.vitorpamplona.quartz.nip01Core.core.EmptyTagList
import com.vitorpamplona.quartz.nip01Core.core.toImmutableListOfLists
import com.vitorpamplona.quartz.nip01Core.hints.EventHintBundle
import com.vitorpamplona.quartz.nip01Core.hints.types.EventIdHintOptional
import com.vitorpamplona.quartz.nip02FollowList.EmptyTagList
import com.vitorpamplona.quartz.nip02FollowList.toImmutableListOfLists
import com.vitorpamplona.quartz.nip19Bech32.entities.NEvent
import com.vitorpamplona.quartz.nip28PublicChat.admin.ChannelCreateEvent
import com.vitorpamplona.quartz.nip28PublicChat.admin.ChannelMetadataEvent
@@ -20,7 +20,6 @@
*/
package com.vitorpamplona.amethyst.model.nip28PublicChats
import android.util.Log
import com.vitorpamplona.amethyst.model.AccountSettings
import com.vitorpamplona.amethyst.model.LocalCache
import com.vitorpamplona.amethyst.model.Note
@@ -29,6 +28,7 @@ import com.vitorpamplona.quartz.nip01Core.core.HexKey
import com.vitorpamplona.quartz.nip01Core.signers.NostrSigner
import com.vitorpamplona.quartz.nip28PublicChat.list.ChannelListEvent
import com.vitorpamplona.quartz.nip28PublicChat.list.tags.ChannelTag
import com.vitorpamplona.quartz.utils.Log
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.DelicateCoroutinesApi
import kotlinx.coroutines.Dispatchers
@@ -25,7 +25,7 @@ import com.vitorpamplona.amethyst.model.LocalCache
import com.vitorpamplona.amethyst.model.Note
import com.vitorpamplona.amethyst.model.NoteState
import com.vitorpamplona.quartz.nip01Core.signers.NostrSigner
import com.vitorpamplona.quartz.nip01Core.tags.addressables.taggedAddresses
import com.vitorpamplona.quartz.nip01Core.tags.aTag.taggedAddresses
import com.vitorpamplona.quartz.nip30CustomEmoji.pack.EmojiPackEvent
import com.vitorpamplona.quartz.nip30CustomEmoji.selection.EmojiPackSelectionEvent
import com.vitorpamplona.quartz.nip30CustomEmoji.taggedEmojis
@@ -20,7 +20,6 @@
*/
package com.vitorpamplona.amethyst.model.nip51Lists.blockedRelays
import android.util.Log
import com.vitorpamplona.amethyst.model.AccountSettings
import com.vitorpamplona.amethyst.model.LocalCache
import com.vitorpamplona.amethyst.model.Note
@@ -29,6 +28,7 @@ import com.vitorpamplona.quartz.nip01Core.relay.normalizer.NormalizedRelayUrl
import com.vitorpamplona.quartz.nip01Core.signers.NostrSigner
import com.vitorpamplona.quartz.nip01Core.signers.SignerExceptions
import com.vitorpamplona.quartz.nip51Lists.relayLists.BlockedRelayListEvent
import com.vitorpamplona.quartz.utils.Log
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.DelicateCoroutinesApi
import kotlinx.coroutines.Dispatchers
@@ -20,13 +20,13 @@
*/
package com.vitorpamplona.amethyst.model.nip51Lists.geohashLists
import android.util.Log
import com.vitorpamplona.amethyst.model.AccountSettings
import com.vitorpamplona.amethyst.model.LocalCache
import com.vitorpamplona.amethyst.model.Note
import com.vitorpamplona.amethyst.model.NoteState
import com.vitorpamplona.quartz.nip01Core.signers.NostrSigner
import com.vitorpamplona.quartz.nip51Lists.geohashList.GeohashListEvent
import com.vitorpamplona.quartz.utils.Log
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.DelicateCoroutinesApi
import kotlinx.coroutines.Dispatchers
@@ -20,13 +20,13 @@
*/
package com.vitorpamplona.amethyst.model.nip51Lists.hashtagLists
import android.util.Log
import com.vitorpamplona.amethyst.model.AccountSettings
import com.vitorpamplona.amethyst.model.LocalCache
import com.vitorpamplona.amethyst.model.Note
import com.vitorpamplona.amethyst.model.NoteState
import com.vitorpamplona.quartz.nip01Core.signers.NostrSigner
import com.vitorpamplona.quartz.nip51Lists.hashtagList.HashtagListEvent
import com.vitorpamplona.quartz.utils.Log
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.DelicateCoroutinesApi
import kotlinx.coroutines.Dispatchers
@@ -20,7 +20,6 @@
*/
package com.vitorpamplona.amethyst.model.nip51Lists.muteList
import android.util.Log
import com.vitorpamplona.amethyst.model.AccountSettings
import com.vitorpamplona.amethyst.model.LocalCache
import com.vitorpamplona.amethyst.model.Note
@@ -30,6 +29,7 @@ import com.vitorpamplona.quartz.nip51Lists.muteList.MuteListEvent
import com.vitorpamplona.quartz.nip51Lists.muteList.tags.MuteTag
import com.vitorpamplona.quartz.nip51Lists.muteList.tags.UserTag
import com.vitorpamplona.quartz.nip51Lists.muteList.tags.WordTag
import com.vitorpamplona.quartz.utils.Log
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.DelicateCoroutinesApi
import kotlinx.coroutines.Dispatchers
@@ -20,7 +20,6 @@
*/
package com.vitorpamplona.amethyst.model.nip51Lists.searchRelays
import android.util.Log
import com.vitorpamplona.amethyst.model.AccountSettings
import com.vitorpamplona.amethyst.model.DefaultSearchRelayList
import com.vitorpamplona.amethyst.model.LocalCache
@@ -29,6 +28,7 @@ import com.vitorpamplona.amethyst.model.NoteState
import com.vitorpamplona.quartz.nip01Core.relay.normalizer.NormalizedRelayUrl
import com.vitorpamplona.quartz.nip01Core.signers.NostrSigner
import com.vitorpamplona.quartz.nip50Search.SearchRelayListEvent
import com.vitorpamplona.quartz.utils.Log
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.DelicateCoroutinesApi
import kotlinx.coroutines.Dispatchers
@@ -20,7 +20,6 @@
*/
package com.vitorpamplona.amethyst.model.nip51Lists.trustedRelays
import android.util.Log
import com.vitorpamplona.amethyst.model.AccountSettings
import com.vitorpamplona.amethyst.model.LocalCache
import com.vitorpamplona.amethyst.model.Note
@@ -28,6 +27,7 @@ import com.vitorpamplona.amethyst.model.NoteState
import com.vitorpamplona.quartz.nip01Core.relay.normalizer.NormalizedRelayUrl
import com.vitorpamplona.quartz.nip01Core.signers.NostrSigner
import com.vitorpamplona.quartz.nip51Lists.relayLists.TrustedRelayListEvent
import com.vitorpamplona.quartz.utils.Log
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.DelicateCoroutinesApi
import kotlinx.coroutines.Dispatchers
@@ -25,8 +25,8 @@ import com.vitorpamplona.amethyst.model.Channel
import com.vitorpamplona.amethyst.model.Note
import com.vitorpamplona.amethyst.model.User
import com.vitorpamplona.amethyst.ui.note.toShortDisplay
import com.vitorpamplona.quartz.nip01Core.tags.addressables.ATag
import com.vitorpamplona.quartz.nip01Core.tags.addressables.Address
import com.vitorpamplona.quartz.nip01Core.core.Address
import com.vitorpamplona.quartz.nip01Core.tags.aTag.ATag
import com.vitorpamplona.quartz.nip19Bech32.entities.NAddress
import com.vitorpamplona.quartz.nip53LiveActivities.streaming.LiveActivitiesEvent
@@ -20,7 +20,6 @@
*/
package com.vitorpamplona.amethyst.model.nip65RelayList
import android.util.Log
import com.vitorpamplona.amethyst.model.AccountSettings
import com.vitorpamplona.amethyst.model.Constants
import com.vitorpamplona.amethyst.model.LocalCache
@@ -30,6 +29,7 @@ import com.vitorpamplona.quartz.nip01Core.relay.normalizer.NormalizedRelayUrl
import com.vitorpamplona.quartz.nip01Core.signers.NostrSigner
import com.vitorpamplona.quartz.nip65RelayList.AdvertisedRelayListEvent
import com.vitorpamplona.quartz.nip65RelayList.tags.AdvertisedRelayInfo
import com.vitorpamplona.quartz.utils.Log
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.DelicateCoroutinesApi
import kotlinx.coroutines.Dispatchers
@@ -20,7 +20,6 @@
*/
package com.vitorpamplona.amethyst.model.nip72Communities
import android.util.Log
import com.vitorpamplona.amethyst.model.AccountSettings
import com.vitorpamplona.amethyst.model.AddressableNote
import com.vitorpamplona.amethyst.model.LocalCache
@@ -30,6 +29,7 @@ import com.vitorpamplona.quartz.nip01Core.signers.NostrSigner
import com.vitorpamplona.quartz.nip72ModCommunities.definition.CommunityDefinitionEvent
import com.vitorpamplona.quartz.nip72ModCommunities.follow.CommunityListEvent
import com.vitorpamplona.quartz.nip72ModCommunities.follow.tags.CommunityTag
import com.vitorpamplona.quartz.utils.Log
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.DelicateCoroutinesApi
import kotlinx.coroutines.Dispatchers
@@ -20,15 +20,14 @@
*/
package com.vitorpamplona.amethyst.model.nip78AppSpecific
import android.util.Log
import com.fasterxml.jackson.module.kotlin.readValue
import com.vitorpamplona.amethyst.model.AccountSettings
import com.vitorpamplona.amethyst.model.AccountSyncedSettingsInternal
import com.vitorpamplona.amethyst.model.LocalCache
import com.vitorpamplona.amethyst.model.NoteState
import com.vitorpamplona.quartz.nip01Core.jackson.JsonMapper
import com.vitorpamplona.quartz.nip01Core.core.JsonMapper
import com.vitorpamplona.quartz.nip01Core.signers.NostrSigner
import com.vitorpamplona.quartz.nip78AppData.AppSpecificDataEvent
import com.vitorpamplona.quartz.utils.Log
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.DelicateCoroutinesApi
import kotlinx.coroutines.Dispatchers
@@ -58,7 +57,7 @@ class AppSpecificState(
val toInternal = settings.syncedSettings.toInternal()
return AppSpecificDataEvent.create(
dTag = APP_SPECIFIC_DATA_D_TAG,
description = signer.nip44Encrypt(JsonMapper.mapper.writeValueAsString(toInternal), signer.pubKey),
description = signer.nip44Encrypt(JsonMapper.toJson(toInternal), signer.pubKey),
otherTags = emptyArray(),
signer = signer,
)
@@ -73,7 +72,7 @@ class AppSpecificState(
LocalCache.justConsumeMyOwnEvent(event)
try {
val decrypted = signer.decrypt(event.content, event.pubKey)
val syncedSettings = JsonMapper.mapper.readValue<AccountSyncedSettingsInternal>(decrypted)
val syncedSettings = JsonMapper.fromJson<AccountSyncedSettingsInternal>(decrypted)
settings.syncedSettings.updateFrom(syncedSettings)
} catch (e: Throwable) {
if (e is CancellationException) throw e
@@ -90,7 +89,7 @@ class AppSpecificState(
(it.note.event as? AppSpecificDataEvent)?.let {
val decrypted = signer.decrypt(it.content, it.pubKey)
try {
val syncedSettings = JsonMapper.mapper.readValue<AccountSyncedSettingsInternal>(decrypted)
val syncedSettings = JsonMapper.fromJson<AccountSyncedSettingsInternal>(decrypted)
settings.updateAppSpecificData(it, syncedSettings)
} catch (e: Throwable) {
if (e is CancellationException) throw e
@@ -23,8 +23,8 @@ package com.vitorpamplona.amethyst.model.observables
import com.vitorpamplona.amethyst.model.AddressableNote
import com.vitorpamplona.amethyst.model.LocalCache
import com.vitorpamplona.amethyst.model.Note
import com.vitorpamplona.quartz.nip01Core.core.Address
import com.vitorpamplona.quartz.nip01Core.core.Event
import com.vitorpamplona.quartz.nip01Core.tags.addressables.Address
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.asStateFlow
@@ -24,7 +24,7 @@ import androidx.datastore.core.DataStore
import androidx.datastore.preferences.core.PreferenceDataStoreFactory
import androidx.datastore.preferences.core.Preferences
import androidx.datastore.preferences.core.stringPreferencesKey
import com.vitorpamplona.quartz.utils.LargeCache
import com.vitorpamplona.quartz.utils.cache.LargeCache
import java.io.File
class AccountPreferenceStores(
@@ -24,7 +24,7 @@ import androidx.datastore.preferences.core.PreferenceDataStoreFactory
import androidx.datastore.preferences.core.stringPreferencesKey
import com.vitorpamplona.quartz.nip01Core.core.HexKey
import com.vitorpamplona.quartz.nip47WalletConnect.Nip47WalletConnect
import com.vitorpamplona.quartz.utils.LargeCache
import com.vitorpamplona.quartz.utils.cache.LargeCache
import kotlinx.coroutines.CoroutineScope
import java.io.File
@@ -29,16 +29,16 @@ import kotlinx.coroutines.flow.catch
import kotlinx.coroutines.flow.firstOrNull
import kotlinx.coroutines.flow.map
import java.io.IOException
import java.util.Base64
import kotlin.io.encoding.Base64
class EncryptedDataStore(
private val store: DataStore<Preferences>,
private val encryption: KeyStoreEncryption = KeyStoreEncryption(),
private val scope: CoroutineScope,
) {
private fun decode(str: String): ByteArray = Base64.getDecoder().decode(str)
private fun decode(str: String): ByteArray = Base64.decode(str)
private fun encode(bytes: ByteArray): String = Base64.getEncoder().encodeToString(bytes)
private fun encode(bytes: ByteArray): String = Base64.encode(bytes)
private fun encrypt(value: String): String = encode(encryption.encrypt(value.toByteArray()))
@@ -21,7 +21,6 @@
package com.vitorpamplona.amethyst.model.preferences
import android.content.Context
import android.util.Log
import androidx.compose.runtime.Stable
import androidx.datastore.preferences.core.booleanPreferencesKey
import androidx.datastore.preferences.core.edit
@@ -30,6 +29,7 @@ import androidx.datastore.preferences.core.stringPreferencesKey
import com.vitorpamplona.amethyst.ui.tor.TorSettings
import com.vitorpamplona.amethyst.ui.tor.TorSettingsFlow
import com.vitorpamplona.amethyst.ui.tor.TorType
import com.vitorpamplona.quartz.utils.Log
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.FlowPreview
@@ -21,7 +21,6 @@
package com.vitorpamplona.amethyst.model.preferences
import android.content.Context
import android.util.Log
import androidx.appcompat.app.AppCompatDelegate
import androidx.compose.runtime.Stable
import androidx.core.os.LocaleListCompat
@@ -39,6 +38,7 @@ import com.vitorpamplona.amethyst.model.ProfileGalleryType
import com.vitorpamplona.amethyst.model.ThemeType
import com.vitorpamplona.amethyst.model.UiSettings
import com.vitorpamplona.amethyst.model.UiSettingsFlow
import com.vitorpamplona.quartz.utils.Log
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.FlowPreview
@@ -25,7 +25,7 @@ import com.vitorpamplona.amethyst.model.User
import com.vitorpamplona.quartz.nip01Core.core.HexKey
import com.vitorpamplona.quartz.nip17Dm.base.ChatroomKey
import com.vitorpamplona.quartz.nip17Dm.base.ChatroomKeyable
import com.vitorpamplona.quartz.utils.LargeCache
import com.vitorpamplona.quartz.utils.cache.LargeCache
import kotlinx.collections.immutable.persistentSetOf
class ChatroomList(
@@ -25,6 +25,7 @@ import com.vitorpamplona.amethyst.model.nipB7Blossom.BlossomServerListState
import com.vitorpamplona.amethyst.ui.actions.mediaServers.DEFAULT_MEDIA_SERVERS
import com.vitorpamplona.amethyst.ui.actions.mediaServers.ServerName
import com.vitorpamplona.amethyst.ui.actions.mediaServers.ServerType
import com.vitorpamplona.quartz.utils.Rfc3986
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.flow.SharingStarted
@@ -33,7 +34,6 @@ import kotlinx.coroutines.flow.combine
import kotlinx.coroutines.flow.flowOn
import kotlinx.coroutines.flow.onStart
import kotlinx.coroutines.flow.stateIn
import org.czeal.rfc3986.URIReference
class MergedServerListState(
val fileServers: FileStorageServerListState,
@@ -42,7 +42,7 @@ class MergedServerListState(
) {
fun host(url: String): String =
try {
URIReference.parse(url).host.value
Rfc3986.host(url)
} catch (e: Exception) {
url
}
@@ -28,7 +28,7 @@ import com.vitorpamplona.amethyst.model.topNavFeeds.OutboxRelayLoader
import com.vitorpamplona.quartz.nip01Core.core.Event
import com.vitorpamplona.quartz.nip01Core.core.HexKey
import com.vitorpamplona.quartz.nip01Core.relay.normalizer.NormalizedRelayUrl
import com.vitorpamplona.quartz.nip01Core.tags.addressables.isTaggedAddressableNotes
import com.vitorpamplona.quartz.nip01Core.tags.aTag.isTaggedAddressableNotes
import com.vitorpamplona.quartz.nip01Core.tags.geohash.isTaggedGeoHashes
import com.vitorpamplona.quartz.nip01Core.tags.hashtags.isTaggedHashes
import com.vitorpamplona.quartz.nip22Comments.CommentEvent
@@ -26,7 +26,7 @@ import com.vitorpamplona.amethyst.model.topNavFeeds.IFeedTopNavFilter
import com.vitorpamplona.quartz.nip01Core.core.Event
import com.vitorpamplona.quartz.nip01Core.core.HexKey
import com.vitorpamplona.quartz.nip01Core.relay.normalizer.NormalizedRelayUrl
import com.vitorpamplona.quartz.nip01Core.tags.addressables.isTaggedAddressableNotes
import com.vitorpamplona.quartz.nip01Core.tags.aTag.isTaggedAddressableNotes
import com.vitorpamplona.quartz.nip01Core.tags.geohash.isTaggedGeoHashes
import com.vitorpamplona.quartz.nip01Core.tags.hashtags.isTaggedHashes
import com.vitorpamplona.quartz.nip22Comments.CommentEvent
@@ -27,7 +27,7 @@ import com.vitorpamplona.amethyst.model.topNavFeeds.IFeedTopNavFilter
import com.vitorpamplona.quartz.nip01Core.core.Event
import com.vitorpamplona.quartz.nip01Core.core.HexKey
import com.vitorpamplona.quartz.nip01Core.relay.normalizer.NormalizedRelayUrl
import com.vitorpamplona.quartz.nip01Core.tags.addressables.isTaggedAddressableNotes
import com.vitorpamplona.quartz.nip01Core.tags.aTag.isTaggedAddressableNotes
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.StateFlow
import kotlinx.coroutines.flow.combine
@@ -27,7 +27,7 @@ import com.vitorpamplona.amethyst.model.topNavFeeds.OutboxRelayLoader
import com.vitorpamplona.quartz.nip01Core.core.Event
import com.vitorpamplona.quartz.nip01Core.core.HexKey
import com.vitorpamplona.quartz.nip01Core.relay.normalizer.NormalizedRelayUrl
import com.vitorpamplona.quartz.nip01Core.tags.addressables.isTaggedAddressableNote
import com.vitorpamplona.quartz.nip01Core.tags.aTag.isTaggedAddressableNote
import com.vitorpamplona.quartz.nip22Comments.CommentEvent
import com.vitorpamplona.quartz.nip53LiveActivities.streaming.LiveActivitiesEvent
import kotlinx.coroutines.flow.Flow
@@ -22,7 +22,7 @@ package com.vitorpamplona.amethyst.model.topNavFeeds.noteBased.community
import androidx.compose.runtime.Immutable
import com.vitorpamplona.amethyst.model.topNavFeeds.IFeedTopNavPerRelayFilter
import com.vitorpamplona.quartz.nip01Core.tags.addressables.Address
import com.vitorpamplona.quartz.nip01Core.core.Address
@Immutable
class SingleCommunityTopNavPerRelayFilter(
@@ -23,7 +23,7 @@ package com.vitorpamplona.amethyst.service
import android.util.LruCache
import com.vitorpamplona.amethyst.commons.richtext.RichTextParser
import com.vitorpamplona.amethyst.commons.richtext.RichTextViewerState
import com.vitorpamplona.quartz.nip02FollowList.ImmutableListOfLists
import com.vitorpamplona.quartz.nip01Core.core.ImmutableListOfLists
object CachedRichTextParser {
private val richTextCache = LruCache<Int, RichTextViewerState>(50)
@@ -20,7 +20,7 @@
*/
package com.vitorpamplona.amethyst.service
import android.util.Log
import com.vitorpamplona.quartz.utils.Log
import kotlinx.coroutines.CancellationException
import kotlinx.coroutines.delay
@@ -21,7 +21,7 @@
package com.vitorpamplona.amethyst.service
import com.vitorpamplona.amethyst.commons.emojicoder.EmojiCoder
import com.vitorpamplona.quartz.nip02FollowList.ImmutableListOfLists
import com.vitorpamplona.quartz.nip01Core.core.ImmutableListOfLists
fun String.isUTF16Char(pos: Int): Boolean = Character.charCount(this.codePointAt(pos)) == 2
@@ -20,9 +20,9 @@
*/
package com.vitorpamplona.amethyst.service
import android.util.Log
import android.util.LruCache
import androidx.compose.runtime.Immutable
import com.vitorpamplona.quartz.utils.Log
import com.vitorpamplona.quartz.utils.RandomInstance
import com.vitorpamplona.quartz.utils.TimeUtils
import okhttp3.EventListener
@@ -24,7 +24,7 @@ import android.content.Context
import android.net.ConnectivityManager
import android.net.Network
import android.net.NetworkCapabilities
import android.util.Log
import com.vitorpamplona.quartz.utils.Log
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.FlowPreview
import kotlinx.coroutines.channels.awaitClose
@@ -20,11 +20,11 @@
*/
package com.vitorpamplona.amethyst.service.eventCache
import android.util.Log
import com.vitorpamplona.amethyst.AccountInfo
import com.vitorpamplona.amethyst.model.Account
import com.vitorpamplona.amethyst.model.LocalCache
import com.vitorpamplona.quartz.nip19Bech32.decodePublicKeyAsHexOrNull
import com.vitorpamplona.quartz.utils.Log
import java.util.concurrent.atomic.AtomicBoolean
class MemoryTrimmingService(
@@ -21,7 +21,6 @@
package com.vitorpamplona.amethyst.service.lnurl
import android.content.Context
import android.util.Log
import com.fasterxml.jackson.module.kotlin.jacksonObjectMapper
import com.vitorpamplona.amethyst.R
import com.vitorpamplona.amethyst.service.HttpStatusMessages
@@ -29,6 +28,7 @@ import com.vitorpamplona.amethyst.ui.stringRes
import com.vitorpamplona.quartz.lightning.LnInvoiceUtil
import com.vitorpamplona.quartz.lightning.Lud06
import com.vitorpamplona.quartz.nip57Zaps.LnZapRequestEvent
import com.vitorpamplona.quartz.utils.Log
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.withContext
import okhttp3.OkHttpClient
@@ -23,8 +23,8 @@ package com.vitorpamplona.amethyst.service.location
import android.content.Context
import android.location.Geocoder
import android.location.Location
import android.util.Log
import android.util.LruCache
import com.vitorpamplona.quartz.utils.Log
/**
* Maintains a cache of geohashes and city,country pairs.
@@ -26,9 +26,9 @@ import android.location.Location
import android.location.LocationListener
import android.location.LocationManager
import android.os.Looper
import android.util.Log
import com.vitorpamplona.amethyst.service.location.LocationState.Companion.MIN_DISTANCE
import com.vitorpamplona.amethyst.service.location.LocationState.Companion.MIN_TIME
import com.vitorpamplona.quartz.utils.Log
import kotlinx.coroutines.channels.awaitClose
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.callbackFlow
@@ -21,10 +21,10 @@
package com.vitorpamplona.amethyst.service.location
import android.content.Context
import android.util.Log
import com.fonfon.kgeohash.GeoHash
import com.fonfon.kgeohash.toGeoHash
import com.vitorpamplona.quartz.nip01Core.tags.geohash.GeohashPrecision
import com.vitorpamplona.quartz.utils.Log
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.flow.MutableStateFlow
@@ -25,8 +25,8 @@ import android.location.Address
import android.location.Geocoder
import android.location.Location
import android.os.Build
import android.util.Log
import androidx.annotation.RequiresApi
import com.vitorpamplona.quartz.utils.Log
import java.io.IOException
class ReverseGeolocation {
@@ -20,8 +20,8 @@
*/
package com.vitorpamplona.amethyst.service.logging
import android.util.Log
import android.view.Choreographer
import com.vitorpamplona.quartz.utils.Log
object ChoreographerHelper {
var lastFrameTimeNanos: Long = 0
@@ -24,8 +24,8 @@ import android.annotation.SuppressLint
import android.os.Handler
import android.os.HandlerThread
import android.os.Looper
import android.util.Log
import android.util.Printer
import com.vitorpamplona.quartz.utils.Log
import java.text.SimpleDateFormat
import java.util.concurrent.atomic.AtomicBoolean
@@ -22,7 +22,6 @@ package com.vitorpamplona.amethyst.service.notifications
import android.app.NotificationManager
import android.content.Context
import android.util.Log
import androidx.core.content.ContextCompat
import com.vitorpamplona.amethyst.Amethyst
import com.vitorpamplona.amethyst.LocalPreferences
@@ -48,6 +47,7 @@ import com.vitorpamplona.quartz.nip57Zaps.LnZapEvent
import com.vitorpamplona.quartz.nip57Zaps.LnZapRequestEvent
import com.vitorpamplona.quartz.nip59Giftwrap.seals.SealedRumorEvent
import com.vitorpamplona.quartz.nip59Giftwrap.wraps.GiftWrapEvent
import com.vitorpamplona.quartz.utils.Log
import com.vitorpamplona.quartz.utils.TimeUtils
import java.math.BigDecimal
import kotlin.coroutines.cancellation.CancellationException
@@ -26,8 +26,8 @@ import android.content.Context.RECEIVER_EXPORTED
import android.content.Intent
import android.content.IntentFilter
import android.os.Build
import android.util.Log
import com.vitorpamplona.quartz.nip01Core.core.Event
import com.vitorpamplona.quartz.utils.Log
import kotlinx.coroutines.CoroutineExceptionHandler
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
@@ -20,7 +20,6 @@
*/
package com.vitorpamplona.amethyst.service.notifications
import android.util.Log
import com.vitorpamplona.amethyst.AccountInfo
import com.vitorpamplona.amethyst.Amethyst
import com.vitorpamplona.amethyst.BuildConfig
@@ -29,6 +28,7 @@ import com.vitorpamplona.amethyst.isDebug
import com.vitorpamplona.amethyst.model.AccountSettings
import com.vitorpamplona.quartz.nip01Core.relay.normalizer.NormalizedRelayUrl
import com.vitorpamplona.quartz.nip42RelayAuth.RelayAuthEvent
import com.vitorpamplona.quartz.utils.Log
import com.vitorpamplona.quartz.utils.mapNotNullAsync
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.withContext
@@ -20,7 +20,7 @@
*/
package com.vitorpamplona.amethyst.service.okhttp
import com.vitorpamplona.quartz.nip17Dm.files.encryption.AESGCM
import com.vitorpamplona.quartz.utils.ciphers.AESGCM
import okhttp3.Interceptor
import okhttp3.MediaType.Companion.toMediaTypeOrNull
import okhttp3.Response
@@ -21,7 +21,7 @@
package com.vitorpamplona.amethyst.service.okhttp
import android.util.LruCache
import com.vitorpamplona.quartz.nip17Dm.files.encryption.NostrCipher
import com.vitorpamplona.quartz.utils.ciphers.NostrCipher
/**
* Neigther ExoPlayer, nor Coil support passing key and nonce to the Interceptor via
@@ -20,7 +20,7 @@
*/
package com.vitorpamplona.amethyst.service.okhttp
import android.util.Log
import com.vitorpamplona.quartz.utils.Log
import okhttp3.Interceptor
import okhttp3.Request
import okhttp3.Response
@@ -21,7 +21,7 @@
package com.vitorpamplona.amethyst.service.okhttp
import android.os.Build
import android.util.Log
import com.vitorpamplona.quartz.utils.Log
import okhttp3.Dispatcher
import okhttp3.OkHttpClient
import java.net.InetSocketAddress
@@ -20,7 +20,6 @@
*/
package com.vitorpamplona.amethyst.service.playback.composable
import android.util.Log
import androidx.compose.runtime.Composable
import androidx.compose.runtime.DisposableEffect
import androidx.compose.runtime.remember
@@ -33,6 +32,7 @@ import androidx.media3.common.Player
import com.vitorpamplona.amethyst.service.playback.composable.mediaitem.LoadedMediaItem
import com.vitorpamplona.amethyst.service.playback.pip.BackgroundMedia
import com.vitorpamplona.amethyst.service.playback.service.PlaybackServiceClient
import com.vitorpamplona.quartz.utils.Log
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch
import java.util.concurrent.atomic.AtomicBoolean
@@ -25,12 +25,14 @@ import androidx.compose.runtime.MutableState
import androidx.compose.runtime.Stable
import androidx.compose.runtime.mutableStateOf
import androidx.media3.session.MediaController
import java.util.UUID
import kotlin.uuid.ExperimentalUuidApi
import kotlin.uuid.Uuid
@OptIn(ExperimentalUuidApi::class)
@Stable
class MediaControllerState(
// each composable has an ID.
val id: String = UUID.randomUUID().toString(),
val id: String = Uuid.random().toString(),
// This is filled after the controller returns from this class
var controller: MediaController? = null,
// this set's the stage to keep playing on the background or not when the user leaves the screen
@@ -21,10 +21,10 @@
package com.vitorpamplona.amethyst.service.playback.playerPool
import android.content.Context
import android.util.Log
import androidx.annotation.OptIn
import androidx.media3.common.util.UnstableApi
import androidx.media3.exoplayer.ExoPlayer
import com.vitorpamplona.quartz.utils.Log
import kotlinx.coroutines.CoroutineExceptionHandler
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
@@ -23,7 +23,6 @@ package com.vitorpamplona.amethyst.service.playback.playerPool
import android.app.PendingIntent
import android.content.Context
import android.content.Intent
import android.util.Log
import android.util.LruCache
import androidx.annotation.OptIn
import androidx.core.net.toUri
@@ -37,6 +36,7 @@ import androidx.media3.session.MediaSession
import com.google.common.util.concurrent.Futures
import com.google.common.util.concurrent.ListenableFuture
import com.vitorpamplona.amethyst.ui.MainActivity
import com.vitorpamplona.quartz.utils.Log
import com.vitorpamplona.quartz.utils.TimeUtils
import kotlinx.coroutines.DelicateCoroutinesApi
import kotlinx.coroutines.Dispatchers
@@ -20,7 +20,6 @@
*/
package com.vitorpamplona.amethyst.service.playback.service
import android.util.Log
import androidx.annotation.OptIn
import androidx.media3.common.C
import androidx.media3.common.Player
@@ -34,6 +33,7 @@ import com.vitorpamplona.amethyst.service.playback.playerPool.ExoPlayerBuilder
import com.vitorpamplona.amethyst.service.playback.playerPool.ExoPlayerPool
import com.vitorpamplona.amethyst.service.playback.playerPool.MediaSessionPool
import com.vitorpamplona.amethyst.service.playback.playerPool.SimultaneousPlaybackCalculator
import com.vitorpamplona.quartz.utils.Log
import okhttp3.OkHttpClient
class PlaybackService : MediaSessionService() {
@@ -23,10 +23,10 @@ package com.vitorpamplona.amethyst.service.playback.service
import android.content.ComponentName
import android.content.Context
import android.os.Bundle
import android.util.Log
import androidx.media3.session.MediaController
import androidx.media3.session.SessionToken
import com.vitorpamplona.amethyst.service.playback.composable.MediaControllerState
import com.vitorpamplona.quartz.utils.Log
import kotlinx.coroutines.CancellationException
import kotlinx.coroutines.DelicateCoroutinesApi
import kotlinx.coroutines.Dispatchers
@@ -20,11 +20,11 @@
*/
package com.vitorpamplona.amethyst.service.relayClient
import android.util.Log
import com.vitorpamplona.quartz.nip01Core.core.Event
import com.vitorpamplona.quartz.nip01Core.relay.client.INostrClient
import com.vitorpamplona.quartz.nip01Core.relay.client.listeners.IRelayClientListener
import com.vitorpamplona.quartz.nip01Core.relay.client.single.IRelayClient
import com.vitorpamplona.quartz.utils.Log
/**
* Listens to NostrClient's onNotify messages from the relay
@@ -20,7 +20,6 @@
*/
package com.vitorpamplona.amethyst.service.relayClient
import android.util.Log
import com.vitorpamplona.amethyst.model.torState.TorRelayEvaluation
import com.vitorpamplona.amethyst.service.connectivity.ConnectivityManager
import com.vitorpamplona.amethyst.service.connectivity.ConnectivityStatus
@@ -28,6 +27,7 @@ import com.vitorpamplona.amethyst.service.okhttp.DualHttpClientManager
import com.vitorpamplona.amethyst.ui.tor.TorManager
import com.vitorpamplona.amethyst.ui.tor.TorServiceStatus
import com.vitorpamplona.quartz.nip01Core.relay.client.INostrClient
import com.vitorpamplona.quartz.utils.Log
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.FlowPreview
@@ -20,11 +20,11 @@
*/
package com.vitorpamplona.amethyst.service.relayClient.authCommand.model
import android.util.Log
import com.vitorpamplona.amethyst.isDebug
import com.vitorpamplona.amethyst.model.Account
import com.vitorpamplona.quartz.nip01Core.relay.client.INostrClient
import com.vitorpamplona.quartz.nip01Core.relay.client.accessories.RelayAuthenticator
import com.vitorpamplona.quartz.utils.Log
import kotlinx.coroutines.CoroutineScope
class ScreenAuthAccount(
@@ -55,7 +55,7 @@ class AuthCoordinator(
if (account == null) return
if (isDebug) {
Log.d(this::class.simpleName, "Watch $account")
Log.d("AuthCoordinator", "Watch $account")
}
authWithAccounts.add(account)
@@ -66,7 +66,7 @@ class AuthCoordinator(
if (account == null) return
if (isDebug) {
Log.d(this::class.simpleName, "Unwatch $account")
Log.d("AuthCoordinator", "Unwatch $account")
}
authWithAccounts.remove(account)
@@ -20,13 +20,13 @@
*/
package com.vitorpamplona.amethyst.service.relayClient.eoseManagers
import android.util.Log
import com.vitorpamplona.amethyst.isDebug
import com.vitorpamplona.ammolite.relays.BundledUpdate
import com.vitorpamplona.quartz.nip01Core.relay.client.INostrClient
import com.vitorpamplona.quartz.nip01Core.relay.client.single.newSubId
import com.vitorpamplona.quartz.nip01Core.relay.client.subscriptions.SubscriptionController
import com.vitorpamplona.quartz.nip01Core.relay.normalizer.NormalizedRelayUrl
import com.vitorpamplona.quartz.utils.Log
import kotlinx.coroutines.Dispatchers
abstract class BaseEoseManager<T>(
@@ -46,7 +46,7 @@ import com.vitorpamplona.amethyst.ui.screen.loggedIn.AccountViewModel
import com.vitorpamplona.amethyst.ui.stringRes
import com.vitorpamplona.amethyst.ui.theme.Size16dp
import com.vitorpamplona.amethyst.ui.theme.StdHorzSpacer
import com.vitorpamplona.quartz.nip02FollowList.EmptyTagList
import com.vitorpamplona.quartz.nip01Core.core.EmptyTagList
@Composable
fun NotifyRequestDialog(
@@ -147,7 +147,7 @@ fun filterJustTheLatestNotificationsToPubkeyFromRandomRelays(
Filter(
kinds = SummaryKinds,
tags = mapOf("p" to listOf(pubkey)),
limit = 500,
limit = 20,
since = since,
),
),
@@ -157,7 +157,7 @@ fun filterJustTheLatestNotificationsToPubkeyFromRandomRelays(
Filter(
kinds = NotificationsPerKeyKinds,
tags = mapOf("p" to listOf(pubkey)),
limit = 500,
limit = 20,
since = since,
),
),
@@ -167,7 +167,7 @@ fun filterJustTheLatestNotificationsToPubkeyFromRandomRelays(
Filter(
kinds = NotificationsPerKeyKinds2,
tags = mapOf("p" to listOf(pubkey)),
limit = 500,
limit = 20,
since = since,
),
),
@@ -23,10 +23,10 @@ package com.vitorpamplona.amethyst.service.relayClient.reqCommand.event.loaders
import com.vitorpamplona.amethyst.model.AddressableNote
import com.vitorpamplona.amethyst.model.LocalCache
import com.vitorpamplona.amethyst.service.relayClient.reqCommand.event.EventFinderQueryState
import com.vitorpamplona.quartz.nip01Core.core.Address
import com.vitorpamplona.quartz.nip01Core.relay.client.pool.RelayBasedFilter
import com.vitorpamplona.quartz.nip01Core.relay.filters.Filter
import com.vitorpamplona.quartz.nip01Core.relay.normalizer.NormalizedRelayUrl
import com.vitorpamplona.quartz.nip01Core.tags.addressables.Address
import com.vitorpamplona.quartz.utils.mapOfSet
fun potentialRelaysToFindAddress(note: AddressableNote): Set<NormalizedRelayUrl> {
@@ -20,10 +20,10 @@
*/
package com.vitorpamplona.amethyst.service.relayClient.speedLogger
import android.util.Log
import com.vitorpamplona.amethyst.service.relayClient.speedLogger.RelaySpeedLogger.Companion.TAG
import com.vitorpamplona.quartz.nip01Core.relay.normalizer.NormalizedRelayUrl
import com.vitorpamplona.quartz.utils.LargeCache
import com.vitorpamplona.quartz.utils.Log
import com.vitorpamplona.quartz.utils.cache.LargeCache
import java.util.concurrent.atomic.AtomicInteger
import kotlin.concurrent.timer
@@ -22,7 +22,7 @@ package com.vitorpamplona.amethyst.service.relayClient.speedLogger
import com.vitorpamplona.quartz.nip01Core.relay.normalizer.NormalizedRelayUrl
import com.vitorpamplona.quartz.nip01Core.relay.normalizer.displayUrl
import com.vitorpamplona.quartz.utils.LargeCache
import com.vitorpamplona.quartz.utils.cache.LargeCache
import java.util.concurrent.atomic.AtomicInteger
import kotlin.concurrent.atomics.ExperimentalAtomicApi
@@ -20,11 +20,11 @@
*/
package com.vitorpamplona.amethyst.service.relayClient.speedLogger
import android.util.Log
import com.vitorpamplona.quartz.nip01Core.core.Event
import com.vitorpamplona.quartz.nip01Core.relay.client.INostrClient
import com.vitorpamplona.quartz.nip01Core.relay.client.listeners.IRelayClientListener
import com.vitorpamplona.quartz.nip01Core.relay.client.single.IRelayClient
import com.vitorpamplona.quartz.utils.Log
/**
* Listens to NostrClient's onNotify messages from the relay

Some files were not shown because too many files have changed in this diff Show More