diff --git a/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/navigation/AppNavigation.kt b/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/navigation/AppNavigation.kt index d31f7171b..84fe53131 100644 --- a/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/navigation/AppNavigation.kt +++ b/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/navigation/AppNavigation.kt @@ -104,6 +104,7 @@ import com.vitorpamplona.amethyst.ui.screen.loggedIn.redirect.LoadRedirectScreen import com.vitorpamplona.amethyst.ui.screen.loggedIn.relays.AllRelayListScreen import com.vitorpamplona.amethyst.ui.screen.loggedIn.relays.RelayInformationScreen import com.vitorpamplona.amethyst.ui.screen.loggedIn.search.SearchScreen +import com.vitorpamplona.amethyst.ui.screen.loggedIn.settings.AllSettingsScreen import com.vitorpamplona.amethyst.ui.screen.loggedIn.settings.NIP47SetupScreen import com.vitorpamplona.amethyst.ui.screen.loggedIn.settings.SecurityFiltersScreen import com.vitorpamplona.amethyst.ui.screen.loggedIn.settings.SettingsScreen @@ -162,6 +163,7 @@ fun AppNavigation( composableFromBottomArgs { NewUserMetadataScreen(nav, accountViewModel) } composable { SearchScreen(accountViewModel, nav) } + composableFromEnd { AllSettingsScreen(nav) } composableFromEnd { SecurityFiltersScreen(accountViewModel, nav) } composableFromEnd { PrivacyOptionsScreen(Amethyst.instance.torPrefs.value, nav) } composableFromEnd { BookmarkListScreen(accountViewModel, nav) } diff --git a/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/navigation/drawer/DrawerContent.kt b/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/navigation/drawer/DrawerContent.kt index dc0e12fcc..4d62d6ca7 100644 --- a/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/navigation/drawer/DrawerContent.kt +++ b/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/navigation/drawer/DrawerContent.kt @@ -46,14 +46,11 @@ import androidx.compose.material.icons.Icons import androidx.compose.material.icons.automirrored.filled.Send import androidx.compose.material.icons.filled.AccountCircle import androidx.compose.material.icons.filled.Delete -import androidx.compose.material.icons.outlined.CloudUpload import androidx.compose.material.icons.outlined.CollectionsBookmark import androidx.compose.material.icons.outlined.Drafts import androidx.compose.material.icons.outlined.GroupAdd import androidx.compose.material.icons.outlined.Key -import androidx.compose.material.icons.outlined.Security import androidx.compose.material.icons.outlined.Settings -import androidx.compose.material.icons.outlined.Translate import androidx.compose.material3.HorizontalDivider import androidx.compose.material3.Icon import androidx.compose.material3.IconButton @@ -480,41 +477,6 @@ fun ListContent( route = Route.Chess, ) - IconRowRelays( - accountViewModel = accountViewModel, - onClick = { - nav.closeDrawer() - nav.nav(Route.EditRelays) - }, - ) - - IconRow( - title = R.string.media_servers, - icon = Icons.Outlined.CloudUpload, - tint = MaterialTheme.colorScheme.onBackground, - onClick = { - nav.closeDrawer() - nav.nav(Route.EditMediaServers) - }, - ) - - NavigationRow( - title = R.string.security_filters, - icon = Icons.Outlined.Security, - tint = MaterialTheme.colorScheme.onBackground, - nav = nav, - route = Route.SecurityFilters, - ) - - NavigationRow( - title = R.string.privacy_options, - icon = R.drawable.ic_tor, - iconReference = 1, - tint = MaterialTheme.colorScheme.onBackground, - nav = nav, - route = Route.PrivacyOptions, - ) - accountViewModel.account.settings.keyPair.privKey?.let { IconRow( title = R.string.backup_keys, @@ -528,19 +490,11 @@ fun ListContent( } NavigationRow( - title = R.string.preferences, + title = R.string.settings, icon = Icons.Outlined.Settings, tint = MaterialTheme.colorScheme.onBackground, nav = nav, - route = Route.Settings, - ) - - NavigationRow( - title = R.string.user_preferences, - icon = Icons.Outlined.Translate, - tint = MaterialTheme.colorScheme.onBackground, - nav = nav, - route = Route.UserSettings, + route = Route.AllSettings, ) Spacer(modifier = Modifier.weight(1f)) diff --git a/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/navigation/routes/Routes.kt b/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/navigation/routes/Routes.kt index 0147f5b14..02e7f12ed 100644 --- a/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/navigation/routes/Routes.kt +++ b/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/navigation/routes/Routes.kt @@ -79,6 +79,8 @@ sealed class Route { @Serializable object Drafts : Route() + @Serializable object AllSettings : Route() + @Serializable object Settings : Route() @Serializable object UserSettings : Route() @@ -325,6 +327,7 @@ fun getRouteWithArguments(navController: NavHostController): Route? { dest.hasRoute() -> entry.toRoute() dest.hasRoute() -> entry.toRoute() dest.hasRoute() -> entry.toRoute() + dest.hasRoute() -> entry.toRoute() dest.hasRoute() -> entry.toRoute() dest.hasRoute() -> entry.toRoute() dest.hasRoute() -> entry.toRoute() diff --git a/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/settings/AllSettingsScreen.kt b/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/settings/AllSettingsScreen.kt new file mode 100644 index 000000000..13aad71c1 --- /dev/null +++ b/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/settings/AllSettingsScreen.kt @@ -0,0 +1,167 @@ +/* + * Copyright (c) 2025 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.screen.loggedIn.settings + +import androidx.compose.foundation.clickable +import androidx.compose.foundation.layout.Column +import androidx.compose.foundation.layout.Row +import androidx.compose.foundation.layout.fillMaxWidth +import androidx.compose.foundation.layout.padding +import androidx.compose.foundation.layout.size +import androidx.compose.material.icons.Icons +import androidx.compose.material.icons.outlined.CloudUpload +import androidx.compose.material.icons.outlined.Security +import androidx.compose.material.icons.outlined.Settings +import androidx.compose.material.icons.outlined.Translate +import androidx.compose.material3.HorizontalDivider +import androidx.compose.material3.Icon +import androidx.compose.material3.MaterialTheme +import androidx.compose.material3.Scaffold +import androidx.compose.material3.Text +import androidx.compose.runtime.Composable +import androidx.compose.ui.Alignment +import androidx.compose.ui.Modifier +import androidx.compose.ui.graphics.Color +import androidx.compose.ui.graphics.vector.ImageVector +import androidx.compose.ui.unit.dp +import androidx.compose.ui.unit.sp +import com.vitorpamplona.amethyst.R +import com.vitorpamplona.amethyst.ui.navigation.navs.INav +import com.vitorpamplona.amethyst.ui.navigation.routes.Route +import com.vitorpamplona.amethyst.ui.navigation.topbars.TopBarWithBackButton +import com.vitorpamplona.amethyst.ui.painterRes +import com.vitorpamplona.amethyst.ui.stringRes + +@Composable +fun AllSettingsScreen(nav: INav) { + val tint = MaterialTheme.colorScheme.onBackground + + Scaffold( + topBar = { + TopBarWithBackButton(stringRes(id = R.string.settings), nav::popBack) + }, + ) { padding -> + Column(Modifier.padding(padding)) { + SettingsNavigationRow( + title = R.string.relay_setup, + iconPainter = R.drawable.relays, + iconPainterRef = 4, + tint = tint, + onClick = { nav.nav(Route.EditRelays) }, + ) + HorizontalDivider() + SettingsNavigationRow( + title = R.string.media_servers, + icon = Icons.Outlined.CloudUpload, + tint = tint, + onClick = { nav.nav(Route.EditMediaServers) }, + ) + HorizontalDivider() + SettingsNavigationRow( + title = R.string.security_filters, + icon = Icons.Outlined.Security, + tint = tint, + onClick = { nav.nav(Route.SecurityFilters) }, + ) + HorizontalDivider() + SettingsNavigationRow( + title = R.string.privacy_options, + iconPainter = R.drawable.ic_tor, + iconPainterRef = 1, + tint = tint, + onClick = { nav.nav(Route.PrivacyOptions) }, + ) + HorizontalDivider() + SettingsNavigationRow( + title = R.string.preferences, + icon = Icons.Outlined.Settings, + tint = tint, + onClick = { nav.nav(Route.Settings) }, + ) + HorizontalDivider() + SettingsNavigationRow( + title = R.string.user_preferences, + icon = Icons.Outlined.Translate, + tint = tint, + onClick = { nav.nav(Route.UserSettings) }, + ) + } + } +} + +@Composable +private fun SettingsNavigationRow( + title: Int, + icon: ImageVector, + tint: Color, + onClick: () -> Unit, +) { + Row( + modifier = + Modifier + .fillMaxWidth() + .clickable(onClick = onClick) + .padding(vertical = 16.dp, horizontal = 24.dp), + verticalAlignment = Alignment.CenterVertically, + ) { + Icon( + imageVector = icon, + contentDescription = stringRes(title), + modifier = Modifier.size(24.dp), + tint = tint, + ) + Text( + text = stringRes(title), + fontSize = 18.sp, + modifier = Modifier.padding(start = 16.dp), + ) + } +} + +@Composable +private fun SettingsNavigationRow( + title: Int, + iconPainter: Int, + iconPainterRef: Int, + tint: Color, + onClick: () -> Unit, +) { + Row( + modifier = + Modifier + .fillMaxWidth() + .clickable(onClick = onClick) + .padding(vertical = 16.dp, horizontal = 24.dp), + verticalAlignment = Alignment.CenterVertically, + ) { + Icon( + painter = painterRes(iconPainter, iconPainterRef), + contentDescription = stringRes(title), + modifier = Modifier.size(24.dp), + tint = tint, + ) + Text( + text = stringRes(title), + fontSize = 18.sp, + modifier = Modifier.padding(start = 16.dp), + ) + } +}