diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 521eafb3d3..d2f3ca18d1 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -51,7 +51,7 @@ jobs: ref: ${{ github.event_name == 'pull_request' && github.event.pull_request.head.sha || github.ref }} persist-credentials: false - name: Use JDK 21 - uses: actions/setup-java@1bcf9fb12cf4aa7d266a90ae39939e61372fe520 # v5.4.0 + uses: actions/setup-java@0f481fcb613427c0f801b606911222b5b6f3083a # v5.5.0 with: distribution: 'temurin' # See 'Supported distributions' for available options java-version: '21' diff --git a/.github/workflows/build_enterprise.yml b/.github/workflows/build_enterprise.yml index 861efd7665..3ff2803bf8 100644 --- a/.github/workflows/build_enterprise.yml +++ b/.github/workflows/build_enterprise.yml @@ -56,7 +56,7 @@ jobs: - name: Clone submodules run: git submodule update --init --recursive - name: Use JDK 21 - uses: actions/setup-java@1bcf9fb12cf4aa7d266a90ae39939e61372fe520 # v5.4.0 + uses: actions/setup-java@0f481fcb613427c0f801b606911222b5b6f3083a # v5.5.0 with: distribution: 'temurin' # See 'Supported distributions' for available options java-version: '21' diff --git a/.github/workflows/generate_github_pages.yml b/.github/workflows/generate_github_pages.yml index a9bee5c09d..33fdec38a4 100644 --- a/.github/workflows/generate_github_pages.yml +++ b/.github/workflows/generate_github_pages.yml @@ -19,7 +19,7 @@ jobs: - name: ⏬ Checkout with LFS uses: nschloe/action-cached-lfs-checkout@385a8ecc719e50b8c71af6ab01a624b486b7c3bc # v1.2.5 - name: Use JDK 21 - uses: actions/setup-java@1bcf9fb12cf4aa7d266a90ae39939e61372fe520 # v5.4.0 + uses: actions/setup-java@0f481fcb613427c0f801b606911222b5b6f3083a # v5.5.0 with: distribution: 'temurin' # See 'Supported distributions' for available options java-version: '21' diff --git a/.github/workflows/gradle-wrapper-update.yml b/.github/workflows/gradle-wrapper-update.yml index e98c7ca9eb..8db2b5fb6b 100644 --- a/.github/workflows/gradle-wrapper-update.yml +++ b/.github/workflows/gradle-wrapper-update.yml @@ -16,9 +16,8 @@ jobs: - uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0 with: persist-credentials: false - - uses: actions/setup-java@1bcf9fb12cf4aa7d266a90ae39939e61372fe520 # v5.4.0 + - uses: actions/setup-java@0f481fcb613427c0f801b606911222b5b6f3083a # v5.5.0 name: Use JDK 21 - if: (github.event_name == 'pull_request' && github.event.pull_request.fork == null) || github.event_name == 'workflow_dispatch' with: distribution: 'temurin' # See 'Supported distributions' for available options java-version: '21' diff --git a/.github/workflows/maestro-local.yml b/.github/workflows/maestro-local.yml index a3f08728e5..99a64da5f2 100644 --- a/.github/workflows/maestro-local.yml +++ b/.github/workflows/maestro-local.yml @@ -44,7 +44,7 @@ jobs: # https://github.com/actions/checkout/issues/881 ref: ${{ github.ref }} persist-credentials: false - - uses: actions/setup-java@1bcf9fb12cf4aa7d266a90ae39939e61372fe520 # v5.4.0 + - uses: actions/setup-java@0f481fcb613427c0f801b606911222b5b6f3083a # v5.5.0 name: Use JDK 21 with: distribution: 'temurin' # See 'Supported distributions' for available options diff --git a/.github/workflows/nightly.yml b/.github/workflows/nightly.yml index f9c960fa8d..c32b277f5c 100644 --- a/.github/workflows/nightly.yml +++ b/.github/workflows/nightly.yml @@ -36,7 +36,7 @@ jobs: with: persist-credentials: false - name: Use JDK 21 - uses: actions/setup-java@1bcf9fb12cf4aa7d266a90ae39939e61372fe520 # v5.4.0 + uses: actions/setup-java@0f481fcb613427c0f801b606911222b5b6f3083a # v5.5.0 with: distribution: 'temurin' # See 'Supported distributions' for available options java-version: '21' diff --git a/.github/workflows/nightlyReports.yml b/.github/workflows/nightlyReports.yml index e3e1ad6d72..ff2b74a753 100644 --- a/.github/workflows/nightlyReports.yml +++ b/.github/workflows/nightlyReports.yml @@ -37,7 +37,7 @@ jobs: uses: nschloe/action-cached-lfs-checkout@385a8ecc719e50b8c71af6ab01a624b486b7c3bc # v1.2.5 - name: Use JDK 21 - uses: actions/setup-java@1bcf9fb12cf4aa7d266a90ae39939e61372fe520 # v5.4.0 + uses: actions/setup-java@0f481fcb613427c0f801b606911222b5b6f3083a # v5.5.0 with: distribution: 'temurin' # See 'Supported distributions' for available options java-version: '21' @@ -80,7 +80,7 @@ jobs: with: persist-credentials: false - name: Use JDK 21 - uses: actions/setup-java@1bcf9fb12cf4aa7d266a90ae39939e61372fe520 # v5.4.0 + uses: actions/setup-java@0f481fcb613427c0f801b606911222b5b6f3083a # v5.5.0 with: distribution: 'temurin' # See 'Supported distributions' for available options java-version: '21' diff --git a/.github/workflows/quality.yml b/.github/workflows/quality.yml index 8aac9e5794..4d5f568dac 100644 --- a/.github/workflows/quality.yml +++ b/.github/workflows/quality.yml @@ -69,7 +69,7 @@ jobs: with: persist-credentials: false - name: Use JDK 21 - uses: actions/setup-java@1bcf9fb12cf4aa7d266a90ae39939e61372fe520 # v5.4.0 + uses: actions/setup-java@0f481fcb613427c0f801b606911222b5b6f3083a # v5.5.0 with: distribution: 'temurin' # See 'Supported distributions' for available options java-version: '21' @@ -108,7 +108,7 @@ jobs: if: ${{ github.event_name != 'pull_request' || github.event.pull_request.head.repo.full_name == 'element-hq/element-x-android' }} run: git submodule update --init --recursive - name: Use JDK 21 - uses: actions/setup-java@1bcf9fb12cf4aa7d266a90ae39939e61372fe520 # v5.4.0 + uses: actions/setup-java@0f481fcb613427c0f801b606911222b5b6f3083a # v5.5.0 with: distribution: 'temurin' # See 'Supported distributions' for available options java-version: '21' @@ -149,7 +149,7 @@ jobs: if: ${{ github.event_name != 'pull_request' || github.event.pull_request.head.repo.full_name == 'element-hq/element-x-android' }} run: git submodule update --init --recursive - name: Use JDK 21 - uses: actions/setup-java@1bcf9fb12cf4aa7d266a90ae39939e61372fe520 # v5.4.0 + uses: actions/setup-java@0f481fcb613427c0f801b606911222b5b6f3083a # v5.5.0 with: distribution: 'temurin' # See 'Supported distributions' for available options java-version: '21' @@ -183,7 +183,7 @@ jobs: if: ${{ github.event_name != 'pull_request' || github.event.pull_request.head.repo.full_name == 'element-hq/element-x-android' }} run: git submodule update --init --recursive - name: Use JDK 21 - uses: actions/setup-java@1bcf9fb12cf4aa7d266a90ae39939e61372fe520 # v5.4.0 + uses: actions/setup-java@0f481fcb613427c0f801b606911222b5b6f3083a # v5.5.0 with: distribution: 'temurin' # See 'Supported distributions' for available options java-version: '21' @@ -228,7 +228,7 @@ jobs: if: ${{ github.event_name != 'pull_request' || github.event.pull_request.head.repo.full_name == 'element-hq/element-x-android' }} run: git submodule update --init --recursive - name: Use JDK 21 - uses: actions/setup-java@1bcf9fb12cf4aa7d266a90ae39939e61372fe520 # v5.4.0 + uses: actions/setup-java@0f481fcb613427c0f801b606911222b5b6f3083a # v5.5.0 with: distribution: 'temurin' # See 'Supported distributions' for available options java-version: '21' @@ -269,7 +269,7 @@ jobs: if: ${{ github.event_name != 'pull_request' || github.event.pull_request.head.repo.full_name == 'element-hq/element-x-android' }} run: git submodule update --init --recursive - name: Use JDK 21 - uses: actions/setup-java@1bcf9fb12cf4aa7d266a90ae39939e61372fe520 # v5.4.0 + uses: actions/setup-java@0f481fcb613427c0f801b606911222b5b6f3083a # v5.5.0 with: distribution: 'temurin' # See 'Supported distributions' for available options java-version: '21' @@ -336,7 +336,7 @@ jobs: - uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0 with: persist-credentials: false - - uses: zizmorcore/zizmor-action@192e21d79ab29983730a13d1382995c2307fbcaa # v0.5.7 + - uses: zizmorcore/zizmor-action@6599ee8b7a49aef6a770f63d261d214911a7ce02 # v0.6.0 upload_reports: name: Project Check Suite diff --git a/.github/workflows/recordScreenshots.yml b/.github/workflows/recordScreenshots.yml index 6edb0492e4..273eac3c34 100644 --- a/.github/workflows/recordScreenshots.yml +++ b/.github/workflows/recordScreenshots.yml @@ -54,7 +54,7 @@ jobs: with: persist-credentials: false - name: ☕️ Use JDK 21 - uses: actions/setup-java@1bcf9fb12cf4aa7d266a90ae39939e61372fe520 # v5.4.0 + uses: actions/setup-java@0f481fcb613427c0f801b606911222b5b6f3083a # v5.5.0 with: distribution: 'temurin' # See 'Supported distributions' for available options java-version: '21' diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 5d59c9530b..e6b83a1fc3 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -38,7 +38,7 @@ jobs: with: persist-credentials: false - name: Use JDK 21 - uses: actions/setup-java@1bcf9fb12cf4aa7d266a90ae39939e61372fe520 # v5.4.0 + uses: actions/setup-java@0f481fcb613427c0f801b606911222b5b6f3083a # v5.5.0 with: distribution: 'temurin' # See 'Supported distributions' for available options java-version: '21' @@ -82,7 +82,7 @@ jobs: - name: Clone submodules run: git submodule update --init --recursive - name: Use JDK 21 - uses: actions/setup-java@1bcf9fb12cf4aa7d266a90ae39939e61372fe520 # v5.4.0 + uses: actions/setup-java@0f481fcb613427c0f801b606911222b5b6f3083a # v5.5.0 with: distribution: 'temurin' # See 'Supported distributions' for available options java-version: '21' @@ -126,7 +126,7 @@ jobs: with: persist-credentials: false - name: Use JDK 21 - uses: actions/setup-java@1bcf9fb12cf4aa7d266a90ae39939e61372fe520 # v5.4.0 + uses: actions/setup-java@0f481fcb613427c0f801b606911222b5b6f3083a # v5.5.0 with: distribution: 'temurin' # See 'Supported distributions' for available options java-version: '21' diff --git a/.github/workflows/sonar.yml b/.github/workflows/sonar.yml index ac9a69c0e8..db1cf2ecfb 100644 --- a/.github/workflows/sonar.yml +++ b/.github/workflows/sonar.yml @@ -45,7 +45,7 @@ jobs: ref: ${{ github.event_name == 'pull_request' && github.event.pull_request.head.sha || github.ref }} persist-credentials: false - name: Use JDK 21 - uses: actions/setup-java@1bcf9fb12cf4aa7d266a90ae39939e61372fe520 # v5.4.0 + uses: actions/setup-java@0f481fcb613427c0f801b606911222b5b6f3083a # v5.5.0 with: distribution: 'temurin' # See 'Supported distributions' for available options java-version: '21' diff --git a/.github/workflows/sync-localazy.yml b/.github/workflows/sync-localazy.yml index 6bd5c84283..bb8ead3aa3 100644 --- a/.github/workflows/sync-localazy.yml +++ b/.github/workflows/sync-localazy.yml @@ -17,7 +17,7 @@ jobs: with: persist-credentials: false - name: Use JDK 21 - uses: actions/setup-java@1bcf9fb12cf4aa7d266a90ae39939e61372fe520 # v5.4.0 + uses: actions/setup-java@0f481fcb613427c0f801b606911222b5b6f3083a # v5.5.0 with: distribution: 'temurin' # See 'Supported distributions' for available options java-version: '21' diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index 5f646cacf7..6edb31ce4f 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -63,7 +63,7 @@ jobs: if: ${{ github.event_name != 'pull_request' || github.event.pull_request.head.repo.full_name == 'element-hq/element-x-android' }} run: git submodule update --init --recursive - name: ☕️ Use JDK 21 - uses: actions/setup-java@1bcf9fb12cf4aa7d266a90ae39939e61372fe520 # v5.4.0 + uses: actions/setup-java@0f481fcb613427c0f801b606911222b5b6f3083a # v5.5.0 with: distribution: 'temurin' # See 'Supported distributions' for available options java-version: '21' diff --git a/enterprise b/enterprise index cca96c4fc2..60de13ffd7 160000 --- a/enterprise +++ b/enterprise @@ -1 +1 @@ -Subproject commit cca96c4fc24b6e2fd1ccf9265c8283ac9bf63dc0 +Subproject commit 60de13ffd7dea97fd4fec6fb6af49b5288e67ff2 diff --git a/features/contentscanner/impl/src/main/kotlin/io/element/android/features/contentscanner/impl/DefaultContentScannerService.kt b/features/contentscanner/impl/src/main/kotlin/io/element/android/features/contentscanner/impl/DefaultContentScannerService.kt index 2765686f9d..c809179552 100644 --- a/features/contentscanner/impl/src/main/kotlin/io/element/android/features/contentscanner/impl/DefaultContentScannerService.kt +++ b/features/contentscanner/impl/src/main/kotlin/io/element/android/features/contentscanner/impl/DefaultContentScannerService.kt @@ -10,6 +10,7 @@ package io.element.android.features.contentscanner.impl import io.element.android.features.contentscanner.api.ContentScannerService import io.element.android.libraries.core.coroutine.CoroutineDispatchers import io.element.android.libraries.matrix.api.core.EventId +import io.element.android.libraries.matrix.api.exception.ClientException import io.element.android.libraries.matrix.api.media.MediaSource import io.element.android.libraries.matrix.api.scanner.ContentScanner import io.element.android.libraries.matrix.ui.media.contentvalidation.ContentValidationState @@ -42,12 +43,19 @@ class DefaultContentScannerService( contentValidationState.update(url, contentValidationValue) } .onFailure { exception -> - if (exception is IOException) { - // If it's an IO-related exception, we can retry later, so we don't store the error - contentValidationState.update(url, ContentValidationValue.Unknown) - } else { - // For other exceptions, we cache the failure - contentValidationState.update(url, ContentValidationValue.UnrecoverableError(exception)) + when (exception) { + is IOException -> { + // If it's an IO-related exception, we can retry later, so we don't store the error + contentValidationState.update(url, ContentValidationValue.Unknown) + } + is ClientException.ContentScanner if exception.reason.isDangerous() -> { + // It's a dangerous content (banned mime-type?), we mark it as invalid + contentValidationState.update(url, ContentValidationValue.Invalid) + } + else -> { + // For other exceptions, we cache the failure + contentValidationState.update(url, ContentValidationValue.UnrecoverableError(exception)) + } } } } diff --git a/features/enterprise/api/build.gradle.kts b/features/enterprise/api/build.gradle.kts index 1c541c5080..5e7f81e4b4 100644 --- a/features/enterprise/api/build.gradle.kts +++ b/features/enterprise/api/build.gradle.kts @@ -17,4 +17,5 @@ dependencies { implementation(projects.libraries.compound) implementation(projects.libraries.architecture) implementation(projects.libraries.matrix.api) + implementation(projects.libraries.wellknown.api) } diff --git a/features/enterprise/api/src/main/kotlin/io/element/android/features/enterprise/api/EnterpriseService.kt b/features/enterprise/api/src/main/kotlin/io/element/android/features/enterprise/api/EnterpriseService.kt index 92d8b9b646..7b595966d4 100644 --- a/features/enterprise/api/src/main/kotlin/io/element/android/features/enterprise/api/EnterpriseService.kt +++ b/features/enterprise/api/src/main/kotlin/io/element/android/features/enterprise/api/EnterpriseService.kt @@ -11,6 +11,7 @@ package io.element.android.features.enterprise.api import androidx.compose.ui.graphics.Color import io.element.android.compound.colors.SemanticColorsLightDark import io.element.android.libraries.matrix.api.core.SessionId +import io.element.android.libraries.wellknown.api.ElementWellKnown import kotlinx.coroutines.flow.Flow interface EnterpriseService { @@ -41,6 +42,11 @@ interface EnterpriseService { */ fun getNoisyNotificationChannelId(sessionId: SessionId): String? + /** + * Gets the overridden Element Well-Known data if it has been set, or null if not set. + */ + fun overriddenElementWellKnown(): ElementWellKnown? + companion object { const val ANY_ACCOUNT_PROVIDER = "*" } diff --git a/features/enterprise/impl-foss/build.gradle.kts b/features/enterprise/impl-foss/build.gradle.kts index f0c63f5655..a45c8ae167 100644 --- a/features/enterprise/impl-foss/build.gradle.kts +++ b/features/enterprise/impl-foss/build.gradle.kts @@ -23,6 +23,7 @@ dependencies { api(projects.features.enterprise.api) implementation(projects.libraries.architecture) implementation(projects.libraries.matrix.api) + implementation(projects.libraries.wellknown.api) testCommonDependencies(libs) testImplementation(projects.libraries.matrix.test) diff --git a/features/enterprise/impl-foss/src/main/kotlin/io/element/android/features/enterprise/impl/DefaultEnterpriseService.kt b/features/enterprise/impl-foss/src/main/kotlin/io/element/android/features/enterprise/impl/DefaultEnterpriseService.kt index 6e3ed5d3cc..bc2a3f1bf1 100644 --- a/features/enterprise/impl-foss/src/main/kotlin/io/element/android/features/enterprise/impl/DefaultEnterpriseService.kt +++ b/features/enterprise/impl-foss/src/main/kotlin/io/element/android/features/enterprise/impl/DefaultEnterpriseService.kt @@ -15,6 +15,7 @@ import io.element.android.compound.colors.SemanticColorsLightDark import io.element.android.features.enterprise.api.BugReportUrl import io.element.android.features.enterprise.api.EnterpriseService import io.element.android.libraries.matrix.api.core.SessionId +import io.element.android.libraries.wellknown.api.ElementWellKnown import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.flowOf @@ -45,4 +46,6 @@ class DefaultEnterpriseService : EnterpriseService { } override fun getNoisyNotificationChannelId(sessionId: SessionId): String? = null + + override fun overriddenElementWellKnown(): ElementWellKnown? = null } diff --git a/features/enterprise/test/build.gradle.kts b/features/enterprise/test/build.gradle.kts index c37fc53de3..99dbe733dd 100644 --- a/features/enterprise/test/build.gradle.kts +++ b/features/enterprise/test/build.gradle.kts @@ -18,5 +18,6 @@ dependencies { implementation(projects.libraries.architecture) implementation(projects.libraries.compound) implementation(projects.libraries.matrix.api) + implementation(projects.libraries.wellknown.api) implementation(projects.tests.testutils) } diff --git a/features/enterprise/test/src/main/kotlin/io/element/android/features/enterprise/test/FakeEnterpriseService.kt b/features/enterprise/test/src/main/kotlin/io/element/android/features/enterprise/test/FakeEnterpriseService.kt index 805c75be6a..f6379bef30 100644 --- a/features/enterprise/test/src/main/kotlin/io/element/android/features/enterprise/test/FakeEnterpriseService.kt +++ b/features/enterprise/test/src/main/kotlin/io/element/android/features/enterprise/test/FakeEnterpriseService.kt @@ -13,6 +13,7 @@ import io.element.android.compound.colors.SemanticColorsLightDark import io.element.android.features.enterprise.api.BugReportUrl import io.element.android.features.enterprise.api.EnterpriseService import io.element.android.libraries.matrix.api.core.SessionId +import io.element.android.libraries.wellknown.api.ElementWellKnown import io.element.android.tests.testutils.lambda.lambdaError import io.element.android.tests.testutils.simulateLongTask import kotlinx.coroutines.flow.Flow @@ -31,6 +32,7 @@ class FakeEnterpriseService( private val unifiedPushDefaultPushGatewayResult: () -> String? = { lambdaError() }, private val getNoisyNotificationChannelIdResult: (SessionId?) -> String? = { lambdaError() }, private val tweakMasUrlResult: (String, String) -> String = { _, _ -> lambdaError() }, + private val overrideWellKnownResult: () -> ElementWellKnown? = { lambdaError() }, ) : EnterpriseService { private val brandColorState = MutableStateFlow(initialBrandColor) private val semanticColorsState = MutableStateFlow(initialSemanticColors) @@ -79,4 +81,8 @@ class FakeEnterpriseService( override fun getNoisyNotificationChannelId(sessionId: SessionId): String? { return getNoisyNotificationChannelIdResult(sessionId) } + + override fun overriddenElementWellKnown(): ElementWellKnown? { + return overrideWellKnownResult() + } } diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/TimelineItemContentScannerPreviews.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/TimelineItemContentScannerPreviews.kt index 5c5414646d..a59a1c0ae0 100644 --- a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/TimelineItemContentScannerPreviews.kt +++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/TimelineItemContentScannerPreviews.kt @@ -147,6 +147,22 @@ internal fun TimelineItemScanningContentFailedPreview() = ElementPreview { } } +@PreviewsDayNight +@Composable +internal fun TimelineItemScanningContentNotFoundPreview() = ElementPreview { + val cache = remember { + InMemoryEventContentValidationCache(initial = mapOf( + AN_EVENT_ID to NoopContentValidationState(ContentValidationValue.UnrecoverableError(IllegalStateException("Not found"))) + )) + } + CompositionLocalProvider(LocalEventContentValidationState provides cache) { + Column(verticalArrangement = Arrangement.spacedBy(10.dp)) { + ATimelineItemEventRow(event = aTimelineItemEvent(eventId = AN_EVENT_ID, content = aTimelineItemImageContent())) + ATimelineItemEventRow(event = aTimelineItemEvent(eventId = AN_EVENT_ID, content = aTimelineItemImageContent(caption = "A caption"))) + } + } +} + @PreviewsDayNight @Composable internal fun TimelineItemScanningContentWithInvalidRepliesPreview() = ElementPreview { diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/event/TimelineItemEventContentView.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/event/TimelineItemEventContentView.kt index c622a3044a..4b7ab9372d 100644 --- a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/event/TimelineItemEventContentView.kt +++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/event/TimelineItemEventContentView.kt @@ -232,7 +232,7 @@ fun TimelineItemEventContentView( } if (showCaption) { - val padding = if (displayInvalidContent) { + val padding = if (displayInvalidContent || displayContentNotFound) { PaddingValues(start = 12.dp, end = 12.dp, top = 4.dp, bottom = 0.dp) } else { when (content) { diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/group/GroupHeaderView.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/group/GroupHeaderView.kt index 883c591fd2..9dbeb83a3c 100644 --- a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/group/GroupHeaderView.kt +++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/group/GroupHeaderView.kt @@ -26,9 +26,11 @@ import androidx.compose.ui.Modifier import androidx.compose.ui.draw.clip import androidx.compose.ui.draw.rotate import androidx.compose.ui.graphics.Color +import androidx.compose.ui.res.stringResource import androidx.compose.ui.semantics.Role import androidx.compose.ui.semantics.clearAndSetSemantics import androidx.compose.ui.semantics.contentDescription +import androidx.compose.ui.semantics.stateDescription import androidx.compose.ui.unit.dp import io.element.android.compound.theme.ElementTheme import io.element.android.compound.tokens.generated.CompoundIcons @@ -37,6 +39,7 @@ import io.element.android.libraries.designsystem.preview.PreviewsDayNight import io.element.android.libraries.designsystem.theme.components.Icon import io.element.android.libraries.designsystem.theme.components.Surface import io.element.android.libraries.designsystem.theme.components.Text +import io.element.android.libraries.ui.strings.CommonStrings private val CORNER_RADIUS = 8.dp @@ -52,6 +55,8 @@ fun GroupHeaderView( val backgroundColor = Color.Transparent val shape = RoundedCornerShape(CORNER_RADIUS) + val expandedStateDescription = stringResource(CommonStrings.a11y_state_expanded) + val collapsedStateDescription = stringResource(CommonStrings.a11y_state_collapsed) Box( modifier = modifier .fillMaxWidth() @@ -62,6 +67,7 @@ fun GroupHeaderView( ) .clearAndSetSemantics { contentDescription = text + stateDescription = if (isExpanded) expandedStateDescription else collapsedStateDescription }, contentAlignment = Alignment.Center ) { diff --git a/features/preferences/api/build.gradle.kts b/features/preferences/api/build.gradle.kts index b5a08b9435..c43259918d 100644 --- a/features/preferences/api/build.gradle.kts +++ b/features/preferences/api/build.gradle.kts @@ -6,7 +6,7 @@ * Please see LICENSE files in the repository root for full details. */ plugins { - id("io.element.android-library") + id("io.element.android-compose-library") id("kotlin-parcelize") } diff --git a/features/preferences/api/src/main/kotlin/io/element/android/features/preferences/api/ExtraDeveloperOptionsRenderer.kt b/features/preferences/api/src/main/kotlin/io/element/android/features/preferences/api/ExtraDeveloperOptionsRenderer.kt new file mode 100644 index 0000000000..7d7eec9d8b --- /dev/null +++ b/features/preferences/api/src/main/kotlin/io/element/android/features/preferences/api/ExtraDeveloperOptionsRenderer.kt @@ -0,0 +1,19 @@ +/* + * 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.preferences.api + +import androidx.compose.runtime.Composable +import androidx.compose.ui.Modifier + +/** + * Component for rendering extra developer options in the preferences screen. + */ +interface ExtraDeveloperOptionsRenderer { + @Composable + fun Render(modifier: Modifier) +} diff --git a/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/developer/DeveloperSettingsNode.kt b/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/developer/DeveloperSettingsNode.kt index 98c7d89633..a8a8c63eed 100644 --- a/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/developer/DeveloperSettingsNode.kt +++ b/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/developer/DeveloperSettingsNode.kt @@ -18,6 +18,7 @@ import com.bumble.appyx.core.plugin.Plugin import dev.zacsweers.metro.Assisted import dev.zacsweers.metro.AssistedInject import io.element.android.annotations.ContributesNode +import io.element.android.features.preferences.api.ExtraDeveloperOptionsRenderer import io.element.android.libraries.architecture.callback import io.element.android.libraries.designsystem.showkase.getBrowserIntent import io.element.android.libraries.di.SessionScope @@ -28,6 +29,7 @@ class DeveloperSettingsNode( @Assisted buildContext: BuildContext, @Assisted plugins: List, private val presenter: DeveloperSettingsPresenter, + private val extraDeveloperOptionsRenderer: ExtraDeveloperOptionsRenderer, ) : Node(buildContext, plugins = plugins) { interface Callback : Plugin { fun navigateToPushHistory() @@ -51,6 +53,7 @@ class DeveloperSettingsNode( onOpenShowkase = ::openShowkase, onPushHistoryClick = callback::navigateToPushHistory, onBackClick = callback::onDone, + extraOptions = { extraDeveloperOptionsRenderer.Render(Modifier) }, ) } } diff --git a/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/developer/DeveloperSettingsView.kt b/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/developer/DeveloperSettingsView.kt index 45009d1f71..0e5f4026ef 100644 --- a/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/developer/DeveloperSettingsView.kt +++ b/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/developer/DeveloperSettingsView.kt @@ -43,6 +43,7 @@ fun DeveloperSettingsView( onPushHistoryClick: () -> Unit, onBackClick: () -> Unit, modifier: Modifier = Modifier, + extraOptions: @Composable () -> Unit = {}, ) { if (state.showLoader) { ProgressDialog() @@ -97,6 +98,9 @@ fun DeveloperSettingsView( ) } } + + extraOptions() + val cache = state.cacheSize PreferenceCategory(title = "Cache") { ListItem( diff --git a/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/developer/NoopExtraDeveloperOptionsRenderer.kt b/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/developer/NoopExtraDeveloperOptionsRenderer.kt new file mode 100644 index 0000000000..da0540a93f --- /dev/null +++ b/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/developer/NoopExtraDeveloperOptionsRenderer.kt @@ -0,0 +1,22 @@ +/* + * 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.preferences.impl.developer + +import androidx.compose.runtime.Composable +import androidx.compose.ui.Modifier +import dev.zacsweers.metro.AppScope +import dev.zacsweers.metro.ContributesBinding +import io.element.android.features.preferences.api.ExtraDeveloperOptionsRenderer + +@ContributesBinding(AppScope::class) +class NoopExtraDeveloperOptionsRenderer : ExtraDeveloperOptionsRenderer { + @Composable + override fun Render(modifier: Modifier) { + // No-op + } +} diff --git a/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/developer/appsettings/AppDeveloperSettingsNode.kt b/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/developer/appsettings/AppDeveloperSettingsNode.kt index ae5e710d4b..89ef240a95 100644 --- a/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/developer/appsettings/AppDeveloperSettingsNode.kt +++ b/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/developer/appsettings/AppDeveloperSettingsNode.kt @@ -18,6 +18,7 @@ import dev.zacsweers.metro.AppScope import dev.zacsweers.metro.Assisted import dev.zacsweers.metro.AssistedInject import io.element.android.annotations.ContributesNode +import io.element.android.features.preferences.api.ExtraDeveloperOptionsRenderer import io.element.android.features.preferences.api.PreferencesEntryPoint import io.element.android.libraries.architecture.callback import io.element.android.libraries.designsystem.showkase.getBrowserIntent @@ -28,6 +29,7 @@ class AppDeveloperSettingsNode( @Assisted buildContext: BuildContext, @Assisted plugins: List, private val presenter: AppDeveloperSettingsPresenter, + private val extraDeveloperOptionsRenderer: ExtraDeveloperOptionsRenderer, ) : Node(buildContext, plugins = plugins) { private val callback: PreferencesEntryPoint.DeveloperSettingsCallback = callback() @@ -45,6 +47,7 @@ class AppDeveloperSettingsNode( modifier = modifier, onOpenShowkase = ::openShowkase, onBackClick = callback::onDone, + extraOptions = { extraDeveloperOptionsRenderer.Render(Modifier) }, ) } } diff --git a/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/developer/appsettings/AppDeveloperSettingsPage.kt b/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/developer/appsettings/AppDeveloperSettingsPage.kt index 81e1304e7b..d7d62aa325 100644 --- a/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/developer/appsettings/AppDeveloperSettingsPage.kt +++ b/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/developer/appsettings/AppDeveloperSettingsPage.kt @@ -24,6 +24,7 @@ fun AppDeveloperSettingsPage( onOpenShowkase: () -> Unit, onBackClick: () -> Unit, modifier: Modifier = Modifier, + extraOptions: @Composable () -> Unit = {}, ) { BackHandler( onBack = onBackClick, @@ -40,6 +41,7 @@ fun AppDeveloperSettingsPage( onOpenShowkase = onOpenShowkase, modifier = Modifier.padding(top = 8.dp) ) + extraOptions() } } diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 07f6098a34..1aee681c47 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -5,7 +5,7 @@ # Project android_gradle_plugin = "9.2.1" # When updating this, please also update the version in the file ./idea/kotlinc.xml -kotlin = "2.4.0" +kotlin = "2.4.10" kotlinpoet = "2.3.0" ksp = "2.3.10" firebaseAppDistribution = "5.3.0" @@ -32,7 +32,7 @@ accompanist = "0.37.3" # Test test_core = "1.7.0" -roborazzi = "1.67.0" +roborazzi = "1.68.0" # Jetbrain datetime = "0.8.0" @@ -51,10 +51,10 @@ telephoto = "0.19.0" haze = "1.7.2" # Dependency analysis -dependencyAnalysis = "3.16.0" +dependencyAnalysis = "3.16.1" # DI -metro = "1.3.0" +metro = "1.3.2" # Auto service autoservice = "1.1.1" @@ -84,7 +84,7 @@ kotlinpoet-ksp = { module = "com.squareup:kotlinpoet-ksp", version.ref = "kotlin kover_gradle_plugin = { module = "org.jetbrains.kotlinx:kover-gradle-plugin", version.ref = "kover" } ksp_gradle_plugin = { module = "com.google.devtools.ksp:com.google.devtools.ksp.gradle.plugin", version.ref = "ksp" } # https://firebase.google.com/docs/android/setup#available-libraries -google_firebase_bom = "com.google.firebase:firebase-bom:34.15.0" +google_firebase_bom = "com.google.firebase:firebase-bom:34.16.0" firebase_appdistribution_gradle = { module = "com.google.firebase:firebase-appdistribution-gradle", version.ref = "firebaseAppDistribution" } autonomousapps_dependencyanalysis_plugin = { module = "com.autonomousapps:dependency-analysis-gradle-plugin", version.ref = "dependencyAnalysis" } ksp_plugin = { module = "com.google.devtools.ksp:symbol-processing-api", version.ref = "ksp" } @@ -185,7 +185,7 @@ test_detekt_test = { module = "io.gitlab.arturbosch.detekt:detekt-test", version # https://github.com/matrix-org/matrix-rust-components-kotlin/commits/main/sdk/sdk-android/src/main/kotlin/org/matrix/rustcomponents/sdk/matrix_sdk_ffi.kt # All new features should not be implemented in the pull request that upgrades the version, developers should # only fix API breaks and may add some TODOs. -matrix_sdk = "org.matrix.rustcomponents:sdk-android:26.07.15" +matrix_sdk = "org.matrix.rustcomponents:sdk-android:26.07.22" # Others coil = { module = "io.coil-kt.coil3:coil", version.ref = "coil" } @@ -242,7 +242,7 @@ sigpwned_emoji4j = "com.sigpwned:emoji4j-core:16.0.0" metro_runtime = { module = "dev.zacsweers.metro:runtime", version.ref = "metro" } # Element Call -element_call_embedded = "io.element.android:element-call-embedded:0.20.3" +element_call_embedded = "io.element.android:element-call-embedded:0.22.0" # Auto services google_autoservice = { module = "com.google.auto.service:auto-service", version.ref = "autoservice" } diff --git a/gradle/wrapper/gradle-wrapper.jar b/gradle/wrapper/gradle-wrapper.jar index 61285a659d..b1b8ef56b4 100644 Binary files a/gradle/wrapper/gradle-wrapper.jar and b/gradle/wrapper/gradle-wrapper.jar differ diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index 4bdb2a9ebd..dbe66e1d66 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,8 +1,10 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists -distributionSha256Sum=bafc141b619ad6350fd975fc903156dd5c151998cc8b058e8c1044ab5f7b031f -distributionUrl=https\://services.gradle.org/distributions/gradle-9.5.1-bin.zip +distributionSha256Sum=9c0f7faeeb306cb14e4279a3e084ca6b596894089a0638e68a07c945a32c9e14 +distributionUrl=https\://services.gradle.org/distributions/gradle-9.6.1-bin.zip networkTimeout=10000 +retries=0 +retryBackOffMs=500 validateDistributionUrl=true zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists diff --git a/gradlew b/gradlew index adff685a03..249efbb032 100755 --- a/gradlew +++ b/gradlew @@ -20,7 +20,7 @@ ############################################################################## # -# Gradle start up script for POSIX generated by Gradle. +# gradlew start up script for POSIX generated by Gradle. # # Important for running: # @@ -29,7 +29,7 @@ # bash, then to run this script, type that shell name before the whole # command line, like: # -# ksh Gradle +# ksh gradlew # # Busybox and similar reduced shells will NOT work, because this script # requires all of these POSIX shell features: @@ -57,7 +57,7 @@ # Darwin, MinGW, and NonStop. # # (3) This script is generated from the Groovy template -# https://github.com/gradle/gradle/blob/HEAD/platforms/jvm/plugins-application/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt +# https://github.com/gradle/gradle/blob/3d91ce3b8caaf77ad09f381f43615b715b53f72c/platforms/jvm/plugins-application/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt # within the Gradle project. # # You can find Gradle at https://github.com/gradle/gradle/. diff --git a/gradlew.bat b/gradlew.bat index e509b2dd8f..8508ef684d 100644 --- a/gradlew.bat +++ b/gradlew.bat @@ -19,12 +19,12 @@ @if "%DEBUG%"=="" @echo off @rem ########################################################################## @rem -@rem Gradle startup script for Windows +@rem gradlew startup script for Windows @rem @rem ########################################################################## -@rem Set local scope for the variables with windows NT shell -if "%OS%"=="Windows_NT" setlocal +@rem Set local scope for the variables, and ensure extensions are enabled +setlocal EnableExtensions set DIRNAME=%~dp0 if "%DIRNAME%"=="" set DIRNAME=. @@ -51,7 +51,7 @@ echo. 1>&2 echo Please set the JAVA_HOME variable in your environment to match the 1>&2 echo location of your Java installation. 1>&2 -goto fail +"%COMSPEC%" /c exit 1 :findJavaFromJavaHome set JAVA_HOME=%JAVA_HOME:"=% @@ -65,29 +65,18 @@ echo. 1>&2 echo Please set the JAVA_HOME variable in your environment to match the 1>&2 echo location of your Java installation. 1>&2 -goto fail +"%COMSPEC%" /c exit 1 :execute @rem Setup the command line -@rem Execute Gradle -"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -jar "%APP_HOME%\gradle\wrapper\gradle-wrapper.jar" %* +@rem Execute gradlew +@rem endlocal doesn't take effect until after the line is parsed and variables are expanded +@rem which allows us to clear the local environment before executing the java command +endlocal & "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -jar "%APP_HOME%\gradle\wrapper\gradle-wrapper.jar" %* & call :exitWithErrorLevel -:end -@rem End local scope for the variables with windows NT shell -if %ERRORLEVEL% equ 0 goto mainEnd - -:fail -rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of -rem the _cmd.exe /c_ return code! -set EXIT_CODE=%ERRORLEVEL% -if %EXIT_CODE% equ 0 set EXIT_CODE=1 -if not ""=="%GRADLE_EXIT_CONSOLE%" exit %EXIT_CODE% -exit /b %EXIT_CODE% - -:mainEnd -if "%OS%"=="Windows_NT" endlocal - -:omega +:exitWithErrorLevel +@rem Use "%COMSPEC%" /c exit to allow operators to work properly in scripts +"%COMSPEC%" /c exit %ERRORLEVEL% diff --git a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/scanner/RustContentScanner.kt b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/scanner/RustContentScanner.kt index ecfa4f0bcd..c07ca94f26 100644 --- a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/scanner/RustContentScanner.kt +++ b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/scanner/RustContentScanner.kt @@ -7,9 +7,11 @@ package io.element.android.libraries.matrix.impl.scanner +import io.element.android.libraries.core.extensions.mapFailure import io.element.android.libraries.core.extensions.runCatchingExceptions import io.element.android.libraries.matrix.api.media.MediaSource import io.element.android.libraries.matrix.api.scanner.ContentScanner +import io.element.android.libraries.matrix.impl.exception.mapClientException import org.matrix.rustcomponents.sdk.Client import org.matrix.rustcomponents.sdk.NoHandle import org.matrix.rustcomponents.sdk.ContentScanner as RustScanner @@ -22,6 +24,8 @@ class RustContentScanner( override suspend fun scan(mediaSource: MediaSource): Result { return runCatchingExceptions { rustScanner.scan(client, mediaSource.toRustMediaSource()).clean + }.mapFailure { + it.mapClientException() } } } diff --git a/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/fixtures/factories/RoomHero.kt b/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/fixtures/factories/RoomHero.kt index 6abb08c667..66ee027443 100644 --- a/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/fixtures/factories/RoomHero.kt +++ b/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/fixtures/factories/RoomHero.kt @@ -11,11 +11,17 @@ package io.element.android.libraries.matrix.impl.fixtures.factories import io.element.android.libraries.matrix.api.core.UserId import io.element.android.libraries.matrix.test.A_USER_ID import org.matrix.rustcomponents.sdk.RoomHero +import org.matrix.rustcomponents.sdk.UserCall +import org.matrix.rustcomponents.sdk.UserStatus internal fun aRustRoomHero( userId: UserId = A_USER_ID, + status: UserStatus? = null, + call: UserCall? = null, ) = RoomHero( userId = userId.value, displayName = "displayName", avatarUrl = "avatarUrl", + status = status, + call = call, ) diff --git a/libraries/ui-strings/src/main/res/values/temporary.xml b/libraries/ui-strings/src/main/res/values/temporary.xml index c0573cc6c2..2526f254d3 100644 --- a/libraries/ui-strings/src/main/res/values/temporary.xml +++ b/libraries/ui-strings/src/main/res/values/temporary.xml @@ -8,6 +8,8 @@ "Mark as read" "Jump to first unread message" + "Expanded" + "Collapsed" Allow access to local network Your homeserver is on your local network. To connect, Element needs permission to reach other devices on this network. Active diff --git a/libraries/wellknown/api/src/main/kotlin/io/element/android/libraries/wellknown/api/ElementWellKnownParser.kt b/libraries/wellknown/api/src/main/kotlin/io/element/android/libraries/wellknown/api/ElementWellKnownParser.kt new file mode 100644 index 0000000000..db0a323a5f --- /dev/null +++ b/libraries/wellknown/api/src/main/kotlin/io/element/android/libraries/wellknown/api/ElementWellKnownParser.kt @@ -0,0 +1,12 @@ +/* + * 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.libraries.wellknown.api + +fun interface ElementWellKnownParser { + fun parse(json: String): Result +} diff --git a/libraries/wellknown/impl/build.gradle.kts b/libraries/wellknown/impl/build.gradle.kts index 1e2c4d7d61..6e7cc5ef1c 100644 --- a/libraries/wellknown/impl/build.gradle.kts +++ b/libraries/wellknown/impl/build.gradle.kts @@ -34,6 +34,7 @@ dependencies { implementation(projects.libraries.matrix.api) implementation(projects.libraries.network) implementation(projects.libraries.cachestore.api) + implementation(projects.features.enterprise.api) implementation(projects.services.toolbox.api) testCommonDependencies(libs) @@ -41,5 +42,6 @@ dependencies { testImplementation(projects.libraries.cachestore.test) testImplementation(projects.libraries.matrix.test) testImplementation(projects.libraries.wellknown.test) + testImplementation(projects.features.enterprise.test) testImplementation(projects.services.toolbox.test) } diff --git a/libraries/wellknown/impl/src/main/kotlin/io/element/android/libraries/wellknown/impl/DefaultElementWellKnownParser.kt b/libraries/wellknown/impl/src/main/kotlin/io/element/android/libraries/wellknown/impl/DefaultElementWellKnownParser.kt new file mode 100644 index 0000000000..4cf72366e0 --- /dev/null +++ b/libraries/wellknown/impl/src/main/kotlin/io/element/android/libraries/wellknown/impl/DefaultElementWellKnownParser.kt @@ -0,0 +1,27 @@ +/* + * 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.libraries.wellknown.impl + +import dev.zacsweers.metro.AppScope +import dev.zacsweers.metro.ContributesBinding +import io.element.android.libraries.androidutils.json.JsonProvider +import io.element.android.libraries.core.extensions.runCatchingExceptions +import io.element.android.libraries.wellknown.api.ElementWellKnown +import io.element.android.libraries.wellknown.api.ElementWellKnownParser + +@ContributesBinding(AppScope::class) +class DefaultElementWellKnownParser( + private val jsonProvider: JsonProvider, +) : ElementWellKnownParser { + override fun parse(json: String): Result { + return runCatchingExceptions { + val decoder = jsonProvider() + decoder.decodeFromString(json).map() + } + } +} diff --git a/libraries/wellknown/impl/src/main/kotlin/io/element/android/libraries/wellknown/impl/DefaultSessionWellknownRetriever.kt b/libraries/wellknown/impl/src/main/kotlin/io/element/android/libraries/wellknown/impl/DefaultSessionWellknownRetriever.kt index 3446cdcb65..66654dd228 100644 --- a/libraries/wellknown/impl/src/main/kotlin/io/element/android/libraries/wellknown/impl/DefaultSessionWellknownRetriever.kt +++ b/libraries/wellknown/impl/src/main/kotlin/io/element/android/libraries/wellknown/impl/DefaultSessionWellknownRetriever.kt @@ -9,13 +9,14 @@ package io.element.android.libraries.wellknown.impl import dev.zacsweers.metro.ContributesBinding -import io.element.android.libraries.androidutils.json.JsonProvider +import io.element.android.features.enterprise.api.EnterpriseService import io.element.android.libraries.core.extensions.mapCatchingExceptions import io.element.android.libraries.di.SessionScope import io.element.android.libraries.di.annotations.SessionCoroutineScope import io.element.android.libraries.matrix.api.MatrixClient import io.element.android.libraries.matrix.api.exception.ClientException import io.element.android.libraries.wellknown.api.ElementWellKnown +import io.element.android.libraries.wellknown.api.ElementWellKnownParser import io.element.android.libraries.wellknown.api.ElementWellknownStore import io.element.android.libraries.wellknown.api.SessionWellknownRetriever import io.element.android.libraries.wellknown.api.WellknownRetrieverResult @@ -26,14 +27,20 @@ import timber.log.Timber @ContributesBinding(SessionScope::class) class DefaultSessionWellknownRetriever( private val matrixClient: MatrixClient, - private val json: JsonProvider, @SessionCoroutineScope private val sessionCoroutineScope: CoroutineScope, private val elementWellknownStore: ElementWellknownStore, + private val elementWellKnownParser: ElementWellKnownParser, + private val enterpriseService: EnterpriseService, ) : SessionWellknownRetriever { private val domain by lazy { matrixClient.userIdServerName() } override suspend fun getElementWellKnown(): WellknownRetrieverResult { + val overriddenElementWellKnown = enterpriseService.overriddenElementWellKnown() + if (overriddenElementWellKnown != null) { + return WellknownRetrieverResult.Success(overriddenElementWellKnown) + } + val cacheData = elementWellknownStore.get(domain) return when (cacheData) { is WellknownRetrieverResult.Success -> { @@ -69,7 +76,7 @@ class DefaultSessionWellknownRetriever( .getUrl(url) .mapCatchingExceptions { val data = String(it) - val parsed = json().decodeFromString(data).map() + val parsed = elementWellKnownParser.parse(data).getOrThrow() // Also store in cache, if valid elementWellknownStore.update(domain, data) .onFailure { exception -> diff --git a/libraries/wellknown/impl/src/main/kotlin/io/element/android/libraries/wellknown/impl/DefaultWellKnownStore.kt b/libraries/wellknown/impl/src/main/kotlin/io/element/android/libraries/wellknown/impl/DefaultWellKnownStore.kt index c3cfcc5019..50c8caeafc 100644 --- a/libraries/wellknown/impl/src/main/kotlin/io/element/android/libraries/wellknown/impl/DefaultWellKnownStore.kt +++ b/libraries/wellknown/impl/src/main/kotlin/io/element/android/libraries/wellknown/impl/DefaultWellKnownStore.kt @@ -9,11 +9,11 @@ package io.element.android.libraries.wellknown.impl import dev.zacsweers.metro.AppScope import dev.zacsweers.metro.ContributesBinding -import io.element.android.libraries.androidutils.json.JsonProvider import io.element.android.libraries.cachestore.api.CacheData import io.element.android.libraries.cachestore.api.CacheStore import io.element.android.libraries.core.extensions.runCatchingExceptions import io.element.android.libraries.wellknown.api.ElementWellKnown +import io.element.android.libraries.wellknown.api.ElementWellKnownParser import io.element.android.libraries.wellknown.api.ElementWellknownStore import io.element.android.libraries.wellknown.api.WellknownRetrieverResult import io.element.android.services.toolbox.api.systemclock.SystemClock @@ -21,14 +21,14 @@ import io.element.android.services.toolbox.api.systemclock.SystemClock @ContributesBinding(AppScope::class) class DefaultWellKnownStore( private val cacheStore: CacheStore, - private val json: JsonProvider, + private val elementWellKnownParser: ElementWellKnownParser, private val systemClock: SystemClock, ) : ElementWellknownStore { override suspend fun get(domain: String): WellknownRetrieverResult { return runCatchingExceptions { val cachedData = cacheStore.getData(key(domain)) if (cachedData != null) { - val data = json().decodeFromString(cachedData.value).map() + val data = elementWellKnownParser.parse(cachedData.value).getOrThrow() if (systemClock.epochMillis() > cachedData.updatedAt + CACHE_VALIDITY_MILLIS) { WellknownRetrieverResult.Outdated(data) } else { diff --git a/libraries/wellknown/impl/src/main/kotlin/io/element/android/libraries/wellknown/impl/DefaultWellknownRetriever.kt b/libraries/wellknown/impl/src/main/kotlin/io/element/android/libraries/wellknown/impl/DefaultWellknownRetriever.kt index a43584d542..10f668cfb0 100644 --- a/libraries/wellknown/impl/src/main/kotlin/io/element/android/libraries/wellknown/impl/DefaultWellknownRetriever.kt +++ b/libraries/wellknown/impl/src/main/kotlin/io/element/android/libraries/wellknown/impl/DefaultWellknownRetriever.kt @@ -10,6 +10,7 @@ package io.element.android.libraries.wellknown.impl import dev.zacsweers.metro.AppScope import dev.zacsweers.metro.ContributesBinding +import io.element.android.features.enterprise.api.EnterpriseService import io.element.android.libraries.androidutils.json.JsonProvider import io.element.android.libraries.core.extensions.runCatchingExceptions import io.element.android.libraries.core.uri.ensureProtocol @@ -28,8 +29,14 @@ class DefaultWellknownRetriever( private val retrofitFactory: RetrofitFactory, private val elementWellknownStore: ElementWellknownStore, private val jsonProvider: JsonProvider, + private val enterpriseService: EnterpriseService, ) : WellknownRetriever { override suspend fun getElementWellKnown(baseUrl: String): WellknownRetrieverResult { + val overriddenElementWellKnown = enterpriseService.overriddenElementWellKnown() + if (overriddenElementWellKnown != null) { + return WellknownRetrieverResult.Success(overriddenElementWellKnown) + } + val domain = URL(baseUrl).host return buildWellknownApi(baseUrl) .map { wellknownApi -> diff --git a/libraries/wellknown/impl/src/test/kotlin/io/element/android/libraries/wellknown/impl/DefaultSessionWellknownRetrieverTest.kt b/libraries/wellknown/impl/src/test/kotlin/io/element/android/libraries/wellknown/impl/DefaultSessionWellknownRetrieverTest.kt index 6a2a12774b..f54cf919d9 100644 --- a/libraries/wellknown/impl/src/test/kotlin/io/element/android/libraries/wellknown/impl/DefaultSessionWellknownRetrieverTest.kt +++ b/libraries/wellknown/impl/src/test/kotlin/io/element/android/libraries/wellknown/impl/DefaultSessionWellknownRetrieverTest.kt @@ -11,15 +11,16 @@ package io.element.android.libraries.wellknown.impl import com.google.common.truth.Truth.assertThat +import io.element.android.features.enterprise.test.FakeEnterpriseService import io.element.android.features.wellknown.test.FakeElementWellknownStore import io.element.android.features.wellknown.test.anElementWellKnown import io.element.android.libraries.androidutils.json.DefaultJsonProvider -import io.element.android.libraries.androidutils.json.JsonProvider import io.element.android.libraries.matrix.api.exception.ClientException import io.element.android.libraries.matrix.test.AN_EXCEPTION import io.element.android.libraries.matrix.test.FakeMatrixClient import io.element.android.libraries.wellknown.api.CustomRecoveryPassphrase import io.element.android.libraries.wellknown.api.ElementWellKnown +import io.element.android.libraries.wellknown.api.ElementWellKnownParser import io.element.android.libraries.wellknown.api.WellknownRetrieverResult import io.element.android.tests.testutils.lambda.lambdaError import io.element.android.tests.testutils.lambda.lambdaRecorder @@ -276,7 +277,7 @@ class DefaultSessionWellknownRetrieverTest { Result.success("{}".toByteArray()) }, cacheStore = cacheStore, - jsonProvider = JsonProvider { error("Failed to parse JSON") } + elementWellKnownParser = { Result.failure(IllegalStateException("Failed to parse JSON")) } ) assertThat(sut.getElementWellKnown()).isInstanceOf(WellknownRetrieverResult.Error::class.java) // Ensure that the cache is deleted after the failure to parse it @@ -320,20 +321,43 @@ class DefaultSessionWellknownRetrieverTest { ) } + @Test + fun `get element wellknown was overridden`() = runTest { + val getLambda = lambdaRecorder> { Result.failure(IllegalStateException("BOOM")) } + val wellKnown = anElementWellKnown() + + val sut = createDefaultSessionWellknownRetriever( + getUrlLambda = getLambda, + enterpriseService = FakeEnterpriseService( + overrideWellKnownResult = { wellKnown } + ) + ) + + // The overridden value is returned + assertThat(sut.getElementWellKnown()).isEqualTo( + WellknownRetrieverResult.Success(wellKnown) + ) + + // And the endpoint is never hit + getLambda.assertions().isNeverCalled() + } + private fun parsedWellKnownContent() = DefaultJsonProvider().invoke().decodeFromString(WELLKNOWN_CONTENT).map() private fun TestScope.createDefaultSessionWellknownRetriever( cacheStore: FakeElementWellknownStore = FakeElementWellknownStore(), getUrlLambda: (String) -> Result, - jsonProvider: JsonProvider = DefaultJsonProvider(), + elementWellKnownParser: ElementWellKnownParser = DefaultElementWellKnownParser(DefaultJsonProvider()), + enterpriseService: FakeEnterpriseService = FakeEnterpriseService(overrideWellKnownResult = { null }), ) = DefaultSessionWellknownRetriever( matrixClient = FakeMatrixClient( userIdServerNameLambda = { "user.domain.org" }, getUrlLambda = getUrlLambda, ), - json = jsonProvider, sessionCoroutineScope = backgroundScope, elementWellknownStore = cacheStore, + elementWellKnownParser = elementWellKnownParser, + enterpriseService = enterpriseService, ) companion object { diff --git a/libraries/wellknown/impl/src/test/kotlin/io/element/android/libraries/wellknown/impl/DefaultWellKnownStoreTest.kt b/libraries/wellknown/impl/src/test/kotlin/io/element/android/libraries/wellknown/impl/DefaultWellKnownStoreTest.kt index 11ec521fed..b53041faf8 100644 --- a/libraries/wellknown/impl/src/test/kotlin/io/element/android/libraries/wellknown/impl/DefaultWellKnownStoreTest.kt +++ b/libraries/wellknown/impl/src/test/kotlin/io/element/android/libraries/wellknown/impl/DefaultWellKnownStoreTest.kt @@ -13,6 +13,7 @@ import io.element.android.libraries.androidutils.json.DefaultJsonProvider import io.element.android.libraries.cachestore.api.CacheData import io.element.android.libraries.sessionstorage.test.InMemoryCacheStore import io.element.android.libraries.wellknown.api.CustomRecoveryPassphrase +import io.element.android.libraries.wellknown.api.ElementWellKnownParser import io.element.android.libraries.wellknown.api.WellknownRetrieverResult import io.element.android.services.toolbox.test.systemclock.A_FAKE_TIMESTAMP import io.element.android.services.toolbox.test.systemclock.FakeSystemClock @@ -150,9 +151,10 @@ class DefaultWellKnownStoreTest { private fun createDefaultWellKnownStore( cacheStore: InMemoryCacheStore = InMemoryCacheStore(), systemClock: FakeSystemClock = FakeSystemClock(), + elementWellKnownParser: ElementWellKnownParser = DefaultElementWellKnownParser(jsonProvider), ) = DefaultWellKnownStore( cacheStore = cacheStore, - json = jsonProvider, systemClock = systemClock, + elementWellKnownParser = elementWellKnownParser, ) } diff --git a/libraries/wellknown/impl/src/test/kotlin/io/element/android/libraries/wellknown/impl/DefaultWellknownRetrieverTest.kt b/libraries/wellknown/impl/src/test/kotlin/io/element/android/libraries/wellknown/impl/DefaultWellknownRetrieverTest.kt index 3ee5b2b91f..96ae4c2b17 100644 --- a/libraries/wellknown/impl/src/test/kotlin/io/element/android/libraries/wellknown/impl/DefaultWellknownRetrieverTest.kt +++ b/libraries/wellknown/impl/src/test/kotlin/io/element/android/libraries/wellknown/impl/DefaultWellknownRetrieverTest.kt @@ -11,6 +11,7 @@ package io.element.android.libraries.wellknown.impl import com.google.common.truth.Truth.assertThat +import io.element.android.features.enterprise.test.FakeEnterpriseService import io.element.android.features.wellknown.test.FakeElementWellknownStore import io.element.android.features.wellknown.test.anElementWellKnown import io.element.android.libraries.androidutils.json.DefaultJsonProvider @@ -19,6 +20,7 @@ import io.element.android.libraries.network.RetrofitFactory import io.element.android.libraries.wellknown.api.CustomRecoveryPassphrase import io.element.android.libraries.wellknown.api.ElementWellKnown import io.element.android.libraries.wellknown.api.WellknownRetrieverResult +import io.element.android.tests.testutils.lambda.lambdaRecorder import io.mockk.every import io.mockk.mockk import io.mockk.verify @@ -236,6 +238,27 @@ class DefaultWellknownRetrieverTest { assertThat(cacheStore.get(WELLKNOWN_URL)).isEqualTo(WellknownRetrieverResult.NotFound) } + @Test + fun `get element wellknown was overridden`() = runTest { + val getLambda = lambdaRecorder { mockCall() } + val wellKnown = anElementWellKnown() + + val sut = createDefaultWellknownRetriever( + callFactory = getLambda, + enterpriseService = FakeEnterpriseService( + overrideWellKnownResult = { wellKnown } + ) + ) + + // The overridden value is returned + assertThat(sut.getElementWellKnown(WELLKNOWN_URL)).isEqualTo( + WellknownRetrieverResult.Success(wellKnown) + ) + + // And the endpoint is never hit + getLambda.assertions().isNeverCalled() + } + private fun defaultResponse( body: String = WELLKNOWN_CONTENT, status: Int = 200, @@ -251,6 +274,7 @@ class DefaultWellknownRetrieverTest { callFactory: Call.Factory = Call.Factory { _: Request -> mockCall(defaultResponse()) }, cacheStore: FakeElementWellknownStore = FakeElementWellknownStore(), jsonProvider: JsonProvider = DefaultJsonProvider(), + enterpriseService: FakeEnterpriseService = FakeEnterpriseService(overrideWellKnownResult = { null }), ) = DefaultWellknownRetriever( retrofitFactory = RetrofitFactory( callFactory = { callFactory }, @@ -258,6 +282,7 @@ class DefaultWellknownRetrieverTest { ), jsonProvider = jsonProvider, elementWellknownStore = cacheStore, + enterpriseService = enterpriseService, ) companion object { diff --git a/tests/konsist/src/test/kotlin/io/element/android/tests/konsist/KonsistPreviewTest.kt b/tests/konsist/src/test/kotlin/io/element/android/tests/konsist/KonsistPreviewTest.kt index 97def07130..deaa903e25 100644 --- a/tests/konsist/src/test/kotlin/io/element/android/tests/konsist/KonsistPreviewTest.kt +++ b/tests/konsist/src/test/kotlin/io/element/android/tests/konsist/KonsistPreviewTest.kt @@ -88,6 +88,8 @@ class KonsistPreviewTest { "BackgroundVerticalGradientPreview", "ColorAliasesPreview", "EmojiItemWithPopupPreview", + "EnterpriseExtraDeveloperOptionsRendererBottomSheetPreview", + "EnterpriseExtraDeveloperOptionsRendererListItemPreview", "FocusedEventPreview", "GradientFloatingActionButtonCircleShapePreview", "HeaderFooterPageScrollablePreview", @@ -164,6 +166,7 @@ class KonsistPreviewTest { "TimelineItemImageViewScanningContentPreview", "TimelineItemRedactedMessagesGroupPreview", "TimelineItemScanningContentFailedPreview", + "TimelineItemScanningContentNotFoundPreview", "TimelineItemScanningContentWithInvalidRepliesPreview", "TimelineItemScanningContentWithRepliesFailedPreview", "TimelineItemStickerViewScanningContentPreview", diff --git a/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components.customreaction_EmojiItemWithPopup_Day_0_en.png b/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components.customreaction_EmojiItemWithPopup_Day_0_en.png index a2b35f18ca..912b90b537 100644 --- a/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components.customreaction_EmojiItemWithPopup_Day_0_en.png +++ b/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components.customreaction_EmojiItemWithPopup_Day_0_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:c5572491b675a16724cd9e33ebb477c82edf285fa07d57ebef09c670fcaaddf1 -size 21285 +oid sha256:4746d11c30648f7c517b0880021e5a1dc6ed2819af6c800b081b0d842ac2c384 +size 5325 diff --git a/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components.event_ATimelineItemEventRow_Day_0_en.png b/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components.event_ATimelineItemEventRow_Day_0_en.png index 12bd190dd1..0ab00359b7 100644 --- a/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components.event_ATimelineItemEventRow_Day_0_en.png +++ b/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components.event_ATimelineItemEventRow_Day_0_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:ce15ca9f89274620728715e3448ce671e2253f4fed22a44035460e9a3709ca0b -size 647404 +oid sha256:7b5e6f4c5ec97e67bb20f03f25f18d9f32d5d1aed5ff30d161b331894ad03443 +size 647384 diff --git a/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_TimelineItemEventRowDisambiguated_Night_0_en.png b/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_TimelineItemEventRowDisambiguated_Night_0_en.png index f0b5506b89..9cbd5c1d95 100644 --- a/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_TimelineItemEventRowDisambiguated_Night_0_en.png +++ b/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_TimelineItemEventRowDisambiguated_Night_0_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:04ea6c2947a21d3d4a3d43e9c4750c4f2a49056536a4da3f34c95df8353e9de3 -size 377990 +oid sha256:d0e170b4bea262de612bf3374d475fcd25470ff91b7554d20809c51857a78cec +size 377963 diff --git a/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_TimelineItemEventRowWithReplyInformative_Day_1_en.png b/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_TimelineItemEventRowWithReplyInformative_Day_1_en.png index 195aa04fe2..86018764ac 100644 --- a/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_TimelineItemEventRowWithReplyInformative_Day_1_en.png +++ b/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_TimelineItemEventRowWithReplyInformative_Day_1_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:76e5ae44362792d570cd82f3910c8bd0acde509b8418c5892e0385e7d636f042 -size 370223 +oid sha256:8344427a0fe87cbf0883ff53a9ee4dcf90976a7011f6618d85961df48b2c53a9 +size 370228 diff --git a/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_TimelineItemEventRowWithReplyInformative_Night_1_en.png b/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_TimelineItemEventRowWithReplyInformative_Night_1_en.png index db4ea8296a..c6d4541184 100644 --- a/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_TimelineItemEventRowWithReplyInformative_Night_1_en.png +++ b/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_TimelineItemEventRowWithReplyInformative_Night_1_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:2f0d24b8011564ee7a8b2f8c2e6a24eda668ee42d451d862f884acb7926aa06c -size 368529 +oid sha256:c00e504593d8eb61b598f05f46ee4d591757975a80c0b4227b240847d2cd4868 +size 368510 diff --git a/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_TimelineItemEventRowWithReplyOther_Day_1_en.png b/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_TimelineItemEventRowWithReplyOther_Day_1_en.png index 73b7e674e2..7ddac02717 100644 --- a/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_TimelineItemEventRowWithReplyOther_Day_1_en.png +++ b/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_TimelineItemEventRowWithReplyOther_Day_1_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:991deacdfb7bc371a2df960a2364ae3b2187e588aa5afe7f39409e367040dd9c -size 363893 +oid sha256:a4ac79f3b8fb4e231244bd96b244a4f2526d6ed28d558f9d50734d83bbb74992 +size 363909 diff --git a/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_TimelineItemEventRowWithReplyOther_Night_1_en.png b/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_TimelineItemEventRowWithReplyOther_Night_1_en.png index b6e4650d9d..4e17de6908 100644 --- a/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_TimelineItemEventRowWithReplyOther_Night_1_en.png +++ b/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_TimelineItemEventRowWithReplyOther_Night_1_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:2cd357a1fbaa425eca95587bff2f768a45e773f983f75664875653ba1900e534 -size 361625 +oid sha256:c1e15400fa2c5ee6087316501445c551a3932b65e16de31e68acc5efbd16a559 +size 361603 diff --git a/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_TimelineItemEventRowWithReply_Day_11_en.png b/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_TimelineItemEventRowWithReply_Day_11_en.png index c4943b892c..e38cf03ad6 100644 --- a/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_TimelineItemEventRowWithReply_Day_11_en.png +++ b/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_TimelineItemEventRowWithReply_Day_11_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:4c410e853089cc2c4a2c48a00dd9a8babc8095aed72bb4625057444710559c6c -size 368129 +oid sha256:41a0e404dea7f52359b24b3ec3926b1405429b165cfed44c63b3922ea6d3cb46 +size 368114 diff --git a/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_TimelineItemEventRowWithReply_Day_1_en.png b/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_TimelineItemEventRowWithReply_Day_1_en.png index b5dac8434c..68f8148879 100644 --- a/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_TimelineItemEventRowWithReply_Day_1_en.png +++ b/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_TimelineItemEventRowWithReply_Day_1_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:1a92f8af94682facac66d4aacb6e49f345561c15be2f8b689041b78aeaaae831 -size 345062 +oid sha256:6ca8cf82aa8ab1bdad56a27584b27789402aeb7ad8fadd038280a376fb75a72c +size 345094 diff --git a/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_TimelineItemEventRowWithReply_Day_3_en.png b/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_TimelineItemEventRowWithReply_Day_3_en.png index cececc229a..b5032c29b3 100644 --- a/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_TimelineItemEventRowWithReply_Day_3_en.png +++ b/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_TimelineItemEventRowWithReply_Day_3_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:f0c6dafaa41849af00d5097a85bd88e3a054a0a9e41c0466a08e6ff8dd6102b2 -size 356857 +oid sha256:dce23463c335d01eb67293cfcede5d85e96ab2ba035cc9a188d42e8e6866bc63 +size 356831 diff --git a/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_TimelineItemEventRowWithReply_Day_5_en.png b/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_TimelineItemEventRowWithReply_Day_5_en.png index d7b969fd5b..133fd3903f 100644 --- a/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_TimelineItemEventRowWithReply_Day_5_en.png +++ b/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_TimelineItemEventRowWithReply_Day_5_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:2528df873713755f542f61cd794080929586c1bd5f316c0378ce9e837c21d50b -size 397145 +oid sha256:426d1c844a8c88281c5fa4c61916d93278fdfd38f8cdf2dc54bf1a821f2de3eb +size 397167 diff --git a/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_TimelineItemEventRowWithReply_Day_7_en.png b/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_TimelineItemEventRowWithReply_Day_7_en.png index 9fcf389708..f67906a37c 100644 --- a/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_TimelineItemEventRowWithReply_Day_7_en.png +++ b/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_TimelineItemEventRowWithReply_Day_7_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:9daeee1aaa04247da3c8bb5aaae9947aab1ed2d2057995e53d6ebdb63e5cd356 -size 355848 +oid sha256:ffa68c8398d789444151855496e5df4ffa03218a383db6ea46fd4f979829b823 +size 355831 diff --git a/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_TimelineItemEventRowWithReply_Day_9_en.png b/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_TimelineItemEventRowWithReply_Day_9_en.png index 0021619c44..b10f9741b9 100644 --- a/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_TimelineItemEventRowWithReply_Day_9_en.png +++ b/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_TimelineItemEventRowWithReply_Day_9_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:7b23d3a37774283067a8919b8c332b1bb5a79e90dceb7216b484b985491282e5 -size 355389 +oid sha256:3ec1b0244dab22414c6719b3309426e13128d0c70fb67dc66cd8a60d42521fd0 +size 355411 diff --git a/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_TimelineItemEventRowWithReply_Night_11_en.png b/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_TimelineItemEventRowWithReply_Night_11_en.png index c081fa16a5..5243218ae3 100644 --- a/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_TimelineItemEventRowWithReply_Night_11_en.png +++ b/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_TimelineItemEventRowWithReply_Night_11_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:6a92bcf5885322e11a706071969fb674b1f6e60e021af153aaa125baa4a602ae -size 366285 +oid sha256:9a85db2f5958db867578663533f204b2e803372d470da890fd8056ffed0cf46c +size 366254 diff --git a/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_TimelineItemEventRowWithReply_Night_1_en.png b/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_TimelineItemEventRowWithReply_Night_1_en.png index 47a9a6b630..b6d1f07279 100644 --- a/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_TimelineItemEventRowWithReply_Night_1_en.png +++ b/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_TimelineItemEventRowWithReply_Night_1_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:54372845e922d047408dd960d048b9b5eae2263d589117d8e7d197741aa34f32 -size 342827 +oid sha256:4bee12a6bdb18fea5ac6997671bfcb903296da7278cf69b2456330066ca31dfb +size 342870 diff --git a/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_TimelineItemEventRowWithReply_Night_3_en.png b/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_TimelineItemEventRowWithReply_Night_3_en.png index 5cc5cfe4fc..5cdad1df92 100644 --- a/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_TimelineItemEventRowWithReply_Night_3_en.png +++ b/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_TimelineItemEventRowWithReply_Night_3_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:6524cc87257cc9d3f135904f4e14594b56df695e71fe576418d2319c472d710b -size 355285 +oid sha256:9e2d8caf5aaae7d3406c703288e491f328552f0acd18e56afd5265b4ceaf1cd1 +size 355272 diff --git a/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_TimelineItemEventRowWithReply_Night_5_en.png b/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_TimelineItemEventRowWithReply_Night_5_en.png index b51a89586b..0eb106f4a9 100644 --- a/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_TimelineItemEventRowWithReply_Night_5_en.png +++ b/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_TimelineItemEventRowWithReply_Night_5_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:e642229c58169775fe702769a306bbef22698516ae6f7ac75a761213c3f195fa -size 395446 +oid sha256:217ac95bf476c53d2dc6d3d0143b21312bf38b8ab86c8dfd4f9360582b584f9d +size 395476 diff --git a/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_TimelineItemEventRowWithReply_Night_7_en.png b/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_TimelineItemEventRowWithReply_Night_7_en.png index 40105c1498..9d617f6688 100644 --- a/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_TimelineItemEventRowWithReply_Night_7_en.png +++ b/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_TimelineItemEventRowWithReply_Night_7_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:5ed24d190f10c079f8cf176404372d40eb25cc78ce595a22febc540315057b86 -size 354075 +oid sha256:dabad9dcd5b8f0d4bb964a0187ad7c94b023b04552dacd29a077daddfd48d550 +size 354052 diff --git a/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_TimelineItemEventRowWithReply_Night_9_en.png b/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_TimelineItemEventRowWithReply_Night_9_en.png index c9227ebf94..c8306263a0 100644 --- a/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_TimelineItemEventRowWithReply_Night_9_en.png +++ b/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_TimelineItemEventRowWithReply_Night_9_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:e614f4a8657637c584a283d69124236d00fe1251c2b8d739c5688a57a6fd152e -size 353693 +oid sha256:756f0cff90ddd61adce2f467c0384d74d430f6d51c091e4980e45bcc9ee6f0fd +size 353705 diff --git a/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_TimelineItemScanningContentNotFound_Day_0_en.png b/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_TimelineItemScanningContentNotFound_Day_0_en.png new file mode 100644 index 0000000000..3c30442331 --- /dev/null +++ b/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_TimelineItemScanningContentNotFound_Day_0_en.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:d082ac0333068f5da70cf40d310d321e6304999ddb6288b680350cfc3a7f40c0 +size 31006 diff --git a/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_TimelineItemScanningContentNotFound_Night_0_en.png b/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_TimelineItemScanningContentNotFound_Night_0_en.png new file mode 100644 index 0000000000..688fa2736b --- /dev/null +++ b/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_TimelineItemScanningContentNotFound_Night_0_en.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:f275ffe26e055fd8f912b7234eae39dfb9f597e23c408dcb58e46d164ce391e9 +size 31959 diff --git a/tests/uitests/src/test/snapshots/images/features.messages.impl_MessagesViewA11y_en.png b/tests/uitests/src/test/snapshots/images/features.messages.impl_MessagesViewA11y_en.png index b2b3f0b813..f47e74ab7b 100644 --- a/tests/uitests/src/test/snapshots/images/features.messages.impl_MessagesViewA11y_en.png +++ b/tests/uitests/src/test/snapshots/images/features.messages.impl_MessagesViewA11y_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:02c4892eaa7d27c867266c428374b64e5915ec50ddcdf8b1d532e1cbc6f56462 -size 130436 +oid sha256:5823ae9a382421609200d569799505706180b94c6923f315caa81f8767ac58f8 +size 131340 diff --git a/tests/uitests/src/test/snapshots/images/features.preferences.impl.blockedusers_BlockedUsersView_Day_5_en.png b/tests/uitests/src/test/snapshots/images/features.preferences.impl.blockedusers_BlockedUsersView_Day_5_en.png index 7cca911c45..2af459c158 100644 --- a/tests/uitests/src/test/snapshots/images/features.preferences.impl.blockedusers_BlockedUsersView_Day_5_en.png +++ b/tests/uitests/src/test/snapshots/images/features.preferences.impl.blockedusers_BlockedUsersView_Day_5_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:26e14b77fa3c3aeaea58782309e6de8b9047e07945009322990ebf5f4c283309 -size 52770 +oid sha256:28a95d4b7ebca92c4e0467f3ecd9acdaf7f6257604d190f5d088a9a25e87d637 +size 55305 diff --git a/tests/uitests/src/test/snapshots/images/features.preferences.impl.blockedusers_BlockedUsersView_Night_4_en.png b/tests/uitests/src/test/snapshots/images/features.preferences.impl.blockedusers_BlockedUsersView_Night_4_en.png index a68f886f73..616c06bf46 100644 --- a/tests/uitests/src/test/snapshots/images/features.preferences.impl.blockedusers_BlockedUsersView_Night_4_en.png +++ b/tests/uitests/src/test/snapshots/images/features.preferences.impl.blockedusers_BlockedUsersView_Night_4_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:e5a2e306087a967849f61872b56a83f194d1a76df5723f0bbae6e6e2f4a98c63 -size 55725 +oid sha256:0ce2519906f1aaf34700ca9ba4bdeaa72030f1f5aff3f7e24352a1435ac67d98 +size 53966 diff --git a/tests/uitests/src/test/snapshots/images/features.preferences.impl.userstatus_UserStatusView_Day_5_en.png b/tests/uitests/src/test/snapshots/images/features.preferences.impl.userstatus_UserStatusView_Day_5_en.png index 270dbe6d1e..7ef9b7ae0a 100644 --- a/tests/uitests/src/test/snapshots/images/features.preferences.impl.userstatus_UserStatusView_Day_5_en.png +++ b/tests/uitests/src/test/snapshots/images/features.preferences.impl.userstatus_UserStatusView_Day_5_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:195338046951366fd2345fdc8471e3e2b2786723c8bfffa9fa9057929c608afb -size 12113 +oid sha256:d19e7a09114e76294a0626e5d617cf55fe7c13a0188a7d5b364f57c0d9daedc1 +size 12123 diff --git a/tests/uitests/src/test/snapshots/images/features.preferences.impl.userstatus_UserStatusView_Night_6_en.png b/tests/uitests/src/test/snapshots/images/features.preferences.impl.userstatus_UserStatusView_Night_6_en.png index ce1258d2ac..8e1b9c99d2 100644 --- a/tests/uitests/src/test/snapshots/images/features.preferences.impl.userstatus_UserStatusView_Night_6_en.png +++ b/tests/uitests/src/test/snapshots/images/features.preferences.impl.userstatus_UserStatusView_Night_6_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:ce754ce205fd864e01828659aff42ab19dccf7c921c1c733ed1757f1b2122309 -size 11403 +oid sha256:66f6d0d6b03ee4c999cd4edc9c6ae567d31b8b537ca6f9cc8fbe436d06ce80ab +size 11643 diff --git a/tests/uitests/src/test/snapshots/images/features.roommembermoderation.impl_RoomMemberModerationView_Day_5_en.png b/tests/uitests/src/test/snapshots/images/features.roommembermoderation.impl_RoomMemberModerationView_Day_5_en.png index 5c597300e4..73b8b8e50c 100644 --- a/tests/uitests/src/test/snapshots/images/features.roommembermoderation.impl_RoomMemberModerationView_Day_5_en.png +++ b/tests/uitests/src/test/snapshots/images/features.roommembermoderation.impl_RoomMemberModerationView_Day_5_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:21aee17ee9a292bb2f0d3d2ec2db565ebb8d5df753454a5a002f033ed5ed39c5 -size 3853 +oid sha256:e8a3ad99763929d2783147814e44fa9ec7e7efb7b99949e3580f23c38fb5d971 +size 9398 diff --git a/tests/uitests/src/test/snapshots/images/features.roommembermoderation.impl_RoomMemberModerationView_Day_7_en.png b/tests/uitests/src/test/snapshots/images/features.roommembermoderation.impl_RoomMemberModerationView_Day_7_en.png index f8a1f24b34..5c597300e4 100644 --- a/tests/uitests/src/test/snapshots/images/features.roommembermoderation.impl_RoomMemberModerationView_Day_7_en.png +++ b/tests/uitests/src/test/snapshots/images/features.roommembermoderation.impl_RoomMemberModerationView_Day_7_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:1342b6427f5b2e3075ae3ccee60bf1d3b11afaccf3e152643d6ef2d65c21b54e -size 9108 +oid sha256:21aee17ee9a292bb2f0d3d2ec2db565ebb8d5df753454a5a002f033ed5ed39c5 +size 3853 diff --git a/tests/uitests/src/test/snapshots/images/features.roommembermoderation.impl_RoomMemberModerationView_Night_5_en.png b/tests/uitests/src/test/snapshots/images/features.roommembermoderation.impl_RoomMemberModerationView_Night_5_en.png index 4ae7279fe7..d47bf90664 100644 --- a/tests/uitests/src/test/snapshots/images/features.roommembermoderation.impl_RoomMemberModerationView_Night_5_en.png +++ b/tests/uitests/src/test/snapshots/images/features.roommembermoderation.impl_RoomMemberModerationView_Night_5_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:410a8596d4c70b9a3856d959d6d71ade8e831e8581ff410c9900957a93b3eb50 -size 8114 +oid sha256:520cae2544153ba45f8fe4b021286c2d22da06aa1b60be7f1b13879723ff994c +size 3664 diff --git a/tests/uitests/src/test/snapshots/images/features.roommembermoderation.impl_RoomMemberModerationView_Night_7_en.png b/tests/uitests/src/test/snapshots/images/features.roommembermoderation.impl_RoomMemberModerationView_Night_7_en.png index d47bf90664..a87d89c701 100644 --- a/tests/uitests/src/test/snapshots/images/features.roommembermoderation.impl_RoomMemberModerationView_Night_7_en.png +++ b/tests/uitests/src/test/snapshots/images/features.roommembermoderation.impl_RoomMemberModerationView_Night_7_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:520cae2544153ba45f8fe4b021286c2d22da06aa1b60be7f1b13879723ff994c -size 3664 +oid sha256:0f3a0cb5d9bae6725a1c527f3d9575aabf85d3edf63a28d9faa23f4f0b65e2d0 +size 7624 diff --git a/tests/uitests/src/test/snapshots/images/libraries.designsystem.theme.components_HorizontalFloatingToolbarNoFab_Night_0_en.png b/tests/uitests/src/test/snapshots/images/libraries.designsystem.theme.components_HorizontalFloatingToolbarNoFab_Night_0_en.png index 52fd9b9693..fedead0fa8 100644 --- a/tests/uitests/src/test/snapshots/images/libraries.designsystem.theme.components_HorizontalFloatingToolbarNoFab_Night_0_en.png +++ b/tests/uitests/src/test/snapshots/images/libraries.designsystem.theme.components_HorizontalFloatingToolbarNoFab_Night_0_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:58b9491aaa5554b89d86c62a5c9c44975367538c6baa5562f8dc5768f76d8264 -size 8705 +oid sha256:4811667dec0f32accc5e2c8a5dd5c0b34017fcff8d1e0376ee7a4708426bca0f +size 9838 diff --git a/tests/uitests/src/test/snapshots/images/libraries.designsystem.theme.components_HorizontalFloatingToolbar_Night_0_en.png b/tests/uitests/src/test/snapshots/images/libraries.designsystem.theme.components_HorizontalFloatingToolbar_Night_0_en.png index 687e0d436a..4da2a98aca 100644 --- a/tests/uitests/src/test/snapshots/images/libraries.designsystem.theme.components_HorizontalFloatingToolbar_Night_0_en.png +++ b/tests/uitests/src/test/snapshots/images/libraries.designsystem.theme.components_HorizontalFloatingToolbar_Night_0_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:d57df7110371c9224e232b707d6a1b10ce14afcb56c803a78220792f2a0d4cf2 -size 11354 +oid sha256:ef0dc4d53daeb986f378b6e4d85928b4b6729336c89cf21e642c88c53688a3ab +size 10292 diff --git a/tools/dependencies/checkDependencies.py b/tools/dependencies/checkDependencies.py index 64ae6341e6..5cb1a4f70a 100755 --- a/tools/dependencies/checkDependencies.py +++ b/tools/dependencies/checkDependencies.py @@ -35,7 +35,7 @@ def checkThatModulesExist(dependencies): line = line.split(" ") for elem in line: if ":" in elem: - modules.add(elem) + modules.add(elem.replace("'", "")) for module in modules: path = "." + module.replace(":", "/") + "/build.gradle.kts" if not os.path.exists(path): @@ -51,12 +51,12 @@ def checkThatThereIsNoTestDependency(dependencies): currentProject = "" for line in dependencies: if line.startswith("+--- project "): - currentProject = line.split(" ")[2] + currentProject = line.split(" ")[2].replace("'", "") else: if ":test" in currentProject: continue else: - subProject = line.split(" ")[-1] + subProject = line.split(" ")[-1].replace("'", "") if subProject.endswith(":test") or ":tests:" in subProject and "detekt-rules" not in subProject: error = "Error: '" + currentProject + "' depends on the test project '" + subProject + "'\n" error += " Please replace occurrence(s) of 'implementation(projects" + subProject.replace(":", ".") + ")'"