mirror of
https://github.com/Novaloop-AG/element-x-android.git
synced 2026-11-04 20:01:55 +00:00
Merge branch 'develop' into feature/valere/timeline_active_call_rendering
This commit is contained in:
@@ -51,7 +51,7 @@ jobs:
|
|||||||
ref: ${{ github.event_name == 'pull_request' && github.event.pull_request.head.sha || github.ref }}
|
ref: ${{ github.event_name == 'pull_request' && github.event.pull_request.head.sha || github.ref }}
|
||||||
persist-credentials: false
|
persist-credentials: false
|
||||||
- name: Use JDK 21
|
- name: Use JDK 21
|
||||||
uses: actions/setup-java@1bcf9fb12cf4aa7d266a90ae39939e61372fe520 # v5.4.0
|
uses: actions/setup-java@0f481fcb613427c0f801b606911222b5b6f3083a # v5.5.0
|
||||||
with:
|
with:
|
||||||
distribution: 'temurin' # See 'Supported distributions' for available options
|
distribution: 'temurin' # See 'Supported distributions' for available options
|
||||||
java-version: '21'
|
java-version: '21'
|
||||||
|
|||||||
@@ -56,7 +56,7 @@ jobs:
|
|||||||
- name: Clone submodules
|
- name: Clone submodules
|
||||||
run: git submodule update --init --recursive
|
run: git submodule update --init --recursive
|
||||||
- name: Use JDK 21
|
- name: Use JDK 21
|
||||||
uses: actions/setup-java@1bcf9fb12cf4aa7d266a90ae39939e61372fe520 # v5.4.0
|
uses: actions/setup-java@0f481fcb613427c0f801b606911222b5b6f3083a # v5.5.0
|
||||||
with:
|
with:
|
||||||
distribution: 'temurin' # See 'Supported distributions' for available options
|
distribution: 'temurin' # See 'Supported distributions' for available options
|
||||||
java-version: '21'
|
java-version: '21'
|
||||||
|
|||||||
@@ -19,7 +19,7 @@ jobs:
|
|||||||
- name: ⏬ Checkout with LFS
|
- name: ⏬ Checkout with LFS
|
||||||
uses: nschloe/action-cached-lfs-checkout@385a8ecc719e50b8c71af6ab01a624b486b7c3bc # v1.2.5
|
uses: nschloe/action-cached-lfs-checkout@385a8ecc719e50b8c71af6ab01a624b486b7c3bc # v1.2.5
|
||||||
- name: Use JDK 21
|
- name: Use JDK 21
|
||||||
uses: actions/setup-java@1bcf9fb12cf4aa7d266a90ae39939e61372fe520 # v5.4.0
|
uses: actions/setup-java@0f481fcb613427c0f801b606911222b5b6f3083a # v5.5.0
|
||||||
with:
|
with:
|
||||||
distribution: 'temurin' # See 'Supported distributions' for available options
|
distribution: 'temurin' # See 'Supported distributions' for available options
|
||||||
java-version: '21'
|
java-version: '21'
|
||||||
|
|||||||
@@ -16,9 +16,8 @@ jobs:
|
|||||||
- uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
|
- uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
|
||||||
with:
|
with:
|
||||||
persist-credentials: false
|
persist-credentials: false
|
||||||
- uses: actions/setup-java@1bcf9fb12cf4aa7d266a90ae39939e61372fe520 # v5.4.0
|
- uses: actions/setup-java@0f481fcb613427c0f801b606911222b5b6f3083a # v5.5.0
|
||||||
name: Use JDK 21
|
name: Use JDK 21
|
||||||
if: (github.event_name == 'pull_request' && github.event.pull_request.fork == null) || github.event_name == 'workflow_dispatch'
|
|
||||||
with:
|
with:
|
||||||
distribution: 'temurin' # See 'Supported distributions' for available options
|
distribution: 'temurin' # See 'Supported distributions' for available options
|
||||||
java-version: '21'
|
java-version: '21'
|
||||||
|
|||||||
@@ -44,7 +44,7 @@ jobs:
|
|||||||
# https://github.com/actions/checkout/issues/881
|
# https://github.com/actions/checkout/issues/881
|
||||||
ref: ${{ github.ref }}
|
ref: ${{ github.ref }}
|
||||||
persist-credentials: false
|
persist-credentials: false
|
||||||
- uses: actions/setup-java@1bcf9fb12cf4aa7d266a90ae39939e61372fe520 # v5.4.0
|
- uses: actions/setup-java@0f481fcb613427c0f801b606911222b5b6f3083a # v5.5.0
|
||||||
name: Use JDK 21
|
name: Use JDK 21
|
||||||
with:
|
with:
|
||||||
distribution: 'temurin' # See 'Supported distributions' for available options
|
distribution: 'temurin' # See 'Supported distributions' for available options
|
||||||
|
|||||||
@@ -36,7 +36,7 @@ jobs:
|
|||||||
with:
|
with:
|
||||||
persist-credentials: false
|
persist-credentials: false
|
||||||
- name: Use JDK 21
|
- name: Use JDK 21
|
||||||
uses: actions/setup-java@1bcf9fb12cf4aa7d266a90ae39939e61372fe520 # v5.4.0
|
uses: actions/setup-java@0f481fcb613427c0f801b606911222b5b6f3083a # v5.5.0
|
||||||
with:
|
with:
|
||||||
distribution: 'temurin' # See 'Supported distributions' for available options
|
distribution: 'temurin' # See 'Supported distributions' for available options
|
||||||
java-version: '21'
|
java-version: '21'
|
||||||
|
|||||||
@@ -37,7 +37,7 @@ jobs:
|
|||||||
uses: nschloe/action-cached-lfs-checkout@385a8ecc719e50b8c71af6ab01a624b486b7c3bc # v1.2.5
|
uses: nschloe/action-cached-lfs-checkout@385a8ecc719e50b8c71af6ab01a624b486b7c3bc # v1.2.5
|
||||||
|
|
||||||
- name: Use JDK 21
|
- name: Use JDK 21
|
||||||
uses: actions/setup-java@1bcf9fb12cf4aa7d266a90ae39939e61372fe520 # v5.4.0
|
uses: actions/setup-java@0f481fcb613427c0f801b606911222b5b6f3083a # v5.5.0
|
||||||
with:
|
with:
|
||||||
distribution: 'temurin' # See 'Supported distributions' for available options
|
distribution: 'temurin' # See 'Supported distributions' for available options
|
||||||
java-version: '21'
|
java-version: '21'
|
||||||
@@ -80,7 +80,7 @@ jobs:
|
|||||||
with:
|
with:
|
||||||
persist-credentials: false
|
persist-credentials: false
|
||||||
- name: Use JDK 21
|
- name: Use JDK 21
|
||||||
uses: actions/setup-java@1bcf9fb12cf4aa7d266a90ae39939e61372fe520 # v5.4.0
|
uses: actions/setup-java@0f481fcb613427c0f801b606911222b5b6f3083a # v5.5.0
|
||||||
with:
|
with:
|
||||||
distribution: 'temurin' # See 'Supported distributions' for available options
|
distribution: 'temurin' # See 'Supported distributions' for available options
|
||||||
java-version: '21'
|
java-version: '21'
|
||||||
|
|||||||
@@ -69,7 +69,7 @@ jobs:
|
|||||||
with:
|
with:
|
||||||
persist-credentials: false
|
persist-credentials: false
|
||||||
- name: Use JDK 21
|
- name: Use JDK 21
|
||||||
uses: actions/setup-java@1bcf9fb12cf4aa7d266a90ae39939e61372fe520 # v5.4.0
|
uses: actions/setup-java@0f481fcb613427c0f801b606911222b5b6f3083a # v5.5.0
|
||||||
with:
|
with:
|
||||||
distribution: 'temurin' # See 'Supported distributions' for available options
|
distribution: 'temurin' # See 'Supported distributions' for available options
|
||||||
java-version: '21'
|
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' }}
|
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
|
run: git submodule update --init --recursive
|
||||||
- name: Use JDK 21
|
- name: Use JDK 21
|
||||||
uses: actions/setup-java@1bcf9fb12cf4aa7d266a90ae39939e61372fe520 # v5.4.0
|
uses: actions/setup-java@0f481fcb613427c0f801b606911222b5b6f3083a # v5.5.0
|
||||||
with:
|
with:
|
||||||
distribution: 'temurin' # See 'Supported distributions' for available options
|
distribution: 'temurin' # See 'Supported distributions' for available options
|
||||||
java-version: '21'
|
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' }}
|
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
|
run: git submodule update --init --recursive
|
||||||
- name: Use JDK 21
|
- name: Use JDK 21
|
||||||
uses: actions/setup-java@1bcf9fb12cf4aa7d266a90ae39939e61372fe520 # v5.4.0
|
uses: actions/setup-java@0f481fcb613427c0f801b606911222b5b6f3083a # v5.5.0
|
||||||
with:
|
with:
|
||||||
distribution: 'temurin' # See 'Supported distributions' for available options
|
distribution: 'temurin' # See 'Supported distributions' for available options
|
||||||
java-version: '21'
|
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' }}
|
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
|
run: git submodule update --init --recursive
|
||||||
- name: Use JDK 21
|
- name: Use JDK 21
|
||||||
uses: actions/setup-java@1bcf9fb12cf4aa7d266a90ae39939e61372fe520 # v5.4.0
|
uses: actions/setup-java@0f481fcb613427c0f801b606911222b5b6f3083a # v5.5.0
|
||||||
with:
|
with:
|
||||||
distribution: 'temurin' # See 'Supported distributions' for available options
|
distribution: 'temurin' # See 'Supported distributions' for available options
|
||||||
java-version: '21'
|
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' }}
|
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
|
run: git submodule update --init --recursive
|
||||||
- name: Use JDK 21
|
- name: Use JDK 21
|
||||||
uses: actions/setup-java@1bcf9fb12cf4aa7d266a90ae39939e61372fe520 # v5.4.0
|
uses: actions/setup-java@0f481fcb613427c0f801b606911222b5b6f3083a # v5.5.0
|
||||||
with:
|
with:
|
||||||
distribution: 'temurin' # See 'Supported distributions' for available options
|
distribution: 'temurin' # See 'Supported distributions' for available options
|
||||||
java-version: '21'
|
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' }}
|
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
|
run: git submodule update --init --recursive
|
||||||
- name: Use JDK 21
|
- name: Use JDK 21
|
||||||
uses: actions/setup-java@1bcf9fb12cf4aa7d266a90ae39939e61372fe520 # v5.4.0
|
uses: actions/setup-java@0f481fcb613427c0f801b606911222b5b6f3083a # v5.5.0
|
||||||
with:
|
with:
|
||||||
distribution: 'temurin' # See 'Supported distributions' for available options
|
distribution: 'temurin' # See 'Supported distributions' for available options
|
||||||
java-version: '21'
|
java-version: '21'
|
||||||
@@ -336,7 +336,7 @@ jobs:
|
|||||||
- uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
|
- uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
|
||||||
with:
|
with:
|
||||||
persist-credentials: false
|
persist-credentials: false
|
||||||
- uses: zizmorcore/zizmor-action@192e21d79ab29983730a13d1382995c2307fbcaa # v0.5.7
|
- uses: zizmorcore/zizmor-action@6599ee8b7a49aef6a770f63d261d214911a7ce02 # v0.6.0
|
||||||
|
|
||||||
upload_reports:
|
upload_reports:
|
||||||
name: Project Check Suite
|
name: Project Check Suite
|
||||||
|
|||||||
@@ -54,7 +54,7 @@ jobs:
|
|||||||
with:
|
with:
|
||||||
persist-credentials: false
|
persist-credentials: false
|
||||||
- name: ☕️ Use JDK 21
|
- name: ☕️ Use JDK 21
|
||||||
uses: actions/setup-java@1bcf9fb12cf4aa7d266a90ae39939e61372fe520 # v5.4.0
|
uses: actions/setup-java@0f481fcb613427c0f801b606911222b5b6f3083a # v5.5.0
|
||||||
with:
|
with:
|
||||||
distribution: 'temurin' # See 'Supported distributions' for available options
|
distribution: 'temurin' # See 'Supported distributions' for available options
|
||||||
java-version: '21'
|
java-version: '21'
|
||||||
|
|||||||
@@ -38,7 +38,7 @@ jobs:
|
|||||||
with:
|
with:
|
||||||
persist-credentials: false
|
persist-credentials: false
|
||||||
- name: Use JDK 21
|
- name: Use JDK 21
|
||||||
uses: actions/setup-java@1bcf9fb12cf4aa7d266a90ae39939e61372fe520 # v5.4.0
|
uses: actions/setup-java@0f481fcb613427c0f801b606911222b5b6f3083a # v5.5.0
|
||||||
with:
|
with:
|
||||||
distribution: 'temurin' # See 'Supported distributions' for available options
|
distribution: 'temurin' # See 'Supported distributions' for available options
|
||||||
java-version: '21'
|
java-version: '21'
|
||||||
@@ -82,7 +82,7 @@ jobs:
|
|||||||
- name: Clone submodules
|
- name: Clone submodules
|
||||||
run: git submodule update --init --recursive
|
run: git submodule update --init --recursive
|
||||||
- name: Use JDK 21
|
- name: Use JDK 21
|
||||||
uses: actions/setup-java@1bcf9fb12cf4aa7d266a90ae39939e61372fe520 # v5.4.0
|
uses: actions/setup-java@0f481fcb613427c0f801b606911222b5b6f3083a # v5.5.0
|
||||||
with:
|
with:
|
||||||
distribution: 'temurin' # See 'Supported distributions' for available options
|
distribution: 'temurin' # See 'Supported distributions' for available options
|
||||||
java-version: '21'
|
java-version: '21'
|
||||||
@@ -126,7 +126,7 @@ jobs:
|
|||||||
with:
|
with:
|
||||||
persist-credentials: false
|
persist-credentials: false
|
||||||
- name: Use JDK 21
|
- name: Use JDK 21
|
||||||
uses: actions/setup-java@1bcf9fb12cf4aa7d266a90ae39939e61372fe520 # v5.4.0
|
uses: actions/setup-java@0f481fcb613427c0f801b606911222b5b6f3083a # v5.5.0
|
||||||
with:
|
with:
|
||||||
distribution: 'temurin' # See 'Supported distributions' for available options
|
distribution: 'temurin' # See 'Supported distributions' for available options
|
||||||
java-version: '21'
|
java-version: '21'
|
||||||
|
|||||||
@@ -45,7 +45,7 @@ jobs:
|
|||||||
ref: ${{ github.event_name == 'pull_request' && github.event.pull_request.head.sha || github.ref }}
|
ref: ${{ github.event_name == 'pull_request' && github.event.pull_request.head.sha || github.ref }}
|
||||||
persist-credentials: false
|
persist-credentials: false
|
||||||
- name: Use JDK 21
|
- name: Use JDK 21
|
||||||
uses: actions/setup-java@1bcf9fb12cf4aa7d266a90ae39939e61372fe520 # v5.4.0
|
uses: actions/setup-java@0f481fcb613427c0f801b606911222b5b6f3083a # v5.5.0
|
||||||
with:
|
with:
|
||||||
distribution: 'temurin' # See 'Supported distributions' for available options
|
distribution: 'temurin' # See 'Supported distributions' for available options
|
||||||
java-version: '21'
|
java-version: '21'
|
||||||
|
|||||||
@@ -17,7 +17,7 @@ jobs:
|
|||||||
with:
|
with:
|
||||||
persist-credentials: false
|
persist-credentials: false
|
||||||
- name: Use JDK 21
|
- name: Use JDK 21
|
||||||
uses: actions/setup-java@1bcf9fb12cf4aa7d266a90ae39939e61372fe520 # v5.4.0
|
uses: actions/setup-java@0f481fcb613427c0f801b606911222b5b6f3083a # v5.5.0
|
||||||
with:
|
with:
|
||||||
distribution: 'temurin' # See 'Supported distributions' for available options
|
distribution: 'temurin' # See 'Supported distributions' for available options
|
||||||
java-version: '21'
|
java-version: '21'
|
||||||
|
|||||||
@@ -63,7 +63,7 @@ jobs:
|
|||||||
if: ${{ github.event_name != 'pull_request' || github.event.pull_request.head.repo.full_name == 'element-hq/element-x-android' }}
|
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
|
run: git submodule update --init --recursive
|
||||||
- name: ☕️ Use JDK 21
|
- name: ☕️ Use JDK 21
|
||||||
uses: actions/setup-java@1bcf9fb12cf4aa7d266a90ae39939e61372fe520 # v5.4.0
|
uses: actions/setup-java@0f481fcb613427c0f801b606911222b5b6f3083a # v5.5.0
|
||||||
with:
|
with:
|
||||||
distribution: 'temurin' # See 'Supported distributions' for available options
|
distribution: 'temurin' # See 'Supported distributions' for available options
|
||||||
java-version: '21'
|
java-version: '21'
|
||||||
|
|||||||
+1
-1
Submodule enterprise updated: cca96c4fc2...60de13ffd7
+10
-2
@@ -10,6 +10,7 @@ package io.element.android.features.contentscanner.impl
|
|||||||
import io.element.android.features.contentscanner.api.ContentScannerService
|
import io.element.android.features.contentscanner.api.ContentScannerService
|
||||||
import io.element.android.libraries.core.coroutine.CoroutineDispatchers
|
import io.element.android.libraries.core.coroutine.CoroutineDispatchers
|
||||||
import io.element.android.libraries.matrix.api.core.EventId
|
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.media.MediaSource
|
||||||
import io.element.android.libraries.matrix.api.scanner.ContentScanner
|
import io.element.android.libraries.matrix.api.scanner.ContentScanner
|
||||||
import io.element.android.libraries.matrix.ui.media.contentvalidation.ContentValidationState
|
import io.element.android.libraries.matrix.ui.media.contentvalidation.ContentValidationState
|
||||||
@@ -42,10 +43,16 @@ class DefaultContentScannerService(
|
|||||||
contentValidationState.update(url, contentValidationValue)
|
contentValidationState.update(url, contentValidationValue)
|
||||||
}
|
}
|
||||||
.onFailure { exception ->
|
.onFailure { exception ->
|
||||||
if (exception is IOException) {
|
when (exception) {
|
||||||
|
is IOException -> {
|
||||||
// If it's an IO-related exception, we can retry later, so we don't store the error
|
// If it's an IO-related exception, we can retry later, so we don't store the error
|
||||||
contentValidationState.update(url, ContentValidationValue.Unknown)
|
contentValidationState.update(url, ContentValidationValue.Unknown)
|
||||||
} else {
|
}
|
||||||
|
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
|
// For other exceptions, we cache the failure
|
||||||
contentValidationState.update(url, ContentValidationValue.UnrecoverableError(exception))
|
contentValidationState.update(url, ContentValidationValue.UnrecoverableError(exception))
|
||||||
}
|
}
|
||||||
@@ -53,4 +60,5 @@ class DefaultContentScannerService(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -17,4 +17,5 @@ dependencies {
|
|||||||
implementation(projects.libraries.compound)
|
implementation(projects.libraries.compound)
|
||||||
implementation(projects.libraries.architecture)
|
implementation(projects.libraries.architecture)
|
||||||
implementation(projects.libraries.matrix.api)
|
implementation(projects.libraries.matrix.api)
|
||||||
|
implementation(projects.libraries.wellknown.api)
|
||||||
}
|
}
|
||||||
|
|||||||
+6
@@ -11,6 +11,7 @@ package io.element.android.features.enterprise.api
|
|||||||
import androidx.compose.ui.graphics.Color
|
import androidx.compose.ui.graphics.Color
|
||||||
import io.element.android.compound.colors.SemanticColorsLightDark
|
import io.element.android.compound.colors.SemanticColorsLightDark
|
||||||
import io.element.android.libraries.matrix.api.core.SessionId
|
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.Flow
|
||||||
|
|
||||||
interface EnterpriseService {
|
interface EnterpriseService {
|
||||||
@@ -41,6 +42,11 @@ interface EnterpriseService {
|
|||||||
*/
|
*/
|
||||||
fun getNoisyNotificationChannelId(sessionId: SessionId): String?
|
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 {
|
companion object {
|
||||||
const val ANY_ACCOUNT_PROVIDER = "*"
|
const val ANY_ACCOUNT_PROVIDER = "*"
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -23,6 +23,7 @@ dependencies {
|
|||||||
api(projects.features.enterprise.api)
|
api(projects.features.enterprise.api)
|
||||||
implementation(projects.libraries.architecture)
|
implementation(projects.libraries.architecture)
|
||||||
implementation(projects.libraries.matrix.api)
|
implementation(projects.libraries.matrix.api)
|
||||||
|
implementation(projects.libraries.wellknown.api)
|
||||||
|
|
||||||
testCommonDependencies(libs)
|
testCommonDependencies(libs)
|
||||||
testImplementation(projects.libraries.matrix.test)
|
testImplementation(projects.libraries.matrix.test)
|
||||||
|
|||||||
+3
@@ -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.BugReportUrl
|
||||||
import io.element.android.features.enterprise.api.EnterpriseService
|
import io.element.android.features.enterprise.api.EnterpriseService
|
||||||
import io.element.android.libraries.matrix.api.core.SessionId
|
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.Flow
|
||||||
import kotlinx.coroutines.flow.flowOf
|
import kotlinx.coroutines.flow.flowOf
|
||||||
|
|
||||||
@@ -45,4 +46,6 @@ class DefaultEnterpriseService : EnterpriseService {
|
|||||||
}
|
}
|
||||||
|
|
||||||
override fun getNoisyNotificationChannelId(sessionId: SessionId): String? = null
|
override fun getNoisyNotificationChannelId(sessionId: SessionId): String? = null
|
||||||
|
|
||||||
|
override fun overriddenElementWellKnown(): ElementWellKnown? = null
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -18,5 +18,6 @@ dependencies {
|
|||||||
implementation(projects.libraries.architecture)
|
implementation(projects.libraries.architecture)
|
||||||
implementation(projects.libraries.compound)
|
implementation(projects.libraries.compound)
|
||||||
implementation(projects.libraries.matrix.api)
|
implementation(projects.libraries.matrix.api)
|
||||||
|
implementation(projects.libraries.wellknown.api)
|
||||||
implementation(projects.tests.testutils)
|
implementation(projects.tests.testutils)
|
||||||
}
|
}
|
||||||
|
|||||||
+6
@@ -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.BugReportUrl
|
||||||
import io.element.android.features.enterprise.api.EnterpriseService
|
import io.element.android.features.enterprise.api.EnterpriseService
|
||||||
import io.element.android.libraries.matrix.api.core.SessionId
|
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.lambda.lambdaError
|
||||||
import io.element.android.tests.testutils.simulateLongTask
|
import io.element.android.tests.testutils.simulateLongTask
|
||||||
import kotlinx.coroutines.flow.Flow
|
import kotlinx.coroutines.flow.Flow
|
||||||
@@ -31,6 +32,7 @@ class FakeEnterpriseService(
|
|||||||
private val unifiedPushDefaultPushGatewayResult: () -> String? = { lambdaError() },
|
private val unifiedPushDefaultPushGatewayResult: () -> String? = { lambdaError() },
|
||||||
private val getNoisyNotificationChannelIdResult: (SessionId?) -> String? = { lambdaError() },
|
private val getNoisyNotificationChannelIdResult: (SessionId?) -> String? = { lambdaError() },
|
||||||
private val tweakMasUrlResult: (String, String) -> String = { _, _ -> lambdaError() },
|
private val tweakMasUrlResult: (String, String) -> String = { _, _ -> lambdaError() },
|
||||||
|
private val overrideWellKnownResult: () -> ElementWellKnown? = { lambdaError() },
|
||||||
) : EnterpriseService {
|
) : EnterpriseService {
|
||||||
private val brandColorState = MutableStateFlow(initialBrandColor)
|
private val brandColorState = MutableStateFlow(initialBrandColor)
|
||||||
private val semanticColorsState = MutableStateFlow(initialSemanticColors)
|
private val semanticColorsState = MutableStateFlow(initialSemanticColors)
|
||||||
@@ -79,4 +81,8 @@ class FakeEnterpriseService(
|
|||||||
override fun getNoisyNotificationChannelId(sessionId: SessionId): String? {
|
override fun getNoisyNotificationChannelId(sessionId: SessionId): String? {
|
||||||
return getNoisyNotificationChannelIdResult(sessionId)
|
return getNoisyNotificationChannelIdResult(sessionId)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override fun overriddenElementWellKnown(): ElementWellKnown? {
|
||||||
|
return overrideWellKnownResult()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+16
@@ -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
|
@PreviewsDayNight
|
||||||
@Composable
|
@Composable
|
||||||
internal fun TimelineItemScanningContentWithInvalidRepliesPreview() = ElementPreview {
|
internal fun TimelineItemScanningContentWithInvalidRepliesPreview() = ElementPreview {
|
||||||
|
|||||||
+1
-1
@@ -232,7 +232,7 @@ fun TimelineItemEventContentView(
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (showCaption) {
|
if (showCaption) {
|
||||||
val padding = if (displayInvalidContent) {
|
val padding = if (displayInvalidContent || displayContentNotFound) {
|
||||||
PaddingValues(start = 12.dp, end = 12.dp, top = 4.dp, bottom = 0.dp)
|
PaddingValues(start = 12.dp, end = 12.dp, top = 4.dp, bottom = 0.dp)
|
||||||
} else {
|
} else {
|
||||||
when (content) {
|
when (content) {
|
||||||
|
|||||||
+6
@@ -26,9 +26,11 @@ import androidx.compose.ui.Modifier
|
|||||||
import androidx.compose.ui.draw.clip
|
import androidx.compose.ui.draw.clip
|
||||||
import androidx.compose.ui.draw.rotate
|
import androidx.compose.ui.draw.rotate
|
||||||
import androidx.compose.ui.graphics.Color
|
import androidx.compose.ui.graphics.Color
|
||||||
|
import androidx.compose.ui.res.stringResource
|
||||||
import androidx.compose.ui.semantics.Role
|
import androidx.compose.ui.semantics.Role
|
||||||
import androidx.compose.ui.semantics.clearAndSetSemantics
|
import androidx.compose.ui.semantics.clearAndSetSemantics
|
||||||
import androidx.compose.ui.semantics.contentDescription
|
import androidx.compose.ui.semantics.contentDescription
|
||||||
|
import androidx.compose.ui.semantics.stateDescription
|
||||||
import androidx.compose.ui.unit.dp
|
import androidx.compose.ui.unit.dp
|
||||||
import io.element.android.compound.theme.ElementTheme
|
import io.element.android.compound.theme.ElementTheme
|
||||||
import io.element.android.compound.tokens.generated.CompoundIcons
|
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.Icon
|
||||||
import io.element.android.libraries.designsystem.theme.components.Surface
|
import io.element.android.libraries.designsystem.theme.components.Surface
|
||||||
import io.element.android.libraries.designsystem.theme.components.Text
|
import io.element.android.libraries.designsystem.theme.components.Text
|
||||||
|
import io.element.android.libraries.ui.strings.CommonStrings
|
||||||
|
|
||||||
private val CORNER_RADIUS = 8.dp
|
private val CORNER_RADIUS = 8.dp
|
||||||
|
|
||||||
@@ -52,6 +55,8 @@ fun GroupHeaderView(
|
|||||||
val backgroundColor = Color.Transparent
|
val backgroundColor = Color.Transparent
|
||||||
val shape = RoundedCornerShape(CORNER_RADIUS)
|
val shape = RoundedCornerShape(CORNER_RADIUS)
|
||||||
|
|
||||||
|
val expandedStateDescription = stringResource(CommonStrings.a11y_state_expanded)
|
||||||
|
val collapsedStateDescription = stringResource(CommonStrings.a11y_state_collapsed)
|
||||||
Box(
|
Box(
|
||||||
modifier = modifier
|
modifier = modifier
|
||||||
.fillMaxWidth()
|
.fillMaxWidth()
|
||||||
@@ -62,6 +67,7 @@ fun GroupHeaderView(
|
|||||||
)
|
)
|
||||||
.clearAndSetSemantics {
|
.clearAndSetSemantics {
|
||||||
contentDescription = text
|
contentDescription = text
|
||||||
|
stateDescription = if (isExpanded) expandedStateDescription else collapsedStateDescription
|
||||||
},
|
},
|
||||||
contentAlignment = Alignment.Center
|
contentAlignment = Alignment.Center
|
||||||
) {
|
) {
|
||||||
|
|||||||
@@ -6,7 +6,7 @@
|
|||||||
* Please see LICENSE files in the repository root for full details.
|
* Please see LICENSE files in the repository root for full details.
|
||||||
*/
|
*/
|
||||||
plugins {
|
plugins {
|
||||||
id("io.element.android-library")
|
id("io.element.android-compose-library")
|
||||||
id("kotlin-parcelize")
|
id("kotlin-parcelize")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+19
@@ -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)
|
||||||
|
}
|
||||||
+3
@@ -18,6 +18,7 @@ import com.bumble.appyx.core.plugin.Plugin
|
|||||||
import dev.zacsweers.metro.Assisted
|
import dev.zacsweers.metro.Assisted
|
||||||
import dev.zacsweers.metro.AssistedInject
|
import dev.zacsweers.metro.AssistedInject
|
||||||
import io.element.android.annotations.ContributesNode
|
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.architecture.callback
|
||||||
import io.element.android.libraries.designsystem.showkase.getBrowserIntent
|
import io.element.android.libraries.designsystem.showkase.getBrowserIntent
|
||||||
import io.element.android.libraries.di.SessionScope
|
import io.element.android.libraries.di.SessionScope
|
||||||
@@ -28,6 +29,7 @@ class DeveloperSettingsNode(
|
|||||||
@Assisted buildContext: BuildContext,
|
@Assisted buildContext: BuildContext,
|
||||||
@Assisted plugins: List<Plugin>,
|
@Assisted plugins: List<Plugin>,
|
||||||
private val presenter: DeveloperSettingsPresenter,
|
private val presenter: DeveloperSettingsPresenter,
|
||||||
|
private val extraDeveloperOptionsRenderer: ExtraDeveloperOptionsRenderer,
|
||||||
) : Node(buildContext, plugins = plugins) {
|
) : Node(buildContext, plugins = plugins) {
|
||||||
interface Callback : Plugin {
|
interface Callback : Plugin {
|
||||||
fun navigateToPushHistory()
|
fun navigateToPushHistory()
|
||||||
@@ -51,6 +53,7 @@ class DeveloperSettingsNode(
|
|||||||
onOpenShowkase = ::openShowkase,
|
onOpenShowkase = ::openShowkase,
|
||||||
onPushHistoryClick = callback::navigateToPushHistory,
|
onPushHistoryClick = callback::navigateToPushHistory,
|
||||||
onBackClick = callback::onDone,
|
onBackClick = callback::onDone,
|
||||||
|
extraOptions = { extraDeveloperOptionsRenderer.Render(Modifier) },
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+4
@@ -43,6 +43,7 @@ fun DeveloperSettingsView(
|
|||||||
onPushHistoryClick: () -> Unit,
|
onPushHistoryClick: () -> Unit,
|
||||||
onBackClick: () -> Unit,
|
onBackClick: () -> Unit,
|
||||||
modifier: Modifier = Modifier,
|
modifier: Modifier = Modifier,
|
||||||
|
extraOptions: @Composable () -> Unit = {},
|
||||||
) {
|
) {
|
||||||
if (state.showLoader) {
|
if (state.showLoader) {
|
||||||
ProgressDialog()
|
ProgressDialog()
|
||||||
@@ -97,6 +98,9 @@ fun DeveloperSettingsView(
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
extraOptions()
|
||||||
|
|
||||||
val cache = state.cacheSize
|
val cache = state.cacheSize
|
||||||
PreferenceCategory(title = "Cache") {
|
PreferenceCategory(title = "Cache") {
|
||||||
ListItem(
|
ListItem(
|
||||||
|
|||||||
+22
@@ -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
|
||||||
|
}
|
||||||
|
}
|
||||||
+3
@@ -18,6 +18,7 @@ import dev.zacsweers.metro.AppScope
|
|||||||
import dev.zacsweers.metro.Assisted
|
import dev.zacsweers.metro.Assisted
|
||||||
import dev.zacsweers.metro.AssistedInject
|
import dev.zacsweers.metro.AssistedInject
|
||||||
import io.element.android.annotations.ContributesNode
|
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.features.preferences.api.PreferencesEntryPoint
|
||||||
import io.element.android.libraries.architecture.callback
|
import io.element.android.libraries.architecture.callback
|
||||||
import io.element.android.libraries.designsystem.showkase.getBrowserIntent
|
import io.element.android.libraries.designsystem.showkase.getBrowserIntent
|
||||||
@@ -28,6 +29,7 @@ class AppDeveloperSettingsNode(
|
|||||||
@Assisted buildContext: BuildContext,
|
@Assisted buildContext: BuildContext,
|
||||||
@Assisted plugins: List<Plugin>,
|
@Assisted plugins: List<Plugin>,
|
||||||
private val presenter: AppDeveloperSettingsPresenter,
|
private val presenter: AppDeveloperSettingsPresenter,
|
||||||
|
private val extraDeveloperOptionsRenderer: ExtraDeveloperOptionsRenderer,
|
||||||
) : Node(buildContext, plugins = plugins) {
|
) : Node(buildContext, plugins = plugins) {
|
||||||
private val callback: PreferencesEntryPoint.DeveloperSettingsCallback = callback()
|
private val callback: PreferencesEntryPoint.DeveloperSettingsCallback = callback()
|
||||||
|
|
||||||
@@ -45,6 +47,7 @@ class AppDeveloperSettingsNode(
|
|||||||
modifier = modifier,
|
modifier = modifier,
|
||||||
onOpenShowkase = ::openShowkase,
|
onOpenShowkase = ::openShowkase,
|
||||||
onBackClick = callback::onDone,
|
onBackClick = callback::onDone,
|
||||||
|
extraOptions = { extraDeveloperOptionsRenderer.Render(Modifier) },
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+2
@@ -24,6 +24,7 @@ fun AppDeveloperSettingsPage(
|
|||||||
onOpenShowkase: () -> Unit,
|
onOpenShowkase: () -> Unit,
|
||||||
onBackClick: () -> Unit,
|
onBackClick: () -> Unit,
|
||||||
modifier: Modifier = Modifier,
|
modifier: Modifier = Modifier,
|
||||||
|
extraOptions: @Composable () -> Unit = {},
|
||||||
) {
|
) {
|
||||||
BackHandler(
|
BackHandler(
|
||||||
onBack = onBackClick,
|
onBack = onBackClick,
|
||||||
@@ -40,6 +41,7 @@ fun AppDeveloperSettingsPage(
|
|||||||
onOpenShowkase = onOpenShowkase,
|
onOpenShowkase = onOpenShowkase,
|
||||||
modifier = Modifier.padding(top = 8.dp)
|
modifier = Modifier.padding(top = 8.dp)
|
||||||
)
|
)
|
||||||
|
extraOptions()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -5,7 +5,7 @@
|
|||||||
# Project
|
# Project
|
||||||
android_gradle_plugin = "9.2.1"
|
android_gradle_plugin = "9.2.1"
|
||||||
# When updating this, please also update the version in the file ./idea/kotlinc.xml
|
# 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"
|
kotlinpoet = "2.3.0"
|
||||||
ksp = "2.3.10"
|
ksp = "2.3.10"
|
||||||
firebaseAppDistribution = "5.3.0"
|
firebaseAppDistribution = "5.3.0"
|
||||||
@@ -32,7 +32,7 @@ accompanist = "0.37.3"
|
|||||||
|
|
||||||
# Test
|
# Test
|
||||||
test_core = "1.7.0"
|
test_core = "1.7.0"
|
||||||
roborazzi = "1.67.0"
|
roborazzi = "1.68.0"
|
||||||
|
|
||||||
# Jetbrain
|
# Jetbrain
|
||||||
datetime = "0.8.0"
|
datetime = "0.8.0"
|
||||||
@@ -51,10 +51,10 @@ telephoto = "0.19.0"
|
|||||||
haze = "1.7.2"
|
haze = "1.7.2"
|
||||||
|
|
||||||
# Dependency analysis
|
# Dependency analysis
|
||||||
dependencyAnalysis = "3.16.0"
|
dependencyAnalysis = "3.16.1"
|
||||||
|
|
||||||
# DI
|
# DI
|
||||||
metro = "1.3.0"
|
metro = "1.3.2"
|
||||||
|
|
||||||
# Auto service
|
# Auto service
|
||||||
autoservice = "1.1.1"
|
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" }
|
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" }
|
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
|
# 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" }
|
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" }
|
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" }
|
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
|
# 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
|
# 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.
|
# 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
|
# Others
|
||||||
coil = { module = "io.coil-kt.coil3:coil", version.ref = "coil" }
|
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" }
|
metro_runtime = { module = "dev.zacsweers.metro:runtime", version.ref = "metro" }
|
||||||
|
|
||||||
# Element Call
|
# 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
|
# Auto services
|
||||||
google_autoservice = { module = "com.google.auto.service:auto-service", version.ref = "autoservice" }
|
google_autoservice = { module = "com.google.auto.service:auto-service", version.ref = "autoservice" }
|
||||||
|
|||||||
Vendored
BIN
Binary file not shown.
+4
-2
@@ -1,8 +1,10 @@
|
|||||||
distributionBase=GRADLE_USER_HOME
|
distributionBase=GRADLE_USER_HOME
|
||||||
distributionPath=wrapper/dists
|
distributionPath=wrapper/dists
|
||||||
distributionSha256Sum=bafc141b619ad6350fd975fc903156dd5c151998cc8b058e8c1044ab5f7b031f
|
distributionSha256Sum=9c0f7faeeb306cb14e4279a3e084ca6b596894089a0638e68a07c945a32c9e14
|
||||||
distributionUrl=https\://services.gradle.org/distributions/gradle-9.5.1-bin.zip
|
distributionUrl=https\://services.gradle.org/distributions/gradle-9.6.1-bin.zip
|
||||||
networkTimeout=10000
|
networkTimeout=10000
|
||||||
|
retries=0
|
||||||
|
retryBackOffMs=500
|
||||||
validateDistributionUrl=true
|
validateDistributionUrl=true
|
||||||
zipStoreBase=GRADLE_USER_HOME
|
zipStoreBase=GRADLE_USER_HOME
|
||||||
zipStorePath=wrapper/dists
|
zipStorePath=wrapper/dists
|
||||||
|
|||||||
@@ -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:
|
# Important for running:
|
||||||
#
|
#
|
||||||
@@ -29,7 +29,7 @@
|
|||||||
# bash, then to run this script, type that shell name before the whole
|
# bash, then to run this script, type that shell name before the whole
|
||||||
# command line, like:
|
# command line, like:
|
||||||
#
|
#
|
||||||
# ksh Gradle
|
# ksh gradlew
|
||||||
#
|
#
|
||||||
# Busybox and similar reduced shells will NOT work, because this script
|
# Busybox and similar reduced shells will NOT work, because this script
|
||||||
# requires all of these POSIX shell features:
|
# requires all of these POSIX shell features:
|
||||||
@@ -57,7 +57,7 @@
|
|||||||
# Darwin, MinGW, and NonStop.
|
# Darwin, MinGW, and NonStop.
|
||||||
#
|
#
|
||||||
# (3) This script is generated from the Groovy template
|
# (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.
|
# within the Gradle project.
|
||||||
#
|
#
|
||||||
# You can find Gradle at https://github.com/gradle/gradle/.
|
# You can find Gradle at https://github.com/gradle/gradle/.
|
||||||
|
|||||||
Vendored
+12
-23
@@ -19,12 +19,12 @@
|
|||||||
@if "%DEBUG%"=="" @echo off
|
@if "%DEBUG%"=="" @echo off
|
||||||
@rem ##########################################################################
|
@rem ##########################################################################
|
||||||
@rem
|
@rem
|
||||||
@rem Gradle startup script for Windows
|
@rem gradlew startup script for Windows
|
||||||
@rem
|
@rem
|
||||||
@rem ##########################################################################
|
@rem ##########################################################################
|
||||||
|
|
||||||
@rem Set local scope for the variables with windows NT shell
|
@rem Set local scope for the variables, and ensure extensions are enabled
|
||||||
if "%OS%"=="Windows_NT" setlocal
|
setlocal EnableExtensions
|
||||||
|
|
||||||
set DIRNAME=%~dp0
|
set DIRNAME=%~dp0
|
||||||
if "%DIRNAME%"=="" set DIRNAME=.
|
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 Please set the JAVA_HOME variable in your environment to match the 1>&2
|
||||||
echo location of your Java installation. 1>&2
|
echo location of your Java installation. 1>&2
|
||||||
|
|
||||||
goto fail
|
"%COMSPEC%" /c exit 1
|
||||||
|
|
||||||
:findJavaFromJavaHome
|
:findJavaFromJavaHome
|
||||||
set JAVA_HOME=%JAVA_HOME:"=%
|
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 Please set the JAVA_HOME variable in your environment to match the 1>&2
|
||||||
echo location of your Java installation. 1>&2
|
echo location of your Java installation. 1>&2
|
||||||
|
|
||||||
goto fail
|
"%COMSPEC%" /c exit 1
|
||||||
|
|
||||||
:execute
|
:execute
|
||||||
@rem Setup the command line
|
@rem Setup the command line
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@rem Execute Gradle
|
@rem Execute gradlew
|
||||||
"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -jar "%APP_HOME%\gradle\wrapper\gradle-wrapper.jar" %*
|
@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
|
:exitWithErrorLevel
|
||||||
@rem End local scope for the variables with windows NT shell
|
@rem Use "%COMSPEC%" /c exit to allow operators to work properly in scripts
|
||||||
if %ERRORLEVEL% equ 0 goto mainEnd
|
"%COMSPEC%" /c exit %ERRORLEVEL%
|
||||||
|
|
||||||
: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
|
|
||||||
|
|||||||
+4
@@ -7,9 +7,11 @@
|
|||||||
|
|
||||||
package io.element.android.libraries.matrix.impl.scanner
|
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.core.extensions.runCatchingExceptions
|
||||||
import io.element.android.libraries.matrix.api.media.MediaSource
|
import io.element.android.libraries.matrix.api.media.MediaSource
|
||||||
import io.element.android.libraries.matrix.api.scanner.ContentScanner
|
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.Client
|
||||||
import org.matrix.rustcomponents.sdk.NoHandle
|
import org.matrix.rustcomponents.sdk.NoHandle
|
||||||
import org.matrix.rustcomponents.sdk.ContentScanner as RustScanner
|
import org.matrix.rustcomponents.sdk.ContentScanner as RustScanner
|
||||||
@@ -22,6 +24,8 @@ class RustContentScanner(
|
|||||||
override suspend fun scan(mediaSource: MediaSource): Result<Boolean> {
|
override suspend fun scan(mediaSource: MediaSource): Result<Boolean> {
|
||||||
return runCatchingExceptions {
|
return runCatchingExceptions {
|
||||||
rustScanner.scan(client, mediaSource.toRustMediaSource()).clean
|
rustScanner.scan(client, mediaSource.toRustMediaSource()).clean
|
||||||
|
}.mapFailure {
|
||||||
|
it.mapClientException()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+6
@@ -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.api.core.UserId
|
||||||
import io.element.android.libraries.matrix.test.A_USER_ID
|
import io.element.android.libraries.matrix.test.A_USER_ID
|
||||||
import org.matrix.rustcomponents.sdk.RoomHero
|
import org.matrix.rustcomponents.sdk.RoomHero
|
||||||
|
import org.matrix.rustcomponents.sdk.UserCall
|
||||||
|
import org.matrix.rustcomponents.sdk.UserStatus
|
||||||
|
|
||||||
internal fun aRustRoomHero(
|
internal fun aRustRoomHero(
|
||||||
userId: UserId = A_USER_ID,
|
userId: UserId = A_USER_ID,
|
||||||
|
status: UserStatus? = null,
|
||||||
|
call: UserCall? = null,
|
||||||
) = RoomHero(
|
) = RoomHero(
|
||||||
userId = userId.value,
|
userId = userId.value,
|
||||||
displayName = "displayName",
|
displayName = "displayName",
|
||||||
avatarUrl = "avatarUrl",
|
avatarUrl = "avatarUrl",
|
||||||
|
status = status,
|
||||||
|
call = call,
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -8,6 +8,8 @@
|
|||||||
<resources>
|
<resources>
|
||||||
<string name="action_mark_as_read">"Mark as read"</string>
|
<string name="action_mark_as_read">"Mark as read"</string>
|
||||||
<string name="a11y_jump_to_unread_messages">"Jump to first unread message"</string>
|
<string name="a11y_jump_to_unread_messages">"Jump to first unread message"</string>
|
||||||
|
<string name="a11y_state_expanded">"Expanded"</string>
|
||||||
|
<string name="a11y_state_collapsed">"Collapsed"</string>
|
||||||
<string name="screen_local_network_opt_in_title">Allow access to local network</string>
|
<string name="screen_local_network_opt_in_title">Allow access to local network</string>
|
||||||
<string name="screen_local_network_opt_in_subtitle">Your homeserver is on your local network. To connect, Element needs permission to reach other devices on this network.</string>
|
<string name="screen_local_network_opt_in_subtitle">Your homeserver is on your local network. To connect, Element needs permission to reach other devices on this network.</string>
|
||||||
<string name="a11y_active">Active</string>
|
<string name="a11y_active">Active</string>
|
||||||
|
|||||||
+12
@@ -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<ElementWellKnown>
|
||||||
|
}
|
||||||
@@ -34,6 +34,7 @@ dependencies {
|
|||||||
implementation(projects.libraries.matrix.api)
|
implementation(projects.libraries.matrix.api)
|
||||||
implementation(projects.libraries.network)
|
implementation(projects.libraries.network)
|
||||||
implementation(projects.libraries.cachestore.api)
|
implementation(projects.libraries.cachestore.api)
|
||||||
|
implementation(projects.features.enterprise.api)
|
||||||
implementation(projects.services.toolbox.api)
|
implementation(projects.services.toolbox.api)
|
||||||
|
|
||||||
testCommonDependencies(libs)
|
testCommonDependencies(libs)
|
||||||
@@ -41,5 +42,6 @@ dependencies {
|
|||||||
testImplementation(projects.libraries.cachestore.test)
|
testImplementation(projects.libraries.cachestore.test)
|
||||||
testImplementation(projects.libraries.matrix.test)
|
testImplementation(projects.libraries.matrix.test)
|
||||||
testImplementation(projects.libraries.wellknown.test)
|
testImplementation(projects.libraries.wellknown.test)
|
||||||
|
testImplementation(projects.features.enterprise.test)
|
||||||
testImplementation(projects.services.toolbox.test)
|
testImplementation(projects.services.toolbox.test)
|
||||||
}
|
}
|
||||||
|
|||||||
+27
@@ -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<ElementWellKnown> {
|
||||||
|
return runCatchingExceptions {
|
||||||
|
val decoder = jsonProvider()
|
||||||
|
decoder.decodeFromString<InternalElementWellKnown>(json).map()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
+10
-3
@@ -9,13 +9,14 @@
|
|||||||
package io.element.android.libraries.wellknown.impl
|
package io.element.android.libraries.wellknown.impl
|
||||||
|
|
||||||
import dev.zacsweers.metro.ContributesBinding
|
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.core.extensions.mapCatchingExceptions
|
||||||
import io.element.android.libraries.di.SessionScope
|
import io.element.android.libraries.di.SessionScope
|
||||||
import io.element.android.libraries.di.annotations.SessionCoroutineScope
|
import io.element.android.libraries.di.annotations.SessionCoroutineScope
|
||||||
import io.element.android.libraries.matrix.api.MatrixClient
|
import io.element.android.libraries.matrix.api.MatrixClient
|
||||||
import io.element.android.libraries.matrix.api.exception.ClientException
|
import io.element.android.libraries.matrix.api.exception.ClientException
|
||||||
import io.element.android.libraries.wellknown.api.ElementWellKnown
|
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.ElementWellknownStore
|
||||||
import io.element.android.libraries.wellknown.api.SessionWellknownRetriever
|
import io.element.android.libraries.wellknown.api.SessionWellknownRetriever
|
||||||
import io.element.android.libraries.wellknown.api.WellknownRetrieverResult
|
import io.element.android.libraries.wellknown.api.WellknownRetrieverResult
|
||||||
@@ -26,14 +27,20 @@ import timber.log.Timber
|
|||||||
@ContributesBinding(SessionScope::class)
|
@ContributesBinding(SessionScope::class)
|
||||||
class DefaultSessionWellknownRetriever(
|
class DefaultSessionWellknownRetriever(
|
||||||
private val matrixClient: MatrixClient,
|
private val matrixClient: MatrixClient,
|
||||||
private val json: JsonProvider,
|
|
||||||
@SessionCoroutineScope
|
@SessionCoroutineScope
|
||||||
private val sessionCoroutineScope: CoroutineScope,
|
private val sessionCoroutineScope: CoroutineScope,
|
||||||
private val elementWellknownStore: ElementWellknownStore,
|
private val elementWellknownStore: ElementWellknownStore,
|
||||||
|
private val elementWellKnownParser: ElementWellKnownParser,
|
||||||
|
private val enterpriseService: EnterpriseService,
|
||||||
) : SessionWellknownRetriever {
|
) : SessionWellknownRetriever {
|
||||||
private val domain by lazy { matrixClient.userIdServerName() }
|
private val domain by lazy { matrixClient.userIdServerName() }
|
||||||
|
|
||||||
override suspend fun getElementWellKnown(): WellknownRetrieverResult<ElementWellKnown> {
|
override suspend fun getElementWellKnown(): WellknownRetrieverResult<ElementWellKnown> {
|
||||||
|
val overriddenElementWellKnown = enterpriseService.overriddenElementWellKnown()
|
||||||
|
if (overriddenElementWellKnown != null) {
|
||||||
|
return WellknownRetrieverResult.Success(overriddenElementWellKnown)
|
||||||
|
}
|
||||||
|
|
||||||
val cacheData = elementWellknownStore.get(domain)
|
val cacheData = elementWellknownStore.get(domain)
|
||||||
return when (cacheData) {
|
return when (cacheData) {
|
||||||
is WellknownRetrieverResult.Success -> {
|
is WellknownRetrieverResult.Success -> {
|
||||||
@@ -69,7 +76,7 @@ class DefaultSessionWellknownRetriever(
|
|||||||
.getUrl(url)
|
.getUrl(url)
|
||||||
.mapCatchingExceptions {
|
.mapCatchingExceptions {
|
||||||
val data = String(it)
|
val data = String(it)
|
||||||
val parsed = json().decodeFromString<InternalElementWellKnown>(data).map()
|
val parsed = elementWellKnownParser.parse(data).getOrThrow()
|
||||||
// Also store in cache, if valid
|
// Also store in cache, if valid
|
||||||
elementWellknownStore.update(domain, data)
|
elementWellknownStore.update(domain, data)
|
||||||
.onFailure { exception ->
|
.onFailure { exception ->
|
||||||
|
|||||||
+3
-3
@@ -9,11 +9,11 @@ package io.element.android.libraries.wellknown.impl
|
|||||||
|
|
||||||
import dev.zacsweers.metro.AppScope
|
import dev.zacsweers.metro.AppScope
|
||||||
import dev.zacsweers.metro.ContributesBinding
|
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.CacheData
|
||||||
import io.element.android.libraries.cachestore.api.CacheStore
|
import io.element.android.libraries.cachestore.api.CacheStore
|
||||||
import io.element.android.libraries.core.extensions.runCatchingExceptions
|
import io.element.android.libraries.core.extensions.runCatchingExceptions
|
||||||
import io.element.android.libraries.wellknown.api.ElementWellKnown
|
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.ElementWellknownStore
|
||||||
import io.element.android.libraries.wellknown.api.WellknownRetrieverResult
|
import io.element.android.libraries.wellknown.api.WellknownRetrieverResult
|
||||||
import io.element.android.services.toolbox.api.systemclock.SystemClock
|
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)
|
@ContributesBinding(AppScope::class)
|
||||||
class DefaultWellKnownStore(
|
class DefaultWellKnownStore(
|
||||||
private val cacheStore: CacheStore,
|
private val cacheStore: CacheStore,
|
||||||
private val json: JsonProvider,
|
private val elementWellKnownParser: ElementWellKnownParser,
|
||||||
private val systemClock: SystemClock,
|
private val systemClock: SystemClock,
|
||||||
) : ElementWellknownStore {
|
) : ElementWellknownStore {
|
||||||
override suspend fun get(domain: String): WellknownRetrieverResult<ElementWellKnown> {
|
override suspend fun get(domain: String): WellknownRetrieverResult<ElementWellKnown> {
|
||||||
return runCatchingExceptions {
|
return runCatchingExceptions {
|
||||||
val cachedData = cacheStore.getData(key(domain))
|
val cachedData = cacheStore.getData(key(domain))
|
||||||
if (cachedData != null) {
|
if (cachedData != null) {
|
||||||
val data = json().decodeFromString<InternalElementWellKnown>(cachedData.value).map()
|
val data = elementWellKnownParser.parse(cachedData.value).getOrThrow()
|
||||||
if (systemClock.epochMillis() > cachedData.updatedAt + CACHE_VALIDITY_MILLIS) {
|
if (systemClock.epochMillis() > cachedData.updatedAt + CACHE_VALIDITY_MILLIS) {
|
||||||
WellknownRetrieverResult.Outdated(data)
|
WellknownRetrieverResult.Outdated(data)
|
||||||
} else {
|
} else {
|
||||||
|
|||||||
+7
@@ -10,6 +10,7 @@ package io.element.android.libraries.wellknown.impl
|
|||||||
|
|
||||||
import dev.zacsweers.metro.AppScope
|
import dev.zacsweers.metro.AppScope
|
||||||
import dev.zacsweers.metro.ContributesBinding
|
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.androidutils.json.JsonProvider
|
||||||
import io.element.android.libraries.core.extensions.runCatchingExceptions
|
import io.element.android.libraries.core.extensions.runCatchingExceptions
|
||||||
import io.element.android.libraries.core.uri.ensureProtocol
|
import io.element.android.libraries.core.uri.ensureProtocol
|
||||||
@@ -28,8 +29,14 @@ class DefaultWellknownRetriever(
|
|||||||
private val retrofitFactory: RetrofitFactory,
|
private val retrofitFactory: RetrofitFactory,
|
||||||
private val elementWellknownStore: ElementWellknownStore,
|
private val elementWellknownStore: ElementWellknownStore,
|
||||||
private val jsonProvider: JsonProvider,
|
private val jsonProvider: JsonProvider,
|
||||||
|
private val enterpriseService: EnterpriseService,
|
||||||
) : WellknownRetriever {
|
) : WellknownRetriever {
|
||||||
override suspend fun getElementWellKnown(baseUrl: String): WellknownRetrieverResult<ElementWellKnown> {
|
override suspend fun getElementWellKnown(baseUrl: String): WellknownRetrieverResult<ElementWellKnown> {
|
||||||
|
val overriddenElementWellKnown = enterpriseService.overriddenElementWellKnown()
|
||||||
|
if (overriddenElementWellKnown != null) {
|
||||||
|
return WellknownRetrieverResult.Success(overriddenElementWellKnown)
|
||||||
|
}
|
||||||
|
|
||||||
val domain = URL(baseUrl).host
|
val domain = URL(baseUrl).host
|
||||||
return buildWellknownApi(baseUrl)
|
return buildWellknownApi(baseUrl)
|
||||||
.map { wellknownApi ->
|
.map { wellknownApi ->
|
||||||
|
|||||||
+28
-4
@@ -11,15 +11,16 @@
|
|||||||
package io.element.android.libraries.wellknown.impl
|
package io.element.android.libraries.wellknown.impl
|
||||||
|
|
||||||
import com.google.common.truth.Truth.assertThat
|
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.FakeElementWellknownStore
|
||||||
import io.element.android.features.wellknown.test.anElementWellKnown
|
import io.element.android.features.wellknown.test.anElementWellKnown
|
||||||
import io.element.android.libraries.androidutils.json.DefaultJsonProvider
|
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.api.exception.ClientException
|
||||||
import io.element.android.libraries.matrix.test.AN_EXCEPTION
|
import io.element.android.libraries.matrix.test.AN_EXCEPTION
|
||||||
import io.element.android.libraries.matrix.test.FakeMatrixClient
|
import io.element.android.libraries.matrix.test.FakeMatrixClient
|
||||||
import io.element.android.libraries.wellknown.api.CustomRecoveryPassphrase
|
import io.element.android.libraries.wellknown.api.CustomRecoveryPassphrase
|
||||||
import io.element.android.libraries.wellknown.api.ElementWellKnown
|
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.libraries.wellknown.api.WellknownRetrieverResult
|
||||||
import io.element.android.tests.testutils.lambda.lambdaError
|
import io.element.android.tests.testutils.lambda.lambdaError
|
||||||
import io.element.android.tests.testutils.lambda.lambdaRecorder
|
import io.element.android.tests.testutils.lambda.lambdaRecorder
|
||||||
@@ -276,7 +277,7 @@ class DefaultSessionWellknownRetrieverTest {
|
|||||||
Result.success("{}".toByteArray())
|
Result.success("{}".toByteArray())
|
||||||
},
|
},
|
||||||
cacheStore = cacheStore,
|
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)
|
assertThat(sut.getElementWellKnown()).isInstanceOf(WellknownRetrieverResult.Error::class.java)
|
||||||
// Ensure that the cache is deleted after the failure to parse it
|
// 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<String, Result<ByteArray>> { 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<InternalElementWellKnown>(WELLKNOWN_CONTENT).map()
|
private fun parsedWellKnownContent() = DefaultJsonProvider().invoke().decodeFromString<InternalElementWellKnown>(WELLKNOWN_CONTENT).map()
|
||||||
|
|
||||||
private fun TestScope.createDefaultSessionWellknownRetriever(
|
private fun TestScope.createDefaultSessionWellknownRetriever(
|
||||||
cacheStore: FakeElementWellknownStore = FakeElementWellknownStore(),
|
cacheStore: FakeElementWellknownStore = FakeElementWellknownStore(),
|
||||||
getUrlLambda: (String) -> Result<ByteArray>,
|
getUrlLambda: (String) -> Result<ByteArray>,
|
||||||
jsonProvider: JsonProvider = DefaultJsonProvider(),
|
elementWellKnownParser: ElementWellKnownParser = DefaultElementWellKnownParser(DefaultJsonProvider()),
|
||||||
|
enterpriseService: FakeEnterpriseService = FakeEnterpriseService(overrideWellKnownResult = { null }),
|
||||||
) = DefaultSessionWellknownRetriever(
|
) = DefaultSessionWellknownRetriever(
|
||||||
matrixClient = FakeMatrixClient(
|
matrixClient = FakeMatrixClient(
|
||||||
userIdServerNameLambda = { "user.domain.org" },
|
userIdServerNameLambda = { "user.domain.org" },
|
||||||
getUrlLambda = getUrlLambda,
|
getUrlLambda = getUrlLambda,
|
||||||
),
|
),
|
||||||
json = jsonProvider,
|
|
||||||
sessionCoroutineScope = backgroundScope,
|
sessionCoroutineScope = backgroundScope,
|
||||||
elementWellknownStore = cacheStore,
|
elementWellknownStore = cacheStore,
|
||||||
|
elementWellKnownParser = elementWellKnownParser,
|
||||||
|
enterpriseService = enterpriseService,
|
||||||
)
|
)
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
|
|||||||
+3
-1
@@ -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.cachestore.api.CacheData
|
||||||
import io.element.android.libraries.sessionstorage.test.InMemoryCacheStore
|
import io.element.android.libraries.sessionstorage.test.InMemoryCacheStore
|
||||||
import io.element.android.libraries.wellknown.api.CustomRecoveryPassphrase
|
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.libraries.wellknown.api.WellknownRetrieverResult
|
||||||
import io.element.android.services.toolbox.test.systemclock.A_FAKE_TIMESTAMP
|
import io.element.android.services.toolbox.test.systemclock.A_FAKE_TIMESTAMP
|
||||||
import io.element.android.services.toolbox.test.systemclock.FakeSystemClock
|
import io.element.android.services.toolbox.test.systemclock.FakeSystemClock
|
||||||
@@ -150,9 +151,10 @@ class DefaultWellKnownStoreTest {
|
|||||||
private fun createDefaultWellKnownStore(
|
private fun createDefaultWellKnownStore(
|
||||||
cacheStore: InMemoryCacheStore = InMemoryCacheStore(),
|
cacheStore: InMemoryCacheStore = InMemoryCacheStore(),
|
||||||
systemClock: FakeSystemClock = FakeSystemClock(),
|
systemClock: FakeSystemClock = FakeSystemClock(),
|
||||||
|
elementWellKnownParser: ElementWellKnownParser = DefaultElementWellKnownParser(jsonProvider),
|
||||||
) = DefaultWellKnownStore(
|
) = DefaultWellKnownStore(
|
||||||
cacheStore = cacheStore,
|
cacheStore = cacheStore,
|
||||||
json = jsonProvider,
|
|
||||||
systemClock = systemClock,
|
systemClock = systemClock,
|
||||||
|
elementWellKnownParser = elementWellKnownParser,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|||||||
+25
@@ -11,6 +11,7 @@
|
|||||||
package io.element.android.libraries.wellknown.impl
|
package io.element.android.libraries.wellknown.impl
|
||||||
|
|
||||||
import com.google.common.truth.Truth.assertThat
|
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.FakeElementWellknownStore
|
||||||
import io.element.android.features.wellknown.test.anElementWellKnown
|
import io.element.android.features.wellknown.test.anElementWellKnown
|
||||||
import io.element.android.libraries.androidutils.json.DefaultJsonProvider
|
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.CustomRecoveryPassphrase
|
||||||
import io.element.android.libraries.wellknown.api.ElementWellKnown
|
import io.element.android.libraries.wellknown.api.ElementWellKnown
|
||||||
import io.element.android.libraries.wellknown.api.WellknownRetrieverResult
|
import io.element.android.libraries.wellknown.api.WellknownRetrieverResult
|
||||||
|
import io.element.android.tests.testutils.lambda.lambdaRecorder
|
||||||
import io.mockk.every
|
import io.mockk.every
|
||||||
import io.mockk.mockk
|
import io.mockk.mockk
|
||||||
import io.mockk.verify
|
import io.mockk.verify
|
||||||
@@ -236,6 +238,27 @@ class DefaultWellknownRetrieverTest {
|
|||||||
assertThat(cacheStore.get(WELLKNOWN_URL)).isEqualTo(WellknownRetrieverResult.NotFound)
|
assertThat(cacheStore.get(WELLKNOWN_URL)).isEqualTo(WellknownRetrieverResult.NotFound)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun `get element wellknown was overridden`() = runTest {
|
||||||
|
val getLambda = lambdaRecorder<Request, Call> { 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(
|
private fun defaultResponse(
|
||||||
body: String = WELLKNOWN_CONTENT,
|
body: String = WELLKNOWN_CONTENT,
|
||||||
status: Int = 200,
|
status: Int = 200,
|
||||||
@@ -251,6 +274,7 @@ class DefaultWellknownRetrieverTest {
|
|||||||
callFactory: Call.Factory = Call.Factory { _: Request -> mockCall(defaultResponse()) },
|
callFactory: Call.Factory = Call.Factory { _: Request -> mockCall(defaultResponse()) },
|
||||||
cacheStore: FakeElementWellknownStore = FakeElementWellknownStore(),
|
cacheStore: FakeElementWellknownStore = FakeElementWellknownStore(),
|
||||||
jsonProvider: JsonProvider = DefaultJsonProvider(),
|
jsonProvider: JsonProvider = DefaultJsonProvider(),
|
||||||
|
enterpriseService: FakeEnterpriseService = FakeEnterpriseService(overrideWellKnownResult = { null }),
|
||||||
) = DefaultWellknownRetriever(
|
) = DefaultWellknownRetriever(
|
||||||
retrofitFactory = RetrofitFactory(
|
retrofitFactory = RetrofitFactory(
|
||||||
callFactory = { callFactory },
|
callFactory = { callFactory },
|
||||||
@@ -258,6 +282,7 @@ class DefaultWellknownRetrieverTest {
|
|||||||
),
|
),
|
||||||
jsonProvider = jsonProvider,
|
jsonProvider = jsonProvider,
|
||||||
elementWellknownStore = cacheStore,
|
elementWellknownStore = cacheStore,
|
||||||
|
enterpriseService = enterpriseService,
|
||||||
)
|
)
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
|
|||||||
@@ -88,6 +88,8 @@ class KonsistPreviewTest {
|
|||||||
"BackgroundVerticalGradientPreview",
|
"BackgroundVerticalGradientPreview",
|
||||||
"ColorAliasesPreview",
|
"ColorAliasesPreview",
|
||||||
"EmojiItemWithPopupPreview",
|
"EmojiItemWithPopupPreview",
|
||||||
|
"EnterpriseExtraDeveloperOptionsRendererBottomSheetPreview",
|
||||||
|
"EnterpriseExtraDeveloperOptionsRendererListItemPreview",
|
||||||
"FocusedEventPreview",
|
"FocusedEventPreview",
|
||||||
"GradientFloatingActionButtonCircleShapePreview",
|
"GradientFloatingActionButtonCircleShapePreview",
|
||||||
"HeaderFooterPageScrollablePreview",
|
"HeaderFooterPageScrollablePreview",
|
||||||
@@ -164,6 +166,7 @@ class KonsistPreviewTest {
|
|||||||
"TimelineItemImageViewScanningContentPreview",
|
"TimelineItemImageViewScanningContentPreview",
|
||||||
"TimelineItemRedactedMessagesGroupPreview",
|
"TimelineItemRedactedMessagesGroupPreview",
|
||||||
"TimelineItemScanningContentFailedPreview",
|
"TimelineItemScanningContentFailedPreview",
|
||||||
|
"TimelineItemScanningContentNotFoundPreview",
|
||||||
"TimelineItemScanningContentWithInvalidRepliesPreview",
|
"TimelineItemScanningContentWithInvalidRepliesPreview",
|
||||||
"TimelineItemScanningContentWithRepliesFailedPreview",
|
"TimelineItemScanningContentWithRepliesFailedPreview",
|
||||||
"TimelineItemStickerViewScanningContentPreview",
|
"TimelineItemStickerViewScanningContentPreview",
|
||||||
|
|||||||
BIN
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
@@ -35,7 +35,7 @@ def checkThatModulesExist(dependencies):
|
|||||||
line = line.split(" ")
|
line = line.split(" ")
|
||||||
for elem in line:
|
for elem in line:
|
||||||
if ":" in elem:
|
if ":" in elem:
|
||||||
modules.add(elem)
|
modules.add(elem.replace("'", ""))
|
||||||
for module in modules:
|
for module in modules:
|
||||||
path = "." + module.replace(":", "/") + "/build.gradle.kts"
|
path = "." + module.replace(":", "/") + "/build.gradle.kts"
|
||||||
if not os.path.exists(path):
|
if not os.path.exists(path):
|
||||||
@@ -51,12 +51,12 @@ def checkThatThereIsNoTestDependency(dependencies):
|
|||||||
currentProject = ""
|
currentProject = ""
|
||||||
for line in dependencies:
|
for line in dependencies:
|
||||||
if line.startswith("+--- project "):
|
if line.startswith("+--- project "):
|
||||||
currentProject = line.split(" ")[2]
|
currentProject = line.split(" ")[2].replace("'", "")
|
||||||
else:
|
else:
|
||||||
if ":test" in currentProject:
|
if ":test" in currentProject:
|
||||||
continue
|
continue
|
||||||
else:
|
else:
|
||||||
subProject = line.split(" ")[-1]
|
subProject = line.split(" ")[-1].replace("'", "")
|
||||||
if subProject.endswith(":test") or ":tests:" in subProject and "detekt-rules" not in subProject:
|
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 = "Error: '" + currentProject + "' depends on the test project '" + subProject + "'\n"
|
||||||
error += " Please replace occurrence(s) of 'implementation(projects" + subProject.replace(":", ".") + ")'"
|
error += " Please replace occurrence(s) of 'implementation(projects" + subProject.replace(":", ".") + ")'"
|
||||||
|
|||||||
Reference in New Issue
Block a user