diff --git a/features/healthchat/api/src/main/kotlin/io/element/android/features/healthchat/api/HealthChatProfileSectionRenderer.kt b/features/healthchat/api/src/main/kotlin/io/element/android/features/healthchat/api/HealthChatProfileSectionRenderer.kt
new file mode 100644
index 0000000000..971c459af4
--- /dev/null
+++ b/features/healthchat/api/src/main/kotlin/io/element/android/features/healthchat/api/HealthChatProfileSectionRenderer.kt
@@ -0,0 +1,28 @@
+/*
+ * Copyright (c) 2026 Novaloop AG
+ * Copyright (c) 2026 Element Creations Ltd.
+ *
+ * SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial.
+ * Please see LICENSE files in the repository root for full details.
+ */
+
+package io.element.android.features.healthchat.api
+
+import androidx.compose.runtime.Composable
+import androidx.compose.ui.Modifier
+import io.element.android.libraries.matrix.api.core.UserId
+
+/**
+ * Renders the HealthChat profile fields (specialty, practice, contact details, …) for a user.
+ *
+ * Injected into the upstream profile screens as a slot so the fork's only upstream diff is
+ * one defaulted parameter plus the injection (same pattern as `InvitePeopleRenderer`).
+ */
+interface HealthChatProfileSectionRenderer {
+ @Composable
+ fun Render(
+ userId: UserId,
+ isCurrentUser: Boolean,
+ modifier: Modifier,
+ )
+}
diff --git a/features/healthchat/api/src/main/res/values-de/strings_healthchat.xml b/features/healthchat/api/src/main/res/values-de/strings_healthchat.xml
index 4ed4da1bc8..3e6e8159cb 100644
--- a/features/healthchat/api/src/main/res/values-de/strings_healthchat.xml
+++ b/features/healthchat/api/src/main/res/values-de/strings_healthchat.xml
@@ -11,4 +11,13 @@
Ein Netzwerkfehler ist aufgetreten. Bitte prüfen Sie Ihre Verbindung und versuchen Sie es erneut.
Etwas ist schiefgelaufen. Bitte versuchen Sie es erneut.
+ Fachgebiet
+ Praxis / Unternehmen
+ Adresse
+ E-Mail (geschäftlich)
+ Telefon (geschäftlich)
+ Webseite
+ Weitere Infos / Qualifikationen
+ Die HealthChat-Profildaten konnten nicht geladen werden.
+ Profildetails sind sichtbar, sobald Ihr Konto freigegeben ist.
diff --git a/features/healthchat/api/src/main/res/values-fr/strings_healthchat.xml b/features/healthchat/api/src/main/res/values-fr/strings_healthchat.xml
index 8538d72b49..55ea83ac9c 100644
--- a/features/healthchat/api/src/main/res/values-fr/strings_healthchat.xml
+++ b/features/healthchat/api/src/main/res/values-fr/strings_healthchat.xml
@@ -11,4 +11,13 @@
Une erreur réseau est survenue. Veuillez vérifier votre connexion et réessayer.
Une erreur est survenue. Veuillez réessayer.
+ Spécialité
+ Cabinet / Entreprise
+ Adresse
+ E-mail (professionnel)
+ Téléphone (professionnel)
+ Site web
+ Informations complémentaires / qualifications
+ Les détails du profil HealthChat n’ont pas pu être chargés.
+ Les détails du profil seront visibles dès que votre compte aura été approuvé.
diff --git a/features/healthchat/api/src/main/res/values-it/strings_healthchat.xml b/features/healthchat/api/src/main/res/values-it/strings_healthchat.xml
index 7e43442ee6..31ffbf5810 100644
--- a/features/healthchat/api/src/main/res/values-it/strings_healthchat.xml
+++ b/features/healthchat/api/src/main/res/values-it/strings_healthchat.xml
@@ -11,4 +11,13 @@
Si è verificato un errore di rete. Controlla la connessione e riprova.
Qualcosa è andato storto. Riprova.
+ Specializzazione
+ Studio / Azienda
+ Indirizzo
+ E-mail (professionale)
+ Telefono (professionale)
+ Sito web
+ Ulteriori informazioni / qualifiche
+ Impossibile caricare i dettagli del profilo HealthChat.
+ I dettagli del profilo saranno visibili non appena il tuo account sarà stato approvato.
diff --git a/features/healthchat/api/src/main/res/values/strings_healthchat.xml b/features/healthchat/api/src/main/res/values/strings_healthchat.xml
index e210d59366..7de9716380 100644
--- a/features/healthchat/api/src/main/res/values/strings_healthchat.xml
+++ b/features/healthchat/api/src/main/res/values/strings_healthchat.xml
@@ -12,4 +12,13 @@
A network error occurred. Please check your connection and try again.
Something went wrong. Please try again.
+ Specialty
+ Practice / Company
+ Address
+ Email (business)
+ Phone (business)
+ Website
+ Further info / qualifications
+ The HealthChat profile details couldn’t be loaded.
+ Profile details become visible once your account has been approved.
diff --git a/features/healthchat/impl/build.gradle.kts b/features/healthchat/impl/build.gradle.kts
index f4eabb30b5..cea0f71299 100644
--- a/features/healthchat/impl/build.gradle.kts
+++ b/features/healthchat/impl/build.gradle.kts
@@ -54,11 +54,13 @@ dependencies {
implementation(projects.libraries.androidutils)
implementation(projects.libraries.architecture)
implementation(projects.libraries.core)
+ implementation(projects.libraries.designsystem)
implementation(projects.libraries.matrix.api)
implementation(projects.libraries.network)
implementation(projects.libraries.sessionStorage.api)
+ implementation(projects.libraries.uiStrings)
- testCommonDependencies(libs)
+ testCommonDependencies(libs, true)
testImplementation(libs.network.mockwebserver)
testImplementation(projects.features.healthchat.test)
testImplementation(projects.libraries.matrix.test)
diff --git a/features/healthchat/impl/src/main/kotlin/io/element/android/features/healthchat/impl/profile/section/DefaultHealthChatProfileSectionRenderer.kt b/features/healthchat/impl/src/main/kotlin/io/element/android/features/healthchat/impl/profile/section/DefaultHealthChatProfileSectionRenderer.kt
new file mode 100644
index 0000000000..f6ce372fb9
--- /dev/null
+++ b/features/healthchat/impl/src/main/kotlin/io/element/android/features/healthchat/impl/profile/section/DefaultHealthChatProfileSectionRenderer.kt
@@ -0,0 +1,37 @@
+/*
+ * Copyright (c) 2026 Novaloop AG
+ * Copyright (c) 2026 Element Creations Ltd.
+ *
+ * SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial.
+ * Please see LICENSE files in the repository root for full details.
+ */
+
+package io.element.android.features.healthchat.impl.profile.section
+
+import androidx.compose.runtime.Composable
+import androidx.compose.runtime.remember
+import androidx.compose.ui.Modifier
+import dev.zacsweers.metro.ContributesBinding
+import io.element.android.features.healthchat.api.HealthChatProfileSectionRenderer
+import io.element.android.libraries.di.SessionScope
+import io.element.android.libraries.matrix.api.core.UserId
+
+@ContributesBinding(SessionScope::class)
+class DefaultHealthChatProfileSectionRenderer(
+ private val presenterFactory: HealthChatProfileSectionPresenter.Factory,
+) : HealthChatProfileSectionRenderer {
+ @Composable
+ override fun Render(
+ userId: UserId,
+ isCurrentUser: Boolean,
+ modifier: Modifier,
+ ) {
+ val presenter = remember(userId, isCurrentUser) {
+ presenterFactory.create(userId = userId, isCurrentUser = isCurrentUser)
+ }
+ HealthChatProfileSectionView(
+ state = presenter.present(),
+ modifier = modifier,
+ )
+ }
+}
diff --git a/features/healthchat/impl/src/main/kotlin/io/element/android/features/healthchat/impl/profile/section/HealthChatProfileSectionEvents.kt b/features/healthchat/impl/src/main/kotlin/io/element/android/features/healthchat/impl/profile/section/HealthChatProfileSectionEvents.kt
new file mode 100644
index 0000000000..62cad15402
--- /dev/null
+++ b/features/healthchat/impl/src/main/kotlin/io/element/android/features/healthchat/impl/profile/section/HealthChatProfileSectionEvents.kt
@@ -0,0 +1,13 @@
+/*
+ * Copyright (c) 2026 Novaloop AG
+ * Copyright (c) 2026 Element Creations Ltd.
+ *
+ * SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial.
+ * Please see LICENSE files in the repository root for full details.
+ */
+
+package io.element.android.features.healthchat.impl.profile.section
+
+sealed interface HealthChatProfileSectionEvents {
+ data object Retry : HealthChatProfileSectionEvents
+}
diff --git a/features/healthchat/impl/src/main/kotlin/io/element/android/features/healthchat/impl/profile/section/HealthChatProfileSectionPresenter.kt b/features/healthchat/impl/src/main/kotlin/io/element/android/features/healthchat/impl/profile/section/HealthChatProfileSectionPresenter.kt
new file mode 100644
index 0000000000..dc6413dedd
--- /dev/null
+++ b/features/healthchat/impl/src/main/kotlin/io/element/android/features/healthchat/impl/profile/section/HealthChatProfileSectionPresenter.kt
@@ -0,0 +1,77 @@
+/*
+ * Copyright (c) 2026 Novaloop AG
+ * Copyright (c) 2026 Element Creations Ltd.
+ *
+ * SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial.
+ * Please see LICENSE files in the repository root for full details.
+ */
+
+package io.element.android.features.healthchat.impl.profile.section
+
+import androidx.compose.runtime.Composable
+import androidx.compose.runtime.LaunchedEffect
+import androidx.compose.runtime.collectAsState
+import androidx.compose.runtime.getValue
+import androidx.compose.runtime.mutableIntStateOf
+import androidx.compose.runtime.mutableStateOf
+import androidx.compose.runtime.remember
+import androidx.compose.runtime.saveable.rememberSaveable
+import androidx.compose.runtime.setValue
+import dev.zacsweers.metro.Assisted
+import dev.zacsweers.metro.AssistedFactory
+import dev.zacsweers.metro.AssistedInject
+import io.element.android.features.healthchat.api.HealthChatDirectoryService
+import io.element.android.features.healthchat.api.HealthChatMember
+import io.element.android.features.healthchat.api.HealthChatProfileRepository
+import io.element.android.libraries.architecture.AsyncData
+import io.element.android.libraries.architecture.Presenter
+import io.element.android.libraries.matrix.api.core.UserId
+
+@AssistedInject
+class HealthChatProfileSectionPresenter(
+ @Assisted private val userId: UserId,
+ @Assisted private val isCurrentUser: Boolean,
+ private val directoryService: HealthChatDirectoryService,
+ private val profileRepository: HealthChatProfileRepository,
+) : Presenter {
+ @AssistedFactory
+ interface Factory {
+ fun create(userId: UserId, isCurrentUser: Boolean): HealthChatProfileSectionPresenter
+ }
+
+ @Composable
+ override fun present(): HealthChatProfileSectionState {
+ var retryTrigger by rememberSaveable { mutableIntStateOf(0) }
+ // isCurrentUser is fixed for the lifetime of the presenter, so the branch is stable.
+ val profile = if (isCurrentUser) {
+ val ownProfile by profileRepository.ownProfile.collectAsState()
+ LaunchedEffect(retryTrigger) {
+ profileRepository.refreshOwnProfile()
+ }
+ ownProfile
+ } else {
+ var memberProfile by remember {
+ mutableStateOf>(AsyncData.Uninitialized)
+ }
+ LaunchedEffect(retryTrigger) {
+ memberProfile = AsyncData.Loading(memberProfile.dataOrNull())
+ directoryService.getMember(userId).fold(
+ onSuccess = { memberProfile = AsyncData.Success(it) },
+ onFailure = { memberProfile = AsyncData.Failure(it, memberProfile.dataOrNull()) },
+ )
+ }
+ memberProfile
+ }
+
+ fun handleEvents(event: HealthChatProfileSectionEvents) {
+ when (event) {
+ HealthChatProfileSectionEvents.Retry -> retryTrigger++
+ }
+ }
+
+ return HealthChatProfileSectionState(
+ profile = profile,
+ eventSink = ::handleEvents,
+ )
+ }
+}
diff --git a/features/healthchat/impl/src/main/kotlin/io/element/android/features/healthchat/impl/profile/section/HealthChatProfileSectionState.kt b/features/healthchat/impl/src/main/kotlin/io/element/android/features/healthchat/impl/profile/section/HealthChatProfileSectionState.kt
new file mode 100644
index 0000000000..1459a0100c
--- /dev/null
+++ b/features/healthchat/impl/src/main/kotlin/io/element/android/features/healthchat/impl/profile/section/HealthChatProfileSectionState.kt
@@ -0,0 +1,17 @@
+/*
+ * Copyright (c) 2026 Novaloop AG
+ * Copyright (c) 2026 Element Creations Ltd.
+ *
+ * SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial.
+ * Please see LICENSE files in the repository root for full details.
+ */
+
+package io.element.android.features.healthchat.impl.profile.section
+
+import io.element.android.features.healthchat.api.HealthChatMember
+import io.element.android.libraries.architecture.AsyncData
+
+data class HealthChatProfileSectionState(
+ val profile: AsyncData,
+ val eventSink: (HealthChatProfileSectionEvents) -> Unit,
+)
diff --git a/features/healthchat/impl/src/main/kotlin/io/element/android/features/healthchat/impl/profile/section/HealthChatProfileSectionStateProvider.kt b/features/healthchat/impl/src/main/kotlin/io/element/android/features/healthchat/impl/profile/section/HealthChatProfileSectionStateProvider.kt
new file mode 100644
index 0000000000..ebfa4e92af
--- /dev/null
+++ b/features/healthchat/impl/src/main/kotlin/io/element/android/features/healthchat/impl/profile/section/HealthChatProfileSectionStateProvider.kt
@@ -0,0 +1,85 @@
+/*
+ * Copyright (c) 2026 Novaloop AG
+ * Copyright (c) 2026 Element Creations Ltd.
+ *
+ * SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial.
+ * Please see LICENSE files in the repository root for full details.
+ */
+
+package io.element.android.features.healthchat.impl.profile.section
+
+import androidx.compose.ui.tooling.preview.PreviewParameterProvider
+import io.element.android.features.healthchat.api.HealthChatApiException
+import io.element.android.features.healthchat.api.HealthChatMember
+import io.element.android.libraries.architecture.AsyncData
+import io.element.android.libraries.matrix.api.core.UserId
+
+open class HealthChatProfileSectionStateProvider : PreviewParameterProvider {
+ override val values: Sequence
+ get() = sequenceOf(
+ aHealthChatProfileSectionState(profile = AsyncData.Success(aProfileSectionMember())),
+ aHealthChatProfileSectionState(
+ profile = AsyncData.Success(
+ aProfileSectionMember(
+ specialty = "Allgemeinmedizin",
+ practiceName = null,
+ businessCity = null,
+ businessEmail = null,
+ businessTel = null,
+ street = null,
+ houseNumber = null,
+ postalCode = null,
+ website = null,
+ furtherInfo = null,
+ )
+ )
+ ),
+ aHealthChatProfileSectionState(profile = AsyncData.Loading()),
+ aHealthChatProfileSectionState(profile = AsyncData.Failure(HealthChatApiException.NotFound(null))),
+ aHealthChatProfileSectionState(profile = AsyncData.Failure(HealthChatApiException.NotApproved(null))),
+ aHealthChatProfileSectionState(
+ profile = AsyncData.Failure(HealthChatApiException.Network(RuntimeException("no network")))
+ ),
+ )
+}
+
+fun aHealthChatProfileSectionState(
+ profile: AsyncData = AsyncData.Uninitialized,
+ eventSink: (HealthChatProfileSectionEvents) -> Unit = {},
+) = HealthChatProfileSectionState(
+ profile = profile,
+ eventSink = eventSink,
+)
+
+fun aProfileSectionMember(
+ userId: UserId = UserId("@erika.muster:healthchat.ch"),
+ displayName: String? = "Dr. med. Erika Muster",
+ specialty: String? = "Allgemeinmedizin",
+ practiceName: String? = "Praxis Muster",
+ businessCity: String? = "Zürich",
+ businessEmail: String? = "praxis@muster.ch",
+ businessTel: String? = "+41 44 123 45 67",
+ street: String? = "Musterstrasse",
+ houseNumber: String? = "12",
+ postalCode: String? = "8001",
+ website: String? = "https://praxis-muster.ch",
+ furtherInfo: String? = "FMH Allgemeine Innere Medizin",
+) = HealthChatMember(
+ userId = userId,
+ displayName = displayName,
+ avatarUrl = null,
+ title = "Dr. med.",
+ firstName = "Erika",
+ lastName = "Muster",
+ specialty = specialty,
+ practiceName = practiceName,
+ businessCity = businessCity,
+ furtherInfo = furtherInfo,
+ businessEmail = businessEmail,
+ businessTel = businessTel,
+ street = street,
+ houseNumber = houseNumber,
+ postalCode = postalCode,
+ website = website,
+ isApproved = true,
+)
diff --git a/features/healthchat/impl/src/main/kotlin/io/element/android/features/healthchat/impl/profile/section/HealthChatProfileSectionView.kt b/features/healthchat/impl/src/main/kotlin/io/element/android/features/healthchat/impl/profile/section/HealthChatProfileSectionView.kt
new file mode 100644
index 0000000000..2b85e502c9
--- /dev/null
+++ b/features/healthchat/impl/src/main/kotlin/io/element/android/features/healthchat/impl/profile/section/HealthChatProfileSectionView.kt
@@ -0,0 +1,212 @@
+/*
+ * Copyright (c) 2026 Novaloop AG
+ * Copyright (c) 2026 Element Creations Ltd.
+ *
+ * SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial.
+ * Please see LICENSE files in the repository root for full details.
+ */
+
+package io.element.android.features.healthchat.impl.profile.section
+
+import androidx.activity.compose.LocalActivity
+import androidx.compose.foundation.layout.Column
+import androidx.compose.foundation.layout.fillMaxWidth
+import androidx.compose.foundation.layout.padding
+import androidx.compose.runtime.Composable
+import androidx.compose.ui.Modifier
+import androidx.compose.ui.graphics.vector.ImageVector
+import androidx.compose.ui.platform.LocalContext
+import androidx.compose.ui.res.stringResource
+import androidx.compose.ui.tooling.preview.PreviewParameter
+import androidx.compose.ui.unit.dp
+import io.element.android.compound.theme.ElementTheme
+import io.element.android.compound.tokens.generated.CompoundIcons
+import io.element.android.features.healthchat.api.HealthChatApiException
+import io.element.android.features.healthchat.api.HealthChatMember
+import io.element.android.features.healthchat.api.HealthChatStrings
+import io.element.android.libraries.androidutils.browser.openUrlInChromeCustomTab
+import io.element.android.libraries.androidutils.system.openUrlInExternalApp
+import io.element.android.libraries.architecture.AsyncData
+import io.element.android.libraries.designsystem.components.list.ListItemContent
+import io.element.android.libraries.designsystem.preview.ElementPreview
+import io.element.android.libraries.designsystem.preview.PreviewsDayNight
+import io.element.android.libraries.designsystem.theme.components.IconSource
+import io.element.android.libraries.designsystem.theme.components.ListItem
+import io.element.android.libraries.designsystem.theme.components.Text
+import io.element.android.libraries.designsystem.theme.components.TextButton
+import io.element.android.libraries.ui.strings.CommonStrings
+
+/**
+ * The HealthChat profile fields block rendered on the profile screens.
+ *
+ * Error behaviour is inline degradation: the host screen's primary job is Matrix identity,
+ * so loading renders nothing, a missing directory record ([HealthChatApiException.NotFound],
+ * e.g. system accounts) renders nothing, an unapproved caller gets a single muted hint, and
+ * any other failure gets a single retry row. Stale data is never shown.
+ */
+@Composable
+fun HealthChatProfileSectionView(
+ state: HealthChatProfileSectionState,
+ modifier: Modifier = Modifier,
+) {
+ when (val profile = state.profile) {
+ AsyncData.Uninitialized,
+ is AsyncData.Loading -> Unit
+ is AsyncData.Failure -> when (profile.error) {
+ is HealthChatApiException.NotFound -> Unit
+ is HealthChatApiException.NotApproved -> NotApprovedHint(modifier = modifier)
+ else -> LoadingErrorRow(
+ onRetry = { state.eventSink(HealthChatProfileSectionEvents.Retry) },
+ modifier = modifier,
+ )
+ }
+ is AsyncData.Success -> ProfileFieldList(
+ member = profile.data,
+ modifier = modifier,
+ )
+ }
+}
+
+@Composable
+private fun ProfileFieldList(
+ member: HealthChatMember,
+ modifier: Modifier = Modifier,
+) {
+ val activity = LocalActivity.current
+ val context = LocalContext.current
+ val darkTheme = ElementTheme.isLightTheme.not()
+ Column(modifier = modifier.fillMaxWidth()) {
+ member.specialty?.let {
+ ProfileFieldRow(
+ value = it,
+ labelRes = HealthChatStrings.healthchat_field_specialty,
+ icon = CompoundIcons.Info(),
+ )
+ }
+ member.practiceName?.let {
+ ProfileFieldRow(
+ value = it,
+ labelRes = HealthChatStrings.healthchat_field_practice_name,
+ icon = CompoundIcons.Company(),
+ )
+ }
+ member.formattedAddress()?.let {
+ ProfileFieldRow(
+ value = it,
+ labelRes = HealthChatStrings.healthchat_field_address,
+ icon = CompoundIcons.LocationPin(),
+ )
+ }
+ member.businessEmail?.let {
+ ProfileFieldRow(
+ value = it,
+ labelRes = HealthChatStrings.healthchat_field_business_email,
+ icon = CompoundIcons.Email(),
+ onClick = { context.openUrlInExternalApp("mailto:$it") },
+ )
+ }
+ member.businessTel?.let {
+ ProfileFieldRow(
+ value = it,
+ labelRes = HealthChatStrings.healthchat_field_business_tel,
+ icon = CompoundIcons.VoiceCall(),
+ onClick = { context.openUrlInExternalApp("tel:$it") },
+ )
+ }
+ member.website?.let { website ->
+ ProfileFieldRow(
+ value = website,
+ labelRes = HealthChatStrings.healthchat_field_website,
+ icon = CompoundIcons.WebBrowser(),
+ onClick = {
+ val url = website.withHttpScheme()
+ if (activity != null) {
+ activity.openUrlInChromeCustomTab(null, darkTheme, url)
+ } else {
+ context.openUrlInExternalApp(url)
+ }
+ },
+ )
+ }
+ member.furtherInfo?.let {
+ ProfileFieldRow(
+ value = it,
+ labelRes = HealthChatStrings.healthchat_field_further_info,
+ icon = CompoundIcons.Document(),
+ )
+ }
+ }
+}
+
+@Composable
+private fun ProfileFieldRow(
+ value: String,
+ labelRes: Int,
+ icon: ImageVector,
+ modifier: Modifier = Modifier,
+ onClick: (() -> Unit)? = null,
+) {
+ ListItem(
+ headlineContent = { Text(value) },
+ supportingContent = { Text(stringResource(labelRes)) },
+ leadingContent = ListItemContent.Icon(IconSource.Vector(icon)),
+ onClick = onClick,
+ modifier = modifier,
+ )
+}
+
+@Composable
+private fun NotApprovedHint(
+ modifier: Modifier = Modifier,
+) {
+ Text(
+ text = stringResource(HealthChatStrings.healthchat_profile_not_approved_hint),
+ style = ElementTheme.typography.fontBodyMdRegular,
+ color = ElementTheme.colors.textSecondary,
+ modifier = modifier
+ .fillMaxWidth()
+ .padding(horizontal = 16.dp, vertical = 8.dp),
+ )
+}
+
+@Composable
+private fun LoadingErrorRow(
+ onRetry: () -> Unit,
+ modifier: Modifier = Modifier,
+) {
+ ListItem(
+ headlineContent = { Text(stringResource(HealthChatStrings.healthchat_profile_error_loading)) },
+ leadingContent = ListItemContent.Icon(IconSource.Vector(CompoundIcons.Error())),
+ trailingContent = ListItemContent.Custom {
+ TextButton(
+ text = stringResource(CommonStrings.action_retry),
+ onClick = onRetry,
+ )
+ },
+ modifier = modifier,
+ )
+}
+
+/**
+ * "Musterstrasse 12\n8001 Zürich" — blank parts are dropped, null when nothing is set.
+ */
+private fun HealthChatMember.formattedAddress(): String? {
+ val streetLine = listOfNotNull(street, houseNumber).joinToString(" ")
+ val cityLine = listOfNotNull(postalCode, businessCity).joinToString(" ")
+ return listOf(streetLine, cityLine)
+ .filter { it.isNotBlank() }
+ .joinToString("\n")
+ .takeIf { it.isNotBlank() }
+}
+
+private fun String.withHttpScheme(): String {
+ return if (startsWith("http://") || startsWith("https://")) this else "https://$this"
+}
+
+@PreviewsDayNight
+@Composable
+internal fun HealthChatProfileSectionViewPreview(
+ @PreviewParameter(HealthChatProfileSectionStateProvider::class) state: HealthChatProfileSectionState
+) = ElementPreview {
+ HealthChatProfileSectionView(state = state)
+}
diff --git a/features/healthchat/impl/src/test/kotlin/io/element/android/features/healthchat/impl/profile/section/HealthChatProfileSectionPresenterTest.kt b/features/healthchat/impl/src/test/kotlin/io/element/android/features/healthchat/impl/profile/section/HealthChatProfileSectionPresenterTest.kt
new file mode 100644
index 0000000000..0fca5457d5
--- /dev/null
+++ b/features/healthchat/impl/src/test/kotlin/io/element/android/features/healthchat/impl/profile/section/HealthChatProfileSectionPresenterTest.kt
@@ -0,0 +1,129 @@
+/*
+ * Copyright (c) 2026 Novaloop AG
+ * Copyright (c) 2026 Element Creations Ltd.
+ *
+ * SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial.
+ * Please see LICENSE files in the repository root for full details.
+ */
+
+package io.element.android.features.healthchat.impl.profile.section
+
+import com.google.common.truth.Truth.assertThat
+import io.element.android.features.healthchat.api.HealthChatApiException
+import io.element.android.features.healthchat.api.HealthChatDirectoryService
+import io.element.android.features.healthchat.api.HealthChatMember
+import io.element.android.features.healthchat.api.HealthChatProfileRepository
+import io.element.android.features.healthchat.test.FakeHealthChatDirectoryService
+import io.element.android.features.healthchat.test.FakeHealthChatProfileRepository
+import io.element.android.features.healthchat.test.aHealthChatMember
+import io.element.android.libraries.architecture.AsyncData
+import io.element.android.libraries.matrix.api.core.UserId
+import io.element.android.libraries.matrix.test.A_USER_ID
+import io.element.android.tests.testutils.WarmUpRule
+import io.element.android.tests.testutils.consumeItemsUntilPredicate
+import io.element.android.tests.testutils.lambda.lambdaRecorder
+import io.element.android.tests.testutils.lambda.value
+import io.element.android.tests.testutils.test
+import kotlinx.coroutines.test.runTest
+import org.junit.Rule
+import org.junit.Test
+import java.io.IOException
+
+class HealthChatProfileSectionPresenterTest {
+ @get:Rule
+ val warmUpRule = WarmUpRule()
+
+ @Test
+ fun `present - own profile is loaded through the repository`() = runTest {
+ val member = aHealthChatMember()
+ val refreshLambda = lambdaRecorder> { Result.success(member) }
+ val repository = FakeHealthChatProfileRepository(
+ refreshOwnProfileLambda = { refreshLambda() },
+ )
+ val presenter = createPresenter(isCurrentUser = true, profileRepository = repository)
+ presenter.test {
+ val state = consumeItemsUntilPredicate { it.profile is AsyncData.Success }.last()
+ assertThat(state.profile).isEqualTo(AsyncData.Success(member))
+ refreshLambda.assertions().isCalledOnce()
+ }
+ }
+
+ @Test
+ fun `present - another member is loaded through the directory service`() = runTest {
+ val member = aHealthChatMember(userId = A_USER_ID)
+ val getMemberLambda = lambdaRecorder> { Result.success(member) }
+ val directoryService = FakeHealthChatDirectoryService(
+ getMemberLambda = { getMemberLambda(it) },
+ )
+ val presenter = createPresenter(isCurrentUser = false, directoryService = directoryService)
+ presenter.test {
+ val state = consumeItemsUntilPredicate { it.profile is AsyncData.Success }.last()
+ assertThat(state.profile).isEqualTo(AsyncData.Success(member))
+ getMemberLambda.assertions().isCalledOnce().with(value(A_USER_ID))
+ }
+ }
+
+ @Test
+ fun `present - a NotFound failure is exposed as such`() = runTest {
+ val error = HealthChatApiException.NotFound(null)
+ val directoryService = FakeHealthChatDirectoryService(
+ getMemberLambda = { Result.failure(error) },
+ )
+ val presenter = createPresenter(isCurrentUser = false, directoryService = directoryService)
+ presenter.test {
+ val state = consumeItemsUntilPredicate { it.profile is AsyncData.Failure }.last()
+ assertThat((state.profile as AsyncData.Failure).error).isEqualTo(error)
+ }
+ }
+
+ @Test
+ fun `present - a NotApproved failure is exposed as such`() = runTest {
+ val error = HealthChatApiException.NotApproved("Konto wird geprüft")
+ val directoryService = FakeHealthChatDirectoryService(
+ getMemberLambda = { Result.failure(error) },
+ )
+ val presenter = createPresenter(isCurrentUser = false, directoryService = directoryService)
+ presenter.test {
+ val state = consumeItemsUntilPredicate { it.profile is AsyncData.Failure }.last()
+ assertThat((state.profile as AsyncData.Failure).error).isEqualTo(error)
+ }
+ }
+
+ @Test
+ fun `present - Retry loads the member again after a failure`() = runTest {
+ val member = aHealthChatMember(userId = A_USER_ID)
+ var callCount = 0
+ val directoryService = FakeHealthChatDirectoryService(
+ getMemberLambda = {
+ callCount++
+ if (callCount == 1) {
+ Result.failure(HealthChatApiException.Network(IOException("no network")))
+ } else {
+ Result.success(member)
+ }
+ },
+ )
+ val presenter = createPresenter(isCurrentUser = false, directoryService = directoryService)
+ presenter.test {
+ val failedState = consumeItemsUntilPredicate { it.profile is AsyncData.Failure }.last()
+ failedState.eventSink(HealthChatProfileSectionEvents.Retry)
+ val state = consumeItemsUntilPredicate { it.profile is AsyncData.Success }.last()
+ assertThat(state.profile).isEqualTo(AsyncData.Success(member))
+ assertThat(callCount).isEqualTo(2)
+ }
+ }
+
+ private fun createPresenter(
+ isCurrentUser: Boolean,
+ userId: UserId = A_USER_ID,
+ directoryService: HealthChatDirectoryService = FakeHealthChatDirectoryService(),
+ profileRepository: HealthChatProfileRepository = FakeHealthChatProfileRepository(),
+ ): HealthChatProfileSectionPresenter {
+ return HealthChatProfileSectionPresenter(
+ userId = userId,
+ isCurrentUser = isCurrentUser,
+ directoryService = directoryService,
+ profileRepository = profileRepository,
+ )
+ }
+}
diff --git a/features/healthchat/impl/src/test/kotlin/io/element/android/features/healthchat/impl/profile/section/HealthChatProfileSectionViewTest.kt b/features/healthchat/impl/src/test/kotlin/io/element/android/features/healthchat/impl/profile/section/HealthChatProfileSectionViewTest.kt
new file mode 100644
index 0000000000..68aece4b41
--- /dev/null
+++ b/features/healthchat/impl/src/test/kotlin/io/element/android/features/healthchat/impl/profile/section/HealthChatProfileSectionViewTest.kt
@@ -0,0 +1,154 @@
+/*
+ * Copyright (c) 2026 Novaloop AG
+ * Copyright (c) 2026 Element Creations Ltd.
+ *
+ * SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial.
+ * Please see LICENSE files in the repository root for full details.
+ */
+
+@file:OptIn(ExperimentalTestApi::class)
+
+package io.element.android.features.healthchat.impl.profile.section
+
+import android.content.Intent
+import androidx.activity.ComponentActivity
+import androidx.compose.ui.test.ExperimentalTestApi
+import androidx.compose.ui.test.onNodeWithText
+import androidx.compose.ui.test.performClick
+import androidx.compose.ui.test.v2.runAndroidComposeUiTest
+import com.google.common.truth.Truth.assertThat
+import io.element.android.features.healthchat.api.HealthChatApiException
+import io.element.android.libraries.architecture.AsyncData
+import io.element.android.libraries.ui.strings.CommonStrings
+import io.element.android.tests.testutils.EventsRecorder
+import io.element.android.tests.testutils.clickOn
+import io.element.android.tests.testutils.robolectric.RobolectricTest
+import org.junit.Test
+import org.robolectric.RuntimeEnvironment
+import org.robolectric.Shadows.shadowOf
+
+class HealthChatProfileSectionViewTest : RobolectricTest() {
+ @Test
+ fun `a loaded profile renders its fields with values`() = runAndroidComposeUiTest {
+ val eventsRecorder = EventsRecorder(expectEvents = false)
+ setContent {
+ HealthChatProfileSectionView(
+ state = aHealthChatProfileSectionState(
+ profile = AsyncData.Success(aProfileSectionMember()),
+ eventSink = eventsRecorder,
+ ),
+ )
+ }
+ onNodeWithText("Allgemeinmedizin").assertExists()
+ onNodeWithText("Praxis Muster").assertExists()
+ onNodeWithText("Musterstrasse 12\n8001 Zürich").assertExists()
+ onNodeWithText("praxis@muster.ch").assertExists()
+ onNodeWithText("+41 44 123 45 67").assertExists()
+ onNodeWithText("https://praxis-muster.ch").assertExists()
+ onNodeWithText("FMH Allgemeine Innere Medizin").assertExists()
+ }
+
+ @Test
+ fun `empty fields are omitted`() = runAndroidComposeUiTest {
+ val eventsRecorder = EventsRecorder(expectEvents = false)
+ setContent {
+ HealthChatProfileSectionView(
+ state = aHealthChatProfileSectionState(
+ profile = AsyncData.Success(
+ aProfileSectionMember(
+ practiceName = null,
+ businessEmail = null,
+ businessTel = null,
+ street = null,
+ houseNumber = null,
+ postalCode = null,
+ businessCity = null,
+ website = null,
+ furtherInfo = null,
+ )
+ ),
+ eventSink = eventsRecorder,
+ ),
+ )
+ }
+ onNodeWithText("Allgemeinmedizin").assertExists()
+ onNodeWithText("Praxis Muster").assertDoesNotExist()
+ }
+
+ @Test
+ fun `clicking the email row opens a mailto intent`() = runAndroidComposeUiTest {
+ val eventsRecorder = EventsRecorder(expectEvents = false)
+ setContent {
+ HealthChatProfileSectionView(
+ state = aHealthChatProfileSectionState(
+ profile = AsyncData.Success(aProfileSectionMember()),
+ eventSink = eventsRecorder,
+ ),
+ )
+ }
+ onNodeWithText("praxis@muster.ch").performClick()
+ val intent = shadowOf(RuntimeEnvironment.getApplication()).nextStartedActivity
+ assertThat(intent.action).isEqualTo(Intent.ACTION_VIEW)
+ assertThat(intent.data.toString()).isEqualTo("mailto:praxis@muster.ch")
+ }
+
+ @Test
+ fun `clicking the phone row opens a tel intent`() = runAndroidComposeUiTest {
+ val eventsRecorder = EventsRecorder(expectEvents = false)
+ setContent {
+ HealthChatProfileSectionView(
+ state = aHealthChatProfileSectionState(
+ profile = AsyncData.Success(aProfileSectionMember()),
+ eventSink = eventsRecorder,
+ ),
+ )
+ }
+ onNodeWithText("+41 44 123 45 67").performClick()
+ val intent = shadowOf(RuntimeEnvironment.getApplication()).nextStartedActivity
+ assertThat(intent.dataString).isEqualTo("tel:+41 44 123 45 67")
+ }
+
+ @Test
+ fun `a loading state renders nothing`() = runAndroidComposeUiTest {
+ val eventsRecorder = EventsRecorder(expectEvents = false)
+ setContent {
+ HealthChatProfileSectionView(
+ state = aHealthChatProfileSectionState(
+ profile = AsyncData.Loading(),
+ eventSink = eventsRecorder,
+ ),
+ )
+ }
+ onNodeWithText("Allgemeinmedizin").assertDoesNotExist()
+ }
+
+ @Test
+ fun `a NotFound failure renders nothing`() = runAndroidComposeUiTest {
+ val eventsRecorder = EventsRecorder(expectEvents = false)
+ val activity = requireNotNull(activity)
+ setContent {
+ HealthChatProfileSectionView(
+ state = aHealthChatProfileSectionState(
+ profile = AsyncData.Failure(HealthChatApiException.NotFound(null)),
+ eventSink = eventsRecorder,
+ ),
+ )
+ }
+ onNodeWithText(activity.getString(CommonStrings.action_retry)).assertDoesNotExist()
+ }
+
+ @Test
+ fun `an error state shows a retry row which emits Retry`() = runAndroidComposeUiTest {
+ val eventsRecorder = EventsRecorder()
+ setContent {
+ HealthChatProfileSectionView(
+ state = aHealthChatProfileSectionState(
+ profile = AsyncData.Failure(HealthChatApiException.Network(RuntimeException("boom"))),
+ eventSink = eventsRecorder,
+ ),
+ )
+ }
+ clickOn(CommonStrings.action_retry)
+ eventsRecorder.assertSingle(HealthChatProfileSectionEvents.Retry)
+ }
+}
diff --git a/features/roomdetails/impl/build.gradle.kts b/features/roomdetails/impl/build.gradle.kts
index b8aa939015..3620860f22 100644
--- a/features/roomdetails/impl/build.gradle.kts
+++ b/features/roomdetails/impl/build.gradle.kts
@@ -41,6 +41,8 @@ dependencies {
api(projects.features.roomdetails.api)
implementation(libs.coil.compose)
implementation(projects.features.call.api)
+ implementation(projects.features.healthchat.api)
+ implementation(projects.features.startchat.api)
implementation(projects.features.leaveroom.api)
implementation(projects.features.userprofile.shared)
implementation(projects.services.analytics.compose)
diff --git a/features/roomdetails/impl/src/main/kotlin/io/element/android/features/roomdetails/impl/members/details/RoomMemberDetailsNode.kt b/features/roomdetails/impl/src/main/kotlin/io/element/android/features/roomdetails/impl/members/details/RoomMemberDetailsNode.kt
index ccf2f28ab5..210348e1fb 100644
--- a/features/roomdetails/impl/src/main/kotlin/io/element/android/features/roomdetails/impl/members/details/RoomMemberDetailsNode.kt
+++ b/features/roomdetails/impl/src/main/kotlin/io/element/android/features/roomdetails/impl/members/details/RoomMemberDetailsNode.kt
@@ -19,6 +19,7 @@ import dev.zacsweers.metro.Assisted
import dev.zacsweers.metro.AssistedInject
import im.vector.app.features.analytics.plan.MobileScreen
import io.element.android.annotations.ContributesNode
+import io.element.android.features.healthchat.api.HealthChatProfileSectionRenderer
import io.element.android.features.userprofile.shared.UserProfileNodeHelper
import io.element.android.features.userprofile.shared.UserProfileView
import io.element.android.libraries.architecture.NodeInputs
@@ -38,6 +39,8 @@ class RoomMemberDetailsNode(
private val analyticsService: AnalyticsService,
private val permalinkBuilder: PermalinkBuilder,
presenterFactory: RoomMemberDetailsPresenter.Factory,
+ // HealthChat fork: renders the extended profile fields.
+ private val healthChatProfileSectionRenderer: HealthChatProfileSectionRenderer,
) : Node(buildContext, plugins = plugins) {
data class RoomMemberDetailsInput(
val roomMemberId: UserId,
@@ -83,6 +86,9 @@ class RoomMemberDetailsNode(
onStartCall = ::onStartCall,
openAvatarPreview = callback::navigateToAvatarPreview,
onVerifyClick = callback::startVerifyUserFlow,
+ healthChatProfileSection = { userId, isCurrentUser ->
+ healthChatProfileSectionRenderer.Render(userId, isCurrentUser, Modifier)
+ },
)
}
}
diff --git a/features/userprofile/impl/build.gradle.kts b/features/userprofile/impl/build.gradle.kts
index b04ca61a23..8ca67b35b2 100644
--- a/features/userprofile/impl/build.gradle.kts
+++ b/features/userprofile/impl/build.gradle.kts
@@ -35,6 +35,7 @@ dependencies {
implementation(projects.libraries.mediaviewer.api)
implementation(projects.features.call.api)
implementation(projects.features.enterprise.api)
+ implementation(projects.features.healthchat.api)
implementation(projects.features.verifysession.api)
api(projects.features.userprofile.api)
api(projects.features.userprofile.shared)
diff --git a/features/userprofile/impl/src/main/kotlin/io/element/android/features/userprofile/impl/root/UserProfileNode.kt b/features/userprofile/impl/src/main/kotlin/io/element/android/features/userprofile/impl/root/UserProfileNode.kt
index 71f95a2e84..36e9f55104 100644
--- a/features/userprofile/impl/src/main/kotlin/io/element/android/features/userprofile/impl/root/UserProfileNode.kt
+++ b/features/userprofile/impl/src/main/kotlin/io/element/android/features/userprofile/impl/root/UserProfileNode.kt
@@ -19,6 +19,7 @@ import dev.zacsweers.metro.Assisted
import dev.zacsweers.metro.AssistedInject
import im.vector.app.features.analytics.plan.MobileScreen
import io.element.android.annotations.ContributesNode
+import io.element.android.features.healthchat.api.HealthChatProfileSectionRenderer
import io.element.android.features.userprofile.shared.UserProfileNodeHelper
import io.element.android.features.userprofile.shared.UserProfileView
import io.element.android.libraries.architecture.NodeInputs
@@ -37,6 +38,8 @@ class UserProfileNode(
private val analyticsService: AnalyticsService,
private val permalinkBuilder: PermalinkBuilder,
presenterFactory: UserProfilePresenter.Factory,
+ // HealthChat fork: renders the extended profile fields.
+ private val healthChatProfileSectionRenderer: HealthChatProfileSectionRenderer,
) : Node(buildContext, plugins = plugins) {
data class UserProfileInputs(
val userId: UserId
@@ -78,6 +81,9 @@ class UserProfileNode(
onStartCall = callback::startCall,
openAvatarPreview = callback::navigateToAvatarPreview,
onVerifyClick = callback::startVerifyUserFlow,
+ healthChatProfileSection = { userId, isCurrentUser ->
+ healthChatProfileSectionRenderer.Render(userId, isCurrentUser, Modifier)
+ },
)
}
}
diff --git a/features/userprofile/shared/src/main/kotlin/io/element/android/features/userprofile/shared/UserProfileView.kt b/features/userprofile/shared/src/main/kotlin/io/element/android/features/userprofile/shared/UserProfileView.kt
index d2d27638b8..0d2fb15758 100644
--- a/features/userprofile/shared/src/main/kotlin/io/element/android/features/userprofile/shared/UserProfileView.kt
+++ b/features/userprofile/shared/src/main/kotlin/io/element/android/features/userprofile/shared/UserProfileView.kt
@@ -56,6 +56,8 @@ fun UserProfileView(
openAvatarPreview: (username: String, url: String) -> Unit,
onVerifyClick: (UserId) -> Unit,
modifier: Modifier = Modifier,
+ // HealthChat fork: slot for the extended profile fields, rendered by features/healthchat.
+ healthChatProfileSection: @Composable (userId: UserId, isCurrentUser: Boolean) -> Unit = { _, _ -> },
) {
val snackbarHostState = rememberSnackbarHostState(snackbarMessage = state.snackbarMessage)
Scaffold(
@@ -93,6 +95,7 @@ fun UserProfileView(
onCall = { intent -> state.dmRoomId?.let { onStartCall(it, intent) } }
)
Spacer(modifier = Modifier.height(26.dp))
+ healthChatProfileSection(state.userId, state.isCurrentUser)
if (!state.isCurrentUser) {
VerifyUserSection(state, onVerifyClick = { onVerifyClick(state.userId) })
BlockUserSection(state)
diff --git a/tests/uitests/src/test/snapshots/images/features.healthchat.impl.profile.section_HealthChatProfileSectionView_Day_0_en.png b/tests/uitests/src/test/snapshots/images/features.healthchat.impl.profile.section_HealthChatProfileSectionView_Day_0_en.png
new file mode 100644
index 0000000000..b84c7a624a
--- /dev/null
+++ b/tests/uitests/src/test/snapshots/images/features.healthchat.impl.profile.section_HealthChatProfileSectionView_Day_0_en.png
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:ba8b7332e2f806bfd622cd2bb944faf783f9708e49538303758b9a4a54792f73
+size 52289
diff --git a/tests/uitests/src/test/snapshots/images/features.healthchat.impl.profile.section_HealthChatProfileSectionView_Day_1_en.png b/tests/uitests/src/test/snapshots/images/features.healthchat.impl.profile.section_HealthChatProfileSectionView_Day_1_en.png
new file mode 100644
index 0000000000..44fe9f7dd6
--- /dev/null
+++ b/tests/uitests/src/test/snapshots/images/features.healthchat.impl.profile.section_HealthChatProfileSectionView_Day_1_en.png
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:88ac59a2bb537aa26b3f27418f92b8f6984892efe925c6f605fd51dd0cbedb3b
+size 9982
diff --git a/tests/uitests/src/test/snapshots/images/features.healthchat.impl.profile.section_HealthChatProfileSectionView_Day_2_en.png b/tests/uitests/src/test/snapshots/images/features.healthchat.impl.profile.section_HealthChatProfileSectionView_Day_2_en.png
new file mode 100644
index 0000000000..bd73e322ab
--- /dev/null
+++ b/tests/uitests/src/test/snapshots/images/features.healthchat.impl.profile.section_HealthChatProfileSectionView_Day_2_en.png
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:12020ba97720f2374f9ace172693f08be01522e4ca30d3970efa91d802581e81
+size 3657
diff --git a/tests/uitests/src/test/snapshots/images/features.healthchat.impl.profile.section_HealthChatProfileSectionView_Day_3_en.png b/tests/uitests/src/test/snapshots/images/features.healthchat.impl.profile.section_HealthChatProfileSectionView_Day_3_en.png
new file mode 100644
index 0000000000..bd73e322ab
--- /dev/null
+++ b/tests/uitests/src/test/snapshots/images/features.healthchat.impl.profile.section_HealthChatProfileSectionView_Day_3_en.png
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:12020ba97720f2374f9ace172693f08be01522e4ca30d3970efa91d802581e81
+size 3657
diff --git a/tests/uitests/src/test/snapshots/images/features.healthchat.impl.profile.section_HealthChatProfileSectionView_Day_4_en.png b/tests/uitests/src/test/snapshots/images/features.healthchat.impl.profile.section_HealthChatProfileSectionView_Day_4_en.png
new file mode 100644
index 0000000000..8e69401b02
--- /dev/null
+++ b/tests/uitests/src/test/snapshots/images/features.healthchat.impl.profile.section_HealthChatProfileSectionView_Day_4_en.png
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:df8ae4aefac7f11ed1f628cf5d6355dcc462996ea7d05b86f2dbae8e77c6fecb
+size 13756
diff --git a/tests/uitests/src/test/snapshots/images/features.healthchat.impl.profile.section_HealthChatProfileSectionView_Day_5_en.png b/tests/uitests/src/test/snapshots/images/features.healthchat.impl.profile.section_HealthChatProfileSectionView_Day_5_en.png
new file mode 100644
index 0000000000..895a4add38
--- /dev/null
+++ b/tests/uitests/src/test/snapshots/images/features.healthchat.impl.profile.section_HealthChatProfileSectionView_Day_5_en.png
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:3278228fe2747cb14a524b05e55970b631ff632d582d7431860f10136ff071be
+size 14424
diff --git a/tests/uitests/src/test/snapshots/images/features.healthchat.impl.profile.section_HealthChatProfileSectionView_Night_0_en.png b/tests/uitests/src/test/snapshots/images/features.healthchat.impl.profile.section_HealthChatProfileSectionView_Night_0_en.png
new file mode 100644
index 0000000000..8d387bd44b
--- /dev/null
+++ b/tests/uitests/src/test/snapshots/images/features.healthchat.impl.profile.section_HealthChatProfileSectionView_Night_0_en.png
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:4c5be695ab84fdc084796b23861191a9fd58a98b2794511bb7e75f7b2081a189
+size 50655
diff --git a/tests/uitests/src/test/snapshots/images/features.healthchat.impl.profile.section_HealthChatProfileSectionView_Night_1_en.png b/tests/uitests/src/test/snapshots/images/features.healthchat.impl.profile.section_HealthChatProfileSectionView_Night_1_en.png
new file mode 100644
index 0000000000..a8f7628012
--- /dev/null
+++ b/tests/uitests/src/test/snapshots/images/features.healthchat.impl.profile.section_HealthChatProfileSectionView_Night_1_en.png
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:acb8aa0c40957ee14a0763473c435664c5a3698b33e83a1b8ae6fef394d9a046
+size 9648
diff --git a/tests/uitests/src/test/snapshots/images/features.healthchat.impl.profile.section_HealthChatProfileSectionView_Night_2_en.png b/tests/uitests/src/test/snapshots/images/features.healthchat.impl.profile.section_HealthChatProfileSectionView_Night_2_en.png
new file mode 100644
index 0000000000..bd73e322ab
--- /dev/null
+++ b/tests/uitests/src/test/snapshots/images/features.healthchat.impl.profile.section_HealthChatProfileSectionView_Night_2_en.png
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:12020ba97720f2374f9ace172693f08be01522e4ca30d3970efa91d802581e81
+size 3657
diff --git a/tests/uitests/src/test/snapshots/images/features.healthchat.impl.profile.section_HealthChatProfileSectionView_Night_3_en.png b/tests/uitests/src/test/snapshots/images/features.healthchat.impl.profile.section_HealthChatProfileSectionView_Night_3_en.png
new file mode 100644
index 0000000000..bd73e322ab
--- /dev/null
+++ b/tests/uitests/src/test/snapshots/images/features.healthchat.impl.profile.section_HealthChatProfileSectionView_Night_3_en.png
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:12020ba97720f2374f9ace172693f08be01522e4ca30d3970efa91d802581e81
+size 3657
diff --git a/tests/uitests/src/test/snapshots/images/features.healthchat.impl.profile.section_HealthChatProfileSectionView_Night_4_en.png b/tests/uitests/src/test/snapshots/images/features.healthchat.impl.profile.section_HealthChatProfileSectionView_Night_4_en.png
new file mode 100644
index 0000000000..034a55b389
--- /dev/null
+++ b/tests/uitests/src/test/snapshots/images/features.healthchat.impl.profile.section_HealthChatProfileSectionView_Night_4_en.png
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:6f2aeea63619087437678c3fc1e91b64e884496bb6446e902ac92e96575aaf12
+size 13272
diff --git a/tests/uitests/src/test/snapshots/images/features.healthchat.impl.profile.section_HealthChatProfileSectionView_Night_5_en.png b/tests/uitests/src/test/snapshots/images/features.healthchat.impl.profile.section_HealthChatProfileSectionView_Night_5_en.png
new file mode 100644
index 0000000000..5b342962a1
--- /dev/null
+++ b/tests/uitests/src/test/snapshots/images/features.healthchat.impl.profile.section_HealthChatProfileSectionView_Night_5_en.png
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:0d84e69e9b1aac2502a854ad1aaed472a63894c078d1cfa974355370e4a017fa
+size 13788