fix: handle user profile navigation correctly
This commit is contained in:
parent
2b9680d3d8
commit
d0bf2a4fb2
|
@ -16,6 +16,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|||
* Fixed a crash when clicking an item on the bottom navigation bar
|
||||
too quickly
|
||||
* Removed buggy deeplinks
|
||||
* Clicking a username now correctly navigates to the right page in-app
|
||||
|
||||
## [1.44.0] - 2024-03-19
|
||||
|
||||
|
|
|
@ -261,6 +261,11 @@ fun LobstersPostsScreen(
|
|||
htmlConverter = htmlConverter,
|
||||
getSeenComments = viewModel::getSeenComments,
|
||||
markSeenComments = viewModel::markSeenComments,
|
||||
openUserProfile = {
|
||||
navController.navigate(
|
||||
Destinations.User.route.replace(Destinations.User.PLACEHOLDER, it)
|
||||
)
|
||||
},
|
||||
)
|
||||
}
|
||||
composable(
|
||||
|
@ -272,7 +277,15 @@ fun LobstersPostsScreen(
|
|||
"Navigating to ${Destinations.User.route} without necessary 'username' argument"
|
||||
}
|
||||
setWebUri("https://lobste.rs/u/$username")
|
||||
UserProfile(username = username, getProfile = viewModel::getUserProfile)
|
||||
UserProfile(
|
||||
username = username,
|
||||
getProfile = viewModel::getUserProfile,
|
||||
openUserProfile = {
|
||||
navController.navigate(
|
||||
Destinations.User.route.replace(Destinations.User.PLACEHOLDER, it)
|
||||
)
|
||||
},
|
||||
)
|
||||
}
|
||||
composable(route = Destinations.Settings.route) {
|
||||
SettingsScreen(
|
||||
|
|
|
@ -67,6 +67,11 @@ fun SearchScreen(
|
|||
htmlConverter = htmlConverter,
|
||||
getSeenComments = viewModel::getSeenComments,
|
||||
markSeenComments = viewModel::markSeenComments,
|
||||
openUserProfile = { username: String ->
|
||||
navController.navigate(
|
||||
Destinations.User.route.replace(Destinations.User.PLACEHOLDER, username)
|
||||
)
|
||||
},
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -29,7 +29,6 @@ import androidx.compose.runtime.getValue
|
|||
import androidx.compose.runtime.produceState
|
||||
import androidx.compose.runtime.remember
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.platform.LocalUriHandler
|
||||
import androidx.compose.ui.text.AnnotatedString
|
||||
import androidx.compose.ui.text.SpanStyle
|
||||
import androidx.compose.ui.text.buildAnnotatedString
|
||||
|
@ -56,9 +55,9 @@ internal fun CommentsHeader(
|
|||
post: UIPost,
|
||||
postActions: PostActions,
|
||||
htmlConverter: HTMLConverter,
|
||||
openUserProfile: (String) -> Unit,
|
||||
modifier: Modifier = Modifier,
|
||||
) {
|
||||
val uriHandler = LocalUriHandler.current
|
||||
val linkMetadata by
|
||||
produceState(initialValue = LinkMetadata(post.url, null)) {
|
||||
runSuspendCatching { postActions.getLinkMetadata(post.url) }
|
||||
|
@ -93,8 +92,7 @@ internal fun CommentsHeader(
|
|||
text = AnnotatedString("Submitted by ${post.submitter}"),
|
||||
avatarUrl = "https://lobste.rs/avatars/${post.submitter}-100.png",
|
||||
contentDescription = "User avatar for ${post.submitter}",
|
||||
modifier =
|
||||
Modifier.clickable { uriHandler.openUri("https://lobste.rs/u/${post.submitter}") },
|
||||
modifier = Modifier.clickable { openUserProfile(post.submitter) },
|
||||
)
|
||||
}
|
||||
}
|
||||
|
@ -133,9 +131,9 @@ internal fun CommentEntry(
|
|||
commentNode: CommentNode,
|
||||
htmlConverter: HTMLConverter,
|
||||
toggleExpanded: (CommentNode) -> Unit,
|
||||
openUserProfile: (String) -> Unit,
|
||||
modifier: Modifier = Modifier,
|
||||
) {
|
||||
val uriHandler = LocalUriHandler.current
|
||||
val comment = commentNode.comment
|
||||
Box(
|
||||
modifier =
|
||||
|
@ -162,7 +160,7 @@ internal fun CommentEntry(
|
|||
),
|
||||
avatarUrl = "https://lobste.rs/avatars/${comment.user}-100.png",
|
||||
contentDescription = "User avatar for ${comment.user}",
|
||||
modifier = Modifier.clickable { uriHandler.openUri("https://lobste.rs/u/${comment.user}") },
|
||||
modifier = Modifier.clickable { openUserProfile(comment.user) },
|
||||
)
|
||||
if (commentNode.isExpanded) {
|
||||
ThemedRichText(
|
||||
|
|
|
@ -84,9 +84,15 @@ internal fun LazyListScope.nodes(
|
|||
nodes: List<CommentNode>,
|
||||
htmlConverter: HTMLConverter,
|
||||
toggleExpanded: (CommentNode) -> Unit,
|
||||
openUserProfile: (String) -> Unit,
|
||||
) {
|
||||
nodes.forEach { node ->
|
||||
node(node = node, htmlConverter = htmlConverter, toggleExpanded = toggleExpanded)
|
||||
node(
|
||||
node = node,
|
||||
htmlConverter = htmlConverter,
|
||||
toggleExpanded = toggleExpanded,
|
||||
openUserProfile = openUserProfile,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -94,16 +100,27 @@ private fun LazyListScope.node(
|
|||
node: CommentNode,
|
||||
htmlConverter: HTMLConverter,
|
||||
toggleExpanded: (CommentNode) -> Unit,
|
||||
openUserProfile: (String) -> Unit,
|
||||
) {
|
||||
// Skip the node if neither the node nor its parent is expanded
|
||||
if (!node.isExpanded && node.parent?.isExpanded == false) {
|
||||
return
|
||||
}
|
||||
item {
|
||||
CommentEntry(commentNode = node, htmlConverter = htmlConverter, toggleExpanded = toggleExpanded)
|
||||
CommentEntry(
|
||||
commentNode = node,
|
||||
htmlConverter = htmlConverter,
|
||||
toggleExpanded = toggleExpanded,
|
||||
openUserProfile = openUserProfile,
|
||||
)
|
||||
HorizontalDivider()
|
||||
}
|
||||
if (node.children.isNotEmpty()) {
|
||||
nodes(node.children, htmlConverter = htmlConverter, toggleExpanded = toggleExpanded)
|
||||
nodes(
|
||||
node.children,
|
||||
htmlConverter = htmlConverter,
|
||||
toggleExpanded = toggleExpanded,
|
||||
openUserProfile = openUserProfile,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -46,6 +46,7 @@ private fun CommentsPageInternal(
|
|||
htmlConverter: HTMLConverter,
|
||||
commentState: PostComments?,
|
||||
markSeenComments: (String, List<Comment>) -> Unit,
|
||||
openUserProfile: (String) -> Unit,
|
||||
modifier: Modifier = Modifier,
|
||||
) {
|
||||
val commentNodes = createListNode(details.comments, commentState).toMutableStateList()
|
||||
|
@ -54,7 +55,12 @@ private fun CommentsPageInternal(
|
|||
Surface(color = MaterialTheme.colorScheme.surfaceVariant) {
|
||||
LazyColumn(modifier = modifier, contentPadding = PaddingValues(bottom = 24.dp)) {
|
||||
item {
|
||||
CommentsHeader(post = details, postActions = postActions, htmlConverter = htmlConverter)
|
||||
CommentsHeader(
|
||||
post = details,
|
||||
postActions = postActions,
|
||||
htmlConverter = htmlConverter,
|
||||
openUserProfile = openUserProfile,
|
||||
)
|
||||
}
|
||||
|
||||
if (commentNodes.isNotEmpty()) {
|
||||
|
@ -79,6 +85,7 @@ private fun CommentsPageInternal(
|
|||
commentNodes.add(index, parent)
|
||||
}
|
||||
},
|
||||
openUserProfile = openUserProfile,
|
||||
)
|
||||
} else {
|
||||
item {
|
||||
|
@ -104,6 +111,7 @@ fun CommentsPage(
|
|||
getSeenComments: suspend (String) -> PostComments?,
|
||||
markSeenComments: (String, List<Comment>) -> Unit,
|
||||
modifier: Modifier = Modifier,
|
||||
openUserProfile: (String) -> Unit,
|
||||
) {
|
||||
val postDetails by
|
||||
produceState<NetworkState>(Loading) {
|
||||
|
@ -124,6 +132,7 @@ fun CommentsPage(
|
|||
htmlConverter = htmlConverter,
|
||||
commentState = commentState,
|
||||
markSeenComments = markSeenComments,
|
||||
openUserProfile = openUserProfile,
|
||||
modifier = modifier.fillMaxSize(),
|
||||
)
|
||||
}
|
||||
|
|
|
@ -24,6 +24,8 @@ import androidx.compose.runtime.produceState
|
|||
import androidx.compose.ui.Alignment
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.draw.clip
|
||||
import androidx.compose.ui.text.LinkAnnotation
|
||||
import androidx.compose.ui.text.buildAnnotatedString
|
||||
import androidx.compose.ui.unit.dp
|
||||
import com.github.michaelbull.result.coroutines.runSuspendCatching
|
||||
import com.github.michaelbull.result.fold
|
||||
|
@ -42,6 +44,7 @@ import dev.msfjarvis.claw.model.User
|
|||
fun UserProfile(
|
||||
username: String,
|
||||
getProfile: suspend (username: String) -> User,
|
||||
openUserProfile: (String) -> Unit,
|
||||
modifier: Modifier = Modifier,
|
||||
) {
|
||||
val user by
|
||||
|
@ -56,7 +59,11 @@ fun UserProfile(
|
|||
}
|
||||
when (user) {
|
||||
is Success<*> -> {
|
||||
UserProfileInternal(user = (user as Success<User>).data, modifier = modifier)
|
||||
UserProfileInternal(
|
||||
user = (user as Success<User>).data,
|
||||
openUserProfile = openUserProfile,
|
||||
modifier = modifier,
|
||||
)
|
||||
}
|
||||
is Error -> {
|
||||
val error = user as Error
|
||||
|
@ -77,7 +84,11 @@ fun UserProfile(
|
|||
}
|
||||
|
||||
@Composable
|
||||
private fun UserProfileInternal(user: User, modifier: Modifier = Modifier) {
|
||||
private fun UserProfileInternal(
|
||||
user: User,
|
||||
openUserProfile: (String) -> Unit,
|
||||
modifier: Modifier = Modifier,
|
||||
) {
|
||||
Surface(modifier = modifier) {
|
||||
Column(
|
||||
horizontalAlignment = Alignment.CenterHorizontally,
|
||||
|
@ -93,7 +104,19 @@ private fun UserProfileInternal(user: User, modifier: Modifier = Modifier) {
|
|||
Text(text = user.username, style = MaterialTheme.typography.displaySmall)
|
||||
ThemedRichText(text = user.about)
|
||||
user.invitedBy?.let { invitedBy ->
|
||||
ThemedRichText(text = "Invited by [${invitedBy}](https://lobste.rs/u/${user.invitedBy})")
|
||||
Text(
|
||||
text =
|
||||
buildAnnotatedString {
|
||||
append("Invited by ")
|
||||
pushLink(
|
||||
LinkAnnotation.Clickable(
|
||||
tag = "username",
|
||||
linkInteractionListener = { openUserProfile(invitedBy) },
|
||||
)
|
||||
)
|
||||
append(invitedBy)
|
||||
}
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue