Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add Profile pictures in remaining places #214

Merged
merged 17 commits into from
Dec 19, 2024
Merged
Show file tree
Hide file tree
Changes from 16 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,6 @@ import de.tum.informatics.www1.artemis.native_app.feature.metis.shared.content.d
import de.tum.informatics.www1.artemis.native_app.feature.metis.shared.content.dto.conversation.GroupChat
import de.tum.informatics.www1.artemis.native_app.feature.metis.shared.content.dto.conversation.OneToOneChat
import de.tum.informatics.www1.artemis.native_app.feature.metis.shared.db.pojo.PostPojo
import de.tum.informatics.www1.artemis.native_app.feature.metis.shared.ui.humanReadableName
import de.tum.informatics.www1.artemis.native_app.feature.metis.shared.visiblemetiscontextreporter.LocalVisibleMetisContextManager
import de.tum.informatics.www1.artemis.native_app.feature.metis.shared.visiblemetiscontextreporter.VisibleMetisContext
import de.tum.informatics.www1.artemis.native_app.feature.metis.shared.visiblemetiscontextreporter.VisibleMetisContextManager
Expand Down Expand Up @@ -222,8 +221,8 @@ fun `Metis - Conversation Channel`() {
modifier = Modifier.fillMaxSize(),
courseId = ScreenshotCourse.id!!,
conversationId = sharedConversation.id,
conversationTitle = sharedConversation.humanReadableName,
isConversationLoaded = true,
conversationDataState = DataState.Success(sharedConversation),
clientId = 1L,
query = "",
onUpdateQuery = {},
onNavigateBack = {},
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,16 +2,19 @@ package de.tum.informatics.www1.artemis.native_app.feature.metis.conversation.ui

import androidx.activity.compose.BackHandler
import androidx.compose.foundation.layout.PaddingValues
import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.Spacer
import androidx.compose.foundation.layout.WindowInsets
import androidx.compose.foundation.layout.asPaddingValues
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.imePadding
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.systemBars
import androidx.compose.foundation.layout.width
import androidx.compose.foundation.lazy.LazyListState
import androidx.compose.foundation.lazy.rememberLazyListState
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.filled.ArrowBack
import androidx.compose.material.icons.automirrored.filled.ArrowBack
import androidx.compose.material.icons.filled.Search
import androidx.compose.material.icons.filled.Settings
import androidx.compose.material3.Icon
Expand All @@ -24,28 +27,35 @@ import androidx.compose.runtime.Composable
import androidx.compose.runtime.CompositionLocalProvider
import androidx.compose.runtime.LaunchedEffect
import androidx.compose.runtime.collectAsState
import androidx.compose.runtime.derivedStateOf
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.runtime.saveable.rememberSaveable
import androidx.compose.runtime.setValue
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.focus.FocusRequester
import androidx.compose.ui.focus.focusRequester
import androidx.compose.ui.text.style.TextOverflow
import androidx.compose.ui.unit.dp
import androidx.paging.compose.LazyPagingItems
import androidx.paging.compose.collectAsLazyPagingItems
import de.tum.informatics.www1.artemis.native_app.core.data.DataState
import de.tum.informatics.www1.artemis.native_app.core.data.isSuccess
import de.tum.informatics.www1.artemis.native_app.core.ui.common.BasicHintTextField
import de.tum.informatics.www1.artemis.native_app.core.ui.common.EmptyDataStateUi
import de.tum.informatics.www1.artemis.native_app.feature.metis.conversation.ui.chatlist.ChatListItem
import de.tum.informatics.www1.artemis.native_app.feature.metis.conversation.ui.chatlist.MetisChatList
import de.tum.informatics.www1.artemis.native_app.feature.metis.conversation.ui.reply.LocalReplyAutoCompleteHintProvider
import de.tum.informatics.www1.artemis.native_app.feature.metis.conversation.ui.shared.ConversationDataStatusButton
import de.tum.informatics.www1.artemis.native_app.feature.metis.conversation.ui.shared.isReplyEnabled
import de.tum.informatics.www1.artemis.native_app.feature.metis.shared.content.StandalonePostId
import de.tum.informatics.www1.artemis.native_app.feature.metis.shared.content.dto.conversation.Conversation
import de.tum.informatics.www1.artemis.native_app.feature.metis.shared.ui.ConversationIcon
import de.tum.informatics.www1.artemis.native_app.feature.metis.shared.ui.humanReadableName
import io.github.fornewid.placeholder.material3.placeholder


@Composable
internal fun ConversationChatListScreen(
modifier: Modifier,
Expand Down Expand Up @@ -78,12 +88,7 @@ internal fun ConversationChatListScreen(
val query by viewModel.chatListUseCase.query.collectAsState()
val conversationDataState by viewModel.latestUpdatedConversation.collectAsState()
val conversationDataStatus by viewModel.conversationDataStatus.collectAsState()

val title by remember(conversationDataState) {
derivedStateOf {
conversationDataState.bind { it.humanReadableName }.orElse("Conversation")
}
}
val clientId by viewModel.clientIdOrDefault.collectAsState()

val chatListState: LazyListState = rememberLazyListState()

Expand All @@ -94,10 +99,10 @@ internal fun ConversationChatListScreen(
modifier = modifier,
courseId = courseId,
conversationId = conversationId,
isConversationLoaded = conversationDataState.isSuccess,
clientId = clientId,
conversationDataState = conversationDataState,
conversationDataStatus = conversationDataStatus,
query = query,
conversationTitle = title,
onNavigateBack = onNavigateBack,
onNavigateToSettings = onNavigateToSettings,
onUpdateQuery = viewModel.chatListUseCase::updateQuery,
Expand All @@ -111,7 +116,11 @@ internal fun ConversationChatListScreen(
modifier = Modifier
.fillMaxSize()
.imePadding()
.padding(bottom = WindowInsets.systemBars.asPaddingValues().calculateBottomPadding()),
.padding(
bottom = WindowInsets.systemBars
.asPaddingValues()
.calculateBottomPadding()
),
viewModel = viewModel,
listContentPadding = PaddingValues(top = padding.calculateTopPadding()),
onClickViewPost = onClickViewPost,
Expand All @@ -129,10 +138,10 @@ fun ConversationChatListScreen(
modifier: Modifier,
courseId: Long,
conversationId: Long,
conversationTitle: String,
query: String,
conversationDataStatus: DataStatus,
isConversationLoaded: Boolean,
conversationDataState: DataState<Conversation>,
clientId: Long,
onNavigateBack: (() -> Unit)?,
onNavigateToSettings: () -> Unit,
onUpdateQuery: (String) -> Unit,
Expand Down Expand Up @@ -169,11 +178,14 @@ fun ConversationChatListScreen(
hintStyle = MaterialTheme.typography.bodyMedium
)
} else {
Text(
modifier = Modifier.placeholder(!isConversationLoaded),
text = conversationTitle,
maxLines = 1
)
EmptyDataStateUi(
dataState = conversationDataState,
otherwise = {
Text("placeholder", Modifier.placeholder(true))
}
) {
ConversationTitle(conversation = it, clientId = clientId)
}
}
},
navigationIcon = {
Expand All @@ -187,7 +199,7 @@ fun ConversationChatListScreen(
}
}
) {
Icon(imageVector = Icons.Default.ArrowBack, contentDescription = null)
Icon(imageVector = Icons.AutoMirrored.Filled.ArrowBack, contentDescription = null)
}
}
},
Expand All @@ -212,3 +224,30 @@ fun ConversationChatListScreen(
content = content
)
}


