diff --git a/app/src/main/java/com/vitorpamplona/amethyst/ui/note/elements/AddInboxRelayForDMCard.kt b/app/src/main/java/com/vitorpamplona/amethyst/ui/note/elements/AddInboxRelayForDMCard.kt new file mode 100644 index 000000000..74387850b --- /dev/null +++ b/app/src/main/java/com/vitorpamplona/amethyst/ui/note/elements/AddInboxRelayForDMCard.kt @@ -0,0 +1,192 @@ +/** + * Copyright (c) 2024 Vitor Pamplona + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of + * this software and associated documentation files (the "Software"), to deal in + * the Software without restriction, including without limitation the rights to use, + * copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the + * Software, and to permit persons to whom the Software is furnished to do so, + * subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS + * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR + * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN + * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ +package com.vitorpamplona.amethyst.ui.note.elements + +import androidx.compose.foundation.layout.Arrangement +import androidx.compose.foundation.layout.Column +import androidx.compose.foundation.layout.Row +import androidx.compose.foundation.layout.Spacer +import androidx.compose.foundation.layout.fillMaxWidth +import androidx.compose.foundation.layout.padding +import androidx.compose.material3.Button +import androidx.compose.material3.Card +import androidx.compose.material3.IconButton +import androidx.compose.material3.MaterialTheme +import androidx.compose.material3.Text +import androidx.compose.runtime.Composable +import androidx.compose.runtime.getValue +import androidx.compose.runtime.livedata.observeAsState +import androidx.compose.runtime.setValue +import androidx.compose.ui.Modifier +import androidx.compose.ui.res.stringResource +import androidx.compose.ui.text.TextStyle +import androidx.compose.ui.text.font.FontWeight +import androidx.compose.ui.tooling.preview.Preview +import androidx.compose.ui.unit.dp +import androidx.compose.ui.unit.sp +import androidx.lifecycle.viewmodel.compose.viewModel +import com.vitorpamplona.amethyst.R +import com.vitorpamplona.amethyst.model.Account +import com.vitorpamplona.amethyst.model.LocalCache +import com.vitorpamplona.amethyst.model.Note +import com.vitorpamplona.amethyst.model.ThemeType +import com.vitorpamplona.amethyst.ui.note.CloseIcon +import com.vitorpamplona.amethyst.ui.note.LoadAddressableNote +import com.vitorpamplona.amethyst.ui.screen.SharedPreferencesViewModel +import com.vitorpamplona.amethyst.ui.screen.loggedIn.AccountViewModel +import com.vitorpamplona.amethyst.ui.theme.DoubleVertSpacer +import com.vitorpamplona.amethyst.ui.theme.Size10dp +import com.vitorpamplona.amethyst.ui.theme.Size20Modifier +import com.vitorpamplona.amethyst.ui.theme.StdVertSpacer +import com.vitorpamplona.amethyst.ui.theme.ThemeComparisonColumn +import com.vitorpamplona.amethyst.ui.theme.imageModifier +import com.vitorpamplona.quartz.crypto.KeyPair +import com.vitorpamplona.quartz.events.ChatMessageRelayListEvent +import com.vitorpamplona.quartz.utils.TimeUtils +import fr.acinq.secp256k1.Hex +import kotlinx.coroutines.CoroutineScope +import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.SupervisorJob +import kotlinx.coroutines.runBlocking + +@Preview +@Composable +fun AddInboxRelayForDMCardPreview() { + val sharedPreferencesViewModel: SharedPreferencesViewModel = viewModel() + val myCoroutineScope = CoroutineScope(Dispatchers.IO + SupervisorJob()) + + sharedPreferencesViewModel.init() + sharedPreferencesViewModel.updateTheme(ThemeType.DARK) + + val pubkey = "989c3734c46abac7ce3ce229971581a5a6ee39cdd6aa7261a55823fa7f8c4799" + + val myAccount = + Account( + keyPair = + KeyPair( + privKey = Hex.decode("0f761f8a5a481e26f06605a1d9b3e9eba7a107d351f43c43a57469b788274499"), + pubKey = Hex.decode(pubkey), + forcePubKeyCheck = false, + ), + scope = myCoroutineScope, + ) + + runBlocking(Dispatchers.IO) { + val createAt = TimeUtils.now() + val list = listOf("wss://inbox.nostr.wine", "wss://vitor.nostr1.com") + val tags = ChatMessageRelayListEvent.createTagArray(list) + val id = "ab" + + LocalCache.justConsume( + ChatMessageRelayListEvent( + id = id, + pubKey = pubkey, + createdAt = createAt, + tags = tags, + content = "", + sig = "", + ), + null, + ) + } + + val accountViewModel = + AccountViewModel( + myAccount, + sharedPreferencesViewModel.sharedPrefs, + ) + + LoadAddressableNote( + ChatMessageRelayListEvent.createAddressTag("989c3734c46abac7ce3ce229971581a5a6ee39cdd6aa7261a55823fa7f8c4799"), + accountViewModel, + ) { relayList -> + Text("Test" + relayList) + if (relayList != null) { + ThemeComparisonColumn { + AddInboxRelayForDMCard( + relayList, + accountViewModel, + nav = {}, + ) + } + } + } +} + +@Composable +fun AddInboxRelayForDMCard( + baseNote: Note, + accountViewModel: AccountViewModel, + nav: (String) -> Unit, +) { + val releaseNoteState by baseNote.live().metadata.observeAsState() + val releaseNote = releaseNoteState?.note ?: return + + Column(modifier = Modifier.padding(horizontal = Size10dp)) { + Card( + modifier = MaterialTheme.colorScheme.imageModifier, + ) { + Column( + modifier = Modifier.padding(16.dp), + ) { + // Title + Row( + modifier = Modifier.fillMaxWidth(), + horizontalArrangement = Arrangement.SpaceBetween, + ) { + Text( + text = stringResource(id = R.string.dm_relays_not_found), + style = + TextStyle( + fontSize = 20.sp, + fontWeight = FontWeight.Bold, + ), + ) + + IconButton( + modifier = Size20Modifier, + onClick = { accountViewModel.markDonatedInThisVersion() }, + ) { + CloseIcon() + } + } + + Spacer(modifier = StdVertSpacer) + + Text( + text = stringResource(id = R.string.dm_relays_not_found_description), + ) + + Spacer(modifier = StdVertSpacer) + + Button( + onClick = { + }, + modifier = Modifier.fillMaxWidth(), + ) { + Text(text = stringResource(id = R.string.dm_relays_not_found_create_now)) + } + } + } + + Spacer(modifier = DoubleVertSpacer) + } +} diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index a23c028b9..9701422ef 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -798,6 +798,11 @@ Invalid address Amethyst received a URI to open but that uri was invalid: %1$s + Set up your Private Inbox relays + This setting informs everybody which relays to use when sending messages to you. Without them you might miss some messages. + DM Inbox relays accept any message from anyone, but only allows you to download them. For example, inbox.nostr.wine operates in this way. + Set up now + Zap the Devs! Your donation helps us make a difference. Every sat counts! Donate Now diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/events/ChatMessageRelayListEvent.kt b/quartz/src/main/java/com/vitorpamplona/quartz/events/ChatMessageRelayListEvent.kt index f10a5a255..80fd277a5 100644 --- a/quartz/src/main/java/com/vitorpamplona/quartz/events/ChatMessageRelayListEvent.kt +++ b/quartz/src/main/java/com/vitorpamplona/quartz/events/ChatMessageRelayListEvent.kt @@ -55,19 +55,19 @@ class ChatMessageRelayListEvent( return ATag.assembleATag(KIND, pubKey, FIXED_D_TAG) } + fun createTagArray(relays: List): Array> { + return relays.map { + arrayOf("relay", it) + }.plusElement(arrayOf("alt", "Relay list for private messages")).toTypedArray() + } + fun create( relays: List, signer: NostrSigner, createdAt: Long = TimeUtils.now(), onReady: (ChatMessageRelayListEvent) -> Unit, ) { - val tags = - relays.map { - arrayOf("relay", it) - }.plusElement(arrayOf("alt", "Relay list for private messages")).toTypedArray() - val msg = "" - - signer.sign(createdAt, KIND, tags, msg, onReady) + signer.sign(createdAt, KIND, createTagArray(relays), "", onReady) } } }