mirror of
https://github.com/vitorpamplona/amethyst.git
synced 2026-10-06 11:48:24 +00:00
refactor(account): replace JVM-only APIs in Account's group with KMP ones
So the group can land in commons/commonMain rather than jvmAndroid: - java.math.BigDecimal -> quartz.utils.BigDecimal (Account, AccountZapActions); on JVM/Android it is a typealias for the same class. - java.util.UUID.randomUUID() -> kotlin.uuid.Uuid.random() (AccountSettings, FollowSetsState, StarterPacksState); same random v4 string form. - java.util.Base64 -> kotlin.io.encoding.Base64 (OtsState); both are the RFC 4648 alphabet with padding. - ConcurrentHashMap -> quartz ConcurrentMap and Collections.synchronizedSet -> commons ConcurrentSet (GeohashChatIdentityState, AccountConcordActions); only get/set/remove and an atomic add are used. - Locale.getDefault().language -> commons getDefaultLanguageCode(), a new expect beside getLanguagesSpokenByUser (Android/JVM: the same call; iOS: NSLocale.currentLocale.languageCode). CashuWalletState's maps are iterated (keys/values/entries), which ConcurrentMap does not offer; they change with the rest of the Cashu promotion. No behaviour change. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01S7FuNBSKiyVecARSoE4B9P
This commit is contained in:
@@ -341,6 +341,7 @@ import com.vitorpamplona.quartz.nipA0VoiceMessages.VoiceReplyEvent
|
||||
import com.vitorpamplona.quartz.nipA3PaymentTargets.PaymentTarget
|
||||
import com.vitorpamplona.quartz.nipB0WebBookmarks.WebBookmarkEvent
|
||||
import com.vitorpamplona.quartz.nipC7Chats.ChatEvent
|
||||
import com.vitorpamplona.quartz.utils.BigDecimal
|
||||
import com.vitorpamplona.quartz.utils.DualCase
|
||||
import com.vitorpamplona.quartz.utils.Log
|
||||
import com.vitorpamplona.quartz.utils.RandomInstance
|
||||
@@ -362,7 +363,6 @@ import kotlinx.coroutines.flow.stateIn
|
||||
import kotlinx.coroutines.launch
|
||||
import kotlinx.coroutines.sync.Mutex
|
||||
import kotlinx.coroutines.sync.withLock
|
||||
import java.math.BigDecimal
|
||||
import kotlin.coroutines.cancellation.CancellationException
|
||||
import com.vitorpamplona.quartz.experimental.nip95.header.thumbhash as nip95thumbhash
|
||||
import com.vitorpamplona.quartz.experimental.profileGallery.thumbhash as galleryThumbhash
|
||||
|
||||
@@ -30,6 +30,7 @@ import com.vitorpamplona.amethyst.commons.model.cache.filter
|
||||
import com.vitorpamplona.amethyst.commons.model.concord.ConcordChannel
|
||||
import com.vitorpamplona.amethyst.commons.model.concord.ConcordCommunitySession
|
||||
import com.vitorpamplona.amethyst.commons.model.concordChannelLastReadRoute
|
||||
import com.vitorpamplona.amethyst.commons.util.ConcurrentSet
|
||||
import com.vitorpamplona.amethyst.commons.viewmodels.ReplyMode
|
||||
import com.vitorpamplona.quartz.concord.cord02Community.ConcordCommunityList.withControlRoot
|
||||
import com.vitorpamplona.quartz.concord.cord02Community.ConcordCommunityListEntry
|
||||
@@ -70,10 +71,10 @@ import com.vitorpamplona.quartz.nipC7Chats.ChatEvent
|
||||
import com.vitorpamplona.quartz.utils.Log
|
||||
import com.vitorpamplona.quartz.utils.RandomInstance
|
||||
import com.vitorpamplona.quartz.utils.TimeUtils
|
||||
import com.vitorpamplona.quartz.utils.concurrent.ConcurrentMap
|
||||
import kotlinx.coroutines.async
|
||||
import kotlinx.coroutines.awaitAll
|
||||
import kotlinx.coroutines.coroutineScope
|
||||
import java.util.concurrent.ConcurrentHashMap
|
||||
|
||||
/** Name of the default Concord community Admin role minted by "Make admin". */
|
||||
private const val CONCORD_ADMIN_ROLE = "Admin"
|
||||
@@ -1222,7 +1223,7 @@ class AccountConcordActions(
|
||||
// Rotations we've already adopted ("communityId:epoch"), so a base-rekey wrap still buffered
|
||||
// in the pre-rebuild window (the session rebuild off `liveCommunities` is async) is not
|
||||
// adopted — and re-published — twice on successive revision ticks.
|
||||
private val adoptedConcordRotations = java.util.Collections.synchronizedSet(HashSet<String>())
|
||||
private val adoptedConcordRotations = ConcurrentSet<String>()
|
||||
|
||||
/**
|
||||
* Persist a rotated access root/epoch for [entry], keeping the prior root as a
|
||||
@@ -1341,7 +1342,7 @@ class AccountConcordActions(
|
||||
// Last time we re-resolved each community's invite_ref, so the recovery sweep rides the
|
||||
// Concord revision tick (which fires on every structural change) without turning it into a
|
||||
// relay-fetch loop.
|
||||
private val lastConcordRecoveryCheck = ConcurrentHashMap<String, Long>()
|
||||
private val lastConcordRecoveryCheck = ConcurrentMap<String, Long>()
|
||||
|
||||
/**
|
||||
* Stranded recovery (CORD-05/06 receive path). A Refounding carries only
|
||||
|
||||
@@ -18,6 +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.
|
||||
*/
|
||||
@file:OptIn(ExperimentalUuidApi::class)
|
||||
|
||||
package com.vitorpamplona.amethyst.model
|
||||
|
||||
import androidx.compose.runtime.Stable
|
||||
@@ -92,6 +94,8 @@ import kotlinx.coroutines.flow.StateFlow
|
||||
import kotlinx.coroutines.flow.map
|
||||
import kotlinx.coroutines.flow.update
|
||||
import kotlinx.serialization.Serializable
|
||||
import kotlin.uuid.ExperimentalUuidApi
|
||||
import kotlin.uuid.Uuid
|
||||
|
||||
val DefaultSignerPermissions =
|
||||
listOf(
|
||||
@@ -596,9 +600,7 @@ class AccountSettings(
|
||||
val entry =
|
||||
NwcWalletEntryNorm(
|
||||
id =
|
||||
java.util.UUID
|
||||
.randomUUID()
|
||||
.toString(),
|
||||
Uuid.random().toString(),
|
||||
name = "Wallet",
|
||||
uri = newServer,
|
||||
)
|
||||
|
||||
+2
-2
@@ -23,10 +23,10 @@ package com.vitorpamplona.amethyst.model
|
||||
import com.vitorpamplona.amethyst.commons.model.navigation.BottomBarEntry
|
||||
import com.vitorpamplona.amethyst.commons.model.navigation.DefaultBottomBarEntries
|
||||
import com.vitorpamplona.amethyst.commons.service.pow.PoWCategory
|
||||
import com.vitorpamplona.amethyst.commons.util.getDefaultLanguageCode
|
||||
import com.vitorpamplona.amethyst.commons.util.getLanguagesSpokenByUser
|
||||
import com.vitorpamplona.quartz.nip57Zaps.ZapReceiptEvent
|
||||
import kotlinx.serialization.Serializable
|
||||
import java.util.Locale
|
||||
|
||||
val DefaultReactions =
|
||||
listOf(
|
||||
@@ -204,7 +204,7 @@ class AccountZapPreferencesInternal(
|
||||
class AccountLanguagePreferencesInternal(
|
||||
var dontTranslateFrom: Set<String> = getLanguagesSpokenByUser(),
|
||||
var languagePreferences: Map<String, String> = mapOf(),
|
||||
var translateTo: String = Locale.getDefault().language,
|
||||
var translateTo: String = getDefaultLanguageCode(),
|
||||
)
|
||||
|
||||
@Serializable
|
||||
|
||||
@@ -50,9 +50,9 @@ import com.vitorpamplona.quartz.nip57Zaps.ZapReceiptEvent
|
||||
import com.vitorpamplona.quartz.nip57Zaps.ZapRequestEvent
|
||||
import com.vitorpamplona.quartz.nipB1Bolt12Zaps.builder.Bolt12ZapBuilder
|
||||
import com.vitorpamplona.quartz.nipB1Bolt12Zaps.verify.Bolt12ZapValidation
|
||||
import com.vitorpamplona.quartz.utils.BigDecimal
|
||||
import com.vitorpamplona.quartz.utils.Log
|
||||
import kotlinx.coroutines.launch
|
||||
import java.math.BigDecimal
|
||||
import kotlin.coroutines.cancellation.CancellationException
|
||||
|
||||
private const val ONCHAIN_BACKEND_NOT_CONFIGURED = "Bitcoin chain backend is not configured"
|
||||
|
||||
@@ -28,11 +28,11 @@ import com.vitorpamplona.quartz.nip01Core.crypto.KeyPair
|
||||
import com.vitorpamplona.quartz.nip01Core.signers.NostrSigner
|
||||
import com.vitorpamplona.quartz.nip01Core.signers.NostrSignerInternal
|
||||
import com.vitorpamplona.quartz.utils.RandomInstance
|
||||
import com.vitorpamplona.quartz.utils.concurrent.ConcurrentMap
|
||||
import kotlinx.coroutines.CoroutineScope
|
||||
import kotlinx.coroutines.launch
|
||||
import kotlinx.coroutines.sync.Mutex
|
||||
import kotlinx.coroutines.sync.withLock
|
||||
import java.util.concurrent.ConcurrentHashMap
|
||||
|
||||
/**
|
||||
* The account's anonymous, per-geohash chat identities.
|
||||
@@ -66,7 +66,7 @@ class GeohashChatIdentityState(
|
||||
* `synchronized`, because the store reads it protects are suspending.
|
||||
*/
|
||||
private val mutex = Mutex()
|
||||
private val cache = ConcurrentHashMap<String, KeyPair>()
|
||||
private val cache = ConcurrentMap<String, KeyPair>()
|
||||
|
||||
@Volatile private var loaded: GeohashIdentitySecrets? = null
|
||||
|
||||
|
||||
@@ -32,7 +32,7 @@ import com.vitorpamplona.quartz.utils.TimeUtils
|
||||
import kotlinx.coroutines.CoroutineScope
|
||||
import kotlinx.coroutines.flow.update
|
||||
import kotlinx.coroutines.launch
|
||||
import java.util.Base64
|
||||
import kotlin.io.encoding.Base64
|
||||
|
||||
class OtsState(
|
||||
val signer: NostrSigner,
|
||||
@@ -58,7 +58,7 @@ class OtsState(
|
||||
Log.d("Pending Attestations") { "Updating ${settings.pendingAttestations.value.size} pending attestations" }
|
||||
|
||||
return settings.pendingAttestations.value.toList().mapNotNull { (key, value) ->
|
||||
val otsState = OtsEvent.upgrade(Base64.getDecoder().decode(value), key, otsResolver())
|
||||
val otsState = OtsEvent.upgrade(Base64.decode(value), key, otsResolver())
|
||||
|
||||
if (otsState != null) {
|
||||
val hint = cache.getNoteIfExists(key)?.toEventHint<Event>()
|
||||
@@ -93,7 +93,7 @@ class OtsState(
|
||||
settings.addPendingAttestation(
|
||||
id = id,
|
||||
stamp =
|
||||
Base64.getEncoder().encodeToString(
|
||||
Base64.encode(
|
||||
OtsEvent.stamp(
|
||||
id,
|
||||
otsResolver(),
|
||||
|
||||
+6
-3
@@ -18,6 +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.
|
||||
*/
|
||||
@file:OptIn(ExperimentalUuidApi::class)
|
||||
|
||||
package com.vitorpamplona.amethyst.model.nip51Lists.followSets
|
||||
|
||||
import com.vitorpamplona.amethyst.commons.model.AddressableNote
|
||||
@@ -55,7 +57,8 @@ import kotlinx.coroutines.flow.onStart
|
||||
import kotlinx.coroutines.flow.stateIn
|
||||
import kotlinx.coroutines.flow.transformLatest
|
||||
import kotlinx.coroutines.flow.update
|
||||
import java.util.UUID
|
||||
import kotlin.uuid.ExperimentalUuidApi
|
||||
import kotlin.uuid.Uuid
|
||||
|
||||
/**
|
||||
* Maintains several stateflows for each step in processing PeopleLists
|
||||
@@ -205,7 +208,7 @@ class FollowSetsState(
|
||||
isPrivate: Boolean = false,
|
||||
account: Account,
|
||||
): String {
|
||||
val dTag = UUID.randomUUID().toString()
|
||||
val dTag = Uuid.random().toString()
|
||||
val newListTemplate =
|
||||
FollowSetEvent.build(
|
||||
dTag = dTag,
|
||||
@@ -253,7 +256,7 @@ class FollowSetsState(
|
||||
) {
|
||||
val newList =
|
||||
FollowSetEvent.createListWithDescription(
|
||||
dTag = UUID.randomUUID().toString(),
|
||||
dTag = Uuid.random().toString(),
|
||||
title = customCloneName ?: currentPeopleList.title,
|
||||
description = customCloneDescription ?: currentPeopleList.description,
|
||||
publicMembers = currentPeopleList.publicMembers.toUserTags(),
|
||||
|
||||
+6
-3
@@ -18,6 +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.
|
||||
*/
|
||||
@file:OptIn(ExperimentalUuidApi::class)
|
||||
|
||||
package com.vitorpamplona.amethyst.model.nip51Lists.followSets
|
||||
|
||||
import com.vitorpamplona.amethyst.commons.model.AddressableNote
|
||||
@@ -58,7 +60,8 @@ import kotlinx.coroutines.flow.onStart
|
||||
import kotlinx.coroutines.flow.stateIn
|
||||
import kotlinx.coroutines.flow.transformLatest
|
||||
import kotlinx.coroutines.flow.update
|
||||
import java.util.UUID
|
||||
import kotlin.uuid.ExperimentalUuidApi
|
||||
import kotlin.uuid.Uuid
|
||||
|
||||
/**
|
||||
* Maintains several stateflows for each step in processing PeopleLists
|
||||
@@ -195,7 +198,7 @@ class StarterPacksState(
|
||||
isPrivate: Boolean = false,
|
||||
account: Account,
|
||||
): String {
|
||||
val dTag = UUID.randomUUID().toString()
|
||||
val dTag = Uuid.random().toString()
|
||||
|
||||
val newListTemplate =
|
||||
StarterPackEvent.build(
|
||||
@@ -245,7 +248,7 @@ class StarterPacksState(
|
||||
val template =
|
||||
listEvent.update {
|
||||
// new list
|
||||
dTag(UUID.randomUUID().toString())
|
||||
dTag(Uuid.random().toString())
|
||||
|
||||
// updates names
|
||||
if (customCloneName != null) title(customCloneName)
|
||||
|
||||
+3
@@ -22,6 +22,7 @@ package com.vitorpamplona.amethyst.commons.util
|
||||
|
||||
import android.content.res.Resources
|
||||
import androidx.core.os.ConfigurationCompat
|
||||
import java.util.Locale
|
||||
|
||||
actual fun getLanguagesSpokenByUser(): Set<String> {
|
||||
val languageList = ConfigurationCompat.getLocales(Resources.getSystem().configuration)
|
||||
@@ -31,3 +32,5 @@ actual fun getLanguagesSpokenByUser(): Set<String> {
|
||||
}
|
||||
return codedList
|
||||
}
|
||||
|
||||
actual fun getDefaultLanguageCode(): String = Locale.getDefault().language
|
||||
|
||||
+3
@@ -25,3 +25,6 @@ package com.vitorpamplona.amethyst.commons.util
|
||||
* device, in no particular order. New accounts default to not translating from these.
|
||||
*/
|
||||
expect fun getLanguagesSpokenByUser(): Set<String>
|
||||
|
||||
/** The ISO 639 code of the device's current language, the default target for translations. */
|
||||
expect fun getDefaultLanguageCode(): String
|
||||
|
||||
+4
@@ -21,6 +21,8 @@
|
||||
package com.vitorpamplona.amethyst.commons.util
|
||||
|
||||
import platform.Foundation.NSLocale
|
||||
import platform.Foundation.currentLocale
|
||||
import platform.Foundation.languageCode
|
||||
import platform.Foundation.preferredLanguages
|
||||
|
||||
// preferredLanguages holds BCP 47 tags ("pt-BR", "zh-Hans-CN"); the language code is the first subtag.
|
||||
@@ -29,3 +31,5 @@ actual fun getLanguagesSpokenByUser(): Set<String> =
|
||||
.mapNotNull { (it as? String)?.substringBefore('-')?.lowercase() }
|
||||
.filter { it.isNotEmpty() }
|
||||
.toSet()
|
||||
|
||||
actual fun getDefaultLanguageCode(): String = NSLocale.currentLocale.languageCode
|
||||
|
||||
+2
@@ -24,3 +24,5 @@ import java.util.Locale
|
||||
|
||||
// The JVM exposes one default locale, not the OS's ordered preference list.
|
||||
actual fun getLanguagesSpokenByUser(): Set<String> = setOf(Locale.getDefault().language)
|
||||
|
||||
actual fun getDefaultLanguageCode(): String = Locale.getDefault().language
|
||||
|
||||
Reference in New Issue
Block a user