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:
davotoula
2026-03-16 16:23:08 +01:00
parent 7f6219c846
commit 588cfe4c96
30 changed files with 65 additions and 57 deletions
@@ -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)
} }
@@ -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.
@@ -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)
} }
@@ -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)
} }
@@ -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
@@ -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 ->
@@ -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
@@ -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)
@@ -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 }) {
@@ -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())
@@ -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)
@@ -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()
@@ -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
} }
@@ -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)
@@ -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,
@@ -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)
@@ -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
@@ -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() {
@@ -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"
@@ -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>()