Unnecessary ?. / ?: / !! on non-null
Missing @OptIn annotations Parameter name mismatches Icons.Filled.* / Icons.AutoMirrored.* No cast needed / remove inline LocalLifecycleOwner import fix NIP-51 name() → title() Chess gameId → startEventId Nullable DecimalFormat safe calls DelicateCoroutinesApi opt-in
This commit is contained in:
@@ -2016,6 +2016,7 @@ class Account(
|
|||||||
}
|
}
|
||||||
|
|
||||||
scope.launch(Dispatchers.IO) {
|
scope.launch(Dispatchers.IO) {
|
||||||
|
@OptIn(kotlinx.coroutines.FlowPreview::class)
|
||||||
settings.saveable.debounce(1000).collect {
|
settings.saveable.debounce(1000).collect {
|
||||||
if (it.accountSettings != null) {
|
if (it.accountSettings != null) {
|
||||||
LocalPreferences.saveToEncryptedStorage(it.accountSettings)
|
LocalPreferences.saveToEncryptedStorage(it.accountSettings)
|
||||||
|
|||||||
@@ -358,19 +358,19 @@ object LocalCache : ILocalCache, ICacheProvider {
|
|||||||
|
|
||||||
fun load(keys: Set<String>): Set<User> = keys.mapNotNullTo(mutableSetOf(), ::checkGetOrCreateUser)
|
fun load(keys: Set<String>): Set<User> = keys.mapNotNullTo(mutableSetOf(), ::checkGetOrCreateUser)
|
||||||
|
|
||||||
override fun getOrCreateUser(key: HexKey): User {
|
override fun getOrCreateUser(pubkey: HexKey): User {
|
||||||
require(isValidHex(key = key)) { "$key is not a valid hex" }
|
require(isValidHex(key = pubkey)) { "$pubkey is not a valid hex" }
|
||||||
|
|
||||||
return users.getOrCreate(key) {
|
return users.getOrCreate(pubkey) {
|
||||||
val nip65RelayListNote = getOrCreateAddressableNoteInternal(AdvertisedRelayListEvent.createAddress(key))
|
val nip65RelayListNote = getOrCreateAddressableNoteInternal(AdvertisedRelayListEvent.createAddress(pubkey))
|
||||||
val dmRelayListNote = getOrCreateAddressableNoteInternal(ChatMessageRelayListEvent.createAddress(key))
|
val dmRelayListNote = getOrCreateAddressableNoteInternal(ChatMessageRelayListEvent.createAddress(pubkey))
|
||||||
User(it, nip65RelayListNote, dmRelayListNote)
|
User(it, nip65RelayListNote, dmRelayListNote)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun getUserIfExists(key: String): User? {
|
override fun getUserIfExists(pubkey: String): User? {
|
||||||
if (key.isEmpty()) return null
|
if (pubkey.isEmpty()) return null
|
||||||
return users.get(key)
|
return users.get(pubkey)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun countUsers(predicate: (String, User) -> Boolean): Int {
|
override fun countUsers(predicate: (String, User) -> Boolean): Int {
|
||||||
@@ -394,7 +394,7 @@ object LocalCache : ILocalCache, ICacheProvider {
|
|||||||
|
|
||||||
fun getAddressableNoteIfExists(address: Address): AddressableNote? = addressables.get(address)
|
fun getAddressableNoteIfExists(address: Address): AddressableNote? = addressables.get(address)
|
||||||
|
|
||||||
override fun getNoteIfExists(key: String): Note? = if (key.length == 64) notes.get(key) else Address.parse(key)?.let { addressables.get(it) }
|
override fun getNoteIfExists(hexKey: String): Note? = if (hexKey.length == 64) notes.get(hexKey) else Address.parse(hexKey)?.let { addressables.get(it) }
|
||||||
|
|
||||||
fun getNoteIfExists(key: ETag): Note? = notes.get(key.eventId)
|
fun getNoteIfExists(key: ETag): Note? = notes.get(key.eventId)
|
||||||
|
|
||||||
@@ -2250,6 +2250,7 @@ object LocalCache : ILocalCache, ICacheProvider {
|
|||||||
|
|
||||||
requestNote?.let { request -> zappedNote?.addZapPayment(request, note) }
|
requestNote?.let { request -> zappedNote?.addZapPayment(request, note) }
|
||||||
|
|
||||||
|
@OptIn(kotlinx.coroutines.DelicateCoroutinesApi::class)
|
||||||
GlobalScope.launch(Dispatchers.IO) {
|
GlobalScope.launch(Dispatchers.IO) {
|
||||||
responseCallback(event)
|
responseCallback(event)
|
||||||
}
|
}
|
||||||
|
|||||||
+1
-1
@@ -114,7 +114,7 @@ class NwcSignerState(
|
|||||||
|
|
||||||
fun hasWalletConnectSetup(): Boolean = nip47Setup.value != null
|
fun hasWalletConnectSetup(): Boolean = nip47Setup.value != null
|
||||||
|
|
||||||
override fun isNIP47Author(pubkey: HexKey?): Boolean = nip47Signer.value.pubKey == pubkey
|
override fun isNIP47Author(pubKey: HexKey?): Boolean = nip47Signer.value.pubKey == pubKey
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Decrypts a NIP-47 payment request using the current signer.
|
* Decrypts a NIP-47 payment request using the current signer.
|
||||||
|
|||||||
+2
-2
@@ -36,7 +36,7 @@ import com.vitorpamplona.quartz.nip51Lists.bookmarkList.tags.BookmarkIdTag
|
|||||||
import com.vitorpamplona.quartz.nip51Lists.labeledBookmarkList.LabeledBookmarkListEvent
|
import com.vitorpamplona.quartz.nip51Lists.labeledBookmarkList.LabeledBookmarkListEvent
|
||||||
import com.vitorpamplona.quartz.nip51Lists.labeledBookmarkList.description
|
import com.vitorpamplona.quartz.nip51Lists.labeledBookmarkList.description
|
||||||
import com.vitorpamplona.quartz.nip51Lists.labeledBookmarkList.image
|
import com.vitorpamplona.quartz.nip51Lists.labeledBookmarkList.image
|
||||||
import com.vitorpamplona.quartz.nip51Lists.labeledBookmarkList.name
|
import com.vitorpamplona.quartz.nip51Lists.labeledBookmarkList.title
|
||||||
import kotlinx.coroutines.CoroutineScope
|
import kotlinx.coroutines.CoroutineScope
|
||||||
import kotlinx.coroutines.Dispatchers
|
import kotlinx.coroutines.Dispatchers
|
||||||
import kotlinx.coroutines.ExperimentalCoroutinesApi
|
import kotlinx.coroutines.ExperimentalCoroutinesApi
|
||||||
@@ -181,7 +181,7 @@ class LabeledBookmarkListsState(
|
|||||||
|
|
||||||
val template =
|
val template =
|
||||||
listEvent.update {
|
listEvent.update {
|
||||||
if (listName != null) name(listName)
|
if (listName != null) title(listName)
|
||||||
if (listDescription != null) description(listDescription)
|
if (listDescription != null) description(listDescription)
|
||||||
if (listImage != null) image(listImage)
|
if (listImage != null) image(listImage)
|
||||||
}
|
}
|
||||||
|
|||||||
+2
-2
@@ -38,7 +38,7 @@ import com.vitorpamplona.quartz.nip51Lists.muteList.tags.UserTag
|
|||||||
import com.vitorpamplona.quartz.nip51Lists.peopleList.PeopleListEvent
|
import com.vitorpamplona.quartz.nip51Lists.peopleList.PeopleListEvent
|
||||||
import com.vitorpamplona.quartz.nip51Lists.peopleList.description
|
import com.vitorpamplona.quartz.nip51Lists.peopleList.description
|
||||||
import com.vitorpamplona.quartz.nip51Lists.peopleList.image
|
import com.vitorpamplona.quartz.nip51Lists.peopleList.image
|
||||||
import com.vitorpamplona.quartz.nip51Lists.peopleList.name
|
import com.vitorpamplona.quartz.nip51Lists.peopleList.title
|
||||||
import com.vitorpamplona.quartz.utils.flattenToSet
|
import com.vitorpamplona.quartz.utils.flattenToSet
|
||||||
import kotlinx.coroutines.CoroutineScope
|
import kotlinx.coroutines.CoroutineScope
|
||||||
import kotlinx.coroutines.Dispatchers
|
import kotlinx.coroutines.Dispatchers
|
||||||
@@ -226,7 +226,7 @@ class PeopleListsState(
|
|||||||
|
|
||||||
val template =
|
val template =
|
||||||
listEvent.update {
|
listEvent.update {
|
||||||
if (listName != null) name(listName)
|
if (listName != null) title(listName)
|
||||||
if (listDescription != null) description(listDescription)
|
if (listDescription != null) description(listDescription)
|
||||||
if (listImage != null) image(listImage)
|
if (listImage != null) image(listImage)
|
||||||
}
|
}
|
||||||
|
|||||||
+1
@@ -79,6 +79,7 @@ class MergedFollowListsState(
|
|||||||
communities = community.mapTo(mutableSetOf()) { it.address.toValue() },
|
communities = community.mapTo(mutableSetOf()) { it.address.toValue() },
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@OptIn(kotlinx.coroutines.FlowPreview::class)
|
||||||
val flow: StateFlow<AllFollows> =
|
val flow: StateFlow<AllFollows> =
|
||||||
combine(
|
combine(
|
||||||
listOf(
|
listOf(
|
||||||
|
|||||||
@@ -20,6 +20,7 @@
|
|||||||
*/
|
*/
|
||||||
package com.vitorpamplona.amethyst.service.cashu.v4
|
package com.vitorpamplona.amethyst.service.cashu.v4
|
||||||
|
|
||||||
|
import kotlinx.serialization.ExperimentalSerializationApi
|
||||||
import kotlinx.serialization.Serializable
|
import kotlinx.serialization.Serializable
|
||||||
import kotlinx.serialization.cbor.ByteString
|
import kotlinx.serialization.cbor.ByteString
|
||||||
|
|
||||||
@@ -34,6 +35,7 @@ class V4Token(
|
|||||||
val t: Array<V4T>?,
|
val t: Array<V4T>?,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@OptIn(ExperimentalSerializationApi::class)
|
||||||
@Serializable
|
@Serializable
|
||||||
class V4T(
|
class V4T(
|
||||||
// identifier
|
// identifier
|
||||||
@@ -42,6 +44,7 @@ class V4T(
|
|||||||
val p: Array<V4Proof>,
|
val p: Array<V4Proof>,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@OptIn(ExperimentalSerializationApi::class)
|
||||||
@Serializable
|
@Serializable
|
||||||
class V4Proof(
|
class V4Proof(
|
||||||
// amount
|
// amount
|
||||||
@@ -57,6 +60,7 @@ class V4Proof(
|
|||||||
val w: String? = null,
|
val w: String? = null,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@OptIn(ExperimentalSerializationApi::class)
|
||||||
@Serializable
|
@Serializable
|
||||||
class V4DleqProof(
|
class V4DleqProof(
|
||||||
@ByteString
|
@ByteString
|
||||||
|
|||||||
+3
-3
@@ -51,14 +51,14 @@ class EventWatcherSubAssembler(
|
|||||||
}
|
}
|
||||||
|
|
||||||
override fun updateFilter(
|
override fun updateFilter(
|
||||||
key: List<EventFinderQueryState>,
|
keys: List<EventFinderQueryState>,
|
||||||
since: SincePerRelayMap?,
|
since: SincePerRelayMap?,
|
||||||
): List<RelayBasedFilter>? {
|
): List<RelayBasedFilter>? {
|
||||||
if (key.isEmpty()) {
|
if (keys.isEmpty()) {
|
||||||
return null
|
return null
|
||||||
}
|
}
|
||||||
|
|
||||||
lastNotesOnFilter = key.map { it.note }
|
lastNotesOnFilter = keys.map { it.note }
|
||||||
|
|
||||||
return groupByRelayPresence(lastNotesOnFilter, latestEOSEs)
|
return groupByRelayPresence(lastNotesOnFilter, latestEOSEs)
|
||||||
.map { group ->
|
.map { group ->
|
||||||
|
|||||||
+1
-1
@@ -53,7 +53,7 @@ class BlossomServersViewModel : ViewModel() {
|
|||||||
fun refresh() {
|
fun refresh() {
|
||||||
isModified = false
|
isModified = false
|
||||||
_fileServers.update {
|
_fileServers.update {
|
||||||
val obtainedFileServers = obtainFileServers() ?: emptyList()
|
val obtainedFileServers = obtainFileServers()
|
||||||
obtainedFileServers.mapNotNull { serverUrl ->
|
obtainedFileServers.mapNotNull { serverUrl ->
|
||||||
try {
|
try {
|
||||||
ServerName(
|
ServerName(
|
||||||
|
|||||||
@@ -62,7 +62,7 @@ fun BadgeCompose(
|
|||||||
nav: INav,
|
nav: INav,
|
||||||
) {
|
) {
|
||||||
val noteState by observeNote(likeSetCard.note, accountViewModel)
|
val noteState by observeNote(likeSetCard.note, accountViewModel)
|
||||||
val note = noteState?.note
|
val note = noteState.note
|
||||||
|
|
||||||
val context = LocalContext.current.applicationContext
|
val context = LocalContext.current.applicationContext
|
||||||
|
|
||||||
|
|||||||
@@ -30,10 +30,10 @@ import androidx.compose.runtime.remember
|
|||||||
import androidx.compose.ui.Modifier
|
import androidx.compose.ui.Modifier
|
||||||
import androidx.compose.ui.graphics.Color
|
import androidx.compose.ui.graphics.Color
|
||||||
import androidx.compose.ui.platform.LocalContext
|
import androidx.compose.ui.platform.LocalContext
|
||||||
import androidx.compose.ui.platform.LocalLifecycleOwner
|
|
||||||
import androidx.compose.ui.text.font.FontWeight
|
import androidx.compose.ui.text.font.FontWeight
|
||||||
import androidx.compose.ui.text.style.TextOverflow
|
import androidx.compose.ui.text.style.TextOverflow
|
||||||
import androidx.lifecycle.LifecycleOwner
|
import androidx.lifecycle.LifecycleOwner
|
||||||
|
import androidx.lifecycle.compose.LocalLifecycleOwner
|
||||||
import com.vitorpamplona.amethyst.commons.model.ImmutableListOfLists
|
import com.vitorpamplona.amethyst.commons.model.ImmutableListOfLists
|
||||||
import com.vitorpamplona.amethyst.model.Note
|
import com.vitorpamplona.amethyst.model.Note
|
||||||
import com.vitorpamplona.amethyst.model.User
|
import com.vitorpamplona.amethyst.model.User
|
||||||
|
|||||||
@@ -49,10 +49,10 @@ fun showAmountInteger(amount: BigDecimal?): String {
|
|||||||
if (amount.abs() < BigDecimal(0.01)) return ""
|
if (amount.abs() < BigDecimal(0.01)) return ""
|
||||||
|
|
||||||
return when {
|
return when {
|
||||||
amount >= OneGiga -> dfG.get().format(amount.div(OneGiga).setScale(0, RoundingMode.HALF_UP))
|
amount >= OneGiga -> dfG.get()?.format(amount.div(OneGiga).setScale(0, RoundingMode.HALF_UP)) ?: ""
|
||||||
amount >= OneMega -> dfM.get().format(amount.div(OneMega).setScale(0, RoundingMode.HALF_UP))
|
amount >= OneMega -> dfM.get()?.format(amount.div(OneMega).setScale(0, RoundingMode.HALF_UP)) ?: ""
|
||||||
amount >= TenKilo -> dfK.get().format(amount.div(OneKilo).setScale(0, RoundingMode.HALF_UP))
|
amount >= TenKilo -> dfK.get()?.format(amount.div(OneKilo).setScale(0, RoundingMode.HALF_UP)) ?: ""
|
||||||
else -> dfN.get().format(amount)
|
else -> dfN.get()?.format(amount) ?: ""
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -118,13 +118,13 @@ class PollNoteViewModel : ViewModel() {
|
|||||||
it.zappedValue.value = zappedValue
|
it.zappedValue.value = zappedValue
|
||||||
it.tally.value = tallyValue.toFloat()
|
it.tally.value = tallyValue.toFloat()
|
||||||
it.consensusThreadhold.value = consensusThreshold != null && tallyValue >= consensusThreshold!!
|
it.consensusThreadhold.value = consensusThreshold != null && tallyValue >= consensusThreshold!!
|
||||||
it.zappedByLoggedIn.value = account?.userProfile()?.let { it1 -> cachedIsPollOptionZappedBy(it.option, it1) } ?: false
|
it.zappedByLoggedIn.value = account.userProfile().let { it1 -> cachedIsPollOptionZappedBy(it.option, it1) }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fun checkIfCanZap(): Boolean {
|
fun checkIfCanZap(): Boolean {
|
||||||
val account = account ?: return false
|
val account = account
|
||||||
val note = pollNote ?: return false
|
val note = pollNote ?: return false
|
||||||
return account.userProfile() != note.author && !wasZappedByLoggedInAccount
|
return account.userProfile() != note.author && !wasZappedByLoggedInAccount
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -96,7 +96,7 @@ fun RenderLiveChessChallenge(
|
|||||||
nav: INav,
|
nav: INav,
|
||||||
) {
|
) {
|
||||||
val event = (note.event as? LiveChessGameChallengeEvent) ?: return
|
val event = (note.event as? LiveChessGameChallengeEvent) ?: return
|
||||||
val gameId = event.gameId() ?: return
|
val gameId = event.gameId()
|
||||||
|
|
||||||
val chessViewModel: ChessViewModelNew =
|
val chessViewModel: ChessViewModelNew =
|
||||||
viewModel(
|
viewModel(
|
||||||
|
|||||||
@@ -72,9 +72,9 @@ private fun ObserverAndRenderNIP95(
|
|||||||
val content by
|
val content by
|
||||||
remember(noteState) {
|
remember(noteState) {
|
||||||
// Creates a new object when the event arrives to force an update of the image.
|
// Creates a new object when the event arrives to force an update of the image.
|
||||||
val note = noteState?.note
|
val note = noteState.note
|
||||||
val uri = header.toNostrUri()
|
val uri = header.toNostrUri()
|
||||||
val localDir = note?.idHex?.let { File(Amethyst.instance.nip95cache, it) }
|
val localDir = note.idHex.let { File(Amethyst.instance.nip95cache, it) }
|
||||||
val blurHash = eventHeader.blurhash()
|
val blurHash = eventHeader.blurhash()
|
||||||
val dimensions = eventHeader.dimensions()
|
val dimensions = eventHeader.dimensions()
|
||||||
val description = eventHeader.alt() ?: eventHeader.content
|
val description = eventHeader.alt() ?: eventHeader.content
|
||||||
|
|||||||
@@ -163,7 +163,7 @@ fun RenderTextModificationEvent(
|
|||||||
}
|
}
|
||||||
|
|
||||||
LaunchedEffect(key1 = noteState) {
|
LaunchedEffect(key1 = noteState) {
|
||||||
val newAuthor = accountViewModel.isLoggedUser(noteState?.note?.author)
|
val newAuthor = accountViewModel.isLoggedUser(noteState.note.author)
|
||||||
|
|
||||||
if (isAuthorTheLoggedUser.value != newAuthor) {
|
if (isAuthorTheLoggedUser.value != newAuthor) {
|
||||||
isAuthorTheLoggedUser.value = newAuthor
|
isAuthorTheLoggedUser.value = newAuthor
|
||||||
|
|||||||
+2
-2
@@ -104,7 +104,7 @@ class ChannelMetadataViewModel : ViewModel() {
|
|||||||
|
|
||||||
fun createOrUpdate(onDone: (PublicChatChannel) -> Unit) {
|
fun createOrUpdate(onDone: (PublicChatChannel) -> Unit) {
|
||||||
viewModelScope.launch(Dispatchers.IO) {
|
viewModelScope.launch(Dispatchers.IO) {
|
||||||
account?.let { account ->
|
account.let { account ->
|
||||||
val channel = originalChannel
|
val channel = originalChannel
|
||||||
if (channel == null) {
|
if (channel == null) {
|
||||||
val template =
|
val template =
|
||||||
@@ -204,7 +204,7 @@ class ChannelMetadataViewModel : ViewModel() {
|
|||||||
onUploaded: (String) -> Unit,
|
onUploaded: (String) -> Unit,
|
||||||
onError: (String, String) -> Unit,
|
onError: (String, String) -> Unit,
|
||||||
) {
|
) {
|
||||||
val account = account ?: return
|
val account = account
|
||||||
onUploading(true)
|
onUploading(true)
|
||||||
|
|
||||||
val compResult = MediaCompressor().compress(galleryUri.uri, galleryUri.mimeType, CompressorQuality.MEDIUM, context.applicationContext)
|
val compResult = MediaCompressor().compress(galleryUri.uri, galleryUri.mimeType, CompressorQuality.MEDIUM, context.applicationContext)
|
||||||
|
|||||||
+7
-10
@@ -220,7 +220,7 @@ open class NewProductViewModel :
|
|||||||
}
|
}
|
||||||
|
|
||||||
open fun quote(quote: Note) {
|
open fun quote(quote: Note) {
|
||||||
val accountViewModel = accountViewModel ?: return
|
val accountViewModel = accountViewModel
|
||||||
|
|
||||||
message = TextFieldValue(message.text + "\nnostr:${quote.toNEvent()}")
|
message = TextFieldValue(message.text + "\nnostr:${quote.toNEvent()}")
|
||||||
|
|
||||||
@@ -307,7 +307,6 @@ open class NewProductViewModel :
|
|||||||
}
|
}
|
||||||
|
|
||||||
suspend fun sendPostSync() {
|
suspend fun sendPostSync() {
|
||||||
val accountViewModel = accountViewModel ?: return
|
|
||||||
val template = createTemplate() ?: return
|
val template = createTemplate() ?: return
|
||||||
|
|
||||||
val version = draftTag.current
|
val version = draftTag.current
|
||||||
@@ -320,8 +319,6 @@ open class NewProductViewModel :
|
|||||||
}
|
}
|
||||||
|
|
||||||
suspend fun sendDraftSync() {
|
suspend fun sendDraftSync() {
|
||||||
val accountViewModel = accountViewModel ?: return
|
|
||||||
|
|
||||||
if (message.text.isBlank()) {
|
if (message.text.isBlank()) {
|
||||||
accountViewModel.account.deleteDraftIgnoreErrors(draftTag.current)
|
accountViewModel.account.deleteDraftIgnoreErrors(draftTag.current)
|
||||||
} else {
|
} else {
|
||||||
@@ -331,7 +328,7 @@ open class NewProductViewModel :
|
|||||||
}
|
}
|
||||||
|
|
||||||
private suspend fun createTemplate(): EventTemplate<out Event>? {
|
private suspend fun createTemplate(): EventTemplate<out Event>? {
|
||||||
val accountViewModel = accountViewModel ?: return null
|
val accountViewModel = accountViewModel
|
||||||
|
|
||||||
val tagger =
|
val tagger =
|
||||||
NewMessageTagger(
|
NewMessageTagger(
|
||||||
@@ -340,7 +337,7 @@ open class NewProductViewModel :
|
|||||||
)
|
)
|
||||||
tagger.run()
|
tagger.run()
|
||||||
|
|
||||||
val emojis = findEmoji(tagger.message, account?.emoji?.myEmojis?.value)
|
val emojis = findEmoji(tagger.message, account.emoji.myEmojis.value)
|
||||||
val urls = findURLs(tagger.message)
|
val urls = findURLs(tagger.message)
|
||||||
val usedAttachments = iMetaDescription.filterIsIn(urls.toSet()) + productImages.map { it.toIMeta() }
|
val usedAttachments = iMetaDescription.filterIsIn(urls.toSet()) + productImages.map { it.toIMeta() }
|
||||||
|
|
||||||
@@ -399,7 +396,7 @@ open class NewProductViewModel :
|
|||||||
context: Context,
|
context: Context,
|
||||||
) {
|
) {
|
||||||
viewModelScope.launch(Dispatchers.IO) {
|
viewModelScope.launch(Dispatchers.IO) {
|
||||||
val myAccount = account ?: return@launch
|
val myAccount = account
|
||||||
val myMultiOrchestrator = multiOrchestrator ?: return@launch
|
val myMultiOrchestrator = multiOrchestrator ?: return@launch
|
||||||
|
|
||||||
mediaUploadTracker.startUpload(myMultiOrchestrator.hasNonMedia())
|
mediaUploadTracker.startUpload(myMultiOrchestrator.hasNonMedia())
|
||||||
@@ -501,8 +498,8 @@ open class NewProductViewModel :
|
|||||||
this.multiOrchestrator?.remove(selected)
|
this.multiOrchestrator?.remove(selected)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun updateMessage(it: TextFieldValue) {
|
override fun updateMessage(newMessage: TextFieldValue) {
|
||||||
message = it
|
message = newMessage
|
||||||
urlPreviews.update(message)
|
urlPreviews.update(message)
|
||||||
|
|
||||||
if (message.selection.collapsed) {
|
if (message.selection.collapsed) {
|
||||||
@@ -616,7 +613,7 @@ open class NewProductViewModel :
|
|||||||
|
|
||||||
override fun updateZapFromText() {
|
override fun updateZapFromText() {
|
||||||
viewModelScope.launch(Dispatchers.IO) {
|
viewModelScope.launch(Dispatchers.IO) {
|
||||||
val tagger = NewMessageTagger(message.text, emptyList(), emptyList(), accountViewModel!!)
|
val tagger = NewMessageTagger(message.text, emptyList(), emptyList(), accountViewModel)
|
||||||
tagger.run()
|
tagger.run()
|
||||||
tagger.pTags?.forEach { taggedUser ->
|
tagger.pTags?.forEach { taggedUser ->
|
||||||
if (!forwardZapTo.value.items.any { it.key == taggedUser }) {
|
if (!forwardZapTo.value.items.any { it.key == taggedUser }) {
|
||||||
|
|||||||
+3
-3
@@ -322,7 +322,7 @@ class NewPublicMessageViewModel :
|
|||||||
}
|
}
|
||||||
|
|
||||||
suspend fun sendPostSync() {
|
suspend fun sendPostSync() {
|
||||||
val template = createTemplate() ?: return
|
val template = createTemplate()
|
||||||
val extraNotesToBroadcast = mutableListOf<Event>()
|
val extraNotesToBroadcast = mutableListOf<Event>()
|
||||||
|
|
||||||
if (nip95attachments.isNotEmpty()) {
|
if (nip95attachments.isNotEmpty()) {
|
||||||
@@ -354,7 +354,7 @@ class NewPublicMessageViewModel :
|
|||||||
broadcast.add(it.second)
|
broadcast.add(it.second)
|
||||||
}
|
}
|
||||||
|
|
||||||
val template = createTemplate() ?: return
|
val template = createTemplate()
|
||||||
accountViewModel.account.createAndSendDraftIgnoreErrors(draftTag.current, template, broadcast)
|
accountViewModel.account.createAndSendDraftIgnoreErrors(draftTag.current, template, broadcast)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -459,7 +459,7 @@ class NewPublicMessageViewModel :
|
|||||||
if (state.result is UploadOrchestrator.OrchestratorResult.NIP95Result) {
|
if (state.result is UploadOrchestrator.OrchestratorResult.NIP95Result) {
|
||||||
val nip95 = account.createNip95(state.result.bytes, headerInfo = state.result.fileHeader, alt, contentWarningReason)
|
val nip95 = account.createNip95(state.result.bytes, headerInfo = state.result.fileHeader, alt, contentWarningReason)
|
||||||
nip95attachments = nip95attachments + nip95
|
nip95attachments = nip95attachments + nip95
|
||||||
val note = nip95.let { it1 -> account?.consumeNip95(it1.first, it1.second) }
|
val note = nip95.let { it1 -> account.consumeNip95(it1.first, it1.second) }
|
||||||
|
|
||||||
note?.let {
|
note?.let {
|
||||||
message = message.insertUrlAtCursor("nostr:" + it.toNEvent())
|
message = message.insertUrlAtCursor("nostr:" + it.toNEvent())
|
||||||
|
|||||||
+1
@@ -63,6 +63,7 @@ class UserProfileFollowersUserFeedViewModel(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@OptIn(kotlinx.coroutines.FlowPreview::class)
|
||||||
val followersFlow: StateFlow<List<User>> =
|
val followersFlow: StateFlow<List<User>> =
|
||||||
account.cache
|
account.cache
|
||||||
.observeEvents(followerFilter)
|
.observeEvents(followerFilter)
|
||||||
|
|||||||
+1
@@ -55,6 +55,7 @@ class UserProfileFollowsUserFeedViewModel(
|
|||||||
return LocalCache.load(nonHiddenFollows).sortedWith(sortingModel)
|
return LocalCache.load(nonHiddenFollows).sortedWith(sortingModel)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@OptIn(kotlinx.coroutines.FlowPreview::class)
|
||||||
val followsFlow: StateFlow<List<User>> =
|
val followsFlow: StateFlow<List<User>> =
|
||||||
contactList
|
contactList
|
||||||
.flow()
|
.flow()
|
||||||
|
|||||||
+1
-1
@@ -56,7 +56,7 @@ fun WatchApp(
|
|||||||
|
|
||||||
LaunchedEffect(key1 = appState) {
|
LaunchedEffect(key1 = appState) {
|
||||||
withContext(Dispatchers.IO) {
|
withContext(Dispatchers.IO) {
|
||||||
(appState?.note?.event as? AppDefinitionEvent)?.appMetaData()?.let { metaData ->
|
(appState.note.event as? AppDefinitionEvent)?.appMetaData()?.let { metaData ->
|
||||||
metaData.picture?.ifBlank { null }?.let { newLogo ->
|
metaData.picture?.ifBlank { null }?.let { newLogo ->
|
||||||
if (newLogo != appLogo) appLogo = newLogo
|
if (newLogo != appLogo) appLogo = newLogo
|
||||||
}
|
}
|
||||||
|
|||||||
+1
@@ -112,6 +112,7 @@ class UserProfileZapsViewModel(
|
|||||||
return results.map { (user, amount) -> ZapAmount(user, amount) }.sortedWith(sortingModel)
|
return results.map { (user, amount) -> ZapAmount(user, amount) }.sortedWith(sortingModel)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@OptIn(kotlinx.coroutines.FlowPreview::class)
|
||||||
val receivedZapAmountsByUser: StateFlow<List<ZapAmount>> =
|
val receivedZapAmountsByUser: StateFlow<List<ZapAmount>> =
|
||||||
account.cache
|
account.cache
|
||||||
.observeEvents(zapsToUser)
|
.observeEvents(zapsToUser)
|
||||||
|
|||||||
+2
-2
@@ -47,6 +47,7 @@ import androidx.compose.material.icons.automirrored.filled.Feed
|
|||||||
import androidx.compose.material.icons.automirrored.filled.Label
|
import androidx.compose.material.icons.automirrored.filled.Label
|
||||||
import androidx.compose.material.icons.automirrored.filled.List
|
import androidx.compose.material.icons.automirrored.filled.List
|
||||||
import androidx.compose.material.icons.automirrored.filled.Message
|
import androidx.compose.material.icons.automirrored.filled.Message
|
||||||
|
import androidx.compose.material.icons.automirrored.filled.Send
|
||||||
import androidx.compose.material.icons.filled.AttachMoney
|
import androidx.compose.material.icons.filled.AttachMoney
|
||||||
import androidx.compose.material.icons.filled.Bolt
|
import androidx.compose.material.icons.filled.Bolt
|
||||||
import androidx.compose.material.icons.filled.Code
|
import androidx.compose.material.icons.filled.Code
|
||||||
@@ -61,7 +62,6 @@ import androidx.compose.material.icons.filled.Language
|
|||||||
import androidx.compose.material.icons.filled.Lock
|
import androidx.compose.material.icons.filled.Lock
|
||||||
import androidx.compose.material.icons.filled.Payment
|
import androidx.compose.material.icons.filled.Payment
|
||||||
import androidx.compose.material.icons.filled.PrivacyTip
|
import androidx.compose.material.icons.filled.PrivacyTip
|
||||||
import androidx.compose.material.icons.filled.Send
|
|
||||||
import androidx.compose.material.icons.filled.Storage
|
import androidx.compose.material.icons.filled.Storage
|
||||||
import androidx.compose.material.icons.filled.Tag
|
import androidx.compose.material.icons.filled.Tag
|
||||||
import androidx.compose.material.icons.filled.Topic
|
import androidx.compose.material.icons.filled.Topic
|
||||||
@@ -931,7 +931,7 @@ private fun OutboxEventsCard(eventIds: Set<HexKey>) {
|
|||||||
horizontalArrangement = Arrangement.spacedBy(4.dp),
|
horizontalArrangement = Arrangement.spacedBy(4.dp),
|
||||||
) {
|
) {
|
||||||
Icon(
|
Icon(
|
||||||
imageVector = Icons.Default.Send,
|
imageVector = Icons.AutoMirrored.Filled.Send,
|
||||||
contentDescription = null,
|
contentDescription = null,
|
||||||
modifier = Modifier.size(12.dp),
|
modifier = Modifier.size(12.dp),
|
||||||
tint = MaterialTheme.colorScheme.onTertiaryContainer,
|
tint = MaterialTheme.colorScheme.onTertiaryContainer,
|
||||||
|
|||||||
+1
@@ -90,6 +90,7 @@ class SearchBarViewModel(
|
|||||||
|
|
||||||
val listState: LazyListState = LazyListState(0, 0)
|
val listState: LazyListState = LazyListState(0, 0)
|
||||||
|
|
||||||
|
@OptIn(kotlinx.coroutines.ExperimentalCoroutinesApi::class)
|
||||||
val directNip05Resolver: Flow<User?> =
|
val directNip05Resolver: Flow<User?> =
|
||||||
searchTerm
|
searchTerm
|
||||||
.debounce(400)
|
.debounce(400)
|
||||||
|
|||||||
+1
-1
@@ -55,7 +55,6 @@ import androidx.compose.runtime.setValue
|
|||||||
import androidx.compose.ui.Alignment
|
import androidx.compose.ui.Alignment
|
||||||
import androidx.compose.ui.Modifier
|
import androidx.compose.ui.Modifier
|
||||||
import androidx.compose.ui.graphics.Color
|
import androidx.compose.ui.graphics.Color
|
||||||
import androidx.compose.ui.platform.LocalLifecycleOwner
|
|
||||||
import androidx.compose.ui.text.font.FontWeight
|
import androidx.compose.ui.text.font.FontWeight
|
||||||
import androidx.compose.ui.text.input.ImeAction
|
import androidx.compose.ui.text.input.ImeAction
|
||||||
import androidx.compose.ui.text.input.KeyboardCapitalization
|
import androidx.compose.ui.text.input.KeyboardCapitalization
|
||||||
@@ -63,6 +62,7 @@ import androidx.compose.ui.text.style.TextAlign
|
|||||||
import androidx.compose.ui.unit.dp
|
import androidx.compose.ui.unit.dp
|
||||||
import androidx.lifecycle.Lifecycle
|
import androidx.lifecycle.Lifecycle
|
||||||
import androidx.lifecycle.LifecycleEventObserver
|
import androidx.lifecycle.LifecycleEventObserver
|
||||||
|
import androidx.lifecycle.compose.LocalLifecycleOwner
|
||||||
import androidx.lifecycle.compose.collectAsStateWithLifecycle
|
import androidx.lifecycle.compose.collectAsStateWithLifecycle
|
||||||
import androidx.lifecycle.viewmodel.compose.viewModel
|
import androidx.lifecycle.viewmodel.compose.viewModel
|
||||||
import com.vitorpamplona.amethyst.R
|
import com.vitorpamplona.amethyst.R
|
||||||
|
|||||||
+1
-1
@@ -99,7 +99,7 @@ class WalletViewModel : ViewModel() {
|
|||||||
|
|
||||||
fun init(account: Account) {
|
fun init(account: Account) {
|
||||||
this.account = account
|
this.account = account
|
||||||
_hasWalletSetup.value = account.nip47SignerState?.hasWalletConnectSetup() == true
|
_hasWalletSetup.value = account.nip47SignerState.hasWalletConnectSetup()
|
||||||
}
|
}
|
||||||
|
|
||||||
fun refreshWalletSetup() {
|
fun refreshWalletSetup() {
|
||||||
|
|||||||
+2
-2
@@ -237,7 +237,7 @@ fun LiveChessGameScreen(
|
|||||||
) {
|
) {
|
||||||
// Game info - use currentPosition.activeColor for turn display
|
// Game info - use currentPosition.activeColor for turn display
|
||||||
GameInfoHeader(
|
GameInfoHeader(
|
||||||
gameId = gameState.gameId,
|
gameId = gameState.startEventId,
|
||||||
opponentName = opponentName,
|
opponentName = opponentName,
|
||||||
playerColor = gameState.playerColor,
|
playerColor = gameState.playerColor,
|
||||||
currentTurn = currentPosition.activeColor,
|
currentTurn = currentPosition.activeColor,
|
||||||
@@ -463,7 +463,7 @@ private fun GameInfoHeader(
|
|||||||
// Show turn or game result
|
// Show turn or game result
|
||||||
when (gameStatus) {
|
when (gameStatus) {
|
||||||
is GameStatus.Finished -> {
|
is GameStatus.Finished -> {
|
||||||
val result = (gameStatus as GameStatus.Finished).result
|
val result = gameStatus.result
|
||||||
val resultText =
|
val resultText =
|
||||||
when {
|
when {
|
||||||
result == GameResult.DRAW -> "Draw"
|
result == GameResult.DRAW -> "Draw"
|
||||||
|
|||||||
+4
-4
@@ -25,8 +25,8 @@ import androidx.compose.foundation.layout.Row
|
|||||||
import androidx.compose.foundation.layout.fillMaxWidth
|
import androidx.compose.foundation.layout.fillMaxWidth
|
||||||
import androidx.compose.foundation.layout.padding
|
import androidx.compose.foundation.layout.padding
|
||||||
import androidx.compose.material.icons.Icons
|
import androidx.compose.material.icons.Icons
|
||||||
import androidx.compose.material.icons.filled.KeyboardArrowLeft
|
import androidx.compose.material.icons.automirrored.filled.KeyboardArrowLeft
|
||||||
import androidx.compose.material.icons.filled.KeyboardArrowRight
|
import androidx.compose.material.icons.automirrored.filled.KeyboardArrowRight
|
||||||
import androidx.compose.material.icons.filled.SkipNext
|
import androidx.compose.material.icons.filled.SkipNext
|
||||||
import androidx.compose.material.icons.filled.SkipPrevious
|
import androidx.compose.material.icons.filled.SkipPrevious
|
||||||
import androidx.compose.material3.Icon
|
import androidx.compose.material3.Icon
|
||||||
@@ -82,7 +82,7 @@ fun MoveNavigator(
|
|||||||
enabled = currentMove > 0,
|
enabled = currentMove > 0,
|
||||||
) {
|
) {
|
||||||
Icon(
|
Icon(
|
||||||
Icons.Default.KeyboardArrowLeft,
|
Icons.AutoMirrored.Filled.KeyboardArrowLeft,
|
||||||
contentDescription = "Previous move",
|
contentDescription = "Previous move",
|
||||||
tint =
|
tint =
|
||||||
if (currentMove > 0) {
|
if (currentMove > 0) {
|
||||||
@@ -106,7 +106,7 @@ fun MoveNavigator(
|
|||||||
enabled = currentMove < totalMoves,
|
enabled = currentMove < totalMoves,
|
||||||
) {
|
) {
|
||||||
Icon(
|
Icon(
|
||||||
Icons.Default.KeyboardArrowRight,
|
Icons.AutoMirrored.Filled.KeyboardArrowRight,
|
||||||
contentDescription = "Next move",
|
contentDescription = "Next move",
|
||||||
tint =
|
tint =
|
||||||
if (currentMove < totalMoves) {
|
if (currentMove < totalMoves) {
|
||||||
|
|||||||
@@ -1027,7 +1027,7 @@ public inline fun <T> Iterable<Note>.filterEvents(predicate: (T) -> Boolean): Li
|
|||||||
return dest
|
return dest
|
||||||
}
|
}
|
||||||
|
|
||||||
public inline fun <T> Iterable<Note>.filterAuthoredEvents(pubkey: HexKey): List<T> {
|
public fun <T> Iterable<Note>.filterAuthoredEvents(pubkey: HexKey): List<T> {
|
||||||
if (this is Collection && isEmpty()) return emptyList()
|
if (this is Collection && isEmpty()) return emptyList()
|
||||||
|
|
||||||
val dest = ArrayList<T>()
|
val dest = ArrayList<T>()
|
||||||
|
|||||||
Reference in New Issue
Block a user