Skip to content

Commit

Permalink
Feature: Send message via user dialog (#285)
Browse files Browse the repository at this point in the history
  • Loading branch information
FelberMartin authored Jan 17, 2025
1 parent faf48d4 commit 271b6ea
Show file tree
Hide file tree
Showing 31 changed files with 564 additions and 359 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -109,13 +109,17 @@ class MainActivity : AppCompatActivity(),
val visibleMetisContextManager = object :
VisibleMetisContextManager {
override fun registerMetisContext(metisContext: VisibleMetisContext) {
visibleMetisContexts.value = visibleMetisContexts.value + metisContext
visibleMetisContexts.value += metisContext

cancelCommunicationNotifications(metisContext)
}

override fun unregisterMetisContext(metisContext: VisibleMetisContext) {
visibleMetisContexts.value = visibleMetisContexts.value - metisContext
visibleMetisContexts.value -= metisContext
}

override fun getRegisteredMetisContexts(): List<VisibleMetisContext> {
return visibleMetisContexts.value
}
}

Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package de.tum.informatics.www1.artemis.native_app.core.data
package de.tum.informatics.www1.artemis.native_app.core.data.test

import de.tum.informatics.www1.artemis.native_app.core.data.NetworkResponse
import de.tum.informatics.www1.artemis.native_app.core.data.service.network.AccountDataService
import de.tum.informatics.www1.artemis.native_app.core.model.account.Account

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import de.tum.informatics.www1.artemis.native_app.android.appModule
import de.tum.informatics.www1.artemis.native_app.core.common.CurrentActivityListener
import de.tum.informatics.www1.artemis.native_app.core.common.test.UnitTest
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.UserIdentifier
import de.tum.informatics.www1.artemis.native_app.feature.quiz.QuizType
import org.junit.Test
import org.junit.experimental.categories.Category
Expand All @@ -32,6 +33,7 @@ class AppModuleTest {
SavedStateHandle::class,
Boolean::class,
Long::class,
UserIdentifier::class,
StandalonePostId::class,
Application::class,
CurrentActivityListener::class,
Expand Down
2 changes: 2 additions & 0 deletions feature/course-view/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -17,9 +17,11 @@ dependencies {
implementation(libs.kotlinx.datetime)
implementation(libs.placeholder.material)
implementation(project(":core:device-test"))
debugImplementation(project(":core:data-test"))

testImplementation(project(":feature:login"))
testImplementation(project(":feature:login-test"))
testImplementation(project(":feature:metis-test"))

kover(project(":core:data"))
}
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,8 @@ import de.tum.informatics.www1.artemis.native_app.feature.courseview.ui.CourseVi
import de.tum.informatics.www1.artemis.native_app.feature.courseview.ui.course_overview.CourseUiScreen
import de.tum.informatics.www1.artemis.native_app.feature.courseview.ui.course_overview.DEFAULT_CONVERSATION_ID
import de.tum.informatics.www1.artemis.native_app.feature.courseview.ui.course_overview.DEFAULT_POST_ID
import de.tum.informatics.www1.artemis.native_app.feature.courseview.ui.course_overview.DEFAULT_USERNAME
import de.tum.informatics.www1.artemis.native_app.feature.courseview.ui.course_overview.DEFAULT_USER_ID
import org.koin.core.context.startKoin
import org.koin.dsl.module

Expand Down Expand Up @@ -54,8 +56,9 @@ fun `Course View - Exercise List`() {
CourseUiScreen(
modifier = Modifier.fillMaxSize(),
viewModel = courseViewModel,
username = "",
courseId = 0L,
username = DEFAULT_USERNAME,
userId = DEFAULT_USER_ID,
conversationId = DEFAULT_CONVERSATION_ID,
postId = DEFAULT_POST_ID,
onNavigateToExercise = {},
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,8 @@ import androidx.compose.runtime.Composable
import androidx.compose.runtime.CompositionLocalProvider
import androidx.compose.ui.Modifier
import androidx.compose.ui.text.input.TextFieldValue
import de.tum.informatics.www1.artemis.native_app.core.data.AccountDataServiceStub
import de.tum.informatics.www1.artemis.native_app.core.data.DataState
import de.tum.informatics.www1.artemis.native_app.core.data.test.AccountDataServiceStub
import de.tum.informatics.www1.artemis.native_app.core.datastore.AccountServiceStub
import de.tum.informatics.www1.artemis.native_app.core.datastore.ServerConfigurationServiceStub
import de.tum.informatics.www1.artemis.native_app.core.device.NetworkStatusProviderStub
Expand Down Expand Up @@ -190,11 +190,9 @@ fun `Metis - Conversation Channel`() {
).reversed()

val visibleMetisContextManagerStub = object : VisibleMetisContextManager {
override fun registerMetisContext(metisContext: VisibleMetisContext) =
Unit

override fun unregisterMetisContext(metisContext: VisibleMetisContext) =
Unit
override fun registerMetisContext(metisContext: VisibleMetisContext) = Unit
override fun unregisterMetisContext(metisContext: VisibleMetisContext) = Unit
override fun getRegisteredMetisContexts(): List<VisibleMetisContext> = emptyList()
}

// TODO: Provide artemis image provider
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -45,11 +45,16 @@ import de.tum.informatics.www1.artemis.native_app.feature.courseview.R
import de.tum.informatics.www1.artemis.native_app.feature.courseview.ui.CourseViewModel
import de.tum.informatics.www1.artemis.native_app.feature.courseview.ui.LectureListUi
import de.tum.informatics.www1.artemis.native_app.feature.courseview.ui.exercise_list.ExerciseListUi
import de.tum.informatics.www1.artemis.native_app.feature.metis.IgnoreCustomBackHandling
import de.tum.informatics.www1.artemis.native_app.feature.metis.NavigateToUserConversation
import de.tum.informatics.www1.artemis.native_app.feature.metis.NothingOpened
import de.tum.informatics.www1.artemis.native_app.feature.metis.OpenedConversation
import de.tum.informatics.www1.artemis.native_app.feature.metis.OpenedThread
import de.tum.informatics.www1.artemis.native_app.feature.metis.shared.content.MetisContext
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.UserIdentifier
import de.tum.informatics.www1.artemis.native_app.feature.metis.shared.visiblemetiscontextreporter.ReportVisibleMetisContext
import de.tum.informatics.www1.artemis.native_app.feature.metis.shared.visiblemetiscontextreporter.VisibleCourse
import de.tum.informatics.www1.artemis.native_app.feature.metis.ui.ConversationFacadeUi
import kotlinx.serialization.Serializable
import org.koin.androidx.compose.koinViewModel
Expand All @@ -61,13 +66,16 @@ internal const val TAB_COMMUNICATION = 2

internal const val DEFAULT_CONVERSATION_ID = -1L
internal const val DEFAULT_POST_ID = -1L
internal const val DEFAULT_USERNAME = ""
internal const val DEFAULT_USER_ID = -1L

@Serializable
private data class CourseUiScreen(
val courseId: Long,
val conversationId: Long = DEFAULT_CONVERSATION_ID,
val postId: Long = DEFAULT_POST_ID,
val username: String = ""
val username: String = DEFAULT_USERNAME,
val userId: Long = DEFAULT_USER_ID
)

fun NavController.navigateToCourse(courseId: Long, builder: NavOptionsBuilder.() -> Unit) {
Expand All @@ -91,7 +99,8 @@ fun NavGraphBuilder.course(
generateLinks("courses/{courseId}") +
generateLinks("courses/{courseId}/exercises") +
generateLinks("courses/{courseId}/messages?conversationId={conversationId}") +
generateLinks("courses/{courseId}/messages?username={username}")
generateLinks("courses/{courseId}/messages?username={username}") +
generateLinks("courses/{courseId}/messages?userId={userId}")
animatedComposable<CourseUiScreen>(
deepLinks = deepLinks
) { backStackEntry ->
Expand All @@ -101,6 +110,7 @@ fun NavGraphBuilder.course(
val conversationId = route.conversationId
val postId = route.postId
val username = route.username
val userId = route.userId

CourseUiScreen(
modifier = Modifier.fillMaxSize(),
Expand All @@ -109,6 +119,7 @@ fun NavGraphBuilder.course(
conversationId = conversationId,
postId = postId,
username = username,
userId = userId,
onNavigateToExercise = onNavigateToExercise,
onNavigateToTextExerciseParticipation = onNavigateToTextExerciseParticipation,
onNavigateToExerciseResultView = onNavigateToExerciseResultView,
Expand All @@ -134,6 +145,7 @@ fun CourseUiScreen(
conversationId: Long,
postId: Long,
username: String,
userId: Long,
onNavigateToExercise: (exerciseId: Long) -> Unit,
onNavigateToTextExerciseParticipation: (exerciseId: Long, participationId: Long) -> Unit,
onNavigateToExerciseResultView: (exerciseId: Long) -> Unit,
Expand All @@ -151,6 +163,7 @@ fun CourseUiScreen(
conversationId = conversationId,
courseDataState = courseDataState,
username = username,
userId = userId,
onNavigateBack = onNavigateBack,
weeklyExercisesDataState = weeklyExercisesDataState,
onNavigateToExercise = onNavigateToExercise,
Expand Down Expand Up @@ -181,6 +194,7 @@ internal fun CourseUiScreen(
conversationId: Long,
postId: Long,
username: String,
userId: Long,
courseDataState: DataState<Course>,
weeklyExercisesDataState: DataState<List<GroupedByWeek<Exercise>>>,
weeklyLecturesDataState: DataState<List<GroupedByWeek<Lecture>>>,
Expand All @@ -196,13 +210,17 @@ internal fun CourseUiScreen(
) {
var selectedTabIndex by rememberSaveable(conversationId) {
val initialTab = when {
conversationId != DEFAULT_CONVERSATION_ID || username.isNotBlank() -> TAB_COMMUNICATION
conversationId != DEFAULT_CONVERSATION_ID -> TAB_COMMUNICATION
username != DEFAULT_USERNAME -> TAB_COMMUNICATION
userId != DEFAULT_USER_ID -> TAB_COMMUNICATION
else -> TAB_EXERCISES
}

mutableIntStateOf(initialTab)
}

ReportVisibleMetisContext(VisibleCourse(MetisContext.Course(courseId)))

CourseUiScreen(
modifier = modifier,
courseDataState = courseDataState,
Expand Down Expand Up @@ -255,19 +273,28 @@ internal fun CourseUiScreen(
val initialConfiguration = remember(conversationId, postId) {
when {
conversationId != DEFAULT_CONVERSATION_ID && postId != DEFAULT_POST_ID -> OpenedConversation(
conversationId,
OpenedThread(
conversationId,
_prevConfiguration = IgnoreCustomBackHandling,
conversationId = conversationId,
openedThread = OpenedThread(
StandalonePostId.ServerSideId(postId)
)
)

conversationId != DEFAULT_CONVERSATION_ID -> OpenedConversation(
conversationId,
null
_prevConfiguration = IgnoreCustomBackHandling,
conversationId = conversationId,
openedThread = null
)

username != DEFAULT_USERNAME -> NavigateToUserConversation(
_prevConfiguration = IgnoreCustomBackHandling,
userIdentifier = UserIdentifier.Username(username)
)

username.isNotBlank() -> NavigateToUserConversation(username)
userId != DEFAULT_USER_ID -> NavigateToUserConversation(
_prevConfiguration = IgnoreCustomBackHandling,
userIdentifier = UserIdentifier.UserId(userId)
)

else -> NothingOpened
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package de.tum.informatics.www1.artemis.native_app.feature.courseview

import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.runtime.CompositionLocalProvider
import androidx.compose.ui.Modifier
import androidx.test.platform.app.InstrumentationRegistry
import de.tum.informatics.www1.artemis.native_app.core.model.Course
Expand All @@ -12,10 +13,14 @@ import de.tum.informatics.www1.artemis.native_app.feature.courseview.ui.CourseVi
import de.tum.informatics.www1.artemis.native_app.feature.courseview.ui.course_overview.CourseUiScreen
import de.tum.informatics.www1.artemis.native_app.feature.courseview.ui.course_overview.DEFAULT_CONVERSATION_ID
import de.tum.informatics.www1.artemis.native_app.feature.courseview.ui.course_overview.DEFAULT_POST_ID
import de.tum.informatics.www1.artemis.native_app.feature.courseview.ui.course_overview.DEFAULT_USERNAME
import de.tum.informatics.www1.artemis.native_app.feature.courseview.ui.course_overview.DEFAULT_USER_ID
import de.tum.informatics.www1.artemis.native_app.feature.login.loginModule
import de.tum.informatics.www1.artemis.native_app.feature.login.test.getAdminAccessToken
import de.tum.informatics.www1.artemis.native_app.feature.login.test.performTestLogin
import de.tum.informatics.www1.artemis.native_app.feature.login.test.testLoginModule
import de.tum.informatics.www1.artemis.native_app.feature.metis.shared.visiblemetiscontextreporter.LocalVisibleMetisContextManager
import de.tum.informatics.www1.artemis.native_app.feature.metistest.VisibleMetisContextManagerMock
import org.junit.Before
import org.junit.Rule
import org.koin.android.ext.koin.androidContext
Expand Down Expand Up @@ -55,21 +60,26 @@ abstract class BaseCourseTest : BaseComposeTest() {
)

composeTestRule.setContent {
CourseUiScreen(
modifier = Modifier.fillMaxSize(),
viewModel = viewModel,
courseId = course.id!!,
conversationId = DEFAULT_CONVERSATION_ID,
postId = DEFAULT_POST_ID,
username = "",
onNavigateToExercise = {},
onNavigateToExerciseResultView = {},
onNavigateToTextExerciseParticipation = { _, _ -> },
onParticipateInQuiz = { _, _ -> },
onClickViewQuizResults = { _, _ -> },
onNavigateToLecture = {},
onNavigateBack = {}
)
CompositionLocalProvider(
LocalVisibleMetisContextManager provides VisibleMetisContextManagerMock
) {
CourseUiScreen(
modifier = Modifier.fillMaxSize(),
viewModel = viewModel,
courseId = course.id!!,
conversationId = DEFAULT_CONVERSATION_ID,
postId = DEFAULT_POST_ID,
username = DEFAULT_USERNAME,
userId = DEFAULT_USER_ID,
onNavigateToExercise = {},
onNavigateToExerciseResultView = {},
onNavigateToTextExerciseParticipation = { _, _ -> },
onParticipateInQuiz = { _, _ -> },
onClickViewQuizResults = { _, _ -> },
onNavigateToLecture = {},
onNavigateBack = {}
)
}
}

return viewModel
Expand Down
Original file line number Diff line number Diff line change
@@ -1,10 +1,18 @@
package de.tum.informatics.www1.artemis.native_app.feature.metis.conversation
package de.tum.informatics.www1.artemis.native_app.feature.metistest

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

object EmptyVisibleMetisContextManager : VisibleMetisContextManager {
override fun registerMetisContext(metisContext: VisibleMetisContext) = Unit
object VisibleMetisContextManagerMock : VisibleMetisContextManager {
private val registeredMetisContexts = mutableListOf<VisibleMetisContext>()

override fun unregisterMetisContext(metisContext: VisibleMetisContext) = Unit
override fun registerMetisContext(metisContext: VisibleMetisContext) {
registeredMetisContexts.add(metisContext)
}

override fun unregisterMetisContext(metisContext: VisibleMetisContext) {
registeredMetisContexts.remove(metisContext)
}

override fun getRegisteredMetisContexts(): List<VisibleMetisContext> = registeredMetisContexts
}
Original file line number Diff line number Diff line change
Expand Up @@ -141,15 +141,6 @@ fun MetisChatList(
title: String,
onFileSelected: (Uri) -> Unit
) {
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
Loading

0 comments on commit 271b6ea

Please sign in to comment.