Move strings to stringResources. Refactor names for consistency. Some cleanup.

This commit is contained in:
KotlinGeekDev
2025-09-23 14:51:05 +01:00
parent 5175c61171
commit 00d5e2fed3
9 changed files with 132 additions and 83 deletions
@@ -78,7 +78,7 @@ import com.vitorpamplona.amethyst.ui.screen.loggedIn.hashtag.HashtagPostScreen
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.home.ShortNotePostScreen import com.vitorpamplona.amethyst.ui.screen.loggedIn.home.ShortNotePostScreen
import com.vitorpamplona.amethyst.ui.screen.loggedIn.lists.ListsScreen import com.vitorpamplona.amethyst.ui.screen.loggedIn.lists.ListsAndSetsScreen
import com.vitorpamplona.amethyst.ui.screen.loggedIn.lists.NostrUserListFeedViewModel import com.vitorpamplona.amethyst.ui.screen.loggedIn.lists.NostrUserListFeedViewModel
import com.vitorpamplona.amethyst.ui.screen.loggedIn.lists.followsets.FollowSetScreen import com.vitorpamplona.amethyst.ui.screen.loggedIn.lists.followsets.FollowSetScreen
import com.vitorpamplona.amethyst.ui.screen.loggedIn.lists.followsets.FollowSetsManagementDialog import com.vitorpamplona.amethyst.ui.screen.loggedIn.lists.followsets.FollowSetsManagementDialog
@@ -127,7 +127,7 @@ fun AppNavigation(
composable<Route.Discover> { DiscoverScreen(accountViewModel, nav) } composable<Route.Discover> { DiscoverScreen(accountViewModel, nav) }
composable<Route.Notification> { NotificationScreen(accountViewModel, nav) } composable<Route.Notification> { NotificationScreen(accountViewModel, nav) }
composableFromEnd<Route.Lists> { ListsScreen(accountViewModel, listsViewModel, nav) } composableFromEnd<Route.Lists> { ListsAndSetsScreen(accountViewModel, listsViewModel, nav) }
composableArgs<Route.FollowSetRoute> { composableArgs<Route.FollowSetRoute> {
FollowSetScreen(it.setIdentifier, accountViewModel, listsViewModel, nav) FollowSetScreen(it.setIdentifier, accountViewModel, listsViewModel, nav)
} }
@@ -436,7 +436,7 @@ fun ListContent(
) )
NavigationRow( NavigationRow(
title = R.string.my_lists, title = R.string.my_lists_and_sets,
icon = ImageVector.vectorResource(R.drawable.format_list_bulleted_type), icon = ImageVector.vectorResource(R.drawable.format_list_bulleted_type),
tint = MaterialTheme.colorScheme.onBackground, tint = MaterialTheme.colorScheme.onBackground,
nav = nav, nav = nav,
@@ -184,7 +184,7 @@ fun NoteDropDownMenu(
HorizontalDivider(thickness = DividerThickness) HorizontalDivider(thickness = DividerThickness)
} }
DropdownMenuItem( DropdownMenuItem(
text = { Text(text = "Add author to follow set") }, text = { Text(text = stringRes(R.string.follow_set_add_author_from_note_action)) },
onClick = { onClick = {
val authorHexKey = note.author?.pubkeyHex ?: return@DropdownMenuItem val authorHexKey = note.author?.pubkeyHex ?: return@DropdownMenuItem
nav.nav(Route.FollowSetManagement(authorHexKey)) nav.nav(Route.FollowSetManagement(authorHexKey))
@@ -49,6 +49,7 @@ import androidx.compose.runtime.rememberCoroutineScope
import androidx.compose.ui.Alignment import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color import androidx.compose.ui.graphics.Color
import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.res.painterResource import androidx.compose.ui.res.painterResource
import androidx.compose.ui.text.style.TextOverflow import androidx.compose.ui.text.style.TextOverflow
import androidx.compose.ui.tooling.preview.Preview import androidx.compose.ui.tooling.preview.Preview
@@ -71,7 +72,7 @@ import com.vitorpamplona.amethyst.ui.theme.ThemeComparisonColumn
import kotlinx.coroutines.launch import kotlinx.coroutines.launch
@Composable @Composable
fun ListsScreen( fun ListsAndSetsScreen(
accountViewModel: AccountViewModel, accountViewModel: AccountViewModel,
followSetsViewModel: NostrUserListFeedViewModel, followSetsViewModel: NostrUserListFeedViewModel,
nav: INav, nav: INav,
@@ -139,7 +140,6 @@ fun CustomListsScreen(
accountViewModel: AccountViewModel, accountViewModel: AccountViewModel,
nav: INav, nav: INav,
) { ) {
// val setsState by followSetsViewModel.feedContent.collectAsStateWithLifecycle()
val pagerState = rememberPagerState { 3 } val pagerState = rememberPagerState { 3 }
val coroutineScope = rememberCoroutineScope() val coroutineScope = rememberCoroutineScope()
@@ -148,7 +148,7 @@ fun CustomListsScreen(
accountViewModel = accountViewModel, accountViewModel = accountViewModel,
topBar = { topBar = {
Column { Column {
TopBarWithBackButton(stringRes(R.string.my_lists), nav::popBack) TopBarWithBackButton(stringRes(R.string.my_lists_and_sets), nav::popBack)
TabRow( TabRow(
selectedTabIndex = pagerState.currentPage, selectedTabIndex = pagerState.currentPage,
modifier = TabRowHeight, modifier = TabRowHeight,
@@ -158,17 +158,17 @@ fun CustomListsScreen(
Tab( Tab(
selected = pagerState.currentPage == 0, selected = pagerState.currentPage == 0,
onClick = { coroutineScope.launch { pagerState.animateScrollToPage(0) } }, onClick = { coroutineScope.launch { pagerState.animateScrollToPage(0) } },
text = { Text(text = "Follow Sets", overflow = TextOverflow.Visible) }, text = { Text(text = stringRes(R.string.follow_sets), overflow = TextOverflow.Visible) },
) )
Tab( Tab(
selected = pagerState.currentPage == 1, selected = pagerState.currentPage == 1,
onClick = { coroutineScope.launch { pagerState.animateScrollToPage(1) } }, onClick = { coroutineScope.launch { pagerState.animateScrollToPage(1) } },
text = { Text(text = "Labeled Bookmarks", overflow = TextOverflow.Visible) }, text = { Text(text = stringRes(R.string.labeled_bookmarks), overflow = TextOverflow.Visible) },
) )
Tab( Tab(
selected = pagerState.currentPage == 2, selected = pagerState.currentPage == 2,
onClick = { coroutineScope.launch { pagerState.animateScrollToPage(2) } }, onClick = { coroutineScope.launch { pagerState.animateScrollToPage(2) } },
text = { Text(text = "General Bookmarks", overflow = TextOverflow.Visible) }, text = { Text(text = stringRes(R.string.general_bookmarks), overflow = TextOverflow.Visible) },
) )
} }
} }
@@ -176,10 +176,10 @@ fun CustomListsScreen(
floatingButton = { floatingButton = {
// TODO: Show components based on current tab // TODO: Show components based on current tab
FollowSetFabsAndMenu( FollowSetFabsAndMenu(
onAddPrivateList = { name: String, description: String? -> onAddPrivateSet = { name: String, description: String? ->
addItem(name, description, ListVisibility.Private) addItem(name, description, ListVisibility.Private)
}, },
onAddPublicList = { name: String, description: String? -> onAddPublicSet = { name: String, description: String? ->
addItem(name, description, ListVisibility.Public) addItem(name, description, ListVisibility.Public)
}, },
) )
@@ -212,10 +212,10 @@ fun CustomListsScreen(
@Composable @Composable
private fun FollowSetFabsAndMenu( private fun FollowSetFabsAndMenu(
modifier: Modifier = Modifier, modifier: Modifier = Modifier,
onAddPrivateList: (name: String, description: String?) -> Unit, onAddPrivateSet: (name: String, description: String?) -> Unit,
onAddPublicList: (name: String, description: String?) -> Unit, onAddPublicSet: (name: String, description: String?) -> Unit,
) { ) {
val isListAdditionDialogOpen = remember { mutableStateOf(false) } val isSetAdditionDialogOpen = remember { mutableStateOf(false) }
val isPrivateOptionTapped = remember { mutableStateOf(false) } val isPrivateOptionTapped = remember { mutableStateOf(false) }
Row( Row(
@@ -223,9 +223,8 @@ private fun FollowSetFabsAndMenu(
) { ) {
FloatingActionButton( FloatingActionButton(
onClick = { onClick = {
println("The private list addition...")
isPrivateOptionTapped.value = true isPrivateOptionTapped.value = true
isListAdditionDialogOpen.value = true isSetAdditionDialogOpen.value = true
}, },
shape = CircleShape, shape = CircleShape,
containerColor = ButtonDefaults.filledTonalButtonColors().containerColor, containerColor = ButtonDefaults.filledTonalButtonColors().containerColor,
@@ -238,8 +237,7 @@ private fun FollowSetFabsAndMenu(
} }
FloatingActionButton( FloatingActionButton(
onClick = { onClick = {
println("The public list creation...") isSetAdditionDialogOpen.value = true
isListAdditionDialogOpen.value = true
}, },
shape = CircleShape, shape = CircleShape,
containerColor = ButtonDefaults.filledTonalButtonColors().containerColor, containerColor = ButtonDefaults.filledTonalButtonColors().containerColor,
@@ -252,18 +250,18 @@ private fun FollowSetFabsAndMenu(
} }
} }
if (isListAdditionDialogOpen.value) { if (isSetAdditionDialogOpen.value) {
NewListCreationDialog( NewSetCreationDialog(
onDismiss = { onDismiss = {
isListAdditionDialogOpen.value = false isSetAdditionDialogOpen.value = false
isPrivateOptionTapped.value = false isPrivateOptionTapped.value = false
}, },
shouldBePrivate = isPrivateOptionTapped.value, shouldBePrivate = isPrivateOptionTapped.value,
onCreateList = { name, description -> onCreateList = { name, description ->
if (isPrivateOptionTapped.value) { if (isPrivateOptionTapped.value) {
onAddPrivateList(name, description) onAddPrivateSet(name, description)
} else { } else {
onAddPublicList(name, description) onAddPublicSet(name, description)
} }
}, },
) )
@@ -271,7 +269,7 @@ private fun FollowSetFabsAndMenu(
} }
@Composable @Composable
fun NewListCreationDialog( fun NewSetCreationDialog(
modifier: Modifier = Modifier, modifier: Modifier = Modifier,
onDismiss: () -> Unit, onDismiss: () -> Unit,
shouldBePrivate: Boolean, shouldBePrivate: Boolean,
@@ -279,12 +277,16 @@ fun NewListCreationDialog(
) { ) {
val newListName = remember { mutableStateOf("") } val newListName = remember { mutableStateOf("") }
val newListDescription = remember { mutableStateOf<String?>(null) } val newListDescription = remember { mutableStateOf<String?>(null) }
val context = LocalContext.current
val listTypeText = val listTypeText =
when (shouldBePrivate) { stringRes(
true -> "Private" context,
false -> "Public" when (shouldBePrivate) {
} true -> R.string.follow_set_type_private
false -> R.string.follow_set_type_public
},
)
val listTypeIcon = val listTypeIcon =
when (shouldBePrivate) { when (shouldBePrivate) {
@@ -304,7 +306,7 @@ fun NewListCreationDialog(
contentDescription = null, contentDescription = null,
) )
Text( Text(
text = "New $listTypeText List", text = stringRes(R.string.follow_set_creation_dialog_title, listTypeText),
) )
} }
}, },
@@ -317,7 +319,7 @@ fun NewListCreationDialog(
value = newListName.value, value = newListName.value,
onValueChange = { newListName.value = it }, onValueChange = { newListName.value = it },
label = { label = {
Text("List name") Text(text = stringRes(R.string.follow_set_creation_name_label))
}, },
) )
Spacer(modifier = DoubleVertSpacer) Spacer(modifier = DoubleVertSpacer)
@@ -329,7 +331,7 @@ fun NewListCreationDialog(
).toString(), ).toString(),
onValueChange = { newListDescription.value = it }, onValueChange = { newListDescription.value = it },
label = { label = {
Text("List description(optional)") Text(text = stringRes(R.string.follow_set_creation_desc_label))
}, },
) )
} }
@@ -341,14 +343,14 @@ fun NewListCreationDialog(
onDismiss() onDismiss()
}, },
) { ) {
Text("Create list") Text(stringRes(R.string.follow_set_creation_action_btn_label))
} }
}, },
dismissButton = { dismissButton = {
Button( Button(
onClick = onDismiss, onClick = onDismiss,
) { ) {
Text("Cancel") Text(stringRes(R.string.cancel))
} }
}, },
) )
@@ -380,7 +382,7 @@ fun GeneralBookmarksFeedView() {
@Preview(showSystemUi = true) @Preview(showSystemUi = true)
@Composable @Composable
private fun ListItemPreview() { private fun SetItemPreview() {
val sampleFollowSet = val sampleFollowSet =
FollowSet( FollowSet(
identifierTag = "00001-2222", identifierTag = "00001-2222",
@@ -390,7 +392,7 @@ private fun ListItemPreview() {
emptySet(), emptySet(),
) )
ThemeComparisonColumn { ThemeComparisonColumn {
CustomListItem( CustomSetItem(
modifier = Modifier, modifier = Modifier,
sampleFollowSet, sampleFollowSet,
onFollowSetClick = { onFollowSetClick = {
@@ -46,6 +46,7 @@ import androidx.compose.runtime.remember
import androidx.compose.ui.Alignment import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color import androidx.compose.ui.graphics.Color
import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.res.painterResource import androidx.compose.ui.res.painterResource
import androidx.compose.ui.text.SpanStyle import androidx.compose.ui.text.SpanStyle
import androidx.compose.ui.text.buildAnnotatedString import androidx.compose.ui.text.buildAnnotatedString
@@ -59,19 +60,22 @@ import androidx.compose.ui.unit.sp
import com.vitorpamplona.amethyst.R import com.vitorpamplona.amethyst.R
import com.vitorpamplona.amethyst.ui.components.ClickableBox import com.vitorpamplona.amethyst.ui.components.ClickableBox
import com.vitorpamplona.amethyst.ui.note.VerticalDotsIcon import com.vitorpamplona.amethyst.ui.note.VerticalDotsIcon
import com.vitorpamplona.amethyst.ui.stringRes
import com.vitorpamplona.amethyst.ui.theme.ButtonBorder import com.vitorpamplona.amethyst.ui.theme.ButtonBorder
import com.vitorpamplona.amethyst.ui.theme.Size5dp import com.vitorpamplona.amethyst.ui.theme.Size5dp
import com.vitorpamplona.amethyst.ui.theme.StdHorzSpacer import com.vitorpamplona.amethyst.ui.theme.StdHorzSpacer
import com.vitorpamplona.amethyst.ui.theme.StdVertSpacer import com.vitorpamplona.amethyst.ui.theme.StdVertSpacer
import kotlin.let
@Composable @Composable
fun CustomListItem( fun CustomSetItem(
modifier: Modifier = Modifier, modifier: Modifier = Modifier,
followSet: FollowSet, followSet: FollowSet,
onFollowSetClick: () -> Unit, onFollowSetClick: () -> Unit,
onFollowSetRename: (String) -> Unit, onFollowSetRename: (String) -> Unit,
onFollowSetDelete: () -> Unit, onFollowSetDelete: () -> Unit,
) { ) {
val context = LocalContext.current
Row( Row(
modifier = modifier =
modifier modifier
@@ -125,9 +129,9 @@ fun CustomListItem(
followSet.visibility.let { followSet.visibility.let {
val text by derivedStateOf { val text by derivedStateOf {
when (it) { when (it) {
ListVisibility.Public -> "Public" ListVisibility.Public -> stringRes(context, R.string.follow_set_type_public)
ListVisibility.Private -> "Private" ListVisibility.Private -> stringRes(context, R.string.follow_set_type_private)
ListVisibility.Mixed -> "Mixed" ListVisibility.Mixed -> stringRes(context, R.string.follow_set_type_mixed)
} }
} }
Column( Column(
@@ -144,7 +148,7 @@ fun CustomListItem(
ListVisibility.Mixed -> R.drawable.format_list_bulleted_type ListVisibility.Mixed -> R.drawable.format_list_bulleted_type
}, },
), ),
contentDescription = "Icon for $text List", contentDescription = stringRes(R.string.follow_set_type_description, text),
) )
Text(text, color = Color.Gray, fontWeight = FontWeight.Light) Text(text, color = Color.Gray, fontWeight = FontWeight.Light)
} }
@@ -159,7 +163,7 @@ fun CustomListItem(
verticalArrangement = Arrangement.Top, verticalArrangement = Arrangement.Top,
horizontalAlignment = Alignment.End, horizontalAlignment = Alignment.End,
) { ) {
ListOptionsButton( SetOptionsButton(
followSetName = followSet.title, followSetName = followSet.title,
onListRename = onFollowSetRename, onListRename = onFollowSetRename,
onListDelete = onFollowSetDelete, onListDelete = onFollowSetDelete,
@@ -169,7 +173,7 @@ fun CustomListItem(
} }
@Composable @Composable
fun ListOptionsButton( fun SetOptionsButton(
modifier: Modifier = Modifier, modifier: Modifier = Modifier,
followSetName: String, followSetName: String,
onListRename: (String) -> Unit, onListRename: (String) -> Unit,
@@ -182,7 +186,7 @@ fun ListOptionsButton(
) { ) {
VerticalDotsIcon() VerticalDotsIcon()
ListOptionsMenu( SetOptionsMenu(
listName = followSetName, listName = followSetName,
isExpanded = isMenuOpen.value, isExpanded = isMenuOpen.value,
onDismiss = { isMenuOpen.value = false }, onDismiss = { isMenuOpen.value = false },
@@ -193,7 +197,7 @@ fun ListOptionsButton(
} }
@Composable @Composable
fun ListOptionsMenu( private fun SetOptionsMenu(
modifier: Modifier = Modifier, modifier: Modifier = Modifier,
isExpanded: Boolean, isExpanded: Boolean,
listName: String, listName: String,
@@ -210,19 +214,17 @@ fun ListOptionsMenu(
) { ) {
DropdownMenuItem( DropdownMenuItem(
text = { text = {
Text(text = "Delete") Text(text = stringRes(R.string.quick_action_delete))
}, },
onClick = { onClick = {
println("The list named $listName has been selected for deletion.")
onDelete() onDelete()
}, },
) )
DropdownMenuItem( DropdownMenuItem(
text = { text = {
Text(text = "Rename list") Text(text = stringRes(R.string.follow_set_rename_btn_label))
}, },
onClick = { onClick = {
println("The list $listName should be renamed...")
isRenameDialogOpen.value = true isRenameDialogOpen.value = true
onDismiss() onDismiss()
}, },
@@ -245,7 +247,7 @@ fun ListOptionsMenu(
} }
@Composable @Composable
fun RenameDialog( private fun RenameDialog(
modifier: Modifier = Modifier, modifier: Modifier = Modifier,
currentName: String, currentName: String,
newName: String, newName: String,
@@ -255,7 +257,7 @@ fun RenameDialog(
) { ) {
val renameIndicator = val renameIndicator =
buildAnnotatedString { buildAnnotatedString {
append("You are renaming from ") append(stringRes(R.string.follow_set_rename_dialog_indicator_first_part) + " ")
withStyle( withStyle(
SpanStyle( SpanStyle(
fontWeight = FontWeight.Bold, fontWeight = FontWeight.Bold,
@@ -265,13 +267,13 @@ fun RenameDialog(
) { ) {
append("\"" + currentName + "\"") append("\"" + currentName + "\"")
} }
append(" to..") append(" " + stringRes(R.string.follow_set_rename_dialog_indicator_second_part))
} }
AlertDialog( AlertDialog(
onDismissRequest = onDismissDialog, onDismissRequest = onDismissDialog,
title = { title = {
Text(text = "Rename List") Text(text = stringRes(R.string.follow_set_rename_btn_label))
}, },
text = { text = {
Column( Column(
@@ -296,10 +298,10 @@ fun RenameDialog(
onListRename(newName) onListRename(newName)
onDismissDialog() onDismissDialog()
}, },
) { Text(text = "Rename") } ) { Text(text = stringRes(R.string.rename)) }
}, },
dismissButton = { dismissButton = {
Button(onClick = onDismissDialog) { Text(text = "Cancel") } Button(onClick = onDismissDialog) { Text(text = stringRes(R.string.cancel)) }
}, },
) )
} }
@@ -55,7 +55,7 @@ fun FollowSetFeedView(
is FollowSetState.Loaded -> { is FollowSetState.Loaded -> {
val followSetFeed = followSetState.feed val followSetFeed = followSetState.feed
FollowListLoaded( FollowSetLoaded(
loadedFeedState = followSetFeed, loadedFeedState = followSetFeed,
onRefresh = onRefresh, onRefresh = onRefresh,
onItemClick = onOpenItem, onItemClick = onOpenItem,
@@ -65,10 +65,8 @@ fun FollowSetFeedView(
} }
is FollowSetState.Empty -> { is FollowSetState.Empty -> {
FollowListFeedEmpty( FollowSetFeedEmpty(
message = message = stringRes(R.string.follow_set_empty_feed_msg),
"It seems you do not have any follow lists yet.\n " +
"Tap below to refresh, or tap the add buttons to create a new one.",
) { ) {
onRefresh() onRefresh()
} }
@@ -84,7 +82,7 @@ fun FollowSetFeedView(
} }
@Composable @Composable
fun FollowListLoaded( fun FollowSetLoaded(
modifier: Modifier = Modifier, modifier: Modifier = Modifier,
loadedFeedState: List<FollowSet>, loadedFeedState: List<FollowSet>,
onRefresh: () -> Unit = {}, onRefresh: () -> Unit = {},
@@ -92,7 +90,7 @@ fun FollowListLoaded(
onItemRename: (followSet: FollowSet, newName: String) -> Unit, onItemRename: (followSet: FollowSet, newName: String) -> Unit,
onItemDelete: (followSet: FollowSet) -> Unit, onItemDelete: (followSet: FollowSet) -> Unit,
) { ) {
Log.d("FollowSetComposable", "FollowListLoaded: Follow Set size: ${loadedFeedState.size}") Log.d("FollowSetComposable", "FollowSetLoaded: Follow Set size: ${loadedFeedState.size}")
val listState = rememberLazyListState() val listState = rememberLazyListState()
RefresheableBox( RefresheableBox(
@@ -103,7 +101,7 @@ fun FollowListLoaded(
contentPadding = FeedPadding, contentPadding = FeedPadding,
) { ) {
itemsIndexed(loadedFeedState, key = { _, item -> item.identifierTag }) { _, set -> itemsIndexed(loadedFeedState, key = { _, item -> item.identifierTag }) { _, set ->
CustomListItem( CustomSetItem(
modifier = Modifier.animateItem(), modifier = Modifier.animateItem(),
followSet = set, followSet = set,
onFollowSetClick = { onFollowSetClick = {
@@ -123,7 +121,7 @@ fun FollowListLoaded(
} }
@Composable @Composable
fun FollowListFeedEmpty( fun FollowSetFeedEmpty(
message: String = stringRes(R.string.feed_is_empty), message: String = stringRes(R.string.feed_is_empty),
onRefresh: () -> Unit, onRefresh: () -> Unit,
) { ) {
@@ -65,6 +65,7 @@ import androidx.compose.runtime.remember
import androidx.compose.ui.Alignment import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color import androidx.compose.ui.graphics.Color
import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.res.painterResource import androidx.compose.ui.res.painterResource
import androidx.compose.ui.semantics.Role import androidx.compose.ui.semantics.Role
import androidx.compose.ui.text.font.FontWeight import androidx.compose.ui.text.font.FontWeight
@@ -80,7 +81,7 @@ import com.vitorpamplona.amethyst.ui.navigation.navs.INav
import com.vitorpamplona.amethyst.ui.note.ArrowBackIcon import com.vitorpamplona.amethyst.ui.note.ArrowBackIcon
import com.vitorpamplona.amethyst.ui.screen.loggedIn.lists.FollowSetState import com.vitorpamplona.amethyst.ui.screen.loggedIn.lists.FollowSetState
import com.vitorpamplona.amethyst.ui.screen.loggedIn.lists.ListVisibility import com.vitorpamplona.amethyst.ui.screen.loggedIn.lists.ListVisibility
import com.vitorpamplona.amethyst.ui.screen.loggedIn.lists.NewListCreationDialog import com.vitorpamplona.amethyst.ui.screen.loggedIn.lists.NewSetCreationDialog
import com.vitorpamplona.amethyst.ui.screen.loggedIn.lists.NostrUserListFeedViewModel import com.vitorpamplona.amethyst.ui.screen.loggedIn.lists.NostrUserListFeedViewModel
import com.vitorpamplona.amethyst.ui.stringRes import com.vitorpamplona.amethyst.ui.stringRes
import com.vitorpamplona.amethyst.ui.theme.ButtonBorder import com.vitorpamplona.amethyst.ui.theme.ButtonBorder
@@ -109,10 +110,9 @@ fun FollowSetsManagementDialog(
title = { title = {
Column { Column {
Text( Text(
text = "Your Lists", text = stringRes(R.string.follow_set_man_dialog_title),
fontWeight = FontWeight.SemiBold, fontWeight = FontWeight.SemiBold,
) )
// HorizontalDivider()
} }
}, },
navigationIcon = { navigationIcon = {
@@ -230,7 +230,7 @@ fun BackActionButton(
colors = ButtonDefaults.filledTonalButtonColors(), colors = ButtonDefaults.filledTonalButtonColors(),
elevation = ButtonDefaults.elevatedButtonElevation(defaultElevation = 6.0.dp), elevation = ButtonDefaults.elevatedButtonElevation(defaultElevation = 6.0.dp),
) { ) {
Text(text = "Back", fontWeight = FontWeight.SemiBold) Text(text = stringRes(R.string.back), fontWeight = FontWeight.SemiBold)
} }
} }
@@ -257,7 +257,7 @@ private fun EmptyOrNoneFound(onRefresh: () -> Unit) {
horizontalAlignment = Alignment.CenterHorizontally, horizontalAlignment = Alignment.CenterHorizontally,
verticalArrangement = Arrangement.Center, verticalArrangement = Arrangement.Center,
) { ) {
Text("No follow sets were found, or you don't have any follow sets. Tap below to refresh, or use the menu to create one.") Text(text = stringRes(R.string.follow_set_empty_dialog_msg))
Spacer(modifier = StdVertSpacer) Spacer(modifier = StdVertSpacer)
OutlinedButton(onClick = onRefresh) { Text(text = stringRes(R.string.refresh)) } OutlinedButton(onClick = onRefresh) { Text(text = stringRes(R.string.refresh)) }
} }
@@ -275,7 +275,7 @@ private fun ErrorMessage(
horizontalAlignment = Alignment.CenterHorizontally, horizontalAlignment = Alignment.CenterHorizontally,
verticalArrangement = Arrangement.Center, verticalArrangement = Arrangement.Center,
) { ) {
Text("There was a problem while fetching: $errorMsg") Text(text = stringRes(R.string.follow_set_error_dialog_msg, errorMsg))
Spacer(modifier = StdVertSpacer) Spacer(modifier = StdVertSpacer)
OutlinedButton(onClick = onRefresh) { Text(text = stringRes(R.string.refresh)) } OutlinedButton(onClick = onRefresh) { Text(text = stringRes(R.string.refresh)) }
} }
@@ -291,6 +291,7 @@ fun FollowSetItem(
onAddUser: () -> Unit, onAddUser: () -> Unit,
onRemoveUser: () -> Unit, onRemoveUser: () -> Unit,
) { ) {
val context = LocalContext.current
Row( Row(
modifier = modifier =
modifier modifier
@@ -313,9 +314,9 @@ fun FollowSetItem(
listVisibility.let { listVisibility.let {
val text by derivedStateOf { val text by derivedStateOf {
when (it) { when (it) {
ListVisibility.Public -> "Public" ListVisibility.Public -> stringRes(context, R.string.follow_set_type_public)
ListVisibility.Private -> "Private" ListVisibility.Private -> stringRes(context, R.string.follow_set_type_private)
ListVisibility.Mixed -> "Mixed" ListVisibility.Mixed -> stringRes(context, R.string.follow_set_type_mixed)
} }
} }
Icon( Icon(
@@ -327,7 +328,7 @@ fun FollowSetItem(
ListVisibility.Mixed -> R.drawable.format_list_bulleted_type ListVisibility.Mixed -> R.drawable.format_list_bulleted_type
}, },
), ),
contentDescription = "Icon for $text List", contentDescription = stringRes(R.string.follow_set_type_description, text),
) )
} }
} }
@@ -339,7 +340,14 @@ fun FollowSetItem(
enabled = isUserInList, enabled = isUserInList,
onClick = {}, onClick = {},
label = { label = {
Text(text = if (isUserInList) "$userName is present in this list" else "$userName is not in this list") Text(
text =
if (isUserInList) {
stringRes(R.string.follow_set_presence_indicator, userName)
} else {
stringRes(R.string.follow_set_absence_indicator, userName)
},
)
}, },
leadingIcon = leadingIcon =
if (isUserInList) { if (isUserInList) {
@@ -392,7 +400,7 @@ fun FollowSetItem(
) )
} }
} }
Text(text = if (isUserInList) "Remove" else "Add", color = Color.Gray) Text(text = stringRes(if (isUserInList) R.string.remove else R.string.add), color = Color.Gray)
} }
} }
} }
@@ -410,7 +418,7 @@ fun FollowSetsCreationMenu(
modifier = modifier.padding(vertical = 30.dp), modifier = modifier.padding(vertical = 30.dp),
) { ) {
Text( Text(
"Make New List", stringRes(R.string.follow_set_creation_menu_title),
fontSize = 18.sp, fontSize = 18.sp,
fontWeight = FontWeight.Bold, fontWeight = FontWeight.Bold,
textAlign = TextAlign.Start, textAlign = TextAlign.Start,
@@ -439,7 +447,7 @@ fun FollowSetsCreationMenu(
} }
if (isListAdditionDialogOpen.value) { if (isListAdditionDialogOpen.value) {
NewListCreationDialog( NewSetCreationDialog(
onDismiss = { onDismiss = {
isListAdditionDialogOpen.value = false isListAdditionDialogOpen.value = false
isPrivateOptionTapped.value = false isPrivateOptionTapped.value = false
@@ -459,6 +467,9 @@ fun FollowSetCreationItem(
userName: String, userName: String,
onClick: () -> Unit, onClick: () -> Unit,
) { ) {
val context = LocalContext.current
val setTypeLabel = stringRes(context, if (setIsPrivate) R.string.follow_set_type_private else R.string.follow_set_type_public)
HorizontalDivider() HorizontalDivider()
Column( Column(
modifier = modifier =
@@ -477,7 +488,11 @@ fun FollowSetCreationItem(
verticalAlignment = Alignment.CenterVertically, verticalAlignment = Alignment.CenterVertically,
) { ) {
Text( Text(
text = "Create new ${if (setIsPrivate) "Private" else "Public"} list with user", text =
stringRes(
R.string.follow_set_creation_item_label,
setTypeLabel,
),
fontWeight = FontWeight.SemiBold, fontWeight = FontWeight.SemiBold,
) )
Spacer(modifier = StdHorzSpacer) Spacer(modifier = StdHorzSpacer)
@@ -491,7 +506,7 @@ fun FollowSetCreationItem(
} }
Spacer(modifier = StdVertSpacer) Spacer(modifier = StdVertSpacer)
Text( Text(
"Creates a ${if (setIsPrivate) "private" else "public"} follow set, and adds $userName to it.", stringRes(R.string.follow_set_creation_item_description, setTypeLabel, userName),
fontWeight = FontWeight.Light, fontWeight = FontWeight.Light,
overflow = TextOverflow.Ellipsis, overflow = TextOverflow.Ellipsis,
maxLines = 2, maxLines = 2,
@@ -23,7 +23,6 @@ package com.vitorpamplona.amethyst.ui.screen.loggedIn.profile.header
import androidx.compose.foundation.shape.CornerSize import androidx.compose.foundation.shape.CornerSize
import androidx.compose.material.icons.Icons import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.automirrored.filled.List import androidx.compose.material.icons.automirrored.filled.List
import androidx.compose.material.icons.filled.List
import androidx.compose.material3.ButtonDefaults import androidx.compose.material3.ButtonDefaults
import androidx.compose.material3.Icon import androidx.compose.material3.Icon
import androidx.compose.material3.TextButton import androidx.compose.material3.TextButton
@@ -31,12 +30,14 @@ import androidx.compose.runtime.Composable
import androidx.compose.runtime.derivedStateOf import androidx.compose.runtime.derivedStateOf
import androidx.compose.runtime.getValue import androidx.compose.runtime.getValue
import androidx.compose.runtime.remember import androidx.compose.runtime.remember
import com.vitorpamplona.amethyst.R
import com.vitorpamplona.amethyst.model.User import com.vitorpamplona.amethyst.model.User
import com.vitorpamplona.amethyst.service.relayClient.reqCommand.account.observeAccountIsHiddenUser import com.vitorpamplona.amethyst.service.relayClient.reqCommand.account.observeAccountIsHiddenUser
import com.vitorpamplona.amethyst.ui.navigation.navs.INav import com.vitorpamplona.amethyst.ui.navigation.navs.INav
import com.vitorpamplona.amethyst.ui.navigation.routes.Route import com.vitorpamplona.amethyst.ui.navigation.routes.Route
import com.vitorpamplona.amethyst.ui.screen.loggedIn.AccountViewModel import com.vitorpamplona.amethyst.ui.screen.loggedIn.AccountViewModel
import com.vitorpamplona.amethyst.ui.screen.loggedIn.profile.zaps.ShowUserButton import com.vitorpamplona.amethyst.ui.screen.loggedIn.profile.zaps.ShowUserButton
import com.vitorpamplona.amethyst.ui.stringRes
import com.vitorpamplona.amethyst.ui.theme.ButtonBorder import com.vitorpamplona.amethyst.ui.theme.ButtonBorder
import com.vitorpamplona.amethyst.ui.theme.ZeroPadding import com.vitorpamplona.amethyst.ui.theme.ZeroPadding
@@ -69,7 +70,7 @@ fun ProfileActions(
) { ) {
Icon( Icon(
imageVector = Icons.AutoMirrored.Filled.List, imageVector = Icons.AutoMirrored.Filled.List,
contentDescription = "Add or remove user from lists, or create a new list with this user.", contentDescription = stringRes(R.string.follow_set_profile_actions_menu_description),
) )
} }
} }
+32 -1
View File
@@ -124,6 +124,7 @@
<string name="post">Post</string> <string name="post">Post</string>
<string name="save">Save</string> <string name="save">Save</string>
<string name="create">Create</string> <string name="create">Create</string>
<string name="rename">Rename</string>
<string name="cancel">Cancel</string> <string name="cancel">Cancel</string>
<string name="failed_to_upload_the_image">Failed to upload the image</string> <string name="failed_to_upload_the_image">Failed to upload the image</string>
<string name="relay_address">Relay Address</string> <string name="relay_address">Relay Address</string>
@@ -508,6 +509,36 @@
<string name="follow_list_global">Global</string> <string name="follow_list_global">Global</string>
<string name="follow_list_mute_list">Mute List</string> <string name="follow_list_mute_list">Mute List</string>
<string name="follow_sets">Follow Sets</string>
<string name="labeled_bookmarks">Labeled Bookmarks</string>
<string name="general_bookmarks">General Bookmarks</string>
<string name="follow_set_type_public">Public</string>
<string name="follow_set_type_private">Private</string>
<string name="follow_set_type_mixed">Mixed</string>
<string name="follow_set_empty_feed_msg">
It seems you do not have any follow sets yet.
\nTap below to refresh, or tap the add buttons to create a new one.
</string>
<string name="follow_set_add_author_from_note_action">Add author to follow set</string>
<string name="follow_set_profile_actions_menu_description">Add or remove user from lists, or create a new list with this user.</string>
<string name="follow_set_type_description">Icon for %1$s List</string>
<string name="follow_set_presence_indicator">"%1$s is present in this list"</string>
<string name="follow_set_absence_indicator">"%1$s is not in this list"</string>
<string name="follow_set_man_dialog_title">Your Follow Sets</string>
<string name="follow_set_empty_dialog_msg">No follow sets were found, or you don\'t have any follow sets. Tap below to refresh, or use the menu to create one.</string>
<string name="follow_set_error_dialog_msg">There was a problem while fetching: %1$s</string>
<string name="follow_set_creation_menu_title">Make New List</string>
<string name="follow_set_creation_item_label">"Create new %1$s list with user</string>
<string name="follow_set_creation_item_description">Creates a %1$s follow set, and adds %2$s to it.</string>
<string name="follow_set_creation_dialog_title">New %1$s List</string>
<string name="follow_set_creation_name_label">Set name</string>
<string name="follow_set_creation_desc_label">Set description(optional)</string>
<string name="follow_set_creation_action_btn_label">Create set</string>
<string name="follow_set_rename_btn_label">Rename set</string>
<string name="follow_set_rename_dialog_indicator_first_part">You are renaming from </string>
<string name="follow_set_rename_dialog_indicator_second_part"> to..</string>
<string name="connect_through_your_orbot_setup_short">Default port is 9050</string> <string name="connect_through_your_orbot_setup_short">Default port is 9050</string>
<string name="connect_through_your_orbot_setup_markdown"> <string name="connect_through_your_orbot_setup_markdown">
## Connect through Tor with Orbot ## Connect through Tor with Orbot
@@ -1231,7 +1262,7 @@
<string name="torrent_no_apps">No torrent apps installed to open and download the file.</string> <string name="torrent_no_apps">No torrent apps installed to open and download the file.</string>
<string name="torrent_no_info">Event doesn\'t have enough information to build a magnet link</string> <string name="torrent_no_info">Event doesn\'t have enough information to build a magnet link</string>
<string name="my_lists">My Lists</string> <string name="my_lists_and_sets">My Lists/Sets</string>
<string name="select_list_to_filter">Select a list to filter the feed</string> <string name="select_list_to_filter">Select a list to filter the feed</string>
<string name="temporary_account">Log off on device lock</string> <string name="temporary_account">Log off on device lock</string>