- Migrates Quartz from Android to CommonMain

- Fully converts OpenTimestamp Java codebase to Kotlin, migrating the sync and async HTTP call interfaces to OkHttp and coroutines
- Redesigns parsing of relay commands, messages and filters for performance in Jackson.
- Starts the use of KotlinX Serialization when speed is not a requirement
- Migrates all Jackson field annotations to Kotlin Serialization
- Migrates Regex use in Quarts to Kotlin's Regex class
- Migrates Base64 from Android to Kotlin
- Migrates UUID from Android/Java to Kotlin
- Migrates LRUCache usage from Android/Java to Kotlin collections
- Migrates all String to bytearray conversions to Kotlin methods
- Migrates all System.arraycopy calls to kotlin native ones.
- Separates parsing code from the data classes Companion objects
- Exposes Rfc3986 normalizations to each platform.
- Exposes URI parsing classes to each platform.
- Exposes URL Encoders to each platform.
- Exposes BigDecimal to each platform.
- Exposes the Url Detector to each platform.
- Exposes MacInstances to each platform
- Exposes Diggest instances to each platform.
- Exposes a BitSet to each platform.
- Exposes GZip to each platform.
- Exposes Secp256k1 to each platform.
- Exposes SecureRandom to each platform.
- Exposes Time in seconds to each platform.
- Exposes the LargeCache to each platform.
- Exposes AES CBC and AES GCM encryption/decryption to each platform
- Migrate test assertions to Kotlin Tests
- Exposes Address class to each platform because of the Parceleable
- Creates our own ByteArrayOutputStream.
- Removes Lock features inside the Bloomfilters because we don't need data consistency/
- Migrates UserMetadata parser from Jackson to Kotlin serialization
- Removes the need for Static methods in each tag.
- Adds an event template serializer
- Adds KotlinX Datetime to migrate some of the date-based logs
- Adds support for LibSodium in the JVM platform
- Creates a shared test build for iOS targets
- Fixes several usages of Reflection when serializing classes
- Fixes a bug on loading RelayDB for the HintBloom filter test
- Increases the Bloom filter space to better use hints in the app.
- Removes support for iOS in x86
- Creates a Jackson mapper just for NIP-55, which stays in the Android build only.
- Keeps the event store in the android build as well.
- Removes @Syncronized tags in favor of Mutexes.
- Improved sendAndWaitForResponse NostrClient method to properly account for returns from each relay.
- Removes the need for GlobalScope and async calls in the downloadFirstEvent method.
- Restructures the parser and serialization of the relay messages and commands for performance with Jackson
- Removes the dependency on Jackson's error classes across the codebase.
- Moves the hint to quote tag extension methods to their own packages.
- Speeds up the generation of Bech32 addresses
- Migrates NIP-6 and Blossom uploads to use Kotlin Serialization
This commit is contained in:
Vitor Pamplona
2025-09-22 19:44:51 -04:00
parent 7949fc66b2
commit 7a280a3cde
1195 changed files with 12671 additions and 5183 deletions
+3
View File
@@ -339,6 +339,9 @@ dependencies {
// Cbor for cashuB format // Cbor for cashuB format
implementation libs.kotlinx.serialization.cbor 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.tor.android
implementation libs.jtorctl implementation libs.jtorctl
@@ -24,9 +24,9 @@ import androidx.test.ext.junit.runners.AndroidJUnit4
import com.vitorpamplona.amethyst.service.cashu.CashuParser import com.vitorpamplona.amethyst.service.cashu.CashuParser
import com.vitorpamplona.amethyst.service.cashu.CashuToken import com.vitorpamplona.amethyst.service.cashu.CashuToken
import com.vitorpamplona.amethyst.ui.components.GenericLoadable import com.vitorpamplona.amethyst.ui.components.GenericLoadable
import junit.framework.TestCase.assertEquals
import kotlinx.collections.immutable.ImmutableList import kotlinx.collections.immutable.ImmutableList
import kotlinx.coroutines.runBlocking import kotlinx.coroutines.runBlocking
import org.junit.Assert.assertEquals
import org.junit.Test import org.junit.Test
import org.junit.runner.RunWith import org.junit.runner.RunWith
@@ -24,10 +24,10 @@ import androidx.test.ext.junit.runners.AndroidJUnit4
import com.vitorpamplona.amethyst.service.okhttp.EncryptedBlobInterceptor import com.vitorpamplona.amethyst.service.okhttp.EncryptedBlobInterceptor
import com.vitorpamplona.amethyst.service.okhttp.EncryptionKeyCache import com.vitorpamplona.amethyst.service.okhttp.EncryptionKeyCache
import com.vitorpamplona.quartz.nip01Core.core.hexToByteArray import com.vitorpamplona.quartz.nip01Core.core.hexToByteArray
import com.vitorpamplona.quartz.nip17Dm.files.encryption.AESGCM import com.vitorpamplona.quartz.utils.ciphers.AESGCM
import junit.framework.TestCase.assertEquals
import okhttp3.OkHttpClient import okhttp3.OkHttpClient
import okhttp3.Request import okhttp3.Request
import org.junit.Assert.assertEquals
import org.junit.Test import org.junit.Test
import org.junit.runner.RunWith 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.nip01Core.signers.NostrSignerInternal
import com.vitorpamplona.quartz.nip98HttpAuth.HTTPAuthorizationEvent import com.vitorpamplona.quartz.nip98HttpAuth.HTTPAuthorizationEvent
import com.vitorpamplona.quartz.utils.sha256.sha256 import com.vitorpamplona.quartz.utils.sha256.sha256
import junit.framework.TestCase.assertEquals
import junit.framework.TestCase.fail import junit.framework.TestCase.fail
import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.Dispatchers
@@ -49,6 +48,7 @@ import kotlinx.coroutines.SupervisorJob
import kotlinx.coroutines.runBlocking import kotlinx.coroutines.runBlocking
import okhttp3.OkHttpClient import okhttp3.OkHttpClient
import org.junit.Assert import org.junit.Assert
import org.junit.Assert.assertEquals
import org.junit.Ignore import org.junit.Ignore
import org.junit.Test import org.junit.Test
import org.junit.runner.RunWith import org.junit.runner.RunWith
@@ -247,13 +247,6 @@ class ImageUploadTesting {
testBase(ServerName("sovbit", "https://files.sovbit.host", ServerType.NIP96)) 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() @Test()
@Ignore("Returns invalid image size") @Ignore("Returns invalid image size")
fun testNostrPic() = fun testNostrPic() =
@@ -21,17 +21,15 @@
package com.vitorpamplona.amethyst package com.vitorpamplona.amethyst
import androidx.test.ext.junit.runners.AndroidJUnit4 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.crypto.KeyPair
import com.vitorpamplona.quartz.nip01Core.jackson.JsonMapper
import com.vitorpamplona.quartz.nip01Core.signers.NostrSignerInternal import com.vitorpamplona.quartz.nip01Core.signers.NostrSignerInternal
import com.vitorpamplona.quartz.nip03Timestamp.OtsEvent import com.vitorpamplona.quartz.nip03Timestamp.OtsEvent
import com.vitorpamplona.quartz.nip03Timestamp.OtsResolver import com.vitorpamplona.quartz.nip03Timestamp.okhttp.OkHttpOtsResolverBuilder
import com.vitorpamplona.quartz.nip03Timestamp.ots.okhttp.OkHttpBitcoinExplorer import com.vitorpamplona.quartz.nip03Timestamp.ots.OtsBlockHeightCache
import com.vitorpamplona.quartz.nip03Timestamp.ots.okhttp.OkHttpCalendarBuilder
import com.vitorpamplona.quartz.nip03Timestamp.ots.okhttp.OtsBlockHeightCache
import junit.framework.TestCase.assertEquals
import kotlinx.coroutines.runBlocking import kotlinx.coroutines.runBlocking
import okhttp3.OkHttpClient import okhttp3.OkHttpClient
import org.junit.Assert.assertEquals
import org.junit.Test import org.junit.Test
import org.junit.runner.RunWith import org.junit.runner.RunWith
@@ -45,51 +43,50 @@ class OkHttpOtsTest {
val otsCache = OtsBlockHeightCache() val otsCache = OtsBlockHeightCache()
val resolver = val resolver =
OtsResolver( OkHttpOtsResolverBuilder(
OkHttpBitcoinExplorer( otsCache,
baseAPI = OkHttpBitcoinExplorer.MEMPOOL_API_URL, ) { OkHttpClient.Builder().build() }.build()
client = OkHttpClient.Builder().build(),
cache = otsCache,
),
OkHttpCalendarBuilder { OkHttpClient.Builder().build() },
)
@Test @Test
fun verifyNostrEvent() { fun verifyNostrEvent() =
val ots = JsonMapper.fromJson(otsEvent) as OtsEvent runBlocking {
println(resolver.info(ots.otsByteArray())) val ots = OptimizedJsonMapper.fromJson(otsEvent) as OtsEvent
assertEquals(1707688818L, ots.verify(resolver)) println(resolver.info(ots.otsByteArray()))
} assertEquals(1707688818L, ots.verify(resolver))
}
@Test @Test
fun verifyNostrEvent2() { fun verifyNostrEvent2() =
val ots = JsonMapper.fromJson(otsEvent2) as OtsEvent runBlocking {
println(resolver.info(ots.otsByteArray())) val ots = OptimizedJsonMapper.fromJson(otsEvent2) as OtsEvent
assertEquals(1706322179L, ots.verify(resolver)) println(resolver.info(ots.otsByteArray()))
} assertEquals(1706322179L, ots.verify(resolver))
}
@Test @Test
fun verifyNostrPendingEvent() { fun verifyNostrPendingEvent() =
val ots = JsonMapper.fromJson(otsPendingEvent) as OtsEvent runBlocking {
println(resolver.info(ots.otsByteArray())) val ots = OptimizedJsonMapper.fromJson(otsPendingEvent) as OtsEvent
assertEquals(null, ots.verify(resolver)) println(resolver.info(ots.otsByteArray()))
} assertEquals(null, ots.verify(resolver))
}
@Test @Test
fun createOTSEventAndVerify() { fun createOTSEventAndVerify() =
val signer = NostrSignerInternal(KeyPair()) runBlocking {
val signer = NostrSignerInternal(KeyPair())
val otsFile = OtsEvent.stamp(otsEvent2Digest, resolver) val otsFile = OtsEvent.stamp(otsEvent2Digest, resolver)
val ots = val ots =
runBlocking { runBlocking {
signer.sign(OtsEvent.build(otsEvent2Digest, otsFile)) signer.sign(OtsEvent.build(otsEvent2Digest, otsFile))
} }
println(ots.toJson()) println(ots.toJson())
println(resolver.info(ots.otsByteArray())) println(resolver.info(ots.otsByteArray()))
// Should not be valid because we need to wait for confirmations // Should not be valid because we need to wait for confirmations
assertEquals(null, ots.verify(resolver)) assertEquals(null, ots.verify(resolver))
} }
} }
@@ -27,21 +27,24 @@ import com.vitorpamplona.amethyst.model.AccountSettings
import com.vitorpamplona.amethyst.model.LocalCache import com.vitorpamplona.amethyst.model.LocalCache
import com.vitorpamplona.amethyst.service.location.LocationState import com.vitorpamplona.amethyst.service.location.LocationState
import com.vitorpamplona.amethyst.service.okhttp.OkHttpWebSocket 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.amethyst.ui.screen.loggedIn.threadview.dal.ThreadFeedFilter
import com.vitorpamplona.quartz.nip01Core.core.Event import com.vitorpamplona.quartz.nip01Core.core.Event
import com.vitorpamplona.quartz.nip01Core.crypto.KeyPair 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.signers.NostrSignerInternal
import com.vitorpamplona.quartz.nip01Core.tags.addressables.ATag import com.vitorpamplona.quartz.nip01Core.tags.aTag.ATag
import com.vitorpamplona.quartz.nip01Core.verify
import junit.framework.TestCase import junit.framework.TestCase
import junit.framework.TestCase.assertEquals
import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.SupervisorJob import kotlinx.coroutines.SupervisorJob
import kotlinx.coroutines.flow.MutableStateFlow import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.runBlocking import kotlinx.coroutines.runBlocking
import okhttp3.OkHttpClient import okhttp3.OkHttpClient
import org.junit.Assert.assertEquals
import org.junit.Test import org.junit.Test
import org.junit.runner.RunWith import org.junit.runner.RunWith
@@ -49,24 +52,28 @@ import org.junit.runner.RunWith
class ThreadDualAxisChartAssemblerTest { class ThreadDualAxisChartAssemblerTest {
companion object { companion object {
val keyPair = KeyPair() val keyPair = KeyPair()
val client =
NostrClient(
OkHttpWebSocket.Builder {
OkHttpClient
.Builder()
.followRedirects(true)
.followSslRedirects(true)
.build()
},
CoroutineScope(Dispatchers.IO + SupervisorJob()),
)
val account = val account =
Account( Account(
settings = AccountSettings(keyPair = keyPair), settings = AccountSettings(keyPair = keyPair),
signer = NostrSignerInternal(keyPair), signer = NostrSignerInternal(keyPair),
scope = CoroutineScope(Dispatchers.IO + SupervisorJob()),
geolocationFlow = MutableStateFlow<LocationState.LocationResult>(LocationState.LocationResult.Loading), geolocationFlow = MutableStateFlow<LocationState.LocationResult>(LocationState.LocationResult.Loading),
nwcFilterAssembler = NWCPaymentFilterAssembler(client),
otsResolverBuilder = EmptyOtsResolverBuilder,
cache = LocalCache, cache = LocalCache,
client = client = client,
NostrClient( scope = CoroutineScope(Dispatchers.IO + SupervisorJob()),
OkHttpWebSocket.Builder {
OkHttpClient
.Builder()
.followRedirects(true)
.followSslRedirects(true)
.build()
},
CoroutineScope(Dispatchers.IO + SupervisorJob()),
),
) )
val db = val db =
@@ -148,7 +155,7 @@ class ThreadDualAxisChartAssemblerTest {
fun threadOrderTest() = fun threadOrderTest() =
runBlocking { runBlocking {
val eventArray = 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 var counter = 0
eventArray.forEach { eventArray.forEach {
@@ -168,7 +175,7 @@ class ThreadDualAxisChartAssemblerTest {
val filter = ThreadFeedFilter(account, naddr.toTag()) val filter = ThreadFeedFilter(account, naddr.toTag())
val calculatedFeed = filter.feed() val calculatedFeed = filter.feed()
val expecteedOrder = val expectedOrder =
listOf( listOf(
"30023:6e468422dfb74a5738702a8823b9b28168abab8655faacb6853cd0ee15deee93:1680612926599", "30023:6e468422dfb74a5738702a8823b9b28168abab8655faacb6853cd0ee15deee93:1680612926599",
"e15b386824fbfdcbf1b50b8860f03062cef534a3ea5339cc837536fb2a58465e", "e15b386824fbfdcbf1b50b8860f03062cef534a3ea5339cc837536fb2a58465e",
@@ -210,8 +217,8 @@ class ThreadDualAxisChartAssemblerTest {
"7a18dda355525d468b31bba4fa947cba98cc19048d4a3099d5e9ba045d878c26", "7a18dda355525d468b31bba4fa947cba98cc19048d4a3099d5e9ba045d878c26",
) )
for (i in expecteedOrder.indices) { for (i in expectedOrder.indices) {
assertEquals(expecteedOrder[i], calculatedFeed[i].idHex) assertEquals(expectedOrder[i], calculatedFeed[i].idHex)
} }
} }
} }
@@ -21,7 +21,7 @@
package com.vitorpamplona.amethyst package com.vitorpamplona.amethyst
import com.vitorpamplona.amethyst.ui.navigation.findParameterValue import com.vitorpamplona.amethyst.ui.navigation.findParameterValue
import junit.framework.TestCase.assertEquals import org.junit.Assert.assertEquals
import org.junit.Test import org.junit.Test
import java.net.URI import java.net.URI
@@ -23,8 +23,8 @@ package com.vitorpamplona.amethyst.service.notifications
import android.content.Context import android.content.Context
import android.content.pm.PackageManager import android.content.pm.PackageManager
import android.os.Build import android.os.Build
import android.util.Log
import com.vitorpamplona.amethyst.Amethyst import com.vitorpamplona.amethyst.Amethyst
import com.vitorpamplona.quartz.utils.Log
import org.unifiedpush.android.connector.UnifiedPush import org.unifiedpush.android.connector.UnifiedPush
interface PushDistributorActions { interface PushDistributorActions {
@@ -22,13 +22,13 @@ package com.vitorpamplona.amethyst.service.notifications
import android.app.NotificationManager import android.app.NotificationManager
import android.content.Context import android.content.Context
import android.util.Log
import android.util.LruCache import android.util.LruCache
import androidx.core.content.ContextCompat import androidx.core.content.ContextCompat
import com.vitorpamplona.amethyst.Amethyst import com.vitorpamplona.amethyst.Amethyst
import com.vitorpamplona.amethyst.LocalPreferences import com.vitorpamplona.amethyst.LocalPreferences
import com.vitorpamplona.quartz.nip01Core.core.Event import com.vitorpamplona.quartz.nip01Core.core.Event
import com.vitorpamplona.quartz.nip59Giftwrap.wraps.GiftWrapEvent import com.vitorpamplona.quartz.nip59Giftwrap.wraps.GiftWrapEvent
import com.vitorpamplona.quartz.utils.Log
import kotlinx.coroutines.CancellationException import kotlinx.coroutines.CancellationException
import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch import kotlinx.coroutines.launch
@@ -22,7 +22,6 @@ package com.vitorpamplona.amethyst.ui.components
import android.Manifest import android.Manifest
import android.os.Build import android.os.Build
import android.util.Log
import androidx.compose.foundation.layout.Arrangement import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.PaddingValues import androidx.compose.foundation.layout.PaddingValues
import androidx.compose.foundation.layout.Row 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.components.TitleExplainer
import com.vitorpamplona.amethyst.ui.screen.loggedIn.settings.SettingsRow import com.vitorpamplona.amethyst.ui.screen.loggedIn.settings.SettingsRow
import com.vitorpamplona.amethyst.ui.stringRes import com.vitorpamplona.amethyst.ui.stringRes
import com.vitorpamplona.quartz.utils.Log
import kotlinx.collections.immutable.ImmutableList import kotlinx.collections.immutable.ImmutableList
import kotlinx.collections.immutable.toImmutableList import kotlinx.collections.immutable.toImmutableList
@@ -28,7 +28,7 @@ import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color import androidx.compose.ui.graphics.Color
import com.vitorpamplona.amethyst.ui.navigation.navs.INav import com.vitorpamplona.amethyst.ui.navigation.navs.INav
import com.vitorpamplona.amethyst.ui.screen.loggedIn.AccountViewModel import com.vitorpamplona.amethyst.ui.screen.loggedIn.AccountViewModel
import com.vitorpamplona.quartz.nip02FollowList.ImmutableListOfLists import com.vitorpamplona.quartz.nip01Core.core.ImmutableListOfLists
@Composable @Composable
fun TranslatableRichTextViewer( fun TranslatableRichTextViewer(
@@ -21,8 +21,8 @@
package com.vitorpamplona.amethyst package com.vitorpamplona.amethyst
import android.app.Application import android.app.Application
import android.util.Log
import com.vitorpamplona.amethyst.service.logging.Logging import com.vitorpamplona.amethyst.service.logging.Logging
import com.vitorpamplona.quartz.utils.Log
class Amethyst : Application() { class Amethyst : Application() {
companion object { companion object {
@@ -22,13 +22,13 @@ package com.vitorpamplona.amethyst
import android.content.ContentResolver import android.content.ContentResolver
import android.content.Context import android.content.Context
import android.util.Log
import androidx.security.crypto.EncryptedSharedPreferences import androidx.security.crypto.EncryptedSharedPreferences
import coil3.disk.DiskCache import coil3.disk.DiskCache
import coil3.memory.MemoryCache import coil3.memory.MemoryCache
import com.vitorpamplona.amethyst.model.LocalCache import com.vitorpamplona.amethyst.model.LocalCache
import com.vitorpamplona.amethyst.model.accountsCache.AccountCacheState import com.vitorpamplona.amethyst.model.accountsCache.AccountCacheState
import com.vitorpamplona.amethyst.model.nip03Timestamp.IncomingOtsEventVerifier 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.nip11RelayInfo.Nip11CachedRetriever
import com.vitorpamplona.amethyst.model.preferences.TorSharedPreferences import com.vitorpamplona.amethyst.model.preferences.TorSharedPreferences
import com.vitorpamplona.amethyst.model.preferences.UiSharedPreferences 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.INostrClient
import com.vitorpamplona.quartz.nip01Core.relay.client.NostrClient import com.vitorpamplona.quartz.nip01Core.relay.client.NostrClient
import com.vitorpamplona.quartz.nip03Timestamp.VerificationStateCache import com.vitorpamplona.quartz.nip03Timestamp.VerificationStateCache
import com.vitorpamplona.quartz.nip03Timestamp.ots.okhttp.OkHttpOtsResolverBuilder import com.vitorpamplona.quartz.nip03Timestamp.ots.OtsBlockHeightCache
import com.vitorpamplona.quartz.nip03Timestamp.ots.okhttp.OtsBlockHeightCache import com.vitorpamplona.quartz.utils.Log
import kotlinx.coroutines.CoroutineExceptionHandler import kotlinx.coroutines.CoroutineExceptionHandler
import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.Dispatchers
@@ -146,8 +146,8 @@ class AppModules(
// Application-wide block height request cache // Application-wide block height request cache
val otsBlockHeightCache by lazy { OtsBlockHeightCache() } val otsBlockHeightCache by lazy { OtsBlockHeightCache() }
val otsResolverBuilder: OkHttpOtsResolverBuilder = val otsResolverBuilder: TorAwareOkHttpOtsResolverBuilder =
OkHttpOtsResolverBuilder( TorAwareOkHttpOtsResolverBuilder(
roleBasedHttpClientBuilder::okHttpClientForMoney, roleBasedHttpClientBuilder::okHttpClientForMoney,
roleBasedHttpClientBuilder::shouldUseTorForMoneyOperations, roleBasedHttpClientBuilder::shouldUseTorForMoneyOperations,
otsBlockHeightCache, otsBlockHeightCache,
@@ -24,9 +24,9 @@ import android.app.ActivityManager
import android.content.Context import android.content.Context
import android.content.pm.ApplicationInfo import android.content.pm.ApplicationInfo
import android.os.Debug import android.os.Debug
import android.util.Log
import androidx.core.content.getSystemService import androidx.core.content.getSystemService
import com.vitorpamplona.amethyst.model.LocalCache import com.vitorpamplona.amethyst.model.LocalCache
import com.vitorpamplona.quartz.utils.Log
import kotlin.time.DurationUnit import kotlin.time.DurationUnit
import kotlin.time.measureTimedValue import kotlin.time.measureTimedValue
@@ -23,10 +23,8 @@ package com.vitorpamplona.amethyst
import android.annotation.SuppressLint import android.annotation.SuppressLint
import android.content.Context import android.content.Context
import android.content.SharedPreferences import android.content.SharedPreferences
import android.util.Log
import androidx.compose.runtime.Immutable import androidx.compose.runtime.Immutable
import androidx.core.content.edit import androidx.core.content.edit
import com.fasterxml.jackson.module.kotlin.readValue
import com.vitorpamplona.amethyst.model.ALL_FOLLOWS import com.vitorpamplona.amethyst.model.ALL_FOLLOWS
import com.vitorpamplona.amethyst.model.AccountSettings import com.vitorpamplona.amethyst.model.AccountSettings
import com.vitorpamplona.amethyst.model.GLOBAL_FOLLOWS 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.experimental.ephemChat.list.EphemeralChatListEvent
import com.vitorpamplona.quartz.nip01Core.core.Event import com.vitorpamplona.quartz.nip01Core.core.Event
import com.vitorpamplona.quartz.nip01Core.core.HexKey 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.hexToByteArray
import com.vitorpamplona.quartz.nip01Core.core.toHexKey import com.vitorpamplona.quartz.nip01Core.core.toHexKey
import com.vitorpamplona.quartz.nip01Core.crypto.KeyPair 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.nip01Core.metadata.MetadataEvent
import com.vitorpamplona.quartz.nip02FollowList.ContactListEvent import com.vitorpamplona.quartz.nip02FollowList.ContactListEvent
import com.vitorpamplona.quartz.nip17Dm.settings.ChatMessageRelayListEvent 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.nip65RelayList.AdvertisedRelayListEvent
import com.vitorpamplona.quartz.nip72ModCommunities.follow.CommunityListEvent import com.vitorpamplona.quartz.nip72ModCommunities.follow.CommunityListEvent
import com.vitorpamplona.quartz.nip78AppData.AppSpecificDataEvent import com.vitorpamplona.quartz.nip78AppData.AppSpecificDataEvent
import com.vitorpamplona.quartz.utils.Log
import kotlinx.coroutines.CancellationException import kotlinx.coroutines.CancellationException
import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.flow.MutableStateFlow import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.sync.Mutex import kotlinx.coroutines.sync.Mutex
import kotlinx.coroutines.sync.withLock import kotlinx.coroutines.sync.withLock
import kotlinx.coroutines.withContext import kotlinx.coroutines.withContext
import kotlinx.serialization.Serializable
import java.io.File import java.io.File
import kotlin.jvm.java
// Release mode (!BuildConfig.DEBUG) always uses encrypted preferences // Release mode (!BuildConfig.DEBUG) always uses encrypted preferences
// To use plaintext SharedPreferences for debugging, set this to true // 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" private const val DEBUG_PREFERENCES_NAME = "debug_prefs"
@Immutable @Immutable
@Serializable
data class AccountInfo( data class AccountInfo(
val npub: String, val npub: String,
val hasPrivKey: Boolean, val hasPrivKey: Boolean,
@@ -161,7 +164,7 @@ object LocalPreferences {
with(encryptedPreferences()) { with(encryptedPreferences()) {
val newSystemOfAccounts = val newSystemOfAccounts =
getString(PrefKeys.ALL_ACCOUNT_INFO, "[]")?.let { getString(PrefKeys.ALL_ACCOUNT_INFO, "[]")?.let {
JsonMapper.mapper.readValue<List<AccountInfo>>(it) JsonMapper.fromJson<List<AccountInfo>>(it)
} }
if (!newSystemOfAccounts.isNullOrEmpty()) { if (!newSystemOfAccounts.isNullOrEmpty()) {
@@ -181,7 +184,9 @@ object LocalPreferences {
savedAccounts.emit(migrated) 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 { .edit {
putString( putString(
PrefKeys.ALL_ACCOUNT_INFO, PrefKeys.ALL_ACCOUNT_INFO,
JsonMapper.mapper.writeValueAsString(accounts.filter { !it.isTransient }), JsonMapper.toJson(accounts.filter { !it.isTransient }),
) )
} }
} }
@@ -308,7 +313,7 @@ object LocalPreferences {
putString( putString(
PrefKeys.DEFAULT_FILE_SERVER, 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_HOME_FOLLOW_LIST, settings.defaultHomeFollowList.value)
putString(PrefKeys.DEFAULT_STORIES_FOLLOW_LIST, settings.defaultStoriesFollowList.value) putString(PrefKeys.DEFAULT_STORIES_FOLLOW_LIST, settings.defaultStoriesFollowList.value)
@@ -320,72 +325,16 @@ object LocalPreferences {
PrefKeys.DEFAULT_DISCOVERY_FOLLOW_LIST, PrefKeys.DEFAULT_DISCOVERY_FOLLOW_LIST,
settings.defaultDiscoveryFollowList.value, settings.defaultDiscoveryFollowList.value,
) )
putString( putOrRemove(PrefKeys.ZAP_PAYMENT_REQUEST_SERVER, settings.zapPaymentRequest.value?.denormalize())
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)
}
if (settings.backupUserMetadata != null) { putOrRemove(PrefKeys.LATEST_CONTACT_LIST, settings.backupContactList)
putString(
PrefKeys.LATEST_USER_METADATA,
JsonMapper.mapper.writeValueAsString(settings.backupUserMetadata),
)
} else {
remove(PrefKeys.LATEST_USER_METADATA)
}
if (settings.backupDMRelayList != null) { putOrRemove(PrefKeys.LATEST_USER_METADATA, settings.backupUserMetadata)
putString( putOrRemove(PrefKeys.LATEST_DM_RELAY_LIST, settings.backupDMRelayList)
PrefKeys.LATEST_DM_RELAY_LIST, putOrRemove(PrefKeys.LATEST_NIP65_RELAY_LIST, settings.backupNIP65RelayList)
JsonMapper.mapper.writeValueAsString(settings.backupDMRelayList), putOrRemove(PrefKeys.LATEST_SEARCH_RELAY_LIST, settings.backupSearchRelayList)
) putOrRemove(PrefKeys.LATEST_BLOCKED_RELAY_LIST, settings.backupBlockedRelayList)
} else { putOrRemove(PrefKeys.LATEST_TRUSTED_RELAY_LIST, settings.backupTrustedRelayList)
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)
}
if (settings.localRelayServers.value.isNotEmpty()) { if (settings.localRelayServers.value.isNotEmpty()) {
putStringSet(PrefKeys.LOCAL_RELAY_SERVERS, settings.localRelayServers.value) putStringSet(PrefKeys.LOCAL_RELAY_SERVERS, settings.localRelayServers.value)
@@ -393,77 +342,15 @@ object LocalPreferences {
remove(PrefKeys.LOCAL_RELAY_SERVERS) remove(PrefKeys.LOCAL_RELAY_SERVERS)
} }
if (settings.backupMuteList != null) { putOrRemove(PrefKeys.LATEST_MUTE_LIST, settings.backupMuteList)
putString( putOrRemove(PrefKeys.LATEST_PRIVATE_HOME_RELAY_LIST, settings.backupPrivateHomeRelayList)
PrefKeys.LATEST_MUTE_LIST, putOrRemove(PrefKeys.LATEST_APP_SPECIFIC_DATA, settings.backupAppSpecificData)
JsonMapper.mapper.writeValueAsString(settings.backupMuteList),
)
} else {
remove(PrefKeys.LATEST_MUTE_LIST)
}
if (settings.backupPrivateHomeRelayList != null) { putOrRemove(PrefKeys.LATEST_CHANNEL_LIST, settings.backupChannelList)
putString( putOrRemove(PrefKeys.LATEST_COMMUNITY_LIST, settings.backupCommunityList)
PrefKeys.LATEST_PRIVATE_HOME_RELAY_LIST, putOrRemove(PrefKeys.LATEST_HASHTAG_LIST, settings.backupHashtagList)
JsonMapper.mapper.writeValueAsString(settings.backupPrivateHomeRelayList), putOrRemove(PrefKeys.LATEST_GEOHASH_LIST, settings.backupGeohashList)
) putOrRemove(PrefKeys.LATEST_EPHEMERAL_LIST, settings.backupEphemeralChatList)
} 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)
}
putBoolean(PrefKeys.HIDE_DELETE_REQUEST_DIALOG, settings.hideDeleteRequestDialog) putBoolean(PrefKeys.HIDE_DELETE_REQUEST_DIALOG, settings.hideDeleteRequestDialog)
putBoolean(PrefKeys.HIDE_NIP_17_WARNING_DIALOG, settings.hideNIP17WarningDialog) putBoolean(PrefKeys.HIDE_NIP_17_WARNING_DIALOG, settings.hideNIP17WarningDialog)
@@ -480,13 +367,13 @@ object LocalPreferences {
putString( putString(
PrefKeys.LAST_READ_PER_ROUTE, PrefKeys.LAST_READ_PER_ROUTE,
JsonMapper.mapper.writeValueAsString(regularMap), JsonMapper.toJson(regularMap),
) )
putStringSet(PrefKeys.HAS_DONATED_IN_VERSION, settings.hasDonatedInVersion.value) putStringSet(PrefKeys.HAS_DONATED_IN_VERSION, settings.hasDonatedInVersion.value)
putString( putString(
PrefKeys.PENDING_ATTESTATIONS, 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") Log.d("LocalPreferences", "Saving to shared settings")
prefs.edit { 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) { with(prefs) {
return try { return try {
getString(PrefKeys.SHARED_SETTINGS, "{}")?.let { getString(PrefKeys.SHARED_SETTINGS, "{}")?.let {
JsonMapper.mapper.readValue<UiSettings>(it) JsonMapper.fromJson<UiSettings>(it)
} }
} catch (e: Throwable) { } catch (e: Throwable) {
if (e is CancellationException) throw e if (e is CancellationException) throw e
@@ -643,7 +530,7 @@ object LocalPreferences {
return result 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) val value = getString(key, null)
if (value.isNullOrEmpty() || value == "null") { if (value.isNullOrEmpty() || value == "null") {
return null return null
@@ -652,7 +539,7 @@ object LocalPreferences {
if (T::class.java.isInstance(Event::class.java)) { if (T::class.java.isInstance(Event::class.java)) {
Event.fromJson(value) as T? Event.fromJson(value) as T?
} else { } else {
JsonMapper.mapper.readValue<T?>(value) JsonMapper.fromJson<T>(value)
} }
} catch (e: Throwable) { } catch (e: Throwable) {
if (e is CancellationException) throw e if (e is CancellationException) throw e
@@ -674,4 +561,26 @@ object LocalPreferences {
null 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 package com.vitorpamplona.amethyst.model
import android.util.Log
import androidx.compose.runtime.Stable import androidx.compose.runtime.Stable
import com.vitorpamplona.amethyst.BuildConfig import com.vitorpamplona.amethyst.BuildConfig
import com.vitorpamplona.amethyst.LocalPreferences import com.vitorpamplona.amethyst.LocalPreferences
@@ -204,6 +203,7 @@ import com.vitorpamplona.quartz.nip94FileMetadata.tags.DimensionTag
import com.vitorpamplona.quartz.nip98HttpAuth.HTTPAuthorizationEvent import com.vitorpamplona.quartz.nip98HttpAuth.HTTPAuthorizationEvent
import com.vitorpamplona.quartz.nipA0VoiceMessages.VoiceEvent import com.vitorpamplona.quartz.nipA0VoiceMessages.VoiceEvent
import com.vitorpamplona.quartz.nipA0VoiceMessages.VoiceReplyEvent import com.vitorpamplona.quartz.nipA0VoiceMessages.VoiceReplyEvent
import com.vitorpamplona.quartz.utils.Log
import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.DelicateCoroutinesApi import kotlinx.coroutines.DelicateCoroutinesApi
import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.Dispatchers
@@ -802,27 +802,27 @@ class Account(
} }
} }
fun broadcast(note: Note) { suspend fun broadcast(note: Note) {
note.event?.let { note.event?.let { noteEvent ->
if (it is WrappedEvent && it.host != null) { if (noteEvent is WrappedEvent && noteEvent.host != null) {
// download the event and send it. // download the event and send it.
it.host?.let { host -> noteEvent.host?.let { host ->
client.downloadFirstEvent( client
filters = .downloadFirstEvent(
note.relays.associateWith { relay -> filters =
listOf( note.relays.associateWith { relay ->
Filter( listOf(
ids = listOf(host.id), Filter(
), ids = listOf(host.id),
) ),
}, )
onResponse = { },
client.send(it, computeRelayListToBroadcast(it)) )?.let { downloadedEvent ->
}, client.send(downloadedEvent, computeRelayListToBroadcast(downloadedEvent))
) }
} }
} else { } 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 android.content.res.Resources
import androidx.core.os.ConfigurationCompat import androidx.core.os.ConfigurationCompat
import com.vitorpamplona.quartz.nip57Zaps.LnZapEvent import com.vitorpamplona.quartz.nip57Zaps.LnZapEvent
import kotlinx.serialization.Serializable
import java.util.Locale import java.util.Locale
val DefaultReactions = val DefaultReactions =
@@ -47,6 +48,7 @@ fun getLanguagesSpokenByUser(): Set<String> {
return codedList return codedList
} }
@Serializable
class AccountSyncedSettingsInternal( class AccountSyncedSettingsInternal(
val reactions: AccountReactionPreferencesInternal = AccountReactionPreferencesInternal(), val reactions: AccountReactionPreferencesInternal = AccountReactionPreferencesInternal(),
val zaps: AccountZapPreferencesInternal = AccountZapPreferencesInternal(), val zaps: AccountZapPreferencesInternal = AccountZapPreferencesInternal(),
@@ -54,21 +56,25 @@ class AccountSyncedSettingsInternal(
val security: AccountSecurityPreferencesInternal = AccountSecurityPreferencesInternal(), val security: AccountSecurityPreferencesInternal = AccountSecurityPreferencesInternal(),
) )
@Serializable
class AccountReactionPreferencesInternal( class AccountReactionPreferencesInternal(
var reactionChoices: List<String> = DefaultReactions, var reactionChoices: List<String> = DefaultReactions,
) )
@Serializable
class AccountZapPreferencesInternal( class AccountZapPreferencesInternal(
var zapAmountChoices: List<Long> = DefaultZapAmounts, var zapAmountChoices: List<Long> = DefaultZapAmounts,
val defaultZapType: LnZapEvent.ZapType = LnZapEvent.ZapType.PUBLIC, val defaultZapType: LnZapEvent.ZapType = LnZapEvent.ZapType.PUBLIC,
) )
@Serializable
class AccountLanguagePreferencesInternal( class AccountLanguagePreferencesInternal(
var dontTranslateFrom: Set<String> = getLanguagesSpokenByUser(), var dontTranslateFrom: Set<String> = getLanguagesSpokenByUser(),
var languagePreferences: Map<String, String> = mapOf(), var languagePreferences: Map<String, String> = mapOf(),
var translateTo: String = Locale.getDefault().language, var translateTo: String = Locale.getDefault().language,
) )
@Serializable
class AccountSecurityPreferencesInternal( class AccountSecurityPreferencesInternal(
val showSensitiveContent: Boolean? = null, val showSensitiveContent: Boolean? = null,
var warnAboutPostsWithReports: Boolean = true, var warnAboutPostsWithReports: Boolean = true,
@@ -20,18 +20,18 @@
*/ */
package com.vitorpamplona.amethyst.model package com.vitorpamplona.amethyst.model
import android.util.Log
import android.util.LruCache import android.util.LruCache
import com.vitorpamplona.amethyst.ui.note.njumpLink 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.AddressableEvent
import com.vitorpamplona.quartz.nip01Core.core.Event import com.vitorpamplona.quartz.nip01Core.core.Event
import com.vitorpamplona.quartz.nip01Core.core.HexKey import com.vitorpamplona.quartz.nip01Core.core.HexKey
import com.vitorpamplona.quartz.nip01Core.relay.client.stats.RelayStats import com.vitorpamplona.quartz.nip01Core.relay.client.stats.RelayStats
import com.vitorpamplona.quartz.nip01Core.relay.normalizer.NormalizedRelayUrl 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.Nip19Parser
import com.vitorpamplona.quartz.nip19Bech32.entities.NAddress import com.vitorpamplona.quartz.nip19Bech32.entities.NAddress
import com.vitorpamplona.quartz.nip19Bech32.entities.NEvent import com.vitorpamplona.quartz.nip19Bech32.entities.NEvent
import com.vitorpamplona.quartz.utils.Log
import kotlinx.coroutines.flow.MutableStateFlow import kotlinx.coroutines.flow.MutableStateFlow
data class Spammer( data class Spammer(
@@ -65,7 +65,7 @@ class AntiSpamFilter {
// really long, make it ok. // really long, make it ok.
// The idea here is to avoid considering repeated "@Bot, command" messages spam, while still // The idea here is to avoid considering repeated "@Bot, command" messages spam, while still
// blocking repeated "lnbc..." invoices or fishing urls // 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: // double list strategy:
// if duplicated, it goes into spam. 1000 spam messages are saved into the spam list. // 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.amethyst.ui.dal.ListChange
import com.vitorpamplona.quartz.nip01Core.core.HexKey import com.vitorpamplona.quartz.nip01Core.core.HexKey
import com.vitorpamplona.quartz.nip01Core.relay.normalizer.NormalizedRelayUrl 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.channels.BufferOverflow
import kotlinx.coroutines.flow.MutableSharedFlow import kotlinx.coroutines.flow.MutableSharedFlow
import kotlinx.coroutines.flow.MutableStateFlow 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.components.RenderRegular
import com.vitorpamplona.amethyst.ui.navigation.navs.EmptyNav import com.vitorpamplona.amethyst.ui.navigation.navs.EmptyNav
import com.vitorpamplona.amethyst.ui.theme.ThemeComparisonColumn import com.vitorpamplona.amethyst.ui.theme.ThemeComparisonColumn
import com.vitorpamplona.quartz.nip02FollowList.EmptyTagList import com.vitorpamplona.quartz.nip01Core.core.EmptyTagList
@Preview @Preview
@Composable @Composable
@@ -18,8 +18,9 @@
* AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION * 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. * 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.lang.ref.WeakReference
import java.util.concurrent.ConcurrentSkipListMap import java.util.concurrent.ConcurrentSkipListMap
import java.util.function.BiConsumer import java.util.function.BiConsumer
@@ -20,7 +20,6 @@
*/ */
package com.vitorpamplona.amethyst.model package com.vitorpamplona.amethyst.model
import android.util.Log
import android.util.LruCache import android.util.LruCache
import androidx.compose.runtime.Stable import androidx.compose.runtime.Stable
import com.vitorpamplona.amethyst.Amethyst 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.publicMessages.PublicMessageEvent
import com.vitorpamplona.quartz.experimental.relationshipStatus.ContactCardEvent import com.vitorpamplona.quartz.experimental.relationshipStatus.ContactCardEvent
import com.vitorpamplona.quartz.experimental.zapPolls.PollNoteEvent 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.AddressableEvent
import com.vitorpamplona.quartz.nip01Core.core.BaseAddressableEvent import com.vitorpamplona.quartz.nip01Core.core.BaseAddressableEvent
import com.vitorpamplona.quartz.nip01Core.core.Event import com.vitorpamplona.quartz.nip01Core.core.Event
import com.vitorpamplona.quartz.nip01Core.core.HexKey import com.vitorpamplona.quartz.nip01Core.core.HexKey
import com.vitorpamplona.quartz.nip01Core.core.tagValueContains 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.AddressHintProvider
import com.vitorpamplona.quartz.nip01Core.hints.EventHintProvider import com.vitorpamplona.quartz.nip01Core.hints.EventHintProvider
import com.vitorpamplona.quartz.nip01Core.hints.HintIndexer 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.client.single.IRelayClient
import com.vitorpamplona.quartz.nip01Core.relay.normalizer.NormalizedRelayUrl import com.vitorpamplona.quartz.nip01Core.relay.normalizer.NormalizedRelayUrl
import com.vitorpamplona.quartz.nip01Core.relay.normalizer.isLocalHost import com.vitorpamplona.quartz.nip01Core.relay.normalizer.isLocalHost
import com.vitorpamplona.quartz.nip01Core.tags.addressables.ATag import com.vitorpamplona.quartz.nip01Core.tags.aTag.ATag
import com.vitorpamplona.quartz.nip01Core.tags.addressables.Address import com.vitorpamplona.quartz.nip01Core.tags.aTag.taggedAddresses
import com.vitorpamplona.quartz.nip01Core.tags.addressables.taggedAddresses
import com.vitorpamplona.quartz.nip01Core.tags.events.ETag import com.vitorpamplona.quartz.nip01Core.tags.events.ETag
import com.vitorpamplona.quartz.nip01Core.tags.events.GenericETag import com.vitorpamplona.quartz.nip01Core.tags.events.GenericETag
import com.vitorpamplona.quartz.nip01Core.tags.events.forEachTaggedEventId import com.vitorpamplona.quartz.nip01Core.tags.events.forEachTaggedEventId
import com.vitorpamplona.quartz.nip01Core.tags.events.isTaggedEvent import com.vitorpamplona.quartz.nip01Core.tags.events.isTaggedEvent
import com.vitorpamplona.quartz.nip01Core.tags.events.taggedEvents import com.vitorpamplona.quartz.nip01Core.tags.events.taggedEvents
import com.vitorpamplona.quartz.nip01Core.tags.people.isTaggedUsers import com.vitorpamplona.quartz.nip01Core.tags.people.isTaggedUsers
import com.vitorpamplona.quartz.nip01Core.verify
import com.vitorpamplona.quartz.nip02FollowList.ContactListEvent import com.vitorpamplona.quartz.nip02FollowList.ContactListEvent
import com.vitorpamplona.quartz.nip03Timestamp.OtsEvent import com.vitorpamplona.quartz.nip03Timestamp.OtsEvent
import com.vitorpamplona.quartz.nip03Timestamp.VerificationState 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.nipA0VoiceMessages.VoiceReplyEvent
import com.vitorpamplona.quartz.nipB7Blossom.BlossomServersEvent import com.vitorpamplona.quartz.nipB7Blossom.BlossomServersEvent
import com.vitorpamplona.quartz.utils.Hex import com.vitorpamplona.quartz.utils.Hex
import com.vitorpamplona.quartz.utils.LargeCache import com.vitorpamplona.quartz.utils.Log
import com.vitorpamplona.quartz.utils.LargeSoftCache
import com.vitorpamplona.quartz.utils.TimeUtils import com.vitorpamplona.quartz.utils.TimeUtils
import com.vitorpamplona.quartz.utils.cache.LargeCache
import kotlinx.collections.immutable.ImmutableList import kotlinx.collections.immutable.ImmutableList
import kotlinx.collections.immutable.toImmutableList import kotlinx.collections.immutable.toImmutableList
import kotlinx.coroutines.CancellationException import kotlinx.coroutines.CancellationException
@@ -2151,7 +2150,7 @@ object LocalCache : ILocalCache {
.toImmutableList() .toImmutableList()
} }
fun findEarliestOtsForNote( suspend fun findEarliestOtsForNote(
note: Note, note: Note,
otsVerifCache: VerificationStateCache, otsVerifCache: VerificationStateCache,
): Long? { ): Long? {
@@ -2160,13 +2159,29 @@ object LocalCache : ILocalCache {
var minTime: Long? = null var minTime: Long? = null
val time = TimeUtils.now() val time = TimeUtils.now()
notes.forEach { _, item -> val candidates =
val noteEvent = item.event notes.mapNotNull { _, item ->
if ((noteEvent is OtsEvent && noteEvent.isTaggedEvent(note.idHex) && !noteEvent.isExpirationBefore(time))) { val noteEvent = item.event
(otsVerifCache.cacheVerify(noteEvent) as? VerificationState.Verified)?.verifiedTime?.let { stampedTime -> if ((noteEvent is OtsEvent && noteEvent.isTaggedEvent(note.idHex) && !noteEvent.isExpirationBefore(time))) {
if (minTime == null || stampedTime < (minTime ?: Long.MAX_VALUE)) { val cachedTime = (otsVerifCache.justCache(noteEvent) as? VerificationState.Verified)?.verifiedTime
minTime = stampedTime 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 package com.vitorpamplona.amethyst.model
import android.util.Log
import androidx.compose.runtime.Stable import androidx.compose.runtime.Stable
import com.fasterxml.jackson.annotation.JsonSubTypes import com.fasterxml.jackson.annotation.JsonSubTypes
import com.fasterxml.jackson.annotation.JsonTypeInfo import com.fasterxml.jackson.annotation.JsonTypeInfo
import com.fasterxml.jackson.databind.DeserializationFeature import com.fasterxml.jackson.databind.DeserializationFeature
import com.fasterxml.jackson.module.kotlin.jacksonObjectMapper 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.ImmutableMap
import kotlinx.collections.immutable.persistentMapOf import kotlinx.collections.immutable.persistentMapOf
import kotlinx.collections.immutable.toImmutableMap import kotlinx.collections.immutable.toImmutableMap
@@ -160,7 +161,7 @@ fun parseResourceBundleOrNull(json: String): FhirElementDatabase? {
jacksonObjectMapper().configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false) jacksonObjectMapper().configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false)
return try { return try {
val resource = mapper.readValue(json, Resource::class.java) val resource = mapper.readValue<Resource>(json)
val db = val db =
when (resource) { 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.addedRewardValue
import com.vitorpamplona.quartz.experimental.bounties.hasAdditionalReward import com.vitorpamplona.quartz.experimental.bounties.hasAdditionalReward
import com.vitorpamplona.quartz.lightning.LnInvoiceUtil 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.Event
import com.vitorpamplona.quartz.nip01Core.core.HexKey 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.hints.EventHintBundle
import com.vitorpamplona.quartz.nip01Core.relay.normalizer.NormalizedRelayUrl import com.vitorpamplona.quartz.nip01Core.relay.normalizer.NormalizedRelayUrl
import com.vitorpamplona.quartz.nip01Core.tags.addressables.ATag import com.vitorpamplona.quartz.nip01Core.tags.aTag.ATag
import com.vitorpamplona.quartz.nip01Core.tags.addressables.Address
import com.vitorpamplona.quartz.nip01Core.tags.events.ETag import com.vitorpamplona.quartz.nip01Core.tags.events.ETag
import com.vitorpamplona.quartz.nip01Core.tags.events.EventReference import com.vitorpamplona.quartz.nip01Core.tags.events.EventReference
import com.vitorpamplona.quartz.nip01Core.tags.hashtags.anyHashTag import com.vitorpamplona.quartz.nip01Core.tags.hashtags.anyHashTag
import com.vitorpamplona.quartz.nip01Core.tags.publishedAt.PublishedAtProvider 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.BaseThreadedEvent
import com.vitorpamplona.quartz.nip10Notes.tags.MarkedETag import com.vitorpamplona.quartz.nip10Notes.tags.MarkedETag
import com.vitorpamplona.quartz.nip18Reposts.GenericRepostEvent import com.vitorpamplona.quartz.nip18Reposts.GenericRepostEvent
@@ -22,8 +22,8 @@ package com.vitorpamplona.amethyst.model
import androidx.compose.runtime.Stable import androidx.compose.runtime.Stable
import com.vitorpamplona.amethyst.service.checkNotInMainThread 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.core.AddressableEvent
import com.vitorpamplona.quartz.nip01Core.tags.addressables.Address
import com.vitorpamplona.quartz.nip18Reposts.GenericRepostEvent import com.vitorpamplona.quartz.nip18Reposts.GenericRepostEvent
import com.vitorpamplona.quartz.nip18Reposts.RepostEvent import com.vitorpamplona.quartz.nip18Reposts.RepostEvent
import kotlinx.collections.immutable.ImmutableSet import kotlinx.collections.immutable.ImmutableSet
@@ -22,8 +22,10 @@ package com.vitorpamplona.amethyst.model
import androidx.compose.runtime.Stable import androidx.compose.runtime.Stable
import com.vitorpamplona.amethyst.R import com.vitorpamplona.amethyst.R
import kotlinx.serialization.Serializable
@Stable @Stable
@Serializable
data class UiSettings( data class UiSettings(
val theme: ThemeType = ThemeType.SYSTEM, val theme: ThemeType = ThemeType.SYSTEM,
val preferredLanguage: String? = null, val preferredLanguage: String? = null,
@@ -25,6 +25,7 @@ import androidx.compose.runtime.Stable
import com.vitorpamplona.amethyst.ui.note.toShortDisplay import com.vitorpamplona.amethyst.ui.note.toShortDisplay
import com.vitorpamplona.quartz.lightning.Lud06 import com.vitorpamplona.quartz.lightning.Lud06
import com.vitorpamplona.quartz.nip01Core.core.HexKey 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.MetadataEvent
import com.vitorpamplona.quartz.nip01Core.metadata.UserMetadata import com.vitorpamplona.quartz.nip01Core.metadata.UserMetadata
import com.vitorpamplona.quartz.nip01Core.relay.normalizer.NormalizedRelayUrl 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.PTag
import com.vitorpamplona.quartz.nip01Core.tags.people.isTaggedUser import com.vitorpamplona.quartz.nip01Core.tags.people.isTaggedUser
import com.vitorpamplona.quartz.nip02FollowList.ContactListEvent import com.vitorpamplona.quartz.nip02FollowList.ContactListEvent
import com.vitorpamplona.quartz.nip02FollowList.toImmutableListOfLists
import com.vitorpamplona.quartz.nip17Dm.settings.ChatMessageRelayListEvent import com.vitorpamplona.quartz.nip17Dm.settings.ChatMessageRelayListEvent
import com.vitorpamplona.quartz.nip19Bech32.entities.NProfile import com.vitorpamplona.quartz.nip19Bech32.entities.NProfile
import com.vitorpamplona.quartz.nip19Bech32.toNpub import com.vitorpamplona.quartz.nip19Bech32.toNpub
@@ -21,7 +21,6 @@
package com.vitorpamplona.amethyst.model.accountsCache package com.vitorpamplona.amethyst.model.accountsCache
import android.content.ContentResolver import android.content.ContentResolver
import android.util.Log
import com.vitorpamplona.amethyst.model.Account import com.vitorpamplona.amethyst.model.Account
import com.vitorpamplona.amethyst.model.AccountSettings import com.vitorpamplona.amethyst.model.AccountSettings
import com.vitorpamplona.amethyst.model.LocalCache 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.nip01Core.signers.NostrSignerInternal
import com.vitorpamplona.quartz.nip03Timestamp.OtsResolverBuilder import com.vitorpamplona.quartz.nip03Timestamp.OtsResolverBuilder
import com.vitorpamplona.quartz.nip55AndroidSigner.client.NostrSignerExternal import com.vitorpamplona.quartz.nip55AndroidSigner.client.NostrSignerExternal
import com.vitorpamplona.quartz.utils.Log
import kotlinx.coroutines.CoroutineExceptionHandler import kotlinx.coroutines.CoroutineExceptionHandler
import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.Dispatchers
@@ -20,7 +20,6 @@
*/ */
package com.vitorpamplona.amethyst.model.edits package com.vitorpamplona.amethyst.model.edits
import android.util.Log
import com.vitorpamplona.amethyst.model.AccountSettings import com.vitorpamplona.amethyst.model.AccountSettings
import com.vitorpamplona.amethyst.model.LocalCache import com.vitorpamplona.amethyst.model.LocalCache
import com.vitorpamplona.amethyst.model.Note 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.relay.normalizer.NormalizedRelayUrl
import com.vitorpamplona.quartz.nip01Core.signers.NostrSigner import com.vitorpamplona.quartz.nip01Core.signers.NostrSigner
import com.vitorpamplona.quartz.nip37Drafts.privateOutbox.PrivateOutboxRelayListEvent import com.vitorpamplona.quartz.nip37Drafts.privateOutbox.PrivateOutboxRelayListEvent
import com.vitorpamplona.quartz.utils.Log
import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.DelicateCoroutinesApi import kotlinx.coroutines.DelicateCoroutinesApi
import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.Dispatchers
@@ -20,7 +20,6 @@
*/ */
package com.vitorpamplona.amethyst.model.emphChat package com.vitorpamplona.amethyst.model.emphChat
import android.util.Log
import com.vitorpamplona.amethyst.model.AccountSettings import com.vitorpamplona.amethyst.model.AccountSettings
import com.vitorpamplona.amethyst.model.LocalCache import com.vitorpamplona.amethyst.model.LocalCache
import com.vitorpamplona.amethyst.model.Note 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.chat.RoomId
import com.vitorpamplona.quartz.experimental.ephemChat.list.EphemeralChatListEvent import com.vitorpamplona.quartz.experimental.ephemChat.list.EphemeralChatListEvent
import com.vitorpamplona.quartz.nip01Core.signers.NostrSigner import com.vitorpamplona.quartz.nip01Core.signers.NostrSigner
import com.vitorpamplona.quartz.utils.Log
import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.DelicateCoroutinesApi import kotlinx.coroutines.DelicateCoroutinesApi
import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.Dispatchers
@@ -20,13 +20,13 @@
*/ */
package com.vitorpamplona.amethyst.model.nip01UserMetadata package com.vitorpamplona.amethyst.model.nip01UserMetadata
import android.util.Log
import com.vitorpamplona.amethyst.model.AccountSettings import com.vitorpamplona.amethyst.model.AccountSettings
import com.vitorpamplona.amethyst.model.LocalCache import com.vitorpamplona.amethyst.model.LocalCache
import com.vitorpamplona.amethyst.model.User import com.vitorpamplona.amethyst.model.User
import com.vitorpamplona.amethyst.model.UserState import com.vitorpamplona.amethyst.model.UserState
import com.vitorpamplona.quartz.nip01Core.metadata.MetadataEvent import com.vitorpamplona.quartz.nip01Core.metadata.MetadataEvent
import com.vitorpamplona.quartz.nip01Core.signers.NostrSigner import com.vitorpamplona.quartz.nip01Core.signers.NostrSigner
import com.vitorpamplona.quartz.utils.Log
import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.DelicateCoroutinesApi import kotlinx.coroutines.DelicateCoroutinesApi
import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.Dispatchers
@@ -20,7 +20,6 @@
*/ */
package com.vitorpamplona.amethyst.model.nip02FollowLists package com.vitorpamplona.amethyst.model.nip02FollowLists
import android.util.Log
import androidx.compose.runtime.Immutable import androidx.compose.runtime.Immutable
import com.vitorpamplona.amethyst.model.AccountSettings import com.vitorpamplona.amethyst.model.AccountSettings
import com.vitorpamplona.amethyst.model.LocalCache 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.nip02FollowList.tags.ContactTag
import com.vitorpamplona.quartz.nip73ExternalIds.location.GeohashId import com.vitorpamplona.quartz.nip73ExternalIds.location.GeohashId
import com.vitorpamplona.quartz.nip73ExternalIds.topics.HashtagId import com.vitorpamplona.quartz.nip73ExternalIds.topics.HashtagId
import com.vitorpamplona.quartz.utils.Log
import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.DelicateCoroutinesApi import kotlinx.coroutines.DelicateCoroutinesApi
import kotlinx.coroutines.Dispatchers 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.OtsEvent
import com.vitorpamplona.quartz.nip03Timestamp.VerificationStateCache import com.vitorpamplona.quartz.nip03Timestamp.VerificationStateCache
import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.flow.SharingStarted import kotlinx.coroutines.flow.SharingStarted
import kotlinx.coroutines.flow.flowOn
import kotlinx.coroutines.flow.onEach import kotlinx.coroutines.flow.onEach
import kotlinx.coroutines.flow.stateIn import kotlinx.coroutines.flow.stateIn
@@ -37,14 +39,17 @@ class IncomingOtsEventVerifier(
val verifying = val verifying =
cache.live.newEventBundles cache.live.newEventBundles
.onEach { newNotes -> .onEach { newNotes ->
newNotes.forEach(::consume) newNotes.forEach {
}.stateIn( consume(it)
}
}.flowOn(Dispatchers.Default)
.stateIn(
scope, scope,
SharingStarted.Eagerly, SharingStarted.Eagerly,
null, null,
) )
fun consume(note: Note) { suspend fun consume(note: Note) {
note.event?.let { event -> note.event?.let { event ->
if (event is OtsEvent) { if (event is OtsEvent) {
otsVerifCache.cacheVerify(event) otsVerifCache.cacheVerify(event)
@@ -20,7 +20,6 @@
*/ */
package com.vitorpamplona.amethyst.model.nip03Timestamp package com.vitorpamplona.amethyst.model.nip03Timestamp
import android.util.Log
import com.vitorpamplona.amethyst.model.AccountSettings import com.vitorpamplona.amethyst.model.AccountSettings
import com.vitorpamplona.amethyst.model.LocalCache import com.vitorpamplona.amethyst.model.LocalCache
import com.vitorpamplona.amethyst.model.Note 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.nip01Core.signers.NostrSigner
import com.vitorpamplona.quartz.nip03Timestamp.OtsEvent import com.vitorpamplona.quartz.nip03Timestamp.OtsEvent
import com.vitorpamplona.quartz.nip03Timestamp.OtsResolverBuilder import com.vitorpamplona.quartz.nip03Timestamp.OtsResolverBuilder
import com.vitorpamplona.quartz.utils.Log
import com.vitorpamplona.quartz.utils.TimeUtils import com.vitorpamplona.quartz.utils.TimeUtils
import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.flow.update import kotlinx.coroutines.flow.update
@@ -85,7 +85,7 @@ class OtsState(
return settings.pendingAttestations.value[id] != null return settings.pendingAttestations.value[id] != null
} }
fun timestamp(note: Note) { suspend fun timestamp(note: Note) {
if (note.isDraft()) return if (note.isDraft()) return
val id = note.event?.id ?: note.idHex 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 package com.vitorpamplona.amethyst.model.nip11RelayInfo
import android.util.Log
import androidx.compose.runtime.Composable import androidx.compose.runtime.Composable
import androidx.compose.runtime.State import androidx.compose.runtime.State
import androidx.compose.runtime.produceState import androidx.compose.runtime.produceState
import com.vitorpamplona.amethyst.Amethyst import com.vitorpamplona.amethyst.Amethyst
import com.vitorpamplona.quartz.nip01Core.relay.normalizer.NormalizedRelayUrl import com.vitorpamplona.quartz.nip01Core.relay.normalizer.NormalizedRelayUrl
import com.vitorpamplona.quartz.nip11RelayInfo.Nip11RelayInformation import com.vitorpamplona.quartz.nip11RelayInfo.Nip11RelayInformation
import com.vitorpamplona.quartz.utils.Log
@Composable @Composable
fun loadRelayInfo(relay: NormalizedRelayUrl): State<Nip11RelayInformation> = loadRelayInfo(relay, Amethyst.instance.nip11Cache) fun loadRelayInfo(relay: NormalizedRelayUrl): State<Nip11RelayInformation> = loadRelayInfo(relay, Amethyst.instance.nip11Cache)
@@ -20,10 +20,10 @@
*/ */
package com.vitorpamplona.amethyst.model.nip11RelayInfo 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.NormalizedRelayUrl
import com.vitorpamplona.quartz.nip01Core.relay.normalizer.toHttp import com.vitorpamplona.quartz.nip01Core.relay.normalizer.toHttp
import com.vitorpamplona.quartz.nip11RelayInfo.Nip11RelayInformation import com.vitorpamplona.quartz.nip11RelayInfo.Nip11RelayInformation
import com.vitorpamplona.quartz.utils.Log
import kotlinx.coroutines.CancellationException import kotlinx.coroutines.CancellationException
import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.withContext import kotlinx.coroutines.withContext
@@ -20,7 +20,6 @@
*/ */
package com.vitorpamplona.amethyst.model.nip17Dms package com.vitorpamplona.amethyst.model.nip17Dms
import android.util.Log
import com.vitorpamplona.amethyst.model.AccountSettings import com.vitorpamplona.amethyst.model.AccountSettings
import com.vitorpamplona.amethyst.model.LocalCache import com.vitorpamplona.amethyst.model.LocalCache
import com.vitorpamplona.amethyst.model.Note 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.relay.normalizer.NormalizedRelayUrl
import com.vitorpamplona.quartz.nip01Core.signers.NostrSigner import com.vitorpamplona.quartz.nip01Core.signers.NostrSigner
import com.vitorpamplona.quartz.nip17Dm.settings.ChatMessageRelayListEvent import com.vitorpamplona.quartz.nip17Dm.settings.ChatMessageRelayListEvent
import com.vitorpamplona.quartz.utils.Log
import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.DelicateCoroutinesApi import kotlinx.coroutines.DelicateCoroutinesApi
import kotlinx.coroutines.Dispatchers 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.Note
import com.vitorpamplona.amethyst.model.User import com.vitorpamplona.amethyst.model.User
import com.vitorpamplona.amethyst.ui.note.toShortDisplay 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.EventHintBundle
import com.vitorpamplona.quartz.nip01Core.hints.types.EventIdHintOptional 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.nip19Bech32.entities.NEvent
import com.vitorpamplona.quartz.nip28PublicChat.admin.ChannelCreateEvent import com.vitorpamplona.quartz.nip28PublicChat.admin.ChannelCreateEvent
import com.vitorpamplona.quartz.nip28PublicChat.admin.ChannelMetadataEvent import com.vitorpamplona.quartz.nip28PublicChat.admin.ChannelMetadataEvent
@@ -20,7 +20,6 @@
*/ */
package com.vitorpamplona.amethyst.model.nip28PublicChats package com.vitorpamplona.amethyst.model.nip28PublicChats
import android.util.Log
import com.vitorpamplona.amethyst.model.AccountSettings import com.vitorpamplona.amethyst.model.AccountSettings
import com.vitorpamplona.amethyst.model.LocalCache import com.vitorpamplona.amethyst.model.LocalCache
import com.vitorpamplona.amethyst.model.Note 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.nip01Core.signers.NostrSigner
import com.vitorpamplona.quartz.nip28PublicChat.list.ChannelListEvent import com.vitorpamplona.quartz.nip28PublicChat.list.ChannelListEvent
import com.vitorpamplona.quartz.nip28PublicChat.list.tags.ChannelTag import com.vitorpamplona.quartz.nip28PublicChat.list.tags.ChannelTag
import com.vitorpamplona.quartz.utils.Log
import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.DelicateCoroutinesApi import kotlinx.coroutines.DelicateCoroutinesApi
import kotlinx.coroutines.Dispatchers 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.Note
import com.vitorpamplona.amethyst.model.NoteState import com.vitorpamplona.amethyst.model.NoteState
import com.vitorpamplona.quartz.nip01Core.signers.NostrSigner 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.pack.EmojiPackEvent
import com.vitorpamplona.quartz.nip30CustomEmoji.selection.EmojiPackSelectionEvent import com.vitorpamplona.quartz.nip30CustomEmoji.selection.EmojiPackSelectionEvent
import com.vitorpamplona.quartz.nip30CustomEmoji.taggedEmojis import com.vitorpamplona.quartz.nip30CustomEmoji.taggedEmojis
@@ -20,7 +20,6 @@
*/ */
package com.vitorpamplona.amethyst.model.nip51Lists.blockedRelays package com.vitorpamplona.amethyst.model.nip51Lists.blockedRelays
import android.util.Log
import com.vitorpamplona.amethyst.model.AccountSettings import com.vitorpamplona.amethyst.model.AccountSettings
import com.vitorpamplona.amethyst.model.LocalCache import com.vitorpamplona.amethyst.model.LocalCache
import com.vitorpamplona.amethyst.model.Note 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.NostrSigner
import com.vitorpamplona.quartz.nip01Core.signers.SignerExceptions import com.vitorpamplona.quartz.nip01Core.signers.SignerExceptions
import com.vitorpamplona.quartz.nip51Lists.relayLists.BlockedRelayListEvent import com.vitorpamplona.quartz.nip51Lists.relayLists.BlockedRelayListEvent
import com.vitorpamplona.quartz.utils.Log
import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.DelicateCoroutinesApi import kotlinx.coroutines.DelicateCoroutinesApi
import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.Dispatchers
@@ -20,13 +20,13 @@
*/ */
package com.vitorpamplona.amethyst.model.nip51Lists.geohashLists package com.vitorpamplona.amethyst.model.nip51Lists.geohashLists
import android.util.Log
import com.vitorpamplona.amethyst.model.AccountSettings import com.vitorpamplona.amethyst.model.AccountSettings
import com.vitorpamplona.amethyst.model.LocalCache import com.vitorpamplona.amethyst.model.LocalCache
import com.vitorpamplona.amethyst.model.Note import com.vitorpamplona.amethyst.model.Note
import com.vitorpamplona.amethyst.model.NoteState import com.vitorpamplona.amethyst.model.NoteState
import com.vitorpamplona.quartz.nip01Core.signers.NostrSigner import com.vitorpamplona.quartz.nip01Core.signers.NostrSigner
import com.vitorpamplona.quartz.nip51Lists.geohashList.GeohashListEvent import com.vitorpamplona.quartz.nip51Lists.geohashList.GeohashListEvent
import com.vitorpamplona.quartz.utils.Log
import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.DelicateCoroutinesApi import kotlinx.coroutines.DelicateCoroutinesApi
import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.Dispatchers
@@ -20,13 +20,13 @@
*/ */
package com.vitorpamplona.amethyst.model.nip51Lists.hashtagLists package com.vitorpamplona.amethyst.model.nip51Lists.hashtagLists
import android.util.Log
import com.vitorpamplona.amethyst.model.AccountSettings import com.vitorpamplona.amethyst.model.AccountSettings
import com.vitorpamplona.amethyst.model.LocalCache import com.vitorpamplona.amethyst.model.LocalCache
import com.vitorpamplona.amethyst.model.Note import com.vitorpamplona.amethyst.model.Note
import com.vitorpamplona.amethyst.model.NoteState import com.vitorpamplona.amethyst.model.NoteState
import com.vitorpamplona.quartz.nip01Core.signers.NostrSigner import com.vitorpamplona.quartz.nip01Core.signers.NostrSigner
import com.vitorpamplona.quartz.nip51Lists.hashtagList.HashtagListEvent import com.vitorpamplona.quartz.nip51Lists.hashtagList.HashtagListEvent
import com.vitorpamplona.quartz.utils.Log
import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.DelicateCoroutinesApi import kotlinx.coroutines.DelicateCoroutinesApi
import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.Dispatchers
@@ -20,7 +20,6 @@
*/ */
package com.vitorpamplona.amethyst.model.nip51Lists.muteList package com.vitorpamplona.amethyst.model.nip51Lists.muteList
import android.util.Log
import com.vitorpamplona.amethyst.model.AccountSettings import com.vitorpamplona.amethyst.model.AccountSettings
import com.vitorpamplona.amethyst.model.LocalCache import com.vitorpamplona.amethyst.model.LocalCache
import com.vitorpamplona.amethyst.model.Note 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.MuteTag
import com.vitorpamplona.quartz.nip51Lists.muteList.tags.UserTag import com.vitorpamplona.quartz.nip51Lists.muteList.tags.UserTag
import com.vitorpamplona.quartz.nip51Lists.muteList.tags.WordTag import com.vitorpamplona.quartz.nip51Lists.muteList.tags.WordTag
import com.vitorpamplona.quartz.utils.Log
import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.DelicateCoroutinesApi import kotlinx.coroutines.DelicateCoroutinesApi
import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.Dispatchers
@@ -20,7 +20,6 @@
*/ */
package com.vitorpamplona.amethyst.model.nip51Lists.searchRelays package com.vitorpamplona.amethyst.model.nip51Lists.searchRelays
import android.util.Log
import com.vitorpamplona.amethyst.model.AccountSettings import com.vitorpamplona.amethyst.model.AccountSettings
import com.vitorpamplona.amethyst.model.DefaultSearchRelayList import com.vitorpamplona.amethyst.model.DefaultSearchRelayList
import com.vitorpamplona.amethyst.model.LocalCache 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.relay.normalizer.NormalizedRelayUrl
import com.vitorpamplona.quartz.nip01Core.signers.NostrSigner import com.vitorpamplona.quartz.nip01Core.signers.NostrSigner
import com.vitorpamplona.quartz.nip50Search.SearchRelayListEvent import com.vitorpamplona.quartz.nip50Search.SearchRelayListEvent
import com.vitorpamplona.quartz.utils.Log
import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.DelicateCoroutinesApi import kotlinx.coroutines.DelicateCoroutinesApi
import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.Dispatchers
@@ -20,7 +20,6 @@
*/ */
package com.vitorpamplona.amethyst.model.nip51Lists.trustedRelays package com.vitorpamplona.amethyst.model.nip51Lists.trustedRelays
import android.util.Log
import com.vitorpamplona.amethyst.model.AccountSettings import com.vitorpamplona.amethyst.model.AccountSettings
import com.vitorpamplona.amethyst.model.LocalCache import com.vitorpamplona.amethyst.model.LocalCache
import com.vitorpamplona.amethyst.model.Note 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.relay.normalizer.NormalizedRelayUrl
import com.vitorpamplona.quartz.nip01Core.signers.NostrSigner import com.vitorpamplona.quartz.nip01Core.signers.NostrSigner
import com.vitorpamplona.quartz.nip51Lists.relayLists.TrustedRelayListEvent import com.vitorpamplona.quartz.nip51Lists.relayLists.TrustedRelayListEvent
import com.vitorpamplona.quartz.utils.Log
import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.DelicateCoroutinesApi import kotlinx.coroutines.DelicateCoroutinesApi
import kotlinx.coroutines.Dispatchers 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.Note
import com.vitorpamplona.amethyst.model.User import com.vitorpamplona.amethyst.model.User
import com.vitorpamplona.amethyst.ui.note.toShortDisplay import com.vitorpamplona.amethyst.ui.note.toShortDisplay
import com.vitorpamplona.quartz.nip01Core.tags.addressables.ATag import com.vitorpamplona.quartz.nip01Core.core.Address
import com.vitorpamplona.quartz.nip01Core.tags.addressables.Address import com.vitorpamplona.quartz.nip01Core.tags.aTag.ATag
import com.vitorpamplona.quartz.nip19Bech32.entities.NAddress import com.vitorpamplona.quartz.nip19Bech32.entities.NAddress
import com.vitorpamplona.quartz.nip53LiveActivities.streaming.LiveActivitiesEvent import com.vitorpamplona.quartz.nip53LiveActivities.streaming.LiveActivitiesEvent
@@ -20,7 +20,6 @@
*/ */
package com.vitorpamplona.amethyst.model.nip65RelayList package com.vitorpamplona.amethyst.model.nip65RelayList
import android.util.Log
import com.vitorpamplona.amethyst.model.AccountSettings import com.vitorpamplona.amethyst.model.AccountSettings
import com.vitorpamplona.amethyst.model.Constants import com.vitorpamplona.amethyst.model.Constants
import com.vitorpamplona.amethyst.model.LocalCache 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.nip01Core.signers.NostrSigner
import com.vitorpamplona.quartz.nip65RelayList.AdvertisedRelayListEvent import com.vitorpamplona.quartz.nip65RelayList.AdvertisedRelayListEvent
import com.vitorpamplona.quartz.nip65RelayList.tags.AdvertisedRelayInfo import com.vitorpamplona.quartz.nip65RelayList.tags.AdvertisedRelayInfo
import com.vitorpamplona.quartz.utils.Log
import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.DelicateCoroutinesApi import kotlinx.coroutines.DelicateCoroutinesApi
import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.Dispatchers
@@ -20,7 +20,6 @@
*/ */
package com.vitorpamplona.amethyst.model.nip72Communities package com.vitorpamplona.amethyst.model.nip72Communities
import android.util.Log
import com.vitorpamplona.amethyst.model.AccountSettings import com.vitorpamplona.amethyst.model.AccountSettings
import com.vitorpamplona.amethyst.model.AddressableNote import com.vitorpamplona.amethyst.model.AddressableNote
import com.vitorpamplona.amethyst.model.LocalCache 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.definition.CommunityDefinitionEvent
import com.vitorpamplona.quartz.nip72ModCommunities.follow.CommunityListEvent import com.vitorpamplona.quartz.nip72ModCommunities.follow.CommunityListEvent
import com.vitorpamplona.quartz.nip72ModCommunities.follow.tags.CommunityTag import com.vitorpamplona.quartz.nip72ModCommunities.follow.tags.CommunityTag
import com.vitorpamplona.quartz.utils.Log
import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.DelicateCoroutinesApi import kotlinx.coroutines.DelicateCoroutinesApi
import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.Dispatchers
@@ -20,15 +20,14 @@
*/ */
package com.vitorpamplona.amethyst.model.nip78AppSpecific 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.AccountSettings
import com.vitorpamplona.amethyst.model.AccountSyncedSettingsInternal import com.vitorpamplona.amethyst.model.AccountSyncedSettingsInternal
import com.vitorpamplona.amethyst.model.LocalCache import com.vitorpamplona.amethyst.model.LocalCache
import com.vitorpamplona.amethyst.model.NoteState 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.nip01Core.signers.NostrSigner
import com.vitorpamplona.quartz.nip78AppData.AppSpecificDataEvent import com.vitorpamplona.quartz.nip78AppData.AppSpecificDataEvent
import com.vitorpamplona.quartz.utils.Log
import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.DelicateCoroutinesApi import kotlinx.coroutines.DelicateCoroutinesApi
import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.Dispatchers
@@ -58,7 +57,7 @@ class AppSpecificState(
val toInternal = settings.syncedSettings.toInternal() val toInternal = settings.syncedSettings.toInternal()
return AppSpecificDataEvent.create( return AppSpecificDataEvent.create(
dTag = APP_SPECIFIC_DATA_D_TAG, 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(), otherTags = emptyArray(),
signer = signer, signer = signer,
) )
@@ -73,7 +72,7 @@ class AppSpecificState(
LocalCache.justConsumeMyOwnEvent(event) LocalCache.justConsumeMyOwnEvent(event)
try { try {
val decrypted = signer.decrypt(event.content, event.pubKey) 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) settings.syncedSettings.updateFrom(syncedSettings)
} catch (e: Throwable) { } catch (e: Throwable) {
if (e is CancellationException) throw e if (e is CancellationException) throw e
@@ -90,7 +89,7 @@ class AppSpecificState(
(it.note.event as? AppSpecificDataEvent)?.let { (it.note.event as? AppSpecificDataEvent)?.let {
val decrypted = signer.decrypt(it.content, it.pubKey) val decrypted = signer.decrypt(it.content, it.pubKey)
try { try {
val syncedSettings = JsonMapper.mapper.readValue<AccountSyncedSettingsInternal>(decrypted) val syncedSettings = JsonMapper.fromJson<AccountSyncedSettingsInternal>(decrypted)
settings.updateAppSpecificData(it, syncedSettings) settings.updateAppSpecificData(it, syncedSettings)
} catch (e: Throwable) { } catch (e: Throwable) {
if (e is CancellationException) throw e 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.AddressableNote
import com.vitorpamplona.amethyst.model.LocalCache import com.vitorpamplona.amethyst.model.LocalCache
import com.vitorpamplona.amethyst.model.Note 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.core.Event
import com.vitorpamplona.quartz.nip01Core.tags.addressables.Address
import kotlinx.coroutines.flow.MutableStateFlow import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.asStateFlow 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.PreferenceDataStoreFactory
import androidx.datastore.preferences.core.Preferences import androidx.datastore.preferences.core.Preferences
import androidx.datastore.preferences.core.stringPreferencesKey import androidx.datastore.preferences.core.stringPreferencesKey
import com.vitorpamplona.quartz.utils.LargeCache import com.vitorpamplona.quartz.utils.cache.LargeCache
import java.io.File import java.io.File
class AccountPreferenceStores( class AccountPreferenceStores(
@@ -24,7 +24,7 @@ import androidx.datastore.preferences.core.PreferenceDataStoreFactory
import androidx.datastore.preferences.core.stringPreferencesKey import androidx.datastore.preferences.core.stringPreferencesKey
import com.vitorpamplona.quartz.nip01Core.core.HexKey import com.vitorpamplona.quartz.nip01Core.core.HexKey
import com.vitorpamplona.quartz.nip47WalletConnect.Nip47WalletConnect import com.vitorpamplona.quartz.nip47WalletConnect.Nip47WalletConnect
import com.vitorpamplona.quartz.utils.LargeCache import com.vitorpamplona.quartz.utils.cache.LargeCache
import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.CoroutineScope
import java.io.File import java.io.File
@@ -29,16 +29,16 @@ import kotlinx.coroutines.flow.catch
import kotlinx.coroutines.flow.firstOrNull import kotlinx.coroutines.flow.firstOrNull
import kotlinx.coroutines.flow.map import kotlinx.coroutines.flow.map
import java.io.IOException import java.io.IOException
import java.util.Base64 import kotlin.io.encoding.Base64
class EncryptedDataStore( class EncryptedDataStore(
private val store: DataStore<Preferences>, private val store: DataStore<Preferences>,
private val encryption: KeyStoreEncryption = KeyStoreEncryption(), private val encryption: KeyStoreEncryption = KeyStoreEncryption(),
private val scope: CoroutineScope, 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())) private fun encrypt(value: String): String = encode(encryption.encrypt(value.toByteArray()))
@@ -21,16 +21,15 @@
package com.vitorpamplona.amethyst.model.preferences package com.vitorpamplona.amethyst.model.preferences
import android.content.Context import android.content.Context
import android.util.Log
import androidx.compose.runtime.Stable import androidx.compose.runtime.Stable
import androidx.datastore.preferences.core.booleanPreferencesKey import androidx.datastore.preferences.core.booleanPreferencesKey
import androidx.datastore.preferences.core.edit import androidx.datastore.preferences.core.edit
import androidx.datastore.preferences.core.intPreferencesKey import androidx.datastore.preferences.core.intPreferencesKey
import androidx.datastore.preferences.core.stringPreferencesKey import androidx.datastore.preferences.core.stringPreferencesKey
import com.vitorpamplona.amethyst.ui.actions.MediaSaverToDisk.save
import com.vitorpamplona.amethyst.ui.tor.TorSettings import com.vitorpamplona.amethyst.ui.tor.TorSettings
import com.vitorpamplona.amethyst.ui.tor.TorSettingsFlow import com.vitorpamplona.amethyst.ui.tor.TorSettingsFlow
import com.vitorpamplona.amethyst.ui.tor.TorType import com.vitorpamplona.amethyst.ui.tor.TorType
import com.vitorpamplona.quartz.utils.Log
import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.FlowPreview import kotlinx.coroutines.FlowPreview
@@ -21,7 +21,6 @@
package com.vitorpamplona.amethyst.model.preferences package com.vitorpamplona.amethyst.model.preferences
import android.content.Context import android.content.Context
import android.util.Log
import androidx.appcompat.app.AppCompatDelegate import androidx.appcompat.app.AppCompatDelegate
import androidx.compose.runtime.Stable import androidx.compose.runtime.Stable
import androidx.core.os.LocaleListCompat 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.ThemeType
import com.vitorpamplona.amethyst.model.UiSettings import com.vitorpamplona.amethyst.model.UiSettings
import com.vitorpamplona.amethyst.model.UiSettingsFlow import com.vitorpamplona.amethyst.model.UiSettingsFlow
import com.vitorpamplona.quartz.utils.Log
import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.FlowPreview 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.nip01Core.core.HexKey
import com.vitorpamplona.quartz.nip17Dm.base.ChatroomKey import com.vitorpamplona.quartz.nip17Dm.base.ChatroomKey
import com.vitorpamplona.quartz.nip17Dm.base.ChatroomKeyable 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 import kotlinx.collections.immutable.persistentSetOf
class ChatroomList( 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.DEFAULT_MEDIA_SERVERS
import com.vitorpamplona.amethyst.ui.actions.mediaServers.ServerName import com.vitorpamplona.amethyst.ui.actions.mediaServers.ServerName
import com.vitorpamplona.amethyst.ui.actions.mediaServers.ServerType import com.vitorpamplona.amethyst.ui.actions.mediaServers.ServerType
import com.vitorpamplona.quartz.utils.Rfc3986
import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.flow.SharingStarted import kotlinx.coroutines.flow.SharingStarted
@@ -33,7 +34,6 @@ import kotlinx.coroutines.flow.combine
import kotlinx.coroutines.flow.flowOn import kotlinx.coroutines.flow.flowOn
import kotlinx.coroutines.flow.onStart import kotlinx.coroutines.flow.onStart
import kotlinx.coroutines.flow.stateIn import kotlinx.coroutines.flow.stateIn
import org.czeal.rfc3986.URIReference
class MergedServerListState( class MergedServerListState(
val fileServers: FileStorageServerListState, val fileServers: FileStorageServerListState,
@@ -42,7 +42,7 @@ class MergedServerListState(
) { ) {
fun host(url: String): String = fun host(url: String): String =
try { try {
URIReference.parse(url).host.value Rfc3986.host(url)
} catch (e: Exception) { } catch (e: Exception) {
url 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.Event
import com.vitorpamplona.quartz.nip01Core.core.HexKey import com.vitorpamplona.quartz.nip01Core.core.HexKey
import com.vitorpamplona.quartz.nip01Core.relay.normalizer.NormalizedRelayUrl 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.geohash.isTaggedGeoHashes
import com.vitorpamplona.quartz.nip01Core.tags.hashtags.isTaggedHashes import com.vitorpamplona.quartz.nip01Core.tags.hashtags.isTaggedHashes
import com.vitorpamplona.quartz.nip22Comments.CommentEvent 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.Event
import com.vitorpamplona.quartz.nip01Core.core.HexKey import com.vitorpamplona.quartz.nip01Core.core.HexKey
import com.vitorpamplona.quartz.nip01Core.relay.normalizer.NormalizedRelayUrl 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.geohash.isTaggedGeoHashes
import com.vitorpamplona.quartz.nip01Core.tags.hashtags.isTaggedHashes import com.vitorpamplona.quartz.nip01Core.tags.hashtags.isTaggedHashes
import com.vitorpamplona.quartz.nip22Comments.CommentEvent 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.Event
import com.vitorpamplona.quartz.nip01Core.core.HexKey import com.vitorpamplona.quartz.nip01Core.core.HexKey
import com.vitorpamplona.quartz.nip01Core.relay.normalizer.NormalizedRelayUrl 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.Flow
import kotlinx.coroutines.flow.StateFlow import kotlinx.coroutines.flow.StateFlow
import kotlinx.coroutines.flow.combine 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.Event
import com.vitorpamplona.quartz.nip01Core.core.HexKey import com.vitorpamplona.quartz.nip01Core.core.HexKey
import com.vitorpamplona.quartz.nip01Core.relay.normalizer.NormalizedRelayUrl 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.nip22Comments.CommentEvent
import com.vitorpamplona.quartz.nip53LiveActivities.streaming.LiveActivitiesEvent import com.vitorpamplona.quartz.nip53LiveActivities.streaming.LiveActivitiesEvent
import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.Flow
@@ -22,7 +22,7 @@ package com.vitorpamplona.amethyst.model.topNavFeeds.noteBased.community
import androidx.compose.runtime.Immutable import androidx.compose.runtime.Immutable
import com.vitorpamplona.amethyst.model.topNavFeeds.IFeedTopNavPerRelayFilter import com.vitorpamplona.amethyst.model.topNavFeeds.IFeedTopNavPerRelayFilter
import com.vitorpamplona.quartz.nip01Core.tags.addressables.Address import com.vitorpamplona.quartz.nip01Core.core.Address
@Immutable @Immutable
class SingleCommunityTopNavPerRelayFilter( class SingleCommunityTopNavPerRelayFilter(
@@ -23,7 +23,7 @@ package com.vitorpamplona.amethyst.service
import android.util.LruCache import android.util.LruCache
import com.vitorpamplona.amethyst.commons.richtext.RichTextParser import com.vitorpamplona.amethyst.commons.richtext.RichTextParser
import com.vitorpamplona.amethyst.commons.richtext.RichTextViewerState import com.vitorpamplona.amethyst.commons.richtext.RichTextViewerState
import com.vitorpamplona.quartz.nip02FollowList.ImmutableListOfLists import com.vitorpamplona.quartz.nip01Core.core.ImmutableListOfLists
object CachedRichTextParser { object CachedRichTextParser {
private val richTextCache = LruCache<Int, RichTextViewerState>(50) private val richTextCache = LruCache<Int, RichTextViewerState>(50)
@@ -20,7 +20,7 @@
*/ */
package com.vitorpamplona.amethyst.service package com.vitorpamplona.amethyst.service
import android.util.Log import com.vitorpamplona.quartz.utils.Log
import kotlinx.coroutines.CancellationException import kotlinx.coroutines.CancellationException
import kotlinx.coroutines.delay import kotlinx.coroutines.delay
@@ -21,7 +21,7 @@
package com.vitorpamplona.amethyst.service package com.vitorpamplona.amethyst.service
import com.vitorpamplona.amethyst.commons.emojicoder.EmojiCoder 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 fun String.isUTF16Char(pos: Int): Boolean = Character.charCount(this.codePointAt(pos)) == 2
@@ -20,9 +20,9 @@
*/ */
package com.vitorpamplona.amethyst.service package com.vitorpamplona.amethyst.service
import android.util.Log
import android.util.LruCache import android.util.LruCache
import androidx.compose.runtime.Immutable import androidx.compose.runtime.Immutable
import com.vitorpamplona.quartz.utils.Log
import com.vitorpamplona.quartz.utils.RandomInstance import com.vitorpamplona.quartz.utils.RandomInstance
import com.vitorpamplona.quartz.utils.TimeUtils import com.vitorpamplona.quartz.utils.TimeUtils
import okhttp3.EventListener import okhttp3.EventListener
@@ -24,7 +24,7 @@ import android.content.Context
import android.net.ConnectivityManager import android.net.ConnectivityManager
import android.net.Network import android.net.Network
import android.net.NetworkCapabilities import android.net.NetworkCapabilities
import android.util.Log import com.vitorpamplona.quartz.utils.Log
import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.FlowPreview import kotlinx.coroutines.FlowPreview
import kotlinx.coroutines.channels.awaitClose import kotlinx.coroutines.channels.awaitClose
@@ -20,11 +20,11 @@
*/ */
package com.vitorpamplona.amethyst.service.eventCache package com.vitorpamplona.amethyst.service.eventCache
import android.util.Log
import com.vitorpamplona.amethyst.AccountInfo import com.vitorpamplona.amethyst.AccountInfo
import com.vitorpamplona.amethyst.model.Account import com.vitorpamplona.amethyst.model.Account
import com.vitorpamplona.amethyst.model.LocalCache import com.vitorpamplona.amethyst.model.LocalCache
import com.vitorpamplona.quartz.nip19Bech32.decodePublicKeyAsHexOrNull import com.vitorpamplona.quartz.nip19Bech32.decodePublicKeyAsHexOrNull
import com.vitorpamplona.quartz.utils.Log
import java.util.concurrent.atomic.AtomicBoolean import java.util.concurrent.atomic.AtomicBoolean
class MemoryTrimmingService( class MemoryTrimmingService(
@@ -21,7 +21,6 @@
package com.vitorpamplona.amethyst.service.lnurl package com.vitorpamplona.amethyst.service.lnurl
import android.content.Context import android.content.Context
import android.util.Log
import com.fasterxml.jackson.module.kotlin.jacksonObjectMapper import com.fasterxml.jackson.module.kotlin.jacksonObjectMapper
import com.vitorpamplona.amethyst.R import com.vitorpamplona.amethyst.R
import com.vitorpamplona.amethyst.service.HttpStatusMessages 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.LnInvoiceUtil
import com.vitorpamplona.quartz.lightning.Lud06 import com.vitorpamplona.quartz.lightning.Lud06
import com.vitorpamplona.quartz.nip57Zaps.LnZapRequestEvent import com.vitorpamplona.quartz.nip57Zaps.LnZapRequestEvent
import com.vitorpamplona.quartz.utils.Log
import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.withContext import kotlinx.coroutines.withContext
import okhttp3.OkHttpClient import okhttp3.OkHttpClient
@@ -23,8 +23,8 @@ package com.vitorpamplona.amethyst.service.location
import android.content.Context import android.content.Context
import android.location.Geocoder import android.location.Geocoder
import android.location.Location import android.location.Location
import android.util.Log
import android.util.LruCache import android.util.LruCache
import com.vitorpamplona.quartz.utils.Log
/** /**
* Maintains a cache of geohashes and city,country pairs. * Maintains a cache of geohashes and city,country pairs.
@@ -26,9 +26,9 @@ import android.location.Location
import android.location.LocationListener import android.location.LocationListener
import android.location.LocationManager import android.location.LocationManager
import android.os.Looper 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_DISTANCE
import com.vitorpamplona.amethyst.service.location.LocationState.Companion.MIN_TIME import com.vitorpamplona.amethyst.service.location.LocationState.Companion.MIN_TIME
import com.vitorpamplona.quartz.utils.Log
import kotlinx.coroutines.channels.awaitClose import kotlinx.coroutines.channels.awaitClose
import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.callbackFlow import kotlinx.coroutines.flow.callbackFlow
@@ -21,10 +21,10 @@
package com.vitorpamplona.amethyst.service.location package com.vitorpamplona.amethyst.service.location
import android.content.Context import android.content.Context
import android.util.Log
import com.fonfon.kgeohash.GeoHash import com.fonfon.kgeohash.GeoHash
import com.fonfon.kgeohash.toGeoHash import com.fonfon.kgeohash.toGeoHash
import com.vitorpamplona.quartz.nip01Core.tags.geohash.GeohashPrecision import com.vitorpamplona.quartz.nip01Core.tags.geohash.GeohashPrecision
import com.vitorpamplona.quartz.utils.Log
import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.ExperimentalCoroutinesApi import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.flow.MutableStateFlow import kotlinx.coroutines.flow.MutableStateFlow
@@ -25,8 +25,8 @@ import android.location.Address
import android.location.Geocoder import android.location.Geocoder
import android.location.Location import android.location.Location
import android.os.Build import android.os.Build
import android.util.Log
import androidx.annotation.RequiresApi import androidx.annotation.RequiresApi
import com.vitorpamplona.quartz.utils.Log
import java.io.IOException import java.io.IOException
class ReverseGeolocation { class ReverseGeolocation {
@@ -20,8 +20,8 @@
*/ */
package com.vitorpamplona.amethyst.service.logging package com.vitorpamplona.amethyst.service.logging
import android.util.Log
import android.view.Choreographer import android.view.Choreographer
import com.vitorpamplona.quartz.utils.Log
object ChoreographerHelper { object ChoreographerHelper {
var lastFrameTimeNanos: Long = 0 var lastFrameTimeNanos: Long = 0
@@ -24,8 +24,8 @@ import android.annotation.SuppressLint
import android.os.Handler import android.os.Handler
import android.os.HandlerThread import android.os.HandlerThread
import android.os.Looper import android.os.Looper
import android.util.Log
import android.util.Printer import android.util.Printer
import com.vitorpamplona.quartz.utils.Log
import java.text.SimpleDateFormat import java.text.SimpleDateFormat
import java.util.concurrent.atomic.AtomicBoolean import java.util.concurrent.atomic.AtomicBoolean
@@ -22,14 +22,12 @@ package com.vitorpamplona.amethyst.service.notifications
import android.app.NotificationManager import android.app.NotificationManager
import android.content.Context import android.content.Context
import android.util.Log
import androidx.core.content.ContextCompat import androidx.core.content.ContextCompat
import com.vitorpamplona.amethyst.Amethyst import com.vitorpamplona.amethyst.Amethyst
import com.vitorpamplona.amethyst.LocalPreferences import com.vitorpamplona.amethyst.LocalPreferences
import com.vitorpamplona.amethyst.R import com.vitorpamplona.amethyst.R
import com.vitorpamplona.amethyst.model.Account import com.vitorpamplona.amethyst.model.Account
import com.vitorpamplona.amethyst.model.LocalCache import com.vitorpamplona.amethyst.model.LocalCache
import com.vitorpamplona.amethyst.model.LocalCache.chatroomList
import com.vitorpamplona.amethyst.model.Note import com.vitorpamplona.amethyst.model.Note
import com.vitorpamplona.amethyst.service.notifications.NotificationUtils.sendDMNotification import com.vitorpamplona.amethyst.service.notifications.NotificationUtils.sendDMNotification
import com.vitorpamplona.amethyst.service.notifications.NotificationUtils.sendZapNotification import com.vitorpamplona.amethyst.service.notifications.NotificationUtils.sendZapNotification
@@ -49,6 +47,7 @@ import com.vitorpamplona.quartz.nip57Zaps.LnZapEvent
import com.vitorpamplona.quartz.nip57Zaps.LnZapRequestEvent import com.vitorpamplona.quartz.nip57Zaps.LnZapRequestEvent
import com.vitorpamplona.quartz.nip59Giftwrap.seals.SealedRumorEvent import com.vitorpamplona.quartz.nip59Giftwrap.seals.SealedRumorEvent
import com.vitorpamplona.quartz.nip59Giftwrap.wraps.GiftWrapEvent import com.vitorpamplona.quartz.nip59Giftwrap.wraps.GiftWrapEvent
import com.vitorpamplona.quartz.utils.Log
import com.vitorpamplona.quartz.utils.TimeUtils import com.vitorpamplona.quartz.utils.TimeUtils
import java.math.BigDecimal import java.math.BigDecimal
import kotlin.coroutines.cancellation.CancellationException import kotlin.coroutines.cancellation.CancellationException
@@ -26,8 +26,8 @@ import android.content.Context.RECEIVER_EXPORTED
import android.content.Intent import android.content.Intent
import android.content.IntentFilter import android.content.IntentFilter
import android.os.Build import android.os.Build
import android.util.Log
import com.vitorpamplona.quartz.nip01Core.core.Event import com.vitorpamplona.quartz.nip01Core.core.Event
import com.vitorpamplona.quartz.utils.Log
import kotlinx.coroutines.CoroutineExceptionHandler import kotlinx.coroutines.CoroutineExceptionHandler
import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.Dispatchers
@@ -20,7 +20,6 @@
*/ */
package com.vitorpamplona.amethyst.service.notifications package com.vitorpamplona.amethyst.service.notifications
import android.util.Log
import com.vitorpamplona.amethyst.AccountInfo import com.vitorpamplona.amethyst.AccountInfo
import com.vitorpamplona.amethyst.Amethyst import com.vitorpamplona.amethyst.Amethyst
import com.vitorpamplona.amethyst.BuildConfig import com.vitorpamplona.amethyst.BuildConfig
@@ -29,6 +28,7 @@ import com.vitorpamplona.amethyst.isDebug
import com.vitorpamplona.amethyst.model.AccountSettings import com.vitorpamplona.amethyst.model.AccountSettings
import com.vitorpamplona.quartz.nip01Core.relay.normalizer.NormalizedRelayUrl import com.vitorpamplona.quartz.nip01Core.relay.normalizer.NormalizedRelayUrl
import com.vitorpamplona.quartz.nip42RelayAuth.RelayAuthEvent import com.vitorpamplona.quartz.nip42RelayAuth.RelayAuthEvent
import com.vitorpamplona.quartz.utils.Log
import com.vitorpamplona.quartz.utils.mapNotNullAsync import com.vitorpamplona.quartz.utils.mapNotNullAsync
import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.withContext import kotlinx.coroutines.withContext
@@ -20,7 +20,7 @@
*/ */
package com.vitorpamplona.amethyst.service.okhttp 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.Interceptor
import okhttp3.MediaType.Companion.toMediaTypeOrNull import okhttp3.MediaType.Companion.toMediaTypeOrNull
import okhttp3.Response import okhttp3.Response
@@ -21,7 +21,7 @@
package com.vitorpamplona.amethyst.service.okhttp package com.vitorpamplona.amethyst.service.okhttp
import android.util.LruCache 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 * Neigther ExoPlayer, nor Coil support passing key and nonce to the Interceptor via
@@ -20,7 +20,7 @@
*/ */
package com.vitorpamplona.amethyst.service.okhttp package com.vitorpamplona.amethyst.service.okhttp
import android.util.Log import com.vitorpamplona.quartz.utils.Log
import okhttp3.Interceptor import okhttp3.Interceptor
import okhttp3.Request import okhttp3.Request
import okhttp3.Response import okhttp3.Response
@@ -21,7 +21,7 @@
package com.vitorpamplona.amethyst.service.okhttp package com.vitorpamplona.amethyst.service.okhttp
import android.os.Build import android.os.Build
import android.util.Log import com.vitorpamplona.quartz.utils.Log
import okhttp3.Dispatcher import okhttp3.Dispatcher
import okhttp3.OkHttpClient import okhttp3.OkHttpClient
import java.net.InetSocketAddress import java.net.InetSocketAddress
@@ -20,7 +20,6 @@
*/ */
package com.vitorpamplona.amethyst.service.playback.composable package com.vitorpamplona.amethyst.service.playback.composable
import android.util.Log
import androidx.compose.runtime.Composable import androidx.compose.runtime.Composable
import androidx.compose.runtime.DisposableEffect import androidx.compose.runtime.DisposableEffect
import androidx.compose.runtime.remember 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.composable.mediaitem.LoadedMediaItem
import com.vitorpamplona.amethyst.service.playback.pip.BackgroundMedia import com.vitorpamplona.amethyst.service.playback.pip.BackgroundMedia
import com.vitorpamplona.amethyst.service.playback.service.PlaybackServiceClient import com.vitorpamplona.amethyst.service.playback.service.PlaybackServiceClient
import com.vitorpamplona.quartz.utils.Log
import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch import kotlinx.coroutines.launch
import java.util.concurrent.atomic.AtomicBoolean import java.util.concurrent.atomic.AtomicBoolean
@@ -25,12 +25,14 @@ import androidx.compose.runtime.MutableState
import androidx.compose.runtime.Stable import androidx.compose.runtime.Stable
import androidx.compose.runtime.mutableStateOf import androidx.compose.runtime.mutableStateOf
import androidx.media3.session.MediaController import androidx.media3.session.MediaController
import java.util.UUID import kotlin.uuid.ExperimentalUuidApi
import kotlin.uuid.Uuid
@OptIn(ExperimentalUuidApi::class)
@Stable @Stable
class MediaControllerState( class MediaControllerState(
// each composable has an ID. // 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 // This is filled after the controller returns from this class
var controller: MediaController? = null, var controller: MediaController? = null,
// this set's the stage to keep playing on the background or not when the user leaves the screen // 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 package com.vitorpamplona.amethyst.service.playback.playerPool
import android.content.Context import android.content.Context
import android.util.Log
import androidx.annotation.OptIn import androidx.annotation.OptIn
import androidx.media3.common.util.UnstableApi import androidx.media3.common.util.UnstableApi
import androidx.media3.exoplayer.ExoPlayer import androidx.media3.exoplayer.ExoPlayer
import com.vitorpamplona.quartz.utils.Log
import kotlinx.coroutines.CoroutineExceptionHandler import kotlinx.coroutines.CoroutineExceptionHandler
import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.Dispatchers
@@ -23,7 +23,6 @@ package com.vitorpamplona.amethyst.service.playback.playerPool
import android.app.PendingIntent import android.app.PendingIntent
import android.content.Context import android.content.Context
import android.content.Intent import android.content.Intent
import android.util.Log
import android.util.LruCache import android.util.LruCache
import androidx.annotation.OptIn import androidx.annotation.OptIn
import androidx.core.net.toUri 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.Futures
import com.google.common.util.concurrent.ListenableFuture import com.google.common.util.concurrent.ListenableFuture
import com.vitorpamplona.amethyst.ui.MainActivity import com.vitorpamplona.amethyst.ui.MainActivity
import com.vitorpamplona.quartz.utils.Log
import com.vitorpamplona.quartz.utils.TimeUtils import com.vitorpamplona.quartz.utils.TimeUtils
import kotlinx.coroutines.DelicateCoroutinesApi import kotlinx.coroutines.DelicateCoroutinesApi
import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.Dispatchers
@@ -20,7 +20,6 @@
*/ */
package com.vitorpamplona.amethyst.service.playback.service package com.vitorpamplona.amethyst.service.playback.service
import android.util.Log
import androidx.annotation.OptIn import androidx.annotation.OptIn
import androidx.media3.common.C import androidx.media3.common.C
import androidx.media3.common.Player 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.ExoPlayerPool
import com.vitorpamplona.amethyst.service.playback.playerPool.MediaSessionPool import com.vitorpamplona.amethyst.service.playback.playerPool.MediaSessionPool
import com.vitorpamplona.amethyst.service.playback.playerPool.SimultaneousPlaybackCalculator import com.vitorpamplona.amethyst.service.playback.playerPool.SimultaneousPlaybackCalculator
import com.vitorpamplona.quartz.utils.Log
import okhttp3.OkHttpClient import okhttp3.OkHttpClient
class PlaybackService : MediaSessionService() { class PlaybackService : MediaSessionService() {
@@ -23,10 +23,10 @@ package com.vitorpamplona.amethyst.service.playback.service
import android.content.ComponentName import android.content.ComponentName
import android.content.Context import android.content.Context
import android.os.Bundle import android.os.Bundle
import android.util.Log
import androidx.media3.session.MediaController import androidx.media3.session.MediaController
import androidx.media3.session.SessionToken import androidx.media3.session.SessionToken
import com.vitorpamplona.amethyst.service.playback.composable.MediaControllerState import com.vitorpamplona.amethyst.service.playback.composable.MediaControllerState
import com.vitorpamplona.quartz.utils.Log
import kotlinx.coroutines.CancellationException import kotlinx.coroutines.CancellationException
import kotlinx.coroutines.DelicateCoroutinesApi import kotlinx.coroutines.DelicateCoroutinesApi
import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.Dispatchers
@@ -20,11 +20,11 @@
*/ */
package com.vitorpamplona.amethyst.service.relayClient package com.vitorpamplona.amethyst.service.relayClient
import android.util.Log
import com.vitorpamplona.quartz.nip01Core.core.Event import com.vitorpamplona.quartz.nip01Core.core.Event
import com.vitorpamplona.quartz.nip01Core.relay.client.INostrClient import com.vitorpamplona.quartz.nip01Core.relay.client.INostrClient
import com.vitorpamplona.quartz.nip01Core.relay.client.listeners.IRelayClientListener import com.vitorpamplona.quartz.nip01Core.relay.client.listeners.IRelayClientListener
import com.vitorpamplona.quartz.nip01Core.relay.client.single.IRelayClient import com.vitorpamplona.quartz.nip01Core.relay.client.single.IRelayClient
import com.vitorpamplona.quartz.utils.Log
/** /**
* Listens to NostrClient's onNotify messages from the relay * Listens to NostrClient's onNotify messages from the relay
@@ -20,7 +20,6 @@
*/ */
package com.vitorpamplona.amethyst.service.relayClient package com.vitorpamplona.amethyst.service.relayClient
import android.util.Log
import com.vitorpamplona.amethyst.model.torState.TorRelayEvaluation import com.vitorpamplona.amethyst.model.torState.TorRelayEvaluation
import com.vitorpamplona.amethyst.service.connectivity.ConnectivityManager import com.vitorpamplona.amethyst.service.connectivity.ConnectivityManager
import com.vitorpamplona.amethyst.service.connectivity.ConnectivityStatus 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.TorManager
import com.vitorpamplona.amethyst.ui.tor.TorServiceStatus import com.vitorpamplona.amethyst.ui.tor.TorServiceStatus
import com.vitorpamplona.quartz.nip01Core.relay.client.INostrClient import com.vitorpamplona.quartz.nip01Core.relay.client.INostrClient
import com.vitorpamplona.quartz.utils.Log
import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.FlowPreview import kotlinx.coroutines.FlowPreview
@@ -20,11 +20,11 @@
*/ */
package com.vitorpamplona.amethyst.service.relayClient.authCommand.model package com.vitorpamplona.amethyst.service.relayClient.authCommand.model
import android.util.Log
import com.vitorpamplona.amethyst.isDebug import com.vitorpamplona.amethyst.isDebug
import com.vitorpamplona.amethyst.model.Account import com.vitorpamplona.amethyst.model.Account
import com.vitorpamplona.quartz.nip01Core.relay.client.INostrClient import com.vitorpamplona.quartz.nip01Core.relay.client.INostrClient
import com.vitorpamplona.quartz.nip01Core.relay.client.accessories.RelayAuthenticator import com.vitorpamplona.quartz.nip01Core.relay.client.accessories.RelayAuthenticator
import com.vitorpamplona.quartz.utils.Log
import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.CoroutineScope
class ScreenAuthAccount( class ScreenAuthAccount(
@@ -55,7 +55,7 @@ class AuthCoordinator(
if (account == null) return if (account == null) return
if (isDebug) { if (isDebug) {
Log.d(this::class.simpleName, "Watch $account") Log.d("AuthCoordinator", "Watch $account")
} }
authWithAccounts.add(account) authWithAccounts.add(account)
@@ -66,7 +66,7 @@ class AuthCoordinator(
if (account == null) return if (account == null) return
if (isDebug) { if (isDebug) {
Log.d(this::class.simpleName, "Unwatch $account") Log.d("AuthCoordinator", "Unwatch $account")
} }
authWithAccounts.remove(account) authWithAccounts.remove(account)
@@ -20,13 +20,13 @@
*/ */
package com.vitorpamplona.amethyst.service.relayClient.eoseManagers package com.vitorpamplona.amethyst.service.relayClient.eoseManagers
import android.util.Log
import com.vitorpamplona.amethyst.isDebug import com.vitorpamplona.amethyst.isDebug
import com.vitorpamplona.ammolite.relays.BundledUpdate import com.vitorpamplona.ammolite.relays.BundledUpdate
import com.vitorpamplona.quartz.nip01Core.relay.client.INostrClient import com.vitorpamplona.quartz.nip01Core.relay.client.INostrClient
import com.vitorpamplona.quartz.nip01Core.relay.client.single.newSubId import com.vitorpamplona.quartz.nip01Core.relay.client.single.newSubId
import com.vitorpamplona.quartz.nip01Core.relay.client.subscriptions.SubscriptionController import com.vitorpamplona.quartz.nip01Core.relay.client.subscriptions.SubscriptionController
import com.vitorpamplona.quartz.nip01Core.relay.normalizer.NormalizedRelayUrl import com.vitorpamplona.quartz.nip01Core.relay.normalizer.NormalizedRelayUrl
import com.vitorpamplona.quartz.utils.Log
import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.Dispatchers
abstract class BaseEoseManager<T>( 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.stringRes
import com.vitorpamplona.amethyst.ui.theme.Size16dp import com.vitorpamplona.amethyst.ui.theme.Size16dp
import com.vitorpamplona.amethyst.ui.theme.StdHorzSpacer import com.vitorpamplona.amethyst.ui.theme.StdHorzSpacer
import com.vitorpamplona.quartz.nip02FollowList.EmptyTagList import com.vitorpamplona.quartz.nip01Core.core.EmptyTagList
@Composable @Composable
fun NotifyRequestDialog( fun NotifyRequestDialog(
@@ -23,10 +23,10 @@ package com.vitorpamplona.amethyst.service.relayClient.reqCommand.event.loaders
import com.vitorpamplona.amethyst.model.AddressableNote import com.vitorpamplona.amethyst.model.AddressableNote
import com.vitorpamplona.amethyst.model.LocalCache import com.vitorpamplona.amethyst.model.LocalCache
import com.vitorpamplona.amethyst.service.relayClient.reqCommand.event.EventFinderQueryState 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.client.pool.RelayBasedFilter
import com.vitorpamplona.quartz.nip01Core.relay.filters.Filter import com.vitorpamplona.quartz.nip01Core.relay.filters.Filter
import com.vitorpamplona.quartz.nip01Core.relay.normalizer.NormalizedRelayUrl import com.vitorpamplona.quartz.nip01Core.relay.normalizer.NormalizedRelayUrl
import com.vitorpamplona.quartz.nip01Core.tags.addressables.Address
import com.vitorpamplona.quartz.utils.mapOfSet import com.vitorpamplona.quartz.utils.mapOfSet
fun potentialRelaysToFindAddress(note: AddressableNote): Set<NormalizedRelayUrl> { fun potentialRelaysToFindAddress(note: AddressableNote): Set<NormalizedRelayUrl> {
@@ -20,10 +20,10 @@
*/ */
package com.vitorpamplona.amethyst.service.relayClient.speedLogger package com.vitorpamplona.amethyst.service.relayClient.speedLogger
import android.util.Log
import com.vitorpamplona.amethyst.service.relayClient.speedLogger.RelaySpeedLogger.Companion.TAG import com.vitorpamplona.amethyst.service.relayClient.speedLogger.RelaySpeedLogger.Companion.TAG
import com.vitorpamplona.quartz.nip01Core.relay.normalizer.NormalizedRelayUrl 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 java.util.concurrent.atomic.AtomicInteger
import kotlin.concurrent.timer 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.NormalizedRelayUrl
import com.vitorpamplona.quartz.nip01Core.relay.normalizer.displayUrl 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 java.util.concurrent.atomic.AtomicInteger
import kotlin.concurrent.atomics.ExperimentalAtomicApi import kotlin.concurrent.atomics.ExperimentalAtomicApi
@@ -20,11 +20,11 @@
*/ */
package com.vitorpamplona.amethyst.service.relayClient.speedLogger package com.vitorpamplona.amethyst.service.relayClient.speedLogger
import android.util.Log
import com.vitorpamplona.quartz.nip01Core.core.Event import com.vitorpamplona.quartz.nip01Core.core.Event
import com.vitorpamplona.quartz.nip01Core.relay.client.INostrClient import com.vitorpamplona.quartz.nip01Core.relay.client.INostrClient
import com.vitorpamplona.quartz.nip01Core.relay.client.listeners.IRelayClientListener import com.vitorpamplona.quartz.nip01Core.relay.client.listeners.IRelayClientListener
import com.vitorpamplona.quartz.nip01Core.relay.client.single.IRelayClient import com.vitorpamplona.quartz.nip01Core.relay.client.single.IRelayClient
import com.vitorpamplona.quartz.utils.Log
/** /**
* Listens to NostrClient's onNotify messages from the relay * Listens to NostrClient's onNotify messages from the relay
@@ -21,10 +21,10 @@
package com.vitorpamplona.amethyst.service.tts package com.vitorpamplona.amethyst.service.tts
import android.content.Context import android.content.Context
import android.util.Log
import androidx.lifecycle.Lifecycle import androidx.lifecycle.Lifecycle
import androidx.lifecycle.LifecycleEventObserver import androidx.lifecycle.LifecycleEventObserver
import androidx.lifecycle.LifecycleOwner import androidx.lifecycle.LifecycleOwner
import com.vitorpamplona.quartz.utils.Log
import java.lang.ref.WeakReference import java.lang.ref.WeakReference
import java.util.Locale import java.util.Locale

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