From 8ed7e634274c21a710fe2bdba2c3f8af32c875ee Mon Sep 17 00:00:00 2001 From: davotoula Date: Wed, 13 May 2026 10:40:38 +0200 Subject: [PATCH] refactor(sonar): merge chained if-else into when MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Sonar — convert 'if (A) {…} else if (B) {…} else {…}' chains into 'when { A -> …; B -> …; else -> … }' across 33 files (~44 sites). The change is mechanically equivalent: same conditions, same branch order, same short-circuit evaluation, no public-signature impact. The 70-branch event-type dispatch in ThreadFeedView.kt:594 is intentionally left as if-else for now — the conversion would balloon to a 280-line diff with no behavioural change, making review impractical. --- .../vitorpamplona/amethyst/model/Account.kt | 51 ++-- .../amethyst/service/ZapPaymentHandler.kt | 80 +++--- .../amethyst/service/previews/UrlPreview.kt | 34 ++- .../relayClient/RelayProxyClientConnector.kt | 54 +++-- .../blossom/bud10/BlossomServerResolver.kt | 13 +- .../amethyst/ui/actions/EditPostView.kt | 58 +++-- .../amethyst/ui/actions/NewMessageTagger.kt | 82 ++++--- .../ui/actions/uploads/ShowImageUploadItem.kt | 106 ++++---- .../amethyst/ui/components/LoadUrlPreview.kt | 60 +++-- .../ui/components/ReusableZapButton.kt | 72 +++--- .../amethyst/ui/note/BlockReportChecker.kt | 42 ++-- .../ui/note/NIP05VerificationDisplay.kt | 130 +++++----- .../amethyst/ui/note/NoteQuickActionMenu.kt | 13 +- .../amethyst/ui/note/ReactionsRow.kt | 86 ++++--- .../amethyst/ui/note/TimeAgoFormatter.kt | 228 +++++++++++------- .../amethyst/ui/note/ZapPollNote.kt | 112 +++++---- .../amethyst/ui/note/ZapPollNoteViewModel.kt | 89 ++++--- .../ui/note/creators/previews/PreviewUrl.kt | 120 +++++---- .../userSuggestions/UserSuggestionState.kt | 86 ++++--- .../amethyst/ui/note/types/Attestation.kt | 106 ++++---- .../amethyst/ui/note/types/Highlight.kt | 34 ++- .../amethyst/ui/note/types/MedicalData.kt | 13 +- .../ui/screen/AccountSessionManager.kt | 68 +++--- .../ui/screen/loggedIn/AccountViewModel.kt | 26 +- .../loggedIn/chats/feed/ChatMessageCompose.kt | 18 +- .../privateDM/send/ChatNewMessageViewModel.kt | 30 ++- .../send/ChannelNewMessageViewModel.kt | 166 +++++++------ .../loggedIn/discover/nip90DVMs/DVMCard.kt | 32 ++- .../notifications/NotificationSummaryState.kt | 154 ++++++------ .../NewPublicMessageViewModel.kt | 28 ++- .../loggedIn/profile/gallery/GalleryThumb.kt | 176 +++++++------- .../loggedIn/search/SearchBarViewModel.kt | 86 ++++--- .../ui/screen/loggedIn/video/VideoScreen.kt | 50 ++-- 33 files changed, 1399 insertions(+), 1104 deletions(-) diff --git a/amethyst/src/main/java/com/vitorpamplona/amethyst/model/Account.kt b/amethyst/src/main/java/com/vitorpamplona/amethyst/model/Account.kt index db26d6206..9d505f3a6 100644 --- a/amethyst/src/main/java/com/vitorpamplona/amethyst/model/Account.kt +++ b/amethyst/src/main/java/com/vitorpamplona/amethyst/model/Account.kt @@ -2859,14 +2859,11 @@ class Account( if (event == null) return null return if (isWriteable()) { - if (event is PrivateDmEvent) { - privateDMDecryptionCache.cachedDM(event) - } else if (event is LnZapRequestEvent && event.isPrivateZap()) { - privateZapsDecryptionCache.cachedPrivateZap(event)?.content - } else if (event is DraftWrapEvent) { - draftsDecryptionCache.preCachedDraft(event)?.content - } else { - event.content + when { + event is PrivateDmEvent -> privateDMDecryptionCache.cachedDM(event) + event is LnZapRequestEvent && event.isPrivateZap() -> privateZapsDecryptionCache.cachedPrivateZap(event)?.content + event is DraftWrapEvent -> draftsDecryptionCache.preCachedDraft(event)?.content + else -> event.content } } else { event.content @@ -2875,22 +2872,30 @@ class Account( suspend fun decryptContent(note: Note): String? { val event = note.event - return if (event is PrivateDmEvent && isWriteable()) { - privateDMDecryptionCache.decryptDM(event) - } else if (event is LnZapRequestEvent && isWriteable()) { - if (event.isPrivateZap()) { - if (isWriteable()) { - privateZapsDecryptionCache.decryptPrivateZap(event)?.content - } else { - null - } - } else { - event.content + return when { + event is PrivateDmEvent && isWriteable() -> { + privateDMDecryptionCache.decryptDM(event) + } + + event is LnZapRequestEvent && isWriteable() -> { + if (event.isPrivateZap()) { + if (isWriteable()) { + privateZapsDecryptionCache.decryptPrivateZap(event)?.content + } else { + null + } + } else { + event.content + } + } + + event is DraftWrapEvent && isWriteable() -> { + draftsDecryptionCache.cachedDraft(event)?.content + } + + else -> { + event?.content } - } else if (event is DraftWrapEvent && isWriteable()) { - draftsDecryptionCache.cachedDraft(event)?.content - } else { - event?.content } } diff --git a/amethyst/src/main/java/com/vitorpamplona/amethyst/service/ZapPaymentHandler.kt b/amethyst/src/main/java/com/vitorpamplona/amethyst/service/ZapPaymentHandler.kt index 2607a9ceb..951358645 100644 --- a/amethyst/src/main/java/com/vitorpamplona/amethyst/service/ZapPaymentHandler.kt +++ b/amethyst/src/main/java/com/vitorpamplona/amethyst/service/ZapPaymentHandler.kt @@ -88,48 +88,56 @@ class ZapPaymentHandler( val zapSplitSetup = noteEvent?.zapSplitSetup() val unverifiedZapsToSend = - if (!zapSplitSetup.isNullOrEmpty()) { - zapSplitSetup.map { setup -> - when (setup) { - is ZapSplitSetupLnAddress -> { - UnverifiedZapSplitSetup( - lnAddress = setup.lnAddress, - weight = setup.weight, - ) - } + when { + !zapSplitSetup.isNullOrEmpty() -> { + zapSplitSetup.map { setup -> + when (setup) { + is ZapSplitSetupLnAddress -> { + UnverifiedZapSplitSetup( + lnAddress = setup.lnAddress, + weight = setup.weight, + ) + } - is ZapSplitSetup -> { - val user = LocalCache.checkGetOrCreateUser(setup.pubKeyHex) - UnverifiedZapSplitSetup( - lnAddress = user?.lnAddress(), - weight = setup.weight, - relay = setup.relay, - user = user, - ) + is ZapSplitSetup -> { + val user = LocalCache.checkGetOrCreateUser(setup.pubKeyHex) + UnverifiedZapSplitSetup( + lnAddress = user?.lnAddress(), + weight = setup.weight, + relay = setup.relay, + user = user, + ) + } } } } - } else if (noteEvent is LiveActivitiesEvent && noteEvent.hasHost()) { - noteEvent.hosts().map { - val user = LocalCache.checkGetOrCreateUser(it.pubKey) - val lnAddress = user?.lnAddress() - UnverifiedZapSplitSetup(lnAddress, relay = it.relayHint, user = user) + + noteEvent is LiveActivitiesEvent && noteEvent.hasHost() -> { + noteEvent.hosts().map { + val user = LocalCache.checkGetOrCreateUser(it.pubKey) + val lnAddress = user?.lnAddress() + UnverifiedZapSplitSetup(lnAddress, relay = it.relayHint, user = user) + } } - } else if (noteEvent is AppDefinitionEvent) { - val appLud16 = noteEvent.appMetaData()?.lnAddress() - if (appLud16 != null) { - listOf(UnverifiedZapSplitSetup(appLud16)) - } else { - val lud16 = - note.author?.lnAddress() - listOf(UnverifiedZapSplitSetup(lud16)) + + noteEvent is AppDefinitionEvent -> { + val appLud16 = noteEvent.appMetaData()?.lnAddress() + if (appLud16 != null) { + listOf(UnverifiedZapSplitSetup(appLud16)) + } else { + val lud16 = + note.author?.lnAddress() + listOf(UnverifiedZapSplitSetup(lud16)) + } + } + + else -> { + listOf( + UnverifiedZapSplitSetup( + note.author?.lnAddress(), + ), + ) } - } else { - listOf( - UnverifiedZapSplitSetup( - note.author?.lnAddress(), - ), - ) } if (showErrorIfNoLnAddress) { diff --git a/amethyst/src/main/java/com/vitorpamplona/amethyst/service/previews/UrlPreview.kt b/amethyst/src/main/java/com/vitorpamplona/amethyst/service/previews/UrlPreview.kt index db4c9ac9d..f339cf879 100644 --- a/amethyst/src/main/java/com/vitorpamplona/amethyst/service/previews/UrlPreview.kt +++ b/amethyst/src/main/java/com/vitorpamplona/amethyst/service/previews/UrlPreview.kt @@ -63,18 +63,28 @@ class UrlPreview { val mimeType = response.headers["Content-Type"]?.toMediaType() ?: throw IllegalArgumentException("Website returned unknown mimetype: ${response.headers["Content-Type"]}") - if (mimeType.type == "text" && mimeType.subtype == "html") { - val metaTags = HtmlParser().parseHtml(response.body.source(), mimeType.charset()) - val data = OpenGraphParser().extractUrlInfo(metaTags) - UrlInfoItem(url, data.title, data.description, data.image, mimeType.toString()) - } else if (mimeType.type == "image") { - UrlInfoItem(url, image = url, mimeType = mimeType.toString()) - } else if (mimeType.type == "video") { - UrlInfoItem(url, image = url, mimeType = mimeType.toString()) - } else if (mimeType.type == "application" && mimeType.subtype == "pdf") { - UrlInfoItem(url, image = url, mimeType = mimeType.toString()) - } else { - throw IllegalArgumentException("Website returned unknown encoding for previews: $mimeType") + when { + mimeType.type == "text" && mimeType.subtype == "html" -> { + val metaTags = HtmlParser().parseHtml(response.body.source(), mimeType.charset()) + val data = OpenGraphParser().extractUrlInfo(metaTags) + UrlInfoItem(url, data.title, data.description, data.image, mimeType.toString()) + } + + mimeType.type == "image" -> { + UrlInfoItem(url, image = url, mimeType = mimeType.toString()) + } + + mimeType.type == "video" -> { + UrlInfoItem(url, image = url, mimeType = mimeType.toString()) + } + + mimeType.type == "application" && mimeType.subtype == "pdf" -> { + UrlInfoItem(url, image = url, mimeType = mimeType.toString()) + } + + else -> { + throw IllegalArgumentException("Website returned unknown encoding for previews: $mimeType") + } } } else { throw IllegalArgumentException("Website returned: " + response.code) diff --git a/amethyst/src/main/java/com/vitorpamplona/amethyst/service/relayClient/RelayProxyClientConnector.kt b/amethyst/src/main/java/com/vitorpamplona/amethyst/service/relayClient/RelayProxyClientConnector.kt index 911ddfa9f..7f7ad3eee 100644 --- a/amethyst/src/main/java/com/vitorpamplona/amethyst/service/relayClient/RelayProxyClientConnector.kt +++ b/amethyst/src/main/java/com/vitorpamplona/amethyst/service/relayClient/RelayProxyClientConnector.kt @@ -70,31 +70,39 @@ class RelayProxyClientConnector( RelayServiceInfra(torSettings, torConnection, clearConnection, connectivity, torStatus) }.debounce(100) .onEach { - if (it.connectivity is ConnectivityStatus.StartingService) { - // ignore - } else if (it.connectivity is ConnectivityStatus.Off) { - Log.d("ManageRelayServices") { "Connectivity Off: Pausing Relay Services ${it.connectivity}" } - if (client.isActive()) { - client.disconnect() - } - if (it.torStatus is TorServiceStatus.Active) { - Log.d("ManageRelayServices", "Connectivity off, Tor idle") - } - } else if (it.connectivity is ConnectivityStatus.Active && !client.isActive()) { - Log.d("ManageRelayServices", "Connectivity On: Resuming Relay Services") - - if (it.torStatus is TorServiceStatus.Active) { - Log.d("ManageRelayServices", "Connectivity resumed, Tor active") + when { + it.connectivity is ConnectivityStatus.StartingService -> { + // ignore } - // only calls this if the client is not active. Otherwise goes to the else below - client.connect() - } else { - Log.d("ManageRelayServices", "Relay Services have changed, reconnecting relays that need to") - client.reconnect( - onlyIfChanged = true, - ignoreRetryDelays = true, - ) + it.connectivity is ConnectivityStatus.Off -> { + Log.d("ManageRelayServices") { "Connectivity Off: Pausing Relay Services ${it.connectivity}" } + if (client.isActive()) { + client.disconnect() + } + if (it.torStatus is TorServiceStatus.Active) { + Log.d("ManageRelayServices", "Connectivity off, Tor idle") + } + } + + it.connectivity is ConnectivityStatus.Active && !client.isActive() -> { + Log.d("ManageRelayServices", "Connectivity On: Resuming Relay Services") + + if (it.torStatus is TorServiceStatus.Active) { + Log.d("ManageRelayServices", "Connectivity resumed, Tor active") + } + + // only calls this if the client is not active. Otherwise goes to the else below + client.connect() + } + + else -> { + Log.d("ManageRelayServices", "Relay Services have changed, reconnecting relays that need to") + client.reconnect( + onlyIfChanged = true, + ignoreRetryDelays = true, + ) + } } }.onStart { Log.d("ManageRelayServices", "Resuming Relay Services") diff --git a/amethyst/src/main/java/com/vitorpamplona/amethyst/service/uploads/blossom/bud10/BlossomServerResolver.kt b/amethyst/src/main/java/com/vitorpamplona/amethyst/service/uploads/blossom/bud10/BlossomServerResolver.kt index e1030da1c..d609103c0 100644 --- a/amethyst/src/main/java/com/vitorpamplona/amethyst/service/uploads/blossom/bud10/BlossomServerResolver.kt +++ b/amethyst/src/main/java/com/vitorpamplona/amethyst/service/uploads/blossom/bud10/BlossomServerResolver.kt @@ -136,14 +136,11 @@ class BlossomServerResolver( url: String, mimeType: String?, ): OkHttpClient = - if (mimeType == null) { - httpClientBuilder.okHttpClientForPreview(url) - } else if (mimeType.startsWith("audio/") || mimeType.startsWith("video/")) { - httpClientBuilder.okHttpClientForVideo(url) - } else if (mimeType.startsWith("image/")) { - httpClientBuilder.okHttpClientForImage(url) - } else { - httpClientBuilder.okHttpClientForPreview(url) + when { + mimeType == null -> httpClientBuilder.okHttpClientForPreview(url) + mimeType.startsWith("audio/") || mimeType.startsWith("video/") -> httpClientBuilder.okHttpClientForVideo(url) + mimeType.startsWith("image/") -> httpClientBuilder.okHttpClientForImage(url) + else -> httpClientBuilder.okHttpClientForPreview(url) } fun canResolve(scheme: String) = scheme == SCHEME diff --git a/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/actions/EditPostView.kt b/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/actions/EditPostView.kt index 0874d1f38..54c4b3c31 100644 --- a/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/actions/EditPostView.kt +++ b/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/actions/EditPostView.kt @@ -212,32 +212,38 @@ fun EditPostView( if (myUrlPreview != null) { Row(modifier = Modifier.padding(vertical = Size5dp, horizontal = Size10dp)) { if (RichTextParser.isValidURL(myUrlPreview)) { - if (RichTextParser.isImageUrl(myUrlPreview)) { - AsyncImage( - model = myUrlPreview, - contentDescription = myUrlPreview, - contentScale = ContentScale.FillWidth, - modifier = - Modifier - .padding(top = 4.dp) - .fillMaxWidth() - .clip(shape = QuoteBorder) - .border( - 1.dp, - MaterialTheme.colorScheme.subtleBorder, - QuoteBorder, - ), - ) - } else if (RichTextParser.isVideoUrl(myUrlPreview)) { - VideoView( - myUrlPreview, - mimeType = null, - roundedCorner = true, - contentScale = ContentScale.FillWidth, - accountViewModel = accountViewModel, - ) - } else { - LoadUrlPreview(myUrlPreview, myUrlPreview, null, accountViewModel) + when { + RichTextParser.isImageUrl(myUrlPreview) -> { + AsyncImage( + model = myUrlPreview, + contentDescription = myUrlPreview, + contentScale = ContentScale.FillWidth, + modifier = + Modifier + .padding(top = 4.dp) + .fillMaxWidth() + .clip(shape = QuoteBorder) + .border( + 1.dp, + MaterialTheme.colorScheme.subtleBorder, + QuoteBorder, + ), + ) + } + + RichTextParser.isVideoUrl(myUrlPreview) -> { + VideoView( + myUrlPreview, + mimeType = null, + roundedCorner = true, + contentScale = ContentScale.FillWidth, + accountViewModel = accountViewModel, + ) + } + + else -> { + LoadUrlPreview(myUrlPreview, myUrlPreview, null, accountViewModel) + } } } else if (RichTextParser.startsWithNIP19Scheme(myUrlPreview)) { val bgColor = MaterialTheme.colorScheme.background diff --git a/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/actions/NewMessageTagger.kt b/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/actions/NewMessageTagger.kt index 459a703c2..1df8b61d1 100644 --- a/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/actions/NewMessageTagger.kt +++ b/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/actions/NewMessageTagger.kt @@ -188,55 +188,67 @@ class NewMessageTagger( key = key.removePrefix("@") try { - if (key.startsWith("nsec1", true)) { - if (key.length < 63) { - return null + when { + key.startsWith("nsec1", true) -> { + if (key.length < 63) { + return null + } + + val keyB32 = key.substring(0, 63) + val restOfWord = key.substring(63) + // Converts to npub + val pubkey = + Nip19Parser.uriToRoute(Nip01Crypto.pubKeyCreate(keyB32.bechToBytes()).toNpub()) ?: return null + + return DirtyKeyInfo(pubkey, restOfWord.ifEmpty { null }) } - val keyB32 = key.substring(0, 63) - val restOfWord = key.substring(63) - // Converts to npub - val pubkey = - Nip19Parser.uriToRoute(Nip01Crypto.pubKeyCreate(keyB32.bechToBytes()).toNpub()) ?: return null + key.startsWith("npub1", true) -> { + if (key.length < 63) { + return null + } - return DirtyKeyInfo(pubkey, restOfWord.ifEmpty { null }) - } else if (key.startsWith("npub1", true)) { - if (key.length < 63) { - return null + val keyB32 = key.substring(0, 63) + val restOfWord = key.substring(63) + + val pubkey = Nip19Parser.uriToRoute(keyB32) ?: return null + + return DirtyKeyInfo(pubkey, restOfWord.ifEmpty { null }) } - val keyB32 = key.substring(0, 63) - val restOfWord = key.substring(63) + key.startsWith("note1", true) -> { + if (key.length < 63) { + return null + } - val pubkey = Nip19Parser.uriToRoute(keyB32) ?: return null + val keyB32 = key.substring(0, 63) + val restOfWord = key.substring(63) - return DirtyKeyInfo(pubkey, restOfWord.ifEmpty { null }) - } else if (key.startsWith("note1", true)) { - if (key.length < 63) { - return null + val noteId = Nip19Parser.uriToRoute(keyB32) ?: return null + + return DirtyKeyInfo(noteId, restOfWord.ifEmpty { null }) } - val keyB32 = key.substring(0, 63) - val restOfWord = key.substring(63) + key.startsWith("nprofile", true) -> { + val pubkeyRelay = Nip19Parser.uriToRoute(key) ?: return null - val noteId = Nip19Parser.uriToRoute(keyB32) ?: return null + return DirtyKeyInfo(pubkeyRelay, pubkeyRelay.additionalChars) + } - return DirtyKeyInfo(noteId, restOfWord.ifEmpty { null }) - } else if (key.startsWith("nprofile", true)) { - val pubkeyRelay = Nip19Parser.uriToRoute(key) ?: return null + key.startsWith("nevent1", true) -> { + val noteRelayId = Nip19Parser.uriToRoute(key) ?: return null - return DirtyKeyInfo(pubkeyRelay, pubkeyRelay.additionalChars) - } else if (key.startsWith("nevent1", true)) { - val noteRelayId = Nip19Parser.uriToRoute(key) ?: return null + return DirtyKeyInfo(noteRelayId, noteRelayId.additionalChars) + } - return DirtyKeyInfo(noteRelayId, noteRelayId.additionalChars) - } else if (key.startsWith("naddr1", true)) { - val address = Nip19Parser.uriToRoute(key) ?: return null + key.startsWith("naddr1", true) -> { + val address = Nip19Parser.uriToRoute(key) ?: return null - return DirtyKeyInfo( - address, - address.additionalChars, - ) // no way to know when they address ends and dirt begins + return DirtyKeyInfo( + address, + address.additionalChars, + ) // no way to know when they address ends and dirt begins + } } } catch (e: Exception) { if (e is CancellationException) throw e diff --git a/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/actions/uploads/ShowImageUploadItem.kt b/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/actions/uploads/ShowImageUploadItem.kt index a27d4d227..06d7c9b55 100644 --- a/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/actions/uploads/ShowImageUploadItem.kt +++ b/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/actions/uploads/ShowImageUploadItem.kt @@ -113,51 +113,69 @@ fun ShowImageGallery( media: SelectedMedia, accountViewModel: AccountViewModel, ) { - if (media.isImage() == true) { - AsyncImage( - model = media.uri.toString(), - contentDescription = media.uri.toString(), - contentScale = ContentScale.Crop, - modifier = - Modifier - .fillMaxWidth() - .windowInsetsPadding(WindowInsets(0.dp, 0.dp, 0.dp, 0.dp)), - ) - } else if (media.isAudio() == true) { - FilePreviewPlaceholder( - icon = MaterialSymbols.AudioFile, - label = media.mimeType ?: "audio/*", - ) - } else if (media.isDocument()) { - FilePreviewPlaceholder( - icon = MaterialSymbols.PictureAsPdf, - label = media.mimeType ?: "application/pdf", - ) - } else if (media.isVideo() == true && Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) { - var bitmap by remember { mutableStateOf(null) } - val context = LocalContext.current + when { + media.isImage() == true -> { + AsyncImage( + model = media.uri.toString(), + contentDescription = media.uri.toString(), + contentScale = ContentScale.Crop, + modifier = + Modifier + .fillMaxWidth() + .windowInsetsPadding(WindowInsets(0.dp, 0.dp, 0.dp, 0.dp)), + ) + } - LaunchedEffect(key1 = media) { - launch(Dispatchers.IO) { - try { - bitmap = createVideoThumb(context, media.uri) - } catch (e: Exception) { - if (e is CancellationException) throw e - Log.w("NewPostView", "Couldn't create thumbnail, but the video can be uploaded", e) + media.isAudio() == true -> { + FilePreviewPlaceholder( + icon = MaterialSymbols.AudioFile, + label = media.mimeType ?: "audio/*", + ) + } + + media.isDocument() -> { + FilePreviewPlaceholder( + icon = MaterialSymbols.PictureAsPdf, + label = media.mimeType ?: "application/pdf", + ) + } + + media.isVideo() == true && Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q -> { + var bitmap by remember { mutableStateOf(null) } + val context = LocalContext.current + + LaunchedEffect(key1 = media) { + launch(Dispatchers.IO) { + try { + bitmap = createVideoThumb(context, media.uri) + } catch (e: Exception) { + if (e is CancellationException) throw e + Log.w("NewPostView", "Couldn't create thumbnail, but the video can be uploaded", e) + } } } + + if (bitmap != null) { + bitmap?.let { + Image( + bitmap = it.asImageBitmap(), + contentDescription = "some useful description", + contentScale = ContentScale.Crop, + modifier = Modifier.fillMaxWidth(), + ) + } + } else { + VideoView( + videoUri = media.uri.toString(), + mimeType = media.mimeType, + roundedCorner = false, + contentScale = ContentScale.Crop, + accountViewModel = accountViewModel, + ) + } } - if (bitmap != null) { - bitmap?.let { - Image( - bitmap = it.asImageBitmap(), - contentDescription = "some useful description", - contentScale = ContentScale.Crop, - modifier = Modifier.fillMaxWidth(), - ) - } - } else { + else -> { VideoView( videoUri = media.uri.toString(), mimeType = media.mimeType, @@ -166,14 +184,6 @@ fun ShowImageGallery( accountViewModel = accountViewModel, ) } - } else { - VideoView( - videoUri = media.uri.toString(), - mimeType = media.mimeType, - roundedCorner = false, - contentScale = ContentScale.Crop, - accountViewModel = accountViewModel, - ) } } diff --git a/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/components/LoadUrlPreview.kt b/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/components/LoadUrlPreview.kt index 371d21b58..0a26b2fc9 100644 --- a/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/components/LoadUrlPreview.kt +++ b/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/components/LoadUrlPreview.kt @@ -95,34 +95,42 @@ fun RenderLoaded( callbackUri: String? = null, accountViewModel: AccountViewModel, ) { - if (state.previewInfo.mimeType.startsWith("image")) { - Box(modifier = HalfVertPadding) { - ZoomableContentView( - content = MediaUrlImage(url, uri = callbackUri), - roundedCorner = true, - contentScale = ContentScale.FillWidth, - accountViewModel = accountViewModel, - ) + when { + state.previewInfo.mimeType.startsWith("image") -> { + Box(modifier = HalfVertPadding) { + ZoomableContentView( + content = MediaUrlImage(url, uri = callbackUri), + roundedCorner = true, + contentScale = ContentScale.FillWidth, + accountViewModel = accountViewModel, + ) + } } - } else if (state.previewInfo.mimeType.startsWith("video")) { - Box(modifier = HalfVertPadding) { - ZoomableContentView( - content = MediaUrlVideo(url, uri = callbackUri), - roundedCorner = true, - contentScale = ContentScale.FillWidth, - accountViewModel = accountViewModel, - ) + + state.previewInfo.mimeType.startsWith("video") -> { + Box(modifier = HalfVertPadding) { + ZoomableContentView( + content = MediaUrlVideo(url, uri = callbackUri), + roundedCorner = true, + contentScale = ContentScale.FillWidth, + accountViewModel = accountViewModel, + ) + } } - } else if (state.previewInfo.mimeType.startsWith("application/pdf")) { - Box(modifier = HalfVertPadding) { - ZoomableContentView( - content = MediaUrlPdf(url, uri = callbackUri, mimeType = state.previewInfo.mimeType), - roundedCorner = true, - contentScale = ContentScale.FillWidth, - accountViewModel = accountViewModel, - ) + + state.previewInfo.mimeType.startsWith("application/pdf") -> { + Box(modifier = HalfVertPadding) { + ZoomableContentView( + content = MediaUrlPdf(url, uri = callbackUri, mimeType = state.previewInfo.mimeType), + roundedCorner = true, + contentScale = ContentScale.FillWidth, + accountViewModel = accountViewModel, + ) + } + } + + else -> { + UrlPreviewCard(url, state.previewInfo) } - } else { - UrlPreviewCard(url, state.previewInfo) } } diff --git a/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/components/ReusableZapButton.kt b/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/components/ReusableZapButton.kt index 6292e5687..7e74f2a3f 100644 --- a/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/components/ReusableZapButton.kt +++ b/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/components/ReusableZapButton.kt @@ -293,40 +293,48 @@ private fun handleZapClick( val choices = zapAmountChoices ?: accountViewModel.zapAmountChoices() - if (choices.isEmpty()) { - accountViewModel.toastManager.toast( - stringRes(context, R.string.error_dialog_zap_error), - stringRes(context, R.string.no_zap_amount_setup_long_press_to_change), - ) - } else if (!accountViewModel.isWriteable()) { - accountViewModel.toastManager.toast( - stringRes(context, R.string.error_dialog_zap_error), - stringRes(context, R.string.login_with_a_private_key_to_be_able_to_send_zaps), - ) - } else if (choices.size == 1) { - val amount = choices.first() - - if (amount > 1100 || zapAmountChoices != null) { - onZapStarts() - accountViewModel.zap( - baseNote, - amount * 1000, - null, - "", - context, - showErrorIfNoLnAddress = false, - onError = onError, - onProgress = { onZappingProgress(it) }, - onPayViaIntent = onPayViaIntent, + when { + choices.isEmpty() -> { + accountViewModel.toastManager.toast( + stringRes(context, R.string.error_dialog_zap_error), + stringRes(context, R.string.no_zap_amount_setup_long_press_to_change), ) - } else { - onMultipleChoices(listOf(1000L, 5_000L, 10_000L)) } - } else { - if (choices.any { it > 1100 } || zapAmountChoices != null) { - onMultipleChoices(choices) - } else { - onMultipleChoices(listOf(1000L, 5_000L, 10_000L)) + + !accountViewModel.isWriteable() -> { + accountViewModel.toastManager.toast( + stringRes(context, R.string.error_dialog_zap_error), + stringRes(context, R.string.login_with_a_private_key_to_be_able_to_send_zaps), + ) + } + + choices.size == 1 -> { + val amount = choices.first() + + if (amount > 1100 || zapAmountChoices != null) { + onZapStarts() + accountViewModel.zap( + baseNote, + amount * 1000, + null, + "", + context, + showErrorIfNoLnAddress = false, + onError = onError, + onProgress = { onZappingProgress(it) }, + onPayViaIntent = onPayViaIntent, + ) + } else { + onMultipleChoices(listOf(1000L, 5_000L, 10_000L)) + } + } + + else -> { + if (choices.any { it > 1100 } || zapAmountChoices != null) { + onMultipleChoices(choices) + } else { + onMultipleChoices(listOf(1000L, 5_000L, 10_000L)) + } } } } diff --git a/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/note/BlockReportChecker.kt b/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/note/BlockReportChecker.kt index f6e3fbe3a..b64b8e0a2 100644 --- a/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/note/BlockReportChecker.kt +++ b/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/note/BlockReportChecker.kt @@ -67,25 +67,31 @@ fun WatchBlockAndReport( mutableStateOf(false) } - if (showAnyway.value) { - normalNote(true) - } else if (!isHidden.isPostHidden) { - if (isHidden.isAcceptable) { - normalNote(isHidden.canPreview) - } else { - HiddenNote( - isHidden.relevantReports, - isHidden.isHiddenAuthor, - accountViewModel, - modifier, - nav, - onClick = { showAnyway.value = true }, - ) + when { + showAnyway.value -> { + normalNote(true) } - } else if (showHiddenWarning) { - // if it is a quoted or boosted note, how the hidden warning. - HiddenNoteByMe { - showAnyway.value = true + + !isHidden.isPostHidden -> { + if (isHidden.isAcceptable) { + normalNote(isHidden.canPreview) + } else { + HiddenNote( + isHidden.relevantReports, + isHidden.isHiddenAuthor, + accountViewModel, + modifier, + nav, + onClick = { showAnyway.value = true }, + ) + } + } + + showHiddenWarning -> { + // if it is a quoted or boosted note, how the hidden warning. + HiddenNoteByMe { + showAnyway.value = true + } } } } diff --git a/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/note/NIP05VerificationDisplay.kt b/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/note/NIP05VerificationDisplay.kt index b33793d13..a6c5825ae 100644 --- a/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/note/NIP05VerificationDisplay.kt +++ b/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/note/NIP05VerificationDisplay.kt @@ -293,78 +293,86 @@ fun DisplayStatusInner( ) } - if (url != null) { - val uri = LocalUriHandler.current - Spacer(modifier = StdHorzSpacer) - IconButton( - modifier = Size15Modifier, - onClick = { runCatching { uri.openUri(url.trim()) } }, - ) { - Icon( - symbol = MaterialSymbols.AutoMirrored.OpenInNew, - null, + when { + url != null -> { + val uri = LocalUriHandler.current + Spacer(modifier = StdHorzSpacer) + IconButton( modifier = Size15Modifier, - tint = MaterialTheme.colorScheme.lessImportantLink, - ) - } - } else if (nostrATag != null) { - LoadAddressableNote(nostrATag, accountViewModel) { note -> - if (note != null) { - Spacer(modifier = StdHorzSpacer) - IconButton( + onClick = { runCatching { uri.openUri(url.trim()) } }, + ) { + Icon( + symbol = MaterialSymbols.AutoMirrored.OpenInNew, + null, modifier = Size15Modifier, - onClick = { - routeFor( - note, - accountViewModel.account, - )?.let { nav.nav(it) } - }, - ) { - Icon( - symbol = MaterialSymbols.AutoMirrored.OpenInNew, - null, + tint = MaterialTheme.colorScheme.lessImportantLink, + ) + } + } + + nostrATag != null -> { + LoadAddressableNote(nostrATag, accountViewModel) { note -> + if (note != null) { + Spacer(modifier = StdHorzSpacer) + IconButton( modifier = Size15Modifier, - tint = MaterialTheme.colorScheme.lessImportantLink, - ) + onClick = { + routeFor( + note, + accountViewModel.account, + )?.let { nav.nav(it) } + }, + ) { + Icon( + symbol = MaterialSymbols.AutoMirrored.OpenInNew, + null, + modifier = Size15Modifier, + tint = MaterialTheme.colorScheme.lessImportantLink, + ) + } } } } - } else if (nostrETag != null) { - LoadNote(baseNoteHex = nostrETag.eventId, accountViewModel) { - if (it != null) { - Spacer(modifier = StdHorzSpacer) - IconButton( - modifier = Size15Modifier, - onClick = { - routeFor( - it, - accountViewModel.account, - )?.let { nav.nav(it) } - }, - ) { - Icon( - symbol = MaterialSymbols.AutoMirrored.OpenInNew, - null, + + nostrETag != null -> { + LoadNote(baseNoteHex = nostrETag.eventId, accountViewModel) { + if (it != null) { + Spacer(modifier = StdHorzSpacer) + IconButton( modifier = Size15Modifier, - tint = MaterialTheme.colorScheme.lessImportantLink, - ) + onClick = { + routeFor( + it, + accountViewModel.account, + )?.let { nav.nav(it) } + }, + ) { + Icon( + symbol = MaterialSymbols.AutoMirrored.OpenInNew, + null, + modifier = Size15Modifier, + tint = MaterialTheme.colorScheme.lessImportantLink, + ) + } } } } - } else if (nostrPTag != null) { - LoadUser(baseUserHex = nostrPTag, accountViewModel) { user -> - if (user != null) { - Spacer(modifier = StdHorzSpacer) - IconButton( - modifier = Size15Modifier, - onClick = { nav.nav(routeForUser(nostrPTag)) }, - ) { - Icon( - symbol = MaterialSymbols.AutoMirrored.OpenInNew, - null, + + nostrPTag != null -> { + LoadUser(baseUserHex = nostrPTag, accountViewModel) { user -> + if (user != null) { + Spacer(modifier = StdHorzSpacer) + IconButton( modifier = Size15Modifier, - tint = MaterialTheme.colorScheme.lessImportantLink, - ) + onClick = { nav.nav(routeForUser(nostrPTag)) }, + ) { + Icon( + symbol = MaterialSymbols.AutoMirrored.OpenInNew, + null, + modifier = Size15Modifier, + tint = MaterialTheme.colorScheme.lessImportantLink, + ) + } } } } diff --git a/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/note/NoteQuickActionMenu.kt b/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/note/NoteQuickActionMenu.kt index 4dfbb1555..a20547295 100644 --- a/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/note/NoteQuickActionMenu.kt +++ b/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/note/NoteQuickActionMenu.kt @@ -116,14 +116,11 @@ val graspLink = { graspNumber: String -> val externalLinkForNote = { note: Note -> if (note is AddressableNote) { - if (note.event?.bountyBaseReward() != null) { - "https://nostrbounties.com/b/${note.toNAddr()}" - } else if (note.event is PeopleListEvent) { - "https://listr.lol/a/${note.toNAddr()}" - } else if (note.event is FollowListEvent) { - "https://following.space/d/${note.address.dTag}?p=${note.address.pubKeyHex}" - } else { - njumpLink(note.toNAddr()) + when { + note.event?.bountyBaseReward() != null -> "https://nostrbounties.com/b/${note.toNAddr()}" + note.event is PeopleListEvent -> "https://listr.lol/a/${note.toNAddr()}" + note.event is FollowListEvent -> "https://following.space/d/${note.address.dTag}?p=${note.address.pubKeyHex}" + else -> njumpLink(note.toNAddr()) } } else { njumpLink(note.toNEvent()) diff --git a/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/note/ReactionsRow.kt b/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/note/ReactionsRow.kt index ef12d1a32..bed452a13 100644 --- a/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/note/ReactionsRow.kt +++ b/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/note/ReactionsRow.kt @@ -1146,20 +1146,28 @@ private fun likeClick( } val choices = accountViewModel.reactionChoices() - if (choices.isEmpty()) { - accountViewModel.toastManager.toast( - R.string.no_reactions_setup, - R.string.no_reaction_type_setup_long_press_to_change, - ) - } else if (!accountViewModel.isWriteable()) { - accountViewModel.toastManager.toast( - R.string.read_only_user, - R.string.login_with_a_private_key_to_like_posts, - ) - } else if (choices.size == 1) { - onWantsToSignReaction() - } else if (choices.size > 1) { - onMultipleChoices() + when { + choices.isEmpty() -> { + accountViewModel.toastManager.toast( + R.string.no_reactions_setup, + R.string.no_reaction_type_setup_long_press_to_change, + ) + } + + !accountViewModel.isWriteable() -> { + accountViewModel.toastManager.toast( + R.string.read_only_user, + R.string.login_with_a_private_key_to_like_posts, + ) + } + + choices.size == 1 -> { + onWantsToSignReaction() + } + + choices.size > 1 -> { + onMultipleChoices() + } } } @@ -1369,27 +1377,35 @@ fun zapClick( val choices = accountViewModel.zapAmountChoices() - if (choices.isEmpty()) { - onCustomAmount() - } else if (!accountViewModel.isWriteable()) { - accountViewModel.toastManager.toast( - R.string.error_dialog_zap_error, - R.string.login_with_a_private_key_to_be_able_to_send_zaps, - ) - } else if (choices.size == 1) { - onZapStarts() - accountViewModel.zap( - baseNote, - choices.first() * 1000, - null, - "", - context, - onError = onError, - onProgress = { onZappingProgress(it) }, - onPayViaIntent = onPayViaIntent, - ) - } else if (choices.size > 1) { - onMultipleChoices() + when { + choices.isEmpty() -> { + onCustomAmount() + } + + !accountViewModel.isWriteable() -> { + accountViewModel.toastManager.toast( + R.string.error_dialog_zap_error, + R.string.login_with_a_private_key_to_be_able_to_send_zaps, + ) + } + + choices.size == 1 -> { + onZapStarts() + accountViewModel.zap( + baseNote, + choices.first() * 1000, + null, + "", + context, + onError = onError, + onProgress = { onZappingProgress(it) }, + onPayViaIntent = onPayViaIntent, + ) + } + + choices.size > 1 -> { + onMultipleChoices() + } } } diff --git a/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/note/TimeAgoFormatter.kt b/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/note/TimeAgoFormatter.kt index c3986ac97..deea89fdf 100644 --- a/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/note/TimeAgoFormatter.kt +++ b/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/note/TimeAgoFormatter.kt @@ -56,34 +56,45 @@ fun timeAgo( val timeDifference = TimeUtils.now() - time - return if (timeDifference > TimeUtils.ONE_YEAR) { - // Dec 12, 2022 + return when { + timeDifference > TimeUtils.ONE_YEAR -> { + // Dec 12, 2022 - if (locale != Locale.getDefault()) { - locale = Locale.getDefault() - yearFormatter = SimpleDateFormat(YEAR_DATE_FORMAT, locale) - monthFormatter = SimpleDateFormat(MONTH_DATE_FORMAT, locale) + if (locale != Locale.getDefault()) { + locale = Locale.getDefault() + yearFormatter = SimpleDateFormat(YEAR_DATE_FORMAT, locale) + monthFormatter = SimpleDateFormat(MONTH_DATE_FORMAT, locale) + } + + prefix + yearFormatter.format(time * 1000) } - prefix + yearFormatter.format(time * 1000) - } else if (timeDifference > TimeUtils.ONE_MONTH) { - // Dec 12 - if (locale != Locale.getDefault()) { - locale = Locale.getDefault() - yearFormatter = SimpleDateFormat(YEAR_DATE_FORMAT, locale) - monthFormatter = SimpleDateFormat(MONTH_DATE_FORMAT, locale) + timeDifference > TimeUtils.ONE_MONTH -> { + // Dec 12 + if (locale != Locale.getDefault()) { + locale = Locale.getDefault() + yearFormatter = SimpleDateFormat(YEAR_DATE_FORMAT, locale) + monthFormatter = SimpleDateFormat(MONTH_DATE_FORMAT, locale) + } + + prefix + monthFormatter.format(time * 1000) } - prefix + monthFormatter.format(time * 1000) - } else if (timeDifference > TimeUtils.ONE_DAY) { - // 2 days - prefix + (timeDifference / TimeUtils.ONE_DAY).toString() + stringRes(context, days) - } else if (timeDifference > TimeUtils.ONE_HOUR) { - prefix + (timeDifference / TimeUtils.ONE_HOUR).toString() + stringRes(context, hours) - } else if (timeDifference > TimeUtils.ONE_MINUTE) { - prefix + (timeDifference / TimeUtils.ONE_MINUTE).toString() + stringRes(context, minutes) - } else { - prefix + stringRes(context, seconds) + timeDifference > TimeUtils.ONE_DAY -> { + prefix + (timeDifference / TimeUtils.ONE_DAY).toString() + stringRes(context, days) + } + + timeDifference > TimeUtils.ONE_HOUR -> { + prefix + (timeDifference / TimeUtils.ONE_HOUR).toString() + stringRes(context, hours) + } + + timeDifference > TimeUtils.ONE_MINUTE -> { + prefix + (timeDifference / TimeUtils.ONE_MINUTE).toString() + stringRes(context, minutes) + } + + else -> { + prefix + stringRes(context, seconds) + } } } @@ -96,34 +107,45 @@ fun timeAgoNoDot( val timeDifference = TimeUtils.now() - time - return if (timeDifference > TimeUtils.ONE_YEAR) { - // Dec 12, 2022 + return when { + timeDifference > TimeUtils.ONE_YEAR -> { + // Dec 12, 2022 - if (locale != Locale.getDefault()) { - locale = Locale.getDefault() - yearFormatter = SimpleDateFormat(YEAR_DATE_FORMAT, locale) - monthFormatter = SimpleDateFormat(MONTH_DATE_FORMAT, locale) + if (locale != Locale.getDefault()) { + locale = Locale.getDefault() + yearFormatter = SimpleDateFormat(YEAR_DATE_FORMAT, locale) + monthFormatter = SimpleDateFormat(MONTH_DATE_FORMAT, locale) + } + + yearFormatter.format(time * 1000) } - yearFormatter.format(time * 1000) - } else if (timeDifference > TimeUtils.ONE_MONTH) { - // Dec 12 - if (locale != Locale.getDefault()) { - locale = Locale.getDefault() - yearFormatter = SimpleDateFormat(YEAR_DATE_FORMAT, locale) - monthFormatter = SimpleDateFormat(MONTH_DATE_FORMAT, locale) + timeDifference > TimeUtils.ONE_MONTH -> { + // Dec 12 + if (locale != Locale.getDefault()) { + locale = Locale.getDefault() + yearFormatter = SimpleDateFormat(YEAR_DATE_FORMAT, locale) + monthFormatter = SimpleDateFormat(MONTH_DATE_FORMAT, locale) + } + + monthFormatter.format(time * 1000) } - monthFormatter.format(time * 1000) - } else if (timeDifference > TimeUtils.ONE_DAY) { - // 2 days - (timeDifference / TimeUtils.ONE_DAY).toString() + stringRes(context, R.string.d) - } else if (timeDifference > TimeUtils.ONE_HOUR) { - (timeDifference / TimeUtils.ONE_HOUR).toString() + stringRes(context, R.string.h) - } else if (timeDifference > TimeUtils.ONE_MINUTE) { - (timeDifference / TimeUtils.ONE_MINUTE).toString() + stringRes(context, R.string.m) - } else { - stringRes(context, R.string.now) + timeDifference > TimeUtils.ONE_DAY -> { + (timeDifference / TimeUtils.ONE_DAY).toString() + stringRes(context, R.string.d) + } + + timeDifference > TimeUtils.ONE_HOUR -> { + (timeDifference / TimeUtils.ONE_HOUR).toString() + stringRes(context, R.string.h) + } + + timeDifference > TimeUtils.ONE_MINUTE -> { + (timeDifference / TimeUtils.ONE_MINUTE).toString() + stringRes(context, R.string.m) + } + + else -> { + stringRes(context, R.string.now) + } } } @@ -136,34 +158,45 @@ fun timeAgoNoDotNoDay( val timeDifference = TimeUtils.now() - time - return if (timeDifference > TimeUtils.ONE_YEAR) { - // Dec 12, 2022 + return when { + timeDifference > TimeUtils.ONE_YEAR -> { + // Dec 12, 2022 - if (locale != Locale.getDefault()) { - locale = Locale.getDefault() - yearNoDayFormatter = SimpleDateFormat(YEAR_NO_DAY_DATE_FORMAT, locale) - monthNoDayFormatter = SimpleDateFormat(MONTH_NO_DAY_DATE_FORMAT, locale) + if (locale != Locale.getDefault()) { + locale = Locale.getDefault() + yearNoDayFormatter = SimpleDateFormat(YEAR_NO_DAY_DATE_FORMAT, locale) + monthNoDayFormatter = SimpleDateFormat(MONTH_NO_DAY_DATE_FORMAT, locale) + } + + yearNoDayFormatter.format(time * 1000) } - yearNoDayFormatter.format(time * 1000) - } else if (timeDifference > TimeUtils.ONE_MONTH) { - // Dec 12 - if (locale != Locale.getDefault()) { - locale = Locale.getDefault() - yearNoDayFormatter = SimpleDateFormat(YEAR_NO_DAY_DATE_FORMAT, locale) - monthNoDayFormatter = SimpleDateFormat(MONTH_NO_DAY_DATE_FORMAT, locale) + timeDifference > TimeUtils.ONE_MONTH -> { + // Dec 12 + if (locale != Locale.getDefault()) { + locale = Locale.getDefault() + yearNoDayFormatter = SimpleDateFormat(YEAR_NO_DAY_DATE_FORMAT, locale) + monthNoDayFormatter = SimpleDateFormat(MONTH_NO_DAY_DATE_FORMAT, locale) + } + + monthNoDayFormatter.format(time * 1000) } - monthNoDayFormatter.format(time * 1000) - } else if (timeDifference > TimeUtils.ONE_DAY) { - // 2 days - (timeDifference / TimeUtils.ONE_DAY).toString() + stringRes(context, R.string.d) - } else if (timeDifference > TimeUtils.ONE_HOUR) { - (timeDifference / TimeUtils.ONE_HOUR).toString() + stringRes(context, R.string.h) - } else if (timeDifference > TimeUtils.ONE_MINUTE) { - (timeDifference / TimeUtils.ONE_MINUTE).toString() + stringRes(context, R.string.m) - } else { - stringRes(context, R.string.now) + timeDifference > TimeUtils.ONE_DAY -> { + (timeDifference / TimeUtils.ONE_DAY).toString() + stringRes(context, R.string.d) + } + + timeDifference > TimeUtils.ONE_HOUR -> { + (timeDifference / TimeUtils.ONE_HOUR).toString() + stringRes(context, R.string.h) + } + + timeDifference > TimeUtils.ONE_MINUTE -> { + (timeDifference / TimeUtils.ONE_MINUTE).toString() + stringRes(context, R.string.m) + } + + else -> { + stringRes(context, R.string.now) + } } } @@ -176,34 +209,45 @@ fun timeAheadNoDot( val timeDifference = time - TimeUtils.now() - return if (timeDifference > TimeUtils.ONE_YEAR) { - // Dec 12, 2022 + return when { + timeDifference > TimeUtils.ONE_YEAR -> { + // Dec 12, 2022 - if (locale != Locale.getDefault()) { - locale = Locale.getDefault() - yearFormatter = SimpleDateFormat(YEAR_DATE_FORMAT, locale) - monthFormatter = SimpleDateFormat(MONTH_DATE_FORMAT, locale) + if (locale != Locale.getDefault()) { + locale = Locale.getDefault() + yearFormatter = SimpleDateFormat(YEAR_DATE_FORMAT, locale) + monthFormatter = SimpleDateFormat(MONTH_DATE_FORMAT, locale) + } + + yearFormatter.format(time * 1000) } - yearFormatter.format(time * 1000) - } else if (timeDifference > TimeUtils.ONE_MONTH) { - // Dec 12 - if (locale != Locale.getDefault()) { - locale = Locale.getDefault() - yearFormatter = SimpleDateFormat(YEAR_DATE_FORMAT, locale) - monthFormatter = SimpleDateFormat(MONTH_DATE_FORMAT, locale) + timeDifference > TimeUtils.ONE_MONTH -> { + // Dec 12 + if (locale != Locale.getDefault()) { + locale = Locale.getDefault() + yearFormatter = SimpleDateFormat(YEAR_DATE_FORMAT, locale) + monthFormatter = SimpleDateFormat(MONTH_DATE_FORMAT, locale) + } + + monthFormatter.format(time * 1000) } - monthFormatter.format(time * 1000) - } else if (timeDifference > TimeUtils.ONE_DAY) { - // 2 days - round(timeDifference / TimeUtils.ONE_DAY.toFloat()).toInt().toString() + stringRes(context, R.string.d) - } else if (timeDifference > TimeUtils.ONE_HOUR) { - round(timeDifference / TimeUtils.ONE_HOUR.toFloat()).toInt().toString() + stringRes(context, R.string.h) - } else if (timeDifference > TimeUtils.ONE_MINUTE) { - round(timeDifference / TimeUtils.ONE_MINUTE.toFloat()).toInt().toString() + stringRes(context, R.string.m) - } else { - stringRes(context, R.string.now) + timeDifference > TimeUtils.ONE_DAY -> { + round(timeDifference / TimeUtils.ONE_DAY.toFloat()).toInt().toString() + stringRes(context, R.string.d) + } + + timeDifference > TimeUtils.ONE_HOUR -> { + round(timeDifference / TimeUtils.ONE_HOUR.toFloat()).toInt().toString() + stringRes(context, R.string.h) + } + + timeDifference > TimeUtils.ONE_MINUTE -> { + round(timeDifference / TimeUtils.ONE_MINUTE.toFloat()).toInt().toString() + stringRes(context, R.string.m) + } + + else -> { + stringRes(context, R.string.now) + } } } diff --git a/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/note/ZapPollNote.kt b/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/note/ZapPollNote.kt index ad9f78acc..a16430e08 100644 --- a/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/note/ZapPollNote.kt +++ b/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/note/ZapPollNote.kt @@ -547,59 +547,69 @@ fun ZapVote( interactionSource = remember { MutableInteractionSource() }, indication = ripple24dp, onClick = { - if (!accountViewModel.isWriteable()) { - accountViewModel.toastManager.toast( - R.string.read_only_user, - R.string.login_with_a_private_key_to_be_able_to_send_zaps, - ) - } else if (pollViewModel.isPollClosed()) { - accountViewModel.toastManager.toast( - R.string.poll_unable_to_vote, - R.string.poll_is_closed_explainer, - ) - } else if (isLoggedUser) { - accountViewModel.toastManager.toast( - R.string.poll_unable_to_vote, - R.string.poll_author_no_vote, - ) - } else if (pollViewModel.isVoteAmountAtomic() && poolOption.zappedByLoggedIn.value) { - // only allow one vote per option when min==max, i.e. atomic vote amount specified - accountViewModel.toastManager.toast( - R.string.poll_unable_to_vote, - R.string.one_vote_per_user_on_atomic_votes, - ) - return@combinedClickable - } else if ( + when { + !accountViewModel.isWriteable() -> { + accountViewModel.toastManager.toast( + R.string.read_only_user, + R.string.login_with_a_private_key_to_be_able_to_send_zaps, + ) + } + + pollViewModel.isPollClosed() -> { + accountViewModel.toastManager.toast( + R.string.poll_unable_to_vote, + R.string.poll_is_closed_explainer, + ) + } + + isLoggedUser -> { + accountViewModel.toastManager.toast( + R.string.poll_unable_to_vote, + R.string.poll_author_no_vote, + ) + } + + pollViewModel.isVoteAmountAtomic() && poolOption.zappedByLoggedIn.value -> { + // only allow one vote per option when min==max, i.e. atomic vote amount specified + accountViewModel.toastManager.toast( + R.string.poll_unable_to_vote, + R.string.one_vote_per_user_on_atomic_votes, + ) + return@combinedClickable + } + accountViewModel.zapAmountChoices().size == 1 && - pollViewModel.isValidInputVoteAmount(accountViewModel.zapAmountChoices().first()) - ) { - accountViewModel.zap( - baseNote, - accountViewModel.zapAmountChoices().first() * 1000, - poolOption.option, - "", - context, - onError = { title, message, user -> - zappingProgress = 0f - showErrorMessageDialog = StringToastMsg(title, message) - }, - onProgress = { scope.launch(Dispatchers.Main) { zappingProgress = it } }, - onPayViaIntent = { - if (it.size == 1) { - val payable = it.first() - payViaIntent(payable.invoice, context, { }) { error -> - zappingProgress = 0f - showErrorMessageDialog = StringToastMsg(stringRes(context, R.string.error_dialog_zap_error), error) + pollViewModel.isValidInputVoteAmount(accountViewModel.zapAmountChoices().first()) -> { + accountViewModel.zap( + baseNote, + accountViewModel.zapAmountChoices().first() * 1000, + poolOption.option, + "", + context, + onError = { title, message, user -> + zappingProgress = 0f + showErrorMessageDialog = StringToastMsg(title, message) + }, + onProgress = { scope.launch(Dispatchers.Main) { zappingProgress = it } }, + onPayViaIntent = { + if (it.size == 1) { + val payable = it.first() + payViaIntent(payable.invoice, context, { }) { error -> + zappingProgress = 0f + showErrorMessageDialog = StringToastMsg(stringRes(context, R.string.error_dialog_zap_error), error) + } + } else { + val uid = Uuid.random().toString() + accountViewModel.tempManualPaymentCache.put(uid, it) + nav.nav(Route.ManualZapSplitPayment(uid)) } - } else { - val uid = Uuid.random().toString() - accountViewModel.tempManualPaymentCache.put(uid, it) - nav.nav(Route.ManualZapSplitPayment(uid)) - } - }, - ) - } else { - wantsToZap = true + }, + ) + } + + else -> { + wantsToZap = true + } } }, ), diff --git a/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/note/ZapPollNoteViewModel.kt b/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/note/ZapPollNoteViewModel.kt index 58e304779..77d435e73 100644 --- a/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/note/ZapPollNoteViewModel.kt +++ b/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/note/ZapPollNoteViewModel.kt @@ -138,14 +138,11 @@ class PollNoteViewModel : ViewModel() { } == true fun voteAmountPlaceHolderText(sats: String): String = - if (valueMinimum == null && valueMaximum == null) { - sats - } else if (valueMinimum == null) { - "1—$valueMaximum $sats" - } else if (valueMaximum == null) { - ">$valueMinimum $sats" - } else { - "$valueMinimum—$valueMaximum $sats" + when { + valueMinimum == null && valueMaximum == null -> sats + valueMinimum == null -> "1—$valueMaximum $sats" + valueMaximum == null -> ">$valueMinimum $sats" + else -> "$valueMinimum—$valueMaximum $sats" } fun inputVoteAmountLong(textAmount: String) = @@ -160,46 +157,66 @@ class PollNoteViewModel : ViewModel() { } fun isValidInputVoteAmount(amount: BigDecimal?): Boolean { - if (amount == null) { - return false - } else if (valueMinimum == null && valueMaximum == null) { - if (amount > BigDecimal.ZERO) { - return true + when { + amount == null -> { + return false } - } else if (valueMinimum == null) { - if (amount > BigDecimal.ZERO && amount <= valueMaximumBD!!) { - return true + + valueMinimum == null && valueMaximum == null -> { + if (amount > BigDecimal.ZERO) { + return true + } } - } else if (valueMaximum == null) { - if (amount >= valueMinimumBD!!) { - return true + + valueMinimum == null -> { + if (amount > BigDecimal.ZERO && amount <= valueMaximumBD!!) { + return true + } } - } else { - if ((valueMinimumBD!! <= amount) && (amount <= valueMaximumBD!!)) { - return true + + valueMaximum == null -> { + if (amount >= valueMinimumBD!!) { + return true + } + } + + else -> { + if ((valueMinimumBD!! <= amount) && (amount <= valueMaximumBD!!)) { + return true + } } } return false } fun isValidInputVoteAmount(amount: Long?): Boolean { - if (amount == null) { - return false - } else if (valueMinimum == null && valueMaximum == null) { - if (amount > 0) { - return true + when { + amount == null -> { + return false } - } else if (valueMinimum == null) { - if (amount > 0 && amount <= valueMaximum!!) { - return true + + valueMinimum == null && valueMaximum == null -> { + if (amount > 0) { + return true + } } - } else if (valueMaximum == null) { - if (amount >= valueMinimum!!) { - return true + + valueMinimum == null -> { + if (amount > 0 && amount <= valueMaximum!!) { + return true + } } - } else { - if ((valueMinimum!! <= amount) && (amount <= valueMaximum!!)) { - return true + + valueMaximum == null -> { + if (amount >= valueMinimum!!) { + return true + } + } + + else -> { + if ((valueMinimum!! <= amount) && (amount <= valueMaximum!!)) { + return true + } } } return false diff --git a/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/note/creators/previews/PreviewUrl.kt b/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/note/creators/previews/PreviewUrl.kt index 8f4b6ac89..df8d78753 100644 --- a/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/note/creators/previews/PreviewUrl.kt +++ b/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/note/creators/previews/PreviewUrl.kt @@ -60,40 +60,52 @@ fun PreviewUrl( accountViewModel: AccountViewModel, nav: INav, ) { - if (RichTextParser.isValidURL(myUrlPreview)) { - if (RichTextParser.isImageUrl(myUrlPreview)) { - AsyncImage( - model = myUrlPreview, - contentDescription = myUrlPreview, - contentScale = ContentScale.FillHeight, - modifier = Modifier.fillMaxHeight().aspectRatio(1f), - ) - } else if (RichTextParser.isVideoUrl(myUrlPreview)) { - VideoView( - myUrlPreview, - mimeType = null, - roundedCorner = false, - gallery = false, - contentScale = ContentScale.FillHeight, - accountViewModel = accountViewModel, - ) - } else { - MyLoadUrlPreviewDirect(myUrlPreview, myUrlPreview, accountViewModel) - } - } else if (RichTextParser.startsWithNIP19Scheme(myUrlPreview)) { - val bgColor = MaterialTheme.colorScheme.background - val backgroundColor = remember { mutableStateOf(bgColor) } + when { + RichTextParser.isValidURL(myUrlPreview) -> { + when { + RichTextParser.isImageUrl(myUrlPreview) -> { + AsyncImage( + model = myUrlPreview, + contentDescription = myUrlPreview, + contentScale = ContentScale.FillHeight, + modifier = Modifier.fillMaxHeight().aspectRatio(1f), + ) + } - BechLinkPreview( - word = myUrlPreview, - canPreview = true, - quotesLeft = 1, - backgroundColor = backgroundColor, - accountViewModel = accountViewModel, - nav = nav, - ) - } else if (RichTextParser.isUrlWithoutScheme(myUrlPreview)) { - MyLoadUrlPreviewDirect("https://$myUrlPreview", myUrlPreview, accountViewModel) + RichTextParser.isVideoUrl(myUrlPreview) -> { + VideoView( + myUrlPreview, + mimeType = null, + roundedCorner = false, + gallery = false, + contentScale = ContentScale.FillHeight, + accountViewModel = accountViewModel, + ) + } + + else -> { + MyLoadUrlPreviewDirect(myUrlPreview, myUrlPreview, accountViewModel) + } + } + } + + RichTextParser.startsWithNIP19Scheme(myUrlPreview) -> { + val bgColor = MaterialTheme.colorScheme.background + val backgroundColor = remember { mutableStateOf(bgColor) } + + BechLinkPreview( + word = myUrlPreview, + canPreview = true, + quotesLeft = 1, + backgroundColor = backgroundColor, + accountViewModel = accountViewModel, + nav = nav, + ) + } + + RichTextParser.isUrlWithoutScheme(myUrlPreview) -> { + MyLoadUrlPreviewDirect("https://$myUrlPreview", myUrlPreview, accountViewModel) + } } } @@ -104,24 +116,30 @@ fun PreviewUrlFillWidth( nav: INav, ) { if (RichTextParser.isValidURL(myUrlPreview)) { - if (RichTextParser.isImageUrl(myUrlPreview)) { - AsyncImage( - model = myUrlPreview, - contentDescription = myUrlPreview, - contentScale = ContentScale.FillWidth, - modifier = Modifier.fillMaxHeight().aspectRatio(1f), - ) - } else if (RichTextParser.isVideoUrl(myUrlPreview)) { - VideoView( - myUrlPreview, - mimeType = null, - roundedCorner = false, - gallery = false, - contentScale = ContentScale.FillWidth, - accountViewModel = accountViewModel, - ) - } else { - MyLoadUrlPreviewDirectFillWidth(myUrlPreview, myUrlPreview, accountViewModel) + when { + RichTextParser.isImageUrl(myUrlPreview) -> { + AsyncImage( + model = myUrlPreview, + contentDescription = myUrlPreview, + contentScale = ContentScale.FillWidth, + modifier = Modifier.fillMaxHeight().aspectRatio(1f), + ) + } + + RichTextParser.isVideoUrl(myUrlPreview) -> { + VideoView( + myUrlPreview, + mimeType = null, + roundedCorner = false, + gallery = false, + contentScale = ContentScale.FillWidth, + accountViewModel = accountViewModel, + ) + } + + else -> { + MyLoadUrlPreviewDirectFillWidth(myUrlPreview, myUrlPreview, accountViewModel) + } } } else if (RichTextParser.startsWithNIP19Scheme(myUrlPreview)) { val bgColor = MaterialTheme.colorScheme.background diff --git a/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/note/creators/userSuggestions/UserSuggestionState.kt b/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/note/creators/userSuggestions/UserSuggestionState.kt index 9643e4d07..f06630343 100644 --- a/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/note/creators/userSuggestions/UserSuggestionState.kt +++ b/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/note/creators/userSuggestions/UserSuggestionState.kt @@ -92,50 +92,58 @@ class UserSuggestionState( } else { null } - if (nip05 != null) { - runCatching { - nip05Client.get(nip05)?.let { info -> - val user = account.cache.checkGetOrCreateUser(info.pubkey) - if (user != null) { - info.relays.forEach { - it.normalizeRelayUrlOrNull()?.let { relay -> - account.cache.relayHints.addKey(user.pubkey(), relay) + when { + nip05 != null -> { + runCatching { + nip05Client.get(nip05)?.let { info -> + val user = account.cache.checkGetOrCreateUser(info.pubkey) + if (user != null) { + info.relays.forEach { + it.normalizeRelayUrlOrNull()?.let { relay -> + account.cache.relayHints.addKey(user.pubkey(), relay) + } + } + } + user + } + }.getOrNull() + } + + prefix.startsWithAny(userUriPrefixes) -> { + runCatching { + Nip19Parser.uriToRoute(prefix)?.entity?.let { parsed -> + when (parsed) { + is NSec -> { + account.cache.getOrCreateUser(parsed.toPubKey().toHexKey()) + } + + is NPub -> { + account.cache.getOrCreateUser(parsed.hex) + } + + is NProfile -> { + val user = account.cache.getOrCreateUser(parsed.hex) + parsed.relay.forEach { relay -> + account.cache.relayHints.addKey(user.pubkey(), relay) + } + user + } + + else -> { + null } } } - user - } - }.getOrNull() - } else if (prefix.startsWithAny(userUriPrefixes)) { - runCatching { - Nip19Parser.uriToRoute(prefix)?.entity?.let { parsed -> - when (parsed) { - is NSec -> { - account.cache.getOrCreateUser(parsed.toPubKey().toHexKey()) - } + }.getOrNull() + } - is NPub -> { - account.cache.getOrCreateUser(parsed.hex) - } + prefix.length == 64 && Hex.isHex64(prefix) -> { + account.cache.getOrCreateUser(prefix) + } - is NProfile -> { - val user = account.cache.getOrCreateUser(parsed.hex) - parsed.relay.forEach { relay -> - account.cache.relayHints.addKey(user.pubkey(), relay) - } - user - } - - else -> { - null - } - } - } - }.getOrNull() - } else if (prefix.length == 64 && Hex.isHex64(prefix)) { - account.cache.getOrCreateUser(prefix) - } else { - null + else -> { + null + } } } else { null diff --git a/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/note/types/Attestation.kt b/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/note/types/Attestation.kt index c777a12f2..a5bafcb6a 100644 --- a/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/note/types/Attestation.kt +++ b/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/note/types/Attestation.kt @@ -331,60 +331,66 @@ fun RenderAttestationRequest( } if (quotesLeft > 0) { - if (aboutAddress != null) { - LoadAddressableNote(aboutAddress, accountViewModel) { - if (it != null) { - Spacer(modifier = DoubleVertSpacer) - Text( - text = stringRes(R.string.attestation_requests_attestation_to), - style = MaterialTheme.typography.labelMedium, - color = MaterialTheme.colorScheme.onSurfaceVariant, - ) - NoteCompose( - baseNote = it, - modifier = MaterialTheme.colorScheme.replyModifier, - isQuotedNote = true, - unPackReply = ReplyRenderType.NONE, - makeItShort = true, - quotesLeft = quotesLeft - 1, - parentBackgroundColor = backgroundColor, - accountViewModel = accountViewModel, - nav = nav, - ) + when { + aboutAddress != null -> { + LoadAddressableNote(aboutAddress, accountViewModel) { + if (it != null) { + Spacer(modifier = DoubleVertSpacer) + Text( + text = stringRes(R.string.attestation_requests_attestation_to), + style = MaterialTheme.typography.labelMedium, + color = MaterialTheme.colorScheme.onSurfaceVariant, + ) + NoteCompose( + baseNote = it, + modifier = MaterialTheme.colorScheme.replyModifier, + isQuotedNote = true, + unPackReply = ReplyRenderType.NONE, + makeItShort = true, + quotesLeft = quotesLeft - 1, + parentBackgroundColor = backgroundColor, + accountViewModel = accountViewModel, + nav = nav, + ) + } } } - } else if (aboutEvent != null) { - LoadNote(aboutEvent, accountViewModel) { - if (it != null) { - Spacer(modifier = DoubleVertSpacer) - Text( - text = stringRes(R.string.attestation_requests_attestation_to), - style = MaterialTheme.typography.labelMedium, - color = MaterialTheme.colorScheme.onSurfaceVariant, - ) - NoteCompose( - baseNote = it, - modifier = MaterialTheme.colorScheme.replyModifier, - isQuotedNote = true, - unPackReply = ReplyRenderType.NONE, - makeItShort = true, - quotesLeft = quotesLeft - 1, - parentBackgroundColor = backgroundColor, - accountViewModel = accountViewModel, - nav = nav, - ) + + aboutEvent != null -> { + LoadNote(aboutEvent, accountViewModel) { + if (it != null) { + Spacer(modifier = DoubleVertSpacer) + Text( + text = stringRes(R.string.attestation_requests_attestation_to), + style = MaterialTheme.typography.labelMedium, + color = MaterialTheme.colorScheme.onSurfaceVariant, + ) + NoteCompose( + baseNote = it, + modifier = MaterialTheme.colorScheme.replyModifier, + isQuotedNote = true, + unPackReply = ReplyRenderType.NONE, + makeItShort = true, + quotesLeft = quotesLeft - 1, + parentBackgroundColor = backgroundColor, + accountViewModel = accountViewModel, + nav = nav, + ) + } } } - } else if (aboutPubkey != null) { - LoadUser(aboutPubkey, accountViewModel) { - if (it != null) { - Spacer(modifier = DoubleVertSpacer) - Text( - text = stringRes(R.string.attestation_requests_attestation_to), - style = MaterialTheme.typography.labelMedium, - color = MaterialTheme.colorScheme.onSurfaceVariant, - ) - UserCompose(it, accountViewModel = accountViewModel, nav = nav) + + aboutPubkey != null -> { + LoadUser(aboutPubkey, accountViewModel) { + if (it != null) { + Spacer(modifier = DoubleVertSpacer) + Text( + text = stringRes(R.string.attestation_requests_attestation_to), + style = MaterialTheme.typography.labelMedium, + color = MaterialTheme.colorScheme.onSurfaceVariant, + ) + UserCompose(it, accountViewModel = accountViewModel, nav = nav) + } } } } diff --git a/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/note/types/Highlight.kt b/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/note/types/Highlight.kt index 40f080cfb..ef181c81a 100644 --- a/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/note/types/Highlight.kt +++ b/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/note/types/Highlight.kt @@ -278,21 +278,29 @@ private fun DisplayQuoteAuthor( } } - if (addressable != null) { - addressable?.let { - DisplayEntryForNote(it, userBase, accountViewModel, nav) + when { + addressable != null -> { + addressable?.let { + DisplayEntryForNote(it, userBase, accountViewModel, nav) + } } - } else if (version != null) { - version?.let { - DisplayEntryForNote(it, userBase, accountViewModel, nav) - } - } else if (baseUrl != null) { - val url = "$baseUrl${if (baseUrl.contains("#")) "&" else "#"}:~:text=${Uri.encode(highlightQuote)}" - DisplayEntryForAUrl(url, userBase, accountViewModel, nav) - } else if (userBase != null) { - userBase?.let { - DisplayEntryForUser(it, accountViewModel, nav) + version != null -> { + version?.let { + DisplayEntryForNote(it, userBase, accountViewModel, nav) + } + } + + baseUrl != null -> { + val url = "$baseUrl${if (baseUrl.contains("#")) "&" else "#"}:~:text=${Uri.encode(highlightQuote)}" + + DisplayEntryForAUrl(url, userBase, accountViewModel, nav) + } + + userBase != null -> { + userBase?.let { + DisplayEntryForUser(it, accountViewModel, nav) + } } } } diff --git a/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/note/types/MedicalData.kt b/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/note/types/MedicalData.kt index f26bbd40d..79aac6452 100644 --- a/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/note/types/MedicalData.kt +++ b/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/note/types/MedicalData.kt @@ -233,14 +233,11 @@ fun RenderEyeGlassesPrescription( val isContacts = contactsRightEye != null || contactsLeftEye != null Text( - if (isGlasses && isContacts) { - "Vision Prescription" - } else if (isGlasses) { - "Glasses Prescription" - } else if (isContacts) { - "Contact Lenses Prescription" - } else { - "Empty Prescription" + when { + isGlasses && isContacts -> "Vision Prescription" + isGlasses -> "Glasses Prescription" + isContacts -> "Contact Lenses Prescription" + else -> "Empty Prescription" }, modifier = Modifier.padding(4.dp).fillMaxWidth(), textAlign = TextAlign.Center, diff --git a/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/AccountSessionManager.kt b/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/AccountSessionManager.kt index e6de75c91..8605707f9 100644 --- a/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/AccountSessionManager.kt +++ b/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/AccountSessionManager.kt @@ -134,35 +134,45 @@ class AccountSessionManager( } val accountSettings = - if (loginWithExternalSigner) { - AccountSettings( - keyPair = KeyPair(pubKey = pubKeyParsed), - transientAccount = transientAccount, - externalSignerPackageName = packageName.ifBlank { "com.greenart7c3.nostrsigner" }, - ) - } else if (key.startsWith("nsec")) { - val privHex = - decodePrivateKeyAsHexOrNull(key) - ?: throw Exception("Invalid nsec key") - AccountSettings( - keyPair = KeyPair(privKey = privHex.hexToByteArray()), - transientAccount = transientAccount, - ) - } else if (key.contains(" ") && Nip06().isValidMnemonic(key)) { - AccountSettings( - keyPair = KeyPair(privKey = Nip06().privateKeyFromMnemonic(key)), - transientAccount = transientAccount, - ) - } else if (pubKeyParsed != null) { - AccountSettings( - keyPair = KeyPair(pubKey = pubKeyParsed), - transientAccount = transientAccount, - ) - } else { - AccountSettings( - keyPair = KeyPair(Hex.decode(key)), - transientAccount = transientAccount, - ) + when { + loginWithExternalSigner -> { + AccountSettings( + keyPair = KeyPair(pubKey = pubKeyParsed), + transientAccount = transientAccount, + externalSignerPackageName = packageName.ifBlank { "com.greenart7c3.nostrsigner" }, + ) + } + + key.startsWith("nsec") -> { + val privHex = + decodePrivateKeyAsHexOrNull(key) + ?: throw Exception("Invalid nsec key") + AccountSettings( + keyPair = KeyPair(privKey = privHex.hexToByteArray()), + transientAccount = transientAccount, + ) + } + + key.contains(" ") && Nip06().isValidMnemonic(key) -> { + AccountSettings( + keyPair = KeyPair(privKey = Nip06().privateKeyFromMnemonic(key)), + transientAccount = transientAccount, + ) + } + + pubKeyParsed != null -> { + AccountSettings( + keyPair = KeyPair(pubKey = pubKeyParsed), + transientAccount = transientAccount, + ) + } + + else -> { + AccountSettings( + keyPair = KeyPair(Hex.decode(key)), + transientAccount = transientAccount, + ) + } } localPreferences.setDefaultAccount(accountSettings) diff --git a/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/AccountViewModel.kt b/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/AccountViewModel.kt index 774e62577..698011afa 100644 --- a/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/AccountViewModel.kt +++ b/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/AccountViewModel.kt @@ -1404,16 +1404,22 @@ class AccountViewModel( viewModelScope.launch(Dispatchers.IO) { for (note in notes) { val noteEvent = note.event - if (noteEvent is IsInPublicChatChannel) { - account.markAsRead("Channel/${noteEvent.channelId()}", noteEvent.createdAt) - } else if (noteEvent is ChatroomKeyable) { - account.markAsRead("Room/${noteEvent.chatroomKey(account.signer.pubKey).hashCode()}", noteEvent.createdAt) - } else if (noteEvent is DraftWrapEvent) { - val innerEvent = account.draftsDecryptionCache.preCachedDraft(noteEvent) - if (innerEvent is IsInPublicChatChannel) { - account.markAsRead("Channel/${innerEvent.channelId()}", noteEvent.createdAt) - } else if (innerEvent is ChatroomKeyable) { - account.markAsRead("Room/${innerEvent.chatroomKey(account.signer.pubKey).hashCode()}", noteEvent.createdAt) + when { + noteEvent is IsInPublicChatChannel -> { + account.markAsRead("Channel/${noteEvent.channelId()}", noteEvent.createdAt) + } + + noteEvent is ChatroomKeyable -> { + account.markAsRead("Room/${noteEvent.chatroomKey(account.signer.pubKey).hashCode()}", noteEvent.createdAt) + } + + noteEvent is DraftWrapEvent -> { + val innerEvent = account.draftsDecryptionCache.preCachedDraft(noteEvent) + if (innerEvent is IsInPublicChatChannel) { + account.markAsRead("Channel/${innerEvent.channelId()}", noteEvent.createdAt) + } else if (innerEvent is ChatroomKeyable) { + account.markAsRead("Room/${innerEvent.chatroomKey(account.signer.pubKey).hashCode()}", noteEvent.createdAt) + } } } } diff --git a/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/chats/feed/ChatMessageCompose.kt b/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/chats/feed/ChatMessageCompose.kt index d01995e59..d0ac5a38e 100644 --- a/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/chats/feed/ChatMessageCompose.kt +++ b/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/chats/feed/ChatMessageCompose.kt @@ -172,15 +172,17 @@ fun NormalChatNote( remember(note) { derivedStateOf { val noteEvent = note.event - if (accountViewModel.isLoggedUser(note.author)) { - false // never shows the user's pictures - } else if (noteEvent is PrivateDmEvent) { - false // one-on-one, never shows it. - } else if (noteEvent is ChatroomKeyable) { + when { + accountViewModel.isLoggedUser(note.author) -> false + + // never shows the user's pictures + noteEvent is PrivateDmEvent -> false + + // one-on-one, never shows it. // only shows in a group chat. - noteEvent.chatroomKey(accountViewModel.userProfile().pubkeyHex).users.size > 1 - } else { - true + noteEvent is ChatroomKeyable -> noteEvent.chatroomKey(accountViewModel.userProfile().pubkeyHex).users.size > 1 + + else -> true } } } diff --git a/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/chats/privateDM/send/ChatNewMessageViewModel.kt b/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/chats/privateDM/send/ChatNewMessageViewModel.kt index 5b83b81b6..17e74d75a 100644 --- a/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/chats/privateDM/send/ChatNewMessageViewModel.kt +++ b/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/chats/privateDM/send/ChatNewMessageViewModel.kt @@ -735,17 +735,25 @@ class ChatNewMessageViewModel : fun autocompleteWithUser(item: User) { userSuggestions?.let { userSuggestions -> - if (userSuggestionsMainMessage == UserSuggestionAnchor.MAIN_MESSAGE) { - val lastWord = message.currentWord() - userSuggestions.replaceCurrentWord(message, lastWord, item) - urlPreviews.update(message.text.toString()) - } else if (userSuggestionsMainMessage == UserSuggestionAnchor.FORWARD_ZAPS) { - forwardZapTo.value.addItem(item) - forwardZapToEditting.value = TextFieldValue("") - } else if (userSuggestionsMainMessage == UserSuggestionAnchor.TO_USERS) { - val lastWord = toUsers.currentWord() - userSuggestions.replaceCurrentWord(toUsers, lastWord, item) - updateRoomFromUsersInput() + when (userSuggestionsMainMessage) { + UserSuggestionAnchor.MAIN_MESSAGE -> { + val lastWord = message.currentWord() + userSuggestions.replaceCurrentWord(message, lastWord, item) + urlPreviews.update(message.text.toString()) + } + + UserSuggestionAnchor.FORWARD_ZAPS -> { + forwardZapTo.value.addItem(item) + forwardZapToEditting.value = TextFieldValue("") + } + + UserSuggestionAnchor.TO_USERS -> { + val lastWord = toUsers.currentWord() + userSuggestions.replaceCurrentWord(toUsers, lastWord, item) + updateRoomFromUsersInput() + } + + else -> {} } userSuggestionsMainMessage = null diff --git a/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/chats/publicChannels/send/ChannelNewMessageViewModel.kt b/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/chats/publicChannels/send/ChannelNewMessageViewModel.kt index 7c2434977..805f6f5a9 100644 --- a/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/chats/publicChannels/send/ChannelNewMessageViewModel.kt +++ b/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/chats/publicChannels/send/ChannelNewMessageViewModel.kt @@ -415,85 +415,106 @@ open class ChannelNewMessageViewModel : val contentWarningReason = if (wantsToMarkAsSensitive) contentWarningDescription else null val localExpirationDate = if (wantsExpirationDate) expirationDate else null - return if (channel is PublicChatChannel) { - val replyingToEvent = replyTo.value?.toEventHint() - val channelEvent = channel.event + return when { + channel is PublicChatChannel -> { + val replyingToEvent = replyTo.value?.toEventHint() + val channelEvent = channel.event - if (replyingToEvent != null) { - ChannelMessageEvent.reply(tagger.message, replyingToEvent) { - notify(replyingToEvent.toPTag()) + if (replyingToEvent != null) { + ChannelMessageEvent.reply(tagger.message, replyingToEvent) { + notify(replyingToEvent.toPTag()) - hashtags(findHashtags(tagger.message)) - references(findURLs(tagger.message)) - quotes(findNostrUris(tagger.message)) - contentWarningReason?.let { contentWarning(it) } - localExpirationDate?.let { expiration(it) } + hashtags(findHashtags(tagger.message)) + references(findURLs(tagger.message)) + quotes(findNostrUris(tagger.message)) + contentWarningReason?.let { contentWarning(it) } + localExpirationDate?.let { expiration(it) } - geoHash?.let { geohash(it) } + geoHash?.let { geohash(it) } - emojis(emojis) - imetas(usedAttachments) - } - } else if (channelEvent != null) { - val hint = EventHintBundle(channelEvent, channelRelays.firstOrNull()) - ChannelMessageEvent.message(tagger.message, hint) { - hashtags(findHashtags(tagger.message)) - references(findURLs(tagger.message)) - quotes(findNostrUris(tagger.message)) - contentWarningReason?.let { contentWarning(it) } - localExpirationDate?.let { expiration(it) } + emojis(emojis) + imetas(usedAttachments) + } + } else if (channelEvent != null) { + val hint = EventHintBundle(channelEvent, channelRelays.firstOrNull()) + ChannelMessageEvent.message(tagger.message, hint) { + hashtags(findHashtags(tagger.message)) + references(findURLs(tagger.message)) + quotes(findNostrUris(tagger.message)) + contentWarningReason?.let { contentWarning(it) } + localExpirationDate?.let { expiration(it) } - geoHash?.let { geohash(it) } + geoHash?.let { geohash(it) } - emojis(emojis) - imetas(usedAttachments) - } - } else { - ChannelMessageEvent.message(tagger.message, ETag(channel.idHex, channelRelays.firstOrNull())) { - hashtags(findHashtags(tagger.message)) - references(findURLs(tagger.message)) - quotes(findNostrUris(tagger.message)) - contentWarningReason?.let { contentWarning(it) } - localExpirationDate?.let { expiration(it) } + emojis(emojis) + imetas(usedAttachments) + } + } else { + ChannelMessageEvent.message(tagger.message, ETag(channel.idHex, channelRelays.firstOrNull())) { + hashtags(findHashtags(tagger.message)) + references(findURLs(tagger.message)) + quotes(findNostrUris(tagger.message)) + contentWarningReason?.let { contentWarning(it) } + localExpirationDate?.let { expiration(it) } - geoHash?.let { geohash(it) } + geoHash?.let { geohash(it) } - emojis(emojis) - imetas(usedAttachments) + emojis(emojis) + imetas(usedAttachments) + } } } - } else if (channel is LiveActivitiesChannel) { - val replyingToEvent = replyTo.value?.toEventHint() - val activity = channel.info - if (replyingToEvent != null) { - LiveActivitiesChatMessageEvent.reply(tagger.message, replyingToEvent) { - notify(replyingToEvent.toPTag()) + channel is LiveActivitiesChannel -> { + val replyingToEvent = replyTo.value?.toEventHint() + val activity = channel.info - hashtags(findHashtags(tagger.message)) - references(findURLs(tagger.message)) - quotes(findNostrUris(tagger.message)) - contentWarningReason?.let { contentWarning(it) } - localExpirationDate?.let { expiration(it) } + if (replyingToEvent != null) { + LiveActivitiesChatMessageEvent.reply(tagger.message, replyingToEvent) { + notify(replyingToEvent.toPTag()) - emojis(emojis) - imetas(usedAttachments) + hashtags(findHashtags(tagger.message)) + references(findURLs(tagger.message)) + quotes(findNostrUris(tagger.message)) + contentWarningReason?.let { contentWarning(it) } + localExpirationDate?.let { expiration(it) } + + emojis(emojis) + imetas(usedAttachments) + } + } else if (activity != null) { + val hint = EventHintBundle(activity, channelRelays.firstOrNull()) + + LiveActivitiesChatMessageEvent.message(tagger.message, hint) { + hashtags(findHashtags(tagger.message)) + references(findURLs(tagger.message)) + quotes(findNostrUris(tagger.message)) + contentWarningReason?.let { contentWarning(it) } + localExpirationDate?.let { expiration(it) } + + emojis(emojis) + imetas(usedAttachments) + } + } else { + LiveActivitiesChatMessageEvent.message(tagger.message, channel.toATag()) { + hashtags(findHashtags(tagger.message)) + references(findURLs(tagger.message)) + quotes(findNostrUris(tagger.message)) + contentWarningReason?.let { contentWarning(it) } + localExpirationDate?.let { expiration(it) } + + emojis(emojis) + imetas(usedAttachments) + } } - } else if (activity != null) { - val hint = EventHintBundle(activity, channelRelays.firstOrNull()) + } - LiveActivitiesChatMessageEvent.message(tagger.message, hint) { - hashtags(findHashtags(tagger.message)) - references(findURLs(tagger.message)) - quotes(findNostrUris(tagger.message)) - contentWarningReason?.let { contentWarning(it) } - localExpirationDate?.let { expiration(it) } - - emojis(emojis) - imetas(usedAttachments) - } - } else { - LiveActivitiesChatMessageEvent.message(tagger.message, channel.toATag()) { + channel is EphemeralChatChannel -> { + EphemeralChatEvent.build( + tagger.message, + channel.roomId.relayUrl, + channel.roomId.id, + ) { hashtags(findHashtags(tagger.message)) references(findURLs(tagger.message)) quotes(findNostrUris(tagger.message)) @@ -504,23 +525,10 @@ open class ChannelNewMessageViewModel : imetas(usedAttachments) } } - } else if (channel is EphemeralChatChannel) { - EphemeralChatEvent.build( - tagger.message, - channel.roomId.relayUrl, - channel.roomId.id, - ) { - hashtags(findHashtags(tagger.message)) - references(findURLs(tagger.message)) - quotes(findNostrUris(tagger.message)) - contentWarningReason?.let { contentWarning(it) } - localExpirationDate?.let { expiration(it) } - emojis(emojis) - imetas(usedAttachments) + else -> { + null } - } else { - null } } diff --git a/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/discover/nip90DVMs/DVMCard.kt b/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/discover/nip90DVMs/DVMCard.kt index 329444e2f..2aa5abffa 100644 --- a/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/discover/nip90DVMs/DVMCard.kt +++ b/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/discover/nip90DVMs/DVMCard.kt @@ -140,18 +140,26 @@ fun RenderContentDVMThumb( card.amount?.let { var color = Color.DarkGray var amount = it - if (card.amount == "free" || card.amount == "0") { - color = MaterialTheme.colorScheme.secondary - amount = "Free" - } else if (card.amount == "flexible") { - color = MaterialTheme.colorScheme.primaryContainer - amount = "Flexible" - } else if (card.amount == "") { - color = MaterialTheme.colorScheme.grayText - amount = "Unknown" - } else { - color = MaterialTheme.colorScheme.primary - amount = card.amount + " Sats" + when { + card.amount == "free" || card.amount == "0" -> { + color = MaterialTheme.colorScheme.secondary + amount = "Free" + } + + card.amount == "flexible" -> { + color = MaterialTheme.colorScheme.primaryContainer + amount = "Flexible" + } + + card.amount == "" -> { + color = MaterialTheme.colorScheme.grayText + amount = "Unknown" + } + + else -> { + color = MaterialTheme.colorScheme.primary + amount = card.amount + " Sats" + } } Text( textAlign = TextAlign.End, diff --git a/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/notifications/NotificationSummaryState.kt b/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/notifications/NotificationSummaryState.kt index 136a8bc46..2dcbabcaf 100644 --- a/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/notifications/NotificationSummaryState.kt +++ b/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/notifications/NotificationSummaryState.kt @@ -98,41 +98,48 @@ class NotificationSummaryState( LocalCache.notes.forEach { _, it -> val noteEvent = it.event if (noteEvent != null && !takenIntoAccount.contains(noteEvent.id)) { - if (noteEvent is ReactionEvent) { - if (noteEvent.isTaggedUser(currentUser) && noteEvent.pubKey != currentUser) { - val netDate = formatDate(noteEvent.createdAt) - reactions[netDate] = (reactions[netDate] ?: 0) + 1 - takenIntoAccount.add(noteEvent.id) - } - } else if (noteEvent is RepostEvent || noteEvent is GenericRepostEvent) { - if (noteEvent.isTaggedUser(currentUser) && noteEvent.pubKey != currentUser) { - val netDate = formatDate(noteEvent.createdAt) - boosts[netDate] = (boosts[netDate] ?: 0) + 1 - takenIntoAccount.add(noteEvent.id) - } - } else if (noteEvent is LnZapEvent) { - // the user might be sending his own receipts noteEvent.pubKey != currentUser - if (noteEvent.isTaggedUser(currentUser)) { - val netDate = formatDate(noteEvent.createdAt) - zaps[netDate] = (zaps[netDate] ?: BigDecimal.ZERO) + (noteEvent.amount ?: BigDecimal.ZERO) - takenIntoAccount.add(noteEvent.id) - } - } else if (noteEvent is BaseThreadedEvent && - noteEvent.isTaggedUser(currentUser) && - noteEvent.pubKey != currentUser - ) { - val isCitation = - noteEvent.findCitations().any { - LocalCache.getNoteIfExists(it)?.author?.pubkeyHex == currentUser + when { + noteEvent is ReactionEvent -> { + if (noteEvent.isTaggedUser(currentUser) && noteEvent.pubKey != currentUser) { + val netDate = formatDate(noteEvent.createdAt) + reactions[netDate] = (reactions[netDate] ?: 0) + 1 + takenIntoAccount.add(noteEvent.id) } - - val netDate = formatDate(noteEvent.createdAt) - if (isCitation) { - boosts[netDate] = (boosts[netDate] ?: 0) + 1 - } else { - replies[netDate] = (replies[netDate] ?: 0) + 1 } - takenIntoAccount.add(noteEvent.id) + + noteEvent is RepostEvent || noteEvent is GenericRepostEvent -> { + if (noteEvent.isTaggedUser(currentUser) && noteEvent.pubKey != currentUser) { + val netDate = formatDate(noteEvent.createdAt) + boosts[netDate] = (boosts[netDate] ?: 0) + 1 + takenIntoAccount.add(noteEvent.id) + } + } + + noteEvent is LnZapEvent -> { + // the user might be sending his own receipts noteEvent.pubKey != currentUser + if (noteEvent.isTaggedUser(currentUser)) { + val netDate = formatDate(noteEvent.createdAt) + zaps[netDate] = (zaps[netDate] ?: BigDecimal.ZERO) + (noteEvent.amount ?: BigDecimal.ZERO) + takenIntoAccount.add(noteEvent.id) + } + } + + noteEvent is BaseThreadedEvent && + noteEvent.isTaggedUser(currentUser) && + noteEvent.pubKey != currentUser -> { + val isCitation = + noteEvent.findCitations().any { + LocalCache.getNoteIfExists(it)?.author?.pubkeyHex == currentUser + } + + val netDate = formatDate(noteEvent.createdAt) + if (isCitation) { + boosts[netDate] = (boosts[netDate] ?: 0) + 1 + } else { + replies[netDate] = (replies[netDate] ?: 0) + 1 + } + takenIntoAccount.add(noteEvent.id) + } } } } @@ -162,45 +169,52 @@ class NotificationSummaryState( newNotes.forEach { val noteEvent = it.event if (noteEvent != null && !takenIntoAccount.contains(noteEvent.id)) { - if (noteEvent is ReactionEvent) { - if (noteEvent.isTaggedUser(currentUser) && noteEvent.pubKey != currentUser) { - val netDate = formatDate(noteEvent.createdAt) - reactions[netDate] = (reactions[netDate] ?: 0) + 1 - takenIntoAccount.add(noteEvent.id) - hasNewElements = true - } - } else if (noteEvent is RepostEvent || noteEvent is GenericRepostEvent) { - if (noteEvent.isTaggedUser(currentUser) && noteEvent.pubKey != currentUser) { - val netDate = formatDate(noteEvent.createdAt) - boosts[netDate] = (boosts[netDate] ?: 0) + 1 - takenIntoAccount.add(noteEvent.id) - hasNewElements = true - } - } else if (noteEvent is LnZapEvent) { - if (noteEvent.isTaggedUser(currentUser)) { - // && noteEvent.pubKey != currentUser User might be sending his own receipts - val netDate = formatDate(noteEvent.createdAt) - zaps[netDate] = (zaps[netDate] ?: BigDecimal.ZERO) + (noteEvent.amount ?: BigDecimal.ZERO) - takenIntoAccount.add(noteEvent.id) - hasNewElements = true - } - } else if (noteEvent is BaseThreadedEvent && - noteEvent.isTaggedUser(currentUser) && - noteEvent.pubKey != currentUser - ) { - val isCitation = - noteEvent.findCitations().any { - LocalCache.getNoteIfExists(it)?.author?.pubkeyHex == currentUser + when { + noteEvent is ReactionEvent -> { + if (noteEvent.isTaggedUser(currentUser) && noteEvent.pubKey != currentUser) { + val netDate = formatDate(noteEvent.createdAt) + reactions[netDate] = (reactions[netDate] ?: 0) + 1 + takenIntoAccount.add(noteEvent.id) + hasNewElements = true } - - val netDate = formatDate(noteEvent.createdAt) - if (isCitation) { - boosts[netDate] = (boosts[netDate] ?: 0) + 1 - } else { - replies[netDate] = (replies[netDate] ?: 0) + 1 } - takenIntoAccount.add(noteEvent.id) - hasNewElements = true + + noteEvent is RepostEvent || noteEvent is GenericRepostEvent -> { + if (noteEvent.isTaggedUser(currentUser) && noteEvent.pubKey != currentUser) { + val netDate = formatDate(noteEvent.createdAt) + boosts[netDate] = (boosts[netDate] ?: 0) + 1 + takenIntoAccount.add(noteEvent.id) + hasNewElements = true + } + } + + noteEvent is LnZapEvent -> { + if (noteEvent.isTaggedUser(currentUser)) { + // && noteEvent.pubKey != currentUser User might be sending his own receipts + val netDate = formatDate(noteEvent.createdAt) + zaps[netDate] = (zaps[netDate] ?: BigDecimal.ZERO) + (noteEvent.amount ?: BigDecimal.ZERO) + takenIntoAccount.add(noteEvent.id) + hasNewElements = true + } + } + + noteEvent is BaseThreadedEvent && + noteEvent.isTaggedUser(currentUser) && + noteEvent.pubKey != currentUser -> { + val isCitation = + noteEvent.findCitations().any { + LocalCache.getNoteIfExists(it)?.author?.pubkeyHex == currentUser + } + + val netDate = formatDate(noteEvent.createdAt) + if (isCitation) { + boosts[netDate] = (boosts[netDate] ?: 0) + 1 + } else { + replies[netDate] = (replies[netDate] ?: 0) + 1 + } + takenIntoAccount.add(noteEvent.id) + hasNewElements = true + } } } } diff --git a/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/notifications/publicMessages/NewPublicMessageViewModel.kt b/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/notifications/publicMessages/NewPublicMessageViewModel.kt index fc197d120..25b5fd733 100644 --- a/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/notifications/publicMessages/NewPublicMessageViewModel.kt +++ b/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/notifications/publicMessages/NewPublicMessageViewModel.kt @@ -598,16 +598,24 @@ class NewPublicMessageViewModel : fun autocompleteWithUser(item: User) { userSuggestions?.let { userSuggestions -> - if (userSuggestionsMainMessage == UserSuggestionAnchor.MAIN_MESSAGE) { - val lastWord = message.currentWord() - userSuggestions.replaceCurrentWord(message, lastWord, item) - urlPreviews.update(message.text.toString()) - } else if (userSuggestionsMainMessage == UserSuggestionAnchor.FORWARD_ZAPS) { - forwardZapTo.value.addItem(item) - forwardZapToEditting.value = TextFieldValue("") - } else if (userSuggestionsMainMessage == UserSuggestionAnchor.TO_USERS) { - val lastWord = toUsers.currentWord() - userSuggestions.replaceCurrentWord(toUsers, lastWord, item) + when (userSuggestionsMainMessage) { + UserSuggestionAnchor.MAIN_MESSAGE -> { + val lastWord = message.currentWord() + userSuggestions.replaceCurrentWord(message, lastWord, item) + urlPreviews.update(message.text.toString()) + } + + UserSuggestionAnchor.FORWARD_ZAPS -> { + forwardZapTo.value.addItem(item) + forwardZapToEditting.value = TextFieldValue("") + } + + UserSuggestionAnchor.TO_USERS -> { + val lastWord = toUsers.currentWord() + userSuggestions.replaceCurrentWord(toUsers, lastWord, item) + } + + else -> {} } userSuggestionsMainMessage = null diff --git a/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/profile/gallery/GalleryThumb.kt b/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/profile/gallery/GalleryThumb.kt index a298f90c1..128abcce0 100644 --- a/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/profile/gallery/GalleryThumb.kt +++ b/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/profile/gallery/GalleryThumb.kt @@ -79,100 +79,110 @@ fun GalleryThumbnail( val noteEvent = noteState.note.event ?: return val content = - if (noteEvent is ProfileGalleryEntryEvent) { - noteEvent.urls().map { url -> - if (isVideoUrl(url)) { - MediaUrlVideo( - url = url, - description = noteEvent.content, - hash = null, - blurhash = noteEvent.blurhash(), - dim = noteEvent.dimensions(), - uri = null, - mimeType = noteEvent.mimeType(), - thumbhash = noteEvent.thumbhash(), - artworkUri = noteEvent.image()?.imageUrl ?: noteEvent.thumb()?.imageUrl, - ) - } else { + when { + noteEvent is ProfileGalleryEntryEvent -> { + noteEvent.urls().map { url -> + if (isVideoUrl(url)) { + MediaUrlVideo( + url = url, + description = noteEvent.content, + hash = null, + blurhash = noteEvent.blurhash(), + dim = noteEvent.dimensions(), + uri = null, + mimeType = noteEvent.mimeType(), + thumbhash = noteEvent.thumbhash(), + artworkUri = noteEvent.image()?.imageUrl ?: noteEvent.thumb()?.imageUrl, + ) + } else { + MediaUrlImage( + url = url, + description = noteEvent.content, + // We don't want to show the hash banner here + hash = null, + blurhash = noteEvent.blurhash(), + dim = noteEvent.dimensions(), + uri = null, + mimeType = noteEvent.mimeType(), + thumbhash = noteEvent.thumbhash(), + ) + } + } + } + + noteEvent is PictureEvent -> { + noteEvent.imetaTags().map { imeta -> MediaUrlImage( - url = url, + url = imeta.url, description = noteEvent.content, // We don't want to show the hash banner here hash = null, - blurhash = noteEvent.blurhash(), - dim = noteEvent.dimensions(), + blurhash = imeta.blurhash, + dim = imeta.dimension, uri = null, - mimeType = noteEvent.mimeType(), - thumbhash = noteEvent.thumbhash(), + mimeType = imeta.mimeType, + thumbhash = imeta.thumbhash, ) } } - } else if (noteEvent is PictureEvent) { - noteEvent.imetaTags().map { imeta -> - MediaUrlImage( - url = imeta.url, - description = noteEvent.content, - // We don't want to show the hash banner here - hash = null, - blurhash = imeta.blurhash, - dim = imeta.dimension, - uri = null, - mimeType = imeta.mimeType, - thumbhash = imeta.thumbhash, - ) - } - } else if (noteEvent is VideoEvent) { - // An HLS publish writes one imeta per rendition (master + each variant) on the same - // NIP-71 event. Rendering them all expands a single video into a sub-grid of black - // tiles inside one gallery card — the .m3u8 playlist is a text manifest Coil can't - // decode. Collapse to a single tile when every imeta is an HLS playlist; prefer an - // imeta that carries a poster image, breaking ties by smallest dimensions so we - // pick the lowest-resolution variant. Non-HLS multi-imeta videos keep the existing - // per-imeta layout. - val imetas = noteEvent.imetaTags() - val isAllHls = imetas.isNotEmpty() && imetas.all { isHlsMimeType(it.mimeType) } - val toRender = - if (isAllHls) { - val withPoster = imetas.filter { it.image.isNotEmpty() } - val pick = - withPoster.ifEmpty { imetas }.minBy { - it.dimension?.let { d -> d.width * d.height } ?: Int.MAX_VALUE - } - listOf(pick) - } else { - imetas - } - toRender.map { imeta -> - MediaUrlVideo( - url = imeta.url, - description = noteEvent.content, - // We don't want to show the hash banner here - hash = null, - blurhash = imeta.blurhash, - dim = imeta.dimension, - uri = null, - mimeType = imeta.mimeType, - thumbhash = imeta.thumbhash, - artworkUri = imeta.image.firstOrNull(), - ) - } - } else if (noteEvent is LiveActivitiesClipEvent) { - noteEvent.videoUrl()?.let { url -> - listOf( + + noteEvent is VideoEvent -> { + // An HLS publish writes one imeta per rendition (master + each variant) on the same + // NIP-71 event. Rendering them all expands a single video into a sub-grid of black + // tiles inside one gallery card — the .m3u8 playlist is a text manifest Coil can't + // decode. Collapse to a single tile when every imeta is an HLS playlist; prefer an + // imeta that carries a poster image, breaking ties by smallest dimensions so we + // pick the lowest-resolution variant. Non-HLS multi-imeta videos keep the existing + // per-imeta layout. + val imetas = noteEvent.imetaTags() + val isAllHls = imetas.isNotEmpty() && imetas.all { isHlsMimeType(it.mimeType) } + val toRender = + if (isAllHls) { + val withPoster = imetas.filter { it.image.isNotEmpty() } + val pick = + withPoster.ifEmpty { imetas }.minBy { + it.dimension?.let { d -> d.width * d.height } ?: Int.MAX_VALUE + } + listOf(pick) + } else { + imetas + } + toRender.map { imeta -> MediaUrlVideo( - url = url, - description = noteEvent.title() ?: noteEvent.content, + url = imeta.url, + description = noteEvent.content, + // We don't want to show the hash banner here hash = null, - blurhash = null, - dim = null, + blurhash = imeta.blurhash, + dim = imeta.dimension, uri = null, - mimeType = null, - thumbhash = null, - ), - ) - } ?: emptyList() - } else { - emptyList() + mimeType = imeta.mimeType, + thumbhash = imeta.thumbhash, + artworkUri = imeta.image.firstOrNull(), + ) + } + } + + noteEvent is LiveActivitiesClipEvent -> { + noteEvent.videoUrl()?.let { url -> + listOf( + MediaUrlVideo( + url = url, + description = noteEvent.title() ?: noteEvent.content, + hash = null, + blurhash = null, + dim = null, + uri = null, + mimeType = null, + thumbhash = null, + ), + ) + } ?: emptyList() + } + + else -> { + emptyList() + } } InnerRenderGalleryThumb(content, baseNote, accountViewModel) diff --git a/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/search/SearchBarViewModel.kt b/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/search/SearchBarViewModel.kt index 2ded2c901..1e5379347 100644 --- a/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/search/SearchBarViewModel.kt +++ b/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/search/SearchBarViewModel.kt @@ -125,50 +125,58 @@ class SearchBarViewModel( } else { null } - if (nip05 != null) { - runCatching { - nip05Client.get(nip05)?.let { info -> - val user = account.cache.checkGetOrCreateUser(info.pubkey) - if (user != null) { - info.relays.forEach { - it.normalizeRelayUrlOrNull()?.let { relay -> - account.cache.relayHints.addKey(user.pubkey(), relay) + when { + nip05 != null -> { + runCatching { + nip05Client.get(nip05)?.let { info -> + val user = account.cache.checkGetOrCreateUser(info.pubkey) + if (user != null) { + info.relays.forEach { + it.normalizeRelayUrlOrNull()?.let { relay -> + account.cache.relayHints.addKey(user.pubkey(), relay) + } + } + } + user + } + }.getOrNull() + } + + term.startsWithAny(userUriPrefixes) -> { + runCatching { + Nip19Parser.uriToRoute(term)?.entity?.let { parsed -> + when (parsed) { + is NSec -> { + account.cache.getOrCreateUser(parsed.toPubKey().toHexKey()) + } + + is NPub -> { + account.cache.getOrCreateUser(parsed.hex) + } + + is NProfile -> { + val user = account.cache.getOrCreateUser(parsed.hex) + parsed.relay.forEach { relay -> + account.cache.relayHints.addKey(user.pubkey(), relay) + } + user + } + + else -> { + null } } } - user - } - }.getOrNull() - } else if (term.startsWithAny(userUriPrefixes)) { - runCatching { - Nip19Parser.uriToRoute(term)?.entity?.let { parsed -> - when (parsed) { - is NSec -> { - account.cache.getOrCreateUser(parsed.toPubKey().toHexKey()) - } + }.getOrNull() + } - is NPub -> { - account.cache.getOrCreateUser(parsed.hex) - } + term.length == 64 && Hex.isHex64(term) -> { + account.cache.getOrCreateUser(term) + } - is NProfile -> { - val user = account.cache.getOrCreateUser(parsed.hex) - parsed.relay.forEach { relay -> - account.cache.relayHints.addKey(user.pubkey(), relay) - } - user - } - - else -> { - null - } - } - } - }.getOrNull() - } else if (term.length == 64 && Hex.isHex64(term)) { - account.cache.getOrCreateUser(term) - } else { - null + else -> { + null + } } }.flowOn(Dispatchers.IO) diff --git a/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/video/VideoScreen.kt b/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/video/VideoScreen.kt index 226e47b52..c2b4de57c 100644 --- a/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/video/VideoScreen.kt +++ b/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/video/VideoScreen.kt @@ -168,34 +168,40 @@ fun VideoFeedLoaded( key = { _, item -> item.idHex }, contentType = { _, item -> item.event?.kind ?: -1 }, ) { _, item -> - if (item.event is PictureEvent) { - PictureCardCompose( - baseNote = item, - accountViewModel = accountViewModel, - nav = nav, - ) + when { + item.event is PictureEvent -> { + PictureCardCompose( + baseNote = item, + accountViewModel = accountViewModel, + nav = nav, + ) - HorizontalDivider( - thickness = DividerThickness, - ) + HorizontalDivider( + thickness = DividerThickness, + ) - Spacer(modifier = Modifier.height(8.dp)) - } else if (item.event is VideoEvent) { - VideoCardCompose(item, accountViewModel, nav) + Spacer(modifier = Modifier.height(8.dp)) + } - HorizontalDivider( - thickness = DividerThickness, - ) + item.event is VideoEvent -> { + VideoCardCompose(item, accountViewModel, nav) - Spacer(modifier = Modifier.height(8.dp)) - } else if (item.event is FileHeaderEvent) { - FileHeaderCardCompose(item, accountViewModel, nav) + HorizontalDivider( + thickness = DividerThickness, + ) - HorizontalDivider( - thickness = DividerThickness, - ) + Spacer(modifier = Modifier.height(8.dp)) + } - Spacer(modifier = Modifier.height(8.dp)) + item.event is FileHeaderEvent -> { + FileHeaderCardCompose(item, accountViewModel, nav) + + HorizontalDivider( + thickness = DividerThickness, + ) + + Spacer(modifier = Modifier.height(8.dp)) + } } } }