From 7a458dab7afc1e4b215588666027206e2f7cf34b Mon Sep 17 00:00:00 2001
From: Martin Felber <45291671+FelberMartin@users.noreply.github.com>
Date: Tue, 19 Nov 2024 13:10:24 +0100
Subject: [PATCH 01/22] Add PR template (#116)
---
.github/pull_request_template.md | 13 +++++++++++++
1 file changed, 13 insertions(+)
create mode 100644 .github/pull_request_template.md
diff --git a/.github/pull_request_template.md b/.github/pull_request_template.md
new file mode 100644
index 000000000..e06b7b0f9
--- /dev/null
+++ b/.github/pull_request_template.md
@@ -0,0 +1,13 @@
+
+
+### Problem Description
+
+
+### Changes
+
+
+
+### Steps for testing
+
+
+### Screenshots
From 1e24253ede18ea0a32a3022f57da541578a4136c Mon Sep 17 00:00:00 2001
From: Martin Felber <45291671+FelberMartin@users.noreply.github.com>
Date: Tue, 19 Nov 2024 15:30:18 +0100
Subject: [PATCH 02/22] Update issue templates
---
.github/ISSUE_TEMPLATE/bug_report.md | 6 +++---
1 file changed, 3 insertions(+), 3 deletions(-)
diff --git a/.github/ISSUE_TEMPLATE/bug_report.md b/.github/ISSUE_TEMPLATE/bug_report.md
index 60cb29409..e52a0b2c2 100644
--- a/.github/ISSUE_TEMPLATE/bug_report.md
+++ b/.github/ISSUE_TEMPLATE/bug_report.md
@@ -7,7 +7,7 @@ assignees: ''
---
-**Describe the bug**
+### Describe the bug
A clear and concise description of what the bug is.
**To Reproduce**
@@ -20,8 +20,8 @@ Steps to reproduce the behavior:
**Expected behavior**
A clear and concise description of what you expected to happen.
-**Screenshots**
+### Screenshots
If applicable, add screenshots to help explain your problem.
-**Additional context**
+### Additional context
Add any other context about the problem here.
From ea12b02b93de446998ff843384044bd8d06c792d Mon Sep 17 00:00:00 2001
From: Martin Felber <45291671+FelberMartin@users.noreply.github.com>
Date: Tue, 19 Nov 2024 22:16:56 +0100
Subject: [PATCH 03/22] `Chore`: Display server url in settings (#122)
---
.../artemis/native_app/feature/settings/SettingsScreen.kt | 8 ++++++++
feature/settings/src/main/res/values/settings_strings.xml | 1 +
2 files changed, 9 insertions(+)
diff --git a/feature/settings/src/main/kotlin/de/tum/informatics/www1/artemis/native_app/feature/settings/SettingsScreen.kt b/feature/settings/src/main/kotlin/de/tum/informatics/www1/artemis/native_app/feature/settings/SettingsScreen.kt
index e17afc751..dfba46ced 100644
--- a/feature/settings/src/main/kotlin/de/tum/informatics/www1/artemis/native_app/feature/settings/SettingsScreen.kt
+++ b/feature/settings/src/main/kotlin/de/tum/informatics/www1/artemis/native_app/feature/settings/SettingsScreen.kt
@@ -207,6 +207,7 @@ private fun SettingsScreen(
AboutSection(
modifier = Modifier.fillMaxWidth(),
hasUserSelectedInstance = hasUserSelectedInstance,
+ serverUrl = serverUrl,
onOpenPrivacyPolicy = {
val link = URLBuilder(serverUrl).appendPathSegments("privacy").buildString()
@@ -334,6 +335,7 @@ private fun NotificationSection(modifier: Modifier, onOpenNotificationSettings:
private fun AboutSection(
modifier: Modifier,
hasUserSelectedInstance: Boolean,
+ serverUrl: String,
onRequestSelectServerInstance: () -> Unit,
onOpenPrivacyPolicy: () -> Unit,
onOpenImprint: () -> Unit,
@@ -352,6 +354,12 @@ private fun AboutSection(
}
if (hasUserSelectedInstance) {
+ PreferenceEntry(
+ modifier = Modifier.fillMaxWidth(),
+ text = stringResource(R.string.settings_server_url, serverUrl),
+ onClick = {}
+ )
+
PreferenceEntry(
modifier = Modifier.fillMaxWidth(),
text = stringResource(id = R.string.settings_about_privacy_policy),
diff --git a/feature/settings/src/main/res/values/settings_strings.xml b/feature/settings/src/main/res/values/settings_strings.xml
index 3954c4b7c..ec4a71b13 100644
--- a/feature/settings/src/main/res/values/settings_strings.xml
+++ b/feature/settings/src/main/res/values/settings_strings.xml
@@ -12,6 +12,7 @@
About
Imprint and privacy policy depend on the server you have currently selected.
+ Server URL: %1$s
Imprint and privacy policy are unavailable as you have not yet selected a server instance. Please select a server instance to view their privacy policy and imprint.
Select instance
Privacy policy
From 5e0e7763a7f44f79aa78a8597274ffd6433ff630 Mon Sep 17 00:00:00 2001
From: Martin Felber <45291671+FelberMartin@users.noreply.github.com>
Date: Wed, 20 Nov 2024 14:29:39 +0100
Subject: [PATCH 04/22] Fix answer post got duplicated (#96)
---
feature/metis/conversation/build.gradle.kts | 8 +-
.../storage/impl/MetisStorageServiceImpl.kt | 16 +-
...geServiceImplTestUpgradeLocalAnswerPost.kt | 207 ++++++++++++++++++
.../feature/metis/shared/db/MetisDao.kt | 2 +-
gradle/libs.versions.toml | 2 +
5 files changed, 228 insertions(+), 7 deletions(-)
create mode 100644 feature/metis/conversation/src/test/kotlin/de/tum/informatics/www1/artemis/native_app/feature/metis/conversation/service/storage/impl/MetisStorageServiceImplTestUpgradeLocalAnswerPost.kt
diff --git a/feature/metis/conversation/build.gradle.kts b/feature/metis/conversation/build.gradle.kts
index 498c87285..c83ed2e88 100644
--- a/feature/metis/conversation/build.gradle.kts
+++ b/feature/metis/conversation/build.gradle.kts
@@ -20,6 +20,7 @@ dependencies {
implementation(project(":core:device"))
implementation(project(":feature:metis:shared"))
+ testImplementation(project(":feature:metis-test"))
implementation(libs.androidx.paging.runtime)
implementation(libs.androidx.paging.compose)
@@ -33,10 +34,9 @@ dependencies {
implementation(libs.androidx.work.runtime.ktx)
implementation(libs.androidx.dataStore.preferences)
-
- testImplementation(project(":feature:metis-test"))
- implementation("androidx.paging:paging-common:3.2.1")
-
+ implementation(libs.androidx.paging.common)
+
+ testImplementation(libs.androidx.paging.testing)
testImplementation(libs.mockk.android)
testImplementation(libs.mockk.agent)
}
diff --git a/feature/metis/conversation/src/main/kotlin/de/tum/informatics/www1/artemis/native_app/feature/metis/conversation/service/storage/impl/MetisStorageServiceImpl.kt b/feature/metis/conversation/src/main/kotlin/de/tum/informatics/www1/artemis/native_app/feature/metis/conversation/service/storage/impl/MetisStorageServiceImpl.kt
index da80b42be..d9bca3b4a 100644
--- a/feature/metis/conversation/src/main/kotlin/de/tum/informatics/www1/artemis/native_app/feature/metis/conversation/service/storage/impl/MetisStorageServiceImpl.kt
+++ b/feature/metis/conversation/src/main/kotlin/de/tum/informatics/www1/artemis/native_app/feature/metis/conversation/service/storage/impl/MetisStorageServiceImpl.kt
@@ -2,9 +2,9 @@ package de.tum.informatics.www1.artemis.native_app.feature.metis.conversation.se
import androidx.paging.PagingSource
import androidx.room.withTransaction
-import de.tum.informatics.www1.artemis.native_app.feature.metis.shared.content.MetisContext
import de.tum.informatics.www1.artemis.native_app.feature.metis.conversation.service.storage.MetisStorageService
import de.tum.informatics.www1.artemis.native_app.feature.metis.shared.MetisDatabaseProvider
+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.dto.AnswerPost
import de.tum.informatics.www1.artemis.native_app.feature.metis.shared.content.dto.BasePost
import de.tum.informatics.www1.artemis.native_app.feature.metis.shared.content.dto.CourseWideContext
@@ -336,6 +336,19 @@ internal class MetisStorageServiceImpl(
val metisDao = databaseProvider.metisDao
databaseProvider.database.withTransaction {
+ val doesPostAnswerAlreadyExist = metisDao.isPostPresentInContext(
+ serverId = host,
+ serverPostId = post.id ?: return@withTransaction,
+ courseId = metisContext.courseId,
+ conversationId = metisContext.conversationId
+ )
+
+ // In rare cases, the websocket connection already inserted the post answer. In that case, we can delete the client side post.
+ if (doesPostAnswerAlreadyExist) {
+ metisDao.deletePostingWithClientSideId(clientPostId = clientSidePostId)
+ return@withTransaction
+ }
+
metisDao.upgradePost(
clientSidePostId = clientSidePostId,
serverSidePostId = post.id ?: return@withTransaction
@@ -502,7 +515,6 @@ internal class MetisStorageServiceImpl(
answerServerIds = sp.answers.orEmpty().mapNotNull { it.id }
)
}
-
for (ap in sp.answers.orEmpty()) {
val answerPostId = ap.id ?: continue
diff --git a/feature/metis/conversation/src/test/kotlin/de/tum/informatics/www1/artemis/native_app/feature/metis/conversation/service/storage/impl/MetisStorageServiceImplTestUpgradeLocalAnswerPost.kt b/feature/metis/conversation/src/test/kotlin/de/tum/informatics/www1/artemis/native_app/feature/metis/conversation/service/storage/impl/MetisStorageServiceImplTestUpgradeLocalAnswerPost.kt
new file mode 100644
index 000000000..cbe8a8b9a
--- /dev/null
+++ b/feature/metis/conversation/src/test/kotlin/de/tum/informatics/www1/artemis/native_app/feature/metis/conversation/service/storage/impl/MetisStorageServiceImplTestUpgradeLocalAnswerPost.kt
@@ -0,0 +1,207 @@
+package de.tum.informatics.www1.artemis.native_app.feature.metis.conversation.service.storage.impl
+
+import androidx.paging.Pager
+import androidx.paging.PagingConfig
+import androidx.paging.PagingSource
+import androidx.paging.testing.asSnapshot
+import androidx.test.platform.app.InstrumentationRegistry
+import de.tum.informatics.www1.artemis.native_app.core.common.test.UnitTest
+import de.tum.informatics.www1.artemis.native_app.core.model.account.User
+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.dto.AnswerPost
+import de.tum.informatics.www1.artemis.native_app.feature.metis.shared.content.dto.StandalonePost
+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.content.dto.conversation.OneToOneChat
+import de.tum.informatics.www1.artemis.native_app.feature.metis.shared.db.pojo.AnswerPostPojo
+import de.tum.informatics.www1.artemis.native_app.feature.metis.shared.db.pojo.PostPojo
+import de.tum.informatics.www1.artemis.native_app.feature.metistest.MetisDatabaseProviderMock
+import kotlinx.coroutines.test.runTest
+import kotlinx.datetime.Clock
+import org.junit.Assert.assertEquals
+import org.junit.Test
+import org.junit.experimental.categories.Category
+import org.junit.runner.RunWith
+import org.robolectric.RobolectricTestRunner
+
+@Category(UnitTest::class)
+@RunWith(RobolectricTestRunner::class)
+class MetisStorageServiceImplUpgradeLocalAnswerPostTest {
+
+ private val databaseProviderMock = MetisDatabaseProviderMock(InstrumentationRegistry.getInstrumentation().context)
+ private val sut = MetisStorageServiceImpl(databaseProviderMock)
+
+ private val host = "host"
+
+ private val author = User(id = 20, name = "AuthorName")
+ private val parentClientPostId = "parent-client-id-0"
+ private val answerClientPostId = "answer-client-id-0"
+
+ private val course: MetisContext.Course = MetisContext.Course(courseId = 1)
+ private val conversation = OneToOneChat(id = 2)
+ private val metisContext = MetisContext.Conversation(course.courseId, conversation.id)
+
+ private val localAnswerPojo = AnswerPostPojo(
+ parentPostId = parentClientPostId,
+ postId = answerClientPostId,
+ resolvesPost = false,
+ basePostingCache = AnswerPostPojo.BasePostingCache(
+ serverPostId = 0,
+ authorId = author.id,
+ creationDate = Clock.System.now(),
+ updatedDate = null,
+ content = "Answer post content 0",
+ authorRole = UserRole.USER,
+ authorName = author.name!!
+ ),
+ reactions = emptyList(),
+ serverPostIdCache = AnswerPostPojo.ServerPostIdCache(
+ serverPostId = null // Only local answer post, no server id
+ )
+ )
+
+ private val basePostPojo = PostPojo(
+ clientPostId = parentClientPostId,
+ serverPostId = 0,
+ content = "Base post content",
+ resolved = false,
+ updatedDate = null,
+ creationDate = Clock.System.now(),
+ authorId = author.id,
+ title = null,
+ authorName = author.name!!,
+ authorRole = UserRole.USER,
+ courseWideContext = null,
+ tags = emptyList(),
+ answers = emptyList(),
+ reactions = emptyList()
+ )
+
+ private val basePost = StandalonePost(basePostPojo, conversation)
+ private val localAnswer = AnswerPost(localAnswerPojo, basePost)
+
+ private lateinit var basePostUpdated: StandalonePost
+ private lateinit var answerUpdated: AnswerPost
+
+ @Test
+ fun testInsertClientSidePost() = runTest {
+ // GIVEN: A base post
+ sut.insertOrUpdatePosts(
+ host = host,
+ metisContext = metisContext,
+ posts = listOf(basePost),
+ )
+
+ // WHEN: Inserting a client side answer post
+ sut.insertClientSidePost(
+ host = host,
+ metisContext = metisContext,
+ post = localAnswer,
+ clientSidePostId = answerClientPostId
+ )
+
+ // THEN: Both the base post and the answer post are stored
+ assertStoredContentIsTheSame()
+ }
+
+ @Test
+ fun testUpgradeClientSideAnswerPost() = runTest {
+ // GIVEN: A post with a new only local answer post
+ setupPostWithLocalAnswer()
+
+ // WHEN: insertOrUpdatePosts is called before upgradeClientSideAnswerPost.
+ updateAnswerPostWithServerId()
+
+ // Called by the WebSocket
+ sut.updatePost(
+ host = host,
+ metisContext = metisContext,
+ post = basePostUpdated
+ )
+
+ // Called by SendConversationPostWorker
+ sut.upgradeClientSideAnswerPost(
+ host = host,
+ metisContext = metisContext,
+ clientSidePostId = answerClientPostId,
+ post = answerUpdated
+ )
+
+ // THEN: Content stays the same and the upgrade is successful
+ assertStoredContentIsTheSame()
+ assertUpgradeSuccessful()
+ }
+
+ @Test
+ fun testUpgradeClientSideAnswerPost2() = runTest {
+ // GIVEN: A post with a new only local answer post
+ setupPostWithLocalAnswer()
+
+ // WHEN: upgradeClientSideAnswerPost is called before updatePost.
+ updateAnswerPostWithServerId()
+
+ // Called by SendConversationPostWorker
+ sut.upgradeClientSideAnswerPost(
+ host = host,
+ metisContext = metisContext,
+ clientSidePostId = answerClientPostId,
+ post = answerUpdated
+ )
+
+ // Called by the WebSocket
+ sut.updatePost(
+ host = host,
+ metisContext = metisContext,
+ post = basePostUpdated
+ )
+
+ // THEN: Content stays the same and the upgrade is successful
+ assertStoredContentIsTheSame()
+ assertUpgradeSuccessful()
+ }
+
+ private suspend fun setupPostWithLocalAnswer() {
+ sut.insertOrUpdatePosts(
+ host = host,
+ metisContext = metisContext,
+ posts = listOf(basePost)
+ )
+ sut.insertClientSidePost(
+ host = host,
+ metisContext = metisContext,
+ clientSidePostId = answerClientPostId,
+ post = localAnswer
+ )
+ }
+
+
+ private fun updateAnswerPostWithServerId() {
+ val answerPojoUpdated = localAnswerPojo.copy(serverPostIdCache = localAnswerPojo.serverPostIdCache.copy(serverPostId = 1))
+ basePostUpdated = StandalonePost(basePostPojo, conversation)
+ answerUpdated = AnswerPost(answerPojoUpdated, basePostUpdated)
+ basePostUpdated = basePostUpdated.copy(answers = listOf(answerUpdated))
+ }
+
+ private suspend fun assertStoredContentIsTheSame() {
+ val posts = getStoredPosts()
+ assertEquals(1, posts.size)
+ assertEquals(basePostPojo.content, posts.first().content)
+ assertEquals(1, posts.first().answers.size)
+ assertEquals(localAnswerPojo.content, posts.first().answers.first().content)
+ }
+
+ private suspend fun assertUpgradeSuccessful() {
+ val posts = getStoredPosts()
+ assertEquals(answerUpdated.serverPostId, posts.first().answers.first().serverPostId)
+ }
+
+ private suspend fun getStoredPosts() = sut.getStoredPosts(
+ serverId = host,
+ metisContext = metisContext
+ ).loadAsList()
+
+ private suspend fun PagingSource.loadAsList(): List {
+ return Pager(PagingConfig(pageSize = 10), pagingSourceFactory = { this }).flow.asSnapshot {
+ scrollTo(50)
+ }
+ }
+}
\ No newline at end of file
diff --git a/feature/metis/shared/src/main/kotlin/de/tum/informatics/www1/artemis/native_app/feature/metis/shared/db/MetisDao.kt b/feature/metis/shared/src/main/kotlin/de/tum/informatics/www1/artemis/native_app/feature/metis/shared/db/MetisDao.kt
index 73207808a..c82654043 100644
--- a/feature/metis/shared/src/main/kotlin/de/tum/informatics/www1/artemis/native_app/feature/metis/shared/db/MetisDao.kt
+++ b/feature/metis/shared/src/main/kotlin/de/tum/informatics/www1/artemis/native_app/feature/metis/shared/db/MetisDao.kt
@@ -140,7 +140,7 @@ interface MetisDao {
postingType: BasePostingEntity.PostingType = BasePostingEntity.PostingType.STANDALONE
)
- @Query("delete from metis_post_context where client_post_id = :clientPostId")
+ @Query("delete from postings where id = :clientPostId")
suspend fun deletePostingWithClientSideId(
clientPostId: String
)
diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml
index 1b8007277..7b14ab928 100644
--- a/gradle/libs.versions.toml
+++ b/gradle/libs.versions.toml
@@ -72,6 +72,8 @@ androidx-lifecycle-viewModelCompose = { group = "androidx.lifecycle", name = "li
androidx-navigation-compose = { group = "androidx.navigation", name = "navigation-compose", version.ref = "androidxNavigation" }
androidx-paging-runtime = { group = "androidx.paging", name = "paging-runtime", version.ref = "androidxPaging" }
androidx-paging-compose = { group = "androidx.paging", name = "paging-compose", version.ref = "androidxPagingCompose" }
+androidx-paging-common = { group = "androidx.paging", name = "paging-common", version.ref = "androidxPaging" }
+androidx-paging-testing = { group = "androidx.paging", name = "paging-testing", version.ref = "androidxPaging" }
androidx-room-runtime = { group = "androidx.room", name = "room-runtime", version.ref = "room" }
androidx-room-compiler = { group = "androidx.room", name = "room-compiler", version.ref = "room" }
androidx-room-paging = { group = "androidx.room", name = "room-paging", version.ref = "room" }
From d8cb940c1713d0ca6f61f0a5bdd43dd8cb13da2e Mon Sep 17 00:00:00 2001
From: Julian Waluschyk <37155504+julian-wls@users.noreply.github.com>
Date: Wed, 20 Nov 2024 15:08:34 +0100
Subject: [PATCH 05/22] Display content edge-to-edge (#91)
Co-authored-by: Martin Felber <45291671+FelberMartin@users.noreply.github.com>
---
.../native_app/android/ui/MainActivity.kt | 1 +
.../core/ui/common/course/CourseListUi.kt | 14 ++-
.../courseregistration/RegisterForCourseUi.kt | 8 +-
.../feature/courseview/ui/WeeklyItemsUi.kt | 12 +-
.../ui/course_overview/CourseUiScreen.kt | 6 +-
.../feature/dashboard/CoursesOverview.kt | 8 +-
.../feature/lectureview/AttachmentsTab.kt | 11 +-
.../feature/lectureview/LectureScreenUi.kt | 2 +-
.../feature/lectureview/OverviewTab.kt | 10 +-
.../native_app/feature/login/AccountUi.kt | 15 ++-
.../feature/login/NotificationSettingsUi.kt | 6 +-
.../InstanceSelectionScreen.kt | 8 +-
.../native_app/feature/login/login/LoginUi.kt | 1 +
.../feature/login/register/RegisterUi.kt | 3 +-
.../feature/login/RegisterEndToEndTest.kt | 2 +
.../codeofconduct/ui/AcceptCodeOfConductUi.kt | 9 +-
.../ui/ConversationChatListScreen.kt | 12 +-
.../ui/ConversationThreadScreen.kt | 6 +-
.../conversation/ui/chatlist/MetisChatList.kt | 4 +-
.../ui/post/PostContextBottomSheet.kt | 3 +
.../conversation/ui/thread/MetisThreadUi.kt | 7 +-
.../metis/conversation/BaseThreadUITest.kt | 97 +++++++++++++++
.../ConversationAnswerMessagesUITest.kt | 115 ++----------------
.../reply/ReplyTextFieldVisibilityUITest.kt | 85 +++++++++++++
.../browse_channels/BrowseChannelsScreen.kt | 6 +-
.../create_channel/CreateChannelScreen.kt | 2 +
.../CreatePersonalConversationScreen.kt | 2 +
.../overview/ConversationOverviewBody.kt | 17 ++-
.../members/ConversationMembersScreen.kt | 5 +-
.../overview/ConversationSettingsBody.kt | 6 +-
.../overview/ConversationSettingsScreen.kt | 8 +-
.../PushNotificationSettingsScreen.kt | 8 +-
.../feature/settings/SettingsScreen.kt | 8 +-
33 files changed, 372 insertions(+), 135 deletions(-)
create mode 100644 feature/metis/conversation/src/test/kotlin/de/tum/informatics/www1/artemis/native_app/feature/metis/conversation/BaseThreadUITest.kt
create mode 100644 feature/metis/conversation/src/test/kotlin/de/tum/informatics/www1/artemis/native_app/feature/metis/conversation/ui/reply/ReplyTextFieldVisibilityUITest.kt
diff --git a/app/src/main/java/de/tum/informatics/www1/artemis/native_app/android/ui/MainActivity.kt b/app/src/main/java/de/tum/informatics/www1/artemis/native_app/android/ui/MainActivity.kt
index ce578fb53..e7903bcba 100644
--- a/app/src/main/java/de/tum/informatics/www1/artemis/native_app/android/ui/MainActivity.kt
+++ b/app/src/main/java/de/tum/informatics/www1/artemis/native_app/android/ui/MainActivity.kt
@@ -91,6 +91,7 @@ class MainActivity : AppCompatActivity(),
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
+ enableEdgeToEdge()
// When the user is logged in, immediately display the course overview.
val startDestination = runBlocking {
diff --git a/core/ui/src/main/kotlin/de/tum/informatics/www1/artemis/native_app/core/ui/common/course/CourseListUi.kt b/core/ui/src/main/kotlin/de/tum/informatics/www1/artemis/native_app/core/ui/common/course/CourseListUi.kt
index 661e46bde..bef41c94c 100644
--- a/core/ui/src/main/kotlin/de/tum/informatics/www1/artemis/native_app/core/ui/common/course/CourseListUi.kt
+++ b/core/ui/src/main/kotlin/de/tum/informatics/www1/artemis/native_app/core/ui/common/course/CourseListUi.kt
@@ -9,12 +9,22 @@ import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.ColumnScope
import androidx.compose.foundation.layout.PaddingValues
import androidx.compose.foundation.layout.Row
+import androidx.compose.foundation.layout.WindowInsets
+import androidx.compose.foundation.layout.WindowInsetsSides
+import androidx.compose.foundation.layout.asPaddingValues
import androidx.compose.foundation.layout.aspectRatio
+import androidx.compose.foundation.layout.consumeWindowInsets
import androidx.compose.foundation.layout.fillMaxHeight
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.height
+import androidx.compose.foundation.layout.ime
+import androidx.compose.foundation.layout.navigationBars
+import androidx.compose.foundation.layout.only
import androidx.compose.foundation.layout.padding
+import androidx.compose.foundation.layout.safeContent
+import androidx.compose.foundation.layout.safeDrawing
import androidx.compose.foundation.layout.size
+import androidx.compose.foundation.layout.systemBars
import androidx.compose.foundation.lazy.grid.GridCells
import androidx.compose.foundation.lazy.grid.LazyGridItemScope
import androidx.compose.foundation.lazy.grid.LazyVerticalGrid
@@ -71,7 +81,9 @@ fun CourseItemGrid(
columns = GridCells.Fixed(columnCount),
verticalArrangement = Arrangement.spacedBy(8.dp),
horizontalArrangement = Arrangement.spacedBy(8.dp),
- contentPadding = PaddingValues(bottom = 90.dp)
+ contentPadding = PaddingValues(
+ bottom = WindowInsets.systemBars.asPaddingValues().calculateBottomPadding()
+ )
) {
items(courses, key = { it.course.id ?: 0L }) { course ->
courseItem(course, courseItemModifier, isCompact)
diff --git a/feature/course-registration/src/main/kotlin/de/tum/informatics/www1/artemis/native_app/feature/courseregistration/RegisterForCourseUi.kt b/feature/course-registration/src/main/kotlin/de/tum/informatics/www1/artemis/native_app/feature/courseregistration/RegisterForCourseUi.kt
index c3c8d6fa2..44d0a3a63 100644
--- a/feature/course-registration/src/main/kotlin/de/tum/informatics/www1/artemis/native_app/feature/courseregistration/RegisterForCourseUi.kt
+++ b/feature/course-registration/src/main/kotlin/de/tum/informatics/www1/artemis/native_app/feature/courseregistration/RegisterForCourseUi.kt
@@ -6,9 +6,13 @@ import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.ColumnScope
import androidx.compose.foundation.layout.Row
+import androidx.compose.foundation.layout.WindowInsets
+import androidx.compose.foundation.layout.asPaddingValues
+import androidx.compose.foundation.layout.consumeWindowInsets
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.padding
+import androidx.compose.foundation.layout.systemBars
import androidx.compose.foundation.lazy.grid.GridCells
import androidx.compose.foundation.lazy.grid.GridItemSpan
import androidx.compose.foundation.lazy.grid.LazyVerticalGrid
@@ -140,7 +144,8 @@ internal fun RegisterForCourseScreen(
RegisterForCourseContent(
modifier = Modifier
.fillMaxSize()
- .padding(padding)
+ .padding(top = padding.calculateTopPadding())
+ .consumeWindowInsets(WindowInsets.systemBars)
.padding(horizontal = 8.dp),
courses = courses,
serverUrl = properServerUrl,
@@ -235,6 +240,7 @@ private fun RegisterForCourseContent(
.fillMaxSize()
.testTag(TEST_TAG_REGISTRABLE_COURSE_LIST),
columns = GridCells.Fixed(columnCount),
+ contentPadding = WindowInsets.systemBars.asPaddingValues(),
verticalArrangement = Arrangement.spacedBy(8.dp),
horizontalArrangement = Arrangement.spacedBy(8.dp),
) {
diff --git a/feature/course-view/src/main/kotlin/de/tum/informatics/www1/artemis/native_app/feature/courseview/ui/WeeklyItemsUi.kt b/feature/course-view/src/main/kotlin/de/tum/informatics/www1/artemis/native_app/feature/courseview/ui/WeeklyItemsUi.kt
index 9f641b192..40f93d56b 100644
--- a/feature/course-view/src/main/kotlin/de/tum/informatics/www1/artemis/native_app/feature/courseview/ui/WeeklyItemsUi.kt
+++ b/feature/course-view/src/main/kotlin/de/tum/informatics/www1/artemis/native_app/feature/courseview/ui/WeeklyItemsUi.kt
@@ -3,9 +3,13 @@ package de.tum.informatics.www1.artemis.native_app.feature.courseview.ui
import android.os.Parcelable
import androidx.compose.foundation.clickable
import androidx.compose.foundation.layout.Arrangement
+import androidx.compose.foundation.layout.PaddingValues
import androidx.compose.foundation.layout.Row
+import androidx.compose.foundation.layout.WindowInsets
+import androidx.compose.foundation.layout.asPaddingValues
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.padding
+import androidx.compose.foundation.layout.systemBars
import androidx.compose.foundation.lazy.LazyColumn
import androidx.compose.foundation.lazy.items
import androidx.compose.material.icons.Icons
@@ -71,7 +75,13 @@ internal fun WeeklyItemsLazyColumn(
}
}
- LazyColumn(modifier = modifier, verticalArrangement = verticalArrangement) {
+ LazyColumn(
+ modifier = modifier,
+ verticalArrangement = verticalArrangement,
+ contentPadding = PaddingValues(
+ bottom = WindowInsets.systemBars.asPaddingValues().calculateBottomPadding()
+ )
+ ) {
weeklyItemGroups.forEachIndexed { index, weeklyItems ->
item {
WeeklyItemsSectionHeader(
diff --git a/feature/course-view/src/main/kotlin/de/tum/informatics/www1/artemis/native_app/feature/courseview/ui/course_overview/CourseUiScreen.kt b/feature/course-view/src/main/kotlin/de/tum/informatics/www1/artemis/native_app/feature/courseview/ui/course_overview/CourseUiScreen.kt
index c2eedf643..557480740 100644
--- a/feature/course-view/src/main/kotlin/de/tum/informatics/www1/artemis/native_app/feature/courseview/ui/course_overview/CourseUiScreen.kt
+++ b/feature/course-view/src/main/kotlin/de/tum/informatics/www1/artemis/native_app/feature/courseview/ui/course_overview/CourseUiScreen.kt
@@ -6,8 +6,11 @@ import androidx.compose.animation.slideInHorizontally
import androidx.compose.animation.slideOutHorizontally
import androidx.compose.animation.togetherWith
import androidx.compose.foundation.layout.Box
+import androidx.compose.foundation.layout.WindowInsets
+import androidx.compose.foundation.layout.consumeWindowInsets
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.padding
+import androidx.compose.foundation.layout.systemBars
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Scaffold
import androidx.compose.material3.Text
@@ -331,7 +334,8 @@ internal fun CourseUiScreen(
BasicDataStateUi(
modifier = Modifier
.fillMaxSize()
- .padding(padding),
+ .padding(top = padding.calculateTopPadding())
+ .consumeWindowInsets(WindowInsets.systemBars),
dataState = courseDataState,
loadingText = stringResource(id = R.string.course_ui_loading_course_loading),
failureText = stringResource(id = R.string.course_ui_loading_course_failed),
diff --git a/feature/dashboard/src/main/kotlin/de/tum/informatics/www1/artemis/native_app/feature/dashboard/CoursesOverview.kt b/feature/dashboard/src/main/kotlin/de/tum/informatics/www1/artemis/native_app/feature/dashboard/CoursesOverview.kt
index 1436d7c7b..dc93016f4 100644
--- a/feature/dashboard/src/main/kotlin/de/tum/informatics/www1/artemis/native_app/feature/dashboard/CoursesOverview.kt
+++ b/feature/dashboard/src/main/kotlin/de/tum/informatics/www1/artemis/native_app/feature/dashboard/CoursesOverview.kt
@@ -8,10 +8,15 @@ import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.BoxWithConstraints
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Row
+import androidx.compose.foundation.layout.WindowInsets
+import androidx.compose.foundation.layout.WindowInsetsSides
import androidx.compose.foundation.layout.aspectRatio
+import androidx.compose.foundation.layout.consumeWindowInsets
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.fillMaxWidth
+import androidx.compose.foundation.layout.only
import androidx.compose.foundation.layout.padding
+import androidx.compose.foundation.layout.systemBars
import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.filled.Add
@@ -188,7 +193,8 @@ internal fun CoursesOverview(
BasicDataStateUi(
modifier = Modifier
.fillMaxSize()
- .padding(padding),
+ .padding(top = padding.calculateTopPadding())
+ .consumeWindowInsets(WindowInsets.systemBars),
dataState = coursesDataState,
loadingText = stringResource(id = R.string.courses_loading_loading),
failureText = stringResource(id = R.string.courses_loading_failure),
diff --git a/feature/lecture-view/src/main/kotlin/de/tum/informatics/www1/artemis/native_app/feature/lectureview/AttachmentsTab.kt b/feature/lecture-view/src/main/kotlin/de/tum/informatics/www1/artemis/native_app/feature/lectureview/AttachmentsTab.kt
index 64ba8bc73..0e01ea757 100644
--- a/feature/lecture-view/src/main/kotlin/de/tum/informatics/www1/artemis/native_app/feature/lectureview/AttachmentsTab.kt
+++ b/feature/lecture-view/src/main/kotlin/de/tum/informatics/www1/artemis/native_app/feature/lectureview/AttachmentsTab.kt
@@ -2,9 +2,13 @@ package de.tum.informatics.www1.artemis.native_app.feature.lectureview
import androidx.compose.foundation.clickable
import androidx.compose.foundation.layout.Box
+import androidx.compose.foundation.layout.PaddingValues
+import androidx.compose.foundation.layout.WindowInsets
+import androidx.compose.foundation.layout.asPaddingValues
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.size
+import androidx.compose.foundation.layout.systemBars
import androidx.compose.foundation.lazy.LazyColumn
import androidx.compose.foundation.lazy.items
import androidx.compose.material.icons.Icons
@@ -31,7 +35,12 @@ internal fun AttachmentsTab(
onClickOpenLinkAttachment: (Attachment) -> Unit
) {
if (attachments.isNotEmpty()) {
- LazyColumn(modifier = modifier) {
+ LazyColumn(
+ modifier = modifier,
+ contentPadding = PaddingValues(
+ bottom = WindowInsets.systemBars.asPaddingValues().calculateBottomPadding()
+ )
+ ) {
items(attachments) { attachment ->
AttachmentItem(
modifier = Modifier.fillMaxWidth(),
diff --git a/feature/lecture-view/src/main/kotlin/de/tum/informatics/www1/artemis/native_app/feature/lectureview/LectureScreenUi.kt b/feature/lecture-view/src/main/kotlin/de/tum/informatics/www1/artemis/native_app/feature/lectureview/LectureScreenUi.kt
index 8a6787be9..3e693705e 100644
--- a/feature/lecture-view/src/main/kotlin/de/tum/informatics/www1/artemis/native_app/feature/lectureview/LectureScreenUi.kt
+++ b/feature/lecture-view/src/main/kotlin/de/tum/informatics/www1/artemis/native_app/feature/lectureview/LectureScreenUi.kt
@@ -195,7 +195,7 @@ internal fun LectureScreen(
) { padding ->
val bodyModifier = Modifier
.fillMaxSize()
- .padding(padding)
+ .padding(top = padding.calculateTopPadding())
contentBody(
bodyModifier
diff --git a/feature/lecture-view/src/main/kotlin/de/tum/informatics/www1/artemis/native_app/feature/lectureview/OverviewTab.kt b/feature/lecture-view/src/main/kotlin/de/tum/informatics/www1/artemis/native_app/feature/lectureview/OverviewTab.kt
index 2da11137c..a53a80388 100644
--- a/feature/lecture-view/src/main/kotlin/de/tum/informatics/www1/artemis/native_app/feature/lectureview/OverviewTab.kt
+++ b/feature/lecture-view/src/main/kotlin/de/tum/informatics/www1/artemis/native_app/feature/lectureview/OverviewTab.kt
@@ -2,7 +2,12 @@ package de.tum.informatics.www1.artemis.native_app.feature.lectureview
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Column
+import androidx.compose.foundation.layout.PaddingValues
+import androidx.compose.foundation.layout.WindowInsets
+import androidx.compose.foundation.layout.asPaddingValues
+import androidx.compose.foundation.layout.consumeWindowInsets
import androidx.compose.foundation.layout.fillMaxWidth
+import androidx.compose.foundation.layout.systemBars
import androidx.compose.foundation.lazy.LazyColumn
import androidx.compose.foundation.lazy.LazyListScope
import androidx.compose.foundation.lazy.LazyListState
@@ -50,7 +55,10 @@ internal fun OverviewTab(
LazyColumn(
modifier = modifier.testTag(TEST_TAG_OVERVIEW_LIST),
verticalArrangement = Arrangement.spacedBy(16.dp),
- state = state
+ state = state,
+ contentPadding = PaddingValues(
+ bottom = WindowInsets.systemBars.asPaddingValues().calculateBottomPadding()
+ )
) {
if (description != null) {
item {
diff --git a/feature/login/src/main/kotlin/de/tum/informatics/www1/artemis/native_app/feature/login/AccountUi.kt b/feature/login/src/main/kotlin/de/tum/informatics/www1/artemis/native_app/feature/login/AccountUi.kt
index a64be37e2..d5ab2fc50 100644
--- a/feature/login/src/main/kotlin/de/tum/informatics/www1/artemis/native_app/feature/login/AccountUi.kt
+++ b/feature/login/src/main/kotlin/de/tum/informatics/www1/artemis/native_app/feature/login/AccountUi.kt
@@ -10,10 +10,15 @@ import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.PaddingValues
+import androidx.compose.foundation.layout.WindowInsets
+import androidx.compose.foundation.layout.asPaddingValues
+import androidx.compose.foundation.layout.consumeWindowInsets
import androidx.compose.foundation.layout.fillMaxHeight
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.fillMaxWidth
+import androidx.compose.foundation.layout.imePadding
import androidx.compose.foundation.layout.padding
+import androidx.compose.foundation.layout.systemBars
import androidx.compose.foundation.rememberScrollState
import androidx.compose.foundation.text.ClickableText
import androidx.compose.foundation.verticalScroll
@@ -273,7 +278,9 @@ private fun LoginUiScreen(
NavHost(
modifier = Modifier
.fillMaxSize()
- .padding(paddingValues),
+ .imePadding()
+ .consumeWindowInsets(WindowInsets.systemBars)
+ .padding(top = paddingValues.calculateTopPadding()),
navController = nestedNavController,
startDestination = if (hasSelectedInstance) NestedDestination.HOME.destination else NestedDestination.INSTANCE_SELECTION.destination
) {
@@ -463,7 +470,11 @@ private fun AccountUi(
ClickableText(
modifier = Modifier
.align(Alignment.CenterHorizontally)
- .padding(bottom = 8.dp),
+ .padding(
+ bottom = WindowInsets.systemBars
+ .asPaddingValues()
+ .calculateBottomPadding()
+ ),
text = AnnotatedString(stringResource(id = R.string.account_change_artemis_instance_label)),
style = MaterialTheme.typography.bodyMedium.copy(color = MaterialTheme.colorScheme.linkTextColor),
onClick = { onNavigateToInstanceSelection() }
diff --git a/feature/login/src/main/kotlin/de/tum/informatics/www1/artemis/native_app/feature/login/NotificationSettingsUi.kt b/feature/login/src/main/kotlin/de/tum/informatics/www1/artemis/native_app/feature/login/NotificationSettingsUi.kt
index 04f4ee1fd..40e576e96 100644
--- a/feature/login/src/main/kotlin/de/tum/informatics/www1/artemis/native_app/feature/login/NotificationSettingsUi.kt
+++ b/feature/login/src/main/kotlin/de/tum/informatics/www1/artemis/native_app/feature/login/NotificationSettingsUi.kt
@@ -5,6 +5,7 @@ import androidx.compose.foundation.layout.Spacer
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.height
+import androidx.compose.foundation.layout.imePadding
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.rememberScrollState
import androidx.compose.foundation.verticalScroll
@@ -88,8 +89,9 @@ internal fun NotificationSettingsUi(modifier: Modifier, onDone: () -> Unit) {
Column(
modifier = Modifier
.fillMaxSize()
- .padding(padding)
- .padding(8.dp)
+ .imePadding()
+ .padding(top = padding.calculateTopPadding())
+ .padding(horizontal = 8.dp)
.verticalScroll(rememberScrollState())
) {
de.tum.informatics.www1.artemis.native_app.feature.push.ui.PushNotificationSettingsUi(
diff --git a/feature/login/src/main/kotlin/de/tum/informatics/www1/artemis/native_app/feature/login/instance_selection/InstanceSelectionScreen.kt b/feature/login/src/main/kotlin/de/tum/informatics/www1/artemis/native_app/feature/login/instance_selection/InstanceSelectionScreen.kt
index 686a22a61..0342ff367 100644
--- a/feature/login/src/main/kotlin/de/tum/informatics/www1/artemis/native_app/feature/login/instance_selection/InstanceSelectionScreen.kt
+++ b/feature/login/src/main/kotlin/de/tum/informatics/www1/artemis/native_app/feature/login/instance_selection/InstanceSelectionScreen.kt
@@ -4,10 +4,14 @@ import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.PaddingValues
+import androidx.compose.foundation.layout.WindowInsets
+import androidx.compose.foundation.layout.asPaddingValues
import androidx.compose.foundation.layout.aspectRatio
+import androidx.compose.foundation.layout.consumeWindowInsets
import androidx.compose.foundation.layout.fillMaxHeight
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.padding
+import androidx.compose.foundation.layout.systemBars
import androidx.compose.foundation.lazy.grid.GridCells
import androidx.compose.foundation.lazy.grid.LazyVerticalGrid
import androidx.compose.foundation.lazy.grid.items
@@ -79,7 +83,9 @@ internal fun InstanceSelectionScreen(
columns = GridCells.Fixed(columnCount),
horizontalArrangement = Arrangement.spacedBy(16.dp),
verticalArrangement = Arrangement.spacedBy(16.dp),
- contentPadding = PaddingValues(bottom = 16.dp)
+ contentPadding = PaddingValues(
+ bottom = WindowInsets.systemBars.asPaddingValues().calculateBottomPadding()
+ )
) {
items(availableInstances) { instance ->
val item = GridCellItem.ArtemisInstanceGridCellItem(
diff --git a/feature/login/src/main/kotlin/de/tum/informatics/www1/artemis/native_app/feature/login/login/LoginUi.kt b/feature/login/src/main/kotlin/de/tum/informatics/www1/artemis/native_app/feature/login/login/LoginUi.kt
index 902aa9382..f38f78582 100644
--- a/feature/login/src/main/kotlin/de/tum/informatics/www1/artemis/native_app/feature/login/login/LoginUi.kt
+++ b/feature/login/src/main/kotlin/de/tum/informatics/www1/artemis/native_app/feature/login/login/LoginUi.kt
@@ -3,6 +3,7 @@ package de.tum.informatics.www1.artemis.native_app.feature.login.login
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.fillMaxWidth
+import androidx.compose.foundation.layout.imePadding
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.widthIn
import androidx.compose.foundation.rememberScrollState
diff --git a/feature/login/src/main/kotlin/de/tum/informatics/www1/artemis/native_app/feature/login/register/RegisterUi.kt b/feature/login/src/main/kotlin/de/tum/informatics/www1/artemis/native_app/feature/login/register/RegisterUi.kt
index 93dcbb6b2..fa7b7ed48 100644
--- a/feature/login/src/main/kotlin/de/tum/informatics/www1/artemis/native_app/feature/login/register/RegisterUi.kt
+++ b/feature/login/src/main/kotlin/de/tum/informatics/www1/artemis/native_app/feature/login/register/RegisterUi.kt
@@ -4,6 +4,7 @@ import androidx.compose.animation.AnimatedVisibility
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.fillMaxWidth
+import androidx.compose.foundation.layout.imePadding
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.text.KeyboardOptions
import androidx.compose.material3.Divider
@@ -92,7 +93,7 @@ internal fun RegisterUi(
}
Column(
- modifier = modifier,
+ modifier = modifier.imePadding(),
verticalArrangement = Arrangement.spacedBy(16.dp)
) {
val textFieldModifier = Modifier
diff --git a/feature/login/src/test/java/de/tum/informatics/www1/artemis/native_app/feature/login/RegisterEndToEndTest.kt b/feature/login/src/test/java/de/tum/informatics/www1/artemis/native_app/feature/login/RegisterEndToEndTest.kt
index dafc3c397..98015640b 100644
--- a/feature/login/src/test/java/de/tum/informatics/www1/artemis/native_app/feature/login/RegisterEndToEndTest.kt
+++ b/feature/login/src/test/java/de/tum/informatics/www1/artemis/native_app/feature/login/RegisterEndToEndTest.kt
@@ -1,6 +1,7 @@
package de.tum.informatics.www1.artemis.native_app.feature.login
import androidx.compose.foundation.layout.fillMaxSize
+import androidx.compose.foundation.layout.imePadding
import androidx.compose.foundation.rememberScrollState
import androidx.compose.foundation.verticalScroll
import androidx.compose.ui.Modifier
@@ -83,6 +84,7 @@ class RegisterEndToEndTest : BaseComposeTest() {
RegisterUi(
modifier = Modifier
.fillMaxSize()
+ .imePadding()
.verticalScroll(rememberScrollState()),
viewModel = viewModel,
onRegistered = { }
diff --git a/feature/metis/code-of-conduct/src/main/kotlin/de/tum/informatics/www1/artemis/native_app/feature/metis/codeofconduct/ui/AcceptCodeOfConductUi.kt b/feature/metis/code-of-conduct/src/main/kotlin/de/tum/informatics/www1/artemis/native_app/feature/metis/codeofconduct/ui/AcceptCodeOfConductUi.kt
index fb255be90..39a57b9a9 100644
--- a/feature/metis/code-of-conduct/src/main/kotlin/de/tum/informatics/www1/artemis/native_app/feature/metis/codeofconduct/ui/AcceptCodeOfConductUi.kt
+++ b/feature/metis/code-of-conduct/src/main/kotlin/de/tum/informatics/www1/artemis/native_app/feature/metis/codeofconduct/ui/AcceptCodeOfConductUi.kt
@@ -11,12 +11,15 @@ import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.Column
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.fillMaxWidth
import androidx.compose.foundation.layout.height
import androidx.compose.foundation.layout.heightIn
import androidx.compose.foundation.layout.offset
import androidx.compose.foundation.layout.padding
+import androidx.compose.foundation.layout.systemBars
import androidx.compose.foundation.rememberScrollState
import androidx.compose.foundation.shape.CircleShape
import androidx.compose.foundation.verticalScroll
@@ -125,7 +128,11 @@ fun AcceptCodeOfConductUi(
Icon(
modifier = Modifier
.align(Alignment.BottomCenter)
- .padding(bottom = 8.dp)
+ .padding(
+ bottom = WindowInsets.systemBars
+ .asPaddingValues()
+ .calculateBottomPadding()
+ )
.offset {
val offsetInDp = 4.dp.toPx()
IntOffset(0, (offsetInDp * additionalOffsetPercent).toInt())
diff --git a/feature/metis/conversation/src/main/kotlin/de/tum/informatics/www1/artemis/native_app/feature/metis/conversation/ui/ConversationChatListScreen.kt b/feature/metis/conversation/src/main/kotlin/de/tum/informatics/www1/artemis/native_app/feature/metis/conversation/ui/ConversationChatListScreen.kt
index a35aa4177..09a7be4ed 100644
--- a/feature/metis/conversation/src/main/kotlin/de/tum/informatics/www1/artemis/native_app/feature/metis/conversation/ui/ConversationChatListScreen.kt
+++ b/feature/metis/conversation/src/main/kotlin/de/tum/informatics/www1/artemis/native_app/feature/metis/conversation/ui/ConversationChatListScreen.kt
@@ -2,8 +2,14 @@ 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.WindowInsets
import androidx.compose.foundation.layout.fillMaxSize
+import androidx.compose.foundation.layout.imePadding
+import androidx.compose.foundation.layout.navigationBarsPadding
import androidx.compose.foundation.layout.padding
+import androidx.compose.foundation.layout.safeContent
+import androidx.compose.foundation.layout.safeContentPadding
+import androidx.compose.foundation.layout.windowInsetsPadding
import androidx.compose.foundation.lazy.LazyListState
import androidx.compose.foundation.lazy.rememberLazyListState
import androidx.compose.material.icons.Icons
@@ -29,6 +35,7 @@ import androidx.compose.runtime.setValue
import androidx.compose.ui.Modifier
import androidx.compose.ui.focus.FocusRequester
import androidx.compose.ui.focus.focusRequester
+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.isSuccess
@@ -106,9 +113,10 @@ internal fun ConversationChatListScreen(
MetisChatList(
modifier = Modifier
.fillMaxSize()
- .padding(padding),
+ .imePadding()
+ .padding(bottom = padding.calculateBottomPadding()),
viewModel = viewModel,
- listContentPadding = PaddingValues(),
+ listContentPadding = PaddingValues(top = padding.calculateTopPadding()),
onClickViewPost = onClickViewPost,
isReplyEnabled = isReplyEnabled,
state = chatListState,
diff --git a/feature/metis/conversation/src/main/kotlin/de/tum/informatics/www1/artemis/native_app/feature/metis/conversation/ui/ConversationThreadScreen.kt b/feature/metis/conversation/src/main/kotlin/de/tum/informatics/www1/artemis/native_app/feature/metis/conversation/ui/ConversationThreadScreen.kt
index 4bf13c8d0..294d5f7cf 100644
--- a/feature/metis/conversation/src/main/kotlin/de/tum/informatics/www1/artemis/native_app/feature/metis/conversation/ui/ConversationThreadScreen.kt
+++ b/feature/metis/conversation/src/main/kotlin/de/tum/informatics/www1/artemis/native_app/feature/metis/conversation/ui/ConversationThreadScreen.kt
@@ -1,8 +1,10 @@
package de.tum.informatics.www1.artemis.native_app.feature.metis.conversation.ui
import androidx.compose.foundation.layout.Column
+import androidx.compose.foundation.layout.PaddingValues
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.fillMaxWidth
+import androidx.compose.foundation.layout.imePadding
import androidx.compose.foundation.layout.padding
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.filled.ArrowBack
@@ -58,13 +60,15 @@ internal fun ConversationThreadScreen(
Column(
modifier = Modifier
.fillMaxSize()
- .padding(padding)
+ .imePadding()
+ .padding(bottom = padding.calculateBottomPadding())
) {
CompositionLocalProvider(LocalReplyAutoCompleteHintProvider provides viewModel) {
MetisThreadUi(
modifier = Modifier
.fillMaxWidth()
.weight(1f),
+ listContentPadding = PaddingValues(top = padding.calculateTopPadding()),
viewModel = viewModel
)
}
diff --git a/feature/metis/conversation/src/main/kotlin/de/tum/informatics/www1/artemis/native_app/feature/metis/conversation/ui/chatlist/MetisChatList.kt b/feature/metis/conversation/src/main/kotlin/de/tum/informatics/www1/artemis/native_app/feature/metis/conversation/ui/chatlist/MetisChatList.kt
index 235d245d9..82e6ad78f 100644
--- a/feature/metis/conversation/src/main/kotlin/de/tum/informatics/www1/artemis/native_app/feature/metis/conversation/ui/chatlist/MetisChatList.kt
+++ b/feature/metis/conversation/src/main/kotlin/de/tum/informatics/www1/artemis/native_app/feature/metis/conversation/ui/chatlist/MetisChatList.kt
@@ -29,6 +29,7 @@ import androidx.compose.ui.text.style.TextAlign
import androidx.compose.ui.unit.dp
import androidx.paging.compose.LazyPagingItems
import de.tum.informatics.www1.artemis.native_app.feature.metis.conversation.R
+import de.tum.informatics.www1.artemis.native_app.feature.metis.conversation.service.EmojiService
import de.tum.informatics.www1.artemis.native_app.feature.metis.conversation.service.MetisModificationFailure
import de.tum.informatics.www1.artemis.native_app.feature.metis.conversation.ui.ConversationViewModel
import de.tum.informatics.www1.artemis.native_app.feature.metis.conversation.ui.post.DisplayPostOrder
@@ -124,6 +125,7 @@ fun MetisChatList(
serverUrl: String,
courseId: Long,
state: LazyListState,
+ emojiService: EmojiService = koinInject(),
isReplyEnabled: Boolean,
onCreatePost: () -> Deferred,
onEditPost: (IStandalonePost, String) -> Deferred,
@@ -155,7 +157,7 @@ fun MetisChatList(
state = state,
itemCount = posts.itemCount,
order = DisplayPostOrder.REVERSED,
- emojiService = koinInject(),
+ emojiService = emojiService,
bottomItem = bottomItem
) {
when (posts) {
diff --git a/feature/metis/conversation/src/main/kotlin/de/tum/informatics/www1/artemis/native_app/feature/metis/conversation/ui/post/PostContextBottomSheet.kt b/feature/metis/conversation/src/main/kotlin/de/tum/informatics/www1/artemis/native_app/feature/metis/conversation/ui/post/PostContextBottomSheet.kt
index 474f6a443..f5d170c34 100644
--- a/feature/metis/conversation/src/main/kotlin/de/tum/informatics/www1/artemis/native_app/feature/metis/conversation/ui/post/PostContextBottomSheet.kt
+++ b/feature/metis/conversation/src/main/kotlin/de/tum/informatics/www1/artemis/native_app/feature/metis/conversation/ui/post/PostContextBottomSheet.kt
@@ -9,10 +9,12 @@ import androidx.compose.foundation.layout.BoxScope
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.PaddingValues
import androidx.compose.foundation.layout.Row
+import androidx.compose.foundation.layout.WindowInsets
import androidx.compose.foundation.layout.fillMaxHeight
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.size
+import androidx.compose.foundation.layout.statusBars
import androidx.compose.foundation.layout.width
import androidx.compose.foundation.shape.CircleShape
import androidx.compose.foundation.shape.RoundedCornerShape
@@ -75,6 +77,7 @@ internal fun PostContextBottomSheet(
if (!displayAllEmojis) {
ModalBottomSheet(
modifier = Modifier.testTag(TEST_TAG_POST_CONTEXT_BOTTOM_SHEET),
+ windowInsets = WindowInsets.statusBars,
sheetState = rememberModalBottomSheetState(),
onDismissRequest = onDismissRequest
) {
diff --git a/feature/metis/conversation/src/main/kotlin/de/tum/informatics/www1/artemis/native_app/feature/metis/conversation/ui/thread/MetisThreadUi.kt b/feature/metis/conversation/src/main/kotlin/de/tum/informatics/www1/artemis/native_app/feature/metis/conversation/ui/thread/MetisThreadUi.kt
index 8914c06db..6149d487d 100644
--- a/feature/metis/conversation/src/main/kotlin/de/tum/informatics/www1/artemis/native_app/feature/metis/conversation/ui/thread/MetisThreadUi.kt
+++ b/feature/metis/conversation/src/main/kotlin/de/tum/informatics/www1/artemis/native_app/feature/metis/conversation/ui/thread/MetisThreadUi.kt
@@ -66,6 +66,7 @@ internal fun testTagForAnswerPost(answerPostId: String) = "answerPost$answerPost
@Composable
internal fun MetisThreadUi(
modifier: Modifier,
+ listContentPadding: PaddingValues,
viewModel: ConversationViewModel
) {
val postDataState: DataState by viewModel.threadUseCase.post.collectAsState()
@@ -97,6 +98,7 @@ internal fun MetisThreadUi(
postDataState = postDataState,
isAtLeastTutorInCourse = isAtLeastTutorInCourse,
hasModerationRights = hasModerationRights,
+ listContentPadding = listContentPadding,
serverUrl = serverUrl,
emojiService = koinInject(),
clientId = clientId,
@@ -142,6 +144,7 @@ internal fun MetisThreadUi(
conversationDataState: DataState,
hasModerationRights: Boolean,
isAtLeastTutorInCourse: Boolean,
+ listContentPadding: PaddingValues,
serverUrl: String,
emojiService: EmojiService,
initialReplyTextProvider: InitialReplyTextProvider,
@@ -200,6 +203,7 @@ internal fun MetisThreadUi(
post = post,
hasModerationRights = hasModerationRights,
isAtLeastTutorInCourse = isAtLeastTutorInCourse,
+ listContentPadding = listContentPadding,
clientId = clientId,
onRequestReactWithEmoji = onRequestReactWithEmojiDelegate,
onRequestEdit = onEditPostDelegate,
@@ -234,6 +238,7 @@ private fun PostAndRepliesList(
post: PostPojo,
hasModerationRights: Boolean,
isAtLeastTutorInCourse: Boolean,
+ listContentPadding: PaddingValues,
clientId: Long,
onRequestEdit: (IBasePost) -> Unit,
onRequestDelete: (IBasePost) -> Unit,
@@ -270,7 +275,7 @@ private fun PostAndRepliesList(
ProvideMarkwon {
LazyColumn(
modifier = modifier,
- contentPadding = PaddingValues(vertical = 8.dp),
+ contentPadding = listContentPadding,
verticalArrangement = Arrangement.spacedBy(8.dp),
state = state
) {
diff --git a/feature/metis/conversation/src/test/kotlin/de/tum/informatics/www1/artemis/native_app/feature/metis/conversation/BaseThreadUITest.kt b/feature/metis/conversation/src/test/kotlin/de/tum/informatics/www1/artemis/native_app/feature/metis/conversation/BaseThreadUITest.kt
new file mode 100644
index 000000000..49db524f3
--- /dev/null
+++ b/feature/metis/conversation/src/test/kotlin/de/tum/informatics/www1/artemis/native_app/feature/metis/conversation/BaseThreadUITest.kt
@@ -0,0 +1,97 @@
+package de.tum.informatics.www1.artemis.native_app.feature.metis.conversation
+
+import androidx.compose.foundation.layout.PaddingValues
+import androidx.compose.foundation.layout.fillMaxSize
+import androidx.compose.runtime.remember
+import androidx.compose.ui.Modifier
+import de.tum.informatics.www1.artemis.native_app.core.data.DataState
+import de.tum.informatics.www1.artemis.native_app.core.model.Course
+import de.tum.informatics.www1.artemis.native_app.core.test.BaseComposeTest
+import de.tum.informatics.www1.artemis.native_app.feature.metis.conversation.service.MetisModificationFailure
+import de.tum.informatics.www1.artemis.native_app.feature.metis.conversation.service.impl.EmojiServiceStub
+import de.tum.informatics.www1.artemis.native_app.feature.metis.conversation.ui.thread.MetisThreadUi
+import de.tum.informatics.www1.artemis.native_app.feature.metis.shared.content.dto.IBasePost
+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.content.dto.conversation.OneToOneChat
+import de.tum.informatics.www1.artemis.native_app.feature.metis.shared.db.pojo.AnswerPostPojo
+import de.tum.informatics.www1.artemis.native_app.feature.metis.shared.db.pojo.PostPojo
+import kotlinx.coroutines.CompletableDeferred
+import kotlinx.coroutines.Deferred
+import kotlinx.datetime.Clock
+
+abstract class BaseThreadUITest : BaseComposeTest() {
+
+ val clientId = 20L
+
+ val course: Course = Course(id = 1)
+ val conversation = OneToOneChat(id = 2)
+
+ val answers = (0..2).map { index ->
+ AnswerPostPojo(
+ parentPostId = "client-id",
+ postId = "answer-client-id-$index",
+ resolvesPost = false,
+ basePostingCache = AnswerPostPojo.BasePostingCache(
+ serverPostId = index.toLong(),
+ authorId = clientId,
+ creationDate = Clock.System.now(),
+ updatedDate = null,
+ content = "Answer Post content $index",
+ authorRole = UserRole.USER,
+ authorName = "author name"
+ ),
+ reactions = emptyList(),
+ serverPostIdCache = AnswerPostPojo.ServerPostIdCache(
+ serverPostId = index.toLong()
+ )
+ )
+ }
+
+ val posts = (0..2).map { index ->
+ PostPojo(
+ clientPostId = "client-id-$index",
+ serverPostId = index.toLong(),
+ content = "Post content $index",
+ resolved = false,
+ updatedDate = null,
+ creationDate = Clock.System.now(),
+ authorId = clientId,
+ title = null,
+ authorName = "author name",
+ authorRole = UserRole.USER,
+ courseWideContext = null,
+ tags = emptyList(),
+ answers = if (index == 0) answers else emptyList(),
+ reactions = emptyList()
+ )
+ }
+
+ fun setupThreadUi(
+ post: PostPojo,
+ onResolvePost: ((IBasePost) -> Deferred)?
+ ) {
+ composeTestRule.setContent {
+ MetisThreadUi(
+ modifier = Modifier.fillMaxSize(),
+ courseId = course.id!!,
+ clientId = clientId,
+ postDataState = DataState.Success(post),
+ conversationDataState = DataState.Success(conversation),
+ hasModerationRights = false,
+ isAtLeastTutorInCourse = false,
+ listContentPadding = PaddingValues(),
+ serverUrl = "",
+ emojiService = EmojiServiceStub,
+ initialReplyTextProvider = remember { TestInitialReplyTextProvider() },
+ onCreatePost = { CompletableDeferred() },
+ onEditPost = { _, _ -> CompletableDeferred() },
+ onResolvePost = onResolvePost,
+ onDeletePost = { CompletableDeferred() },
+ onRequestReactWithEmoji = { _, _, _ -> CompletableDeferred() },
+ onRequestReload = {},
+ onRequestRetrySend = { _, _ -> },
+ )
+ }
+ }
+
+}
diff --git a/feature/metis/conversation/src/test/kotlin/de/tum/informatics/www1/artemis/native_app/feature/metis/conversation/ConversationAnswerMessagesUITest.kt b/feature/metis/conversation/src/test/kotlin/de/tum/informatics/www1/artemis/native_app/feature/metis/conversation/ConversationAnswerMessagesUITest.kt
index da5f2f06d..b9a232f32 100644
--- a/feature/metis/conversation/src/test/kotlin/de/tum/informatics/www1/artemis/native_app/feature/metis/conversation/ConversationAnswerMessagesUITest.kt
+++ b/feature/metis/conversation/src/test/kotlin/de/tum/informatics/www1/artemis/native_app/feature/metis/conversation/ConversationAnswerMessagesUITest.kt
@@ -1,105 +1,37 @@
package de.tum.informatics.www1.artemis.native_app.feature.metis.conversation
-import androidx.compose.foundation.layout.fillMaxSize
-import androidx.compose.foundation.lazy.LazyListState
-import androidx.compose.runtime.Composable
-import androidx.compose.runtime.remember
-import androidx.compose.ui.Modifier
import androidx.compose.ui.semantics.SemanticsActions
-import androidx.compose.ui.semantics.SemanticsProperties
-import androidx.compose.ui.semantics.getOrNull
-import androidx.compose.ui.test.SemanticsNodeInteraction
import androidx.compose.ui.test.assert
-import androidx.compose.ui.test.assertHasClickAction
import androidx.compose.ui.test.hasAnyChild
-import androidx.compose.ui.test.hasScrollAction
-import androidx.compose.ui.test.hasTestTag
import androidx.compose.ui.test.hasText
import androidx.compose.ui.test.onNodeWithTag
import androidx.compose.ui.test.onNodeWithText
-import androidx.compose.ui.test.onParent
-import androidx.compose.ui.test.onRoot
import androidx.compose.ui.test.performClick
-import androidx.compose.ui.test.performScrollTo
import androidx.compose.ui.test.performScrollToIndex
import androidx.compose.ui.test.performSemanticsAction
-import androidx.compose.ui.test.printToLog
-import de.tum.informatics.www1.artemis.native_app.core.common.test.EndToEndTest
-import de.tum.informatics.www1.artemis.native_app.core.data.DataState
-import de.tum.informatics.www1.artemis.native_app.core.model.Course
-import de.tum.informatics.www1.artemis.native_app.core.test.BaseComposeTest
-import de.tum.informatics.www1.artemis.native_app.feature.metis.conversation.service.MetisModificationFailure
-import de.tum.informatics.www1.artemis.native_app.feature.metis.conversation.service.impl.EmojiServiceStub
-import de.tum.informatics.www1.artemis.native_app.feature.metis.conversation.ui.thread.MetisThreadUi
+import de.tum.informatics.www1.artemis.native_app.core.common.test.UnitTest
import de.tum.informatics.www1.artemis.native_app.feature.metis.conversation.ui.thread.TEST_TAG_THREAD_LIST
import de.tum.informatics.www1.artemis.native_app.feature.metis.shared.content.dto.IBasePost
-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.content.dto.conversation.OneToOneChat
import de.tum.informatics.www1.artemis.native_app.feature.metis.shared.db.pojo.AnswerPostPojo
-import de.tum.informatics.www1.artemis.native_app.feature.metis.shared.db.pojo.PostPojo
import kotlinx.coroutines.CompletableDeferred
-import kotlinx.coroutines.Deferred
-import kotlinx.coroutines.runBlocking
-import kotlinx.datetime.Clock
import org.junit.Test
import org.junit.experimental.categories.Category
import org.junit.runner.RunWith
import org.robolectric.RobolectricTestRunner
-@Category(EndToEndTest::class)
+@Category(UnitTest::class)
@RunWith(RobolectricTestRunner::class)
-class ConversationAnswerMessagesUITest : BaseComposeTest() {
-
- private val clientId = 20L
-
- private val course: Course = Course(id = 1)
- private val conversation = OneToOneChat(id = 2)
-
- private val answers = (0..2).map { index ->
- AnswerPostPojo(
- parentPostId = "client-id",
- postId = "answer-client-id-$index",
- resolvesPost = false,
- basePostingCache = AnswerPostPojo.BasePostingCache(
- serverPostId = index.toLong(),
- authorId = clientId,
- creationDate = Clock.System.now(),
- updatedDate = null,
- content = "Answer Post content $index",
- authorRole = UserRole.USER,
- authorName = "author name"
- ),
- reactions = emptyList(),
- serverPostIdCache = AnswerPostPojo.ServerPostIdCache(
- serverPostId = index.toLong()
- )
- )
- }
-
- private val post = PostPojo(
- clientPostId = "client-id",
- serverPostId = 12,
- content = "Post content",
- resolved = false,
- updatedDate = null,
- creationDate = Clock.System.now(),
- authorId = clientId,
- title = null,
- authorName = "author name",
- authorRole = UserRole.USER,
- courseWideContext = null,
- tags = emptyList(),
- answers = answers,
- reactions = emptyList()
- )
+class ConversationAnswerMessagesUITest : BaseThreadUITest() {
private fun testTagForAnswerPost(answerPostId: String) = "answerPost$answerPostId"
+ private val post = posts[0]
+
@Test
fun `test GIVEN post is not resolved WHEN resolving the post THEN the post is resolved with the first answer post`() {
var resolvedPost: IBasePost? = null
- setupUi(post) { post ->
+ setupThreadUi(post) { post ->
resolvedPost = post
CompletableDeferred()
}
@@ -118,7 +50,7 @@ class ConversationAnswerMessagesUITest : BaseComposeTest() {
fun `test GIVEN post is not resolved WHEN resolving the post THEN the post is resolved with the third answer post`() {
var resolvedPost: IBasePost? = null
- setupUi(post) { post ->
+ setupThreadUi(post) { post ->
resolvedPost = post
CompletableDeferred()
}
@@ -145,7 +77,7 @@ class ConversationAnswerMessagesUITest : BaseComposeTest() {
var unresolvedPost: IBasePost? = null
- setupUi(resolvedPost) { post ->
+ setupThreadUi(resolvedPost) { post ->
unresolvedPost = post
CompletableDeferred()
}
@@ -162,7 +94,7 @@ class ConversationAnswerMessagesUITest : BaseComposeTest() {
@Test
fun `test GIVEN the post is not resolved and no answer post is resolving THEN the post is shown as not resolved and no answer post is shown as resolving`() {
- setupUi(post) { CompletableDeferred() }
+ setupThreadUi(post) { CompletableDeferred() }
composeTestRule.onNodeWithText(post.content).assertExists()
for (answer in answers) {
@@ -185,7 +117,7 @@ class ConversationAnswerMessagesUITest : BaseComposeTest() {
answers = modifiedAnswers
)
- setupUi(resolvedPost) { CompletableDeferred() }
+ setupThreadUi(resolvedPost) { CompletableDeferred() }
val resolvesAssertion = hasAnyChild(hasText(context.getString(R.string.post_resolves)))
@@ -199,31 +131,4 @@ class ConversationAnswerMessagesUITest : BaseComposeTest() {
.assert(if (i == resolvingIndex) resolvesAssertion else resolvesAssertion.not())
}
}
-
- private fun setupUi(
- post: PostPojo,
- onResolvePost: ((IBasePost) -> Deferred)?
- ) {
- composeTestRule.setContent {
- MetisThreadUi(
- modifier = Modifier.fillMaxSize(),
- courseId = course.id!!,
- clientId = clientId,
- postDataState = DataState.Success(post),
- conversationDataState = DataState.Success(conversation),
- hasModerationRights = false,
- isAtLeastTutorInCourse = false,
- serverUrl = "",
- emojiService = EmojiServiceStub,
- initialReplyTextProvider = remember { TestInitialReplyTextProvider() },
- onCreatePost = { CompletableDeferred() },
- onEditPost = { _, _ -> CompletableDeferred() },
- onResolvePost = onResolvePost,
- onDeletePost = { CompletableDeferred() },
- onRequestReactWithEmoji = { _, _, _ -> CompletableDeferred() },
- onRequestReload = {},
- onRequestRetrySend = { _, _ -> },
- )
- }
- }
}
\ No newline at end of file
diff --git a/feature/metis/conversation/src/test/kotlin/de/tum/informatics/www1/artemis/native_app/feature/metis/conversation/ui/reply/ReplyTextFieldVisibilityUITest.kt b/feature/metis/conversation/src/test/kotlin/de/tum/informatics/www1/artemis/native_app/feature/metis/conversation/ui/reply/ReplyTextFieldVisibilityUITest.kt
new file mode 100644
index 000000000..0ad718440
--- /dev/null
+++ b/feature/metis/conversation/src/test/kotlin/de/tum/informatics/www1/artemis/native_app/feature/metis/conversation/ui/reply/ReplyTextFieldVisibilityUITest.kt
@@ -0,0 +1,85 @@
+package de.tum.informatics.www1.artemis.native_app.feature.metis.conversation.ui.reply
+
+import androidx.compose.foundation.layout.PaddingValues
+import androidx.compose.foundation.layout.fillMaxSize
+import androidx.compose.foundation.lazy.rememberLazyListState
+import androidx.compose.runtime.remember
+import androidx.compose.ui.Modifier
+import androidx.compose.ui.test.assertIsDisplayed
+import androidx.compose.ui.test.onNodeWithTag
+import androidx.compose.ui.test.performClick
+import de.tum.informatics.www1.artemis.native_app.core.common.test.EndToEndTest
+import de.tum.informatics.www1.artemis.native_app.core.common.test.UnitTest
+import de.tum.informatics.www1.artemis.native_app.feature.metis.conversation.BaseThreadUITest
+import de.tum.informatics.www1.artemis.native_app.feature.metis.conversation.TestInitialReplyTextProvider
+import de.tum.informatics.www1.artemis.native_app.feature.metis.conversation.service.impl.EmojiServiceStub
+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.chatlist.PostsDataState
+import de.tum.informatics.www1.artemis.native_app.feature.metis.shared.db.pojo.PostPojo
+import junit.framework.TestCase.assertTrue
+import kotlinx.coroutines.CompletableDeferred
+import org.junit.Test
+import org.junit.experimental.categories.Category
+import org.junit.runner.RunWith
+import org.robolectric.RobolectricTestRunner
+
+@Category(UnitTest::class)
+@RunWith(RobolectricTestRunner::class)
+class ReplyTextFieldVisibilityUITest : BaseThreadUITest() {
+
+ @Test
+ fun `test GIVEN the thread view is shown containing one post and three answer posts WHEN the markdown text field is clicked THEN the keyboard is shown below the markdown text field`() {
+ setupThreadUi(posts[0]) { CompletableDeferred() }
+ runTest()
+ }
+
+ @Test
+ fun `test GIVEN the chat list containing three posts is shown WHEN the markdown text field is clicked THEN the keyboard is shown below the markdown text field`() {
+ setupChatUi(posts)
+ runTest()
+ }
+
+ private fun runTest() {
+ val markdownTextField = composeTestRule.onNodeWithTag(TEST_TAG_CAN_CREATE_REPLY)
+ val initialPosition = markdownTextField.fetchSemanticsNode().positionInRoot.y
+
+ markdownTextField.performClick()
+ composeTestRule.waitForIdle()
+
+ val newPosition = markdownTextField.fetchSemanticsNode().positionInRoot.y
+
+ markdownTextField
+ .assertExists()
+ .assertIsDisplayed()
+ assertTrue("Text field should move up when the keyboard appears", newPosition < initialPosition)
+ }
+
+ private fun setupChatUi(posts: List) {
+ composeTestRule.setContent {
+ val list = posts.map { post -> ChatListItem.PostChatListItem(post) }.toMutableList()
+ MetisChatList(
+ modifier = Modifier.fillMaxSize(),
+ initialReplyTextProvider = remember { TestInitialReplyTextProvider() },
+ posts = PostsDataState.Loaded.WithList(list, PostsDataState.NotLoading),
+ clientId = clientId,
+ hasModerationRights = false,
+ isAtLeastTutorInCourse = false,
+ listContentPadding = PaddingValues(),
+ serverUrl = "",
+ courseId = course.id!!,
+ state = rememberLazyListState(),
+ emojiService = EmojiServiceStub,
+ bottomItem = posts.lastOrNull(),
+ isReplyEnabled = true,
+ onCreatePost = { CompletableDeferred() },
+ onEditPost = { _, _ -> CompletableDeferred() },
+ onDeletePost = { CompletableDeferred() },
+ onRequestReactWithEmoji = { _, _, _ -> CompletableDeferred() },
+ onClickViewPost = {},
+ onRequestRetrySend = { _ -> },
+ title = "Title"
+ )
+ }
+ }
+}
diff --git a/feature/metis/manage-conversations/src/main/kotlin/de/tum/informatics/www1/artemis/native_app/feature/metis/manageconversations/ui/conversation/browse_channels/BrowseChannelsScreen.kt b/feature/metis/manage-conversations/src/main/kotlin/de/tum/informatics/www1/artemis/native_app/feature/metis/manageconversations/ui/conversation/browse_channels/BrowseChannelsScreen.kt
index 15463df2f..61a95fb97 100644
--- a/feature/metis/manage-conversations/src/main/kotlin/de/tum/informatics/www1/artemis/native_app/feature/metis/manageconversations/ui/conversation/browse_channels/BrowseChannelsScreen.kt
+++ b/feature/metis/manage-conversations/src/main/kotlin/de/tum/informatics/www1/artemis/native_app/feature/metis/manageconversations/ui/conversation/browse_channels/BrowseChannelsScreen.kt
@@ -3,9 +3,12 @@ package de.tum.informatics.www1.artemis.native_app.feature.metis.manageconversat
import androidx.compose.foundation.background
import androidx.compose.foundation.layout.PaddingValues
import androidx.compose.foundation.layout.Row
+import androidx.compose.foundation.layout.WindowInsets
+import androidx.compose.foundation.layout.consumeWindowInsets
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.padding
+import androidx.compose.foundation.layout.systemBars
import androidx.compose.foundation.layout.wrapContentSize
import androidx.compose.foundation.lazy.LazyColumn
import androidx.compose.foundation.lazy.items
@@ -103,7 +106,8 @@ internal fun BrowseChannelsScreen(
BasicDataStateUi(
modifier = Modifier
.fillMaxSize()
- .padding(padding),
+ .padding(top = padding.calculateTopPadding())
+ .consumeWindowInsets(WindowInsets.systemBars),
dataState = channelsDataState,
loadingText = stringResource(id = R.string.browse_channel_list_loading),
failureText = stringResource(id = R.string.browse_channel_list_failure),
diff --git a/feature/metis/manage-conversations/src/main/kotlin/de/tum/informatics/www1/artemis/native_app/feature/metis/manageconversations/ui/conversation/create_channel/CreateChannelScreen.kt b/feature/metis/manage-conversations/src/main/kotlin/de/tum/informatics/www1/artemis/native_app/feature/metis/manageconversations/ui/conversation/create_channel/CreateChannelScreen.kt
index 6f209ac66..0091182bd 100644
--- a/feature/metis/manage-conversations/src/main/kotlin/de/tum/informatics/www1/artemis/native_app/feature/metis/manageconversations/ui/conversation/create_channel/CreateChannelScreen.kt
+++ b/feature/metis/manage-conversations/src/main/kotlin/de/tum/informatics/www1/artemis/native_app/feature/metis/manageconversations/ui/conversation/create_channel/CreateChannelScreen.kt
@@ -7,6 +7,7 @@ import androidx.compose.foundation.layout.Spacer
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.height
+import androidx.compose.foundation.layout.imePadding
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.rememberScrollState
import androidx.compose.foundation.verticalScroll
@@ -92,6 +93,7 @@ internal fun CreateChannelScreen(
Column(
modifier = Modifier
.fillMaxSize()
+ .imePadding()
.padding(paddingValues)
.verticalScroll(rememberScrollState())
.padding(horizontal = Spacings.ScreenHorizontalSpacing),
diff --git a/feature/metis/manage-conversations/src/main/kotlin/de/tum/informatics/www1/artemis/native_app/feature/metis/manageconversations/ui/conversation/create_personal_conversation/CreatePersonalConversationScreen.kt b/feature/metis/manage-conversations/src/main/kotlin/de/tum/informatics/www1/artemis/native_app/feature/metis/manageconversations/ui/conversation/create_personal_conversation/CreatePersonalConversationScreen.kt
index 1fe03354b..816af3a5d 100644
--- a/feature/metis/manage-conversations/src/main/kotlin/de/tum/informatics/www1/artemis/native_app/feature/metis/manageconversations/ui/conversation/create_personal_conversation/CreatePersonalConversationScreen.kt
+++ b/feature/metis/manage-conversations/src/main/kotlin/de/tum/informatics/www1/artemis/native_app/feature/metis/manageconversations/ui/conversation/create_personal_conversation/CreatePersonalConversationScreen.kt
@@ -1,6 +1,7 @@
package de.tum.informatics.www1.artemis.native_app.feature.metis.manageconversations.ui.conversation.create_personal_conversation
import androidx.compose.foundation.layout.fillMaxSize
+import androidx.compose.foundation.layout.imePadding
import androidx.compose.foundation.layout.padding
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.filled.ArrowBack
@@ -87,6 +88,7 @@ internal fun CreatePersonalConversationScreen(
MemberSelection(
modifier = Modifier
.fillMaxSize()
+ .imePadding()
.padding(padding)
.padding(horizontal = Spacings.ScreenHorizontalSpacing),
viewModel = viewModel
diff --git a/feature/metis/manage-conversations/src/main/kotlin/de/tum/informatics/www1/artemis/native_app/feature/metis/manageconversations/ui/conversation/overview/ConversationOverviewBody.kt b/feature/metis/manage-conversations/src/main/kotlin/de/tum/informatics/www1/artemis/native_app/feature/metis/manageconversations/ui/conversation/overview/ConversationOverviewBody.kt
index 960a3b505..cfed38cbc 100644
--- a/feature/metis/manage-conversations/src/main/kotlin/de/tum/informatics/www1/artemis/native_app/feature/metis/manageconversations/ui/conversation/overview/ConversationOverviewBody.kt
+++ b/feature/metis/manage-conversations/src/main/kotlin/de/tum/informatics/www1/artemis/native_app/feature/metis/manageconversations/ui/conversation/overview/ConversationOverviewBody.kt
@@ -7,10 +7,15 @@ import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.Column
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.fillMaxWidth
+import androidx.compose.foundation.layout.imePadding
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.size
+import androidx.compose.foundation.layout.statusBars
+import androidx.compose.foundation.layout.systemBars
import androidx.compose.foundation.rememberScrollState
import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.foundation.verticalScroll
@@ -155,7 +160,8 @@ fun ConversationOverviewBody(
Box(
modifier = Modifier
.fillMaxWidth()
- .padding(top = 16.dp)
+ .padding(16.dp)
+ .padding(bottom = 24.dp)
) {
TextButton(
modifier = Modifier.align(Alignment.Center),
@@ -184,6 +190,7 @@ fun ConversationOverviewBody(
if (showCodeOfConduct) {
ModalBottomSheet(
+ windowInsets = WindowInsets.statusBars,
onDismissRequest = { showCodeOfConduct = false }
) {
CodeOfConductUi(
@@ -210,7 +217,13 @@ fun ConversationFabMenu(
Box(
modifier = Modifier
.fillMaxSize()
- .padding(16.dp),
+ .padding(
+ bottom = WindowInsets.systemBars
+ .asPaddingValues()
+ .calculateBottomPadding() + 8.dp,
+ end = 16.dp
+ )
+ .imePadding(),
contentAlignment = Alignment.BottomEnd
) {
Box {
diff --git a/feature/metis/manage-conversations/src/main/kotlin/de/tum/informatics/www1/artemis/native_app/feature/metis/manageconversations/ui/conversation/settings/members/ConversationMembersScreen.kt b/feature/metis/manage-conversations/src/main/kotlin/de/tum/informatics/www1/artemis/native_app/feature/metis/manageconversations/ui/conversation/settings/members/ConversationMembersScreen.kt
index 662c1a63a..eb6bdec30 100644
--- a/feature/metis/manage-conversations/src/main/kotlin/de/tum/informatics/www1/artemis/native_app/feature/metis/manageconversations/ui/conversation/settings/members/ConversationMembersScreen.kt
+++ b/feature/metis/manage-conversations/src/main/kotlin/de/tum/informatics/www1/artemis/native_app/feature/metis/manageconversations/ui/conversation/settings/members/ConversationMembersScreen.kt
@@ -1,7 +1,10 @@
package de.tum.informatics.www1.artemis.native_app.feature.metis.manageconversations.ui.conversation.settings.members
+import androidx.compose.foundation.layout.WindowInsets
+import androidx.compose.foundation.layout.consumeWindowInsets
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.padding
+import androidx.compose.foundation.layout.systemBars
import androidx.compose.material3.Scaffold
import androidx.compose.material3.Text
import androidx.compose.material3.TopAppBar
@@ -61,7 +64,7 @@ fun ConversationMembersScreen(
ConversationMembersBody(
modifier = Modifier
.fillMaxSize()
- .padding(padding)
+ .consumeWindowInsets(WindowInsets.systemBars)
.padding(top = 16.dp),
courseId = courseId,
conversationId = conversationId
diff --git a/feature/metis/manage-conversations/src/main/kotlin/de/tum/informatics/www1/artemis/native_app/feature/metis/manageconversations/ui/conversation/settings/overview/ConversationSettingsBody.kt b/feature/metis/manage-conversations/src/main/kotlin/de/tum/informatics/www1/artemis/native_app/feature/metis/manageconversations/ui/conversation/settings/overview/ConversationSettingsBody.kt
index cc5136014..db639141c 100644
--- a/feature/metis/manage-conversations/src/main/kotlin/de/tum/informatics/www1/artemis/native_app/feature/metis/manageconversations/ui/conversation/settings/overview/ConversationSettingsBody.kt
+++ b/feature/metis/manage-conversations/src/main/kotlin/de/tum/informatics/www1/artemis/native_app/feature/metis/manageconversations/ui/conversation/settings/overview/ConversationSettingsBody.kt
@@ -2,9 +2,12 @@ package de.tum.informatics.www1.artemis.native_app.feature.metis.manageconversat
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Column
+import androidx.compose.foundation.layout.WindowInsets
+import androidx.compose.foundation.layout.asPaddingValues
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.padding
+import androidx.compose.foundation.layout.systemBars
import androidx.compose.foundation.rememberScrollState
import androidx.compose.foundation.verticalScroll
import androidx.compose.material3.MaterialTheme
@@ -136,7 +139,8 @@ internal fun ConversationSettingsBody(
Column(
modifier = Modifier
.fillMaxSize()
- .verticalScroll(rememberScrollState()),
+ .verticalScroll(rememberScrollState())
+ .padding(bottom = WindowInsets.systemBars.asPaddingValues().calculateBottomPadding()),
verticalArrangement = Arrangement.spacedBy(16.dp)
) {
ConversationInfoSettings(
diff --git a/feature/metis/manage-conversations/src/main/kotlin/de/tum/informatics/www1/artemis/native_app/feature/metis/manageconversations/ui/conversation/settings/overview/ConversationSettingsScreen.kt b/feature/metis/manage-conversations/src/main/kotlin/de/tum/informatics/www1/artemis/native_app/feature/metis/manageconversations/ui/conversation/settings/overview/ConversationSettingsScreen.kt
index 795755ce1..e87e15fdc 100644
--- a/feature/metis/manage-conversations/src/main/kotlin/de/tum/informatics/www1/artemis/native_app/feature/metis/manageconversations/ui/conversation/settings/overview/ConversationSettingsScreen.kt
+++ b/feature/metis/manage-conversations/src/main/kotlin/de/tum/informatics/www1/artemis/native_app/feature/metis/manageconversations/ui/conversation/settings/overview/ConversationSettingsScreen.kt
@@ -1,7 +1,11 @@
package de.tum.informatics.www1.artemis.native_app.feature.metis.manageconversations.ui.conversation.settings.overview
+import androidx.compose.foundation.layout.WindowInsets
+import androidx.compose.foundation.layout.consumeWindowInsets
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.material.icons.Icons
import androidx.compose.material.icons.filled.Refresh
import androidx.compose.material3.Icon
@@ -121,7 +125,9 @@ internal fun ConversationSettingsScreen(
ConversationSettingsBody(
modifier = Modifier
.fillMaxSize()
- .padding(paddingValues),
+ .imePadding()
+ .padding(top = paddingValues.calculateTopPadding())
+ .consumeWindowInsets(WindowInsets.systemBars),
viewModel = viewModel,
onRequestViewAllMembers = onRequestViewAllMembers,
onRequestAddMembers = onRequestAddMembers,
diff --git a/feature/settings/src/main/kotlin/de/tum/informatics/www1/artemis/native_app/feature/settings/PushNotificationSettingsScreen.kt b/feature/settings/src/main/kotlin/de/tum/informatics/www1/artemis/native_app/feature/settings/PushNotificationSettingsScreen.kt
index 28bcd23f3..c6b216307 100644
--- a/feature/settings/src/main/kotlin/de/tum/informatics/www1/artemis/native_app/feature/settings/PushNotificationSettingsScreen.kt
+++ b/feature/settings/src/main/kotlin/de/tum/informatics/www1/artemis/native_app/feature/settings/PushNotificationSettingsScreen.kt
@@ -1,7 +1,10 @@
package de.tum.informatics.www1.artemis.native_app.feature.settings
+import androidx.compose.foundation.layout.WindowInsets
+import androidx.compose.foundation.layout.asPaddingValues
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.padding
+import androidx.compose.foundation.layout.systemBars
import androidx.compose.foundation.rememberScrollState
import androidx.compose.foundation.verticalScroll
import androidx.compose.material.icons.Icons
@@ -67,9 +70,10 @@ internal fun PushNotificationSettingsScreen(modifier: Modifier, onNavigateBack:
PushNotificationSettingsUi(
modifier = Modifier
.fillMaxSize()
- .padding(padding)
+ .padding(top = padding.calculateTopPadding())
.padding(horizontal = 8.dp)
- .verticalScroll(rememberScrollState()),
+ .verticalScroll(rememberScrollState())
+ .padding(bottom = WindowInsets.systemBars.asPaddingValues().calculateBottomPadding()),
viewModel = viewModel
)
diff --git a/feature/settings/src/main/kotlin/de/tum/informatics/www1/artemis/native_app/feature/settings/SettingsScreen.kt b/feature/settings/src/main/kotlin/de/tum/informatics/www1/artemis/native_app/feature/settings/SettingsScreen.kt
index dfba46ced..00e78af6d 100644
--- a/feature/settings/src/main/kotlin/de/tum/informatics/www1/artemis/native_app/feature/settings/SettingsScreen.kt
+++ b/feature/settings/src/main/kotlin/de/tum/informatics/www1/artemis/native_app/feature/settings/SettingsScreen.kt
@@ -6,9 +6,12 @@ import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.ColumnScope
import androidx.compose.foundation.layout.Row
+import androidx.compose.foundation.layout.WindowInsets
+import androidx.compose.foundation.layout.asPaddingValues
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.padding
+import androidx.compose.foundation.layout.systemBars
import androidx.compose.foundation.rememberScrollState
import androidx.compose.foundation.verticalScroll
import androidx.compose.material.icons.Icons
@@ -175,8 +178,9 @@ private fun SettingsScreen(
Column(
modifier = Modifier
.fillMaxSize()
- .padding(padding)
- .verticalScroll(rememberScrollState()),
+ .padding(top = padding.calculateTopPadding())
+ .verticalScroll(rememberScrollState())
+ .padding(bottom = WindowInsets.systemBars.asPaddingValues().calculateBottomPadding()),
verticalArrangement = Arrangement.spacedBy(16.dp)
) {
if (authToken != null) {
From d89336f36247f532fd1d117cd846f47f76e98f15 Mon Sep 17 00:00:00 2001
From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com>
Date: Wed, 20 Nov 2024 15:12:38 +0100
Subject: [PATCH 06/22] Bump sentry-android from 6.22.0 to 7.17.0 (#113)
Signed-off-by: dependabot[bot]
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: Martin Felber
Co-authored-by: Martin Felber <45291671+FelberMartin@users.noreply.github.com>
---
.github/workflows/e2e-test.yml | 5 +++++
.github/workflows/unit-test.yml | 5 +++++
gradle/libs.versions.toml | 2 +-
3 files changed, 11 insertions(+), 1 deletion(-)
diff --git a/.github/workflows/e2e-test.yml b/.github/workflows/e2e-test.yml
index 7194207da..0277a2045 100644
--- a/.github/workflows/e2e-test.yml
+++ b/.github/workflows/e2e-test.yml
@@ -8,6 +8,11 @@ on:
pull_request:
workflow_dispatch:
+permissions:
+ id-token: write
+ contents: read
+ checks: write
+
jobs:
end-to-end-tests:
name: E2E Tests
diff --git a/.github/workflows/unit-test.yml b/.github/workflows/unit-test.yml
index f560eef1f..5a444809f 100644
--- a/.github/workflows/unit-test.yml
+++ b/.github/workflows/unit-test.yml
@@ -8,6 +8,11 @@ on:
pull_request:
workflow_dispatch:
+permissions:
+ id-token: write
+ contents: read
+ checks: write
+
jobs:
jUnit:
name: JUnit Tests
diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml
index 7b14ab928..852573e89 100644
--- a/gradle/libs.versions.toml
+++ b/gradle/libs.versions.toml
@@ -31,7 +31,7 @@ mockk = "1.13.8"
ossLicensesPlugin = "0.10.6"
placeholderMaterial = "1.0.1"
room = "2.6.0"
-sentry-android = "6.22.0"
+sentry-android = "7.17.0"
work = "2.9.0"
# Used indirecly in the build config -> Do not remove without double checking.
From b69876651f63eeb782b53332ffd33816df053077 Mon Sep 17 00:00:00 2001
From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com>
Date: Wed, 20 Nov 2024 16:02:09 +0100
Subject: [PATCH 07/22] Bump ktor from 2.3.7 to 2.3.12 (#112)
Signed-off-by: dependabot[bot]
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: Martin Felber
---
gradle/libs.versions.toml | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml
index 852573e89..fb40cd9a7 100644
--- a/gradle/libs.versions.toml
+++ b/gradle/libs.versions.toml
@@ -24,7 +24,7 @@ kotlinxSerializationJson = "1.5.1"
koin = "3.5.3"
koinAndroidxCompose = "3.4.5"
kover = "0.7.2"
-ktor = "2.3.7"
+ktor = "2.3.12"
krossbow = "5.2.0"
markwon = "4.6.2"
mockk = "1.13.8"
From 0ae3b859def5b2d6e5d44cbcf5c0d68b694acb09 Mon Sep 17 00:00:00 2001
From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com>
Date: Wed, 20 Nov 2024 17:35:54 +0100
Subject: [PATCH 08/22] Bump plugin.serialization from 1.8.10 to 2.0.21 (#50)
Signed-off-by: dependabot[bot]
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: Martin Felber <45291671+FelberMartin@users.noreply.github.com>
---
buildSrc/build.gradle.kts | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/buildSrc/build.gradle.kts b/buildSrc/build.gradle.kts
index e3f9e9cd6..0b1e201ba 100644
--- a/buildSrc/build.gradle.kts
+++ b/buildSrc/build.gradle.kts
@@ -1,7 +1,7 @@
plugins {
`kotlin-dsl`
kotlin("jvm") version "1.8.10"
- kotlin("plugin.serialization") version "1.8.10"
+ kotlin("plugin.serialization") version "2.0.21"
// id("java-gradle-plugin")
}
From 964e5b9787baa4492c83e8e8b8ccd89808c44573 Mon Sep 17 00:00:00 2001
From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com>
Date: Thu, 21 Nov 2024 08:34:27 +0100
Subject: [PATCH 09/22] Bump kotlinxCoroutines from 1.7.3 to 1.9.0 (#45)
Signed-off-by: dependabot[bot]
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: Martin Felber <45291671+FelberMartin@users.noreply.github.com>
---
gradle/libs.versions.toml | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml
index fb40cd9a7..ff8fb54e2 100644
--- a/gradle/libs.versions.toml
+++ b/gradle/libs.versions.toml
@@ -18,7 +18,7 @@ androidxPagingCompose = "3.2.1"
coil = "2.4.0"
emoji2 = "1.4.0"
kotlin = "1.9.25"
-kotlinxCoroutines = "1.7.3"
+kotlinxCoroutines = "1.9.0"
kotlinxDatetime = "0.4.0"
kotlinxSerializationJson = "1.5.1"
koin = "3.5.3"
From 27853fce6e1c8034423608ab00cf3d40fbd648c9 Mon Sep 17 00:00:00 2001
From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com>
Date: Thu, 21 Nov 2024 08:34:57 +0100
Subject: [PATCH 10/22] Bump androidx.work:work-runtime-ktx from 2.9.0 to
2.10.0 (#129)
Signed-off-by: dependabot[bot]
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
---
gradle/libs.versions.toml | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml
index ff8fb54e2..7d4df60a4 100644
--- a/gradle/libs.versions.toml
+++ b/gradle/libs.versions.toml
@@ -32,7 +32,7 @@ ossLicensesPlugin = "0.10.6"
placeholderMaterial = "1.0.1"
room = "2.6.0"
sentry-android = "7.17.0"
-work = "2.9.0"
+work = "2.10.0"
# Used indirecly in the build config -> Do not remove without double checking.
androidxComposeCompiler = "1.5.15"
From 98e93fd8c3f89848185971db10132a6beb88ffc6 Mon Sep 17 00:00:00 2001
From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com>
Date: Thu, 21 Nov 2024 08:35:09 +0100
Subject: [PATCH 11/22] Bump androidxDataStore from 1.0.0 to 1.1.1 (#131)
Signed-off-by: dependabot[bot]
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
---
gradle/libs.versions.toml | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml
index 7d4df60a4..e56b6383c 100644
--- a/gradle/libs.versions.toml
+++ b/gradle/libs.versions.toml
@@ -12,7 +12,7 @@ androidxComposeBom = "2023.10.01"
androidxLifecycle = "2.6.2"
androidxNavigation = "2.7.5"
androidGradlePlugin = "8.7.0"
-androidxDataStore = "1.0.0"
+androidxDataStore = "1.1.1"
androidxPaging = "3.2.1"
androidxPagingCompose = "3.2.1"
coil = "2.4.0"
From 9457e86129aaf326a8ab244f858c7f563bba97a8 Mon Sep 17 00:00:00 2001
From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com>
Date: Thu, 21 Nov 2024 08:48:14 +0100
Subject: [PATCH 12/22] Bump androidxPaging from 3.2.1 to 3.3.4 (#132)
Signed-off-by: dependabot[bot]
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: Martin Felber <45291671+FelberMartin@users.noreply.github.com>
---
gradle/libs.versions.toml | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml
index e56b6383c..5d0170b43 100644
--- a/gradle/libs.versions.toml
+++ b/gradle/libs.versions.toml
@@ -12,8 +12,8 @@ androidxComposeBom = "2023.10.01"
androidxLifecycle = "2.6.2"
androidxNavigation = "2.7.5"
androidGradlePlugin = "8.7.0"
+androidxPaging = "3.3.4"
androidxDataStore = "1.1.1"
-androidxPaging = "3.2.1"
androidxPagingCompose = "3.2.1"
coil = "2.4.0"
emoji2 = "1.4.0"
From 1e520ed93d5f337c06dedf47a376faa00352ecd4 Mon Sep 17 00:00:00 2001
From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com>
Date: Thu, 21 Nov 2024 12:01:43 +0100
Subject: [PATCH 13/22] Bump io.github.fornewid:placeholder-material3 from
1.0.1 to 2.0.0 (#130)
Signed-off-by: dependabot[bot]
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: Martin Felber
Co-authored-by: Martin Felber <45291671+FelberMartin@users.noreply.github.com>
---
.../core/test/test_setup/TestVariables.kt | 2 +-
.../ConversationMemberSettingsE2eTest.kt | 25 +++++++------------
gradle/libs.versions.toml | 4 +--
3 files changed, 12 insertions(+), 19 deletions(-)
diff --git a/core/core-test/src/main/kotlin/de/tum/informatics/www1/artemis/native_app/core/test/test_setup/TestVariables.kt b/core/core-test/src/main/kotlin/de/tum/informatics/www1/artemis/native_app/core/test/test_setup/TestVariables.kt
index dbc20f4f4..af73193f5 100644
--- a/core/core-test/src/main/kotlin/de/tum/informatics/www1/artemis/native_app/core/test/test_setup/TestVariables.kt
+++ b/core/core-test/src/main/kotlin/de/tum/informatics/www1/artemis/native_app/core/test/test_setup/TestVariables.kt
@@ -1,3 +1,3 @@
package de.tum.informatics.www1.artemis.native_app.core.test.test_setup
-val DefaultTimeoutMillis: Long get() = System.getenv("DEFAULT_TIMEOUT")?.toLong() ?: 10000L
\ No newline at end of file
+val DefaultTimeoutMillis: Long get() = System.getenv("DEFAULT_TIMEOUT")?.toLong() ?: 15000L
\ No newline at end of file
diff --git a/feature/metis/manage-conversations/src/test/kotlin/de/tum/informatics/www1/artemis/native_app/feature/metis/manageconversations/members/ConversationMemberSettingsE2eTest.kt b/feature/metis/manage-conversations/src/test/kotlin/de/tum/informatics/www1/artemis/native_app/feature/metis/manageconversations/members/ConversationMemberSettingsE2eTest.kt
index b51c8f4e9..18223e902 100644
--- a/feature/metis/manage-conversations/src/test/kotlin/de/tum/informatics/www1/artemis/native_app/feature/metis/manageconversations/members/ConversationMemberSettingsE2eTest.kt
+++ b/feature/metis/manage-conversations/src/test/kotlin/de/tum/informatics/www1/artemis/native_app/feature/metis/manageconversations/members/ConversationMemberSettingsE2eTest.kt
@@ -6,7 +6,6 @@ import androidx.compose.ui.Modifier
import androidx.compose.ui.test.ExperimentalTestApi
import androidx.compose.ui.test.assert
import androidx.compose.ui.test.hasAnyAncestor
-import androidx.compose.ui.test.hasAnyDescendant
import androidx.compose.ui.test.hasContentDescription
import androidx.compose.ui.test.hasTestTag
import androidx.compose.ui.test.hasText
@@ -15,10 +14,10 @@ import androidx.compose.ui.test.onNodeWithText
import androidx.compose.ui.test.performClick
import androidx.compose.ui.test.performScrollTo
import androidx.lifecycle.SavedStateHandle
-import de.tum.informatics.www1.artemis.native_app.core.common.test.EndToEndTest
import de.tum.informatics.www1.artemis.native_app.core.common.test.DefaultTestTimeoutMillis
-import de.tum.informatics.www1.artemis.native_app.core.test.test_setup.DefaultTimeoutMillis
+import de.tum.informatics.www1.artemis.native_app.core.common.test.EndToEndTest
import de.tum.informatics.www1.artemis.native_app.core.common.test.testServerUrl
+import de.tum.informatics.www1.artemis.native_app.core.test.test_setup.DefaultTimeoutMillis
import de.tum.informatics.www1.artemis.native_app.feature.login.test.user1Username
import de.tum.informatics.www1.artemis.native_app.feature.login.test.user2Username
import de.tum.informatics.www1.artemis.native_app.feature.login.test.user3Username
@@ -83,28 +82,24 @@ class ConversationMemberSettingsE2eTest : ConversationBaseTest() {
composeTestRule
.onNodeWithTag(testTagForMember(user1Username))
.performScrollTo()
- .assert(
- hasAnyDescendant(hasText(user1Username)) and hasAnyDescendant(
- hasContentDescription(context.getString(R.string.conversation_members_content_description_moderator))
- )
- )
+ .assert(hasText(user1Username))
+ .assert(hasContentDescription(context.getString(R.string.conversation_members_content_description_moderator))
+ )
composeTestRule
.onNodeWithTag(testTagForMember(user2Username))
.performScrollTo()
.assert(
- hasAnyDescendant(hasText(user2Username)) and !hasAnyDescendant(
+ hasText(user2Username) and !
hasContentDescription(context.getString(R.string.conversation_members_content_description_moderator))
- )
)
composeTestRule
.onNodeWithTag(testTagForMember(user2Username))
.performScrollTo()
.assert(
- hasAnyDescendant(hasText(user2Username)) and !hasAnyDescendant(
+ hasText(user2Username) and !
hasContentDescription(context.getString(R.string.conversation_members_content_description_moderator))
- )
)
}
@@ -186,10 +181,8 @@ class ConversationMemberSettingsE2eTest : ConversationBaseTest() {
)
.performClick()
- val isModeratorCheck = hasAnyDescendant(
- hasContentDescription(
- context.getString(R.string.conversation_members_content_description_moderator)
- )
+ val isModeratorCheck = hasContentDescription(
+ context.getString(R.string.conversation_members_content_description_moderator)
)
composeTestRule.waitUntilExactlyOneExists(
diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml
index 5d0170b43..fc668c6d8 100644
--- a/gradle/libs.versions.toml
+++ b/gradle/libs.versions.toml
@@ -8,7 +8,7 @@ accompanist = "0.30.1"
androidDesugarJdkLibs = "2.0.4"
androidxActivity = "1.8.1"
androidxAppCompat = "1.6.1"
-androidxComposeBom = "2023.10.01"
+androidxComposeBom = "2024.06.00"
androidxLifecycle = "2.6.2"
androidxNavigation = "2.7.5"
androidGradlePlugin = "8.7.0"
@@ -29,7 +29,7 @@ krossbow = "5.2.0"
markwon = "4.6.2"
mockk = "1.13.8"
ossLicensesPlugin = "0.10.6"
-placeholderMaterial = "1.0.1"
+placeholderMaterial = "2.0.0"
room = "2.6.0"
sentry-android = "7.17.0"
work = "2.10.0"
From fd3dfbcc5f87a11afcc34e89cae944d22ceb9412 Mon Sep 17 00:00:00 2001
From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com>
Date: Fri, 22 Nov 2024 07:52:54 +0100
Subject: [PATCH 14/22] Bump emoji2 from 1.4.0 to 1.5.0 (#138)
Signed-off-by: dependabot[bot]
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
---
gradle/libs.versions.toml | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml
index fc668c6d8..3f996b422 100644
--- a/gradle/libs.versions.toml
+++ b/gradle/libs.versions.toml
@@ -16,7 +16,7 @@ androidxPaging = "3.3.4"
androidxDataStore = "1.1.1"
androidxPagingCompose = "3.2.1"
coil = "2.4.0"
-emoji2 = "1.4.0"
+emoji2 = "1.5.0"
kotlin = "1.9.25"
kotlinxCoroutines = "1.9.0"
kotlinxDatetime = "0.4.0"
From 63e45eacff43cd2312187e34be5ed95bf8c79c70 Mon Sep 17 00:00:00 2001
From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com>
Date: Fri, 22 Nov 2024 07:53:48 +0100
Subject: [PATCH 15/22] Bump room from 2.6.0 to 2.6.1 (#136)
Signed-off-by: dependabot[bot]
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
---
gradle/libs.versions.toml | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml
index 3f996b422..560c66603 100644
--- a/gradle/libs.versions.toml
+++ b/gradle/libs.versions.toml
@@ -30,7 +30,7 @@ markwon = "4.6.2"
mockk = "1.13.8"
ossLicensesPlugin = "0.10.6"
placeholderMaterial = "2.0.0"
-room = "2.6.0"
+room = "2.6.1"
sentry-android = "7.17.0"
work = "2.10.0"
From b70948a4e3193acfb2ed645803e671b10a043009 Mon Sep 17 00:00:00 2001
From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com>
Date: Fri, 22 Nov 2024 14:23:28 +0100
Subject: [PATCH 16/22] Bump io.coil-kt:coil-compose from 2.4.0 to 2.7.0 (#137)
Signed-off-by: dependabot[bot]
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: Martin Felber <45291671+FelberMartin@users.noreply.github.com>
---
gradle/libs.versions.toml | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml
index 560c66603..e455469b8 100644
--- a/gradle/libs.versions.toml
+++ b/gradle/libs.versions.toml
@@ -15,7 +15,7 @@ androidGradlePlugin = "8.7.0"
androidxPaging = "3.3.4"
androidxDataStore = "1.1.1"
androidxPagingCompose = "3.2.1"
-coil = "2.4.0"
+coil = "2.7.0"
emoji2 = "1.5.0"
kotlin = "1.9.25"
kotlinxCoroutines = "1.9.0"
From 180670a4a6d3ba68134a605cd04405686ed3116d Mon Sep 17 00:00:00 2001
From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com>
Date: Sat, 23 Nov 2024 10:26:16 +0100
Subject: [PATCH 17/22] Bump ktor from 2.3.12 to 2.3.13 (#141)
Signed-off-by: dependabot[bot]
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
---
gradle/libs.versions.toml | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml
index e455469b8..196176725 100644
--- a/gradle/libs.versions.toml
+++ b/gradle/libs.versions.toml
@@ -24,7 +24,7 @@ kotlinxSerializationJson = "1.5.1"
koin = "3.5.3"
koinAndroidxCompose = "3.4.5"
kover = "0.7.2"
-ktor = "2.3.12"
+ktor = "2.3.13"
krossbow = "5.2.0"
markwon = "4.6.2"
mockk = "1.13.8"
From 11b990b1b530caa8c9ebc7c2740f4a467e7a76bb Mon Sep 17 00:00:00 2001
From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com>
Date: Sat, 23 Nov 2024 10:26:27 +0100
Subject: [PATCH 18/22] Bump com.google.android.gms:play-services-oss-licenses
from 17.0.1 to 17.1.0 (#142)
Signed-off-by: dependabot[bot]
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
---
gradle/libs.versions.toml | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml
index 196176725..7f58a8eab 100644
--- a/gradle/libs.versions.toml
+++ b/gradle/libs.versions.toml
@@ -123,7 +123,7 @@ noties-markwon-simple-ext = { group = "io.noties.markwon", name = "simple-ext",
noties-markwon-image-coil = { group = "io.noties.markwon", name = "image-coil", version.ref = "markwon" }
oss-licenses-plugin = { module = "com.google.android.gms:oss-licenses-plugin", version.ref = "ossLicensesPlugin" }
placeholder-material = { group = "io.github.fornewid", name = "placeholder-material3", version.ref = "placeholderMaterial" }
-play-services-oss-licences = { group = "com.google.android.gms", name = "play-services-oss-licenses", version = "17.0.1" }
+play-services-oss-licences = { group = "com.google.android.gms", name = "play-services-oss-licenses", version = "17.1.0" }
robolectric = { group = "org.robolectric", name = "robolectric", version = "4.13" }
sentry-android = { group = "io.sentry", name = "sentry-android", version.ref = "sentry-android" }
sentry-compose-android = { group = "io.sentry", name = "sentry-compose-android", version.ref = "sentry-android" }
From 372ba2382d95f15a1e073542466bfc3937c37127 Mon Sep 17 00:00:00 2001
From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com>
Date: Sat, 23 Nov 2024 10:26:37 +0100
Subject: [PATCH 19/22] Bump androidxLifecycle from 2.6.2 to 2.8.7 (#143)
Signed-off-by: dependabot[bot]
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
---
gradle/libs.versions.toml | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml
index 7f58a8eab..47c21103c 100644
--- a/gradle/libs.versions.toml
+++ b/gradle/libs.versions.toml
@@ -9,7 +9,7 @@ androidDesugarJdkLibs = "2.0.4"
androidxActivity = "1.8.1"
androidxAppCompat = "1.6.1"
androidxComposeBom = "2024.06.00"
-androidxLifecycle = "2.6.2"
+androidxLifecycle = "2.8.7"
androidxNavigation = "2.7.5"
androidGradlePlugin = "8.7.0"
androidxPaging = "3.3.4"
From a8098e9c25697660a502f64845c9fa027f9a0fb7 Mon Sep 17 00:00:00 2001
From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com>
Date: Sat, 23 Nov 2024 10:42:26 +0100
Subject: [PATCH 20/22] Bump com.google.firebase.appdistribution from 4.0.1 to
5.0.0 (#144)
Signed-off-by: dependabot[bot]
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: Martin Felber <45291671+FelberMartin@users.noreply.github.com>
---
gradle/libs.versions.toml | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml
index 47c21103c..57393bb45 100644
--- a/gradle/libs.versions.toml
+++ b/gradle/libs.versions.toml
@@ -139,6 +139,6 @@ android-library = { id = "com.android.library", version.ref = "androidGradlePlug
kotlin-jvm = { id = "org.jetbrains.kotlin.jvm", version.ref = "kotlin" }
kotlin-serialization = { id = "org.jetbrains.kotlin.plugin.serialization", version.ref = "kotlin" }
google-services = { id = "com.google.gms.google-services", version = "4.4.2" }
-google-firebase-appdistribution = { id = "com.google.firebase.appdistribution", version = "4.0.1" }
+google-firebase-appdistribution = { id = "com.google.firebase.appdistribution", version = "5.0.0" }
kover = { id = "org.jetbrains.kotlinx.kover", version.ref = "kover" }
google-ksp = { id = "com.google.devtools.ksp", version = "1.9.25-1.0.20" }
From 8f8393180bbac26ed15c9e7732701bf64b72a450 Mon Sep 17 00:00:00 2001
From: Julian Waluschyk
Date: Tue, 26 Nov 2024 14:15:21 +0100
Subject: [PATCH 21/22] minor changes
---
.../courseview/MessagingScreenshots.kt | 1 -
.../conversation/ui/chatlist/MetisChatList.kt | 50 +++++------
.../ui/chatlist/MetisPostListHandler.kt | 9 +-
.../conversation/ui/thread/MetisThreadUi.kt | 87 +++++++++----------
4 files changed, 70 insertions(+), 77 deletions(-)
diff --git a/feature/course-view/src/debug/kotlin/de/tum/informatics/www1/artemis/native_app/feature/courseview/MessagingScreenshots.kt b/feature/course-view/src/debug/kotlin/de/tum/informatics/www1/artemis/native_app/feature/courseview/MessagingScreenshots.kt
index cb0fc96cd..05ede95c2 100644
--- a/feature/course-view/src/debug/kotlin/de/tum/informatics/www1/artemis/native_app/feature/courseview/MessagingScreenshots.kt
+++ b/feature/course-view/src/debug/kotlin/de/tum/informatics/www1/artemis/native_app/feature/courseview/MessagingScreenshots.kt
@@ -247,7 +247,6 @@ fun `Metis - Conversation Channel`() {
listContentPadding = PaddingValues(),
serverUrl = "",
courseId = 0,
- markdownImageLoader = null,
state = rememberLazyListState(),
isReplyEnabled = true,
onCreatePost = { CompletableDeferred() },
diff --git a/feature/metis/conversation/src/main/kotlin/de/tum/informatics/www1/artemis/native_app/feature/metis/conversation/ui/chatlist/MetisChatList.kt b/feature/metis/conversation/src/main/kotlin/de/tum/informatics/www1/artemis/native_app/feature/metis/conversation/ui/chatlist/MetisChatList.kt
index b42c7d421..900010940 100644
--- a/feature/metis/conversation/src/main/kotlin/de/tum/informatics/www1/artemis/native_app/feature/metis/conversation/ui/chatlist/MetisChatList.kt
+++ b/feature/metis/conversation/src/main/kotlin/de/tum/informatics/www1/artemis/native_app/feature/metis/conversation/ui/chatlist/MetisChatList.kt
@@ -34,6 +34,7 @@ import androidx.compose.ui.text.style.TextAlign
import androidx.compose.ui.unit.dp
import androidx.paging.compose.LazyPagingItems
import coil.ImageLoader
+import de.tum.informatics.www1.artemis.native_app.core.ui.markdown.ProvideMarkwon
import de.tum.informatics.www1.artemis.native_app.feature.metis.conversation.R
import de.tum.informatics.www1.artemis.native_app.feature.metis.conversation.service.EmojiService
import de.tum.informatics.www1.artemis.native_app.feature.metis.conversation.service.MetisModificationFailure
@@ -91,7 +92,7 @@ internal fun MetisChatList(
val context = LocalContext.current
var imageLoader: ImageLoader? by remember { mutableStateOf(null) }
- LaunchedEffect(rememberCoroutineScope()) {
+ LaunchedEffect(true) {
imageLoader = viewModel.createMarkdownImageLoader(context).await()
}
@@ -101,28 +102,29 @@ internal fun MetisChatList(
}
}
- MetisChatList(
- modifier = modifier,
- initialReplyTextProvider = viewModel,
- posts = posts.asPostsDataState(),
- clientId = clientId,
- hasModerationRights = hasModerationRights,
- isAtLeastTutorInCourse = isAtLeastTutorInCourse,
- listContentPadding = listContentPadding,
- serverUrl = serverUrl,
- courseId = viewModel.courseId,
- markdownImageLoader = imageLoader,
- state = state,
- bottomItem = bottomItem,
- isReplyEnabled = isReplyEnabled,
- onCreatePost = viewModel::createPost,
- onEditPost = viewModel::editPost,
- onDeletePost = viewModel::deletePost,
- onRequestReactWithEmoji = viewModel::createOrDeleteReaction,
- onClickViewPost = onClickViewPost,
- onRequestRetrySend = viewModel::retryCreatePost,
- title = updatedTitle
- )
+ ProvideMarkwon(imageLoader) {
+ MetisChatList(
+ modifier = modifier,
+ initialReplyTextProvider = viewModel,
+ posts = posts.asPostsDataState(),
+ clientId = clientId,
+ hasModerationRights = hasModerationRights,
+ isAtLeastTutorInCourse = isAtLeastTutorInCourse,
+ listContentPadding = listContentPadding,
+ serverUrl = serverUrl,
+ courseId = viewModel.courseId,
+ state = state,
+ bottomItem = bottomItem,
+ isReplyEnabled = isReplyEnabled,
+ onCreatePost = viewModel::createPost,
+ onEditPost = viewModel::editPost,
+ onDeletePost = viewModel::deletePost,
+ onRequestReactWithEmoji = viewModel::createOrDeleteReaction,
+ onClickViewPost = onClickViewPost,
+ onRequestRetrySend = viewModel::retryCreatePost,
+ title = updatedTitle
+ )
+ }
}
@Composable
@@ -137,7 +139,6 @@ fun MetisChatList(
listContentPadding: PaddingValues,
serverUrl: String,
courseId: Long,
- markdownImageLoader: ImageLoader?,
state: LazyListState,
emojiService: EmojiService = koinInject(),
isReplyEnabled: Boolean,
@@ -172,7 +173,6 @@ fun MetisChatList(
itemCount = posts.itemCount,
order = DisplayPostOrder.REVERSED,
emojiService = emojiService,
- markdownImageLoader = markdownImageLoader,
bottomItem = bottomItem
) {
when (posts) {
diff --git a/feature/metis/conversation/src/main/kotlin/de/tum/informatics/www1/artemis/native_app/feature/metis/conversation/ui/chatlist/MetisPostListHandler.kt b/feature/metis/conversation/src/main/kotlin/de/tum/informatics/www1/artemis/native_app/feature/metis/conversation/ui/chatlist/MetisPostListHandler.kt
index c63ee04c0..b9d51bfd8 100644
--- a/feature/metis/conversation/src/main/kotlin/de/tum/informatics/www1/artemis/native_app/feature/metis/conversation/ui/chatlist/MetisPostListHandler.kt
+++ b/feature/metis/conversation/src/main/kotlin/de/tum/informatics/www1/artemis/native_app/feature/metis/conversation/ui/chatlist/MetisPostListHandler.kt
@@ -42,7 +42,6 @@ internal fun MetisPostListHandler(
itemCount: Int,
bottomItem: T?,
order: DisplayPostOrder,
- markdownImageLoader: ImageLoader?,
emojiService: EmojiService,
content: @Composable BoxScope.() -> Unit
) {
@@ -119,11 +118,9 @@ internal fun MetisPostListHandler(
PostArtemisMarkdownTransformer(serverUrl = strippedServerUrl, courseId = courseId)
}
- ProvideMarkwon(markdownImageLoader) {
- ProvideEmojis(emojiService) {
- CompositionLocalProvider(LocalMarkdownTransformer provides markdownTransformer) {
- content()
- }
+ ProvideEmojis(emojiService) {
+ CompositionLocalProvider(LocalMarkdownTransformer provides markdownTransformer) {
+ content()
}
}
}
diff --git a/feature/metis/conversation/src/main/kotlin/de/tum/informatics/www1/artemis/native_app/feature/metis/conversation/ui/thread/MetisThreadUi.kt b/feature/metis/conversation/src/main/kotlin/de/tum/informatics/www1/artemis/native_app/feature/metis/conversation/ui/thread/MetisThreadUi.kt
index f2f2f1656..90cb8b9e4 100644
--- a/feature/metis/conversation/src/main/kotlin/de/tum/informatics/www1/artemis/native_app/feature/metis/conversation/ui/thread/MetisThreadUi.kt
+++ b/feature/metis/conversation/src/main/kotlin/de/tum/informatics/www1/artemis/native_app/feature/metis/conversation/ui/thread/MetisThreadUi.kt
@@ -84,7 +84,7 @@ internal fun MetisThreadUi(
val context = LocalContext.current
var imageLoader: ImageLoader? by remember { mutableStateOf(null) }
- LaunchedEffect(rememberCoroutineScope()) {
+ LaunchedEffect(true) {
imageLoader = viewModel.createMarkdownImageLoader(context).await()
}
@@ -101,50 +101,51 @@ internal fun MetisThreadUi(
val conversationDataState by viewModel.conversation.collectAsState()
- MetisThreadUi(
- modifier = modifier,
- courseId = viewModel.courseId,
- initialReplyTextProvider = viewModel,
- conversationDataState = conversationDataState,
- postDataState = postDataState,
- isAtLeastTutorInCourse = isAtLeastTutorInCourse,
- hasModerationRights = hasModerationRights,
- listContentPadding = listContentPadding,
- serverUrl = serverUrl,
- emojiService = koinInject(),
- clientId = clientId,
- markdownImageLoader = imageLoader,
- onCreatePost = viewModel::createReply,
- onEditPost = { post, newText ->
- val parentPost = postDataState.orNull()
+ ProvideMarkwon(imageLoader) {
+ MetisThreadUi(
+ modifier = modifier,
+ courseId = viewModel.courseId,
+ initialReplyTextProvider = viewModel,
+ conversationDataState = conversationDataState,
+ postDataState = postDataState,
+ isAtLeastTutorInCourse = isAtLeastTutorInCourse,
+ hasModerationRights = hasModerationRights,
+ listContentPadding = listContentPadding,
+ serverUrl = serverUrl,
+ emojiService = koinInject(),
+ clientId = clientId,
+ onCreatePost = viewModel::createReply,
+ onEditPost = { post, newText ->
+ val parentPost = postDataState.orNull()
+
+ when (post) {
+ is AnswerPostPojo -> {
+ if (parentPost == null) CompletableDeferred(
+ MetisModificationFailure.UPDATE_POST
+ ) else viewModel.editAnswerPost(parentPost, post, newText)
+ }
- when (post) {
- is AnswerPostPojo -> {
+ is PostPojo -> viewModel.editPost(post, newText)
+ else -> throw NotImplementedError()
+ }
+ },
+ onResolvePost = { post ->
+ val parentPost = postDataState.orNull()
+
+ if (post is AnswerPostPojo) {
if (parentPost == null) CompletableDeferred(
MetisModificationFailure.UPDATE_POST
- ) else viewModel.editAnswerPost(parentPost, post, newText)
+ ) else viewModel.toggleResolvePost(parentPost, post)
+ } else {
+ throw NotImplementedError()
}
-
- is PostPojo -> viewModel.editPost(post, newText)
- else -> throw NotImplementedError()
- }
- },
- onResolvePost = { post ->
- val parentPost = postDataState.orNull()
-
- if (post is AnswerPostPojo) {
- if (parentPost == null) CompletableDeferred(
- MetisModificationFailure.UPDATE_POST
- ) else viewModel.toggleResolvePost(parentPost, post)
- } else {
- throw NotImplementedError()
- }
- },
- onDeletePost = viewModel::deletePost,
- onRequestReactWithEmoji = viewModel::createOrDeleteReaction,
- onRequestReload = viewModel::requestReload,
- onRequestRetrySend = viewModel::retryCreateReply
- )
+ },
+ onDeletePost = viewModel::deletePost,
+ onRequestReactWithEmoji = viewModel::createOrDeleteReaction,
+ onRequestReload = viewModel::requestReload,
+ onRequestRetrySend = viewModel::retryCreateReply
+ )
+ }
}
@Composable
@@ -159,7 +160,6 @@ internal fun MetisThreadUi(
listContentPadding: PaddingValues,
serverUrl: String,
emojiService: EmojiService,
- markdownImageLoader: ImageLoader?,
initialReplyTextProvider: InitialReplyTextProvider,
onCreatePost: () -> Deferred,
onEditPost: (IBasePost, String) -> Deferred,
@@ -206,7 +206,6 @@ internal fun MetisThreadUi(
state = listState,
itemCount = post.orderedAnswerPostings.size,
order = DisplayPostOrder.REGULAR,
- markdownImageLoader = markdownImageLoader,
emojiService = emojiService,
bottomItem = post.orderedAnswerPostings.lastOrNull()
) {
@@ -219,7 +218,6 @@ internal fun MetisThreadUi(
isAtLeastTutorInCourse = isAtLeastTutorInCourse,
listContentPadding = listContentPadding,
clientId = clientId,
- markdownImageLoader = markdownImageLoader,
onRequestReactWithEmoji = onRequestReactWithEmojiDelegate,
onRequestEdit = onEditPostDelegate,
onRequestDelete = onDeletePostDelegate,
@@ -255,7 +253,6 @@ private fun PostAndRepliesList(
isAtLeastTutorInCourse: Boolean,
listContentPadding: PaddingValues,
clientId: Long,
- markdownImageLoader: ImageLoader?,
onRequestEdit: (IBasePost) -> Unit,
onRequestDelete: (IBasePost) -> Unit,
onRequestResolve: (IBasePost) -> Unit,
From cbd528978977c7d2a51d840987118e99be1fb399 Mon Sep 17 00:00:00 2001
From: Julian Waluschyk
Date: Tue, 26 Nov 2024 15:43:40 +0100
Subject: [PATCH 22/22] minor changes
---
.../www1/artemis/native_app/core/ui/markdown/LocalMarkwon.kt | 1 -
.../native_app/core/ui/remote_images/DefaultImageProvider.kt | 1 -
2 files changed, 2 deletions(-)
diff --git a/core/ui/src/main/kotlin/de/tum/informatics/www1/artemis/native_app/core/ui/markdown/LocalMarkwon.kt b/core/ui/src/main/kotlin/de/tum/informatics/www1/artemis/native_app/core/ui/markdown/LocalMarkwon.kt
index 92473eb9b..ec5e2efd3 100644
--- a/core/ui/src/main/kotlin/de/tum/informatics/www1/artemis/native_app/core/ui/markdown/LocalMarkwon.kt
+++ b/core/ui/src/main/kotlin/de/tum/informatics/www1/artemis/native_app/core/ui/markdown/LocalMarkwon.kt
@@ -18,7 +18,6 @@ fun ProvideMarkwon(imageLoader: ImageLoader? = null, content: @Composable () ->
val imageWith = context.resources.displayMetrics.widthPixels
val markdownRender: Markwon = remember(imageLoader) {
- println(imageWith)
createMarkdownRender(context, imageLoader, imageWith)
}
diff --git a/core/ui/src/main/kotlin/de/tum/informatics/www1/artemis/native_app/core/ui/remote_images/DefaultImageProvider.kt b/core/ui/src/main/kotlin/de/tum/informatics/www1/artemis/native_app/core/ui/remote_images/DefaultImageProvider.kt
index ea4f89c7a..c581e33ae 100644
--- a/core/ui/src/main/kotlin/de/tum/informatics/www1/artemis/native_app/core/ui/remote_images/DefaultImageProvider.kt
+++ b/core/ui/src/main/kotlin/de/tum/informatics/www1/artemis/native_app/core/ui/remote_images/DefaultImageProvider.kt
@@ -27,7 +27,6 @@ class DefaultImageProvider : BaseImageProvider {
return builder.build()
}
-
override fun createImageLoader(
context: Context,
authorizationToken: String