diff --git a/app/src/main/java/com/vitorpamplona/amethyst/service/Nip05Verifier.kt b/app/src/main/java/com/vitorpamplona/amethyst/service/Nip05Verifier.kt index d21e43599..085afad02 100644 --- a/app/src/main/java/com/vitorpamplona/amethyst/service/Nip05Verifier.kt +++ b/app/src/main/java/com/vitorpamplona/amethyst/service/Nip05Verifier.kt @@ -13,8 +13,6 @@ import okhttp3.Request import okhttp3.Response class Nip05Verifier() { - val client = HttpClient.getHttpClient() - fun assembleUrl(nip05address: String): String? { val parts = nip05address.trim().split("@") @@ -49,7 +47,7 @@ class Nip05Verifier() { .url(url) .build() - client.newCall(request).enqueue(object : Callback { + HttpClient.getHttpClient().newCall(request).enqueue(object : Callback { override fun onResponse(call: Call, response: Response) { response.use { if (it.isSuccessful) { diff --git a/app/src/main/java/com/vitorpamplona/amethyst/ui/components/BundledUpdate.kt b/app/src/main/java/com/vitorpamplona/amethyst/ui/components/BundledUpdate.kt index 6f3140e3c..890704ae7 100644 --- a/app/src/main/java/com/vitorpamplona/amethyst/ui/components/BundledUpdate.kt +++ b/app/src/main/java/com/vitorpamplona/amethyst/ui/components/BundledUpdate.kt @@ -1,5 +1,6 @@ package com.vitorpamplona.amethyst.ui.components +import androidx.compose.runtime.Stable import com.vitorpamplona.amethyst.service.checkNotInMainThread import kotlinx.coroutines.CoroutineDispatcher import kotlinx.coroutines.CoroutineScope @@ -15,6 +16,7 @@ import java.util.concurrent.atomic.AtomicBoolean /** * This class is designed to have a waiting time between two calls of invalidate */ +@Stable class BundledUpdate( val delay: Long, val dispatcher: CoroutineDispatcher = Dispatchers.Default @@ -51,6 +53,7 @@ class BundledUpdate( /** * This class is designed to have a waiting time between two calls of invalidate */ +@Stable class BundledInsert( val delay: Long, val dispatcher: CoroutineDispatcher = Dispatchers.Default diff --git a/app/src/main/java/com/vitorpamplona/amethyst/ui/note/MultiSetCompose.kt b/app/src/main/java/com/vitorpamplona/amethyst/ui/note/MultiSetCompose.kt index 705acd7d6..2bce342e8 100644 --- a/app/src/main/java/com/vitorpamplona/amethyst/ui/note/MultiSetCompose.kt +++ b/app/src/main/java/com/vitorpamplona/amethyst/ui/note/MultiSetCompose.kt @@ -222,30 +222,35 @@ fun RenderZapGallery( nav: (String) -> Unit, accountViewModel: AccountViewModel ) { - Row(remember { Modifier.fillMaxWidth() }) { - Box( - modifier = remember { - Modifier - .width(55.dp) - .padding(0.dp) - } - ) { - Icon( - imageVector = Icons.Default.Bolt, - contentDescription = "Zaps", - tint = BitcoinOrange, - modifier = remember { - Modifier - .size(25.dp) - .align(Alignment.TopEnd) - } - ) - } + Row(Modifier.fillMaxWidth()) { + ZapIcon() AuthorGalleryZaps(zapEvents, backgroundColor, nav, accountViewModel) } } +@Composable +private fun ZapIcon() { + Box( + modifier = remember { + Modifier + .width(55.dp) + .padding(0.dp) + } + ) { + Icon( + imageVector = Icons.Default.Bolt, + contentDescription = "Zaps", + tint = BitcoinOrange, + modifier = remember { + Modifier + .size(25.dp) + .align(Alignment.TopEnd) + } + ) + } +} + @Composable fun RenderBoostGallery( boostEvents: ImmutableList, @@ -313,7 +318,7 @@ private fun AuthorPictureAndComment( nav: (String) -> Unit, accountViewModel: AccountViewModel ) { - var content by remember { + val content = remember { mutableStateOf( ZapAmountCommentNotification( user = zapRequest.author, @@ -330,28 +335,24 @@ private fun AuthorPictureAndComment( val amount = (zapEvent?.event as? LnZapEvent)?.amount if (decryptedContent != null) { val newAuthor = LocalCache.getOrCreateUser(decryptedContent.pubKey) - content = ZapAmountCommentNotification(newAuthor, decryptedContent.content.ifBlank { null }, showAmountAxis(amount)) + content.value = ZapAmountCommentNotification(newAuthor, decryptedContent.content.ifBlank { null }, showAmountAxis(amount)) } else { if (!zapRequest.event?.content().isNullOrBlank() || amount != null) { - content = ZapAmountCommentNotification(zapRequest.author, zapRequest.event?.content()?.ifBlank { null }, showAmountAxis(amount)) + content.value = ZapAmountCommentNotification(zapRequest.author, zapRequest.event?.content()?.ifBlank { null }, showAmountAxis(amount)) } } } } } - val route by remember { - derivedStateOf { - "User/${content.user?.pubkeyHex}" - } - } - - content.user?.let { user -> + Row( + modifier = Modifier.clickable { + nav("User/${content.value.user?.pubkeyHex}") + }, + verticalAlignment = Alignment.CenterVertically + ) { AuthorPictureAndComment( - author = user, - comment = content.comment, - amount = content.amount, - route = route, + authorComment = content, backgroundColor = backgroundColor, nav = nav, accountViewModel = accountViewModel @@ -375,69 +376,76 @@ val commentTextSize = 12.sp @Composable private fun AuthorPictureAndComment( - author: User, - comment: String?, - amount: String?, - route: String, + authorComment: MutableState, backgroundColor: MutableState, nav: (String) -> Unit, accountViewModel: AccountViewModel ) { - val modifier = remember { - Modifier.clickable { - nav(route) - } + Box(modifier = sizedModifier, contentAlignment = Alignment.BottomCenter) { + DisplayPicture(authorComment, accountViewModel) + DisplayAmount(authorComment) } - Row( - modifier = modifier, - verticalAlignment = Alignment.CenterVertically - ) { - Box(modifier = sizedModifier, contentAlignment = Alignment.BottomCenter) { - FastNoteAuthorPicture( - author = author, - size = Size35dp, - accountViewModel = accountViewModel, - pictureModifier = simpleModifier - ) + DisplayComment(authorComment, backgroundColor, nav, accountViewModel) +} - amount?.let { - Box( - modifier = amountBoxModifier, - contentAlignment = Alignment.BottomCenter - ) { - val backgroundColor = MaterialTheme.colors.overPictureBackground - Box( - modifier = remember { - Modifier - .fillMaxWidth() - .drawBehind { drawRect(backgroundColor) } - }, - contentAlignment = Alignment.BottomCenter - ) { - Text( - text = it, - fontWeight = FontWeight.Bold, - color = MaterialTheme.colors.secondaryVariant, - fontSize = commentTextSize, - modifier = bottomPadding1dp - ) - } - } +@Composable +fun DisplayPicture(authorComment: MutableState, accountViewModel: AccountViewModel) { + authorComment.value.user?.let { + FastNoteAuthorPicture( + author = it, + size = Size35dp, + accountViewModel = accountViewModel, + pictureModifier = simpleModifier + ) + } +} + +@Composable +fun DisplayAmount(authorComment: MutableState) { + authorComment.value.amount?.let { + Box( + modifier = amountBoxModifier, + contentAlignment = Alignment.BottomCenter + ) { + val backgroundColor = MaterialTheme.colors.overPictureBackground + Box( + modifier = remember { + Modifier + .fillMaxWidth() + .drawBehind { drawRect(backgroundColor) } + }, + contentAlignment = Alignment.BottomCenter + ) { + Text( + text = it, + fontWeight = FontWeight.Bold, + color = MaterialTheme.colors.secondaryVariant, + fontSize = commentTextSize, + modifier = bottomPadding1dp + ) } } + } +} - comment?.let { - TranslatableRichTextViewer( - content = it, - canPreview = true, - tags = remember { ImmutableListOfLists() }, - modifier = textBoxModifier, - backgroundColor = backgroundColor, - accountViewModel = accountViewModel, - nav = nav - ) - } +@Composable +fun DisplayComment( + authorComment: MutableState, + backgroundColor: MutableState, + nav: (String) -> Unit, + accountViewModel: AccountViewModel +) { + authorComment.value.comment?.let { + TranslatableRichTextViewer( + content = it, + canPreview = true, + tags = remember { ImmutableListOfLists() }, + modifier = textBoxModifier, + backgroundColor = backgroundColor, + accountViewModel = accountViewModel, + nav = nav + ) } } @@ -477,19 +485,28 @@ private fun NotePictureAndComment( nav: (String) -> Unit, accountViewModel: AccountViewModel ) { - val author by remember(baseNote) { - derivedStateOf { - baseNote.author + val author = remember(baseNote) { + mutableStateOf( + ZapAmountCommentNotification( + user = baseNote.author, + comment = null, + amount = null + ) + ) + } + + val modifier = remember(baseNote) { + Modifier.clickable { + nav("User/${baseNote.author?.pubkeyHex}") } } - val route by remember(baseNote) { - derivedStateOf { - "User/${baseNote.author?.pubkeyHex}" - } + Row( + modifier = modifier, + verticalAlignment = Alignment.CenterVertically + ) { + AuthorPictureAndComment(authorComment = author, backgroundColor, nav, accountViewModel) } - - author?.let { AuthorPictureAndComment(it, null, null, route, backgroundColor, nav, accountViewModel) } } @Composable diff --git a/app/src/main/java/com/vitorpamplona/amethyst/ui/note/NoteCompose.kt b/app/src/main/java/com/vitorpamplona/amethyst/ui/note/NoteCompose.kt index 3f18b9ad4..6bb0371f9 100644 --- a/app/src/main/java/com/vitorpamplona/amethyst/ui/note/NoteCompose.kt +++ b/app/src/main/java/com/vitorpamplona/amethyst/ui/note/NoteCompose.kt @@ -2706,9 +2706,7 @@ private fun VerticalRelayPanelWithFlow( val showMoreRelaysButtonIconButtonModifier = Modifier.size(24.dp) val showMoreRelaysButtonIconModifier = Modifier.size(15.dp) -val showMoreRelaysButtonBoxModifer = Modifier - .fillMaxWidth() - .height(25.dp) +val showMoreRelaysButtonBoxModifer = Modifier.fillMaxWidth().height(25.dp) @Composable private fun ShowMoreRelaysButton(onClick: () -> Unit) { @@ -2879,7 +2877,7 @@ fun UserPicture( @Composable private fun ObserveAndDisplayFollowingMark(userHex: String, iconSize: Dp, accountViewModel: AccountViewModel) { - val accountFollowsState by accountViewModel.account.userProfile().live().follows.observeAsState() + val accountFollowsState by accountViewModel.userFollows.observeAsState() var showFollowingMark by remember { mutableStateOf(false) } 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 8bd528cbd..ef793eb5c 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 @@ -15,6 +15,7 @@ import com.vitorpamplona.amethyst.model.Account import com.vitorpamplona.amethyst.model.AccountState import com.vitorpamplona.amethyst.model.Note import com.vitorpamplona.amethyst.model.User +import com.vitorpamplona.amethyst.model.UserState import com.vitorpamplona.amethyst.service.lnurl.LightningAddressResolver import com.vitorpamplona.amethyst.service.model.Event import com.vitorpamplona.amethyst.service.model.LnZapEvent @@ -32,6 +33,8 @@ class AccountViewModel(val account: Account) : ViewModel() { val accountLanguagesLiveData: LiveData = account.liveLanguages.map { it } val accountLastReadLiveData: LiveData = account.liveLastRead.map { it } + val userFollows: LiveData = account.userProfile().live().follows.map { it } + fun isWriteable(): Boolean { return account.isWriteable() }