@Composable
private fun ConversationTitle(
modifier: Modifier = Modifier,
conversation: Conversation,
clientId: Long
) {
Row(
modifier = modifier,
verticalAlignment = Alignment.CenterVertically,
) {
ConversationIcon(
conversation = conversation,
clientId = clientId,
showDialogOnOneToOneChatClick = true
)

Spacer(Modifier.width(8.dp))

Text(
text = conversation.humanReadableName,
maxLines = 1,
overflow = TextOverflow.Ellipsis
)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.lazy.LazyColumn
import androidx.compose.foundation.lazy.LazyListState
import androidx.compose.foundation.lazy.rememberLazyListState
import androidx.compose.material3.Divider
import androidx.compose.material3.HorizontalDivider
import androidx.compose.material3.LinearProgressIndicator
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Text
Expand All @@ -22,6 +22,7 @@ import androidx.compose.runtime.getValue
import androidx.compose.runtime.remember
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.platform.testTag
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.text.font.FontWeight
Expand Down Expand Up @@ -71,7 +72,6 @@ internal fun MetisChatList(
state: LazyListState = rememberLazyListState(),
isReplyEnabled: Boolean = true,
onClickViewPost: (StandalonePostId) -> Unit,
title: String? = "Replying..."
) {
ReportVisibleMetisContext(remember(viewModel.metisContext) { VisiblePostList(viewModel.metisContext) })

Expand Down Expand Up @@ -138,6 +138,15 @@ fun MetisChatList(
onRequestRetrySend: (StandalonePostId) -> Unit,
title: String
) {
val context = LocalContext.current

// TODO: https://github.com/ls1intum/artemis-android/issues/213
// val navigateToChat = { userId: Long ->
// val chatLink = "artemis://courses/$courseId/messages?userId=$userId"
// val intent = Intent(Intent.ACTION_VIEW, Uri.parse(chatLink))
// context.startActivity(intent)
// }

MetisReplyHandler(
initialReplyTextProvider = initialReplyTextProvider,
onCreatePost = onCreatePost,
Expand Down Expand Up @@ -197,7 +206,7 @@ fun MetisChatList(
onRequestDelete = onDeletePostDelegate,
onRequestPin = onPinPostDelegate,
onRequestReactWithEmoji = onRequestReactWithEmojiDelegate,
onRequestRetrySend = onRequestRetrySend
onRequestRetrySend = onRequestRetrySend,
)
}
}
Expand Down Expand Up @@ -388,14 +397,14 @@ private fun DateDivider(modifier: Modifier, date: LocalDate) {
horizontalArrangement = Arrangement.spacedBy(4.dp),
verticalAlignment = Alignment.CenterVertically
) {
Divider(modifier = Modifier.weight(1f))
HorizontalDivider(modifier = Modifier.weight(1f))

Text(
text = dateAsString,
style = MaterialTheme.typography.bodyMedium,
fontWeight = FontWeight.Bold
)

Divider(modifier = Modifier.weight(1f))
HorizontalDivider(modifier = Modifier.weight(1f))
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -27,9 +27,6 @@ import androidx.compose.foundation.rememberScrollState
import androidx.compose.foundation.shape.CircleShape
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.filled.Check
import androidx.compose.material.icons.filled.Person
import androidx.compose.material.icons.filled.School
import androidx.compose.material.icons.filled.SupervisorAccount
import androidx.compose.material.icons.outlined.PushPin
import androidx.compose.material3.Icon
import androidx.compose.material3.MaterialTheme
Expand Down Expand Up @@ -60,8 +57,8 @@ import de.tum.informatics.www1.artemis.native_app.feature.metis.shared.content.d
import de.tum.informatics.www1.artemis.native_app.feature.metis.shared.content.dto.IReaction
import de.tum.informatics.www1.artemis.native_app.feature.metis.shared.content.dto.IStandalonePost
import de.tum.informatics.www1.artemis.native_app.feature.metis.shared.content.dto.UserRole
import de.tum.informatics.www1.artemis.native_app.feature.metis.shared.ui.profile_picture.ProfilePicture
import de.tum.informatics.www1.artemis.native_app.feature.metis.shared.ui.profile_picture.ProfilePictureData
import de.tum.informatics.www1.artemis.native_app.feature.metis.shared.ui.UserRoleIcon
import de.tum.informatics.www1.artemis.native_app.feature.metis.shared.ui.profile_picture.ProfilePictureWithDialog
import io.github.fornewid.placeholder.material3.placeholder
import kotlinx.datetime.Clock
import kotlinx.datetime.Instant
Expand Down Expand Up @@ -157,14 +154,11 @@ internal fun PostItem(
postStatus = postStatus,
authorRole = post?.authorRole,
authorName = post?.authorName,
profilePictureData = ProfilePictureData.create(
userId = post?.authorId,
username = post?.authorName,
imageUrl = post?.authorImageUrl
),
authorId = post?.authorId ?: -1,
authorImageUrl = post?.authorImageUrl,
creationDate = post?.creationDate,
expanded = isExpanded,
displayHeader = displayHeader
displayHeader = displayHeader,
) {
Column(
modifier = Modifier.fillMaxWidth(),
Expand Down Expand Up @@ -238,7 +232,8 @@ private fun PostHeadline(
modifier: Modifier,
authorRole: UserRole?,
authorName: String?,
profilePictureData: ProfilePictureData,
authorId: Long,
authorImageUrl: String?,
creationDate: Instant?,
postStatus: CreatePostService.Status,
expanded: Boolean = false,
Expand All @@ -252,7 +247,10 @@ private fun PostHeadline(
horizontalArrangement = Arrangement.spacedBy(16.dp)
) {
HeadlineProfilePicture(
profilePictureData = profilePictureData,
userId = authorId,
userName = authorName.orEmpty(),
imageUrl = authorImageUrl,
userRole = authorRole,
)

HeadlineAuthorInfo(
Expand All @@ -274,7 +272,10 @@ private fun PostHeadline(
val doDisplayHeader = displayHeader || postStatus == CreatePostService.Status.FAILED

HeadlineProfilePicture(
profilePictureData = profilePictureData,
userId = authorId,
userName = authorName.orEmpty(),
imageUrl = authorImageUrl,
userRole = authorRole,
displayImage = doDisplayHeader
)

Expand Down Expand Up @@ -380,7 +381,7 @@ private fun AuthorRoleAndNameRow(
Row(
verticalAlignment = Alignment.CenterVertically,
) {
HeadlineAuthorIcon(authorRole)
UserRoleIcon(userRole = authorRole)

Spacer(modifier = Modifier.width(4.dp))

Expand All @@ -396,7 +397,10 @@ private fun AuthorRoleAndNameRow(

@Composable
private fun HeadlineProfilePicture(
profilePictureData: ProfilePictureData,
userId: Long,
userName: String,
imageUrl: String?,
userRole: UserRole?,
displayImage: Boolean = true
) {
val size = 30.dp
Expand All @@ -405,32 +409,17 @@ private fun HeadlineProfilePicture(
return
}

ProfilePicture(
modifier = Modifier
.size(size)
.clip(MaterialTheme.shapes.extraSmall),
profilePictureData = profilePictureData,
ProfilePictureWithDialog(
modifier = Modifier.size(size),
userId = userId,
userName = userName,
userRole = userRole,
imageUrl = imageUrl,
)
}
}

@Composable
private fun HeadlineAuthorIcon(
authorRole: UserRole?,
) {
val icon = when (authorRole) {
UserRole.INSTRUCTOR -> Icons.Default.School
UserRole.TUTOR -> Icons.Default.SupervisorAccount
UserRole.USER -> Icons.Default.Person
null -> Icons.Default.Person
}

Icon(
modifier = Modifier.size(16.dp),
imageVector = icon,
contentDescription = null
)
}

/**
* Display the tags, the reactions and the action buttons like reply, view replies and react with emoji.
Expand Down
Loading
Loading