diff --git a/app/src/main/java/com/vitorpamplona/amethyst/ui/note/BoostSetCompose.kt b/app/src/main/java/com/vitorpamplona/amethyst/ui/note/BoostSetCompose.kt index a7291ced6..b45eda201 100644 --- a/app/src/main/java/com/vitorpamplona/amethyst/ui/note/BoostSetCompose.kt +++ b/app/src/main/java/com/vitorpamplona/amethyst/ui/note/BoostSetCompose.kt @@ -76,19 +76,12 @@ fun BoostSetCompose(likeSetCard: BoostSetCard, isInnerNote: Boolean = false, rou Column(modifier = Modifier.padding(start = if (!isInnerNote) 10.dp else 0.dp)) { FlowRow() { likeSetCard.boostEvents.forEach { - val cardNoteState by it.live.observeAsState() - val cardNote = cardNoteState?.note - - if (cardNote?.author != null) { - val userState by cardNote.author!!.live.observeAsState() - - UserPicture( - user = userState?.user, - navController = navController, - userAccount = account.userProfile(), - size = 35.dp - ) - } + NoteAuthorPicture( + note = it, + navController = navController, + userAccount = account.userProfile(), + size = 35.dp + ) } } diff --git a/app/src/main/java/com/vitorpamplona/amethyst/ui/note/ChatroomCompose.kt b/app/src/main/java/com/vitorpamplona/amethyst/ui/note/ChatroomCompose.kt index 15b9b7112..ee1c436ff 100644 --- a/app/src/main/java/com/vitorpamplona/amethyst/ui/note/ChatroomCompose.kt +++ b/app/src/main/java/com/vitorpamplona/amethyst/ui/note/ChatroomCompose.kt @@ -134,7 +134,7 @@ fun ChatroomCompose(baseNote: Note, accountViewModel: AccountViewModel, navContr false ChannelName( - channelPicture = { UserPicture(user = user, userAccount = accountUser, size = 55.dp) }, + channelPicture = { UserPicture(user, accountUser, size = 55.dp) }, channelTitle = { UsernameDisplay(user, it) }, channelLastTime = noteEvent?.createdAt, channelLastContent = accountViewModel.decrypt(note), diff --git a/app/src/main/java/com/vitorpamplona/amethyst/ui/note/LikeSetCompose.kt b/app/src/main/java/com/vitorpamplona/amethyst/ui/note/LikeSetCompose.kt index 79a084c55..67fc34288 100644 --- a/app/src/main/java/com/vitorpamplona/amethyst/ui/note/LikeSetCompose.kt +++ b/app/src/main/java/com/vitorpamplona/amethyst/ui/note/LikeSetCompose.kt @@ -76,19 +76,12 @@ fun LikeSetCompose(likeSetCard: LikeSetCard, modifier: Modifier = Modifier, isIn Column(modifier = Modifier.padding(start = if (!isInnerNote) 10.dp else 0.dp)) { FlowRow() { likeSetCard.likeEvents.forEach { - val cardNoteState by it.live.observeAsState() - val cardNote = cardNoteState?.note - - if (cardNote?.author != null) { - val userState by cardNote.author!!.live.observeAsState() - - UserPicture( - user = userState?.user, - navController = navController, - userAccount = account.userProfile(), - size = 35.dp - ) - } + NoteAuthorPicture( + note = it, + navController = navController, + userAccount = account.userProfile(), + size = 35.dp + ) } } diff --git a/app/src/main/java/com/vitorpamplona/amethyst/ui/note/NoteCompose.kt b/app/src/main/java/com/vitorpamplona/amethyst/ui/note/NoteCompose.kt index 93e438c90..8fb185fa3 100644 --- a/app/src/main/java/com/vitorpamplona/amethyst/ui/note/NoteCompose.kt +++ b/app/src/main/java/com/vitorpamplona/amethyst/ui/note/NoteCompose.kt @@ -95,9 +95,6 @@ fun NoteCompose( onLongClick = { popupExpanded = true }, ), isInnerNote) } else { - val authorState by note.author?.live!!.observeAsState() - val author = authorState?.user ?: return // if it has event, it should have an author - val isNew = routeForLastRead?.run { val lastTime = NotificationCache.load(this, context) @@ -145,20 +142,20 @@ fun NoteCompose( Box(modifier = Modifier .width(55.dp) .padding(0.dp)) { - UserPicture(author, navController, account.userProfile(), 55.dp) - // boosted picture - val boostedPosts = note.replyTo - if (note.event is RepostEvent && boostedPosts != null && boostedPosts.isNotEmpty()) { - val boostedAuthor = boostedPosts[0].author - Box( - Modifier - .width(30.dp) - .height(30.dp) - .align(Alignment.BottomEnd)) { - UserPicture(boostedAuthor, navController, account.userProfile(), 35.dp, - pictureModifier = Modifier.border(2.dp, MaterialTheme.colors.background, CircleShape) - ) + NoteAuthorPicture(note, navController, account.userProfile(), 55.dp) + + if (note.event is RepostEvent) { + note.replyTo?.lastOrNull()?.let { + Box( + Modifier + .width(30.dp) + .height(30.dp) + .align(Alignment.BottomEnd)) { + NoteAuthorPicture(it, navController, account.userProfile(), 35.dp, + pictureModifier = Modifier.border(2.dp, MaterialTheme.colors.background, CircleShape) + ) + } } } @@ -197,8 +194,7 @@ fun NoteCompose( Column(modifier = Modifier.padding(start = if (!isInnerNote) 10.dp else 0.dp)) { Row(verticalAlignment = Alignment.CenterVertically) { - if (author != null) - UsernameDisplay(author, Modifier.weight(1f)) + NoteUsernameDisplay(note, Modifier.weight(1f)) if (note.event !is RepostEvent) { Text( @@ -274,40 +270,42 @@ fun NoteCompose( } } + @Composable -fun UserPicture( - user: User?, +fun NoteAuthorPicture( + note: Note, navController: NavController, userAccount: User, size: Dp, pictureModifier: Modifier = Modifier ) { - UserPicture(user, userAccount, size, pictureModifier) { - user?.let { - navController.navigate("User/${it.pubkeyHex}") - } + NoteAuthorPicture(note, userAccount, size, pictureModifier) { + navController.navigate("User/${it.pubkeyHex}") } } + @Composable -fun UserPicture( - user: User?, - userAccount: User, +fun NoteAuthorPicture( + baseNote: Note, + baseUserAccount: User, size: Dp, pictureModifier: Modifier = Modifier, - onClick: (() -> Unit)? = null + onClick: ((User) -> Unit)? = null ) { - val accountState by userAccount.live.observeAsState() - val accountUser = accountState?.user ?: return + val noteState by baseNote.live.observeAsState() + val note = noteState?.note ?: return + + val author = note.author Box( Modifier .width(size) .height(size)) { - if (user == null) { + if (author == null) { AsyncImage( model = "https://robohash.org/ohno.png", - contentDescription = "Profile Image", + contentDescription = "Unknown Author", placeholder = rememberAsyncImagePainter("https://robohash.org/ohno.png"), modifier = pictureModifier .fillMaxSize(1f) @@ -315,54 +313,88 @@ fun UserPicture( .background(MaterialTheme.colors.background) ) } else { - val userState by user.live.observeAsState() - val userLive = userState?.user ?: return + UserPicture(author, baseUserAccount, size, pictureModifier, onClick) + } + } +} - AsyncImage( - model = userLive.profilePicture(), - contentDescription = "Profile Image", - placeholder = rememberAsyncImagePainter("https://robohash.org/${userLive.pubkeyHex}.png"), - modifier = pictureModifier - .fillMaxSize(1f) - .clip(shape = CircleShape) - .background(MaterialTheme.colors.background) - .run { - if (onClick != null) - this.clickable(onClick = onClick) - else - this - } +@Composable +fun UserPicture( + user: User, + navController: NavController, + userAccount: User, + size: Dp, + pictureModifier: Modifier = Modifier +) { + UserPicture(user, userAccount, size, pictureModifier) { + navController.navigate("User/${it.pubkeyHex}") + } +} - ) +@Composable +fun UserPicture( + baseUser: User, + baseUserAccount: User, + size: Dp, + pictureModifier: Modifier = Modifier, + onClick: ((User) -> Unit)? = null +) { + val accountState by baseUserAccount.live.observeAsState() + val accountUser = accountState?.user ?: return - if (accountUser.isFollowing(userLive) || userLive == accountUser) { - Box( - Modifier - .width(size.div(3.5f)) - .height(size.div(3.5f)) - .align(Alignment.TopEnd), - contentAlignment = Alignment.Center - ) { - // Background for the transparent checkmark - Text( - "x", - Modifier - .padding(4.dp) - .fillMaxSize() - .align(Alignment.Center) - .background(MaterialTheme.colors.background) - .clip(shape = CircleShape) - ) + val userState by baseUser.live.observeAsState() + val user = userState?.user ?: return - Icon( - painter = painterResource(R.drawable.ic_verified), - "Following", - modifier = Modifier.fillMaxSize(), - tint = Following - ) + Box( + Modifier + .width(size) + .height(size)) { + + AsyncImage( + model = user.profilePicture(), + contentDescription = "Profile Image", + placeholder = rememberAsyncImagePainter("https://robohash.org/${user.pubkeyHex}.png"), + modifier = pictureModifier + .fillMaxSize(1f) + .clip(shape = CircleShape) + .background(MaterialTheme.colors.background) + .run { + if (onClick != null) + this.clickable(onClick = { onClick(user) } ) + else + this } + + ) + + if (accountUser.isFollowing(user) || user == accountUser) { + Box( + Modifier + .width(size.div(3.5f)) + .height(size.div(3.5f)) + .align(Alignment.TopEnd), + contentAlignment = Alignment.Center + ) { + // Background for the transparent checkmark + Text( + "x", + Modifier + .padding(4.dp) + .fillMaxSize() + .align(Alignment.Center) + .background(MaterialTheme.colors.background) + .clip(shape = CircleShape) + ) + + Icon( + painter = painterResource(R.drawable.ic_verified), + "Following", + modifier = Modifier.fillMaxSize(), + tint = Following + ) } } + } } diff --git a/app/src/main/java/com/vitorpamplona/amethyst/ui/note/UserCompose.kt b/app/src/main/java/com/vitorpamplona/amethyst/ui/note/UserCompose.kt index bfbf85194..82af8d053 100644 --- a/app/src/main/java/com/vitorpamplona/amethyst/ui/note/UserCompose.kt +++ b/app/src/main/java/com/vitorpamplona/amethyst/ui/note/UserCompose.kt @@ -52,11 +52,11 @@ fun UserCompose(baseUser: User, accountViewModel: AccountViewModel, navControlle top = 10.dp) ) { - UserPicture(user, navController, account.userProfile(), 55.dp) + UserPicture(baseUser, navController, account.userProfile(), 55.dp) Column(modifier = Modifier.padding(start = 10.dp).weight(1f)) { Row(verticalAlignment = Alignment.CenterVertically) { - UsernameDisplay(user) + UsernameDisplay(baseUser) } Text( diff --git a/app/src/main/java/com/vitorpamplona/amethyst/ui/note/UsernameDisplay.kt b/app/src/main/java/com/vitorpamplona/amethyst/ui/note/UsernameDisplay.kt index adb156d72..604830125 100644 --- a/app/src/main/java/com/vitorpamplona/amethyst/ui/note/UsernameDisplay.kt +++ b/app/src/main/java/com/vitorpamplona/amethyst/ui/note/UsernameDisplay.kt @@ -3,42 +3,61 @@ package com.vitorpamplona.amethyst.ui.note import androidx.compose.material.MaterialTheme import androidx.compose.material.Text import androidx.compose.runtime.Composable +import androidx.compose.runtime.getValue +import androidx.compose.runtime.livedata.observeAsState import androidx.compose.ui.Modifier import androidx.compose.ui.text.font.FontWeight import androidx.compose.ui.text.style.TextOverflow +import com.vitorpamplona.amethyst.model.Note import com.vitorpamplona.amethyst.model.User + @Composable -fun UsernameDisplay(user: User, weight: Modifier = Modifier) { - if (user.bestUsername() != null || user.bestDisplayName() != null) { - if (user.bestDisplayName().isNullOrBlank()) { - Text( - "@${(user.bestUsername() ?: "")}", - fontWeight = FontWeight.Bold, - maxLines = 1, - overflow = TextOverflow.Ellipsis, - modifier = weight - ) - } else { - Text( - user.bestDisplayName() ?: "", - fontWeight = FontWeight.Bold, - ) - Text( - "@${(user.bestUsername() ?: "")}", - color = MaterialTheme.colors.onSurface.copy(alpha = 0.32f), - maxLines = 1, - overflow = TextOverflow.Ellipsis, - modifier = weight - ) - } - } else { +fun NoteUsernameDisplay(baseNote: Note, weight: Modifier = Modifier) { + val noteState by baseNote.live.observeAsState() + val note = noteState?.note ?: return + + val author = note.author + + if (author != null) { + UsernameDisplay(author, weight) + } +} + +@Composable +fun UsernameDisplay(baseUser: User, weight: Modifier = Modifier) { + val userState by baseUser.live.observeAsState() + val user = userState?.user ?: return + + if (user.bestUsername() != null || user.bestDisplayName() != null) { + if (user.bestDisplayName().isNullOrBlank()) { Text( - user.pubkeyDisplayHex, + "@${(user.bestUsername() ?: "")}", fontWeight = FontWeight.Bold, maxLines = 1, overflow = TextOverflow.Ellipsis, modifier = weight ) + } else { + Text( + user.bestDisplayName() ?: "", + fontWeight = FontWeight.Bold, + ) + Text( + "@${(user.bestUsername() ?: "")}", + color = MaterialTheme.colors.onSurface.copy(alpha = 0.32f), + maxLines = 1, + overflow = TextOverflow.Ellipsis, + modifier = weight + ) } + } else { + Text( + user.pubkeyDisplayHex, + fontWeight = FontWeight.Bold, + maxLines = 1, + overflow = TextOverflow.Ellipsis, + modifier = weight + ) + } } \ No newline at end of file diff --git a/app/src/main/java/com/vitorpamplona/amethyst/ui/screen/ThreadFeedView.kt b/app/src/main/java/com/vitorpamplona/amethyst/ui/screen/ThreadFeedView.kt index 4210b5545..32d0e7f5d 100644 --- a/app/src/main/java/com/vitorpamplona/amethyst/ui/screen/ThreadFeedView.kt +++ b/app/src/main/java/com/vitorpamplona/amethyst/ui/screen/ThreadFeedView.kt @@ -41,7 +41,9 @@ import com.vitorpamplona.amethyst.model.Note import com.vitorpamplona.amethyst.ui.components.RichTextViewer import com.vitorpamplona.amethyst.ui.note.BlankNote import com.vitorpamplona.amethyst.ui.note.HiddenNote +import com.vitorpamplona.amethyst.ui.note.NoteAuthorPicture import com.vitorpamplona.amethyst.ui.note.NoteCompose +import com.vitorpamplona.amethyst.ui.note.NoteUsernameDisplay import com.vitorpamplona.amethyst.ui.note.ReactionsRow import com.vitorpamplona.amethyst.ui.note.UserPicture import com.vitorpamplona.amethyst.ui.note.UsernameDisplay @@ -185,12 +187,16 @@ fun NoteMaster(baseNote: Note, accountViewModel: AccountViewModel, navController } }) ) { - UserPicture(user = author, navController, userAccount = account.userProfile(), size = 55.dp) + NoteAuthorPicture( + note = baseNote, + navController = navController, + userAccount = account.userProfile(), + size = 55.dp + ) Column(modifier = Modifier.padding(start = 10.dp)) { Row(verticalAlignment = Alignment.CenterVertically) { - if (author != null) - UsernameDisplay(author) + NoteUsernameDisplay(baseNote) } Row(verticalAlignment = Alignment.CenterVertically) { diff --git a/app/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/ChatroomScreen.kt b/app/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/ChatroomScreen.kt index 35ca8243e..785ea70d5 100644 --- a/app/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/ChatroomScreen.kt +++ b/app/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/ChatroomScreen.kt @@ -139,8 +139,7 @@ fun ChatroomHeader(baseUser: User, accountViewModel: AccountViewModel, navContro Column(modifier = Modifier.padding(start = 10.dp)) { Row(verticalAlignment = Alignment.CenterVertically) { - if (author != null) - UsernameDisplay(author) + UsernameDisplay(baseUser) } } } diff --git a/app/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/SearchScreen.kt b/app/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/SearchScreen.kt index 7c507bd5a..46482ae16 100644 --- a/app/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/SearchScreen.kt +++ b/app/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/SearchScreen.kt @@ -234,7 +234,7 @@ fun UserLine( .weight(1f) ) { Row(verticalAlignment = Alignment.CenterVertically) { - UsernameDisplay(user) + UsernameDisplay(baseUser) } Text(