diff --git a/ammolite/.gitignore b/ammolite/.gitignore
new file mode 100644
index 0000000000..42afabfd2a
--- /dev/null
+++ b/ammolite/.gitignore
@@ -0,0 +1 @@
+/build
\ No newline at end of file
diff --git a/ammolite/build.gradle b/ammolite/build.gradle
new file mode 100644
index 0000000000..8a14671f0f
--- /dev/null
+++ b/ammolite/build.gradle
@@ -0,0 +1,59 @@
+plugins {
+ alias(libs.plugins.androidLibrary)
+ alias(libs.plugins.jetbrainsKotlinAndroid)
+}
+
+android {
+ namespace 'com.vitorpamplona.ammolite'
+ compileSdk 34
+
+ defaultConfig {
+ minSdk 26
+ targetSdk 34
+
+ testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
+ consumerProguardFiles "consumer-rules.pro"
+ }
+
+ buildFeatures {
+ buildConfig = true
+ }
+
+ buildTypes {
+ release {
+ minifyEnabled true
+ proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
+ }
+ create("benchmark") {
+ initWith(getByName("release"))
+ signingConfig signingConfigs.debug
+ }
+ }
+ compileOptions {
+ sourceCompatibility JavaVersion.VERSION_17
+ targetCompatibility JavaVersion.VERSION_17
+ }
+ kotlinOptions {
+ jvmTarget = '17'
+ freeCompilerArgs += "-Xstring-concat=inline"
+ }
+ packagingOptions {
+ resources {
+ excludes += ['**/libscrypt.dylib']
+ }
+ }
+}
+
+dependencies {
+
+ implementation libs.androidx.core.ktx
+ implementation libs.androidx.appcompat
+ implementation libs.material
+ implementation project(path: ':quartz')
+ implementation libs.androidx.runtime.runtime
+ testImplementation libs.junit
+ androidTestImplementation libs.androidx.junit
+ androidTestImplementation libs.androidx.espresso.core
+
+ implementation libs.okhttp
+}
\ No newline at end of file
diff --git a/ammolite/consumer-rules.pro b/ammolite/consumer-rules.pro
new file mode 100644
index 0000000000..e69de29bb2
diff --git a/ammolite/proguard-rules.pro b/ammolite/proguard-rules.pro
new file mode 100644
index 0000000000..f2c80152a6
--- /dev/null
+++ b/ammolite/proguard-rules.pro
@@ -0,0 +1,24 @@
+# Add project specific ProGuard rules here.
+# You can control the set of applied configuration files using the
+# proguardFiles setting in build.gradle.
+#
+# For more details, see
+# http://developer.android.com/guide/developing/tools/proguard.html
+
+# If your project uses WebView with JS, uncomment the following
+# and specify the fully qualified class name to the JavaScript interface
+# class:
+#-keepclassmembers class fqcn.of.javascript.interface.for.webview {
+# public *;
+#}
+
+# Uncomment this to preserve the line number information for
+# debugging stack traces.
+#-keepattributes SourceFile,LineNumberTable
+
+# If you keep the line number information, uncomment this to
+# hide the original source file name.
+#-renamesourcefileattribute SourceFile
+
+-keep class com.vitorpamplona.ammolite.service.** { *; }
+-keep class com.vitorpamplona.ammolite.relays.** { *; }
\ No newline at end of file
diff --git a/ammolite/src/main/AndroidManifest.xml b/ammolite/src/main/AndroidManifest.xml
new file mode 100644
index 0000000000..a5918e68ab
--- /dev/null
+++ b/ammolite/src/main/AndroidManifest.xml
@@ -0,0 +1,4 @@
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/java/com/vitorpamplona/amethyst/ui/components/BundledUpdate.kt b/ammolite/src/main/java/com/vitorpamplona/ammolite/relays/BundledUpdate.kt
similarity index 97%
rename from app/src/main/java/com/vitorpamplona/amethyst/ui/components/BundledUpdate.kt
rename to ammolite/src/main/java/com/vitorpamplona/ammolite/relays/BundledUpdate.kt
index be77cf5f6a..0a26b050b1 100644
--- a/app/src/main/java/com/vitorpamplona/amethyst/ui/components/BundledUpdate.kt
+++ b/ammolite/src/main/java/com/vitorpamplona/ammolite/relays/BundledUpdate.kt
@@ -18,10 +18,10 @@
* 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.ui.components
+package com.vitorpamplona.ammolite.relays
import androidx.compose.runtime.Stable
-import com.vitorpamplona.amethyst.service.checkNotInMainThread
+import com.vitorpamplona.ammolite.service.checkNotInMainThread
import kotlinx.coroutines.CoroutineDispatcher
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
diff --git a/app/src/main/java/com/vitorpamplona/amethyst/service/relays/Client.kt b/ammolite/src/main/java/com/vitorpamplona/ammolite/relays/Client.kt
similarity index 87%
rename from app/src/main/java/com/vitorpamplona/amethyst/service/relays/Client.kt
rename to ammolite/src/main/java/com/vitorpamplona/ammolite/relays/Client.kt
index edfe68d008..12bc0a62f3 100644
--- a/app/src/main/java/com/vitorpamplona/amethyst/service/relays/Client.kt
+++ b/ammolite/src/main/java/com/vitorpamplona/ammolite/relays/Client.kt
@@ -18,11 +18,10 @@
* 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.service.relays
+package com.vitorpamplona.ammolite.relays
import android.util.Log
-import com.vitorpamplona.amethyst.model.RelaySetupInfo
-import com.vitorpamplona.amethyst.service.checkNotInMainThread
+import com.vitorpamplona.ammolite.service.checkNotInMainThread
import com.vitorpamplona.quartz.events.Event
import com.vitorpamplona.quartz.events.EventInterface
import kotlinx.coroutines.DelicateCoroutinesApi
@@ -50,7 +49,7 @@ object Client : RelayPool.Listener {
if (onlyIfChanged) {
if (!isSameRelaySetConfig(relays)) {
- if (this.relays.isNotEmpty()) {
+ if (Client.relays.isNotEmpty()) {
RelayPool.disconnect()
RelayPool.unregister(this)
RelayPool.unloadRelays()
@@ -61,11 +60,11 @@ object Client : RelayPool.Listener {
RelayPool.register(this)
RelayPool.loadRelays(newRelays)
RelayPool.requestAndWatch()
- this.relays = newRelays.toTypedArray()
+ Client.relays = newRelays.toTypedArray()
}
}
} else {
- if (this.relays.isNotEmpty()) {
+ if (Client.relays.isNotEmpty()) {
RelayPool.disconnect()
RelayPool.unregister(this)
RelayPool.unloadRelays()
@@ -76,7 +75,7 @@ object Client : RelayPool.Listener {
RelayPool.register(this)
RelayPool.loadRelays(newRelays)
RelayPool.requestAndWatch()
- this.relays = newRelays.toTypedArray()
+ Client.relays = newRelays.toTypedArray()
}
}
}
@@ -195,7 +194,6 @@ object Client : RelayPool.Listener {
}
}
- @OptIn(DelicateCoroutinesApi::class)
override fun onRelayStateChange(
type: Relay.StateType,
relay: Relay,
@@ -208,7 +206,6 @@ object Client : RelayPool.Listener {
// }
}
- @OptIn(DelicateCoroutinesApi::class)
override fun onSendResponse(
eventId: String,
success: Boolean,
@@ -222,7 +219,6 @@ object Client : RelayPool.Listener {
}
}
- @OptIn(DelicateCoroutinesApi::class)
override fun onAuth(
relay: Relay,
challenge: String,
@@ -243,6 +239,35 @@ object Client : RelayPool.Listener {
}
}
+ override fun onSend(
+ relay: Relay,
+ msg: String,
+ success: Boolean,
+ ) {
+ GlobalScope.launch(Dispatchers.Default) {
+ listeners.forEach { it.onSend(relay, msg, success) }
+ }
+ }
+
+ override fun onBeforeSend(
+ relay: Relay,
+ event: EventInterface,
+ ) {
+ GlobalScope.launch(Dispatchers.Default) {
+ listeners.forEach { it.onBeforeSend(relay, event) }
+ }
+ }
+
+ override fun onError(
+ error: Error,
+ subscriptionId: String,
+ relay: Relay,
+ ) {
+ GlobalScope.launch(Dispatchers.Default) {
+ listeners.forEach { it.onError(error, subscriptionId, relay) }
+ }
+ }
+
fun subscribe(listener: Listener) {
listeners = listeners.plus(listener)
}
@@ -290,5 +315,22 @@ object Client : RelayPool.Listener {
relay: Relay,
description: String,
) = Unit
+
+ open fun onSend(
+ relay: Relay,
+ msg: String,
+ success: Boolean,
+ ) = Unit
+
+ open fun onBeforeSend(
+ relay: Relay,
+ event: EventInterface,
+ ) = Unit
+
+ open fun onError(
+ error: Error,
+ subscriptionId: String,
+ relay: Relay,
+ ) = Unit
}
}
diff --git a/app/src/main/java/com/vitorpamplona/amethyst/service/relays/Constants.kt b/ammolite/src/main/java/com/vitorpamplona/ammolite/relays/Constants.kt
similarity index 97%
rename from app/src/main/java/com/vitorpamplona/amethyst/service/relays/Constants.kt
rename to ammolite/src/main/java/com/vitorpamplona/ammolite/relays/Constants.kt
index f0d8189b82..8c49189c13 100644
--- a/app/src/main/java/com/vitorpamplona/amethyst/service/relays/Constants.kt
+++ b/ammolite/src/main/java/com/vitorpamplona/ammolite/relays/Constants.kt
@@ -18,9 +18,8 @@
* 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.service.relays
+package com.vitorpamplona.ammolite.relays
-import com.vitorpamplona.amethyst.model.RelaySetupInfo
import com.vitorpamplona.quartz.encoders.RelayUrlFormatter
object Constants {
diff --git a/ammolite/src/main/java/com/vitorpamplona/ammolite/relays/EOSETime.kt b/ammolite/src/main/java/com/vitorpamplona/ammolite/relays/EOSETime.kt
new file mode 100644
index 0000000000..4d0ed60e4f
--- /dev/null
+++ b/ammolite/src/main/java/com/vitorpamplona/ammolite/relays/EOSETime.kt
@@ -0,0 +1,27 @@
+/**
+ * Copyright (c) 2024 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.ammolite.relays
+
+class EOSETime(var time: Long) {
+ override fun toString(): String {
+ return time.toString()
+ }
+}
diff --git a/app/src/main/java/com/vitorpamplona/amethyst/service/relays/JsonFilter.kt b/ammolite/src/main/java/com/vitorpamplona/ammolite/relays/JsonFilter.kt
similarity index 98%
rename from app/src/main/java/com/vitorpamplona/amethyst/service/relays/JsonFilter.kt
rename to ammolite/src/main/java/com/vitorpamplona/ammolite/relays/JsonFilter.kt
index eac7b0f8f2..8d36668bef 100644
--- a/app/src/main/java/com/vitorpamplona/amethyst/service/relays/JsonFilter.kt
+++ b/ammolite/src/main/java/com/vitorpamplona/ammolite/relays/JsonFilter.kt
@@ -18,7 +18,7 @@
* 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.service.relays
+package com.vitorpamplona.ammolite.relays
import com.vitorpamplona.quartz.events.Event
diff --git a/app/src/main/java/com/vitorpamplona/amethyst/service/NostrDataSource.kt b/ammolite/src/main/java/com/vitorpamplona/ammolite/relays/NostrDataSource.kt
similarity index 93%
rename from app/src/main/java/com/vitorpamplona/amethyst/service/NostrDataSource.kt
rename to ammolite/src/main/java/com/vitorpamplona/ammolite/relays/NostrDataSource.kt
index 4b6beb515e..666b550613 100644
--- a/app/src/main/java/com/vitorpamplona/amethyst/service/NostrDataSource.kt
+++ b/ammolite/src/main/java/com/vitorpamplona/ammolite/relays/NostrDataSource.kt
@@ -18,18 +18,14 @@
* 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.service
+package com.vitorpamplona.ammolite.relays
import android.util.Log
-import com.vitorpamplona.amethyst.model.LocalCache
-import com.vitorpamplona.amethyst.service.relays.Client
-import com.vitorpamplona.amethyst.service.relays.Relay
-import com.vitorpamplona.amethyst.service.relays.Subscription
-import com.vitorpamplona.amethyst.ui.components.BundledUpdate
-import com.vitorpamplona.quartz.events.AddressableEvent
+import com.vitorpamplona.ammolite.service.checkNotInMainThread
import com.vitorpamplona.quartz.events.Event
import com.vitorpamplona.quartz.utils.TimeUtils
import kotlinx.coroutines.CoroutineScope
+import kotlinx.coroutines.DelicateCoroutinesApi
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.GlobalScope
import kotlinx.coroutines.SupervisorJob
@@ -157,6 +153,7 @@ abstract class NostrDataSource(val debugName: String) {
resetFilters()
}
+ @OptIn(DelicateCoroutinesApi::class)
open fun stop() {
active = false
println("DataSource: ${this.javaClass.simpleName} Stop")
@@ -207,7 +204,7 @@ abstract class NostrDataSource(val debugName: String) {
scope.launch(Dispatchers.IO) { resetFiltersSuspend() }
}
- fun resetFiltersSuspend() {
+ private fun resetFiltersSuspend() {
println("DataSource: ${this.javaClass.simpleName} resetFiltersSuspend $active")
checkNotInMainThread()
@@ -278,22 +275,12 @@ abstract class NostrDataSource(val debugName: String) {
open fun consume(
event: Event,
relay: Relay,
- ) {
- LocalCache.verifyAndConsume(event, relay)
- }
+ ) = Unit
open fun markAsSeenOnRelay(
eventId: String,
relay: Relay,
- ) {
- val note = LocalCache.getNoteIfExists(eventId)
- val noteEvent = note?.event
- if (noteEvent is AddressableEvent) {
- LocalCache.getAddressableNoteIfExists(noteEvent.address().toTag())?.addRelay(relay)
- } else {
- note?.addRelay(relay)
- }
- }
+ ) = Unit
open fun markAsEOSE(
subscriptionId: String,
diff --git a/app/src/main/java/com/vitorpamplona/amethyst/service/relays/Relay.kt b/ammolite/src/main/java/com/vitorpamplona/ammolite/relays/Relay.kt
similarity index 94%
rename from app/src/main/java/com/vitorpamplona/amethyst/service/relays/Relay.kt
rename to ammolite/src/main/java/com/vitorpamplona/ammolite/relays/Relay.kt
index ab7108d842..9c7af4c023 100644
--- a/app/src/main/java/com/vitorpamplona/amethyst/service/relays/Relay.kt
+++ b/ammolite/src/main/java/com/vitorpamplona/ammolite/relays/Relay.kt
@@ -18,14 +18,12 @@
* 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.service.relays
+package com.vitorpamplona.ammolite.relays
import android.util.Log
-import com.vitorpamplona.amethyst.BuildConfig
-import com.vitorpamplona.amethyst.model.RelayBriefInfoCache
-import com.vitorpamplona.amethyst.model.RelaySetupInfo
-import com.vitorpamplona.amethyst.service.HttpClientManager
-import com.vitorpamplona.amethyst.service.checkNotInMainThread
+import com.vitorpamplona.ammolite.BuildConfig
+import com.vitorpamplona.ammolite.service.HttpClientManager
+import com.vitorpamplona.ammolite.service.checkNotInMainThread
import com.vitorpamplona.quartz.encoders.HexKey
import com.vitorpamplona.quartz.events.Event
import com.vitorpamplona.quartz.events.EventInterface
@@ -123,7 +121,7 @@ class Relay(
val request =
Request
.Builder()
- .header("User-Agent", "Amethyst/${BuildConfig.VERSION_NAME}")
+ .header("User-Agent", HttpClientManager.getDefaultUserAgentHeader())
.url(url.trim())
.build()
@@ -452,6 +450,10 @@ class Relay(
fun sendOverride(signedEvent: EventInterface) {
checkNotInMainThread()
+ listeners.forEach { listener ->
+ listener.onBeforeSend(this@Relay, signedEvent)
+ }
+
if (signedEvent is RelayAuthEvent) {
sendAuth(signedEvent)
} else {
@@ -462,6 +464,10 @@ class Relay(
fun send(signedEvent: EventInterface) {
checkNotInMainThread()
+ listeners.forEach { listener ->
+ listener.onBeforeSend(this@Relay, signedEvent)
+ }
+
if (signedEvent is RelayAuthEvent) {
sendAuth(signedEvent)
} else {
@@ -496,6 +502,10 @@ class Relay(
if (isConnected()) {
if (isReady) {
writeToSocket("""["EVENT",${signedEvent.toJson()}]""")
+ } else {
+ synchronized(sendWhenReady) {
+ sendWhenReady.add(signedEvent)
+ }
}
} else {
// sends all filters after connection is successful.
@@ -512,7 +522,10 @@ class Relay(
socket?.let {
checkNotInMainThread()
- it.send(str)
+ val result = it.send(str)
+ listeners.forEach { listener ->
+ listener.onSend(this@Relay, str, result)
+ }
RelayStats.addBytesSent(url, str.bytesUsedInMemory())
if (BuildConfig.DEBUG) {
@@ -588,5 +601,16 @@ class Relay(
relay: Relay,
description: String,
)
+
+ fun onSend(
+ relay: Relay,
+ msg: String,
+ success: Boolean,
+ )
+
+ fun onBeforeSend(
+ relay: Relay,
+ event: EventInterface,
+ )
}
}
diff --git a/ammolite/src/main/java/com/vitorpamplona/ammolite/relays/RelayBriefInfoCache.kt b/ammolite/src/main/java/com/vitorpamplona/ammolite/relays/RelayBriefInfoCache.kt
new file mode 100644
index 0000000000..51757c1a9a
--- /dev/null
+++ b/ammolite/src/main/java/com/vitorpamplona/ammolite/relays/RelayBriefInfoCache.kt
@@ -0,0 +1,46 @@
+/**
+ * Copyright (c) 2024 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.ammolite.relays
+
+import android.util.LruCache
+import androidx.compose.runtime.Immutable
+import com.vitorpamplona.quartz.encoders.RelayUrlFormatter
+
+object RelayBriefInfoCache {
+ val cache = LruCache(50)
+
+ @Immutable
+ class RelayBriefInfo(
+ val url: String,
+ ) {
+ val displayUrl: String = RelayUrlFormatter.displayUrl(url).intern()
+ val favIcon: String = "https://$displayUrl/favicon.ico".intern()
+ }
+
+ fun get(url: String): RelayBriefInfo {
+ val info = cache[url]
+ if (info != null) return info
+
+ val newInfo = RelayBriefInfo(url)
+ cache.put(url, newInfo)
+ return newInfo
+ }
+}
diff --git a/app/src/main/java/com/vitorpamplona/amethyst/service/relays/RelayPool.kt b/ammolite/src/main/java/com/vitorpamplona/ammolite/relays/RelayPool.kt
similarity index 90%
rename from app/src/main/java/com/vitorpamplona/amethyst/service/relays/RelayPool.kt
rename to ammolite/src/main/java/com/vitorpamplona/ammolite/relays/RelayPool.kt
index b7470feca5..0bc96ce90c 100644
--- a/app/src/main/java/com/vitorpamplona/amethyst/service/relays/RelayPool.kt
+++ b/ammolite/src/main/java/com/vitorpamplona/ammolite/relays/RelayPool.kt
@@ -18,11 +18,10 @@
* 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.service.relays
+package com.vitorpamplona.ammolite.relays
import androidx.compose.runtime.Immutable
-import com.vitorpamplona.amethyst.model.RelaySetupInfo
-import com.vitorpamplona.amethyst.service.checkNotInMainThread
+import com.vitorpamplona.ammolite.service.checkNotInMainThread
import com.vitorpamplona.quartz.events.Event
import com.vitorpamplona.quartz.events.EventInterface
import kotlinx.coroutines.DelicateCoroutinesApi
@@ -64,6 +63,8 @@ object RelayPool : Relay.Listener {
return relays.filter { it.url == url }
}
+ fun getAll() = relays
+
fun getOrCreateRelay(
url: String,
feedTypes: Set? = null,
@@ -221,6 +222,23 @@ object RelayPool : Relay.Listener {
relay: Relay,
description: String,
)
+
+ fun onSend(
+ relay: Relay,
+ msg: String,
+ success: Boolean,
+ )
+
+ fun onBeforeSend(
+ relay: Relay,
+ event: EventInterface,
+ )
+
+ fun onError(
+ error: Error,
+ subscriptionId: String,
+ relay: Relay,
+ )
}
override fun onEvent(
@@ -237,6 +255,7 @@ object RelayPool : Relay.Listener {
subscriptionId: String,
error: Error,
) {
+ listeners.forEach { it.onError(error, subscriptionId, relay) }
updateStatus()
}
@@ -274,6 +293,21 @@ object RelayPool : Relay.Listener {
listeners.forEach { it.onNotify(relay, description) }
}
+ override fun onSend(
+ relay: Relay,
+ msg: String,
+ success: Boolean,
+ ) {
+ listeners.forEach { it.onSend(relay, msg, success) }
+ }
+
+ override fun onBeforeSend(
+ relay: Relay,
+ event: EventInterface,
+ ) {
+ listeners.forEach { it.onBeforeSend(relay, event) }
+ }
+
private fun updateStatus() {
val connected = connectedRelays()
val available = availableRelays()
diff --git a/app/src/main/java/com/vitorpamplona/amethyst/model/RelaySetupInfo.kt b/ammolite/src/main/java/com/vitorpamplona/ammolite/relays/RelaySetupInfo.kt
similarity index 92%
rename from app/src/main/java/com/vitorpamplona/amethyst/model/RelaySetupInfo.kt
rename to ammolite/src/main/java/com/vitorpamplona/ammolite/relays/RelaySetupInfo.kt
index 6f9094c549..6c18edca80 100644
--- a/app/src/main/java/com/vitorpamplona/amethyst/model/RelaySetupInfo.kt
+++ b/ammolite/src/main/java/com/vitorpamplona/ammolite/relays/RelaySetupInfo.kt
@@ -18,10 +18,9 @@
* AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
-package com.vitorpamplona.amethyst.model
+package com.vitorpamplona.ammolite.relays
import androidx.compose.runtime.Immutable
-import com.vitorpamplona.amethyst.service.relays.FeedType
@Immutable
data class RelaySetupInfo(
diff --git a/app/src/main/java/com/vitorpamplona/amethyst/service/relays/RelayStats.kt b/ammolite/src/main/java/com/vitorpamplona/ammolite/relays/RelayStats.kt
similarity index 98%
rename from app/src/main/java/com/vitorpamplona/amethyst/service/relays/RelayStats.kt
rename to ammolite/src/main/java/com/vitorpamplona/ammolite/relays/RelayStats.kt
index 60a05958d0..2db9be54f8 100644
--- a/app/src/main/java/com/vitorpamplona/amethyst/service/relays/RelayStats.kt
+++ b/ammolite/src/main/java/com/vitorpamplona/ammolite/relays/RelayStats.kt
@@ -18,7 +18,7 @@
* 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.service.relays
+package com.vitorpamplona.ammolite.relays
import androidx.collection.LruCache
import com.vitorpamplona.quartz.utils.TimeUtils
diff --git a/app/src/main/java/com/vitorpamplona/amethyst/service/relays/Subscription.kt b/ammolite/src/main/java/com/vitorpamplona/ammolite/relays/Subscription.kt
similarity index 98%
rename from app/src/main/java/com/vitorpamplona/amethyst/service/relays/Subscription.kt
rename to ammolite/src/main/java/com/vitorpamplona/ammolite/relays/Subscription.kt
index ebd0ce3889..9f93b41044 100644
--- a/app/src/main/java/com/vitorpamplona/amethyst/service/relays/Subscription.kt
+++ b/ammolite/src/main/java/com/vitorpamplona/ammolite/relays/Subscription.kt
@@ -18,7 +18,7 @@
* 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.service.relays
+package com.vitorpamplona.ammolite.relays
import java.util.UUID
diff --git a/app/src/main/java/com/vitorpamplona/amethyst/service/relays/TypedFilter.kt b/ammolite/src/main/java/com/vitorpamplona/ammolite/relays/TypedFilter.kt
similarity index 95%
rename from app/src/main/java/com/vitorpamplona/amethyst/service/relays/TypedFilter.kt
rename to ammolite/src/main/java/com/vitorpamplona/ammolite/relays/TypedFilter.kt
index 4817e7b30a..84841a3e46 100644
--- a/app/src/main/java/com/vitorpamplona/amethyst/service/relays/TypedFilter.kt
+++ b/ammolite/src/main/java/com/vitorpamplona/ammolite/relays/TypedFilter.kt
@@ -18,7 +18,7 @@
* 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.service.relays
+package com.vitorpamplona.ammolite.relays
class TypedFilter(
val types: Set,
diff --git a/app/src/main/java/com/vitorpamplona/amethyst/service/HttpClientManager.kt b/ammolite/src/main/java/com/vitorpamplona/ammolite/service/HttpClientManager.kt
similarity index 88%
rename from app/src/main/java/com/vitorpamplona/amethyst/service/HttpClientManager.kt
rename to ammolite/src/main/java/com/vitorpamplona/ammolite/service/HttpClientManager.kt
index 0bf677167f..20b14bcae4 100644
--- a/app/src/main/java/com/vitorpamplona/amethyst/service/HttpClientManager.kt
+++ b/ammolite/src/main/java/com/vitorpamplona/ammolite/service/HttpClientManager.kt
@@ -18,10 +18,9 @@
* AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
-package com.vitorpamplona.amethyst.service
+package com.vitorpamplona.ammolite.service
import android.util.Log
-import com.vitorpamplona.amethyst.BuildConfig
import okhttp3.Interceptor
import okhttp3.OkHttpClient
import okhttp3.Request
@@ -40,6 +39,7 @@ object HttpClientManager {
private var defaultTimeout = DEFAULT_TIMEOUT_ON_WIFI
private var defaultHttpClient: OkHttpClient? = null
private var defaultHttpClientWithoutProxy: OkHttpClient? = null
+ private var userAgent: String = "Amethyst"
// fires off every time value of the property changes
private var internalProxy: Proxy? by
@@ -73,6 +73,14 @@ object HttpClientManager {
}
}
+ fun setDefaultUserAgent(userAgentHeader: String) {
+ Log.d("HttpClient", "Changing userAgent")
+ this.userAgent = userAgentHeader
+ this.defaultHttpClient = buildHttpClient(internalProxy, defaultTimeout)
+ }
+
+ fun getDefaultUserAgentHeader() = this.userAgent
+
private fun buildHttpClient(
proxy: Proxy?,
timeout: Duration,
@@ -84,20 +92,22 @@ object HttpClientManager {
.readTimeout(duration)
.connectTimeout(duration)
.writeTimeout(duration)
- .addInterceptor(DefaultContentTypeInterceptor())
+ .addInterceptor(DefaultContentTypeInterceptor(userAgent))
.followRedirects(true)
.followSslRedirects(true)
.build()
}
- class DefaultContentTypeInterceptor : Interceptor {
+ class DefaultContentTypeInterceptor(
+ private val userAgentHeader: String,
+ ) : Interceptor {
@Throws(IOException::class)
override fun intercept(chain: Interceptor.Chain): Response {
val originalRequest: Request = chain.request()
val requestWithUserAgent: Request =
originalRequest
.newBuilder()
- .header("User-Agent", "Amethyst/${BuildConfig.VERSION_NAME}")
+ .header("User-Agent", userAgentHeader)
.build()
return chain.proceed(requestWithUserAgent)
}
diff --git a/ammolite/src/main/java/com/vitorpamplona/ammolite/service/MainThreadChecker.kt b/ammolite/src/main/java/com/vitorpamplona/ammolite/service/MainThreadChecker.kt
new file mode 100644
index 0000000000..9b09960738
--- /dev/null
+++ b/ammolite/src/main/java/com/vitorpamplona/ammolite/service/MainThreadChecker.kt
@@ -0,0 +1,34 @@
+/**
+ * Copyright (c) 2024 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.ammolite.service
+
+import android.os.Looper
+import com.vitorpamplona.ammolite.BuildConfig
+
+fun checkNotInMainThread() {
+ if (BuildConfig.DEBUG && isMainThread()) {
+ throw OnMainThreadException("It should not be in the MainThread")
+ }
+}
+
+fun isMainThread() = Looper.myLooper() == Looper.getMainLooper()
+
+class OnMainThreadException(str: String) : RuntimeException(str)
diff --git a/ammolite/src/test/java/com/vitorpamplona/ammolite/HttpClientHelperTest.kt b/ammolite/src/test/java/com/vitorpamplona/ammolite/HttpClientHelperTest.kt
new file mode 100644
index 0000000000..e13e41ea3d
--- /dev/null
+++ b/ammolite/src/test/java/com/vitorpamplona/ammolite/HttpClientHelperTest.kt
@@ -0,0 +1,36 @@
+/**
+ * Copyright (c) 2024 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.ammolite
+
+import com.vitorpamplona.ammolite.service.HttpClientManager
+import junit.framework.TestCase.assertEquals
+import org.junit.Test
+import org.junit.runner.RunWith
+import org.junit.runners.JUnit4
+
+@RunWith(JUnit4::class)
+class HttpClientHelperTest {
+ @Test
+ fun test() {
+ val proxy = HttpClientManager.getDefaultProxy()
+ assertEquals(null, proxy)
+ }
+}
diff --git a/app/build.gradle b/app/build.gradle
index 8f9b63997a..b39f077c5b 100644
--- a/app/build.gradle
+++ b/app/build.gradle
@@ -165,6 +165,7 @@ dependencies {
implementation project(path: ':quartz')
implementation project(path: ':commons')
+ implementation project(path: ':ammolite')
implementation libs.androidx.core.ktx
implementation libs.androidx.activity.compose
diff --git a/app/proguard-rules.pro b/app/proguard-rules.pro
index 5b1f59d16f..fc7d6cf0f3 100644
--- a/app/proguard-rules.pro
+++ b/app/proguard-rules.pro
@@ -63,3 +63,5 @@
-keep class com.vitorpamplona.quartz.events.** { *; }
-keep class com.vitorpamplona.amethyst.model.** { *; }
-keep class com.vitorpamplona.amethyst.service.** { *; }
+-keep class com.vitorpamplona.ammolite.service.** { *; }
+-keep class com.vitorpamplona.ammolite.relays.** { *; }
diff --git a/app/src/main/java/com/vitorpamplona/amethyst/Amethyst.kt b/app/src/main/java/com/vitorpamplona/amethyst/Amethyst.kt
index f3dde4d652..1199f184b5 100644
--- a/app/src/main/java/com/vitorpamplona/amethyst/Amethyst.kt
+++ b/app/src/main/java/com/vitorpamplona/amethyst/Amethyst.kt
@@ -70,6 +70,7 @@ class Amethyst : Application() {
override fun onCreate() {
super.onCreate()
+
instance = this
OtsEvent.otsInstance = OpenTimestamps(OkHttpBlockstreamExplorer(), OkHttpCalendarBuilder())
diff --git a/app/src/main/java/com/vitorpamplona/amethyst/LocalPreferences.kt b/app/src/main/java/com/vitorpamplona/amethyst/LocalPreferences.kt
index f0d8e2e980..7a3c1ac786 100644
--- a/app/src/main/java/com/vitorpamplona/amethyst/LocalPreferences.kt
+++ b/app/src/main/java/com/vitorpamplona/amethyst/LocalPreferences.kt
@@ -31,11 +31,11 @@ import com.vitorpamplona.amethyst.model.DefaultReactions
import com.vitorpamplona.amethyst.model.DefaultZapAmounts
import com.vitorpamplona.amethyst.model.GLOBAL_FOLLOWS
import com.vitorpamplona.amethyst.model.KIND3_FOLLOWS
-import com.vitorpamplona.amethyst.model.RelaySetupInfo
import com.vitorpamplona.amethyst.model.Settings
-import com.vitorpamplona.amethyst.service.HttpClientManager
import com.vitorpamplona.amethyst.service.Nip96MediaServers
import com.vitorpamplona.amethyst.service.checkNotInMainThread
+import com.vitorpamplona.ammolite.relays.RelaySetupInfo
+import com.vitorpamplona.ammolite.service.HttpClientManager
import com.vitorpamplona.quartz.crypto.KeyPair
import com.vitorpamplona.quartz.encoders.HexKey
import com.vitorpamplona.quartz.encoders.Nip47WalletConnect
diff --git a/app/src/main/java/com/vitorpamplona/amethyst/ServiceManager.kt b/app/src/main/java/com/vitorpamplona/amethyst/ServiceManager.kt
index de9a28a1ea..aec03f645f 100644
--- a/app/src/main/java/com/vitorpamplona/amethyst/ServiceManager.kt
+++ b/app/src/main/java/com/vitorpamplona/amethyst/ServiceManager.kt
@@ -30,7 +30,6 @@ import coil.decode.SvgDecoder
import coil.size.Precision
import com.vitorpamplona.amethyst.model.Account
import com.vitorpamplona.amethyst.model.LocalCache
-import com.vitorpamplona.amethyst.service.HttpClientManager
import com.vitorpamplona.amethyst.service.NostrAccountDataSource
import com.vitorpamplona.amethyst.service.NostrChannelDataSource
import com.vitorpamplona.amethyst.service.NostrChatroomDataSource
@@ -47,7 +46,8 @@ import com.vitorpamplona.amethyst.service.NostrSingleUserDataSource
import com.vitorpamplona.amethyst.service.NostrThreadDataSource
import com.vitorpamplona.amethyst.service.NostrUserProfileDataSource
import com.vitorpamplona.amethyst.service.NostrVideoDataSource
-import com.vitorpamplona.amethyst.service.relays.Client
+import com.vitorpamplona.ammolite.relays.Client
+import com.vitorpamplona.ammolite.service.HttpClientManager
import com.vitorpamplona.quartz.encoders.bechToBytes
import com.vitorpamplona.quartz.encoders.decodePublicKeyAsHexOrNull
import com.vitorpamplona.quartz.encoders.toHexKey
@@ -86,6 +86,7 @@ class ServiceManager {
// Resets Proxy Use
HttpClientManager.setDefaultProxy(account?.proxy)
+ HttpClientManager.setDefaultUserAgent("Amethyst/${BuildConfig.VERSION_NAME}")
LocalCache.antiSpam.active = account?.filterSpamFromStrangers ?: true
Coil.setImageLoader {
Amethyst.instance
diff --git a/app/src/main/java/com/vitorpamplona/amethyst/model/Account.kt b/app/src/main/java/com/vitorpamplona/amethyst/model/Account.kt
index c9b1ecf34c..1e3ff69ffd 100644
--- a/app/src/main/java/com/vitorpamplona/amethyst/model/Account.kt
+++ b/app/src/main/java/com/vitorpamplona/amethyst/model/Account.kt
@@ -35,13 +35,14 @@ import com.vitorpamplona.amethyst.service.FileHeader
import com.vitorpamplona.amethyst.service.Nip96MediaServers
import com.vitorpamplona.amethyst.service.NostrLnZapPaymentResponseDataSource
import com.vitorpamplona.amethyst.service.checkNotInMainThread
-import com.vitorpamplona.amethyst.service.relays.Client
-import com.vitorpamplona.amethyst.service.relays.Constants
-import com.vitorpamplona.amethyst.service.relays.FeedType
-import com.vitorpamplona.amethyst.service.relays.JsonFilter
-import com.vitorpamplona.amethyst.service.relays.Relay
-import com.vitorpamplona.amethyst.service.relays.TypedFilter
-import com.vitorpamplona.amethyst.ui.components.BundledUpdate
+import com.vitorpamplona.ammolite.relays.BundledUpdate
+import com.vitorpamplona.ammolite.relays.Client
+import com.vitorpamplona.ammolite.relays.Constants
+import com.vitorpamplona.ammolite.relays.FeedType
+import com.vitorpamplona.ammolite.relays.JsonFilter
+import com.vitorpamplona.ammolite.relays.Relay
+import com.vitorpamplona.ammolite.relays.RelaySetupInfo
+import com.vitorpamplona.ammolite.relays.TypedFilter
import com.vitorpamplona.quartz.crypto.KeyPair
import com.vitorpamplona.quartz.encoders.ATag
import com.vitorpamplona.quartz.encoders.HexKey
@@ -266,7 +267,13 @@ class Account(
newDMRelaySet.forEach { newUrl ->
if (mappedRelaySet.none { it.url == newUrl }) {
- mappedRelaySet = mappedRelaySet + RelaySetupInfo(newUrl, true, true, setOf(FeedType.PRIVATE_DMS))
+ mappedRelaySet = mappedRelaySet +
+ RelaySetupInfo(
+ newUrl, true, true,
+ setOf(
+ FeedType.PRIVATE_DMS,
+ ),
+ )
}
}
@@ -285,7 +292,13 @@ class Account(
searchRelaySet.forEach { newUrl ->
if (mappedRelaySet.none { it.url == newUrl }) {
- mappedRelaySet = mappedRelaySet + RelaySetupInfo(newUrl, true, false, setOf(FeedType.SEARCH))
+ mappedRelaySet = mappedRelaySet +
+ RelaySetupInfo(
+ newUrl, true, false,
+ setOf(
+ FeedType.SEARCH,
+ ),
+ )
}
}
@@ -304,7 +317,13 @@ class Account(
privateOutboxRelaySet.forEach { newUrl ->
if (mappedRelaySet.none { it.url == newUrl }) {
- mappedRelaySet = mappedRelaySet + RelaySetupInfo(newUrl, true, true, setOf(FeedType.FOLLOWS, FeedType.PUBLIC_CHATS, FeedType.GLOBAL, FeedType.PRIVATE_DMS))
+ mappedRelaySet = mappedRelaySet +
+ RelaySetupInfo(
+ newUrl, true, true,
+ setOf(
+ FeedType.FOLLOWS, FeedType.PUBLIC_CHATS, FeedType.GLOBAL, FeedType.PRIVATE_DMS,
+ ),
+ )
}
}
@@ -323,7 +342,13 @@ class Account(
localRelayServers.forEach { newUrl ->
if (mappedRelaySet.none { it.url == newUrl }) {
- mappedRelaySet = mappedRelaySet + RelaySetupInfo(newUrl, true, true, setOf(FeedType.FOLLOWS, FeedType.PUBLIC_CHATS, FeedType.GLOBAL, FeedType.PRIVATE_DMS))
+ mappedRelaySet = mappedRelaySet +
+ RelaySetupInfo(
+ newUrl, true, true,
+ setOf(
+ FeedType.FOLLOWS, FeedType.PUBLIC_CHATS, FeedType.GLOBAL, FeedType.PRIVATE_DMS,
+ ),
+ )
}
}
@@ -337,7 +362,13 @@ class Account(
if (nip65setup != null) {
val write = nip65setup.type == AdvertisedRelayListEvent.AdvertisedRelayType.BOTH || nip65setup.type == AdvertisedRelayListEvent.AdvertisedRelayType.READ
- RelaySetupInfo(relay.url, true, relay.write || write, relay.feedTypes + setOf(FeedType.FOLLOWS, FeedType.GLOBAL, FeedType.PUBLIC_CHATS))
+ RelaySetupInfo(
+ relay.url, true, relay.write || write,
+ relay.feedTypes +
+ setOf(
+ FeedType.FOLLOWS, FeedType.GLOBAL, FeedType.PUBLIC_CHATS,
+ ),
+ )
} else {
relay
}
@@ -347,7 +378,13 @@ class Account(
if (mappedRelaySet.none { it.url == newNip65Setup.relayUrl }) {
val write = newNip65Setup.type == AdvertisedRelayListEvent.AdvertisedRelayType.BOTH || newNip65Setup.type == AdvertisedRelayListEvent.AdvertisedRelayType.READ
- mappedRelaySet = mappedRelaySet + RelaySetupInfo(newNip65Setup.relayUrl, true, write, setOf(FeedType.FOLLOWS, FeedType.PUBLIC_CHATS))
+ mappedRelaySet = mappedRelaySet +
+ RelaySetupInfo(
+ newNip65Setup.relayUrl, true, write,
+ setOf(
+ FeedType.FOLLOWS, FeedType.PUBLIC_CHATS,
+ ),
+ )
}
}
diff --git a/app/src/main/java/com/vitorpamplona/amethyst/model/AntiSpamFilter.kt b/app/src/main/java/com/vitorpamplona/amethyst/model/AntiSpamFilter.kt
index b5063e67c0..2f0911488e 100644
--- a/app/src/main/java/com/vitorpamplona/amethyst/model/AntiSpamFilter.kt
+++ b/app/src/main/java/com/vitorpamplona/amethyst/model/AntiSpamFilter.kt
@@ -25,9 +25,9 @@ import android.util.LruCache
import androidx.compose.runtime.Stable
import androidx.lifecycle.LiveData
import com.vitorpamplona.amethyst.service.checkNotInMainThread
-import com.vitorpamplona.amethyst.service.relays.Relay
-import com.vitorpamplona.amethyst.service.relays.RelayStats
-import com.vitorpamplona.amethyst.ui.components.BundledUpdate
+import com.vitorpamplona.ammolite.relays.BundledUpdate
+import com.vitorpamplona.ammolite.relays.Relay
+import com.vitorpamplona.ammolite.relays.RelayStats
import com.vitorpamplona.quartz.encoders.HexKey
import com.vitorpamplona.quartz.encoders.Nip19Bech32
import com.vitorpamplona.quartz.events.Event
diff --git a/app/src/main/java/com/vitorpamplona/amethyst/model/Channel.kt b/app/src/main/java/com/vitorpamplona/amethyst/model/Channel.kt
index 0c127556e2..2c12a5147a 100644
--- a/app/src/main/java/com/vitorpamplona/amethyst/model/Channel.kt
+++ b/app/src/main/java/com/vitorpamplona/amethyst/model/Channel.kt
@@ -25,9 +25,9 @@ import androidx.lifecycle.LiveData
import com.vitorpamplona.amethyst.commons.data.LargeCache
import com.vitorpamplona.amethyst.service.NostrSingleChannelDataSource
import com.vitorpamplona.amethyst.service.checkNotInMainThread
-import com.vitorpamplona.amethyst.ui.components.BundledUpdate
import com.vitorpamplona.amethyst.ui.dal.DefaultFeedOrder
import com.vitorpamplona.amethyst.ui.note.toShortenHex
+import com.vitorpamplona.ammolite.relays.BundledUpdate
import com.vitorpamplona.quartz.encoders.ATag
import com.vitorpamplona.quartz.encoders.Hex
import com.vitorpamplona.quartz.encoders.HexKey
diff --git a/app/src/main/java/com/vitorpamplona/amethyst/model/LocalCache.kt b/app/src/main/java/com/vitorpamplona/amethyst/model/LocalCache.kt
index 48c5f88d14..5e605af24f 100644
--- a/app/src/main/java/com/vitorpamplona/amethyst/model/LocalCache.kt
+++ b/app/src/main/java/com/vitorpamplona/amethyst/model/LocalCache.kt
@@ -29,8 +29,8 @@ import com.vitorpamplona.amethyst.commons.data.LargeCache
import com.vitorpamplona.amethyst.model.observables.LatestByKindAndAuthor
import com.vitorpamplona.amethyst.model.observables.LatestByKindWithETag
import com.vitorpamplona.amethyst.service.checkNotInMainThread
-import com.vitorpamplona.amethyst.service.relays.Relay
-import com.vitorpamplona.amethyst.ui.components.BundledInsert
+import com.vitorpamplona.ammolite.relays.BundledInsert
+import com.vitorpamplona.ammolite.relays.Relay
import com.vitorpamplona.quartz.encoders.ATag
import com.vitorpamplona.quartz.encoders.HexKey
import com.vitorpamplona.quartz.encoders.HexValidator
diff --git a/app/src/main/java/com/vitorpamplona/amethyst/model/Note.kt b/app/src/main/java/com/vitorpamplona/amethyst/model/Note.kt
index fc05e4e2d1..055476c112 100644
--- a/app/src/main/java/com/vitorpamplona/amethyst/model/Note.kt
+++ b/app/src/main/java/com/vitorpamplona/amethyst/model/Note.kt
@@ -20,7 +20,6 @@
*/
package com.vitorpamplona.amethyst.model
-import android.util.LruCache
import androidx.compose.runtime.Immutable
import androidx.compose.runtime.Stable
import androidx.lifecycle.LiveData
@@ -29,18 +28,18 @@ import androidx.lifecycle.distinctUntilChanged
import com.vitorpamplona.amethyst.service.NostrSingleEventDataSource
import com.vitorpamplona.amethyst.service.checkNotInMainThread
import com.vitorpamplona.amethyst.service.firstFullCharOrEmoji
-import com.vitorpamplona.amethyst.service.relays.EOSETime
-import com.vitorpamplona.amethyst.service.relays.Relay
import com.vitorpamplona.amethyst.ui.actions.relays.updated
-import com.vitorpamplona.amethyst.ui.components.BundledUpdate
import com.vitorpamplona.amethyst.ui.note.combineWith
import com.vitorpamplona.amethyst.ui.note.toShortenHex
+import com.vitorpamplona.ammolite.relays.BundledUpdate
+import com.vitorpamplona.ammolite.relays.EOSETime
+import com.vitorpamplona.ammolite.relays.Relay
+import com.vitorpamplona.ammolite.relays.RelayBriefInfoCache
import com.vitorpamplona.quartz.encoders.ATag
import com.vitorpamplona.quartz.encoders.Hex
import com.vitorpamplona.quartz.encoders.HexKey
import com.vitorpamplona.quartz.encoders.LnInvoiceUtil
import com.vitorpamplona.quartz.encoders.Nip19Bech32
-import com.vitorpamplona.quartz.encoders.RelayUrlFormatter
import com.vitorpamplona.quartz.encoders.toNote
import com.vitorpamplona.quartz.events.AddressableEvent
import com.vitorpamplona.quartz.events.BaseTextNoteEvent
@@ -1010,24 +1009,3 @@ class NoteLoadingLiveData(
@Immutable class NoteState(
val note: Note,
)
-
-object RelayBriefInfoCache {
- val cache = LruCache(50)
-
- @Immutable
- class RelayBriefInfo(
- val url: String,
- ) {
- val displayUrl: String = RelayUrlFormatter.displayUrl(url).intern()
- val favIcon: String = "https://$displayUrl/favicon.ico".intern()
- }
-
- fun get(url: String): RelayBriefInfo {
- val info = cache[url]
- if (info != null) return info
-
- val newInfo = RelayBriefInfo(url)
- cache.put(url, newInfo)
- return newInfo
- }
-}
diff --git a/app/src/main/java/com/vitorpamplona/amethyst/model/User.kt b/app/src/main/java/com/vitorpamplona/amethyst/model/User.kt
index 0d78e8c3e0..01abf0ad70 100644
--- a/app/src/main/java/com/vitorpamplona/amethyst/model/User.kt
+++ b/app/src/main/java/com/vitorpamplona/amethyst/model/User.kt
@@ -27,10 +27,10 @@ import androidx.lifecycle.MediatorLiveData
import androidx.lifecycle.distinctUntilChanged
import com.vitorpamplona.amethyst.service.NostrSingleUserDataSource
import com.vitorpamplona.amethyst.service.checkNotInMainThread
-import com.vitorpamplona.amethyst.service.relays.EOSETime
-import com.vitorpamplona.amethyst.service.relays.Relay
-import com.vitorpamplona.amethyst.ui.components.BundledUpdate
import com.vitorpamplona.amethyst.ui.note.toShortenHex
+import com.vitorpamplona.ammolite.relays.BundledUpdate
+import com.vitorpamplona.ammolite.relays.EOSETime
+import com.vitorpamplona.ammolite.relays.Relay
import com.vitorpamplona.quartz.encoders.Hex
import com.vitorpamplona.quartz.encoders.HexKey
import com.vitorpamplona.quartz.encoders.Lud06
diff --git a/app/src/main/java/com/vitorpamplona/amethyst/service/AmethystNostrDataSource.kt b/app/src/main/java/com/vitorpamplona/amethyst/service/AmethystNostrDataSource.kt
new file mode 100644
index 0000000000..244d60a1fd
--- /dev/null
+++ b/app/src/main/java/com/vitorpamplona/amethyst/service/AmethystNostrDataSource.kt
@@ -0,0 +1,49 @@
+/**
+ * Copyright (c) 2024 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.service
+
+import com.vitorpamplona.amethyst.model.LocalCache
+import com.vitorpamplona.ammolite.relays.NostrDataSource
+import com.vitorpamplona.ammolite.relays.Relay
+import com.vitorpamplona.quartz.events.AddressableEvent
+import com.vitorpamplona.quartz.events.Event
+
+abstract class AmethystNostrDataSource(debugName: String) : NostrDataSource(debugName) {
+ override fun consume(
+ event: Event,
+ relay: Relay,
+ ) {
+ LocalCache.verifyAndConsume(event, relay)
+ }
+
+ override fun markAsSeenOnRelay(
+ eventId: String,
+ relay: Relay,
+ ) {
+ val note = LocalCache.getNoteIfExists(eventId)
+ val noteEvent = note?.event
+ if (noteEvent is AddressableEvent) {
+ LocalCache.getAddressableNoteIfExists(noteEvent.address().toTag())?.addRelay(relay)
+ } else {
+ note?.addRelay(relay)
+ }
+ }
+}
diff --git a/app/src/main/java/com/vitorpamplona/amethyst/service/CashuProcessor.kt b/app/src/main/java/com/vitorpamplona/amethyst/service/CashuProcessor.kt
index 50203703b1..9d603e50f0 100644
--- a/app/src/main/java/com/vitorpamplona/amethyst/service/CashuProcessor.kt
+++ b/app/src/main/java/com/vitorpamplona/amethyst/service/CashuProcessor.kt
@@ -29,6 +29,7 @@ import com.vitorpamplona.amethyst.R
import com.vitorpamplona.amethyst.service.lnurl.LightningAddressResolver
import com.vitorpamplona.amethyst.ui.components.GenericLoadable
import com.vitorpamplona.amethyst.ui.stringRes
+import com.vitorpamplona.ammolite.service.HttpClientManager
import com.vitorpamplona.quartz.events.Event
import okhttp3.MediaType.Companion.toMediaType
import okhttp3.Request
diff --git a/app/src/main/java/com/vitorpamplona/amethyst/service/Nip05NostrAddressVerifier.kt b/app/src/main/java/com/vitorpamplona/amethyst/service/Nip05NostrAddressVerifier.kt
index 1846124976..1771e29eca 100644
--- a/app/src/main/java/com/vitorpamplona/amethyst/service/Nip05NostrAddressVerifier.kt
+++ b/app/src/main/java/com/vitorpamplona/amethyst/service/Nip05NostrAddressVerifier.kt
@@ -22,6 +22,7 @@ package com.vitorpamplona.amethyst.service
import com.fasterxml.jackson.module.kotlin.jacksonObjectMapper
import com.vitorpamplona.amethyst.BuildConfig
+import com.vitorpamplona.ammolite.service.HttpClientManager
import kotlinx.coroutines.CancellationException
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.withContext
diff --git a/app/src/main/java/com/vitorpamplona/amethyst/service/Nip11RelayInfoRetriever.kt b/app/src/main/java/com/vitorpamplona/amethyst/service/Nip11RelayInfoRetriever.kt
index f5cbf8e68e..b0f4134a1e 100644
--- a/app/src/main/java/com/vitorpamplona/amethyst/service/Nip11RelayInfoRetriever.kt
+++ b/app/src/main/java/com/vitorpamplona/amethyst/service/Nip11RelayInfoRetriever.kt
@@ -22,6 +22,7 @@ package com.vitorpamplona.amethyst.service
import android.util.Log
import android.util.LruCache
+import com.vitorpamplona.ammolite.service.HttpClientManager
import com.vitorpamplona.quartz.encoders.Nip11RelayInformation
import com.vitorpamplona.quartz.encoders.RelayUrlFormatter
import com.vitorpamplona.quartz.utils.TimeUtils
diff --git a/app/src/main/java/com/vitorpamplona/amethyst/service/Nip96MediaServers.kt b/app/src/main/java/com/vitorpamplona/amethyst/service/Nip96MediaServers.kt
index 8b4771a9a9..07f7244eba 100644
--- a/app/src/main/java/com/vitorpamplona/amethyst/service/Nip96MediaServers.kt
+++ b/app/src/main/java/com/vitorpamplona/amethyst/service/Nip96MediaServers.kt
@@ -24,6 +24,7 @@ import android.util.Log
import com.fasterxml.jackson.annotation.JsonProperty
import com.fasterxml.jackson.databind.DeserializationFeature
import com.fasterxml.jackson.module.kotlin.jacksonObjectMapper
+import com.vitorpamplona.ammolite.service.HttpClientManager
import kotlinx.coroutines.CancellationException
import okhttp3.Request
diff --git a/app/src/main/java/com/vitorpamplona/amethyst/service/Nip96Uploader.kt b/app/src/main/java/com/vitorpamplona/amethyst/service/Nip96Uploader.kt
index 923538ed55..7d069d0f18 100644
--- a/app/src/main/java/com/vitorpamplona/amethyst/service/Nip96Uploader.kt
+++ b/app/src/main/java/com/vitorpamplona/amethyst/service/Nip96Uploader.kt
@@ -30,6 +30,7 @@ import com.fasterxml.jackson.databind.DeserializationFeature
import com.fasterxml.jackson.module.kotlin.jacksonObjectMapper
import com.vitorpamplona.amethyst.BuildConfig
import com.vitorpamplona.amethyst.model.Account
+import com.vitorpamplona.ammolite.service.HttpClientManager
import kotlinx.coroutines.delay
import kotlinx.coroutines.suspendCancellableCoroutine
import kotlinx.coroutines.withTimeoutOrNull
diff --git a/app/src/main/java/com/vitorpamplona/amethyst/service/NostrAccountDataSource.kt b/app/src/main/java/com/vitorpamplona/amethyst/service/NostrAccountDataSource.kt
index 298bcb6b3e..d844308a69 100644
--- a/app/src/main/java/com/vitorpamplona/amethyst/service/NostrAccountDataSource.kt
+++ b/app/src/main/java/com/vitorpamplona/amethyst/service/NostrAccountDataSource.kt
@@ -23,14 +23,14 @@ package com.vitorpamplona.amethyst.service
import com.vitorpamplona.amethyst.model.Account
import com.vitorpamplona.amethyst.model.LocalCache
import com.vitorpamplona.amethyst.model.User
-import com.vitorpamplona.amethyst.service.relays.COMMON_FEED_TYPES
-import com.vitorpamplona.amethyst.service.relays.Client
import com.vitorpamplona.amethyst.service.relays.EOSEAccount
-import com.vitorpamplona.amethyst.service.relays.EOSETime
-import com.vitorpamplona.amethyst.service.relays.EVENT_FINDER_TYPES
-import com.vitorpamplona.amethyst.service.relays.JsonFilter
-import com.vitorpamplona.amethyst.service.relays.Relay
-import com.vitorpamplona.amethyst.service.relays.TypedFilter
+import com.vitorpamplona.ammolite.relays.COMMON_FEED_TYPES
+import com.vitorpamplona.ammolite.relays.Client
+import com.vitorpamplona.ammolite.relays.EOSETime
+import com.vitorpamplona.ammolite.relays.EVENT_FINDER_TYPES
+import com.vitorpamplona.ammolite.relays.JsonFilter
+import com.vitorpamplona.ammolite.relays.Relay
+import com.vitorpamplona.ammolite.relays.TypedFilter
import com.vitorpamplona.quartz.encoders.HexKey
import com.vitorpamplona.quartz.events.AdvertisedRelayListEvent
import com.vitorpamplona.quartz.events.BadgeAwardEvent
@@ -70,7 +70,7 @@ import com.vitorpamplona.quartz.events.TextNoteEvent
import com.vitorpamplona.quartz.utils.TimeUtils
// TODO: Migrate this to a property of AccountVi
-object NostrAccountDataSource : NostrDataSource("AccountData") {
+object NostrAccountDataSource : AmethystNostrDataSource("AccountData") {
lateinit var account: Account
var otherAccounts = listOf()
diff --git a/app/src/main/java/com/vitorpamplona/amethyst/service/NostrChannelDataSource.kt b/app/src/main/java/com/vitorpamplona/amethyst/service/NostrChannelDataSource.kt
index 8b820d2849..dee51163a2 100644
--- a/app/src/main/java/com/vitorpamplona/amethyst/service/NostrChannelDataSource.kt
+++ b/app/src/main/java/com/vitorpamplona/amethyst/service/NostrChannelDataSource.kt
@@ -24,13 +24,13 @@ import com.vitorpamplona.amethyst.model.Account
import com.vitorpamplona.amethyst.model.Channel
import com.vitorpamplona.amethyst.model.LiveActivitiesChannel
import com.vitorpamplona.amethyst.model.PublicChatChannel
-import com.vitorpamplona.amethyst.service.relays.FeedType
-import com.vitorpamplona.amethyst.service.relays.JsonFilter
-import com.vitorpamplona.amethyst.service.relays.TypedFilter
+import com.vitorpamplona.ammolite.relays.FeedType
+import com.vitorpamplona.ammolite.relays.JsonFilter
+import com.vitorpamplona.ammolite.relays.TypedFilter
import com.vitorpamplona.quartz.events.ChannelMessageEvent
import com.vitorpamplona.quartz.events.LiveActivitiesChatMessageEvent
-object NostrChannelDataSource : NostrDataSource("ChatroomFeed") {
+object NostrChannelDataSource : AmethystNostrDataSource("ChatroomFeed") {
var account: Account? = null
var channel: Channel? = null
diff --git a/app/src/main/java/com/vitorpamplona/amethyst/service/NostrChatroomDataSource.kt b/app/src/main/java/com/vitorpamplona/amethyst/service/NostrChatroomDataSource.kt
index ecb0efe56a..86858a07b2 100644
--- a/app/src/main/java/com/vitorpamplona/amethyst/service/NostrChatroomDataSource.kt
+++ b/app/src/main/java/com/vitorpamplona/amethyst/service/NostrChatroomDataSource.kt
@@ -22,13 +22,13 @@ package com.vitorpamplona.amethyst.service
import com.vitorpamplona.amethyst.model.Account
import com.vitorpamplona.amethyst.service.relays.EOSEAccount
-import com.vitorpamplona.amethyst.service.relays.FeedType
-import com.vitorpamplona.amethyst.service.relays.JsonFilter
-import com.vitorpamplona.amethyst.service.relays.TypedFilter
+import com.vitorpamplona.ammolite.relays.FeedType
+import com.vitorpamplona.ammolite.relays.JsonFilter
+import com.vitorpamplona.ammolite.relays.TypedFilter
import com.vitorpamplona.quartz.events.ChatroomKey
import com.vitorpamplona.quartz.events.PrivateDmEvent
-object NostrChatroomDataSource : NostrDataSource("ChatroomFeed") {
+object NostrChatroomDataSource : AmethystNostrDataSource("ChatroomFeed") {
lateinit var account: Account
private var withRoom: ChatroomKey? = null
diff --git a/app/src/main/java/com/vitorpamplona/amethyst/service/NostrChatroomListDataSource.kt b/app/src/main/java/com/vitorpamplona/amethyst/service/NostrChatroomListDataSource.kt
index e650a9f451..35631e73f1 100644
--- a/app/src/main/java/com/vitorpamplona/amethyst/service/NostrChatroomListDataSource.kt
+++ b/app/src/main/java/com/vitorpamplona/amethyst/service/NostrChatroomListDataSource.kt
@@ -22,16 +22,16 @@ package com.vitorpamplona.amethyst.service
import com.vitorpamplona.amethyst.model.Account
import com.vitorpamplona.amethyst.service.relays.EOSEAccount
-import com.vitorpamplona.amethyst.service.relays.EVENT_FINDER_TYPES
-import com.vitorpamplona.amethyst.service.relays.FeedType
-import com.vitorpamplona.amethyst.service.relays.JsonFilter
-import com.vitorpamplona.amethyst.service.relays.TypedFilter
+import com.vitorpamplona.ammolite.relays.EVENT_FINDER_TYPES
+import com.vitorpamplona.ammolite.relays.FeedType
+import com.vitorpamplona.ammolite.relays.JsonFilter
+import com.vitorpamplona.ammolite.relays.TypedFilter
import com.vitorpamplona.quartz.events.ChannelCreateEvent
import com.vitorpamplona.quartz.events.ChannelMessageEvent
import com.vitorpamplona.quartz.events.ChannelMetadataEvent
import com.vitorpamplona.quartz.events.PrivateDmEvent
-object NostrChatroomListDataSource : NostrDataSource("MailBoxFeed") {
+object NostrChatroomListDataSource : AmethystNostrDataSource("MailBoxFeed") {
lateinit var account: Account
val latestEOSEs = EOSEAccount()
diff --git a/app/src/main/java/com/vitorpamplona/amethyst/service/NostrCommunityDataSource.kt b/app/src/main/java/com/vitorpamplona/amethyst/service/NostrCommunityDataSource.kt
index a4e0aacec8..f96db23716 100644
--- a/app/src/main/java/com/vitorpamplona/amethyst/service/NostrCommunityDataSource.kt
+++ b/app/src/main/java/com/vitorpamplona/amethyst/service/NostrCommunityDataSource.kt
@@ -21,13 +21,13 @@
package com.vitorpamplona.amethyst.service
import com.vitorpamplona.amethyst.model.AddressableNote
-import com.vitorpamplona.amethyst.service.relays.COMMON_FEED_TYPES
-import com.vitorpamplona.amethyst.service.relays.JsonFilter
-import com.vitorpamplona.amethyst.service.relays.TypedFilter
+import com.vitorpamplona.ammolite.relays.COMMON_FEED_TYPES
+import com.vitorpamplona.ammolite.relays.JsonFilter
+import com.vitorpamplona.ammolite.relays.TypedFilter
import com.vitorpamplona.quartz.events.CommunityDefinitionEvent
import com.vitorpamplona.quartz.events.CommunityPostApprovalEvent
-object NostrCommunityDataSource : NostrDataSource("SingleCommunityFeed") {
+object NostrCommunityDataSource : AmethystNostrDataSource("SingleCommunityFeed") {
private var communityToWatch: AddressableNote? = null
private fun createLoadCommunityFilter(): TypedFilter? {
diff --git a/app/src/main/java/com/vitorpamplona/amethyst/service/NostrDiscoveryDataSource.kt b/app/src/main/java/com/vitorpamplona/amethyst/service/NostrDiscoveryDataSource.kt
index 160daee76f..62401ba1fd 100644
--- a/app/src/main/java/com/vitorpamplona/amethyst/service/NostrDiscoveryDataSource.kt
+++ b/app/src/main/java/com/vitorpamplona/amethyst/service/NostrDiscoveryDataSource.kt
@@ -23,9 +23,9 @@ package com.vitorpamplona.amethyst.service
import com.vitorpamplona.amethyst.Amethyst
import com.vitorpamplona.amethyst.model.Account
import com.vitorpamplona.amethyst.service.relays.EOSEAccount
-import com.vitorpamplona.amethyst.service.relays.FeedType
-import com.vitorpamplona.amethyst.service.relays.JsonFilter
-import com.vitorpamplona.amethyst.service.relays.TypedFilter
+import com.vitorpamplona.ammolite.relays.FeedType
+import com.vitorpamplona.ammolite.relays.JsonFilter
+import com.vitorpamplona.ammolite.relays.TypedFilter
import com.vitorpamplona.quartz.events.AppDefinitionEvent
import com.vitorpamplona.quartz.events.ChannelCreateEvent
import com.vitorpamplona.quartz.events.ChannelMessageEvent
@@ -39,7 +39,7 @@ import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.Job
import kotlinx.coroutines.launch
-object NostrDiscoveryDataSource : NostrDataSource("DiscoveryFeed") {
+object NostrDiscoveryDataSource : AmethystNostrDataSource("DiscoveryFeed") {
lateinit var account: Account
val scope = Amethyst.instance.applicationIOScope
diff --git a/app/src/main/java/com/vitorpamplona/amethyst/service/NostrGeohashDataSource.kt b/app/src/main/java/com/vitorpamplona/amethyst/service/NostrGeohashDataSource.kt
index 70e5052871..55ba2e6588 100644
--- a/app/src/main/java/com/vitorpamplona/amethyst/service/NostrGeohashDataSource.kt
+++ b/app/src/main/java/com/vitorpamplona/amethyst/service/NostrGeohashDataSource.kt
@@ -20,9 +20,9 @@
*/
package com.vitorpamplona.amethyst.service
-import com.vitorpamplona.amethyst.service.relays.COMMON_FEED_TYPES
-import com.vitorpamplona.amethyst.service.relays.JsonFilter
-import com.vitorpamplona.amethyst.service.relays.TypedFilter
+import com.vitorpamplona.ammolite.relays.COMMON_FEED_TYPES
+import com.vitorpamplona.ammolite.relays.JsonFilter
+import com.vitorpamplona.ammolite.relays.TypedFilter
import com.vitorpamplona.quartz.events.AudioHeaderEvent
import com.vitorpamplona.quartz.events.AudioTrackEvent
import com.vitorpamplona.quartz.events.ChannelMessageEvent
@@ -34,7 +34,7 @@ import com.vitorpamplona.quartz.events.PollNoteEvent
import com.vitorpamplona.quartz.events.TextNoteEvent
import com.vitorpamplona.quartz.events.WikiNoteEvent
-object NostrGeohashDataSource : NostrDataSource("SingleGeoHashFeed") {
+object NostrGeohashDataSource : AmethystNostrDataSource("SingleGeoHashFeed") {
private var geohashToWatch: String? = null
fun createLoadHashtagFilter(): TypedFilter? {
diff --git a/app/src/main/java/com/vitorpamplona/amethyst/service/NostrHashtagDataSource.kt b/app/src/main/java/com/vitorpamplona/amethyst/service/NostrHashtagDataSource.kt
index cea761f7ea..d13d6d695f 100644
--- a/app/src/main/java/com/vitorpamplona/amethyst/service/NostrHashtagDataSource.kt
+++ b/app/src/main/java/com/vitorpamplona/amethyst/service/NostrHashtagDataSource.kt
@@ -20,9 +20,9 @@
*/
package com.vitorpamplona.amethyst.service
-import com.vitorpamplona.amethyst.service.relays.COMMON_FEED_TYPES
-import com.vitorpamplona.amethyst.service.relays.JsonFilter
-import com.vitorpamplona.amethyst.service.relays.TypedFilter
+import com.vitorpamplona.ammolite.relays.COMMON_FEED_TYPES
+import com.vitorpamplona.ammolite.relays.JsonFilter
+import com.vitorpamplona.ammolite.relays.TypedFilter
import com.vitorpamplona.quartz.events.AudioHeaderEvent
import com.vitorpamplona.quartz.events.AudioTrackEvent
import com.vitorpamplona.quartz.events.ChannelMessageEvent
@@ -34,7 +34,7 @@ import com.vitorpamplona.quartz.events.PollNoteEvent
import com.vitorpamplona.quartz.events.TextNoteEvent
import com.vitorpamplona.quartz.events.WikiNoteEvent
-object NostrHashtagDataSource : NostrDataSource("SingleHashtagFeed") {
+object NostrHashtagDataSource : AmethystNostrDataSource("SingleHashtagFeed") {
private var hashtagToWatch: String? = null
fun createLoadHashtagFilter(): TypedFilter? {
diff --git a/app/src/main/java/com/vitorpamplona/amethyst/service/NostrHomeDataSource.kt b/app/src/main/java/com/vitorpamplona/amethyst/service/NostrHomeDataSource.kt
index be917641cb..2417d2f299 100644
--- a/app/src/main/java/com/vitorpamplona/amethyst/service/NostrHomeDataSource.kt
+++ b/app/src/main/java/com/vitorpamplona/amethyst/service/NostrHomeDataSource.kt
@@ -23,9 +23,9 @@ package com.vitorpamplona.amethyst.service
import com.vitorpamplona.amethyst.Amethyst
import com.vitorpamplona.amethyst.model.Account
import com.vitorpamplona.amethyst.service.relays.EOSEAccount
-import com.vitorpamplona.amethyst.service.relays.FeedType
-import com.vitorpamplona.amethyst.service.relays.JsonFilter
-import com.vitorpamplona.amethyst.service.relays.TypedFilter
+import com.vitorpamplona.ammolite.relays.FeedType
+import com.vitorpamplona.ammolite.relays.JsonFilter
+import com.vitorpamplona.ammolite.relays.TypedFilter
import com.vitorpamplona.quartz.events.AudioHeaderEvent
import com.vitorpamplona.quartz.events.AudioTrackEvent
import com.vitorpamplona.quartz.events.ClassifiedsEvent
@@ -45,7 +45,7 @@ import kotlinx.coroutines.Job
import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext
-object NostrHomeDataSource : NostrDataSource("HomeFeed") {
+object NostrHomeDataSource : AmethystNostrDataSource("HomeFeed") {
lateinit var account: Account
val scope = Amethyst.instance.applicationIOScope
diff --git a/app/src/main/java/com/vitorpamplona/amethyst/service/NostrLnZapPaymentResponseDataSource.kt b/app/src/main/java/com/vitorpamplona/amethyst/service/NostrLnZapPaymentResponseDataSource.kt
index 0cd136ccb2..cd5a927db4 100644
--- a/app/src/main/java/com/vitorpamplona/amethyst/service/NostrLnZapPaymentResponseDataSource.kt
+++ b/app/src/main/java/com/vitorpamplona/amethyst/service/NostrLnZapPaymentResponseDataSource.kt
@@ -20,11 +20,11 @@
*/
package com.vitorpamplona.amethyst.service
-import com.vitorpamplona.amethyst.service.relays.Client
-import com.vitorpamplona.amethyst.service.relays.FeedType
-import com.vitorpamplona.amethyst.service.relays.JsonFilter
-import com.vitorpamplona.amethyst.service.relays.Relay
-import com.vitorpamplona.amethyst.service.relays.TypedFilter
+import com.vitorpamplona.ammolite.relays.Client
+import com.vitorpamplona.ammolite.relays.FeedType
+import com.vitorpamplona.ammolite.relays.JsonFilter
+import com.vitorpamplona.ammolite.relays.Relay
+import com.vitorpamplona.ammolite.relays.TypedFilter
import com.vitorpamplona.quartz.events.LnZapPaymentResponseEvent
import com.vitorpamplona.quartz.events.RelayAuthEvent
import com.vitorpamplona.quartz.signers.NostrSigner
@@ -34,7 +34,7 @@ class NostrLnZapPaymentResponseDataSource(
private val toUserHex: String,
private val replyingToHex: String,
private val authSigner: NostrSigner,
-) : NostrDataSource("LnZapPaymentResponseFeed") {
+) : AmethystNostrDataSource("LnZapPaymentResponseFeed") {
val feedTypes = setOf(FeedType.WALLET_CONNECT)
private fun createWalletConnectServiceWatcher(): TypedFilter {
diff --git a/app/src/main/java/com/vitorpamplona/amethyst/service/NostrSearchEventOrUserDataSource.kt b/app/src/main/java/com/vitorpamplona/amethyst/service/NostrSearchEventOrUserDataSource.kt
index 429f2117c9..4327657285 100644
--- a/app/src/main/java/com/vitorpamplona/amethyst/service/NostrSearchEventOrUserDataSource.kt
+++ b/app/src/main/java/com/vitorpamplona/amethyst/service/NostrSearchEventOrUserDataSource.kt
@@ -20,10 +20,10 @@
*/
package com.vitorpamplona.amethyst.service
-import com.vitorpamplona.amethyst.service.relays.COMMON_FEED_TYPES
-import com.vitorpamplona.amethyst.service.relays.FeedType
-import com.vitorpamplona.amethyst.service.relays.JsonFilter
-import com.vitorpamplona.amethyst.service.relays.TypedFilter
+import com.vitorpamplona.ammolite.relays.COMMON_FEED_TYPES
+import com.vitorpamplona.ammolite.relays.FeedType
+import com.vitorpamplona.ammolite.relays.JsonFilter
+import com.vitorpamplona.ammolite.relays.TypedFilter
import com.vitorpamplona.quartz.crypto.KeyPair
import com.vitorpamplona.quartz.encoders.ATag
import com.vitorpamplona.quartz.encoders.Hex
@@ -52,7 +52,7 @@ import com.vitorpamplona.quartz.events.TextNoteEvent
import com.vitorpamplona.quartz.events.WikiNoteEvent
import kotlin.coroutines.cancellation.CancellationException
-object NostrSearchEventOrUserDataSource : NostrDataSource("SearchEventFeed") {
+object NostrSearchEventOrUserDataSource : AmethystNostrDataSource("SearchEventFeed") {
private var searchString: String? = null
private fun createAnythingWithIDFilter(): List? {
diff --git a/app/src/main/java/com/vitorpamplona/amethyst/service/NostrSingleChannelDataSource.kt b/app/src/main/java/com/vitorpamplona/amethyst/service/NostrSingleChannelDataSource.kt
index 73003b297b..129e8746ca 100644
--- a/app/src/main/java/com/vitorpamplona/amethyst/service/NostrSingleChannelDataSource.kt
+++ b/app/src/main/java/com/vitorpamplona/amethyst/service/NostrSingleChannelDataSource.kt
@@ -23,14 +23,14 @@ package com.vitorpamplona.amethyst.service
import com.vitorpamplona.amethyst.model.Channel
import com.vitorpamplona.amethyst.model.LiveActivitiesChannel
import com.vitorpamplona.amethyst.model.PublicChatChannel
-import com.vitorpamplona.amethyst.service.relays.EVENT_FINDER_TYPES
-import com.vitorpamplona.amethyst.service.relays.FeedType
-import com.vitorpamplona.amethyst.service.relays.JsonFilter
-import com.vitorpamplona.amethyst.service.relays.TypedFilter
+import com.vitorpamplona.ammolite.relays.EVENT_FINDER_TYPES
+import com.vitorpamplona.ammolite.relays.FeedType
+import com.vitorpamplona.ammolite.relays.JsonFilter
+import com.vitorpamplona.ammolite.relays.TypedFilter
import com.vitorpamplona.quartz.events.ChannelCreateEvent
import com.vitorpamplona.quartz.events.ChannelMetadataEvent
-object NostrSingleChannelDataSource : NostrDataSource("SingleChannelFeed") {
+object NostrSingleChannelDataSource : AmethystNostrDataSource("SingleChannelFeed") {
private var channelsToWatch = setOf()
private fun createMetadataChangeFilter(): TypedFilter? {
diff --git a/app/src/main/java/com/vitorpamplona/amethyst/service/NostrSingleEventDataSource.kt b/app/src/main/java/com/vitorpamplona/amethyst/service/NostrSingleEventDataSource.kt
index ae21fd1bcc..cde6acce88 100644
--- a/app/src/main/java/com/vitorpamplona/amethyst/service/NostrSingleEventDataSource.kt
+++ b/app/src/main/java/com/vitorpamplona/amethyst/service/NostrSingleEventDataSource.kt
@@ -23,10 +23,10 @@ package com.vitorpamplona.amethyst.service
import com.vitorpamplona.amethyst.model.AddressableNote
import com.vitorpamplona.amethyst.model.Note
import com.vitorpamplona.amethyst.model.User
-import com.vitorpamplona.amethyst.service.relays.EOSETime
-import com.vitorpamplona.amethyst.service.relays.EVENT_FINDER_TYPES
-import com.vitorpamplona.amethyst.service.relays.JsonFilter
-import com.vitorpamplona.amethyst.service.relays.TypedFilter
+import com.vitorpamplona.ammolite.relays.EOSETime
+import com.vitorpamplona.ammolite.relays.EVENT_FINDER_TYPES
+import com.vitorpamplona.ammolite.relays.JsonFilter
+import com.vitorpamplona.ammolite.relays.TypedFilter
import com.vitorpamplona.quartz.events.CommunityPostApprovalEvent
import com.vitorpamplona.quartz.events.DeletionEvent
import com.vitorpamplona.quartz.events.GenericRepostEvent
@@ -43,7 +43,7 @@ import com.vitorpamplona.quartz.events.RepostEvent
import com.vitorpamplona.quartz.events.TextNoteEvent
import com.vitorpamplona.quartz.events.TextNoteModificationEvent
-object NostrSingleEventDataSource : NostrDataSource("SingleEventFeed") {
+object NostrSingleEventDataSource : AmethystNostrDataSource("SingleEventFeed") {
private var eventsToWatch = setOf()
private var addressesToWatch = setOf()
diff --git a/app/src/main/java/com/vitorpamplona/amethyst/service/NostrSingleUserDataSource.kt b/app/src/main/java/com/vitorpamplona/amethyst/service/NostrSingleUserDataSource.kt
index e1a768992c..7cfb2604a2 100644
--- a/app/src/main/java/com/vitorpamplona/amethyst/service/NostrSingleUserDataSource.kt
+++ b/app/src/main/java/com/vitorpamplona/amethyst/service/NostrSingleUserDataSource.kt
@@ -21,16 +21,16 @@
package com.vitorpamplona.amethyst.service
import com.vitorpamplona.amethyst.model.User
-import com.vitorpamplona.amethyst.service.relays.EOSETime
-import com.vitorpamplona.amethyst.service.relays.EVENT_FINDER_TYPES
-import com.vitorpamplona.amethyst.service.relays.JsonFilter
-import com.vitorpamplona.amethyst.service.relays.TypedFilter
+import com.vitorpamplona.ammolite.relays.EOSETime
+import com.vitorpamplona.ammolite.relays.EVENT_FINDER_TYPES
+import com.vitorpamplona.ammolite.relays.JsonFilter
+import com.vitorpamplona.ammolite.relays.TypedFilter
import com.vitorpamplona.quartz.events.AdvertisedRelayListEvent
import com.vitorpamplona.quartz.events.MetadataEvent
import com.vitorpamplona.quartz.events.ReportEvent
import com.vitorpamplona.quartz.events.StatusEvent
-object NostrSingleUserDataSource : NostrDataSource("SingleUserFeed") {
+object NostrSingleUserDataSource : AmethystNostrDataSource("SingleUserFeed") {
private var usersToWatch = setOf()
fun createUserMetadataFilter(): List? {
diff --git a/app/src/main/java/com/vitorpamplona/amethyst/service/NostrThreadDataSource.kt b/app/src/main/java/com/vitorpamplona/amethyst/service/NostrThreadDataSource.kt
index 4d6d730a1f..3fae129a4e 100644
--- a/app/src/main/java/com/vitorpamplona/amethyst/service/NostrThreadDataSource.kt
+++ b/app/src/main/java/com/vitorpamplona/amethyst/service/NostrThreadDataSource.kt
@@ -21,11 +21,11 @@
package com.vitorpamplona.amethyst.service
import com.vitorpamplona.amethyst.model.ThreadAssembler
-import com.vitorpamplona.amethyst.service.relays.COMMON_FEED_TYPES
-import com.vitorpamplona.amethyst.service.relays.JsonFilter
-import com.vitorpamplona.amethyst.service.relays.TypedFilter
+import com.vitorpamplona.ammolite.relays.COMMON_FEED_TYPES
+import com.vitorpamplona.ammolite.relays.JsonFilter
+import com.vitorpamplona.ammolite.relays.TypedFilter
-object NostrThreadDataSource : NostrDataSource("SingleThreadFeed") {
+object NostrThreadDataSource : AmethystNostrDataSource("SingleThreadFeed") {
private var eventToWatch: String? = null
fun createLoadEventsIfNotLoadedFilter(): TypedFilter? {
diff --git a/app/src/main/java/com/vitorpamplona/amethyst/service/NostrUserProfileDataSource.kt b/app/src/main/java/com/vitorpamplona/amethyst/service/NostrUserProfileDataSource.kt
index 58ab69b5bb..19e16f2ecd 100644
--- a/app/src/main/java/com/vitorpamplona/amethyst/service/NostrUserProfileDataSource.kt
+++ b/app/src/main/java/com/vitorpamplona/amethyst/service/NostrUserProfileDataSource.kt
@@ -21,9 +21,9 @@
package com.vitorpamplona.amethyst.service
import com.vitorpamplona.amethyst.model.User
-import com.vitorpamplona.amethyst.service.relays.COMMON_FEED_TYPES
-import com.vitorpamplona.amethyst.service.relays.JsonFilter
-import com.vitorpamplona.amethyst.service.relays.TypedFilter
+import com.vitorpamplona.ammolite.relays.COMMON_FEED_TYPES
+import com.vitorpamplona.ammolite.relays.JsonFilter
+import com.vitorpamplona.ammolite.relays.TypedFilter
import com.vitorpamplona.quartz.events.AppRecommendationEvent
import com.vitorpamplona.quartz.events.AudioHeaderEvent
import com.vitorpamplona.quartz.events.AudioTrackEvent
@@ -43,7 +43,7 @@ import com.vitorpamplona.quartz.events.RepostEvent
import com.vitorpamplona.quartz.events.TextNoteEvent
import com.vitorpamplona.quartz.events.WikiNoteEvent
-object NostrUserProfileDataSource : NostrDataSource("UserProfileFeed") {
+object NostrUserProfileDataSource : AmethystNostrDataSource("UserProfileFeed") {
var user: User? = null
fun loadUserProfile(user: User?) {
diff --git a/app/src/main/java/com/vitorpamplona/amethyst/service/NostrVideoDataSource.kt b/app/src/main/java/com/vitorpamplona/amethyst/service/NostrVideoDataSource.kt
index 9cca2cfd2f..2dc2c18f22 100644
--- a/app/src/main/java/com/vitorpamplona/amethyst/service/NostrVideoDataSource.kt
+++ b/app/src/main/java/com/vitorpamplona/amethyst/service/NostrVideoDataSource.kt
@@ -23,9 +23,9 @@ package com.vitorpamplona.amethyst.service
import com.vitorpamplona.amethyst.Amethyst
import com.vitorpamplona.amethyst.model.Account
import com.vitorpamplona.amethyst.service.relays.EOSEAccount
-import com.vitorpamplona.amethyst.service.relays.FeedType
-import com.vitorpamplona.amethyst.service.relays.JsonFilter
-import com.vitorpamplona.amethyst.service.relays.TypedFilter
+import com.vitorpamplona.ammolite.relays.FeedType
+import com.vitorpamplona.ammolite.relays.JsonFilter
+import com.vitorpamplona.ammolite.relays.TypedFilter
import com.vitorpamplona.quartz.events.FileHeaderEvent
import com.vitorpamplona.quartz.events.FileStorageHeaderEvent
import com.vitorpamplona.quartz.events.VideoHorizontalEvent
@@ -37,7 +37,7 @@ import kotlinx.coroutines.launch
val SUPPORTED_VIDEO_FEED_MIME_TYPES = listOf("image/jpeg", "image/gif", "image/png", "image/webp", "video/mp4", "video/mpeg", "video/webm", "audio/aac", "audio/mpeg", "audio/webm", "audio/wav", "image/avif")
val SUPPORTED_VIDEO_FEED_MIME_TYPES_SET = SUPPORTED_VIDEO_FEED_MIME_TYPES.toSet()
-object NostrVideoDataSource : NostrDataSource("VideoFeed") {
+object NostrVideoDataSource : AmethystNostrDataSource("VideoFeed") {
lateinit var account: Account
val scope = Amethyst.instance.applicationIOScope
diff --git a/app/src/main/java/com/vitorpamplona/amethyst/service/OnlineCheck.kt b/app/src/main/java/com/vitorpamplona/amethyst/service/OnlineCheck.kt
index b2eff00bdf..72e11ab2e1 100644
--- a/app/src/main/java/com/vitorpamplona/amethyst/service/OnlineCheck.kt
+++ b/app/src/main/java/com/vitorpamplona/amethyst/service/OnlineCheck.kt
@@ -24,6 +24,7 @@ import android.util.Log
import android.util.LruCache
import androidx.compose.runtime.Immutable
import com.vitorpamplona.amethyst.BuildConfig
+import com.vitorpamplona.ammolite.service.HttpClientManager
import com.vitorpamplona.quartz.crypto.CryptoUtils
import okhttp3.EventListener
import okhttp3.Protocol
diff --git a/app/src/main/java/com/vitorpamplona/amethyst/service/lnurl/LightningAddressResolver.kt b/app/src/main/java/com/vitorpamplona/amethyst/service/lnurl/LightningAddressResolver.kt
index 85b19ebce8..4f142daf0d 100644
--- a/app/src/main/java/com/vitorpamplona/amethyst/service/lnurl/LightningAddressResolver.kt
+++ b/app/src/main/java/com/vitorpamplona/amethyst/service/lnurl/LightningAddressResolver.kt
@@ -24,9 +24,9 @@ import android.content.Context
import com.fasterxml.jackson.module.kotlin.jacksonObjectMapper
import com.vitorpamplona.amethyst.BuildConfig
import com.vitorpamplona.amethyst.R
-import com.vitorpamplona.amethyst.service.HttpClientManager
import com.vitorpamplona.amethyst.service.checkNotInMainThread
import com.vitorpamplona.amethyst.ui.stringRes
+import com.vitorpamplona.ammolite.service.HttpClientManager
import com.vitorpamplona.quartz.encoders.LnInvoiceUtil
import com.vitorpamplona.quartz.encoders.Lud06
import okhttp3.Request
diff --git a/app/src/main/java/com/vitorpamplona/amethyst/service/notifications/RegisterAccounts.kt b/app/src/main/java/com/vitorpamplona/amethyst/service/notifications/RegisterAccounts.kt
index 2049d817dc..6ce76450b2 100644
--- a/app/src/main/java/com/vitorpamplona/amethyst/service/notifications/RegisterAccounts.kt
+++ b/app/src/main/java/com/vitorpamplona/amethyst/service/notifications/RegisterAccounts.kt
@@ -25,7 +25,7 @@ import com.vitorpamplona.amethyst.AccountInfo
import com.vitorpamplona.amethyst.BuildConfig
import com.vitorpamplona.amethyst.LocalPreferences
import com.vitorpamplona.amethyst.model.Account
-import com.vitorpamplona.amethyst.service.HttpClientManager
+import com.vitorpamplona.ammolite.service.HttpClientManager
import com.vitorpamplona.quartz.events.RelayAuthEvent
import kotlinx.coroutines.CancellationException
import kotlinx.coroutines.Dispatchers
diff --git a/app/src/main/java/com/vitorpamplona/amethyst/service/ots/OkHttpBlockstreamExplorer.kt b/app/src/main/java/com/vitorpamplona/amethyst/service/ots/OkHttpBlockstreamExplorer.kt
index 9b074670a1..eeb0923956 100644
--- a/app/src/main/java/com/vitorpamplona/amethyst/service/ots/OkHttpBlockstreamExplorer.kt
+++ b/app/src/main/java/com/vitorpamplona/amethyst/service/ots/OkHttpBlockstreamExplorer.kt
@@ -23,7 +23,7 @@ package com.vitorpamplona.amethyst.service.ots
import android.util.Log
import com.fasterxml.jackson.module.kotlin.jacksonObjectMapper
import com.vitorpamplona.amethyst.BuildConfig
-import com.vitorpamplona.amethyst.service.HttpClientManager
+import com.vitorpamplona.ammolite.service.HttpClientManager
import com.vitorpamplona.quartz.ots.BitcoinExplorer
import com.vitorpamplona.quartz.ots.BlockHeader
import com.vitorpamplona.quartz.ots.exceptions.UrlException
diff --git a/app/src/main/java/com/vitorpamplona/amethyst/service/ots/OkHttpCalendar.kt b/app/src/main/java/com/vitorpamplona/amethyst/service/ots/OkHttpCalendar.kt
index 91db7a2b49..0e16a2320e 100644
--- a/app/src/main/java/com/vitorpamplona/amethyst/service/ots/OkHttpCalendar.kt
+++ b/app/src/main/java/com/vitorpamplona/amethyst/service/ots/OkHttpCalendar.kt
@@ -21,7 +21,7 @@
package com.vitorpamplona.amethyst.service.ots
import com.vitorpamplona.amethyst.BuildConfig
-import com.vitorpamplona.amethyst.service.HttpClientManager
+import com.vitorpamplona.ammolite.service.HttpClientManager
import com.vitorpamplona.quartz.encoders.Hex
import com.vitorpamplona.quartz.ots.ICalendar
import com.vitorpamplona.quartz.ots.StreamDeserializationContext
diff --git a/app/src/main/java/com/vitorpamplona/amethyst/service/ots/OkHttpCalendarAsyncSubmit.kt b/app/src/main/java/com/vitorpamplona/amethyst/service/ots/OkHttpCalendarAsyncSubmit.kt
index be082413fb..515f9150e5 100644
--- a/app/src/main/java/com/vitorpamplona/amethyst/service/ots/OkHttpCalendarAsyncSubmit.kt
+++ b/app/src/main/java/com/vitorpamplona/amethyst/service/ots/OkHttpCalendarAsyncSubmit.kt
@@ -21,7 +21,7 @@
package com.vitorpamplona.amethyst.service.ots
import com.vitorpamplona.amethyst.BuildConfig
-import com.vitorpamplona.amethyst.service.HttpClientManager
+import com.vitorpamplona.ammolite.service.HttpClientManager
import com.vitorpamplona.quartz.ots.ICalendarAsyncSubmit
import com.vitorpamplona.quartz.ots.StreamDeserializationContext
import com.vitorpamplona.quartz.ots.Timestamp
diff --git a/app/src/main/java/com/vitorpamplona/amethyst/service/playback/PlaybackService.kt b/app/src/main/java/com/vitorpamplona/amethyst/service/playback/PlaybackService.kt
index 82167f0ad8..449055818b 100644
--- a/app/src/main/java/com/vitorpamplona/amethyst/service/playback/PlaybackService.kt
+++ b/app/src/main/java/com/vitorpamplona/amethyst/service/playback/PlaybackService.kt
@@ -33,7 +33,7 @@ import androidx.media3.exoplayer.upstream.LoadErrorHandlingPolicy
import androidx.media3.session.MediaSession
import androidx.media3.session.MediaSessionService
import com.vitorpamplona.amethyst.Amethyst
-import com.vitorpamplona.amethyst.service.HttpClientManager
+import com.vitorpamplona.ammolite.service.HttpClientManager
/**
* HLS LiveStreams cannot use cache.
diff --git a/app/src/main/java/com/vitorpamplona/amethyst/service/previews/UrlPreviewUtils.kt b/app/src/main/java/com/vitorpamplona/amethyst/service/previews/UrlPreviewUtils.kt
index ea2425fc3e..79fb36e324 100644
--- a/app/src/main/java/com/vitorpamplona/amethyst/service/previews/UrlPreviewUtils.kt
+++ b/app/src/main/java/com/vitorpamplona/amethyst/service/previews/UrlPreviewUtils.kt
@@ -22,8 +22,8 @@ package com.vitorpamplona.amethyst.service.previews
import com.vitorpamplona.amethyst.commons.preview.MetaTag
import com.vitorpamplona.amethyst.commons.preview.MetaTagsParser
-import com.vitorpamplona.amethyst.service.HttpClientManager
import com.vitorpamplona.amethyst.service.checkNotInMainThread
+import com.vitorpamplona.ammolite.service.HttpClientManager
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.withContext
import okhttp3.MediaType
diff --git a/app/src/main/java/com/vitorpamplona/amethyst/service/relays/EOSE.kt b/app/src/main/java/com/vitorpamplona/amethyst/service/relays/EOSE.kt
index a99a838787..83f2e97292 100644
--- a/app/src/main/java/com/vitorpamplona/amethyst/service/relays/EOSE.kt
+++ b/app/src/main/java/com/vitorpamplona/amethyst/service/relays/EOSE.kt
@@ -21,12 +21,7 @@
package com.vitorpamplona.amethyst.service.relays
import com.vitorpamplona.amethyst.model.User
-
-class EOSETime(var time: Long) {
- override fun toString(): String {
- return time.toString()
- }
-}
+import com.vitorpamplona.ammolite.relays.EOSETime
class EOSERelayList(var relayList: Map = emptyMap()) {
fun addOrUpdate(
diff --git a/app/src/main/java/com/vitorpamplona/amethyst/ui/MainActivity.kt b/app/src/main/java/com/vitorpamplona/amethyst/ui/MainActivity.kt
index f59c2a2bd2..d26a4cea59 100644
--- a/app/src/main/java/com/vitorpamplona/amethyst/ui/MainActivity.kt
+++ b/app/src/main/java/com/vitorpamplona/amethyst/ui/MainActivity.kt
@@ -37,13 +37,13 @@ import androidx.compose.runtime.mutableStateOf
import com.vitorpamplona.amethyst.LocalPreferences
import com.vitorpamplona.amethyst.ServiceManager
import com.vitorpamplona.amethyst.model.LocalCache
-import com.vitorpamplona.amethyst.service.HttpClientManager
import com.vitorpamplona.amethyst.service.lang.LanguageTranslatorService
import com.vitorpamplona.amethyst.service.notifications.PushNotificationUtils
import com.vitorpamplona.amethyst.ui.components.DEFAULT_MUTED_SETTING
import com.vitorpamplona.amethyst.ui.components.keepPlayingMutex
import com.vitorpamplona.amethyst.ui.navigation.Route
import com.vitorpamplona.amethyst.ui.navigation.debugState
+import com.vitorpamplona.ammolite.service.HttpClientManager
import com.vitorpamplona.quartz.encoders.Nip19Bech32
import com.vitorpamplona.quartz.encoders.Nip47WalletConnect
import com.vitorpamplona.quartz.events.ChannelCreateEvent
diff --git a/app/src/main/java/com/vitorpamplona/amethyst/ui/actions/EditPostViewModel.kt b/app/src/main/java/com/vitorpamplona/amethyst/ui/actions/EditPostViewModel.kt
index abfc5d22fd..a951d4a7ad 100644
--- a/app/src/main/java/com/vitorpamplona/amethyst/ui/actions/EditPostViewModel.kt
+++ b/app/src/main/java/com/vitorpamplona/amethyst/ui/actions/EditPostViewModel.kt
@@ -36,13 +36,13 @@ import com.vitorpamplona.amethyst.commons.richtext.RichTextParser
import com.vitorpamplona.amethyst.model.Account
import com.vitorpamplona.amethyst.model.LocalCache
import com.vitorpamplona.amethyst.model.Note
-import com.vitorpamplona.amethyst.model.RelaySetupInfo
import com.vitorpamplona.amethyst.model.User
import com.vitorpamplona.amethyst.service.FileHeader
import com.vitorpamplona.amethyst.service.Nip96Uploader
import com.vitorpamplona.amethyst.service.NostrSearchEventOrUserDataSource
import com.vitorpamplona.amethyst.ui.components.MediaCompressor
import com.vitorpamplona.amethyst.ui.screen.loggedIn.AccountViewModel
+import com.vitorpamplona.ammolite.relays.RelaySetupInfo
import com.vitorpamplona.quartz.events.FileHeaderEvent
import com.vitorpamplona.quartz.events.FileStorageEvent
import com.vitorpamplona.quartz.events.FileStorageHeaderEvent
diff --git a/app/src/main/java/com/vitorpamplona/amethyst/ui/actions/ImageDownloader.kt b/app/src/main/java/com/vitorpamplona/amethyst/ui/actions/ImageDownloader.kt
index e61c88ccdc..466fd0a7f0 100644
--- a/app/src/main/java/com/vitorpamplona/amethyst/ui/actions/ImageDownloader.kt
+++ b/app/src/main/java/com/vitorpamplona/amethyst/ui/actions/ImageDownloader.kt
@@ -20,7 +20,7 @@
*/
package com.vitorpamplona.amethyst.ui.actions
-import com.vitorpamplona.amethyst.service.HttpClientManager
+import com.vitorpamplona.ammolite.service.HttpClientManager
import kotlinx.coroutines.CancellationException
import kotlinx.coroutines.delay
import java.net.HttpURLConnection
diff --git a/app/src/main/java/com/vitorpamplona/amethyst/ui/actions/ImageSaver.kt b/app/src/main/java/com/vitorpamplona/amethyst/ui/actions/ImageSaver.kt
index b734e01ee6..d044d249e2 100644
--- a/app/src/main/java/com/vitorpamplona/amethyst/ui/actions/ImageSaver.kt
+++ b/app/src/main/java/com/vitorpamplona/amethyst/ui/actions/ImageSaver.kt
@@ -32,7 +32,7 @@ import androidx.annotation.RequiresApi
import androidx.core.net.toFile
import androidx.core.net.toUri
import com.vitorpamplona.amethyst.BuildConfig
-import com.vitorpamplona.amethyst.service.HttpClientManager
+import com.vitorpamplona.ammolite.service.HttpClientManager
import kotlinx.coroutines.CancellationException
import okhttp3.Call
import okhttp3.Callback
diff --git a/app/src/main/java/com/vitorpamplona/amethyst/ui/actions/NewMediaModel.kt b/app/src/main/java/com/vitorpamplona/amethyst/ui/actions/NewMediaModel.kt
index 91c0bf1c8d..c9d3ccf79b 100644
--- a/app/src/main/java/com/vitorpamplona/amethyst/ui/actions/NewMediaModel.kt
+++ b/app/src/main/java/com/vitorpamplona/amethyst/ui/actions/NewMediaModel.kt
@@ -31,12 +31,12 @@ import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope
import com.vitorpamplona.amethyst.R
import com.vitorpamplona.amethyst.model.Account
-import com.vitorpamplona.amethyst.model.RelaySetupInfo
import com.vitorpamplona.amethyst.service.FileHeader
import com.vitorpamplona.amethyst.service.Nip96MediaServers
import com.vitorpamplona.amethyst.service.Nip96Uploader
import com.vitorpamplona.amethyst.ui.components.MediaCompressor
import com.vitorpamplona.amethyst.ui.stringRes
+import com.vitorpamplona.ammolite.relays.RelaySetupInfo
import kotlinx.coroutines.CancellationException
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch
diff --git a/app/src/main/java/com/vitorpamplona/amethyst/ui/actions/NewPostViewModel.kt b/app/src/main/java/com/vitorpamplona/amethyst/ui/actions/NewPostViewModel.kt
index 2172bafa20..4dd0e23a53 100644
--- a/app/src/main/java/com/vitorpamplona/amethyst/ui/actions/NewPostViewModel.kt
+++ b/app/src/main/java/com/vitorpamplona/amethyst/ui/actions/NewPostViewModel.kt
@@ -40,7 +40,6 @@ import com.vitorpamplona.amethyst.commons.richtext.RichTextParser
import com.vitorpamplona.amethyst.model.Account
import com.vitorpamplona.amethyst.model.LocalCache
import com.vitorpamplona.amethyst.model.Note
-import com.vitorpamplona.amethyst.model.RelaySetupInfo
import com.vitorpamplona.amethyst.model.User
import com.vitorpamplona.amethyst.service.FileHeader
import com.vitorpamplona.amethyst.service.LocationUtil
@@ -49,6 +48,7 @@ import com.vitorpamplona.amethyst.service.NostrSearchEventOrUserDataSource
import com.vitorpamplona.amethyst.ui.components.MediaCompressor
import com.vitorpamplona.amethyst.ui.components.Split
import com.vitorpamplona.amethyst.ui.screen.loggedIn.AccountViewModel
+import com.vitorpamplona.ammolite.relays.RelaySetupInfo
import com.vitorpamplona.quartz.encoders.Hex
import com.vitorpamplona.quartz.encoders.HexKey
import com.vitorpamplona.quartz.encoders.toNpub
diff --git a/app/src/main/java/com/vitorpamplona/amethyst/ui/actions/RelaySelectionDialog.kt b/app/src/main/java/com/vitorpamplona/amethyst/ui/actions/RelaySelectionDialog.kt
index fceca37605..4d28188f9a 100644
--- a/app/src/main/java/com/vitorpamplona/amethyst/ui/actions/RelaySelectionDialog.kt
+++ b/app/src/main/java/com/vitorpamplona/amethyst/ui/actions/RelaySelectionDialog.kt
@@ -46,13 +46,13 @@ import androidx.compose.ui.unit.dp
import androidx.compose.ui.window.Dialog
import androidx.compose.ui.window.DialogProperties
import com.vitorpamplona.amethyst.R
-import com.vitorpamplona.amethyst.model.RelayBriefInfoCache
-import com.vitorpamplona.amethyst.model.RelaySetupInfo
import com.vitorpamplona.amethyst.service.Nip11Retriever
import com.vitorpamplona.amethyst.ui.actions.relays.RelayInformationDialog
import com.vitorpamplona.amethyst.ui.screen.loggedIn.AccountViewModel
import com.vitorpamplona.amethyst.ui.stringRes
import com.vitorpamplona.amethyst.ui.theme.FeedPadding
+import com.vitorpamplona.ammolite.relays.RelayBriefInfoCache
+import com.vitorpamplona.ammolite.relays.RelaySetupInfo
import com.vitorpamplona.quartz.encoders.Nip11RelayInformation
import kotlinx.collections.immutable.ImmutableList
import kotlinx.collections.immutable.toImmutableList
diff --git a/app/src/main/java/com/vitorpamplona/amethyst/ui/actions/relays/AllRelayListView.kt b/app/src/main/java/com/vitorpamplona/amethyst/ui/actions/relays/AllRelayListView.kt
index 3db1051555..a24f599c5a 100644
--- a/app/src/main/java/com/vitorpamplona/amethyst/ui/actions/relays/AllRelayListView.kt
+++ b/app/src/main/java/com/vitorpamplona/amethyst/ui/actions/relays/AllRelayListView.kt
@@ -47,8 +47,6 @@ import androidx.compose.ui.window.DialogProperties
import androidx.lifecycle.compose.collectAsStateWithLifecycle
import androidx.lifecycle.viewmodel.compose.viewModel
import com.vitorpamplona.amethyst.R
-import com.vitorpamplona.amethyst.service.relays.Constants
-import com.vitorpamplona.amethyst.service.relays.RelayStat
import com.vitorpamplona.amethyst.ui.actions.CloseButton
import com.vitorpamplona.amethyst.ui.actions.SaveButton
import com.vitorpamplona.amethyst.ui.screen.loggedIn.AccountViewModel
@@ -58,6 +56,8 @@ import com.vitorpamplona.amethyst.ui.theme.MinHorzSpacer
import com.vitorpamplona.amethyst.ui.theme.RowColSpacing
import com.vitorpamplona.amethyst.ui.theme.StdHorzSpacer
import com.vitorpamplona.amethyst.ui.theme.grayText
+import com.vitorpamplona.ammolite.relays.Constants
+import com.vitorpamplona.ammolite.relays.RelayStat
@OptIn(ExperimentalMaterial3Api::class)
@Composable
diff --git a/app/src/main/java/com/vitorpamplona/amethyst/ui/actions/relays/BasicRelaySetupInfo.kt b/app/src/main/java/com/vitorpamplona/amethyst/ui/actions/relays/BasicRelaySetupInfo.kt
index be695f9950..2d03d4ad78 100644
--- a/app/src/main/java/com/vitorpamplona/amethyst/ui/actions/relays/BasicRelaySetupInfo.kt
+++ b/app/src/main/java/com/vitorpamplona/amethyst/ui/actions/relays/BasicRelaySetupInfo.kt
@@ -21,9 +21,9 @@
package com.vitorpamplona.amethyst.ui.actions.relays
import androidx.compose.runtime.Immutable
-import com.vitorpamplona.amethyst.model.RelayBriefInfoCache
-import com.vitorpamplona.amethyst.service.relays.FeedType
-import com.vitorpamplona.amethyst.service.relays.RelayStat
+import com.vitorpamplona.ammolite.relays.FeedType
+import com.vitorpamplona.ammolite.relays.RelayBriefInfoCache
+import com.vitorpamplona.ammolite.relays.RelayStat
@Immutable
data class BasicRelaySetupInfo(
diff --git a/app/src/main/java/com/vitorpamplona/amethyst/ui/actions/relays/BasicRelaySetupInfoDialog.kt b/app/src/main/java/com/vitorpamplona/amethyst/ui/actions/relays/BasicRelaySetupInfoDialog.kt
index cc69a83c41..134320ed09 100644
--- a/app/src/main/java/com/vitorpamplona/amethyst/ui/actions/relays/BasicRelaySetupInfoDialog.kt
+++ b/app/src/main/java/com/vitorpamplona/amethyst/ui/actions/relays/BasicRelaySetupInfoDialog.kt
@@ -28,11 +28,11 @@ import androidx.compose.runtime.setValue
import androidx.compose.ui.platform.LocalContext
import com.vitorpamplona.amethyst.R
import com.vitorpamplona.amethyst.model.FeatureSetType
-import com.vitorpamplona.amethyst.model.RelayBriefInfoCache
import com.vitorpamplona.amethyst.service.Nip11Retriever
import com.vitorpamplona.amethyst.ui.actions.RelayInfoDialog
import com.vitorpamplona.amethyst.ui.screen.loggedIn.AccountViewModel
import com.vitorpamplona.amethyst.ui.stringRes
+import com.vitorpamplona.ammolite.relays.RelayBriefInfoCache
@Composable
fun BasicRelaySetupInfoDialog(
diff --git a/app/src/main/java/com/vitorpamplona/amethyst/ui/actions/relays/BasicRelaySetupInfoModel.kt b/app/src/main/java/com/vitorpamplona/amethyst/ui/actions/relays/BasicRelaySetupInfoModel.kt
index 69fb9a41ab..9eea0faa91 100644
--- a/app/src/main/java/com/vitorpamplona/amethyst/ui/actions/relays/BasicRelaySetupInfoModel.kt
+++ b/app/src/main/java/com/vitorpamplona/amethyst/ui/actions/relays/BasicRelaySetupInfoModel.kt
@@ -24,7 +24,7 @@ import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope
import com.vitorpamplona.amethyst.model.Account
import com.vitorpamplona.amethyst.service.Nip11CachedRetriever
-import com.vitorpamplona.amethyst.service.relays.RelayStats
+import com.vitorpamplona.ammolite.relays.RelayStats
import com.vitorpamplona.quartz.encoders.RelayUrlFormatter
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.flow.MutableStateFlow
diff --git a/app/src/main/java/com/vitorpamplona/amethyst/ui/actions/relays/Kind3RelayListView.kt b/app/src/main/java/com/vitorpamplona/amethyst/ui/actions/relays/Kind3RelayListView.kt
index 0eba7699e2..8741f2cdb9 100644
--- a/app/src/main/java/com/vitorpamplona/amethyst/ui/actions/relays/Kind3RelayListView.kt
+++ b/app/src/main/java/com/vitorpamplona/amethyst/ui/actions/relays/Kind3RelayListView.kt
@@ -67,12 +67,8 @@ import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.sp
import com.vitorpamplona.amethyst.R
import com.vitorpamplona.amethyst.model.FeatureSetType
-import com.vitorpamplona.amethyst.model.RelayBriefInfoCache
import com.vitorpamplona.amethyst.service.Nip11CachedRetriever
import com.vitorpamplona.amethyst.service.Nip11Retriever
-import com.vitorpamplona.amethyst.service.relays.Constants
-import com.vitorpamplona.amethyst.service.relays.FeedType
-import com.vitorpamplona.amethyst.service.relays.RelayStat
import com.vitorpamplona.amethyst.ui.actions.RelayInfoDialog
import com.vitorpamplona.amethyst.ui.note.RenderRelayIcon
import com.vitorpamplona.amethyst.ui.screen.loggedIn.AccountViewModel
@@ -91,6 +87,10 @@ import com.vitorpamplona.amethyst.ui.theme.allGoodColor
import com.vitorpamplona.amethyst.ui.theme.largeRelayIconModifier
import com.vitorpamplona.amethyst.ui.theme.placeholderText
import com.vitorpamplona.amethyst.ui.theme.warningColor
+import com.vitorpamplona.ammolite.relays.Constants
+import com.vitorpamplona.ammolite.relays.FeedType
+import com.vitorpamplona.ammolite.relays.RelayBriefInfoCache
+import com.vitorpamplona.ammolite.relays.RelayStat
import com.vitorpamplona.quartz.encoders.RelayUrlFormatter
import kotlinx.coroutines.launch
diff --git a/app/src/main/java/com/vitorpamplona/amethyst/ui/actions/relays/Kind3RelayListViewModel.kt b/app/src/main/java/com/vitorpamplona/amethyst/ui/actions/relays/Kind3RelayListViewModel.kt
index bbd00140ba..de48cb7904 100644
--- a/app/src/main/java/com/vitorpamplona/amethyst/ui/actions/relays/Kind3RelayListViewModel.kt
+++ b/app/src/main/java/com/vitorpamplona/amethyst/ui/actions/relays/Kind3RelayListViewModel.kt
@@ -23,11 +23,11 @@ package com.vitorpamplona.amethyst.ui.actions.relays
import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope
import com.vitorpamplona.amethyst.model.Account
-import com.vitorpamplona.amethyst.model.RelaySetupInfo
import com.vitorpamplona.amethyst.service.Nip11CachedRetriever
-import com.vitorpamplona.amethyst.service.relays.Constants
-import com.vitorpamplona.amethyst.service.relays.FeedType
-import com.vitorpamplona.amethyst.service.relays.RelayStats
+import com.vitorpamplona.ammolite.relays.Constants
+import com.vitorpamplona.ammolite.relays.FeedType
+import com.vitorpamplona.ammolite.relays.RelaySetupInfo
+import com.vitorpamplona.ammolite.relays.RelayStats
import com.vitorpamplona.quartz.encoders.RelayUrlFormatter
import kotlinx.collections.immutable.toImmutableSet
import kotlinx.coroutines.Dispatchers
diff --git a/app/src/main/java/com/vitorpamplona/amethyst/ui/actions/relays/Nip65RelayListViewModel.kt b/app/src/main/java/com/vitorpamplona/amethyst/ui/actions/relays/Nip65RelayListViewModel.kt
index 615a41e03e..c41ce2c1d5 100644
--- a/app/src/main/java/com/vitorpamplona/amethyst/ui/actions/relays/Nip65RelayListViewModel.kt
+++ b/app/src/main/java/com/vitorpamplona/amethyst/ui/actions/relays/Nip65RelayListViewModel.kt
@@ -24,7 +24,7 @@ import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope
import com.vitorpamplona.amethyst.model.Account
import com.vitorpamplona.amethyst.service.Nip11CachedRetriever
-import com.vitorpamplona.amethyst.service.relays.RelayStats
+import com.vitorpamplona.ammolite.relays.RelayStats
import com.vitorpamplona.quartz.encoders.RelayUrlFormatter
import com.vitorpamplona.quartz.events.AdvertisedRelayListEvent
import kotlinx.coroutines.Dispatchers
diff --git a/app/src/main/java/com/vitorpamplona/amethyst/ui/actions/relays/RelayInformationDialog.kt b/app/src/main/java/com/vitorpamplona/amethyst/ui/actions/relays/RelayInformationDialog.kt
index fa4b5c0862..368f5b3ee8 100644
--- a/app/src/main/java/com/vitorpamplona/amethyst/ui/actions/relays/RelayInformationDialog.kt
+++ b/app/src/main/java/com/vitorpamplona/amethyst/ui/actions/relays/RelayInformationDialog.kt
@@ -49,8 +49,6 @@ import androidx.compose.ui.window.Dialog
import androidx.compose.ui.window.DialogProperties
import com.vitorpamplona.amethyst.R
import com.vitorpamplona.amethyst.model.FeatureSetType
-import com.vitorpamplona.amethyst.model.RelayBriefInfoCache
-import com.vitorpamplona.amethyst.service.relays.RelayStats
import com.vitorpamplona.amethyst.ui.actions.CloseButton
import com.vitorpamplona.amethyst.ui.actions.CrossfadeIfEnabled
import com.vitorpamplona.amethyst.ui.components.ClickableEmail
@@ -67,6 +65,8 @@ import com.vitorpamplona.amethyst.ui.theme.DoubleVertSpacer
import com.vitorpamplona.amethyst.ui.theme.StdPadding
import com.vitorpamplona.amethyst.ui.theme.StdVertSpacer
import com.vitorpamplona.amethyst.ui.theme.largeRelayIconModifier
+import com.vitorpamplona.ammolite.relays.RelayBriefInfoCache
+import com.vitorpamplona.ammolite.relays.RelayStats
import com.vitorpamplona.quartz.encoders.Nip11RelayInformation
import com.vitorpamplona.quartz.events.EmptyTagList
import kotlinx.collections.immutable.toImmutableList
diff --git a/app/src/main/java/com/vitorpamplona/amethyst/ui/actions/relays/RelayUrlEditField.kt b/app/src/main/java/com/vitorpamplona/amethyst/ui/actions/relays/RelayUrlEditField.kt
index ded0da3987..3cbe0af8a0 100644
--- a/app/src/main/java/com/vitorpamplona/amethyst/ui/actions/relays/RelayUrlEditField.kt
+++ b/app/src/main/java/com/vitorpamplona/amethyst/ui/actions/relays/RelayUrlEditField.kt
@@ -36,11 +36,11 @@ import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color
import com.vitorpamplona.amethyst.R
-import com.vitorpamplona.amethyst.service.relays.RelayStat
import com.vitorpamplona.amethyst.ui.stringRes
import com.vitorpamplona.amethyst.ui.theme.ButtonBorder
import com.vitorpamplona.amethyst.ui.theme.Size10dp
import com.vitorpamplona.amethyst.ui.theme.placeholderText
+import com.vitorpamplona.ammolite.relays.RelayStat
import com.vitorpamplona.quartz.encoders.RelayUrlFormatter
@Composable
diff --git a/app/src/main/java/com/vitorpamplona/amethyst/ui/navigation/AppTopBar.kt b/app/src/main/java/com/vitorpamplona/amethyst/ui/navigation/AppTopBar.kt
index 5f33119404..f915355ee6 100644
--- a/app/src/main/java/com/vitorpamplona/amethyst/ui/navigation/AppTopBar.kt
+++ b/app/src/main/java/com/vitorpamplona/amethyst/ui/navigation/AppTopBar.kt
@@ -98,8 +98,6 @@ import com.vitorpamplona.amethyst.service.NostrThreadDataSource
import com.vitorpamplona.amethyst.service.NostrUserProfileDataSource
import com.vitorpamplona.amethyst.service.NostrVideoDataSource
import com.vitorpamplona.amethyst.service.checkNotInMainThread
-import com.vitorpamplona.amethyst.service.relays.Client
-import com.vitorpamplona.amethyst.service.relays.RelayPool
import com.vitorpamplona.amethyst.ui.components.LoadNote
import com.vitorpamplona.amethyst.ui.components.RobohashFallbackAsyncImage
import com.vitorpamplona.amethyst.ui.note.AmethystIcon
@@ -139,6 +137,8 @@ import com.vitorpamplona.amethyst.ui.theme.Size22Modifier
import com.vitorpamplona.amethyst.ui.theme.Size34dp
import com.vitorpamplona.amethyst.ui.theme.Size40dp
import com.vitorpamplona.amethyst.ui.theme.placeholderText
+import com.vitorpamplona.ammolite.relays.Client
+import com.vitorpamplona.ammolite.relays.RelayPool
import com.vitorpamplona.quartz.events.ChatroomKey
import com.vitorpamplona.quartz.events.ContactListEvent
import com.vitorpamplona.quartz.events.MuteListEvent
diff --git a/app/src/main/java/com/vitorpamplona/amethyst/ui/navigation/DrawerContent.kt b/app/src/main/java/com/vitorpamplona/amethyst/ui/navigation/DrawerContent.kt
index edcf50c7fa..1206b56966 100644
--- a/app/src/main/java/com/vitorpamplona/amethyst/ui/navigation/DrawerContent.kt
+++ b/app/src/main/java/com/vitorpamplona/amethyst/ui/navigation/DrawerContent.kt
@@ -85,8 +85,6 @@ import com.vitorpamplona.amethyst.BuildConfig
import com.vitorpamplona.amethyst.R
import com.vitorpamplona.amethyst.model.FeatureSetType
import com.vitorpamplona.amethyst.model.User
-import com.vitorpamplona.amethyst.service.relays.RelayPool
-import com.vitorpamplona.amethyst.service.relays.RelayPoolStatus
import com.vitorpamplona.amethyst.ui.actions.relays.AllRelayListView
import com.vitorpamplona.amethyst.ui.components.ClickableText
import com.vitorpamplona.amethyst.ui.components.CreateTextWithEmoji
@@ -110,6 +108,8 @@ import com.vitorpamplona.amethyst.ui.theme.bannerModifier
import com.vitorpamplona.amethyst.ui.theme.drawerSpacing
import com.vitorpamplona.amethyst.ui.theme.placeholderText
import com.vitorpamplona.amethyst.ui.theme.profileContentHeaderModifier
+import com.vitorpamplona.ammolite.relays.RelayPool
+import com.vitorpamplona.ammolite.relays.RelayPoolStatus
import com.vitorpamplona.quartz.encoders.ATag
import com.vitorpamplona.quartz.encoders.HexKey
import com.vitorpamplona.quartz.events.ImmutableListOfLists
diff --git a/app/src/main/java/com/vitorpamplona/amethyst/ui/note/RelayListRow.kt b/app/src/main/java/com/vitorpamplona/amethyst/ui/note/RelayListRow.kt
index 39a5b3dd6a..c9c3bed9a9 100644
--- a/app/src/main/java/com/vitorpamplona/amethyst/ui/note/RelayListRow.kt
+++ b/app/src/main/java/com/vitorpamplona/amethyst/ui/note/RelayListRow.kt
@@ -40,7 +40,6 @@ import androidx.lifecycle.compose.collectAsStateWithLifecycle
import com.vitorpamplona.amethyst.R
import com.vitorpamplona.amethyst.model.FeatureSetType
import com.vitorpamplona.amethyst.model.Note
-import com.vitorpamplona.amethyst.model.RelayBriefInfoCache
import com.vitorpamplona.amethyst.service.Nip11CachedRetriever
import com.vitorpamplona.amethyst.service.Nip11Retriever
import com.vitorpamplona.amethyst.ui.actions.relays.RelayInformationDialog
@@ -54,6 +53,7 @@ import com.vitorpamplona.amethyst.ui.theme.Size17dp
import com.vitorpamplona.amethyst.ui.theme.StdStartPadding
import com.vitorpamplona.amethyst.ui.theme.placeholderText
import com.vitorpamplona.amethyst.ui.theme.relayIconModifier
+import com.vitorpamplona.ammolite.relays.RelayBriefInfoCache
@Composable
public fun RelayBadgesHorizontal(
diff --git a/app/src/main/java/com/vitorpamplona/amethyst/ui/note/UserReactionsRow.kt b/app/src/main/java/com/vitorpamplona/amethyst/ui/note/UserReactionsRow.kt
index 4d07867c41..9b2e8fd5d9 100644
--- a/app/src/main/java/com/vitorpamplona/amethyst/ui/note/UserReactionsRow.kt
+++ b/app/src/main/java/com/vitorpamplona/amethyst/ui/note/UserReactionsRow.kt
@@ -57,7 +57,6 @@ import com.vitorpamplona.amethyst.model.LocalCache
import com.vitorpamplona.amethyst.model.Note
import com.vitorpamplona.amethyst.model.User
import com.vitorpamplona.amethyst.service.checkNotInMainThread
-import com.vitorpamplona.amethyst.ui.components.BundledInsert
import com.vitorpamplona.amethyst.ui.screen.loggedIn.showAmountAxis
import com.vitorpamplona.amethyst.ui.stringRes
import com.vitorpamplona.amethyst.ui.theme.BitcoinOrange
@@ -66,6 +65,7 @@ import com.vitorpamplona.amethyst.ui.theme.Size20Modifier
import com.vitorpamplona.amethyst.ui.theme.Size24Modifier
import com.vitorpamplona.amethyst.ui.theme.StdHorzSpacer
import com.vitorpamplona.amethyst.ui.theme.placeholderText
+import com.vitorpamplona.ammolite.relays.BundledInsert
import com.vitorpamplona.quartz.encoders.HexKey
import com.vitorpamplona.quartz.events.BaseTextNoteEvent
import com.vitorpamplona.quartz.events.GenericRepostEvent
diff --git a/app/src/main/java/com/vitorpamplona/amethyst/ui/note/types/RelayList.kt b/app/src/main/java/com/vitorpamplona/amethyst/ui/note/types/RelayList.kt
index 5bef0fcdb5..59f0a69e36 100644
--- a/app/src/main/java/com/vitorpamplona/amethyst/ui/note/types/RelayList.kt
+++ b/app/src/main/java/com/vitorpamplona/amethyst/ui/note/types/RelayList.kt
@@ -44,13 +44,13 @@ import androidx.compose.ui.text.style.TextAlign
import androidx.compose.ui.text.style.TextOverflow
import androidx.compose.ui.unit.dp
import com.vitorpamplona.amethyst.model.Note
-import com.vitorpamplona.amethyst.model.RelayBriefInfoCache
import com.vitorpamplona.amethyst.ui.actions.relays.AllRelayListView
import com.vitorpamplona.amethyst.ui.components.ShowMoreButton
import com.vitorpamplona.amethyst.ui.note.AddRelayButton
import com.vitorpamplona.amethyst.ui.note.RemoveRelayButton
import com.vitorpamplona.amethyst.ui.note.getGradient
import com.vitorpamplona.amethyst.ui.screen.loggedIn.AccountViewModel
+import com.vitorpamplona.ammolite.relays.RelayBriefInfoCache
import com.vitorpamplona.quartz.events.RelaySetEvent
import kotlinx.collections.immutable.toImmutableList
diff --git a/app/src/main/java/com/vitorpamplona/amethyst/ui/screen/AccountStateViewModel.kt b/app/src/main/java/com/vitorpamplona/amethyst/ui/screen/AccountStateViewModel.kt
index 18e4803c28..e7ba98d216 100644
--- a/app/src/main/java/com/vitorpamplona/amethyst/ui/screen/AccountStateViewModel.kt
+++ b/app/src/main/java/com/vitorpamplona/amethyst/ui/screen/AccountStateViewModel.kt
@@ -28,9 +28,9 @@ import com.vitorpamplona.amethyst.AccountInfo
import com.vitorpamplona.amethyst.LocalPreferences
import com.vitorpamplona.amethyst.ServiceManager
import com.vitorpamplona.amethyst.model.Account
-import com.vitorpamplona.amethyst.service.HttpClientManager
import com.vitorpamplona.amethyst.service.Nip05NostrAddressVerifier
-import com.vitorpamplona.amethyst.service.relays.Client
+import com.vitorpamplona.ammolite.relays.Client
+import com.vitorpamplona.ammolite.service.HttpClientManager
import com.vitorpamplona.quartz.crypto.CryptoUtils
import com.vitorpamplona.quartz.crypto.KeyPair
import com.vitorpamplona.quartz.crypto.nip06.Nip06
diff --git a/app/src/main/java/com/vitorpamplona/amethyst/ui/screen/CardFeedViewModel.kt b/app/src/main/java/com/vitorpamplona/amethyst/ui/screen/CardFeedViewModel.kt
index 26134adc5c..d41d246239 100644
--- a/app/src/main/java/com/vitorpamplona/amethyst/ui/screen/CardFeedViewModel.kt
+++ b/app/src/main/java/com/vitorpamplona/amethyst/ui/screen/CardFeedViewModel.kt
@@ -32,11 +32,11 @@ import com.vitorpamplona.amethyst.model.LocalCache
import com.vitorpamplona.amethyst.model.Note
import com.vitorpamplona.amethyst.model.User
import com.vitorpamplona.amethyst.service.checkNotInMainThread
-import com.vitorpamplona.amethyst.ui.components.BundledInsert
-import com.vitorpamplona.amethyst.ui.components.BundledUpdate
import com.vitorpamplona.amethyst.ui.dal.AdditiveFeedFilter
import com.vitorpamplona.amethyst.ui.dal.FeedFilter
import com.vitorpamplona.amethyst.ui.dal.NotificationFeedFilter
+import com.vitorpamplona.ammolite.relays.BundledInsert
+import com.vitorpamplona.ammolite.relays.BundledUpdate
import com.vitorpamplona.quartz.events.BadgeAwardEvent
import com.vitorpamplona.quartz.events.ChannelCreateEvent
import com.vitorpamplona.quartz.events.ChannelMetadataEvent
diff --git a/app/src/main/java/com/vitorpamplona/amethyst/ui/screen/FeedViewModel.kt b/app/src/main/java/com/vitorpamplona/amethyst/ui/screen/FeedViewModel.kt
index c4ca09313f..422bd15a2c 100644
--- a/app/src/main/java/com/vitorpamplona/amethyst/ui/screen/FeedViewModel.kt
+++ b/app/src/main/java/com/vitorpamplona/amethyst/ui/screen/FeedViewModel.kt
@@ -33,8 +33,6 @@ import com.vitorpamplona.amethyst.model.LocalCache
import com.vitorpamplona.amethyst.model.Note
import com.vitorpamplona.amethyst.model.User
import com.vitorpamplona.amethyst.service.checkNotInMainThread
-import com.vitorpamplona.amethyst.ui.components.BundledInsert
-import com.vitorpamplona.amethyst.ui.components.BundledUpdate
import com.vitorpamplona.amethyst.ui.dal.AdditiveFeedFilter
import com.vitorpamplona.amethyst.ui.dal.BookmarkPrivateFeedFilter
import com.vitorpamplona.amethyst.ui.dal.BookmarkPublicFeedFilter
@@ -62,6 +60,8 @@ import com.vitorpamplona.amethyst.ui.dal.UserProfileConversationsFeedFilter
import com.vitorpamplona.amethyst.ui.dal.UserProfileNewThreadFeedFilter
import com.vitorpamplona.amethyst.ui.dal.UserProfileReportsFeedFilter
import com.vitorpamplona.amethyst.ui.dal.VideoFeedFilter
+import com.vitorpamplona.ammolite.relays.BundledInsert
+import com.vitorpamplona.ammolite.relays.BundledUpdate
import com.vitorpamplona.quartz.events.ChatroomKey
import com.vitorpamplona.quartz.events.DeletionEvent
import kotlinx.collections.immutable.ImmutableList
diff --git a/app/src/main/java/com/vitorpamplona/amethyst/ui/screen/LnZapFeedViewModel.kt b/app/src/main/java/com/vitorpamplona/amethyst/ui/screen/LnZapFeedViewModel.kt
index 1465d73ead..a0db78fc0b 100644
--- a/app/src/main/java/com/vitorpamplona/amethyst/ui/screen/LnZapFeedViewModel.kt
+++ b/app/src/main/java/com/vitorpamplona/amethyst/ui/screen/LnZapFeedViewModel.kt
@@ -29,9 +29,9 @@ import androidx.lifecycle.viewModelScope
import com.vitorpamplona.amethyst.model.LocalCache
import com.vitorpamplona.amethyst.model.User
import com.vitorpamplona.amethyst.service.checkNotInMainThread
-import com.vitorpamplona.amethyst.ui.components.BundledUpdate
import com.vitorpamplona.amethyst.ui.dal.FeedFilter
import com.vitorpamplona.amethyst.ui.dal.UserProfileZapsFeedFilter
+import com.vitorpamplona.ammolite.relays.BundledUpdate
import kotlinx.collections.immutable.ImmutableList
import kotlinx.collections.immutable.toImmutableList
import kotlinx.coroutines.Dispatchers
diff --git a/app/src/main/java/com/vitorpamplona/amethyst/ui/screen/RelayFeedView.kt b/app/src/main/java/com/vitorpamplona/amethyst/ui/screen/RelayFeedView.kt
index dafa52a53c..38b5550b16 100644
--- a/app/src/main/java/com/vitorpamplona/amethyst/ui/screen/RelayFeedView.kt
+++ b/app/src/main/java/com/vitorpamplona/amethyst/ui/screen/RelayFeedView.kt
@@ -38,11 +38,11 @@ import com.vitorpamplona.amethyst.model.RelayInfo
import com.vitorpamplona.amethyst.model.User
import com.vitorpamplona.amethyst.model.UserState
import com.vitorpamplona.amethyst.ui.actions.relays.AllRelayListView
-import com.vitorpamplona.amethyst.ui.components.BundledUpdate
import com.vitorpamplona.amethyst.ui.note.RelayCompose
import com.vitorpamplona.amethyst.ui.screen.loggedIn.AccountViewModel
import com.vitorpamplona.amethyst.ui.theme.DividerThickness
import com.vitorpamplona.amethyst.ui.theme.FeedPadding
+import com.vitorpamplona.ammolite.relays.BundledUpdate
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.asStateFlow
diff --git a/app/src/main/java/com/vitorpamplona/amethyst/ui/screen/StringFeedViewModel.kt b/app/src/main/java/com/vitorpamplona/amethyst/ui/screen/StringFeedViewModel.kt
index 438c5849b6..600d8b7566 100644
--- a/app/src/main/java/com/vitorpamplona/amethyst/ui/screen/StringFeedViewModel.kt
+++ b/app/src/main/java/com/vitorpamplona/amethyst/ui/screen/StringFeedViewModel.kt
@@ -29,9 +29,9 @@ import androidx.lifecycle.viewModelScope
import com.vitorpamplona.amethyst.model.Account
import com.vitorpamplona.amethyst.model.LocalCache
import com.vitorpamplona.amethyst.service.checkNotInMainThread
-import com.vitorpamplona.amethyst.ui.components.BundledUpdate
import com.vitorpamplona.amethyst.ui.dal.FeedFilter
import com.vitorpamplona.amethyst.ui.dal.HiddenWordsFeedFilter
+import com.vitorpamplona.ammolite.relays.BundledUpdate
import kotlinx.collections.immutable.ImmutableList
import kotlinx.collections.immutable.toImmutableList
import kotlinx.coroutines.Dispatchers
diff --git a/app/src/main/java/com/vitorpamplona/amethyst/ui/screen/UserFeedViewModel.kt b/app/src/main/java/com/vitorpamplona/amethyst/ui/screen/UserFeedViewModel.kt
index 58a5b8b4ea..252d3fdb07 100644
--- a/app/src/main/java/com/vitorpamplona/amethyst/ui/screen/UserFeedViewModel.kt
+++ b/app/src/main/java/com/vitorpamplona/amethyst/ui/screen/UserFeedViewModel.kt
@@ -30,12 +30,12 @@ import com.vitorpamplona.amethyst.model.Account
import com.vitorpamplona.amethyst.model.LocalCache
import com.vitorpamplona.amethyst.model.User
import com.vitorpamplona.amethyst.service.checkNotInMainThread
-import com.vitorpamplona.amethyst.ui.components.BundledUpdate
import com.vitorpamplona.amethyst.ui.dal.FeedFilter
import com.vitorpamplona.amethyst.ui.dal.HiddenAccountsFeedFilter
import com.vitorpamplona.amethyst.ui.dal.SpammerAccountsFeedFilter
import com.vitorpamplona.amethyst.ui.dal.UserProfileFollowersFeedFilter
import com.vitorpamplona.amethyst.ui.dal.UserProfileFollowsFeedFilter
+import com.vitorpamplona.ammolite.relays.BundledUpdate
import kotlinx.collections.immutable.ImmutableList
import kotlinx.collections.immutable.toImmutableList
import kotlinx.coroutines.Dispatchers
diff --git a/app/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/AccountViewModel.kt b/app/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/AccountViewModel.kt
index f24d669cdd..df62b338a0 100644
--- a/app/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/AccountViewModel.kt
+++ b/app/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/AccountViewModel.kt
@@ -52,7 +52,6 @@ import com.vitorpamplona.amethyst.model.UserState
import com.vitorpamplona.amethyst.model.observables.CreatedAtComparator
import com.vitorpamplona.amethyst.service.CashuProcessor
import com.vitorpamplona.amethyst.service.CashuToken
-import com.vitorpamplona.amethyst.service.HttpClientManager
import com.vitorpamplona.amethyst.service.Nip05NostrAddressVerifier
import com.vitorpamplona.amethyst.service.Nip11CachedRetriever
import com.vitorpamplona.amethyst.service.Nip11Retriever
@@ -60,7 +59,6 @@ import com.vitorpamplona.amethyst.service.OnlineChecker
import com.vitorpamplona.amethyst.service.ZapPaymentHandler
import com.vitorpamplona.amethyst.service.checkNotInMainThread
import com.vitorpamplona.amethyst.ui.actions.Dao
-import com.vitorpamplona.amethyst.ui.components.BundledInsert
import com.vitorpamplona.amethyst.ui.components.UrlPreviewState
import com.vitorpamplona.amethyst.ui.navigation.Route
import com.vitorpamplona.amethyst.ui.navigation.bottomNavigationItems
@@ -70,6 +68,8 @@ import com.vitorpamplona.amethyst.ui.note.showAmount
import com.vitorpamplona.amethyst.ui.screen.CombinedZap
import com.vitorpamplona.amethyst.ui.screen.SettingsState
import com.vitorpamplona.amethyst.ui.stringRes
+import com.vitorpamplona.ammolite.relays.BundledInsert
+import com.vitorpamplona.ammolite.service.HttpClientManager
import com.vitorpamplona.quartz.encoders.ATag
import com.vitorpamplona.quartz.encoders.HexKey
import com.vitorpamplona.quartz.encoders.Nip11RelayInformation
diff --git a/app/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/SearchScreen.kt b/app/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/SearchScreen.kt
index 04587f1089..b2f8e7b601 100644
--- a/app/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/SearchScreen.kt
+++ b/app/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/SearchScreen.kt
@@ -76,7 +76,6 @@ import com.vitorpamplona.amethyst.model.Note
import com.vitorpamplona.amethyst.model.User
import com.vitorpamplona.amethyst.service.NostrSearchEventOrUserDataSource
import com.vitorpamplona.amethyst.service.checkNotInMainThread
-import com.vitorpamplona.amethyst.ui.components.BundledUpdate
import com.vitorpamplona.amethyst.ui.note.AboutDisplay
import com.vitorpamplona.amethyst.ui.note.ChannelName
import com.vitorpamplona.amethyst.ui.note.ClearTextIcon
@@ -92,6 +91,7 @@ import com.vitorpamplona.amethyst.ui.theme.FeedPadding
import com.vitorpamplona.amethyst.ui.theme.Size20Modifier
import com.vitorpamplona.amethyst.ui.theme.StdTopPadding
import com.vitorpamplona.amethyst.ui.theme.placeholderText
+import com.vitorpamplona.ammolite.relays.BundledUpdate
import com.vitorpamplona.quartz.events.findHashtags
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.FlowPreview
diff --git a/benchmark/build.gradle b/benchmark/build.gradle
index cf523ff76d..b2f754cb2a 100644
--- a/benchmark/build.gradle
+++ b/benchmark/build.gradle
@@ -55,6 +55,7 @@ dependencies {
androidTestImplementation libs.androidx.benchmark.junit4
androidTestImplementation project(path: ':quartz')
androidTestImplementation project(path: ':commons')
+ androidTestImplementation project(path: ':ammolite')
androidTestImplementation libs.androidx.compose.foundation
diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml
index f7ae275e1e..2d232dcf86 100644
--- a/gradle/libs.versions.toml
+++ b/gradle/libs.versions.toml
@@ -44,6 +44,8 @@ zelory = "3.0.1"
zoomable = "1.6.1"
zxing = "3.5.3"
zxingAndroidEmbedded = "4.3.0"
+material = "1.10.0"
+materialVersion = "1.10.0"
[libraries]
abedElazizShe-image-compressor = { group = "com.github.AbedElazizShe", name = "LightCompressor", version.ref = "lightcompressor" }
@@ -114,6 +116,7 @@ zelory-video-compressor = { group = "id.zelory", name = "compressor", version.re
zoomable = { group = "net.engawapg.lib", name = "zoomable", version.ref = "zoomable" }
zxing = { group = "com.google.zxing", name = "core", version.ref = "zxing" }
zxing-embedded = { group = "com.journeyapps", name = "zxing-android-embedded", version.ref = "zxingAndroidEmbedded" }
+material = { group = "com.google.android.material", name = "material", version.ref = "materialVersion" }
[plugins]
androidApplication = { id = "com.android.application", version.ref = "agp" }
diff --git a/settings.gradle b/settings.gradle
index 45a4461c79..5c054bd44b 100644
--- a/settings.gradle
+++ b/settings.gradle
@@ -32,3 +32,4 @@ include ':app'
include ':benchmark'
include ':quartz'
include ':commons'
+include ':ammolite'