Moves privacy option from dialog to route

This commit is contained in:
Vitor Pamplona
2025-04-25 12:14:44 -04:00
parent 390e0615d1
commit aef7d91a6b
5 changed files with 247 additions and 140 deletions
@@ -70,6 +70,7 @@ import com.vitorpamplona.amethyst.ui.screen.loggedIn.geohash.GeoHashScreen
import com.vitorpamplona.amethyst.ui.screen.loggedIn.hashtag.HashtagScreen import com.vitorpamplona.amethyst.ui.screen.loggedIn.hashtag.HashtagScreen
import com.vitorpamplona.amethyst.ui.screen.loggedIn.home.HomeScreen import com.vitorpamplona.amethyst.ui.screen.loggedIn.home.HomeScreen
import com.vitorpamplona.amethyst.ui.screen.loggedIn.notifications.NotificationScreen import com.vitorpamplona.amethyst.ui.screen.loggedIn.notifications.NotificationScreen
import com.vitorpamplona.amethyst.ui.screen.loggedIn.privacy.PrivacyOptionsScreen
import com.vitorpamplona.amethyst.ui.screen.loggedIn.profile.ProfileScreen import com.vitorpamplona.amethyst.ui.screen.loggedIn.profile.ProfileScreen
import com.vitorpamplona.amethyst.ui.screen.loggedIn.redirect.LoadRedirectScreen 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.AllRelayListScreen
@@ -111,6 +112,7 @@ fun AppNavigation(
composable<Route.Search> { SearchScreen(accountViewModel, nav) } composable<Route.Search> { SearchScreen(accountViewModel, nav) }
composableFromEnd<Route.SecurityFilters> { SecurityFiltersScreen(accountViewModel, nav) } composableFromEnd<Route.SecurityFilters> { SecurityFiltersScreen(accountViewModel, nav) }
composableFromEnd<Route.PrivacyOptions> { PrivacyOptionsScreen(accountViewModel, nav) }
composableFromEnd<Route.Bookmarks> { BookmarkListScreen(accountViewModel, nav) } composableFromEnd<Route.Bookmarks> { BookmarkListScreen(accountViewModel, nav) }
composableFromEnd<Route.Drafts> { DraftListScreen(accountViewModel, nav) } composableFromEnd<Route.Drafts> { DraftListScreen(accountViewModel, nav) }
composableFromEnd<Route.Settings> { SettingsScreen(sharedPreferencesViewModel, accountViewModel, nav) } composableFromEnd<Route.Settings> { SettingsScreen(sharedPreferencesViewModel, accountViewModel, nav) }
@@ -122,7 +122,6 @@ import com.vitorpamplona.amethyst.ui.theme.bannerModifier
import com.vitorpamplona.amethyst.ui.theme.drawerSpacing import com.vitorpamplona.amethyst.ui.theme.drawerSpacing
import com.vitorpamplona.amethyst.ui.theme.placeholderText import com.vitorpamplona.amethyst.ui.theme.placeholderText
import com.vitorpamplona.amethyst.ui.theme.profileContentHeaderModifier import com.vitorpamplona.amethyst.ui.theme.profileContentHeaderModifier
import com.vitorpamplona.amethyst.ui.tor.ConnectTorDialog
import com.vitorpamplona.ammolite.relays.RelayPoolStatus import com.vitorpamplona.ammolite.relays.RelayPoolStatus
import com.vitorpamplona.quartz.nip01Core.core.HexKey import com.vitorpamplona.quartz.nip01Core.core.HexKey
import com.vitorpamplona.quartz.nip01Core.tags.addressables.Address import com.vitorpamplona.quartz.nip01Core.tags.addressables.Address
@@ -429,8 +428,6 @@ fun ListContent(
var backupDialogOpen by remember { mutableStateOf(false) } var backupDialogOpen by remember { mutableStateOf(false) }
var conectOrbotDialogOpen by remember { mutableStateOf(false) }
val context = LocalContext.current val context = LocalContext.current
Column(modifier) { Column(modifier) {
@@ -484,14 +481,12 @@ fun ListContent(
route = Route.SecurityFilters, route = Route.SecurityFilters,
) )
IconRow( NavigationRow(
title = R.string.privacy_options, title = R.string.privacy_options,
icon = R.drawable.ic_tor, icon = R.drawable.ic_tor,
tint = MaterialTheme.colorScheme.onBackground, tint = MaterialTheme.colorScheme.onBackground,
onClick = { nav = nav,
nav.closeDrawer() route = Route.PrivacyOptions,
conectOrbotDialogOpen = true
},
) )
accountViewModel.account.settings.keyPair.privKey?.let { accountViewModel.account.settings.keyPair.privKey?.let {
@@ -530,24 +525,6 @@ fun ListContent(
if (backupDialogOpen) { if (backupDialogOpen) {
AccountBackupDialog(accountViewModel, onClose = { backupDialogOpen = false }) AccountBackupDialog(accountViewModel, onClose = { backupDialogOpen = false })
} }
if (conectOrbotDialogOpen) {
ConnectTorDialog(
torSettings =
accountViewModel.account.settings.torSettings
.toSettings(),
onClose = { conectOrbotDialogOpen = false },
onPost = { torSettings ->
conectOrbotDialogOpen = false
accountViewModel.setTorSettings(torSettings)
},
onError = {
accountViewModel.toastManager.toast(
stringRes(context, R.string.could_not_connect_to_tor),
it,
)
},
)
}
} }
@Composable @Composable
@@ -54,6 +54,8 @@ sealed class Route {
@Serializable object SecurityFilters : Route() @Serializable object SecurityFilters : Route()
@Serializable object PrivacyOptions : Route()
@Serializable object Bookmarks : Route() @Serializable object Bookmarks : Route()
@Serializable object Drafts : Route() @Serializable object Drafts : Route()
@@ -150,6 +152,7 @@ fun getRouteWithArguments(navController: NavHostController): Route? {
dest.hasRoute<Route.Search>() -> entry.toRoute<Route.Search>() dest.hasRoute<Route.Search>() -> entry.toRoute<Route.Search>()
dest.hasRoute<Route.SecurityFilters>() -> entry.toRoute<Route.SecurityFilters>() dest.hasRoute<Route.SecurityFilters>() -> entry.toRoute<Route.SecurityFilters>()
dest.hasRoute<Route.PrivacyOptions>() -> entry.toRoute<Route.PrivacyOptions>()
dest.hasRoute<Route.Bookmarks>() -> entry.toRoute<Route.Bookmarks>() dest.hasRoute<Route.Bookmarks>() -> entry.toRoute<Route.Bookmarks>()
dest.hasRoute<Route.ContentDiscovery>() -> entry.toRoute<Route.ContentDiscovery>() dest.hasRoute<Route.ContentDiscovery>() -> entry.toRoute<Route.ContentDiscovery>()
dest.hasRoute<Route.Drafts>() -> entry.toRoute<Route.Drafts>() dest.hasRoute<Route.Drafts>() -> entry.toRoute<Route.Drafts>()
@@ -0,0 +1,120 @@
/**
* 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.screen.loggedIn.privacy
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.fillMaxSize
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.rememberScrollState
import androidx.compose.foundation.verticalScroll
import androidx.compose.material3.ExperimentalMaterial3Api
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Scaffold
import androidx.compose.material3.Text
import androidx.compose.material3.TopAppBar
import androidx.compose.material3.TopAppBarDefaults
import androidx.compose.runtime.Composable
import androidx.compose.runtime.LaunchedEffect
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.unit.dp
import androidx.lifecycle.viewmodel.compose.viewModel
import com.vitorpamplona.amethyst.R
import com.vitorpamplona.amethyst.ui.navigation.INav
import com.vitorpamplona.amethyst.ui.screen.loggedIn.AccountViewModel
import com.vitorpamplona.amethyst.ui.screen.loggedIn.CloseButton
import com.vitorpamplona.amethyst.ui.screen.loggedIn.SaveButton
import com.vitorpamplona.amethyst.ui.stringRes
import com.vitorpamplona.amethyst.ui.theme.StdHorzSpacer
import com.vitorpamplona.amethyst.ui.tor.PrivacySettingsBody
import com.vitorpamplona.amethyst.ui.tor.TorDialogViewModel
@OptIn(ExperimentalMaterial3Api::class)
@Composable
fun PrivacyOptionsScreen(
accountViewModel: AccountViewModel,
nav: INav,
) {
val dialogViewModel = viewModel<TorDialogViewModel>()
LaunchedEffect(dialogViewModel, accountViewModel) {
dialogViewModel.reset(
accountViewModel.account.settings.torSettings
.toSettings(),
)
}
Scaffold(
topBar = {
TopAppBar(
title = {
Row(
modifier = Modifier.fillMaxWidth(),
horizontalArrangement = Arrangement.SpaceBetween,
verticalAlignment = Alignment.CenterVertically,
) {
Spacer(modifier = StdHorzSpacer)
Text(
stringRes(id = R.string.privacy_options),
)
SaveButton(
onPost = {
accountViewModel.setTorSettings(dialogViewModel.save())
nav.popBack()
},
isActive = true,
)
}
},
navigationIcon = {
Row {
Spacer(modifier = StdHorzSpacer)
CloseButton(
onPress = {
nav.popBack()
},
)
}
},
colors =
TopAppBarDefaults.topAppBarColors(
containerColor = MaterialTheme.colorScheme.surface,
),
)
},
) {
Column(
Modifier
.padding(it)
.fillMaxSize()
.verticalScroll(
rememberScrollState(),
).padding(horizontal = 10.dp),
) {
PrivacySettingsBody(dialogViewModel)
}
}
}
@@ -151,6 +151,12 @@ fun TorDialogContents(
) )
} }
PrivacySettingsBody(dialogViewModel)
}
}
@Composable
fun PrivacySettingsBody(dialogViewModel: TorDialogViewModel) {
Column( Column(
modifier = Modifier.padding(horizontal = 5.dp), modifier = Modifier.padding(horizontal = 5.dp),
verticalArrangement = Arrangement.spacedBy(Size10dp), verticalArrangement = Arrangement.spacedBy(Size10dp),
@@ -286,7 +292,6 @@ fun TorDialogContents(
) )
} }
} }
}
} }
@Composable @Composable