diff --git a/app/src/main/java/com/vitorpamplona/amethyst/ui/actions/RelaySelectionDialog.kt b/app/src/main/java/com/vitorpamplona/amethyst/ui/actions/RelaySelectionDialog.kt index b2286c749..a4cd084e2 100644 --- a/app/src/main/java/com/vitorpamplona/amethyst/ui/actions/RelaySelectionDialog.kt +++ b/app/src/main/java/com/vitorpamplona/amethyst/ui/actions/RelaySelectionDialog.kt @@ -49,6 +49,7 @@ import com.vitorpamplona.amethyst.R import com.vitorpamplona.amethyst.model.RelayBriefInfoCache import com.vitorpamplona.amethyst.service.Nip11Retriever import com.vitorpamplona.amethyst.service.relays.Relay +import com.vitorpamplona.amethyst.ui.actions.relays.RelayInformationDialog import com.vitorpamplona.amethyst.ui.screen.loggedIn.AccountViewModel import com.vitorpamplona.amethyst.ui.theme.FeedPadding import com.vitorpamplona.quartz.encoders.Nip11RelayInformation diff --git a/app/src/main/java/com/vitorpamplona/amethyst/ui/actions/relays/AllRelayListView.kt b/app/src/main/java/com/vitorpamplona/amethyst/ui/actions/relays/AllRelayListView.kt index a25cf511d..a73c625f0 100644 --- a/app/src/main/java/com/vitorpamplona/amethyst/ui/actions/relays/AllRelayListView.kt +++ b/app/src/main/java/com/vitorpamplona/amethyst/ui/actions/relays/AllRelayListView.kt @@ -27,6 +27,7 @@ import androidx.compose.foundation.layout.Spacer import androidx.compose.foundation.layout.fillMaxSize import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.foundation.layout.padding +import androidx.compose.foundation.lazy.LazyColumn import androidx.compose.material3.Button import androidx.compose.material3.ExperimentalMaterial3Api import androidx.compose.material3.MaterialTheme @@ -46,12 +47,13 @@ import androidx.compose.ui.window.DialogProperties import androidx.lifecycle.compose.collectAsStateWithLifecycle import androidx.lifecycle.viewmodel.compose.viewModel import com.vitorpamplona.amethyst.R -import com.vitorpamplona.amethyst.service.relays.Constants.defaultRelays +import com.vitorpamplona.amethyst.service.relays.Constants import com.vitorpamplona.amethyst.ui.actions.CloseButton import com.vitorpamplona.amethyst.ui.actions.SaveButton import com.vitorpamplona.amethyst.ui.screen.loggedIn.AccountViewModel import com.vitorpamplona.amethyst.ui.theme.DoubleHorzSpacer -import com.vitorpamplona.amethyst.ui.theme.StdHorzSpacer +import com.vitorpamplona.amethyst.ui.theme.FeedPadding +import com.vitorpamplona.amethyst.ui.theme.grayText @OptIn(ExperimentalMaterial3Api::class) @Composable @@ -61,11 +63,15 @@ fun AllRelayListView( accountViewModel: AccountViewModel, nav: (String) -> Unit, ) { - val postViewModel: Kind3RelayListViewModel = viewModel() + val kind3ViewModel: Kind3RelayListViewModel = viewModel() val dmViewModel: DMRelayListViewModel = viewModel() - val feedState by postViewModel.relays.collectAsStateWithLifecycle() + val kind3FeedState by kind3ViewModel.relays.collectAsStateWithLifecycle() + val dmFeedState by dmViewModel.relays.collectAsStateWithLifecycle() - LaunchedEffect(Unit) { postViewModel.load(accountViewModel.account) } + LaunchedEffect(Unit) { + kind3ViewModel.load(accountViewModel.account) + dmViewModel.load(accountViewModel.account) + } Dialog( onDismissRequest = onClose, @@ -77,24 +83,12 @@ fun AllRelayListView( title = { Row( modifier = Modifier.fillMaxWidth(), - horizontalArrangement = Arrangement.SpaceBetween, + horizontalArrangement = Arrangement.End, verticalAlignment = Alignment.CenterVertically, ) { - Spacer(modifier = StdHorzSpacer) - - Button( - onClick = { - postViewModel.deleteAll() - defaultRelays.forEach { postViewModel.addRelay(it) } - postViewModel.loadRelayDocuments() - }, - ) { - Text(stringResource(R.string.default_relays)) - } - SaveButton( onPost = { - postViewModel.create() + kind3ViewModel.create() onClose() }, true, @@ -105,7 +99,7 @@ fun AllRelayListView( Spacer(modifier = DoubleHorzSpacer) CloseButton( onPress = { - postViewModel.clear() + kind3ViewModel.clear() onClose() }, ) @@ -119,16 +113,100 @@ fun AllRelayListView( ) { pad -> Column( modifier = - Modifier.fillMaxSize().padding( - 16.dp, - pad.calculateTopPadding(), - 16.dp, - pad.calculateBottomPadding(), - ), + Modifier + .fillMaxSize() + .padding( + 16.dp, + pad.calculateTopPadding(), + 16.dp, + pad.calculateBottomPadding(), + ), verticalArrangement = Arrangement.SpaceAround, ) { - Kind3RelayListView(feedState, postViewModel, accountViewModel, onClose, nav, relayToAdd) + LazyColumn(contentPadding = FeedPadding) { + item { + SettingsCategory( + stringResource(R.string.private_inbox_section), + stringResource(R.string.private_inbox_section_explainer), + Modifier.padding(bottom = 8.dp), + ) + } + renderDMItems(dmFeedState, dmViewModel, accountViewModel, onClose, nav) + + item { + SettingsCategoryWithButton( + stringResource(R.string.kind_3_section), + stringResource(R.string.kind_3_section_description), + action = { + ResetKind3Relays(kind3ViewModel) + }, + ) + } + renderKind3Items(kind3FeedState, kind3ViewModel, accountViewModel, onClose, nav, relayToAdd) + } } } } } + +@Composable +fun ResetKind3Relays(postViewModel: Kind3RelayListViewModel) { + Button( + onClick = { + postViewModel.deleteAll() + Constants.defaultRelays.forEach { postViewModel.addRelay(it) } + postViewModel.loadRelayDocuments() + }, + ) { + Text(stringResource(R.string.default_relays)) + } +} + +@Composable +fun SettingsCategory( + title: String, + description: String? = null, + modifier: Modifier = Modifier.padding(top = 24.dp, bottom = 8.dp), +) { + Column(modifier) { + Text( + text = title, + color = MaterialTheme.colorScheme.primary, + style = MaterialTheme.typography.titleSmall, + ) + if (description != null) { + Text( + description, + style = MaterialTheme.typography.bodyMedium, + color = MaterialTheme.colorScheme.grayText, + ) + } + } +} + +@Composable +fun SettingsCategoryWithButton( + title: String, + description: String? = null, + action: @Composable () -> Unit, + modifier: Modifier = Modifier.padding(top = 24.dp, bottom = 8.dp), +) { + Row(modifier) { + Column(modifier = Modifier.weight(1f)) { + Text( + text = title, + color = MaterialTheme.colorScheme.primary, + style = MaterialTheme.typography.titleSmall, + ) + if (description != null) { + Text( + text = description, + style = MaterialTheme.typography.bodyMedium, + color = MaterialTheme.colorScheme.grayText, + ) + } + } + + action() + } +} diff --git a/app/src/main/java/com/vitorpamplona/amethyst/ui/actions/relays/DMRelayListView.kt b/app/src/main/java/com/vitorpamplona/amethyst/ui/actions/relays/DMRelayListView.kt index 20f833691..28d856aa5 100644 --- a/app/src/main/java/com/vitorpamplona/amethyst/ui/actions/relays/DMRelayListView.kt +++ b/app/src/main/java/com/vitorpamplona/amethyst/ui/actions/relays/DMRelayListView.kt @@ -32,6 +32,7 @@ import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.foundation.layout.padding import androidx.compose.foundation.layout.size import androidx.compose.foundation.lazy.LazyColumn +import androidx.compose.foundation.lazy.LazyListScope import androidx.compose.foundation.lazy.itemsIndexed import androidx.compose.material.icons.Icons import androidx.compose.material.icons.filled.Cancel @@ -68,7 +69,6 @@ import com.vitorpamplona.amethyst.model.RelayBriefInfoCache import com.vitorpamplona.amethyst.service.Nip11CachedRetriever import com.vitorpamplona.amethyst.service.Nip11Retriever import com.vitorpamplona.amethyst.ui.actions.RelayInfoDialog -import com.vitorpamplona.amethyst.ui.actions.RelayInformationDialog import com.vitorpamplona.amethyst.ui.note.RenderRelayIcon import com.vitorpamplona.amethyst.ui.screen.loggedIn.AccountViewModel import com.vitorpamplona.amethyst.ui.theme.ButtonBorder @@ -100,22 +100,33 @@ fun DMRelayList( LazyColumn( contentPadding = FeedPadding, ) { - itemsIndexed(feedState, key = { _, item -> item.url }) { index, item -> - DMServerConfig( - item, - onDelete = { postViewModel.deleteRelay(item) }, - accountViewModel = accountViewModel, - ) { - onClose() - nav(it) - } - } + renderDMItems(feedState, postViewModel, accountViewModel, onClose, nav) + } + } +} + +fun LazyListScope.renderDMItems( + feedState: List, + postViewModel: DMRelayListViewModel, + accountViewModel: AccountViewModel, + onClose: () -> Unit, + nav: (String) -> Unit, +) { + itemsIndexed(feedState, key = { _, item -> item.url }) { index, item -> + DMServerConfig( + item, + onDelete = { postViewModel.deleteRelay(item) }, + accountViewModel = accountViewModel, + ) { + onClose() + nav(it) } } - Spacer(modifier = StdVertSpacer) - - DMEditableServerConfig { postViewModel.addRelay(it) } + item { + Spacer(modifier = StdVertSpacer) + DMEditableServerConfig { postViewModel.addRelay(it) } + } } @Composable diff --git a/app/src/main/java/com/vitorpamplona/amethyst/ui/actions/relays/Kind3RelayListView.kt b/app/src/main/java/com/vitorpamplona/amethyst/ui/actions/relays/Kind3RelayListView.kt index 30d39c567..672bfe9e7 100644 --- a/app/src/main/java/com/vitorpamplona/amethyst/ui/actions/relays/Kind3RelayListView.kt +++ b/app/src/main/java/com/vitorpamplona/amethyst/ui/actions/relays/Kind3RelayListView.kt @@ -31,6 +31,7 @@ import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.foundation.layout.padding import androidx.compose.foundation.layout.size import androidx.compose.foundation.lazy.LazyColumn +import androidx.compose.foundation.lazy.LazyListScope import androidx.compose.foundation.lazy.itemsIndexed import androidx.compose.material.icons.Icons import androidx.compose.material.icons.filled.Cancel @@ -74,7 +75,6 @@ import com.vitorpamplona.amethyst.service.Nip11Retriever import com.vitorpamplona.amethyst.service.relays.Constants import com.vitorpamplona.amethyst.service.relays.FeedType import com.vitorpamplona.amethyst.ui.actions.RelayInfoDialog -import com.vitorpamplona.amethyst.ui.actions.RelayInformationDialog import com.vitorpamplona.amethyst.ui.note.RenderRelayIcon import com.vitorpamplona.amethyst.ui.screen.loggedIn.AccountViewModel import com.vitorpamplona.amethyst.ui.theme.ButtonBorder @@ -104,35 +104,44 @@ fun Kind3RelayListView( relayToAdd: String, ) { Row(modifier = Modifier.fillMaxWidth(), verticalAlignment = Alignment.CenterVertically) { - LazyColumn( - contentPadding = FeedPadding, - ) { - itemsIndexed(feedState, key = { _, item -> item.url }) { index, item -> - LoadRelayInfo( - item, - onToggleDownload = { postViewModel.toggleDownload(it) }, - onToggleUpload = { postViewModel.toggleUpload(it) }, - onToggleFollows = { postViewModel.toggleFollows(it) }, - onTogglePrivateDMs = { postViewModel.toggleMessages(it) }, - onTogglePublicChats = { postViewModel.togglePublicChats(it) }, - onToggleGlobal = { postViewModel.toggleGlobal(it) }, - onToggleSearch = { postViewModel.toggleSearch(it) }, - onDelete = { postViewModel.deleteRelay(it) }, - accountViewModel = accountViewModel, - ) { - onClose() - nav(it) - } - } - - item { - Spacer(modifier = StdVertSpacer) - Kind3RelayEditBox(relayToAdd) { postViewModel.addRelay(it) } - } + LazyColumn(contentPadding = FeedPadding) { + renderKind3Items(feedState, postViewModel, accountViewModel, onClose, nav, relayToAdd) } } } +fun LazyListScope.renderKind3Items( + feedState: List, + postViewModel: Kind3RelayListViewModel, + accountViewModel: AccountViewModel, + onClose: () -> Unit, + nav: (String) -> Unit, + relayToAdd: String, +) { + itemsIndexed(feedState, key = { _, item -> item.url }) { index, item -> + LoadRelayInfo( + item, + onToggleDownload = { postViewModel.toggleDownload(it) }, + onToggleUpload = { postViewModel.toggleUpload(it) }, + onToggleFollows = { postViewModel.toggleFollows(it) }, + onTogglePrivateDMs = { postViewModel.toggleMessages(it) }, + onTogglePublicChats = { postViewModel.togglePublicChats(it) }, + onToggleGlobal = { postViewModel.toggleGlobal(it) }, + onToggleSearch = { postViewModel.toggleSearch(it) }, + onDelete = { postViewModel.deleteRelay(it) }, + accountViewModel = accountViewModel, + ) { + onClose() + nav(it) + } + } + + item { + Spacer(modifier = StdVertSpacer) + Kind3RelayEditBox(relayToAdd) { postViewModel.addRelay(it) } + } +} + @Preview @Composable fun ServerConfigPreview() { diff --git a/app/src/main/java/com/vitorpamplona/amethyst/ui/actions/RelayInformationDialog.kt b/app/src/main/java/com/vitorpamplona/amethyst/ui/actions/relays/RelayInformationDialog.kt similarity index 99% rename from app/src/main/java/com/vitorpamplona/amethyst/ui/actions/RelayInformationDialog.kt rename to app/src/main/java/com/vitorpamplona/amethyst/ui/actions/relays/RelayInformationDialog.kt index c8c44970e..780d7d271 100644 --- a/app/src/main/java/com/vitorpamplona/amethyst/ui/actions/RelayInformationDialog.kt +++ b/app/src/main/java/com/vitorpamplona/amethyst/ui/actions/relays/RelayInformationDialog.kt @@ -18,7 +18,7 @@ * 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.actions +package com.vitorpamplona.amethyst.ui.actions.relays import androidx.compose.animation.Crossfade import androidx.compose.foundation.layout.Arrangement @@ -48,6 +48,7 @@ import androidx.compose.ui.window.Dialog import androidx.compose.ui.window.DialogProperties import com.vitorpamplona.amethyst.R import com.vitorpamplona.amethyst.model.RelayBriefInfoCache +import com.vitorpamplona.amethyst.ui.actions.CloseButton import com.vitorpamplona.amethyst.ui.components.ClickableEmail import com.vitorpamplona.amethyst.ui.components.ClickableUrl import com.vitorpamplona.amethyst.ui.note.LoadUser diff --git a/app/src/main/java/com/vitorpamplona/amethyst/ui/note/RelayListRow.kt b/app/src/main/java/com/vitorpamplona/amethyst/ui/note/RelayListRow.kt index ee5ecfcde..7e8b9671f 100644 --- a/app/src/main/java/com/vitorpamplona/amethyst/ui/note/RelayListRow.kt +++ b/app/src/main/java/com/vitorpamplona/amethyst/ui/note/RelayListRow.kt @@ -52,7 +52,7 @@ import com.vitorpamplona.amethyst.model.Note import com.vitorpamplona.amethyst.model.RelayBriefInfoCache import com.vitorpamplona.amethyst.service.Nip11CachedRetriever import com.vitorpamplona.amethyst.service.Nip11Retriever -import com.vitorpamplona.amethyst.ui.actions.RelayInformationDialog +import com.vitorpamplona.amethyst.ui.actions.relays.RelayInformationDialog import com.vitorpamplona.amethyst.ui.components.RobohashFallbackAsyncImage import com.vitorpamplona.amethyst.ui.screen.loggedIn.AccountViewModel import com.vitorpamplona.amethyst.ui.theme.RelayIconFilter diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index ee628becb..28bbf1280 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -812,6 +812,11 @@ Insert between 1-3 relays to serve as your private inbox. DM Inbox relays should accept any message from anyone, but only allow you to download them. Set up now + DM Inbox Relays + Insert between 1-3 relays to serve as your private inbox. Others will use these relays to send DMs to you. DM Inbox relays should accept any message from anyone, but only allow you to download them. Good options are:\n - inbox.nostr.wine (paid)\n - you.nostr1.com (personal relays - paid) + General Relays + Amethyst uses these relays to download posts for you. + Zap the Devs! Your donation helps us make a difference. Every sat counts! Donate Now