From 6ee15e4b6a8e19d08d50a2b90f8e07d52c3dc609 Mon Sep 17 00:00:00 2001 From: ganfra Date: Fri, 19 Jul 2024 17:13:49 +0200 Subject: [PATCH 01/15] Compose : add immutability to some Reaction classes --- .../reactionsummary/ReactionSummaryPresenter.kt | 6 +++--- .../reactionsummary/ReactionSummaryState.kt | 3 ++- .../factories/event/TimelineItemEventFactory.kt | 5 ++++- .../impl/timeline/model/AggregatedReaction.kt | 15 +++++---------- .../timeline/model/AggregatedReactionProvider.kt | 3 ++- .../timeline/model/AggregatedReactionSender.kt | 2 ++ 6 files changed, 18 insertions(+), 16 deletions(-) diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/reactionsummary/ReactionSummaryPresenter.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/reactionsummary/ReactionSummaryPresenter.kt index 5f9a2ea428..bba17d7f9d 100644 --- a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/reactionsummary/ReactionSummaryPresenter.kt +++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/reactionsummary/ReactionSummaryPresenter.kt @@ -47,7 +47,7 @@ class ReactionSummaryPresenter @Inject constructor( fun handleEvents(event: ReactionSummaryEvents) { when (event) { is ReactionSummaryEvents.ShowReactionSummary -> target.value = ReactionSummaryState.Summary( - reactions = event.reactions, + reactions = event.reactions.toImmutableList(), selectedKey = event.selectedKey, selectedEventId = event.eventId ) @@ -73,8 +73,8 @@ class ReactionSummaryPresenter @Inject constructor( avatarUrl = member?.avatarUrl ) sender.copy(user = user) - }) - }) + }.toImmutableList()) + }.toImmutableList()) } } } diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/reactionsummary/ReactionSummaryState.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/reactionsummary/ReactionSummaryState.kt index 1d1606e53d..1ccfdc9abf 100644 --- a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/reactionsummary/ReactionSummaryState.kt +++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/reactionsummary/ReactionSummaryState.kt @@ -18,13 +18,14 @@ package io.element.android.features.messages.impl.timeline.components.reactionsu import io.element.android.features.messages.impl.timeline.model.AggregatedReaction import io.element.android.libraries.matrix.api.core.EventId +import kotlinx.collections.immutable.ImmutableList data class ReactionSummaryState( val target: Summary?, val eventSink: (ReactionSummaryEvents) -> Unit ) { data class Summary( - val reactions: List, + val reactions: ImmutableList, val selectedKey: String, val selectedEventId: EventId ) diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/factories/event/TimelineItemEventFactory.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/factories/event/TimelineItemEventFactory.kt index aea1019f11..c5d303b3f1 100644 --- a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/factories/event/TimelineItemEventFactory.kt +++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/factories/event/TimelineItemEventFactory.kt @@ -117,6 +117,7 @@ class TimelineItemEventFactory @Inject constructor( sentTime = timeFormatter.format(date), ) } + .toImmutableList() ) } // Sort aggregated reactions by count and then timestamp ascending, using @@ -127,7 +128,9 @@ class TimelineItemEventFactory @Inject constructor( compareByDescending { it.count } .thenBy { it.senders[0].timestamp } ) - return TimelineItemReactions(aggregatedReactions.toImmutableList()) + return TimelineItemReactions( + reactions = aggregatedReactions.toImmutableList() + ) } private fun MatrixTimelineItem.Event.computeReadReceiptState( diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/model/AggregatedReaction.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/model/AggregatedReaction.kt index 59c52ed8cf..cc6e956a1c 100644 --- a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/model/AggregatedReaction.kt +++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/model/AggregatedReaction.kt @@ -18,6 +18,7 @@ package io.element.android.features.messages.impl.timeline.model import io.element.android.libraries.core.extensions.ellipsize import io.element.android.libraries.matrix.api.core.UserId +import kotlinx.collections.immutable.ImmutableList /** * Length at which we ellipsize a reaction key for display @@ -35,28 +36,22 @@ private const val MAX_DISPLAY_CHARS = 16 data class AggregatedReaction( val currentUserId: UserId, val key: String, - val senders: List + val senders: ImmutableList ) { /** * The key to be displayed on screen. * * See [MAX_DISPLAY_CHARS]. */ - val displayKey: String by lazy { - key.ellipsize(MAX_DISPLAY_CHARS) - } + val displayKey: String = key.ellipsize(MAX_DISPLAY_CHARS) /** * The number of users who reacted with this key. */ - val count: Int by lazy { - senders.count() - } + val count: Int = senders.count() /** * True if the reaction has (also) been sent by the current user. */ - val isHighlighted: Boolean by lazy { - senders.any { it.senderId.value == currentUserId.value } - } + val isHighlighted: Boolean = senders.any { it.senderId == currentUserId } } diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/model/AggregatedReactionProvider.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/model/AggregatedReactionProvider.kt index dcd6bb105c..087de1753a 100644 --- a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/model/AggregatedReactionProvider.kt +++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/model/AggregatedReactionProvider.kt @@ -18,6 +18,7 @@ package io.element.android.features.messages.impl.timeline.model import androidx.compose.ui.tooling.preview.PreviewParameterProvider import io.element.android.libraries.matrix.api.core.UserId +import kotlinx.collections.immutable.toImmutableList import java.text.DateFormat import java.util.Date @@ -53,6 +54,6 @@ fun anAggregatedReaction( return AggregatedReaction( currentUserId = userId, key = key, - senders = senders + senders = senders.toImmutableList() ) } diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/model/AggregatedReactionSender.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/model/AggregatedReactionSender.kt index 276ee0b266..987474bf04 100644 --- a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/model/AggregatedReactionSender.kt +++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/model/AggregatedReactionSender.kt @@ -16,10 +16,12 @@ package io.element.android.features.messages.impl.timeline.model +import androidx.compose.runtime.Immutable import io.element.android.libraries.matrix.api.core.UserId import io.element.android.libraries.matrix.api.user.MatrixUser import java.util.Date +@Immutable data class AggregatedReactionSender( val senderId: UserId, val timestamp: Date, From 508b7e48e3fcccfc7e2e06bceb8657f9d146a520 Mon Sep 17 00:00:00 2001 From: Jorge Martin Espinosa Date: Fri, 19 Jul 2024 17:25:49 +0200 Subject: [PATCH 02/15] Only add private SSH keys and clone submodules in the original repo (#3225) --- .github/workflows/danger.yml | 1 + .github/workflows/quality.yml | 6 ++++++ .github/workflows/release.yml | 2 ++ .github/workflows/tests.yml | 1 + 4 files changed, 10 insertions(+) diff --git a/.github/workflows/danger.yml b/.github/workflows/danger.yml index b4fd79e5dd..5af04df63e 100644 --- a/.github/workflows/danger.yml +++ b/.github/workflows/danger.yml @@ -10,6 +10,7 @@ jobs: - uses: actions/checkout@v4 - name: Add SSH private keys for submodule repositories uses: webfactory/ssh-agent@v0.9.0 + if: github.repository == 'element-hq/element-x-android' with: ssh-private-key: ${{ secrets.ELEMENT_ENTERPRISE_DEPLOY_KEY }} - name: Clone submodules diff --git a/.github/workflows/quality.yml b/.github/workflows/quality.yml index ff435ee988..78961a0416 100644 --- a/.github/workflows/quality.yml +++ b/.github/workflows/quality.yml @@ -20,6 +20,7 @@ jobs: - uses: actions/checkout@v4 - name: Add SSH private keys for submodule repositories uses: webfactory/ssh-agent@v0.9.0 + if: github.repository == 'element-hq/element-x-android' with: ssh-private-key: ${{ secrets.ELEMENT_ENTERPRISE_DEPLOY_KEY }} - name: Clone submodules @@ -77,6 +78,7 @@ jobs: ref: ${{ github.event_name == 'pull_request' && github.event.pull_request.head.sha || github.ref }} - name: Add SSH private keys for submodule repositories uses: webfactory/ssh-agent@v0.9.0 + if: github.repository == 'element-hq/element-x-android' with: ssh-private-key: ${{ secrets.ELEMENT_ENTERPRISE_DEPLOY_KEY }} - name: Clone submodules @@ -116,6 +118,7 @@ jobs: ref: ${{ github.event_name == 'pull_request' && github.event.pull_request.head.sha || github.ref }} - name: Add SSH private keys for submodule repositories uses: webfactory/ssh-agent@v0.9.0 + if: github.repository == 'element-hq/element-x-android' with: ssh-private-key: ${{ secrets.ELEMENT_ENTERPRISE_DEPLOY_KEY }} - name: Clone submodules @@ -159,6 +162,7 @@ jobs: ref: ${{ github.event_name == 'pull_request' && github.event.pull_request.head.sha || github.ref }} - name: Add SSH private keys for submodule repositories uses: webfactory/ssh-agent@v0.9.0 + if: github.repository == 'element-hq/element-x-android' with: ssh-private-key: ${{ secrets.ELEMENT_ENTERPRISE_DEPLOY_KEY }} - name: Clone submodules @@ -198,6 +202,7 @@ jobs: ref: ${{ github.event_name == 'pull_request' && github.event.pull_request.head.sha || github.ref }} - name: Add SSH private keys for submodule repositories uses: webfactory/ssh-agent@v0.9.0 + if: github.repository == 'element-hq/element-x-android' with: ssh-private-key: ${{ secrets.ELEMENT_ENTERPRISE_DEPLOY_KEY }} - name: Clone submodules @@ -237,6 +242,7 @@ jobs: ref: ${{ github.event_name == 'pull_request' && github.event.pull_request.head.sha || github.ref }} - name: Add SSH private keys for submodule repositories uses: webfactory/ssh-agent@v0.9.0 + if: github.repository == 'element-hq/element-x-android' with: ssh-private-key: ${{ secrets.ELEMENT_ENTERPRISE_DEPLOY_KEY }} - name: Clone submodules diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index b58f2f3348..9dfa6c56c3 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -42,6 +42,7 @@ jobs: enterprise: name: Create App Bundle Enterprise runs-on: ubuntu-latest + if: github.repository == 'element-hq/element-x-android' concurrency: group: ${{ format('build-release-main-gplay-{0}', github.sha) }} cancel-in-progress: true @@ -49,6 +50,7 @@ jobs: - uses: actions/checkout@v4 - name: Add SSH private keys for submodule repositories uses: webfactory/ssh-agent@v0.9.0 + if: github.repository == 'element-hq/element-x-android' with: ssh-private-key: ${{ secrets.ELEMENT_ENTERPRISE_DEPLOY_KEY }} - name: Clone submodules diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index a132fd7d14..0d502abbb4 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -40,6 +40,7 @@ jobs: ref: ${{ github.event_name == 'pull_request' && github.event.pull_request.head.sha || github.ref }} - name: Add SSH private keys for submodule repositories uses: webfactory/ssh-agent@v0.9.0 + if: github.repository == 'element-hq/element-x-android' with: ssh-private-key: ${{ secrets.ELEMENT_ENTERPRISE_DEPLOY_KEY }} - name: Clone submodules From bbe1dc4952abe830d5c90ccfe97317e760728fba Mon Sep 17 00:00:00 2001 From: Jorge Martin Espinosa Date: Fri, 19 Jul 2024 17:46:56 +0200 Subject: [PATCH 03/15] Fix CI for forks (#3226) * Try with a different condition for forks * Skip danger in forks, the fallback token won't let it write comments in PRs anyway --- .github/workflows/build_enterprise.yml | 2 +- .github/workflows/danger.yml | 5 +++-- .github/workflows/generate_github_pages.yml | 2 +- .github/workflows/gradle-wrapper-update.yml | 2 +- .github/workflows/quality.yml | 25 +++++++++++---------- .github/workflows/release.yml | 4 ++-- .github/workflows/sync-localazy.yml | 2 +- .github/workflows/sync-sas-strings.yml | 2 +- .github/workflows/tests.yml | 4 ++-- 9 files changed, 25 insertions(+), 23 deletions(-) diff --git a/.github/workflows/build_enterprise.yml b/.github/workflows/build_enterprise.yml index 7547d5291c..602b43a7e1 100644 --- a/.github/workflows/build_enterprise.yml +++ b/.github/workflows/build_enterprise.yml @@ -17,7 +17,7 @@ jobs: name: Build Enterprise APKs runs-on: ubuntu-latest # Skip in forks - if: github.repository == 'element-hq/element-x-android' + if: ${{ github.event_name != 'pull_request' || github.event.pull_request.head.repo.full_name == 'element-hq/element-x-android' }} strategy: matrix: variant: [debug, release, nightly] diff --git a/.github/workflows/danger.yml b/.github/workflows/danger.yml index 5af04df63e..6b6ac8243e 100644 --- a/.github/workflows/danger.yml +++ b/.github/workflows/danger.yml @@ -6,15 +6,16 @@ jobs: build: runs-on: ubuntu-latest name: Danger main check + # Skip in forks, it doesn't work even with the fallback token + if: ${{ github.event_name != 'pull_request' || github.event.pull_request.head.repo.full_name == 'element-hq/element-x-android' }} steps: - uses: actions/checkout@v4 - name: Add SSH private keys for submodule repositories uses: webfactory/ssh-agent@v0.9.0 - if: github.repository == 'element-hq/element-x-android' with: ssh-private-key: ${{ secrets.ELEMENT_ENTERPRISE_DEPLOY_KEY }} - name: Clone submodules - if: github.repository == '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: | npm install --save-dev @babel/plugin-transform-flow-strip-types diff --git a/.github/workflows/generate_github_pages.yml b/.github/workflows/generate_github_pages.yml index 96f64eb1f7..46494ba76a 100644 --- a/.github/workflows/generate_github_pages.yml +++ b/.github/workflows/generate_github_pages.yml @@ -9,7 +9,7 @@ jobs: generate-github-pages: runs-on: ubuntu-latest # Skip in forks - if: github.repository == 'element-hq/element-x-android' + if: ${{ github.event_name != 'pull_request' || github.event.pull_request.head.repo.full_name == 'element-hq/element-x-android' }} steps: - name: ⏬ Checkout with LFS uses: nschloe/action-cached-lfs-checkout@v1.2.2 diff --git a/.github/workflows/gradle-wrapper-update.yml b/.github/workflows/gradle-wrapper-update.yml index b3493e3bf7..d35bace705 100644 --- a/.github/workflows/gradle-wrapper-update.yml +++ b/.github/workflows/gradle-wrapper-update.yml @@ -12,7 +12,7 @@ jobs: - name: Update Gradle Wrapper uses: gradle-update/update-gradle-wrapper-action@v1 # Skip in forks - if: github.repository == 'element-hq/element-x-android' + if: ${{ github.event_name != 'pull_request' || github.event.pull_request.head.repo.full_name == 'element-hq/element-x-android' }} with: repo-token: ${{ secrets.GITHUB_TOKEN }} target-branch: develop diff --git a/.github/workflows/quality.yml b/.github/workflows/quality.yml index 78961a0416..a0643c426f 100644 --- a/.github/workflows/quality.yml +++ b/.github/workflows/quality.yml @@ -20,11 +20,11 @@ jobs: - uses: actions/checkout@v4 - name: Add SSH private keys for submodule repositories uses: webfactory/ssh-agent@v0.9.0 - if: github.repository == 'element-hq/element-x-android' + if: ${{ github.event_name != 'pull_request' || github.event.pull_request.head.repo.full_name == 'element-hq/element-x-android' }} with: ssh-private-key: ${{ secrets.ELEMENT_ENTERPRISE_DEPLOY_KEY }} - name: Clone submodules - if: github.repository == '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 - name: Run code quality check suite run: ./tools/check/check_code_quality.sh @@ -78,11 +78,11 @@ jobs: ref: ${{ github.event_name == 'pull_request' && github.event.pull_request.head.sha || github.ref }} - name: Add SSH private keys for submodule repositories uses: webfactory/ssh-agent@v0.9.0 - if: github.repository == 'element-hq/element-x-android' + if: ${{ github.event_name != 'pull_request' || github.event.pull_request.head.repo.full_name == 'element-hq/element-x-android' }} with: ssh-private-key: ${{ secrets.ELEMENT_ENTERPRISE_DEPLOY_KEY }} - name: Clone submodules - if: github.repository == '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 - name: Use JDK 17 uses: actions/setup-java@v4 @@ -118,11 +118,11 @@ jobs: ref: ${{ github.event_name == 'pull_request' && github.event.pull_request.head.sha || github.ref }} - name: Add SSH private keys for submodule repositories uses: webfactory/ssh-agent@v0.9.0 - if: github.repository == 'element-hq/element-x-android' + if: ${{ github.event_name != 'pull_request' || github.event.pull_request.head.repo.full_name == 'element-hq/element-x-android' }} with: ssh-private-key: ${{ secrets.ELEMENT_ENTERPRISE_DEPLOY_KEY }} - name: Clone submodules - if: github.repository == '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 - name: Use JDK 17 uses: actions/setup-java@v4 @@ -162,11 +162,11 @@ jobs: ref: ${{ github.event_name == 'pull_request' && github.event.pull_request.head.sha || github.ref }} - name: Add SSH private keys for submodule repositories uses: webfactory/ssh-agent@v0.9.0 - if: github.repository == 'element-hq/element-x-android' + if: ${{ github.event_name != 'pull_request' || github.event.pull_request.head.repo.full_name == 'element-hq/element-x-android' }} with: ssh-private-key: ${{ secrets.ELEMENT_ENTERPRISE_DEPLOY_KEY }} - name: Clone submodules - if: github.repository == '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 - name: Use JDK 17 uses: actions/setup-java@v4 @@ -202,11 +202,11 @@ jobs: ref: ${{ github.event_name == 'pull_request' && github.event.pull_request.head.sha || github.ref }} - name: Add SSH private keys for submodule repositories uses: webfactory/ssh-agent@v0.9.0 - if: github.repository == 'element-hq/element-x-android' + if: ${{ github.event_name != 'pull_request' || github.event.pull_request.head.repo.full_name == 'element-hq/element-x-android' }} with: ssh-private-key: ${{ secrets.ELEMENT_ENTERPRISE_DEPLOY_KEY }} - name: Clone submodules - if: github.repository == '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 - name: Use JDK 17 uses: actions/setup-java@v4 @@ -242,11 +242,11 @@ jobs: ref: ${{ github.event_name == 'pull_request' && github.event.pull_request.head.sha || github.ref }} - name: Add SSH private keys for submodule repositories uses: webfactory/ssh-agent@v0.9.0 - if: github.repository == 'element-hq/element-x-android' + if: ${{ github.event_name != 'pull_request' || github.event.pull_request.head.repo.full_name == 'element-hq/element-x-android' }} with: ssh-private-key: ${{ secrets.ELEMENT_ENTERPRISE_DEPLOY_KEY }} - name: Clone submodules - if: github.repository == '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 - name: Use JDK 17 uses: actions/setup-java@v4 @@ -277,6 +277,7 @@ jobs: name: Project Check Suite runs-on: ubuntu-latest needs: [konsist, lint, ktlint, detekt] + if: ${{ github.event_name != 'pull_request' || github.event.pull_request.head.repo.full_name == 'element-hq/element-x-android' }} steps: - uses: actions/checkout@v4 with: diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 9dfa6c56c3..38be804fc1 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -42,7 +42,7 @@ jobs: enterprise: name: Create App Bundle Enterprise runs-on: ubuntu-latest - if: github.repository == 'element-hq/element-x-android' + if: ${{ github.event_name != 'pull_request' || github.event.pull_request.head.repo.full_name == 'element-hq/element-x-android' }} concurrency: group: ${{ format('build-release-main-gplay-{0}', github.sha) }} cancel-in-progress: true @@ -50,7 +50,7 @@ jobs: - uses: actions/checkout@v4 - name: Add SSH private keys for submodule repositories uses: webfactory/ssh-agent@v0.9.0 - if: github.repository == 'element-hq/element-x-android' + if: ${{ github.event_name != 'pull_request' || github.event.pull_request.head.repo.full_name == 'element-hq/element-x-android' }} with: ssh-private-key: ${{ secrets.ELEMENT_ENTERPRISE_DEPLOY_KEY }} - name: Clone submodules diff --git a/.github/workflows/sync-localazy.yml b/.github/workflows/sync-localazy.yml index 347923a6c0..5f99cac17a 100644 --- a/.github/workflows/sync-localazy.yml +++ b/.github/workflows/sync-localazy.yml @@ -9,7 +9,7 @@ jobs: sync-localazy: runs-on: ubuntu-latest # Skip in forks - if: github.repository == 'element-hq/element-x-android' + if: ${{ github.event_name != 'pull_request' || github.event.pull_request.head.repo.full_name == 'element-hq/element-x-android' }} steps: - uses: actions/checkout@v4 - name: Use JDK 17 diff --git a/.github/workflows/sync-sas-strings.yml b/.github/workflows/sync-sas-strings.yml index f9bff2905b..d06cfe268a 100644 --- a/.github/workflows/sync-sas-strings.yml +++ b/.github/workflows/sync-sas-strings.yml @@ -9,7 +9,7 @@ jobs: sync-sas-strings: runs-on: ubuntu-latest # Skip in forks - if: github.repository == 'element-hq/element-x-android' + if: ${{ github.event_name != 'pull_request' || github.event.pull_request.head.repo.full_name == 'element-hq/element-x-android' }} # No concurrency required, runs every time on a schedule. steps: - uses: actions/checkout@v4 diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index 0d502abbb4..fa274baf89 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -40,11 +40,11 @@ jobs: ref: ${{ github.event_name == 'pull_request' && github.event.pull_request.head.sha || github.ref }} - name: Add SSH private keys for submodule repositories uses: webfactory/ssh-agent@v0.9.0 - if: github.repository == 'element-hq/element-x-android' + if: ${{ github.event_name != 'pull_request' || github.event.pull_request.head.repo.full_name == 'element-hq/element-x-android' }} with: ssh-private-key: ${{ secrets.ELEMENT_ENTERPRISE_DEPLOY_KEY }} - name: Clone submodules - if: github.repository == '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 - name: ☕️ Use JDK 17 uses: actions/setup-java@v4 From bc87ff01cf9cb3aa46c2ec12a8a02900dba7de6c Mon Sep 17 00:00:00 2001 From: Jorge Martin Espinosa Date: Fri, 19 Jul 2024 17:51:44 +0200 Subject: [PATCH 04/15] Cancel ringing call notification on call cancellation (#3047) * Cancel ringing call notification on call cancellation * Improve implementation, add some comments to clarify how it works. * Make sure the call timeout job is cancelled --- .../call/impl/utils/ActiveCallManager.kt | 45 ++++ .../utils/DefaultActiveCallManagerTest.kt | 249 ++++++++++++------ .../matrix/test/FakeMatrixClientProvider.kt | 2 +- 3 files changed, 220 insertions(+), 76 deletions(-) diff --git a/features/call/impl/src/main/kotlin/io/element/android/features/call/impl/utils/ActiveCallManager.kt b/features/call/impl/src/main/kotlin/io/element/android/features/call/impl/utils/ActiveCallManager.kt index c02006cb54..1e217da7a8 100644 --- a/features/call/impl/src/main/kotlin/io/element/android/features/call/impl/utils/ActiveCallManager.kt +++ b/features/call/impl/src/main/kotlin/io/element/android/features/call/impl/utils/ActiveCallManager.kt @@ -25,14 +25,25 @@ import io.element.android.features.call.impl.notifications.CallNotificationData import io.element.android.features.call.impl.notifications.RingingCallNotificationCreator import io.element.android.libraries.di.AppScope import io.element.android.libraries.di.SingleIn +import io.element.android.libraries.matrix.api.MatrixClientProvider import io.element.android.libraries.push.api.notifications.ForegroundServiceType import io.element.android.libraries.push.api.notifications.NotificationIdProvider import io.element.android.libraries.push.api.notifications.OnMissedCallNotificationHandler import kotlinx.coroutines.CoroutineScope +import kotlinx.coroutines.ExperimentalCoroutinesApi import kotlinx.coroutines.Job import kotlinx.coroutines.delay import kotlinx.coroutines.flow.MutableStateFlow import kotlinx.coroutines.flow.StateFlow +import kotlinx.coroutines.flow.distinctUntilChanged +import kotlinx.coroutines.flow.drop +import kotlinx.coroutines.flow.filter +import kotlinx.coroutines.flow.filterNotNull +import kotlinx.coroutines.flow.flatMapLatest +import kotlinx.coroutines.flow.flowOf +import kotlinx.coroutines.flow.launchIn +import kotlinx.coroutines.flow.map +import kotlinx.coroutines.flow.onEach import kotlinx.coroutines.launch import timber.log.Timber import javax.inject.Inject @@ -79,11 +90,16 @@ class DefaultActiveCallManager @Inject constructor( private val onMissedCallNotificationHandler: OnMissedCallNotificationHandler, private val ringingCallNotificationCreator: RingingCallNotificationCreator, private val notificationManagerCompat: NotificationManagerCompat, + private val matrixClientProvider: MatrixClientProvider, ) : ActiveCallManager { private var timedOutCallJob: Job? = null override val activeCall = MutableStateFlow(null) + init { + observeRingingCall() + } + override fun registerIncomingCall(notificationData: CallNotificationData) { if (activeCall.value != null) { displayMissedCallNotification(notificationData) @@ -173,6 +189,35 @@ class DefaultActiveCallManager @Inject constructor( ) } } + + @OptIn(ExperimentalCoroutinesApi::class) + private fun observeRingingCall() { + // This will observe ringing calls and ensure they're terminated if the room call is cancelled + activeCall + .filterNotNull() + .filter { it.callState is CallState.Ringing && it.callType is CallType.RoomCall } + .flatMapLatest { activeCall -> + val callType = activeCall.callType as CallType.RoomCall + // Get a flow of updated `hasRoomCall` values for the room + matrixClientProvider.getOrRestore(callType.sessionId).getOrNull() + ?.getRoom(callType.roomId) + ?.roomInfoFlow + ?.map { it.hasRoomCall } + ?: flowOf() + } + // We only want to check if the room active call status changes + .distinctUntilChanged() + // Skip the first one, we're not interested in it (if the check below passes, it had to be active anyway) + .drop(1) + .onEach { roomHasActiveCall -> + if (!roomHasActiveCall) { + // The call was cancelled + timedOutCallJob?.cancel() + incomingCallTimedOut() + } + } + .launchIn(coroutineScope) + } } /** diff --git a/features/call/impl/src/test/kotlin/io/element/android/features/call/utils/DefaultActiveCallManagerTest.kt b/features/call/impl/src/test/kotlin/io/element/android/features/call/utils/DefaultActiveCallManagerTest.kt index d62f55c23d..b6f9e84a60 100644 --- a/features/call/impl/src/test/kotlin/io/element/android/features/call/utils/DefaultActiveCallManagerTest.kt +++ b/features/call/impl/src/test/kotlin/io/element/android/features/call/utils/DefaultActiveCallManagerTest.kt @@ -32,7 +32,10 @@ import io.element.android.libraries.matrix.test.AN_EVENT_ID import io.element.android.libraries.matrix.test.A_ROOM_ID import io.element.android.libraries.matrix.test.A_ROOM_ID_2 import io.element.android.libraries.matrix.test.A_SESSION_ID +import io.element.android.libraries.matrix.test.FakeMatrixClient import io.element.android.libraries.matrix.test.FakeMatrixClientProvider +import io.element.android.libraries.matrix.test.room.FakeMatrixRoom +import io.element.android.libraries.matrix.test.room.aRoomInfo import io.element.android.libraries.push.api.notifications.ForegroundServiceType import io.element.android.libraries.push.api.notifications.NotificationIdProvider import io.element.android.libraries.push.test.notifications.FakeImageLoaderHolder @@ -42,7 +45,11 @@ import io.element.android.tests.testutils.lambda.lambdaRecorder import io.element.android.tests.testutils.lambda.value import io.mockk.mockk import io.mockk.verify +import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.ExperimentalCoroutinesApi +import kotlinx.coroutines.SupervisorJob +import kotlinx.coroutines.cancel +import kotlinx.coroutines.launch import kotlinx.coroutines.test.TestScope import kotlinx.coroutines.test.advanceTimeBy import kotlinx.coroutines.test.runCurrent @@ -59,26 +66,28 @@ class DefaultActiveCallManagerTest { @Test fun `registerIncomingCall - sets the incoming call as active`() = runTest { val notificationManagerCompat = mockk(relaxed = true) - val manager = createActiveCallManager(notificationManagerCompat = notificationManagerCompat) + inCancellableScope { + val manager = createActiveCallManager(notificationManagerCompat = notificationManagerCompat) - assertThat(manager.activeCall.value).isNull() + assertThat(manager.activeCall.value).isNull() - val callNotificationData = aCallNotificationData() - manager.registerIncomingCall(callNotificationData) + val callNotificationData = aCallNotificationData() + manager.registerIncomingCall(callNotificationData) - assertThat(manager.activeCall.value).isEqualTo( - ActiveCall( - callType = CallType.RoomCall( - sessionId = callNotificationData.sessionId, - roomId = callNotificationData.roomId, - ), - callState = CallState.Ringing(callNotificationData) + assertThat(manager.activeCall.value).isEqualTo( + ActiveCall( + callType = CallType.RoomCall( + sessionId = callNotificationData.sessionId, + roomId = callNotificationData.roomId, + ), + callState = CallState.Ringing(callNotificationData) + ) ) - ) - runCurrent() + runCurrent() - verify { notificationManagerCompat.notify(notificationId, any()) } + verify { notificationManagerCompat.notify(notificationId, any()) } + } } @OptIn(ExperimentalCoroutinesApi::class) @@ -86,38 +95,42 @@ class DefaultActiveCallManagerTest { fun `registerIncomingCall - when there is an already active call adds missed call notification`() = runTest { val addMissedCallNotificationLambda = lambdaRecorder { _, _, _ -> } val onMissedCallNotificationHandler = FakeOnMissedCallNotificationHandler(addMissedCallNotificationLambda = addMissedCallNotificationLambda) - val manager = createActiveCallManager( - onMissedCallNotificationHandler = onMissedCallNotificationHandler, - ) + inCancellableScope { + val manager = createActiveCallManager( + onMissedCallNotificationHandler = onMissedCallNotificationHandler, + ) - // Register existing call - val callNotificationData = aCallNotificationData() - manager.registerIncomingCall(callNotificationData) - val activeCall = manager.activeCall.value + // Register existing call + val callNotificationData = aCallNotificationData() + manager.registerIncomingCall(callNotificationData) + val activeCall = manager.activeCall.value - // Now add a new call - manager.registerIncomingCall(aCallNotificationData(roomId = A_ROOM_ID_2)) + // Now add a new call + manager.registerIncomingCall(aCallNotificationData(roomId = A_ROOM_ID_2)) - assertThat(manager.activeCall.value).isEqualTo(activeCall) - assertThat((manager.activeCall.value?.callType as? CallType.RoomCall)?.roomId).isNotEqualTo(A_ROOM_ID_2) + assertThat(manager.activeCall.value).isEqualTo(activeCall) + assertThat((manager.activeCall.value?.callType as? CallType.RoomCall)?.roomId).isNotEqualTo(A_ROOM_ID_2) - advanceTimeBy(1) + advanceTimeBy(1) - addMissedCallNotificationLambda.assertions() - .isCalledOnce() - .with(value(A_SESSION_ID), value(A_ROOM_ID_2), value(AN_EVENT_ID)) + addMissedCallNotificationLambda.assertions() + .isCalledOnce() + .with(value(A_SESSION_ID), value(A_ROOM_ID_2), value(AN_EVENT_ID)) + } } @Test fun `incomingCallTimedOut - when there isn't an active call does nothing`() = runTest { val addMissedCallNotificationLambda = lambdaRecorder { _, _, _ -> } - val manager = createActiveCallManager( - onMissedCallNotificationHandler = FakeOnMissedCallNotificationHandler(addMissedCallNotificationLambda = addMissedCallNotificationLambda) - ) + inCancellableScope { + val manager = createActiveCallManager( + onMissedCallNotificationHandler = FakeOnMissedCallNotificationHandler(addMissedCallNotificationLambda = addMissedCallNotificationLambda) + ) - manager.incomingCallTimedOut() + manager.incomingCallTimedOut() - addMissedCallNotificationLambda.assertions().isNeverCalled() + addMissedCallNotificationLambda.assertions().isNeverCalled() + } } @OptIn(ExperimentalCoroutinesApi::class) @@ -125,82 +138,167 @@ class DefaultActiveCallManagerTest { fun `incomingCallTimedOut - when there is an active call removes it and adds a missed call notification`() = runTest { val notificationManagerCompat = mockk(relaxed = true) val addMissedCallNotificationLambda = lambdaRecorder { _, _, _ -> } - val manager = createActiveCallManager( - onMissedCallNotificationHandler = FakeOnMissedCallNotificationHandler(addMissedCallNotificationLambda = addMissedCallNotificationLambda), - notificationManagerCompat = notificationManagerCompat, - ) + inCancellableScope { + val manager = createActiveCallManager( + onMissedCallNotificationHandler = FakeOnMissedCallNotificationHandler(addMissedCallNotificationLambda = addMissedCallNotificationLambda), + notificationManagerCompat = notificationManagerCompat, + ) - manager.registerIncomingCall(aCallNotificationData()) - assertThat(manager.activeCall.value).isNotNull() + manager.registerIncomingCall(aCallNotificationData()) + assertThat(manager.activeCall.value).isNotNull() - manager.incomingCallTimedOut() - advanceTimeBy(1) + manager.incomingCallTimedOut() + advanceTimeBy(1) - assertThat(manager.activeCall.value).isNull() - addMissedCallNotificationLambda.assertions().isCalledOnce() - verify { notificationManagerCompat.cancel(notificationId) } + assertThat(manager.activeCall.value).isNull() + addMissedCallNotificationLambda.assertions().isCalledOnce() + verify { notificationManagerCompat.cancel(notificationId) } + } } @Test fun `hungUpCall - removes existing call if the CallType matches`() = runTest { val notificationManagerCompat = mockk(relaxed = true) - val manager = createActiveCallManager(notificationManagerCompat = notificationManagerCompat) + // Create a cancellable coroutine scope to cancel the test when needed + inCancellableScope { + val manager = createActiveCallManager(notificationManagerCompat = notificationManagerCompat) - val notificationData = aCallNotificationData() - manager.registerIncomingCall(notificationData) - assertThat(manager.activeCall.value).isNotNull() + val notificationData = aCallNotificationData() + manager.registerIncomingCall(notificationData) + assertThat(manager.activeCall.value).isNotNull() - manager.hungUpCall(CallType.RoomCall(notificationData.sessionId, notificationData.roomId)) - assertThat(manager.activeCall.value).isNull() + manager.hungUpCall(CallType.RoomCall(notificationData.sessionId, notificationData.roomId)) + assertThat(manager.activeCall.value).isNull() - verify { notificationManagerCompat.cancel(notificationId) } + verify { notificationManagerCompat.cancel(notificationId) } + } } @Test fun `hungUpCall - does nothing if the CallType doesn't match`() = runTest { val notificationManagerCompat = mockk(relaxed = true) - val manager = createActiveCallManager(notificationManagerCompat = notificationManagerCompat) + // Create a cancellable coroutine scope to cancel the test when needed + inCancellableScope { + val manager = createActiveCallManager(notificationManagerCompat = notificationManagerCompat) - manager.registerIncomingCall(aCallNotificationData()) - assertThat(manager.activeCall.value).isNotNull() + manager.registerIncomingCall(aCallNotificationData()) + assertThat(manager.activeCall.value).isNotNull() - manager.hungUpCall(CallType.ExternalUrl("https://example.com")) - assertThat(manager.activeCall.value).isNotNull() + manager.hungUpCall(CallType.ExternalUrl("https://example.com")) + assertThat(manager.activeCall.value).isNotNull() - verify(exactly = 0) { notificationManagerCompat.cancel(notificationId) } + verify(exactly = 0) { notificationManagerCompat.cancel(notificationId) } + } } @OptIn(ExperimentalCoroutinesApi::class) @Test fun `joinedCall - register an ongoing call and tries sending the call notify event`() = runTest { val notificationManagerCompat = mockk(relaxed = true) - val manager = createActiveCallManager( - notificationManagerCompat = notificationManagerCompat, - ) - assertThat(manager.activeCall.value).isNull() + inCancellableScope { + val manager = createActiveCallManager(notificationManagerCompat = notificationManagerCompat) + assertThat(manager.activeCall.value).isNull() - manager.joinedCall(CallType.RoomCall(A_SESSION_ID, A_ROOM_ID)) - assertThat(manager.activeCall.value).isEqualTo( - ActiveCall( - callType = CallType.RoomCall( - sessionId = A_SESSION_ID, - roomId = A_ROOM_ID, - ), - callState = CallState.InCall, + manager.joinedCall(CallType.RoomCall(A_SESSION_ID, A_ROOM_ID)) + assertThat(manager.activeCall.value).isEqualTo( + ActiveCall( + callType = CallType.RoomCall( + sessionId = A_SESSION_ID, + roomId = A_ROOM_ID, + ), + callState = CallState.InCall, + ) ) - ) - runCurrent() + runCurrent() - verify { notificationManagerCompat.cancel(notificationId) } + verify { notificationManagerCompat.cancel(notificationId) } + } } - private fun TestScope.createActiveCallManager( + @OptIn(ExperimentalCoroutinesApi::class) + @Test + fun `observeRingingCalls - will cancel the active ringing call if the call is cancelled`() = runTest { + val room = FakeMatrixRoom().apply { + givenRoomInfo(aRoomInfo()) + } + val client = FakeMatrixClient().apply { + givenGetRoomResult(A_ROOM_ID, room) + } + // Create a cancellable coroutine scope to cancel the test when needed + inCancellableScope { + val matrixClientProvider = FakeMatrixClientProvider(getClient = { Result.success(client) }) + val manager = createActiveCallManager(matrixClientProvider = matrixClientProvider) + + manager.registerIncomingCall(aCallNotificationData()) + + // Call is active (the other user join the call) + room.givenRoomInfo(aRoomInfo(hasRoomCall = true)) + advanceTimeBy(1) + // Call is cancelled (the other user left the call) + room.givenRoomInfo(aRoomInfo(hasRoomCall = false)) + advanceTimeBy(1) + + assertThat(manager.activeCall.value).isNull() + } + } + + @OptIn(ExperimentalCoroutinesApi::class) + @Test + fun `observeRingingCalls - will do nothing if either the session or the room are not found`() = runTest { + val room = FakeMatrixRoom().apply { + givenRoomInfo(aRoomInfo()) + } + val client = FakeMatrixClient().apply { + givenGetRoomResult(A_ROOM_ID, room) + } + // Create a cancellable coroutine scope to cancel the test when needed + inCancellableScope { + val matrixClientProvider = FakeMatrixClientProvider(getClient = { Result.failure(IllegalStateException("Matrix client not found")) }) + val manager = createActiveCallManager(matrixClientProvider = matrixClientProvider) + + // No matrix client + + manager.registerIncomingCall(aCallNotificationData()) + + room.givenRoomInfo(aRoomInfo(hasRoomCall = true)) + advanceTimeBy(1) + room.givenRoomInfo(aRoomInfo(hasRoomCall = false)) + advanceTimeBy(1) + + // The call should still be active + assertThat(manager.activeCall.value).isNotNull() + + // No room + client.givenGetRoomResult(A_ROOM_ID, null) + matrixClientProvider.getClient = { Result.success(client) } + + manager.registerIncomingCall(aCallNotificationData()) + + room.givenRoomInfo(aRoomInfo(hasRoomCall = true)) + advanceTimeBy(1) + room.givenRoomInfo(aRoomInfo(hasRoomCall = false)) + advanceTimeBy(1) + + // The call should still be active + assertThat(manager.activeCall.value).isNotNull() + } + } + + private fun TestScope.inCancellableScope(block: suspend CoroutineScope.() -> Unit) { + launch(SupervisorJob()) { + block() + cancel() + } + } + + private fun CoroutineScope.createActiveCallManager( matrixClientProvider: FakeMatrixClientProvider = FakeMatrixClientProvider(), onMissedCallNotificationHandler: FakeOnMissedCallNotificationHandler = FakeOnMissedCallNotificationHandler(), notificationManagerCompat: NotificationManagerCompat = mockk(relaxed = true), + coroutineScope: CoroutineScope = this, ) = DefaultActiveCallManager( - coroutineScope = this, + coroutineScope = coroutineScope, onMissedCallNotificationHandler = onMissedCallNotificationHandler, ringingCallNotificationCreator = RingingCallNotificationCreator( context = InstrumentationRegistry.getInstrumentation().targetContext, @@ -209,5 +307,6 @@ class DefaultActiveCallManagerTest { notificationBitmapLoader = FakeNotificationBitmapLoader(), ), notificationManagerCompat = notificationManagerCompat, + matrixClientProvider = matrixClientProvider, ) } diff --git a/libraries/matrix/test/src/main/kotlin/io/element/android/libraries/matrix/test/FakeMatrixClientProvider.kt b/libraries/matrix/test/src/main/kotlin/io/element/android/libraries/matrix/test/FakeMatrixClientProvider.kt index 53ebf00f41..de03a43df5 100644 --- a/libraries/matrix/test/src/main/kotlin/io/element/android/libraries/matrix/test/FakeMatrixClientProvider.kt +++ b/libraries/matrix/test/src/main/kotlin/io/element/android/libraries/matrix/test/FakeMatrixClientProvider.kt @@ -21,7 +21,7 @@ import io.element.android.libraries.matrix.api.MatrixClientProvider import io.element.android.libraries.matrix.api.core.SessionId class FakeMatrixClientProvider( - private val getClient: (SessionId) -> Result = { Result.success(FakeMatrixClient()) } + var getClient: (SessionId) -> Result = { Result.success(FakeMatrixClient()) } ) : MatrixClientProvider { override suspend fun getOrRestore(sessionId: SessionId): Result = getClient(sessionId) From cdcaace22718947b73f355ae830761b4289ddb7d Mon Sep 17 00:00:00 2001 From: Marco Antonio Alvarez Date: Fri, 19 Jul 2024 22:14:22 +0200 Subject: [PATCH 05/15] Fix stickers display text on room summary (#3221) Signed-off-by: Marco Antonio Alvarez --- .../eventformatter/impl/DefaultRoomLastMessageFormatter.kt | 2 +- .../impl/DefaultRoomLastMessageFormatterTest.kt | 5 +++-- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/libraries/eventformatter/impl/src/main/kotlin/io/element/android/libraries/eventformatter/impl/DefaultRoomLastMessageFormatter.kt b/libraries/eventformatter/impl/src/main/kotlin/io/element/android/libraries/eventformatter/impl/DefaultRoomLastMessageFormatter.kt index 428e6d1da1..13655c48f2 100644 --- a/libraries/eventformatter/impl/src/main/kotlin/io/element/android/libraries/eventformatter/impl/DefaultRoomLastMessageFormatter.kt +++ b/libraries/eventformatter/impl/src/main/kotlin/io/element/android/libraries/eventformatter/impl/DefaultRoomLastMessageFormatter.kt @@ -85,7 +85,7 @@ class DefaultRoomLastMessageFormatter @Inject constructor( } } is StickerContent -> { - content.body + prefixIfNeeded(sp.getString(CommonStrings.common_sticker) + " (" + content.body + ")", senderDisambiguatedDisplayName, isDmRoom) } is UnableToDecryptContent -> { val message = sp.getString(CommonStrings.common_waiting_for_decryption_key) diff --git a/libraries/eventformatter/impl/src/test/kotlin/io/element/android/libraries/eventformatter/impl/DefaultRoomLastMessageFormatterTest.kt b/libraries/eventformatter/impl/src/test/kotlin/io/element/android/libraries/eventformatter/impl/DefaultRoomLastMessageFormatterTest.kt index 5255fcea4a..5465882479 100644 --- a/libraries/eventformatter/impl/src/test/kotlin/io/element/android/libraries/eventformatter/impl/DefaultRoomLastMessageFormatterTest.kt +++ b/libraries/eventformatter/impl/src/test/kotlin/io/element/android/libraries/eventformatter/impl/DefaultRoomLastMessageFormatterTest.kt @@ -105,11 +105,12 @@ class DefaultRoomLastMessageFormatterTest { @Test @Config(qualifiers = "en") fun `Sticker content`() { - val body = "body" + val body = "a sticker body" val info = ImageInfo(null, null, null, null, null, null, null) val message = createRoomEvent(false, null, StickerContent(body, info, aMediaSource(url = "url"))) val result = formatter.format(message, false) - assertThat(result).isEqualTo(body) + val expectedBody = someoneElseId.toString() + ": Sticker (a sticker body)" + assertThat(result.toString()).isEqualTo(expectedBody) } @Test From 5219216eac0aed8a32c9abfb82e41fdafec7c552 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Sat, 20 Jul 2024 08:32:35 +0000 Subject: [PATCH 06/15] Update telephoto to v0.12.1 --- gradle/libs.versions.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index e39b0297b6..97f6585b34 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -45,7 +45,7 @@ showkase = "1.0.3" appyx = "1.4.0" sqldelight = "2.0.2" wysiwyg = "2.37.7" -telephoto = "0.12.0" +telephoto = "0.12.1" # DI dagger = "2.51.1" From 94f38f1af5f4bb430b32304db659d09d2b0205e7 Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Mon, 22 Jul 2024 10:39:48 +0200 Subject: [PATCH 07/15] Rework FakeMatrixRoom so that it contains only lambdas. (#3229) * Upgrade lint to 8.7.0-alpha01 * FakeMatrixRoom: lambda everywhere Fix test compilation issues --- .../appnav/JoinRoomLoadedFlowNodeTest.kt | 8 +- .../android/appnav/loggedin/SendQueuesTest.kt | 16 +- .../utils/DefaultCallWidgetProviderTest.kt | 38 +- .../AcceptDeclineInvitePresenterTest.kt | 8 +- .../impl/DefaultLeaveRoomPresenterTest.kt | 20 +- .../impl/send/SendLocationPresenterTest.kt | 74 ++- .../messages/impl/MessagesPresenterTest.kt | 186 ++++++- .../AttachmentsPreviewPresenterTest.kt | 26 +- .../impl/report/ReportMessagePresenterTest.kt | 30 +- .../MessageComposerPresenterTest.kt | 142 +++-- .../impl/timeline/TimelineControllerTest.kt | 31 +- .../impl/timeline/TimelinePresenterTest.kt | 28 +- .../VoiceMessageComposerPresenterTest.kt | 26 +- .../impl/create/CreatePollPresenterTest.kt | 54 +- .../features/roomdetails/MatrixRoomFixture.kt | 26 +- .../roomdetails/RoomDetailsPresenterTest.kt | 283 +++++++--- .../edit/RoomDetailsEditPresenterTest.kt | 169 +++--- .../members/RoomMemberListPresenterTest.kt | 71 ++- .../details/RoomMemberDetailsPresenterTest.kt | 88 ++- ...faultRoomMembersModerationPresenterTest.kt | 104 ++-- .../RolesAndPermissionPresenterTest.kt | 21 +- .../changeroles/ChangeRolesPresenterTest.kt | 15 +- .../ChangeRoomPermissionsPresenterTest.kt | 25 +- .../roomlist/impl/RoomListPresenterTest.kt | 13 +- .../features/share/impl/SharePresenterTest.kt | 9 +- gradle.properties | 2 +- .../matrix/test/room/FakeMatrixRoom.kt | 523 +++++------------- libraries/mediaupload/api/build.gradle.kts | 1 + .../mediaupload/api/MediaSenderTest.kt | 23 +- ...otificationBroadcastReceiverHandlerTest.kt | 11 +- 30 files changed, 1253 insertions(+), 818 deletions(-) diff --git a/appnav/src/test/kotlin/io/element/android/appnav/JoinRoomLoadedFlowNodeTest.kt b/appnav/src/test/kotlin/io/element/android/appnav/JoinRoomLoadedFlowNodeTest.kt index d307f851cd..b1009f20da 100644 --- a/appnav/src/test/kotlin/io/element/android/appnav/JoinRoomLoadedFlowNodeTest.kt +++ b/appnav/src/test/kotlin/io/element/android/appnav/JoinRoomLoadedFlowNodeTest.kt @@ -123,7 +123,9 @@ class JoinRoomLoadedFlowNodeTest { @Test fun `given a room flow node when initialized then it loads messages entry point`() = runTest { // GIVEN - val room = FakeMatrixRoom() + val room = FakeMatrixRoom( + updateMembersResult = { } + ) val fakeMessagesEntryPoint = FakeMessagesEntryPoint() val inputs = JoinedRoomLoadedFlowNode.Inputs(room, RoomNavigationTarget.Messages()) val roomFlowNode = createJoinedRoomLoadedFlowNode( @@ -144,7 +146,9 @@ class JoinRoomLoadedFlowNodeTest { @Test fun `given a room flow node when callback on room details is triggered then it loads room details entry point`() = runTest { // GIVEN - val room = FakeMatrixRoom() + val room = FakeMatrixRoom( + updateMembersResult = { } + ) val fakeMessagesEntryPoint = FakeMessagesEntryPoint() val fakeRoomDetailsEntryPoint = FakeRoomDetailsEntryPoint() val inputs = JoinedRoomLoadedFlowNode.Inputs(room, RoomNavigationTarget.Messages()) diff --git a/appnav/src/test/kotlin/io/element/android/appnav/loggedin/SendQueuesTest.kt b/appnav/src/test/kotlin/io/element/android/appnav/loggedin/SendQueuesTest.kt index bb4e8f3dbf..91f0aee517 100644 --- a/appnav/src/test/kotlin/io/element/android/appnav/loggedin/SendQueuesTest.kt +++ b/appnav/src/test/kotlin/io/element/android/appnav/loggedin/SendQueuesTest.kt @@ -33,7 +33,6 @@ import org.junit.Test @OptIn(ExperimentalCoroutinesApi::class) class SendQueuesTest { private val matrixClient = FakeMatrixClient() - private val room = FakeMatrixRoom() private val networkMonitor = FakeNetworkMonitor() private val sut = SendQueues(matrixClient, networkMonitor) @@ -43,11 +42,11 @@ import org.junit.Test val setAllSendQueuesEnabledLambda = lambdaRecorder { _: Boolean -> } matrixClient.sendQueueDisabledFlow = sendQueueDisabledFlow matrixClient.setAllSendQueuesEnabledLambda = setAllSendQueuesEnabledLambda - matrixClient.givenGetRoomResult(room.roomId, room) - val setRoomSendQueueEnabledLambda = lambdaRecorder { _: Boolean -> } - room.setSendQueueEnabledLambda = setRoomSendQueueEnabledLambda - + val room = FakeMatrixRoom( + setSendQueueEnabledLambda = setRoomSendQueueEnabledLambda + ) + matrixClient.givenGetRoomResult(room.roomId, room) sut.launchIn(backgroundScope) sendQueueDisabledFlow.emit(room.roomId) @@ -72,10 +71,11 @@ import org.junit.Test matrixClient.sendQueueDisabledFlow = sendQueueDisabledFlow matrixClient.setAllSendQueuesEnabledLambda = setAllSendQueuesEnabledLambda networkMonitor.connectivity.value = NetworkStatus.Offline - matrixClient.givenGetRoomResult(room.roomId, room) - val setRoomSendQueueEnabledLambda = lambdaRecorder { _: Boolean -> } - room.setSendQueueEnabledLambda = setRoomSendQueueEnabledLambda + val room = FakeMatrixRoom( + setSendQueueEnabledLambda = setRoomSendQueueEnabledLambda + ) + matrixClient.givenGetRoomResult(room.roomId, room) sut.launchIn(backgroundScope) diff --git a/features/call/impl/src/test/kotlin/io/element/android/features/call/utils/DefaultCallWidgetProviderTest.kt b/features/call/impl/src/test/kotlin/io/element/android/features/call/utils/DefaultCallWidgetProviderTest.kt index 7eb426c35e..a0c2f9a80e 100644 --- a/features/call/impl/src/test/kotlin/io/element/android/features/call/utils/DefaultCallWidgetProviderTest.kt +++ b/features/call/impl/src/test/kotlin/io/element/android/features/call/utils/DefaultCallWidgetProviderTest.kt @@ -54,9 +54,9 @@ class DefaultCallWidgetProviderTest { @Test fun `getWidget - fails if it can't generate the URL for the widget`() = runTest { - val room = FakeMatrixRoom().apply { - givenGenerateWidgetWebViewUrlResult(Result.failure(Exception("Can't generate URL for widget"))) - } + val room = FakeMatrixRoom( + generateWidgetWebViewUrlResult = { _, _, _, _ -> Result.failure(Exception("Can't generate URL for widget")) } + ) val client = FakeMatrixClient().apply { givenGetRoomResult(A_ROOM_ID, room) } @@ -66,10 +66,10 @@ class DefaultCallWidgetProviderTest { @Test fun `getWidget - fails if it can't get the widget driver`() = runTest { - val room = FakeMatrixRoom().apply { - givenGenerateWidgetWebViewUrlResult(Result.success("url")) - givenGetWidgetDriverResult(Result.failure(Exception("Can't get a widget driver"))) - } + val room = FakeMatrixRoom( + generateWidgetWebViewUrlResult = { _, _, _, _ -> Result.success("url") }, + getWidgetDriverResult = { Result.failure(Exception("Can't get a widget driver")) } + ) val client = FakeMatrixClient().apply { givenGetRoomResult(A_ROOM_ID, room) } @@ -79,10 +79,10 @@ class DefaultCallWidgetProviderTest { @Test fun `getWidget - returns a widget driver when all steps are successful`() = runTest { - val room = FakeMatrixRoom().apply { - givenGenerateWidgetWebViewUrlResult(Result.success("url")) - givenGetWidgetDriverResult(Result.success(FakeMatrixWidgetDriver())) - } + val room = FakeMatrixRoom( + generateWidgetWebViewUrlResult = { _, _, _, _ -> Result.success("url") }, + getWidgetDriverResult = { Result.success(FakeMatrixWidgetDriver()) }, + ) val client = FakeMatrixClient().apply { givenGetRoomResult(A_ROOM_ID, room) } @@ -92,10 +92,10 @@ class DefaultCallWidgetProviderTest { @Test fun `getWidget - will use a custom base url if it exists`() = runTest { - val room = FakeMatrixRoom().apply { - givenGenerateWidgetWebViewUrlResult(Result.success("url")) - givenGetWidgetDriverResult(Result.success(FakeMatrixWidgetDriver())) - } + val room = FakeMatrixRoom( + generateWidgetWebViewUrlResult = { _, _, _, _ -> Result.success("url") }, + getWidgetDriverResult = { Result.success(FakeMatrixWidgetDriver()) }, + ) val client = FakeMatrixClient().apply { givenGetRoomResult(A_ROOM_ID, room) } @@ -120,10 +120,10 @@ class DefaultCallWidgetProviderTest { val elementCallBaseUrlProvider = FakeElementCallBaseUrlProvider { matrixClient -> providesLambda(matrixClient) } - val room = FakeMatrixRoom().apply { - givenGenerateWidgetWebViewUrlResult(Result.success("url")) - givenGetWidgetDriverResult(Result.success(FakeMatrixWidgetDriver())) - } + val room = FakeMatrixRoom( + generateWidgetWebViewUrlResult = { _, _, _, _ -> Result.success("url") }, + getWidgetDriverResult = { Result.success(FakeMatrixWidgetDriver()) }, + ) val client = FakeMatrixClient().apply { givenGetRoomResult(A_ROOM_ID, room) } diff --git a/features/invite/impl/src/test/kotlin/io/element/android/features/invite/impl/response/AcceptDeclineInvitePresenterTest.kt b/features/invite/impl/src/test/kotlin/io/element/android/features/invite/impl/response/AcceptDeclineInvitePresenterTest.kt index 9a12e33b33..39a0321b01 100644 --- a/features/invite/impl/src/test/kotlin/io/element/android/features/invite/impl/response/AcceptDeclineInvitePresenterTest.kt +++ b/features/invite/impl/src/test/kotlin/io/element/android/features/invite/impl/response/AcceptDeclineInvitePresenterTest.kt @@ -92,9 +92,9 @@ class AcceptDeclineInvitePresenterTest { val client = FakeMatrixClient().apply { givenGetRoomResult( roomId = A_ROOM_ID, - result = FakeMatrixRoom().apply { + result = FakeMatrixRoom( leaveRoomLambda = declineInviteFailure - } + ) ) } val presenter = createAcceptDeclineInvitePresenter(client = client) @@ -142,9 +142,9 @@ class AcceptDeclineInvitePresenterTest { val client = FakeMatrixClient().apply { givenGetRoomResult( roomId = A_ROOM_ID, - result = FakeMatrixRoom().apply { + result = FakeMatrixRoom( leaveRoomLambda = declineInviteSuccess - } + ) ) } val presenter = createAcceptDeclineInvitePresenter( diff --git a/features/leaveroom/impl/src/test/kotlin/io/element/android/features/leaveroom/impl/DefaultLeaveRoomPresenterTest.kt b/features/leaveroom/impl/src/test/kotlin/io/element/android/features/leaveroom/impl/DefaultLeaveRoomPresenterTest.kt index 49b44851de..a063b9ca90 100644 --- a/features/leaveroom/impl/src/test/kotlin/io/element/android/features/leaveroom/impl/DefaultLeaveRoomPresenterTest.kt +++ b/features/leaveroom/impl/src/test/kotlin/io/element/android/features/leaveroom/impl/DefaultLeaveRoomPresenterTest.kt @@ -140,7 +140,9 @@ class DefaultLeaveRoomPresenterTest { client = FakeMatrixClient().apply { givenGetRoomResult( roomId = A_ROOM_ID, - result = FakeMatrixRoom(), + result = FakeMatrixRoom( + leaveRoomLambda = { Result.success(Unit) } + ), ) }, roomMembershipObserver = roomMembershipObserver @@ -162,9 +164,9 @@ class DefaultLeaveRoomPresenterTest { client = FakeMatrixClient().apply { givenGetRoomResult( roomId = A_ROOM_ID, - result = FakeMatrixRoom().apply { - this.leaveRoomLambda = { Result.failure(RuntimeException("Blimey!")) } - }, + result = FakeMatrixRoom( + leaveRoomLambda = { Result.failure(RuntimeException("Blimey!")) } + ), ) } ) @@ -186,7 +188,9 @@ class DefaultLeaveRoomPresenterTest { client = FakeMatrixClient().apply { givenGetRoomResult( roomId = A_ROOM_ID, - result = FakeMatrixRoom(), + result = FakeMatrixRoom( + leaveRoomLambda = { Result.success(Unit) } + ), ) } ) @@ -208,9 +212,9 @@ class DefaultLeaveRoomPresenterTest { client = FakeMatrixClient().apply { givenGetRoomResult( roomId = A_ROOM_ID, - result = FakeMatrixRoom().apply { - this.leaveRoomLambda = { Result.failure(RuntimeException("Blimey!")) } - }, + result = FakeMatrixRoom( + leaveRoomLambda = { Result.failure(RuntimeException("Blimey!")) } + ), ) } ) diff --git a/features/location/impl/src/test/kotlin/io/element/android/features/location/impl/send/SendLocationPresenterTest.kt b/features/location/impl/src/test/kotlin/io/element/android/features/location/impl/send/SendLocationPresenterTest.kt index 93e15f7868..24fcd3537c 100644 --- a/features/location/impl/src/test/kotlin/io/element/android/features/location/impl/send/SendLocationPresenterTest.kt +++ b/features/location/impl/src/test/kotlin/io/element/android/features/location/impl/send/SendLocationPresenterTest.kt @@ -29,13 +29,15 @@ import io.element.android.features.location.impl.common.permissions.PermissionsE import io.element.android.features.location.impl.common.permissions.PermissionsPresenter import io.element.android.features.location.impl.common.permissions.PermissionsState import io.element.android.features.messages.test.FakeMessageComposerContext +import io.element.android.libraries.matrix.api.room.MatrixRoom import io.element.android.libraries.matrix.api.room.location.AssetType import io.element.android.libraries.matrix.test.core.aBuildMeta import io.element.android.libraries.matrix.test.room.FakeMatrixRoom -import io.element.android.libraries.matrix.test.room.SendLocationInvocation import io.element.android.libraries.textcomposer.model.MessageComposerMode import io.element.android.services.analytics.test.FakeAnalyticsService import io.element.android.tests.testutils.WarmUpRule +import io.element.android.tests.testutils.lambda.lambdaRecorder +import io.element.android.tests.testutils.lambda.value import kotlinx.coroutines.delay import kotlinx.coroutines.test.runTest import org.junit.Rule @@ -46,16 +48,18 @@ class SendLocationPresenterTest { val warmUpRule = WarmUpRule() private val fakePermissionsPresenter = FakePermissionsPresenter() - private val fakeMatrixRoom = FakeMatrixRoom() private val fakeAnalyticsService = FakeAnalyticsService() private val fakeMessageComposerContext = FakeMessageComposerContext() private val fakeLocationActions = FakeLocationActions() private val fakeBuildMeta = aBuildMeta(applicationName = "app name") - private val sendLocationPresenter: SendLocationPresenter = SendLocationPresenter( + + private fun createSendLocationPresenter( + matrixRoom: MatrixRoom = FakeMatrixRoom(), + ): SendLocationPresenter = SendLocationPresenter( permissionsPresenterFactory = object : PermissionsPresenter.Factory { override fun create(permissions: List): PermissionsPresenter = fakePermissionsPresenter }, - room = fakeMatrixRoom, + room = matrixRoom, analyticsService = fakeAnalyticsService, messageComposerContext = fakeMessageComposerContext, locationActions = fakeLocationActions, @@ -64,6 +68,7 @@ class SendLocationPresenterTest { @Test fun `initial state with permissions granted`() = runTest { + val sendLocationPresenter = createSendLocationPresenter() fakePermissionsPresenter.givenState( aPermissionsState( permissions = PermissionsState.Permissions.AllGranted, @@ -90,6 +95,7 @@ class SendLocationPresenterTest { @Test fun `initial state with permissions partially granted`() = runTest { + val sendLocationPresenter = createSendLocationPresenter() fakePermissionsPresenter.givenState( aPermissionsState( permissions = PermissionsState.Permissions.SomeGranted, @@ -116,6 +122,7 @@ class SendLocationPresenterTest { @Test fun `initial state with permissions denied`() = runTest { + val sendLocationPresenter = createSendLocationPresenter() fakePermissionsPresenter.givenState( aPermissionsState( permissions = PermissionsState.Permissions.NoneGranted, @@ -142,6 +149,7 @@ class SendLocationPresenterTest { @Test fun `initial state with permissions denied once`() = runTest { + val sendLocationPresenter = createSendLocationPresenter() fakePermissionsPresenter.givenState( aPermissionsState( permissions = PermissionsState.Permissions.NoneGranted, @@ -168,6 +176,7 @@ class SendLocationPresenterTest { @Test fun `rationale dialog dismiss`() = runTest { + val sendLocationPresenter = createSendLocationPresenter() fakePermissionsPresenter.givenState( aPermissionsState( permissions = PermissionsState.Permissions.NoneGranted, @@ -199,6 +208,7 @@ class SendLocationPresenterTest { @Test fun `rationale dialog continue`() = runTest { + val sendLocationPresenter = createSendLocationPresenter() fakePermissionsPresenter.givenState( aPermissionsState( permissions = PermissionsState.Permissions.NoneGranted, @@ -227,6 +237,7 @@ class SendLocationPresenterTest { @Test fun `permission denied dialog dismiss`() = runTest { + val sendLocationPresenter = createSendLocationPresenter() fakePermissionsPresenter.givenState( aPermissionsState( permissions = PermissionsState.Permissions.NoneGranted, @@ -258,6 +269,13 @@ class SendLocationPresenterTest { @Test fun `share sender location`() = runTest { + val sendLocationResult = lambdaRecorder> { _, _, _, _, _ -> + Result.success(Unit) + } + val matrixRoom = FakeMatrixRoom( + sendLocationResult = sendLocationResult, + ) + val sendLocationPresenter = createSendLocationPresenter(matrixRoom) fakePermissionsPresenter.givenState( aPermissionsState( permissions = PermissionsState.Permissions.AllGranted, @@ -289,16 +307,14 @@ class SendLocationPresenterTest { delay(1) // Wait for the coroutine to finish - assertThat(fakeMatrixRoom.sentLocations.size).isEqualTo(1) - assertThat(fakeMatrixRoom.sentLocations.last()).isEqualTo( - SendLocationInvocation( - body = "Location was shared at geo:3.0,4.0;u=5.0", - geoUri = "geo:3.0,4.0;u=5.0", - description = null, - zoomLevel = 15, - assetType = AssetType.SENDER + sendLocationResult.assertions().isCalledOnce() + .with( + value("Location was shared at geo:3.0,4.0;u=5.0"), + value("geo:3.0,4.0;u=5.0"), + value(null), + value(15), + value(AssetType.SENDER), ) - ) assertThat(fakeAnalyticsService.capturedEvents.size).isEqualTo(1) assertThat(fakeAnalyticsService.capturedEvents.last()).isEqualTo( @@ -314,6 +330,13 @@ class SendLocationPresenterTest { @Test fun `share pin location`() = runTest { + val sendLocationResult = lambdaRecorder> { _, _, _, _, _ -> + Result.success(Unit) + } + val matrixRoom = FakeMatrixRoom( + sendLocationResult = sendLocationResult, + ) + val sendLocationPresenter = createSendLocationPresenter(matrixRoom) fakePermissionsPresenter.givenState( aPermissionsState( permissions = PermissionsState.Permissions.NoneGranted, @@ -345,16 +368,14 @@ class SendLocationPresenterTest { delay(1) // Wait for the coroutine to finish - assertThat(fakeMatrixRoom.sentLocations.size).isEqualTo(1) - assertThat(fakeMatrixRoom.sentLocations.last()).isEqualTo( - SendLocationInvocation( - body = "Location was shared at geo:0.0,1.0", - geoUri = "geo:0.0,1.0", - description = null, - zoomLevel = 15, - assetType = AssetType.PIN + sendLocationResult.assertions().isCalledOnce() + .with( + value("Location was shared at geo:0.0,1.0"), + value("geo:0.0,1.0"), + value(null), + value(15), + value(AssetType.PIN), ) - ) assertThat(fakeAnalyticsService.capturedEvents.size).isEqualTo(1) assertThat(fakeAnalyticsService.capturedEvents.last()).isEqualTo( @@ -370,6 +391,13 @@ class SendLocationPresenterTest { @Test fun `composer context passes through analytics`() = runTest { + val sendLocationResult = lambdaRecorder> { _, _, _, _, _ -> + Result.success(Unit) + } + val matrixRoom = FakeMatrixRoom( + sendLocationResult = sendLocationResult, + ) + val sendLocationPresenter = createSendLocationPresenter(matrixRoom) fakePermissionsPresenter.givenState( aPermissionsState( permissions = PermissionsState.Permissions.NoneGranted, @@ -418,6 +446,7 @@ class SendLocationPresenterTest { @Test fun `open settings activity`() = runTest { + val sendLocationPresenter = createSendLocationPresenter() fakePermissionsPresenter.givenState( aPermissionsState( permissions = PermissionsState.Permissions.NoneGranted, @@ -452,6 +481,7 @@ class SendLocationPresenterTest { @Test fun `application name is in state`() = runTest { + val sendLocationPresenter = createSendLocationPresenter() moleculeFlow(RecompositionMode.Immediate) { sendLocationPresenter.present() }.test { diff --git a/features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/MessagesPresenterTest.kt b/features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/MessagesPresenterTest.kt index 2d08b8d4a2..091305893e 100644 --- a/features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/MessagesPresenterTest.kt +++ b/features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/MessagesPresenterTest.kt @@ -65,6 +65,7 @@ import io.element.android.libraries.featureflag.api.FeatureFlags import io.element.android.libraries.featureflag.test.FakeFeatureFlagService import io.element.android.libraries.matrix.api.core.EventId import io.element.android.libraries.matrix.api.core.TransactionId +import io.element.android.libraries.matrix.api.core.UserId import io.element.android.libraries.matrix.api.media.MediaSource import io.element.android.libraries.matrix.api.permalink.PermalinkParser import io.element.android.libraries.matrix.api.room.MatrixRoom @@ -103,6 +104,7 @@ import io.element.android.tests.testutils.WarmUpRule import io.element.android.tests.testutils.consumeItemsUntilPredicate import io.element.android.tests.testutils.consumeItemsUntilTimeout import io.element.android.tests.testutils.lambda.assert +import io.element.android.tests.testutils.lambda.lambdaError import io.element.android.tests.testutils.lambda.lambdaRecorder import io.element.android.tests.testutils.lambda.value import io.element.android.tests.testutils.testCoroutineDispatchers @@ -136,7 +138,7 @@ class MessagesPresenterTest { assertThat(initialState.roomAvatar) .isEqualTo(AsyncData.Success(AvatarData(id = A_ROOM_ID.value, name = "", url = AN_AVATAR_URL, size = AvatarSize.TimelineRoom))) assertThat(initialState.userHasPermissionToSendMessage).isTrue() - assertThat(initialState.userHasPermissionToRedactOwn).isFalse() + assertThat(initialState.userHasPermissionToRedactOwn).isTrue() assertThat(initialState.hasNetworkConnection).isTrue() assertThat(initialState.snackbarMessage).isNull() assertThat(initialState.inviteProgress).isEqualTo(AsyncData.Uninitialized) @@ -147,7 +149,13 @@ class MessagesPresenterTest { @OptIn(ExperimentalCoroutinesApi::class) @Test fun `present - check that the room's unread flag is removed`() = runTest { - val room = FakeMatrixRoom() + val room = FakeMatrixRoom( + canUserSendMessageResult = { _, _ -> Result.success(true) }, + canRedactOwnResult = { Result.success(true) }, + canRedactOtherResult = { Result.success(true) }, + canUserJoinCallResult = { Result.success(true) }, + typingNoticeResult = { Result.success(Unit) }, + ) assertThat(room.markAsReadCalls).isEmpty() val presenter = createMessagesPresenter(matrixRoom = room) moleculeFlow(RecompositionMode.Immediate) { @@ -161,8 +169,13 @@ class MessagesPresenterTest { @Test fun `present - call is disabled if user cannot join it even if there is an ongoing call`() = runTest { - val room = FakeMatrixRoom().apply { - givenCanUserJoinCall(Result.success(false)) + val room = FakeMatrixRoom( + canUserJoinCallResult = { Result.success(false) }, + canUserSendMessageResult = { _, _ -> Result.success(true) }, + canRedactOwnResult = { Result.success(true) }, + canRedactOtherResult = { Result.success(true) }, + typingNoticeResult = { Result.success(Unit) }, + ).apply { givenRoomInfo(aRoomInfo(hasRoomCall = true)) } val presenter = createMessagesPresenter(matrixRoom = room) @@ -183,7 +196,14 @@ class MessagesPresenterTest { val timeline = FakeTimeline().apply { this.toggleReactionLambda = toggleReactionSuccess } - val room = FakeMatrixRoom(liveTimeline = timeline) + val room = FakeMatrixRoom( + liveTimeline = timeline, + canUserSendMessageResult = { _, _ -> Result.success(true) }, + canRedactOwnResult = { Result.success(true) }, + canRedactOtherResult = { Result.success(true) }, + canUserJoinCallResult = { Result.success(true) }, + typingNoticeResult = { Result.success(Unit) }, + ) val presenter = createMessagesPresenter(matrixRoom = room, coroutineDispatchers = coroutineDispatchers) moleculeFlow(RecompositionMode.Immediate) { presenter.present() @@ -213,7 +233,14 @@ class MessagesPresenterTest { val timeline = FakeTimeline().apply { this.toggleReactionLambda = toggleReactionSuccess } - val room = FakeMatrixRoom(liveTimeline = timeline) + val room = FakeMatrixRoom( + liveTimeline = timeline, + canUserSendMessageResult = { _, _ -> Result.success(true) }, + canRedactOwnResult = { Result.success(true) }, + canRedactOtherResult = { Result.success(true) }, + canUserJoinCallResult = { Result.success(true) }, + typingNoticeResult = { Result.success(Unit) }, + ) val presenter = createMessagesPresenter(matrixRoom = room, coroutineDispatchers = coroutineDispatchers) moleculeFlow(RecompositionMode.Immediate) { presenter.present() @@ -266,6 +293,11 @@ class MessagesPresenterTest { val event = aMessageEvent() val matrixRoom = FakeMatrixRoom( eventPermalinkResult = { Result.success("a link") }, + canUserSendMessageResult = { _, _ -> Result.success(true) }, + canRedactOwnResult = { Result.success(true) }, + canRedactOtherResult = { Result.success(true) }, + canUserJoinCallResult = { Result.success(true) }, + typingNoticeResult = { Result.success(Unit) }, ) val presenter = createMessagesPresenter( clipboardHelper = clipboardHelper, @@ -448,7 +480,14 @@ class MessagesPresenterTest { val coroutineDispatchers = testCoroutineDispatchers(useUnconfinedTestDispatcher = true) val liveTimeline = FakeTimeline() - val matrixRoom = FakeMatrixRoom(liveTimeline = liveTimeline) + val matrixRoom = FakeMatrixRoom( + liveTimeline = liveTimeline, + canUserSendMessageResult = { _, _ -> Result.success(true) }, + canRedactOwnResult = { Result.success(true) }, + canRedactOtherResult = { Result.success(true) }, + canUserJoinCallResult = { Result.success(true) }, + typingNoticeResult = { Result.success(Unit) }, + ) val redactEventLambda = lambdaRecorder { _: EventId?, _: TransactionId?, _: String? -> Result.success(true) } liveTimeline.redactEventLambda = redactEventLambda @@ -513,7 +552,16 @@ class MessagesPresenterTest { @Test fun `present - shows prompt to reinvite users in DM`() = runTest { - val room = FakeMatrixRoom(sessionId = A_SESSION_ID, isDirect = true, activeMemberCount = 1L) + val room = FakeMatrixRoom( + sessionId = A_SESSION_ID, + isDirect = true, + activeMemberCount = 1L, + canUserSendMessageResult = { _, _ -> Result.success(true) }, + canRedactOwnResult = { Result.success(true) }, + canRedactOtherResult = { Result.success(true) }, + canUserJoinCallResult = { Result.success(true) }, + typingNoticeResult = { Result.success(Unit) }, + ) val presenter = createMessagesPresenter(matrixRoom = room) moleculeFlow(RecompositionMode.Immediate) { presenter.present() @@ -539,7 +587,16 @@ class MessagesPresenterTest { @Test fun `present - doesn't show reinvite prompt in non-direct room`() = runTest { - val room = FakeMatrixRoom(sessionId = A_SESSION_ID, isDirect = false, activeMemberCount = 1L) + val room = FakeMatrixRoom( + sessionId = A_SESSION_ID, + isDirect = false, + activeMemberCount = 1L, + canUserSendMessageResult = { _, _ -> Result.success(true) }, + canRedactOwnResult = { Result.success(true) }, + canRedactOtherResult = { Result.success(true) }, + canUserJoinCallResult = { Result.success(true) }, + typingNoticeResult = { Result.success(Unit) }, + ) val presenter = createMessagesPresenter(matrixRoom = room) moleculeFlow(RecompositionMode.Immediate) { presenter.present() @@ -554,7 +611,16 @@ class MessagesPresenterTest { @Test fun `present - doesn't show reinvite prompt if other party is present`() = runTest { - val room = FakeMatrixRoom(sessionId = A_SESSION_ID, isDirect = true, activeMemberCount = 2L) + val room = FakeMatrixRoom( + sessionId = A_SESSION_ID, + isDirect = true, + activeMemberCount = 2L, + canUserSendMessageResult = { _, _ -> Result.success(true) }, + canRedactOwnResult = { Result.success(true) }, + canRedactOtherResult = { Result.success(true) }, + canUserJoinCallResult = { Result.success(true) }, + typingNoticeResult = { Result.success(Unit) }, + ) val presenter = createMessagesPresenter(matrixRoom = room) moleculeFlow(RecompositionMode.Immediate) { presenter.present() @@ -569,7 +635,16 @@ class MessagesPresenterTest { @Test fun `present - handle reinviting other user when memberlist is ready`() = runTest { - val room = FakeMatrixRoom(sessionId = A_SESSION_ID) + val inviteUserResult = lambdaRecorder { _: UserId -> Result.success(Unit) } + val room = FakeMatrixRoom( + sessionId = A_SESSION_ID, + inviteUserResult = inviteUserResult, + canUserSendMessageResult = { _, _ -> Result.success(true) }, + canRedactOwnResult = { Result.success(true) }, + canRedactOtherResult = { Result.success(true) }, + canUserJoinCallResult = { Result.success(true) }, + typingNoticeResult = { Result.success(Unit) }, + ) room.givenRoomMembersState( MatrixRoomMembersState.Ready( persistentListOf( @@ -589,13 +664,22 @@ class MessagesPresenterTest { assertThat(loadingState.inviteProgress.isLoading()).isTrue() val newState = awaitItem() assertThat(newState.inviteProgress.isSuccess()).isTrue() - assertThat(room.invitedUserId).isEqualTo(A_SESSION_ID_2) + inviteUserResult.assertions().isCalledOnce().with(value(A_SESSION_ID_2)) } } @Test fun `present - handle reinviting other user when memberlist is error`() = runTest { - val room = FakeMatrixRoom(sessionId = A_SESSION_ID) + val inviteUserResult = lambdaRecorder { _: UserId -> Result.success(Unit) } + val room = FakeMatrixRoom( + sessionId = A_SESSION_ID, + inviteUserResult = inviteUserResult, + canUserSendMessageResult = { _, _ -> Result.success(true) }, + canRedactOwnResult = { Result.success(true) }, + canRedactOtherResult = { Result.success(true) }, + canUserJoinCallResult = { Result.success(true) }, + typingNoticeResult = { Result.success(Unit) }, + ) room.givenRoomMembersState( MatrixRoomMembersState.Error( failure = Throwable(), @@ -618,13 +702,20 @@ class MessagesPresenterTest { assertThat(loadingState.inviteProgress.isLoading()).isTrue() val newState = awaitItem() assertThat(newState.inviteProgress.isSuccess()).isTrue() - assertThat(room.invitedUserId).isEqualTo(A_SESSION_ID_2) + inviteUserResult.assertions().isCalledOnce().with(value(A_SESSION_ID_2)) } } @Test fun `present - handle reinviting other user when memberlist is not ready`() = runTest { - val room = FakeMatrixRoom(sessionId = A_SESSION_ID) + val room = FakeMatrixRoom( + sessionId = A_SESSION_ID, + canUserSendMessageResult = { _, _ -> Result.success(true) }, + canRedactOwnResult = { Result.success(true) }, + canRedactOtherResult = { Result.success(true) }, + canUserJoinCallResult = { Result.success(true) }, + typingNoticeResult = { Result.success(Unit) }, + ) room.givenRoomMembersState(MatrixRoomMembersState.Unknown) val presenter = createMessagesPresenter(matrixRoom = room) moleculeFlow(RecompositionMode.Immediate) { @@ -642,7 +733,15 @@ class MessagesPresenterTest { @Test fun `present - handle reinviting other user when inviting fails`() = runTest { - val room = FakeMatrixRoom(sessionId = A_SESSION_ID) + val room = FakeMatrixRoom( + sessionId = A_SESSION_ID, + inviteUserResult = { Result.failure(Throwable("Oops!")) }, + canUserSendMessageResult = { _, _ -> Result.success(true) }, + canRedactOwnResult = { Result.success(true) }, + canRedactOtherResult = { Result.success(true) }, + canUserJoinCallResult = { Result.success(true) }, + typingNoticeResult = { Result.success(Unit) }, + ) room.givenRoomMembersState( MatrixRoomMembersState.Ready( persistentListOf( @@ -651,7 +750,6 @@ class MessagesPresenterTest { ) ) ) - room.givenInviteUserResult(Result.failure(Throwable("Oops!"))) val presenter = createMessagesPresenter(matrixRoom = room) moleculeFlow(RecompositionMode.Immediate) { presenter.present() @@ -671,8 +769,19 @@ class MessagesPresenterTest { @Test fun `present - permission to post`() = runTest { - val matrixRoom = FakeMatrixRoom() - matrixRoom.givenCanSendEventResult(MessageEventType.ROOM_MESSAGE, Result.success(true)) + val matrixRoom = FakeMatrixRoom( + canUserSendMessageResult = { _, messageEventType -> + when (messageEventType) { + MessageEventType.ROOM_MESSAGE -> Result.success(true) + MessageEventType.REACTION -> Result.success(true) + else -> lambdaError() + } + }, + canRedactOwnResult = { Result.success(true) }, + canRedactOtherResult = { Result.success(true) }, + canUserJoinCallResult = { Result.success(true) }, + typingNoticeResult = { Result.success(Unit) }, + ) val presenter = createMessagesPresenter(matrixRoom = matrixRoom) moleculeFlow(RecompositionMode.Immediate) { presenter.present() @@ -684,8 +793,19 @@ class MessagesPresenterTest { @Test fun `present - no permission to post`() = runTest { - val matrixRoom = FakeMatrixRoom() - matrixRoom.givenCanSendEventResult(MessageEventType.ROOM_MESSAGE, Result.success(false)) + val matrixRoom = FakeMatrixRoom( + canUserSendMessageResult = { _, messageEventType -> + when (messageEventType) { + MessageEventType.ROOM_MESSAGE -> Result.success(false) + MessageEventType.REACTION -> Result.success(false) + else -> lambdaError() + } + }, + canRedactOwnResult = { Result.success(true) }, + canRedactOtherResult = { Result.success(true) }, + canUserJoinCallResult = { Result.success(true) }, + typingNoticeResult = { Result.success(Unit) }, + ) val presenter = createMessagesPresenter(matrixRoom = matrixRoom) moleculeFlow(RecompositionMode.Immediate) { presenter.present() @@ -700,7 +820,13 @@ class MessagesPresenterTest { @Test fun `present - permission to redact own`() = runTest { - val matrixRoom = FakeMatrixRoom(canRedactOwn = true) + val matrixRoom = FakeMatrixRoom( + canRedactOwnResult = { Result.success(true) }, + canUserSendMessageResult = { _, _ -> Result.success(true) }, + canRedactOtherResult = { Result.success(false) }, + canUserJoinCallResult = { Result.success(true) }, + typingNoticeResult = { Result.success(Unit) }, + ) val presenter = createMessagesPresenter(matrixRoom = matrixRoom) moleculeFlow(RecompositionMode.Immediate) { presenter.present() @@ -714,7 +840,13 @@ class MessagesPresenterTest { @Test fun `present - permission to redact other`() = runTest { - val matrixRoom = FakeMatrixRoom(canRedactOther = true) + val matrixRoom = FakeMatrixRoom( + canRedactOtherResult = { Result.success(true) }, + canUserSendMessageResult = { _, _ -> Result.success(true) }, + canRedactOwnResult = { Result.success(false) }, + canUserJoinCallResult = { Result.success(true) }, + typingNoticeResult = { Result.success(Unit) }, + ) val presenter = createMessagesPresenter(matrixRoom = matrixRoom) moleculeFlow(RecompositionMode.Immediate) { presenter.present() @@ -754,7 +886,13 @@ class MessagesPresenterTest { private fun TestScope.createMessagesPresenter( coroutineDispatchers: CoroutineDispatchers = testCoroutineDispatchers(), - matrixRoom: MatrixRoom = FakeMatrixRoom().apply { + matrixRoom: MatrixRoom = FakeMatrixRoom( + canUserSendMessageResult = { _, _ -> Result.success(true) }, + canRedactOwnResult = { Result.success(true) }, + canRedactOtherResult = { Result.success(true) }, + canUserJoinCallResult = { Result.success(true) }, + typingNoticeResult = { Result.success(Unit) }, + ).apply { givenRoomInfo(aRoomInfo(id = roomId, name = "")) }, navigator: FakeMessagesNavigator = FakeMessagesNavigator(), diff --git a/features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/attachments/AttachmentsPreviewPresenterTest.kt b/features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/attachments/AttachmentsPreviewPresenterTest.kt index 0168fcbde5..e2fbeebe3a 100644 --- a/features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/attachments/AttachmentsPreviewPresenterTest.kt +++ b/features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/attachments/AttachmentsPreviewPresenterTest.kt @@ -26,7 +26,9 @@ import com.google.common.truth.Truth.assertThat import io.element.android.features.messages.impl.attachments.preview.AttachmentsPreviewEvents import io.element.android.features.messages.impl.attachments.preview.AttachmentsPreviewPresenter import io.element.android.features.messages.impl.attachments.preview.SendActionState +import io.element.android.libraries.matrix.api.core.ProgressCallback import io.element.android.libraries.matrix.api.room.MatrixRoom +import io.element.android.libraries.matrix.test.media.FakeMediaUploadHandler import io.element.android.libraries.matrix.test.room.FakeMatrixRoom import io.element.android.libraries.mediaupload.api.MediaPreProcessor import io.element.android.libraries.mediaupload.api.MediaSender @@ -34,6 +36,7 @@ import io.element.android.libraries.mediaupload.test.FakeMediaPreProcessor import io.element.android.libraries.mediaviewer.api.local.LocalMedia import io.element.android.libraries.mediaviewer.test.viewer.aLocalMedia import io.element.android.tests.testutils.WarmUpRule +import io.element.android.tests.testutils.lambda.lambdaRecorder import io.mockk.mockk import kotlinx.coroutines.ExperimentalCoroutinesApi import kotlinx.coroutines.test.runTest @@ -49,13 +52,16 @@ class AttachmentsPreviewPresenterTest { @Test fun `present - send media success scenario`() = runTest { - val room = FakeMatrixRoom() - room.givenProgressCallbackValues( - listOf( + val sendMediaResult = lambdaRecorder> { + Result.success(FakeMediaUploadHandler()) + } + val room = FakeMatrixRoom( + progressCallbackValues = listOf( Pair(0, 10), Pair(5, 10), Pair(10, 10) - ) + ), + sendMediaResult = sendMediaResult, ) val presenter = createAttachmentsPreviewPresenter(room = room) moleculeFlow(RecompositionMode.Immediate) { @@ -70,15 +76,19 @@ class AttachmentsPreviewPresenterTest { assertThat(awaitItem().sendActionState).isEqualTo(SendActionState.Sending.Uploading(1f)) val successState = awaitItem() assertThat(successState.sendActionState).isEqualTo(SendActionState.Done) - assertThat(room.sendMediaCount).isEqualTo(1) + sendMediaResult.assertions().isCalledOnce() } } @Test fun `present - send media failure scenario`() = runTest { - val room = FakeMatrixRoom() val failure = MediaPreProcessor.Failure(null) - room.givenSendMediaResult(Result.failure(failure)) + val sendMediaResult = lambdaRecorder> { + Result.failure(failure) + } + val room = FakeMatrixRoom( + sendMediaResult = sendMediaResult, + ) val presenter = createAttachmentsPreviewPresenter(room = room) moleculeFlow(RecompositionMode.Immediate) { presenter.present() @@ -90,7 +100,7 @@ class AttachmentsPreviewPresenterTest { assertThat(loadingState.sendActionState).isEqualTo(SendActionState.Sending.Processing) val failureState = awaitItem() assertThat(failureState.sendActionState).isEqualTo(SendActionState.Failure(failure)) - assertThat(room.sendMediaCount).isEqualTo(0) + sendMediaResult.assertions().isCalledOnce() failureState.eventSink(AttachmentsPreviewEvents.ClearSendState) val clearedState = awaitItem() assertThat(clearedState.sendActionState).isEqualTo(SendActionState.Idle) diff --git a/features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/report/ReportMessagePresenterTest.kt b/features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/report/ReportMessagePresenterTest.kt index b5408434de..a15ea45a6c 100644 --- a/features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/report/ReportMessagePresenterTest.kt +++ b/features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/report/ReportMessagePresenterTest.kt @@ -22,11 +22,14 @@ import app.cash.turbine.test import com.google.common.truth.Truth.assertThat import io.element.android.libraries.architecture.AsyncAction import io.element.android.libraries.designsystem.utils.snackbar.SnackbarDispatcher +import io.element.android.libraries.matrix.api.core.EventId +import io.element.android.libraries.matrix.api.core.UserId import io.element.android.libraries.matrix.api.room.MatrixRoom import io.element.android.libraries.matrix.test.AN_EVENT_ID import io.element.android.libraries.matrix.test.A_USER_ID import io.element.android.libraries.matrix.test.room.FakeMatrixRoom import io.element.android.tests.testutils.WarmUpRule +import io.element.android.tests.testutils.lambda.lambdaRecorder import kotlinx.coroutines.test.runTest import org.junit.Rule import org.junit.Test @@ -81,7 +84,12 @@ class ReportMessagePresenterTest { @Test fun `presenter - handle successful report and block user`() = runTest { - val room = FakeMatrixRoom() + val reportContentResult = lambdaRecorder> { _, _, _ -> + Result.success(Unit) + } + val room = FakeMatrixRoom( + reportContentResult = reportContentResult + ) val presenter = createReportMessagePresenter(matrixRoom = room) moleculeFlow(RecompositionMode.Immediate) { presenter.present() @@ -92,13 +100,18 @@ class ReportMessagePresenterTest { initialState.eventSink(ReportMessageEvents.Report) assertThat(awaitItem().result).isInstanceOf(AsyncAction.Loading::class.java) assertThat(awaitItem().result).isInstanceOf(AsyncAction.Success::class.java) - assertThat(room.reportedContentCount).isEqualTo(1) + reportContentResult.assertions().isCalledOnce() } } @Test fun `presenter - handle successful report`() = runTest { - val room = FakeMatrixRoom() + val reportContentResult = lambdaRecorder> { _, _, _ -> + Result.success(Unit) + } + val room = FakeMatrixRoom( + reportContentResult = reportContentResult + ) val presenter = createReportMessagePresenter(matrixRoom = room) moleculeFlow(RecompositionMode.Immediate) { presenter.present() @@ -107,15 +120,18 @@ class ReportMessagePresenterTest { initialState.eventSink(ReportMessageEvents.Report) assertThat(awaitItem().result).isInstanceOf(AsyncAction.Loading::class.java) assertThat(awaitItem().result).isInstanceOf(AsyncAction.Success::class.java) - assertThat(room.reportedContentCount).isEqualTo(1) + reportContentResult.assertions().isCalledOnce() } } @Test fun `presenter - handle failed report`() = runTest { - val room = FakeMatrixRoom().apply { - givenReportContentResult(Result.failure(Exception("Failed to report content"))) + val reportContentResult = lambdaRecorder> { _, _, _ -> + Result.failure(Exception("Failed to report content")) } + val room = FakeMatrixRoom( + reportContentResult = reportContentResult + ) val presenter = createReportMessagePresenter(matrixRoom = room) moleculeFlow(RecompositionMode.Immediate) { presenter.present() @@ -125,7 +141,7 @@ class ReportMessagePresenterTest { assertThat(awaitItem().result).isInstanceOf(AsyncAction.Loading::class.java) val resultState = awaitItem() assertThat(resultState.result).isInstanceOf(AsyncAction.Failure::class.java) - assertThat(room.reportedContentCount).isEqualTo(1) + reportContentResult.assertions().isCalledOnce() resultState.eventSink(ReportMessageEvents.ClearError) assertThat(awaitItem().result).isInstanceOf(AsyncAction.Uninitialized::class.java) diff --git a/features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/textcomposer/MessageComposerPresenterTest.kt b/features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/textcomposer/MessageComposerPresenterTest.kt index de48ee62b6..b944ea3d95 100644 --- a/features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/textcomposer/MessageComposerPresenterTest.kt +++ b/features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/textcomposer/MessageComposerPresenterTest.kt @@ -43,6 +43,7 @@ import io.element.android.libraries.featureflag.api.FeatureFlagService import io.element.android.libraries.featureflag.api.FeatureFlags import io.element.android.libraries.featureflag.test.FakeFeatureFlagService import io.element.android.libraries.matrix.api.core.EventId +import io.element.android.libraries.matrix.api.core.ProgressCallback import io.element.android.libraries.matrix.api.core.RoomId import io.element.android.libraries.matrix.api.core.TransactionId import io.element.android.libraries.matrix.api.media.ImageInfo @@ -67,6 +68,7 @@ import io.element.android.libraries.matrix.test.A_USER_ID_2 import io.element.android.libraries.matrix.test.A_USER_ID_3 import io.element.android.libraries.matrix.test.A_USER_ID_4 import io.element.android.libraries.matrix.test.core.aBuildMeta +import io.element.android.libraries.matrix.test.media.FakeMediaUploadHandler import io.element.android.libraries.matrix.test.permalink.FakePermalinkBuilder import io.element.android.libraries.matrix.test.permalink.FakePermalinkParser import io.element.android.libraries.matrix.test.room.FakeMatrixRoom @@ -297,7 +299,13 @@ class MessageComposerPresenterTest { @Test fun `present - send message with rich text enabled`() = runTest { - val presenter = createPresenter(this) + val presenter = createPresenter( + coroutineScope = this, + room = FakeMatrixRoom( + sendMessageResult = { _, _, _ -> Result.success(Unit) }, + typingNoticeResult = { Result.success(Unit) } + ), + ) moleculeFlow(RecompositionMode.Immediate) { val state = presenter.present() remember(state, state.textEditorState.messageHtml()) { state } @@ -324,7 +332,14 @@ class MessageComposerPresenterTest { @Test fun `present - send message with plain text enabled`() = runTest { val permalinkBuilder = FakePermalinkBuilder(permalinkForUserLambda = { Result.success("") }) - val presenter = createPresenter(this, isRichTextEditorEnabled = false) + val presenter = createPresenter( + coroutineScope = this, + isRichTextEditorEnabled = false, + room = FakeMatrixRoom( + sendMessageResult = { _, _, _ -> Result.success(Unit) }, + typingNoticeResult = { Result.success(Unit) } + ), + ) moleculeFlow(RecompositionMode.Immediate) { val state = presenter.present() val messageMarkdown = state.textEditorState.messageMarkdown(permalinkBuilder) @@ -358,7 +373,10 @@ class MessageComposerPresenterTest { val timeline = FakeTimeline().apply { this.editMessageLambda = editMessageLambda } - val fakeMatrixRoom = FakeMatrixRoom(liveTimeline = timeline) + val fakeMatrixRoom = FakeMatrixRoom( + liveTimeline = timeline, + typingNoticeResult = { Result.success(Unit) } + ) val presenter = createPresenter( this, fakeMatrixRoom, @@ -407,7 +425,10 @@ class MessageComposerPresenterTest { val timeline = FakeTimeline().apply { this.editMessageLambda = editMessageLambda } - val fakeMatrixRoom = FakeMatrixRoom(liveTimeline = timeline) + val fakeMatrixRoom = FakeMatrixRoom( + liveTimeline = timeline, + typingNoticeResult = { Result.success(Unit) }, + ) val presenter = createPresenter( this, fakeMatrixRoom, @@ -456,7 +477,10 @@ class MessageComposerPresenterTest { val timeline = FakeTimeline().apply { this.replyMessageLambda = replyMessageLambda } - val fakeMatrixRoom = FakeMatrixRoom(liveTimeline = timeline) + val fakeMatrixRoom = FakeMatrixRoom( + liveTimeline = timeline, + typingNoticeResult = { Result.success(Unit) } + ) val presenter = createPresenter( this, fakeMatrixRoom, @@ -524,7 +548,9 @@ class MessageComposerPresenterTest { @Test fun `present - Pick image from gallery`() = runTest { - val room = FakeMatrixRoom() + val room = FakeMatrixRoom( + typingNoticeResult = { Result.success(Unit) } + ) val presenter = createPresenter(this, room = room) pickerProvider.givenMimeType(MimeTypes.Images) mediaPreProcessor.givenResult( @@ -557,7 +583,9 @@ class MessageComposerPresenterTest { @Test fun `present - Pick video from gallery`() = runTest { - val room = FakeMatrixRoom() + val room = FakeMatrixRoom( + typingNoticeResult = { Result.success(Unit) } + ) val presenter = createPresenter(this, room = room) pickerProvider.givenMimeType(MimeTypes.Videos) mediaPreProcessor.givenResult( @@ -607,13 +635,17 @@ class MessageComposerPresenterTest { @Test fun `present - Pick file from storage`() = runTest { - val room = FakeMatrixRoom() - room.givenProgressCallbackValues( - listOf( + val sendMediaResult = lambdaRecorder { _: ProgressCallback? -> + Result.success(FakeMediaUploadHandler()) + } + val room = FakeMatrixRoom( + progressCallbackValues = listOf( Pair(0, 10), Pair(5, 10), Pair(10, 10) - ) + ), + sendMediaResult = sendMediaResult, + typingNoticeResult = { Result.success(Unit) } ) val presenter = createPresenter(this, room = room) moleculeFlow(RecompositionMode.Immediate) { @@ -629,13 +661,15 @@ class MessageComposerPresenterTest { assertThat(awaitItem().attachmentsState).isEqualTo(AttachmentsState.Sending.Uploading(1f)) val sentState = awaitItem() assertThat(sentState.attachmentsState).isEqualTo(AttachmentsState.None) - assertThat(room.sendMediaCount).isEqualTo(1) + sendMediaResult.assertions().isCalledOnce() } } @Test fun `present - create poll`() = runTest { - val room = FakeMatrixRoom() + val room = FakeMatrixRoom( + typingNoticeResult = { Result.success(Unit) } + ) val presenter = createPresenter(this, room = room) moleculeFlow(RecompositionMode.Immediate) { presenter.present() @@ -652,7 +686,9 @@ class MessageComposerPresenterTest { @Test fun `present - share location`() = runTest { - val room = FakeMatrixRoom() + val room = FakeMatrixRoom( + typingNoticeResult = { Result.success(Unit) } + ) val presenter = createPresenter(this, room = room) moleculeFlow(RecompositionMode.Immediate) { presenter.present() @@ -669,7 +705,9 @@ class MessageComposerPresenterTest { @Test fun `present - Take photo`() = runTest { - val room = FakeMatrixRoom() + val room = FakeMatrixRoom( + typingNoticeResult = { Result.success(Unit) } + ) val permissionPresenter = FakePermissionsPresenter().apply { setPermissionGranted() } val presenter = createPresenter( this, @@ -689,7 +727,9 @@ class MessageComposerPresenterTest { @Test fun `present - Take photo with permission request`() = runTest { - val room = FakeMatrixRoom() + val room = FakeMatrixRoom( + typingNoticeResult = { Result.success(Unit) } + ) val permissionPresenter = FakePermissionsPresenter() val presenter = createPresenter( this, @@ -714,7 +754,9 @@ class MessageComposerPresenterTest { @Test fun `present - Record video`() = runTest { - val room = FakeMatrixRoom() + val room = FakeMatrixRoom( + typingNoticeResult = { Result.success(Unit) } + ) val permissionPresenter = FakePermissionsPresenter().apply { setPermissionGranted() } val presenter = createPresenter( this, @@ -734,7 +776,9 @@ class MessageComposerPresenterTest { @Test fun `present - Record video with permission request`() = runTest { - val room = FakeMatrixRoom() + val room = FakeMatrixRoom( + typingNoticeResult = { Result.success(Unit) } + ) val permissionPresenter = FakePermissionsPresenter() val presenter = createPresenter( this, @@ -759,9 +803,10 @@ class MessageComposerPresenterTest { @Test fun `present - Uploading media failure can be recovered from`() = runTest { - val room = FakeMatrixRoom().apply { - givenSendMediaResult(Result.failure(Exception())) - } + val room = FakeMatrixRoom( + sendMediaResult = { Result.failure(Exception()) }, + typingNoticeResult = { Result.success(Unit) } + ) val presenter = createPresenter(this, room = room) moleculeFlow(RecompositionMode.Immediate) { presenter.present() @@ -842,15 +887,17 @@ class MessageComposerPresenterTest { val invitedUser = aRoomMember(userId = A_USER_ID_3, membership = RoomMembershipState.INVITE) val bob = aRoomMember(userId = A_USER_ID_2, membership = RoomMembershipState.JOIN) val david = aRoomMember(userId = A_USER_ID_4, displayName = "Dave", membership = RoomMembershipState.JOIN) + var canUserTriggerRoomNotificationResult = true val room = FakeMatrixRoom( isDirect = false, + canUserTriggerRoomNotificationResult = { Result.success(canUserTriggerRoomNotificationResult) }, + typingNoticeResult = { Result.success(Unit) } ).apply { givenRoomMembersState( MatrixRoomMembersState.Ready( persistentListOf(currentUser, invitedUser, bob, david), ) ) - givenCanTriggerRoomNotification(Result.success(true)) } val flagsService = FakeFeatureFlagService( mapOf( @@ -890,13 +937,10 @@ class MessageComposerPresenterTest { assertThat(awaitItem().memberSuggestions).isEmpty() // If user has no permission to send `@room` mentions, `RoomMemberSuggestion.Room` is not returned - room.givenCanTriggerRoomNotification(Result.success(false)) + canUserTriggerRoomNotificationResult = false initialState.eventSink(MessageComposerEvents.SuggestionReceived(Suggestion(0, 0, SuggestionType.Mention, ""))) assertThat(awaitItem().memberSuggestions) .containsExactly(ResolvedMentionSuggestion.Member(bob), ResolvedMentionSuggestion.Member(david)) - - // If room is a DM, `RoomMemberSuggestion.Room` is not returned - room.givenCanTriggerRoomNotification(Result.success(true)) } } @@ -910,13 +954,14 @@ class MessageComposerPresenterTest { isDirect = true, activeMemberCount = 2, isEncrypted = true, + canUserTriggerRoomNotificationResult = { Result.success(true) }, + typingNoticeResult = { Result.success(Unit) } ).apply { givenRoomMembersState( MatrixRoomMembersState.Ready( persistentListOf(currentUser, invitedUser, bob, david), ) ) - givenCanTriggerRoomNotification(Result.success(true)) } val flagsService = FakeFeatureFlagService( mapOf( @@ -973,7 +1018,14 @@ class MessageComposerPresenterTest { this.replyMessageLambda = replyMessageLambda this.editMessageLambda = editMessageLambda } - val room = FakeMatrixRoom(liveTimeline = timeline) + val sendMessageResult = lambdaRecorder { _: String, _: String?, _: List -> + Result.success(Unit) + } + val room = FakeMatrixRoom( + liveTimeline = timeline, + sendMessageResult = sendMessageResult, + typingNoticeResult = { Result.success(Unit) } + ) val presenter = createPresenter(room = room, coroutineScope = this) moleculeFlow(RecompositionMode.Immediate) { presenter.present() @@ -993,7 +1045,8 @@ class MessageComposerPresenterTest { advanceUntilIdle() - assertThat(room.sendMessageMentions).isEqualTo(listOf(Mention.User(A_USER_ID))) + sendMessageResult.assertions().isCalledOnce() + .with(value(A_MESSAGE), any(), value(listOf(Mention.User(A_USER_ID)))) // Check intentional mentions on reply sent initialState.eventSink(MessageComposerEvents.SetMode(aReplyMode())) @@ -1049,22 +1102,32 @@ class MessageComposerPresenterTest { @Test fun `present - handle typing notice event`() = runTest { - val room = FakeMatrixRoom() + val typingNoticeResult = lambdaRecorder> { Result.success(Unit) } + val room = FakeMatrixRoom( + typingNoticeResult = typingNoticeResult + ) val presenter = createPresenter(room = room, coroutineScope = this) moleculeFlow(RecompositionMode.Immediate) { presenter.present() }.test { val initialState = awaitFirstItem() - assertThat(room.typingRecord).isEmpty() + typingNoticeResult.assertions().isNeverCalled() initialState.eventSink.invoke(MessageComposerEvents.TypingNotice(true)) initialState.eventSink.invoke(MessageComposerEvents.TypingNotice(false)) - assertThat(room.typingRecord).isEqualTo(listOf(true, false)) + typingNoticeResult.assertions().isCalledExactly(2) + .withSequence( + listOf(value(true)), + listOf(value(false)), + ) } } @Test fun `present - handle typing notice event when sending typing notice is disabled`() = runTest { - val room = FakeMatrixRoom() + val typingNoticeResult = lambdaRecorder> { Result.success(Unit) } + val room = FakeMatrixRoom( + typingNoticeResult = typingNoticeResult + ) val store = InMemorySessionPreferencesStore( isSendTypingNotificationsEnabled = false ) @@ -1073,10 +1136,10 @@ class MessageComposerPresenterTest { presenter.present() }.test { val initialState = awaitFirstItem() - assertThat(room.typingRecord).isEmpty() + typingNoticeResult.assertions().isNeverCalled() initialState.eventSink.invoke(MessageComposerEvents.TypingNotice(true)) initialState.eventSink.invoke(MessageComposerEvents.TypingNotice(false)) - assertThat(room.typingRecord).isEmpty() + typingNoticeResult.assertions().isNeverCalled() } } @@ -1215,7 +1278,10 @@ class MessageComposerPresenterTest { val timeline = FakeTimeline().apply { this.loadReplyDetailsLambda = loadReplyDetailsLambda } - val room = FakeMatrixRoom(liveTimeline = timeline) + val room = FakeMatrixRoom( + liveTimeline = timeline, + typingNoticeResult = { Result.success(Unit) }, + ) val permalinkBuilder = FakePermalinkBuilder() val presenter = createPresenter( room = room, @@ -1352,7 +1418,9 @@ class MessageComposerPresenterTest { private fun createPresenter( coroutineScope: CoroutineScope, - room: MatrixRoom = FakeMatrixRoom(), + room: MatrixRoom = FakeMatrixRoom( + typingNoticeResult = { Result.success(Unit) } + ), pickerProvider: PickerProvider = this.pickerProvider, featureFlagService: FeatureFlagService = this.featureFlagService, sessionPreferencesStore: SessionPreferencesStore = InMemorySessionPreferencesStore(), diff --git a/features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/timeline/TimelineControllerTest.kt b/features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/timeline/TimelineControllerTest.kt index 58cf11c4a7..887ce88d95 100644 --- a/features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/timeline/TimelineControllerTest.kt +++ b/features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/timeline/TimelineControllerTest.kt @@ -26,6 +26,7 @@ import io.element.android.libraries.matrix.test.A_UNIQUE_ID import io.element.android.libraries.matrix.test.room.FakeMatrixRoom import io.element.android.libraries.matrix.test.timeline.FakeTimeline import io.element.android.libraries.matrix.test.timeline.anEventTimelineItem +import io.element.android.tests.testutils.lambda.lambdaError import io.element.android.tests.testutils.lambda.lambdaRecorder import kotlinx.coroutines.flow.first import kotlinx.coroutines.flow.flowOf @@ -38,9 +39,9 @@ class TimelineControllerTest { val liveTimeline = FakeTimeline(name = "live") val detachedTimeline = FakeTimeline(name = "detached") val matrixRoom = FakeMatrixRoom( - liveTimeline = liveTimeline + liveTimeline = liveTimeline, + timelineFocusedOnEventResult = { Result.success(detachedTimeline) } ) - matrixRoom.givenTimelineFocusedOnEventResult(Result.success(detachedTimeline)) val sut = TimelineController(matrixRoom) sut.activeTimelineFlow().test { @@ -68,8 +69,17 @@ class TimelineControllerTest { val liveTimeline = FakeTimeline(name = "live") val detachedTimeline1 = FakeTimeline(name = "detached 1") val detachedTimeline2 = FakeTimeline(name = "detached 2") + var callNumber = 0 val matrixRoom = FakeMatrixRoom( - liveTimeline = liveTimeline + liveTimeline = liveTimeline, + timelineFocusedOnEventResult = { + callNumber++ + when (callNumber) { + 1 -> Result.success(detachedTimeline1) + 2 -> Result.success(detachedTimeline2) + else -> lambdaError() + } + } ) val sut = TimelineController(matrixRoom) @@ -77,7 +87,6 @@ class TimelineControllerTest { awaitItem().also { state -> assertThat(state).isEqualTo(liveTimeline) } - matrixRoom.givenTimelineFocusedOnEventResult(Result.success(detachedTimeline1)) sut.focusOnEvent(AN_EVENT_ID) awaitItem().also { state -> assertThat(state).isEqualTo(detachedTimeline1) @@ -85,7 +94,6 @@ class TimelineControllerTest { assertThat(detachedTimeline1.closeCounter).isEqualTo(0) assertThat(detachedTimeline2.closeCounter).isEqualTo(0) // Focus on another event should close the previous detached timeline - matrixRoom.givenTimelineFocusedOnEventResult(Result.success(detachedTimeline2)) sut.focusOnEvent(AN_EVENT_ID) awaitItem().also { state -> assertThat(state).isEqualTo(detachedTimeline2) @@ -117,11 +125,10 @@ class TimelineControllerTest { val liveTimeline = FakeTimeline(name = "live") val detachedTimeline = FakeTimeline(name = "detached") val matrixRoom = FakeMatrixRoom( - liveTimeline = liveTimeline + liveTimeline = liveTimeline, + timelineFocusedOnEventResult = { Result.success(detachedTimeline) } ) - matrixRoom.givenTimelineFocusedOnEventResult(Result.success(detachedTimeline)) val sut = TimelineController(matrixRoom) - sut.activeTimelineFlow().test { awaitItem().also { state -> assertThat(state).isEqualTo(liveTimeline) @@ -168,9 +175,9 @@ class TimelineControllerTest { sendMessageLambda = lambdaForDetached } val matrixRoom = FakeMatrixRoom( - liveTimeline = liveTimeline + liveTimeline = liveTimeline, + timelineFocusedOnEventResult = { Result.success(detachedTimeline) } ) - matrixRoom.givenTimelineFocusedOnEventResult(Result.success(detachedTimeline)) val sut = TimelineController(matrixRoom) sut.activeTimelineFlow().test { sut.focusOnEvent(AN_EVENT_ID) @@ -193,9 +200,9 @@ class TimelineControllerTest { val liveTimeline = FakeTimeline(name = "live") val detachedTimeline = FakeTimeline(name = "detached") val matrixRoom = FakeMatrixRoom( - liveTimeline = liveTimeline + liveTimeline = liveTimeline, + timelineFocusedOnEventResult = { Result.success(detachedTimeline) } ) - matrixRoom.givenTimelineFocusedOnEventResult(Result.success(detachedTimeline)) val sut = TimelineController(matrixRoom) sut.activeTimelineFlow().test { diff --git a/features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/timeline/TimelinePresenterTest.kt b/features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/timeline/TimelinePresenterTest.kt index ad52af11ca..5a171227e7 100644 --- a/features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/timeline/TimelinePresenterTest.kt +++ b/features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/timeline/TimelinePresenterTest.kt @@ -133,7 +133,10 @@ private const val FAKE_UNIQUE_ID_2 = "FAKE_UNIQUE_ID_2" ) ) ) - val room = FakeMatrixRoom(liveTimeline = timeline) + val room = FakeMatrixRoom( + liveTimeline = timeline, + canUserSendMessageResult = { _, _ -> Result.success(true) }, + ) val sessionPreferencesStore = InMemorySessionPreferencesStore(isSendPublicReadReceiptsEnabled = false) val presenter = createTimelinePresenter( timeline = timeline, @@ -482,9 +485,9 @@ private const val FAKE_UNIQUE_ID_2 = "FAKE_UNIQUE_ID_2" ) val room = FakeMatrixRoom( liveTimeline = liveTimeline, - ).apply { - givenTimelineFocusedOnEventResult(Result.success(detachedTimeline)) - } + timelineFocusedOnEventResult = { Result.success(detachedTimeline) }, + canUserSendMessageResult = { _, _ -> Result.success(true) }, + ) val presenter = createTimelinePresenter( room = room, ) @@ -529,6 +532,7 @@ private const val FAKE_UNIQUE_ID_2 = "FAKE_UNIQUE_ID_2" ) ) ), + canUserSendMessageResult = { _, _ -> Result.success(true) }, ), timelineItemIndexer = timelineItemIndexer, ) @@ -551,9 +555,9 @@ private const val FAKE_UNIQUE_ID_2 = "FAKE_UNIQUE_ID_2" liveTimeline = FakeTimeline( timelineItems = flowOf(emptyList()), ), - ).apply { - givenTimelineFocusedOnEventResult(Result.failure(Throwable("An error"))) - }, + timelineFocusedOnEventResult = { Result.failure(Throwable("An error")) }, + canUserSendMessageResult = { _, _ -> Result.success(true) }, + ) ) moleculeFlow(RecompositionMode.Immediate) { presenter.present() @@ -594,7 +598,10 @@ private const val FAKE_UNIQUE_ID_2 = "FAKE_UNIQUE_ID_2" ) ) ) - val room = FakeMatrixRoom(liveTimeline = timeline).apply { + val room = FakeMatrixRoom( + liveTimeline = timeline, + canUserSendMessageResult = { _, _ -> Result.success(true) }, + ).apply { givenRoomMembersState(MatrixRoomMembersState.Unknown) } @@ -626,7 +633,10 @@ private const val FAKE_UNIQUE_ID_2 = "FAKE_UNIQUE_ID_2" private fun TestScope.createTimelinePresenter( timeline: Timeline = FakeTimeline(), - room: FakeMatrixRoom = FakeMatrixRoom(liveTimeline = timeline), + room: FakeMatrixRoom = FakeMatrixRoom( + liveTimeline = timeline, + canUserSendMessageResult = { _, _ -> Result.success(true) } + ), timelineItemsFactory: TimelineItemsFactory = aTimelineItemsFactory(), redactedVoiceMessageManager: RedactedVoiceMessageManager = FakeRedactedVoiceMessageManager(), messagesNavigator: FakeMessagesNavigator = FakeMessagesNavigator(), diff --git a/features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/voicemessages/composer/VoiceMessageComposerPresenterTest.kt b/features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/voicemessages/composer/VoiceMessageComposerPresenterTest.kt index 1c08a76e3d..0e507bdecf 100644 --- a/features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/voicemessages/composer/VoiceMessageComposerPresenterTest.kt +++ b/features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/voicemessages/composer/VoiceMessageComposerPresenterTest.kt @@ -28,7 +28,9 @@ import com.google.common.truth.Truth.assertThat import im.vector.app.features.analytics.plan.Composer import io.element.android.features.messages.impl.voicemessages.VoiceMessageException import io.element.android.features.messages.test.FakeMessageComposerContext +import io.element.android.libraries.matrix.api.core.ProgressCallback import io.element.android.libraries.matrix.test.AN_EVENT_ID +import io.element.android.libraries.matrix.test.media.FakeMediaUploadHandler import io.element.android.libraries.matrix.test.room.FakeMatrixRoom import io.element.android.libraries.matrix.ui.messages.reply.InReplyToDetails import io.element.android.libraries.mediaplayer.test.FakeMediaPlayer @@ -45,6 +47,7 @@ import io.element.android.libraries.textcomposer.model.VoiceMessageState import io.element.android.libraries.voicerecorder.test.FakeVoiceRecorder import io.element.android.services.analytics.test.FakeAnalyticsService import io.element.android.tests.testutils.WarmUpRule +import io.element.android.tests.testutils.lambda.lambdaRecorder import kotlinx.collections.immutable.toImmutableList import kotlinx.collections.immutable.toPersistentList import kotlinx.coroutines.ExperimentalCoroutinesApi @@ -63,7 +66,10 @@ class VoiceMessageComposerPresenterTest { recordingDuration = RECORDING_DURATION ) private val analyticsService = FakeAnalyticsService() - private val matrixRoom = FakeMatrixRoom() + private val sendMediaResult = lambdaRecorder> { Result.success(FakeMediaUploadHandler()) } + private val matrixRoom = FakeMatrixRoom( + sendMediaResult = sendMediaResult + ) private val mediaPreProcessor = FakeMediaPreProcessor().apply { givenAudioResult() } private val mediaSender = MediaSender(mediaPreProcessor, matrixRoom) private val messageComposerContext = FakeMessageComposerContext() @@ -295,7 +301,7 @@ class VoiceMessageComposerPresenterTest { val finalState = awaitItem() assertThat(finalState.voiceMessageState).isEqualTo(VoiceMessageState.Idle) - assertThat(matrixRoom.sendMediaCount).isEqualTo(1) + sendMediaResult.assertions().isCalledOnce() voiceRecorder.assertCalls(started = 1, stopped = 1, deleted = 1) testPauseAndDestroy(finalState) @@ -346,7 +352,7 @@ class VoiceMessageComposerPresenterTest { val finalState = awaitItem() assertThat(finalState.voiceMessageState).isEqualTo(VoiceMessageState.Idle) - assertThat(matrixRoom.sendMediaCount).isEqualTo(1) + sendMediaResult.assertions().isCalledOnce() voiceRecorder.assertCalls(started = 1, stopped = 1, deleted = 1) testPauseAndDestroy(finalState) @@ -369,7 +375,7 @@ class VoiceMessageComposerPresenterTest { val finalState = awaitItem() assertThat(finalState.voiceMessageState).isEqualTo(VoiceMessageState.Idle) - assertThat(matrixRoom.sendMediaCount).isEqualTo(1) + sendMediaResult.assertions().isCalledOnce() voiceRecorder.assertCalls(started = 1, stopped = 1, deleted = 1) testPauseAndDestroy(finalState) @@ -393,7 +399,7 @@ class VoiceMessageComposerPresenterTest { val finalState = awaitItem() assertThat(finalState.voiceMessageState).isEqualTo(aPreviewState(isSending = true)) - assertThat(matrixRoom.sendMediaCount).isEqualTo(0) + sendMediaResult.assertions().isNeverCalled() assertThat(analyticsService.trackedErrors).hasSize(0) voiceRecorder.assertCalls(started = 1, stopped = 1, deleted = 0) @@ -418,13 +424,13 @@ class VoiceMessageComposerPresenterTest { ensureAllEventsConsumed() assertThat(previewState.voiceMessageState).isEqualTo(aPreviewState()) - assertThat(matrixRoom.sendMediaCount).isEqualTo(0) + sendMediaResult.assertions().isNeverCalled() mediaPreProcessor.givenAudioResult() previewState.eventSink(VoiceMessageComposerEvents.SendVoiceMessage) val finalState = awaitItem() assertThat(finalState.voiceMessageState).isEqualTo(VoiceMessageState.Idle) - assertThat(matrixRoom.sendMediaCount).isEqualTo(1) + sendMediaResult.assertions().isCalledOnce() voiceRecorder.assertCalls(started = 1, stopped = 1, deleted = 1) testPauseAndDestroy(finalState) @@ -461,7 +467,7 @@ class VoiceMessageComposerPresenterTest { assertThat(showSendFailureDialog).isFalse() } - assertThat(matrixRoom.sendMediaCount).isEqualTo(0) + sendMediaResult.assertions().isNeverCalled() testPauseAndDestroy(finalState) } } @@ -477,7 +483,7 @@ class VoiceMessageComposerPresenterTest { initialState.eventSink(VoiceMessageComposerEvents.SendVoiceMessage) assertThat(initialState.voiceMessageState).isEqualTo(VoiceMessageState.Idle) - assertThat(matrixRoom.sendMediaCount).isEqualTo(0) + sendMediaResult.assertions().isNeverCalled() assertThat(analyticsService.trackedErrors).hasSize(1) voiceRecorder.assertCalls(started = 0) @@ -496,7 +502,7 @@ class VoiceMessageComposerPresenterTest { val initialState = awaitItem() initialState.eventSink(VoiceMessageComposerEvents.RecorderEvent(VoiceMessageRecorderEvent.Start)) - assertThat(matrixRoom.sendMediaCount).isEqualTo(0) + sendMediaResult.assertions().isNeverCalled() assertThat(analyticsService.trackedErrors).containsExactly( VoiceMessageException.PermissionMissing(message = "Expected permission to record but none", cause = exception) ) diff --git a/features/poll/impl/src/test/kotlin/io/element/android/features/poll/impl/create/CreatePollPresenterTest.kt b/features/poll/impl/src/test/kotlin/io/element/android/features/poll/impl/create/CreatePollPresenterTest.kt index 89536deaec..334ea7018b 100644 --- a/features/poll/impl/src/test/kotlin/io/element/android/features/poll/impl/create/CreatePollPresenterTest.kt +++ b/features/poll/impl/src/test/kotlin/io/element/android/features/poll/impl/create/CreatePollPresenterTest.kt @@ -35,7 +35,6 @@ import io.element.android.libraries.matrix.api.room.MatrixRoom import io.element.android.libraries.matrix.api.timeline.item.event.PollContent import io.element.android.libraries.matrix.test.AN_EVENT_ID import io.element.android.libraries.matrix.test.room.FakeMatrixRoom -import io.element.android.libraries.matrix.test.room.SavePollInvocation import io.element.android.libraries.matrix.test.timeline.FakeTimeline import io.element.android.libraries.matrix.test.timeline.LiveTimelineProvider import io.element.android.services.analytics.test.FakeAnalyticsService @@ -51,9 +50,9 @@ import kotlinx.coroutines.test.runTest import org.junit.Rule import org.junit.Test -@OptIn(ExperimentalCoroutinesApi::class) class CreatePollPresenterTest { - @get:Rule - val warmUpRule = WarmUpRule() +@OptIn(ExperimentalCoroutinesApi::class) +class CreatePollPresenterTest { + @get:Rule val warmUpRule = WarmUpRule() private val pollEventId = AN_EVENT_ID private var navUpInvocationsCount = 0 @@ -128,7 +127,13 @@ import org.junit.Test @Test fun `create poll sends a poll start event`() = runTest { - val presenter = createCreatePollPresenter(mode = CreatePollMode.NewPoll) + val createPollResult = lambdaRecorder, Int, PollKind, Result> { _, _, _, _ -> Result.success(Unit) } + val presenter = createCreatePollPresenter( + room = FakeMatrixRoom( + createPollResult = createPollResult + ), + mode = CreatePollMode.NewPoll, + ) moleculeFlow(RecompositionMode.Immediate) { presenter.present() }.test { @@ -139,15 +144,13 @@ import org.junit.Test skipItems(3) initial.eventSink(CreatePollEvents.Save) delay(1) // Wait for the coroutine to finish - assertThat(fakeMatrixRoom.createPollInvocations.size).isEqualTo(1) - assertThat(fakeMatrixRoom.createPollInvocations.last()).isEqualTo( - SavePollInvocation( - question = "A question?", - answers = listOf("Answer 1", "Answer 2"), - maxSelections = 1, - pollKind = PollKind.Disclosed + createPollResult.assertions().isCalledOnce() + .with( + value("A question?"), + value(listOf("Answer 1", "Answer 2")), + value(1), + value(PollKind.Disclosed), ) - ) assertThat(fakeAnalyticsService.capturedEvents.size).isEqualTo(2) assertThat(fakeAnalyticsService.capturedEvents[0]).isEqualTo( Composer( @@ -170,8 +173,15 @@ import org.junit.Test @Test fun `when poll creation fails, error is tracked`() = runTest { val error = Exception("cause") - fakeMatrixRoom.givenCreatePollResult(Result.failure(error)) - val presenter = createCreatePollPresenter(mode = CreatePollMode.NewPoll) + val createPollResult = lambdaRecorder, Int, PollKind, Result> { _, _, _, _ -> + Result.failure(error) + } + val presenter = createCreatePollPresenter( + room = FakeMatrixRoom( + createPollResult = createPollResult + ), + mode = CreatePollMode.NewPoll, + ) moleculeFlow(RecompositionMode.Immediate) { presenter.present() }.test { @@ -180,7 +190,7 @@ import org.junit.Test awaitItem().eventSink(CreatePollEvents.SetAnswer(1, "Answer 2")) awaitItem().eventSink(CreatePollEvents.Save) delay(1) // Wait for the coroutine to finish - assertThat(fakeMatrixRoom.createPollInvocations).hasSize(1) + createPollResult.assertions().isCalledOnce() assertThat(fakeAnalyticsService.capturedEvents).isEmpty() assertThat(fakeAnalyticsService.trackedErrors).hasSize(1) assertThat(fakeAnalyticsService.trackedErrors).containsExactly( @@ -252,14 +262,22 @@ import org.junit.Test @Test fun `when edit poll fails, error is tracked`() = runTest { val error = Exception("cause") + val editPollResult = lambdaRecorder { _: EventId, _: String, _: List, _: Int, _: PollKind -> + Result.failure(error) + } + val presenter = createCreatePollPresenter( + room = FakeMatrixRoom( + editPollResult = editPollResult, + liveTimeline = timeline, + ), + mode = CreatePollMode.EditPoll(pollEventId), + ) val editPollLambda = lambdaRecorder { _: EventId, _: String, _: List, _: Int, _: PollKind -> Result.failure(error) } timeline.apply { this.editPollLambda = editPollLambda } - fakeMatrixRoom.givenEditPollResult(Result.failure(error)) - val presenter = createCreatePollPresenter(mode = CreatePollMode.EditPoll(pollEventId)) moleculeFlow(RecompositionMode.Immediate) { presenter.present() }.test { diff --git a/features/roomdetails/impl/src/test/kotlin/io/element/android/features/roomdetails/MatrixRoomFixture.kt b/features/roomdetails/impl/src/test/kotlin/io/element/android/features/roomdetails/MatrixRoomFixture.kt index cffd2ae1f1..9fd89f482d 100644 --- a/features/roomdetails/impl/src/test/kotlin/io/element/android/features/roomdetails/MatrixRoomFixture.kt +++ b/features/roomdetails/impl/src/test/kotlin/io/element/android/features/roomdetails/MatrixRoomFixture.kt @@ -17,11 +17,15 @@ package io.element.android.features.roomdetails import io.element.android.libraries.matrix.api.core.RoomId +import io.element.android.libraries.matrix.api.core.UserId +import io.element.android.libraries.matrix.api.room.RoomMember +import io.element.android.libraries.matrix.api.room.StateEventType import io.element.android.libraries.matrix.test.A_ROOM_ID import io.element.android.libraries.matrix.test.A_ROOM_NAME import io.element.android.libraries.matrix.test.notificationsettings.FakeNotificationSettingsService import io.element.android.libraries.matrix.test.room.FakeMatrixRoom import io.element.android.libraries.matrix.test.room.aRoomInfo +import io.element.android.tests.testutils.lambda.lambdaError fun aMatrixRoom( roomId: RoomId = A_ROOM_ID, @@ -34,6 +38,16 @@ fun aMatrixRoom( isDirect: Boolean = false, notificationSettingsService: FakeNotificationSettingsService = FakeNotificationSettingsService(), emitRoomInfo: Boolean = false, + canInviteResult: (UserId) -> Result = { lambdaError() }, + canSendStateResult: (UserId, StateEventType) -> Result = { _, _ -> lambdaError() }, + userDisplayNameResult: () -> Result = { lambdaError() }, + userAvatarUrlResult: () -> Result = { lambdaError() }, + setNameResult: (String) -> Result = { lambdaError() }, + setTopicResult: (String) -> Result = { lambdaError() }, + updateAvatarResult: (String, ByteArray) -> Result = { _, _ -> lambdaError() }, + removeAvatarResult: () -> Result = { lambdaError() }, + canUserJoinCallResult: (UserId) -> Result = { lambdaError() }, + getUpdatedMemberResult: (UserId) -> Result = { lambdaError() }, ) = FakeMatrixRoom( roomId = roomId, displayName = displayName, @@ -42,7 +56,17 @@ fun aMatrixRoom( isEncrypted = isEncrypted, isPublic = isPublic, isDirect = isDirect, - notificationSettingsService = notificationSettingsService + notificationSettingsService = notificationSettingsService, + canInviteResult = canInviteResult, + canSendStateResult = canSendStateResult, + userDisplayNameResult = userDisplayNameResult, + userAvatarUrlResult = userAvatarUrlResult, + setNameResult = setNameResult, + setTopicResult = setTopicResult, + updateAvatarResult = updateAvatarResult, + removeAvatarResult = removeAvatarResult, + canUserJoinCallResult = canUserJoinCallResult, + getUpdatedMemberResult = getUpdatedMemberResult, ).apply { if (emitRoomInfo) { givenRoomInfo( diff --git a/features/roomdetails/impl/src/test/kotlin/io/element/android/features/roomdetails/RoomDetailsPresenterTest.kt b/features/roomdetails/impl/src/test/kotlin/io/element/android/features/roomdetails/RoomDetailsPresenterTest.kt index 92ac27454a..ff89aba9be 100644 --- a/features/roomdetails/impl/src/test/kotlin/io/element/android/features/roomdetails/RoomDetailsPresenterTest.kt +++ b/features/roomdetails/impl/src/test/kotlin/io/element/android/features/roomdetails/RoomDetailsPresenterTest.kt @@ -53,6 +53,9 @@ import io.element.android.services.analytics.test.FakeAnalyticsService import io.element.android.tests.testutils.FakeLifecycleOwner import io.element.android.tests.testutils.WarmUpRule import io.element.android.tests.testutils.consumeItemsUntilPredicate +import io.element.android.tests.testutils.lambda.lambdaError +import io.element.android.tests.testutils.lambda.lambdaRecorder +import io.element.android.tests.testutils.lambda.value import io.element.android.tests.testutils.testCoroutineDispatchers import io.element.android.tests.testutils.withFakeLifecycleOwner import kotlinx.collections.immutable.persistentListOf @@ -110,7 +113,11 @@ class RoomDetailsPresenterTest { @Test fun `present - initial state is created from room if roomInfo is null`() = runTest { - val room = aMatrixRoom() + val room = aMatrixRoom( + canInviteResult = { Result.success(true) }, + canUserJoinCallResult = { Result.success(true) }, + canSendStateResult = { _, _ -> Result.success(true) }, + ) val presenter = createRoomDetailsPresenter(room) presenter.test { val initialState = awaitItem() @@ -128,7 +135,11 @@ class RoomDetailsPresenterTest { @Test fun `present - initial state is updated with roomInfo if it exists`() = runTest { val roomInfo = aRoomInfo(name = "A room name", topic = "A topic", avatarUrl = "https://matrix.org/avatar.jpg") - val room = aMatrixRoom().apply { + val room = aMatrixRoom( + canInviteResult = { Result.success(true) }, + canUserJoinCallResult = { Result.success(true) }, + canSendStateResult = { _, _ -> Result.success(true) }, + ).apply { givenRoomInfo(roomInfo) } val presenter = createRoomDetailsPresenter(room) @@ -145,7 +156,12 @@ class RoomDetailsPresenterTest { @Test fun `present - initial state with no room name`() = runTest { - val room = aMatrixRoom(displayName = "") + val room = aMatrixRoom( + displayName = "", + canInviteResult = { Result.success(true) }, + canUserJoinCallResult = { Result.success(true) }, + canSendStateResult = { _, _ -> Result.success(true) }, + ) val presenter = createRoomDetailsPresenter(room) presenter.test { val initialState = awaitItem() @@ -162,6 +178,16 @@ class RoomDetailsPresenterTest { val room = aMatrixRoom( isEncrypted = true, isDirect = true, + canInviteResult = { Result.success(true) }, + canUserJoinCallResult = { Result.success(true) }, + canSendStateResult = { _, _ -> Result.success(true) }, + getUpdatedMemberResult = { userId -> + when (userId) { + A_SESSION_ID -> Result.success(myRoomMember) + A_USER_ID_2 -> Result.success(otherRoomMember) + else -> lambdaError() + } + }, ).apply { val roomMembers = persistentListOf(myRoomMember, otherRoomMember) givenRoomMembersState(MatrixRoomMembersState.Ready(roomMembers)) @@ -181,9 +207,11 @@ class RoomDetailsPresenterTest { @Test fun `present - initial state when user can invite others to room`() = runTest { - val room = aMatrixRoom().apply { - givenCanInviteResult(Result.success(true)) - } + val room = aMatrixRoom( + canInviteResult = { Result.success(true) }, + canUserJoinCallResult = { Result.success(true) }, + canSendStateResult = { _, _ -> Result.success(true) }, + ) val presenter = createRoomDetailsPresenter(room, dispatchers = testCoroutineDispatchers()) presenter.test { // Initially false @@ -197,9 +225,11 @@ class RoomDetailsPresenterTest { @Test fun `present - initial state when user can not invite others to room`() = runTest { - val room = aMatrixRoom().apply { - givenCanInviteResult(Result.success(false)) - } + val room = aMatrixRoom( + canInviteResult = { Result.success(false) }, + canUserJoinCallResult = { Result.success(true) }, + canSendStateResult = { _, _ -> Result.success(true) }, + ) val presenter = createRoomDetailsPresenter(room) presenter.test { assertThat(awaitItem().canInvite).isFalse() @@ -210,9 +240,11 @@ class RoomDetailsPresenterTest { @Test fun `present - initial state when canInvite errors`() = runTest { - val room = aMatrixRoom().apply { - givenCanInviteResult(Result.failure(Throwable("Whoops"))) - } + val room = aMatrixRoom( + canInviteResult = { Result.failure(Throwable("Whoops")) }, + canUserJoinCallResult = { Result.success(true) }, + canSendStateResult = { _, _ -> Result.success(true) }, + ) val presenter = createRoomDetailsPresenter(room) presenter.test { assertThat(awaitItem().canInvite).isFalse() @@ -223,12 +255,18 @@ class RoomDetailsPresenterTest { @Test fun `present - initial state when user can edit one attribute`() = runTest { - val room = aMatrixRoom().apply { - givenCanSendStateResult(StateEventType.ROOM_TOPIC, Result.success(true)) - givenCanSendStateResult(StateEventType.ROOM_NAME, Result.success(false)) - givenCanSendStateResult(StateEventType.ROOM_AVATAR, Result.failure(Throwable("Whelp"))) - givenCanInviteResult(Result.success(false)) - } + val room = aMatrixRoom( + canSendStateResult = { _, stateEventType -> + when (stateEventType) { + StateEventType.ROOM_TOPIC -> Result.success(true) + StateEventType.ROOM_NAME -> Result.success(false) + StateEventType.ROOM_AVATAR -> Result.failure(Throwable("Whelp")) + else -> lambdaError() + } + }, + canInviteResult = { Result.success(false) }, + canUserJoinCallResult = { Result.success(true) }, + ) val presenter = createRoomDetailsPresenter(room) presenter.test { // Initially false @@ -247,14 +285,26 @@ class RoomDetailsPresenterTest { val room = aMatrixRoom( isEncrypted = true, isDirect = true, + canSendStateResult = { _, stateEventType -> + when (stateEventType) { + StateEventType.ROOM_TOPIC -> Result.success(true) + StateEventType.ROOM_NAME -> Result.success(true) + StateEventType.ROOM_AVATAR -> Result.success(true) + else -> lambdaError() + } + }, + canInviteResult = { Result.success(false) }, + canUserJoinCallResult = { Result.success(true) }, + getUpdatedMemberResult = { userId -> + when (userId) { + A_SESSION_ID -> Result.success(myRoomMember) + A_USER_ID_2 -> Result.success(otherRoomMember) + else -> lambdaError() + } + }, ).apply { val roomMembers = persistentListOf(myRoomMember, otherRoomMember) givenRoomMembersState(MatrixRoomMembersState.Ready(roomMembers)) - - givenCanSendStateResult(StateEventType.ROOM_TOPIC, Result.success(true)) - givenCanSendStateResult(StateEventType.ROOM_NAME, Result.success(true)) - givenCanSendStateResult(StateEventType.ROOM_AVATAR, Result.success(true)) - givenCanInviteResult(Result.success(false)) } val presenter = createRoomDetailsPresenter(room) presenter.test { @@ -278,12 +328,28 @@ class RoomDetailsPresenterTest { isEncrypted = true, isDirect = true, topic = null, + canSendStateResult = { _, stateEventType -> + when (stateEventType) { + StateEventType.ROOM_AVATAR, + StateEventType.ROOM_TOPIC, + StateEventType.ROOM_NAME -> Result.success(true) + else -> lambdaError() + } + }, + canInviteResult = { Result.success(true) }, + canUserJoinCallResult = { Result.success(true) }, + getUpdatedMemberResult = { userId -> + when (userId) { + A_SESSION_ID -> Result.success(myRoomMember) + A_USER_ID_2 -> Result.success(otherRoomMember) + else -> lambdaError() + } + }, ).apply { val roomMembers = persistentListOf(myRoomMember, otherRoomMember) givenRoomMembersState(MatrixRoomMembersState.Ready(roomMembers)) - - givenCanSendStateResult(StateEventType.ROOM_TOPIC, Result.success(true)) } + val presenter = createRoomDetailsPresenter(room) presenter.test { skipItems(1) @@ -297,12 +363,20 @@ class RoomDetailsPresenterTest { @Test fun `present - initial state when user can edit all attributes`() = runTest { - val room = aMatrixRoom().apply { - givenCanSendStateResult(StateEventType.ROOM_TOPIC, Result.success(true)) - givenCanSendStateResult(StateEventType.ROOM_NAME, Result.success(true)) - givenCanSendStateResult(StateEventType.ROOM_AVATAR, Result.success(true)) - givenCanInviteResult(Result.success(false)) - } + val room = aMatrixRoom( + canSendStateResult = { _, stateEventType -> + when (stateEventType) { + StateEventType.ROOM_TOPIC -> Result.success(true) + StateEventType.ROOM_NAME -> Result.success(true) + StateEventType.ROOM_AVATAR -> Result.success(true) + else -> lambdaError() + } + }, + canInviteResult = { + Result.success(false) + }, + canUserJoinCallResult = { Result.success(true) }, + ) val presenter = createRoomDetailsPresenter(room) presenter.test { // Initially false @@ -316,12 +390,20 @@ class RoomDetailsPresenterTest { @Test fun `present - initial state when user can edit no attributes`() = runTest { - val room = aMatrixRoom().apply { - givenCanSendStateResult(StateEventType.ROOM_TOPIC, Result.success(false)) - givenCanSendStateResult(StateEventType.ROOM_NAME, Result.success(false)) - givenCanSendStateResult(StateEventType.ROOM_AVATAR, Result.success(false)) - givenCanInviteResult(Result.success(false)) - } + val room = aMatrixRoom( + canSendStateResult = { _, stateEventType -> + when (stateEventType) { + StateEventType.ROOM_TOPIC -> Result.success(false) + StateEventType.ROOM_NAME -> Result.success(false) + StateEventType.ROOM_AVATAR -> Result.success(false) + else -> lambdaError() + } + }, + canInviteResult = { + Result.success(false) + }, + canUserJoinCallResult = { Result.success(true) }, + ) val presenter = createRoomDetailsPresenter(room) presenter.test { // Initially false, and no further events @@ -333,11 +415,21 @@ class RoomDetailsPresenterTest { @Test fun `present - topic state is hidden when no topic and user has no permission`() = runTest { - val room = aMatrixRoom(topic = null).apply { - givenCanSendStateResult(StateEventType.ROOM_TOPIC, Result.success(false)) - givenCanInviteResult(Result.success(false)) - } - + val room = aMatrixRoom( + topic = null, + canSendStateResult = { _, stateEventType -> + when (stateEventType) { + StateEventType.ROOM_AVATAR, + StateEventType.ROOM_NAME -> Result.success(true) + StateEventType.ROOM_TOPIC -> Result.success(false) + else -> lambdaError() + } + }, + canInviteResult = { + Result.success(false) + }, + canUserJoinCallResult = { Result.success(true) }, + ) val presenter = createRoomDetailsPresenter(room) presenter.test { // The initial state is "hidden" and no further state changes happen @@ -349,12 +441,23 @@ class RoomDetailsPresenterTest { @Test fun `present - topic state is 'can add topic' when no topic and user has permission`() = runTest { - val room = aMatrixRoom(topic = null).apply { - givenCanSendStateResult(StateEventType.ROOM_TOPIC, Result.success(true)) - givenCanInviteResult(Result.success(false)) + val room = aMatrixRoom( + topic = null, + canSendStateResult = { _, stateEventType -> + when (stateEventType) { + StateEventType.ROOM_AVATAR, + StateEventType.ROOM_TOPIC, + StateEventType.ROOM_NAME -> Result.success(true) + else -> lambdaError() + } + }, + canInviteResult = { + Result.success(false) + }, + canUserJoinCallResult = { Result.success(true) }, + ).apply { givenRoomInfo(aRoomInfo(topic = null)) } - val presenter = createRoomDetailsPresenter(room) presenter.test { // Ignore the initial state @@ -370,7 +473,11 @@ class RoomDetailsPresenterTest { @Test fun `present - leave room event is passed on to leave room presenter`() = runTest { val leaveRoomPresenter = FakeLeaveRoomPresenter() - val room = aMatrixRoom() + val room = aMatrixRoom( + canInviteResult = { Result.success(true) }, + canUserJoinCallResult = { Result.success(true) }, + canSendStateResult = { _, _ -> Result.success(true) }, + ) val presenter = createRoomDetailsPresenter( room = room, leaveRoomPresenter = leaveRoomPresenter, @@ -379,7 +486,11 @@ class RoomDetailsPresenterTest { presenter.test { awaitItem().eventSink(RoomDetailsEvent.LeaveRoom) - assertThat(leaveRoomPresenter.events).contains(LeaveRoomEvent.ShowConfirmation(room.roomId)) + assertThat(leaveRoomPresenter.events).contains( + LeaveRoomEvent.ShowConfirmation( + room.roomId + ) + ) cancelAndIgnoreRemainingEvents() } @@ -389,33 +500,54 @@ class RoomDetailsPresenterTest { fun `present - notification mode changes`() = runTest { val leaveRoomPresenter = FakeLeaveRoomPresenter() val notificationSettingsService = FakeNotificationSettingsService() - val room = aMatrixRoom(notificationSettingsService = notificationSettingsService) + val room = aMatrixRoom( + notificationSettingsService = notificationSettingsService, + canInviteResult = { Result.success(true) }, + canUserJoinCallResult = { Result.success(true) }, + canSendStateResult = { _, _ -> Result.success(true) }, + ) val presenter = createRoomDetailsPresenter( room = room, leaveRoomPresenter = leaveRoomPresenter, notificationSettingsService = notificationSettingsService, ) presenter.test { - notificationSettingsService.setRoomNotificationMode(room.roomId, RoomNotificationMode.MENTIONS_AND_KEYWORDS_ONLY) + notificationSettingsService.setRoomNotificationMode( + room.roomId, + RoomNotificationMode.MENTIONS_AND_KEYWORDS_ONLY + ) val updatedState = consumeItemsUntilPredicate { it.roomNotificationSettings?.mode == RoomNotificationMode.MENTIONS_AND_KEYWORDS_ONLY }.last() - assertThat(updatedState.roomNotificationSettings?.mode).isEqualTo(RoomNotificationMode.MENTIONS_AND_KEYWORDS_ONLY) + assertThat(updatedState.roomNotificationSettings?.mode).isEqualTo( + RoomNotificationMode.MENTIONS_AND_KEYWORDS_ONLY + ) cancelAndIgnoreRemainingEvents() } } @Test fun `present - mute room notifications`() = runTest { - val notificationSettingsService = FakeNotificationSettingsService(initialRoomMode = RoomNotificationMode.MENTIONS_AND_KEYWORDS_ONLY) - val room = aMatrixRoom(notificationSettingsService = notificationSettingsService) - val presenter = createRoomDetailsPresenter(room = room, notificationSettingsService = notificationSettingsService) + val notificationSettingsService = + FakeNotificationSettingsService(initialRoomMode = RoomNotificationMode.MENTIONS_AND_KEYWORDS_ONLY) + val room = aMatrixRoom( + notificationSettingsService = notificationSettingsService, + canInviteResult = { Result.success(true) }, + canUserJoinCallResult = { Result.success(true) }, + canSendStateResult = { _, _ -> Result.success(true) }, + ) + val presenter = createRoomDetailsPresenter( + room = room, + notificationSettingsService = notificationSettingsService + ) presenter.test { awaitItem().eventSink(RoomDetailsEvent.MuteNotification) val updatedState = consumeItemsUntilPredicate(timeout = 250.milliseconds) { it.roomNotificationSettings?.mode == RoomNotificationMode.MUTE }.last() - assertThat(updatedState.roomNotificationSettings?.mode).isEqualTo(RoomNotificationMode.MUTE) + assertThat(updatedState.roomNotificationSettings?.mode).isEqualTo( + RoomNotificationMode.MUTE + ) cancelAndIgnoreRemainingEvents() } } @@ -426,29 +558,50 @@ class RoomDetailsPresenterTest { initialRoomMode = RoomNotificationMode.MENTIONS_AND_KEYWORDS_ONLY, initialEncryptedGroupDefaultMode = RoomNotificationMode.ALL_MESSAGES ) - val room = aMatrixRoom(notificationSettingsService = notificationSettingsService) - val presenter = createRoomDetailsPresenter(room = room, notificationSettingsService = notificationSettingsService) + val room = aMatrixRoom( + notificationSettingsService = notificationSettingsService, + canInviteResult = { Result.success(true) }, + canUserJoinCallResult = { Result.success(true) }, + canSendStateResult = { _, _ -> Result.success(true) }, + ) + val presenter = createRoomDetailsPresenter( + room = room, + notificationSettingsService = notificationSettingsService + ) presenter.test { awaitItem().eventSink(RoomDetailsEvent.UnmuteNotification) val updatedState = consumeItemsUntilPredicate { it.roomNotificationSettings?.mode == RoomNotificationMode.ALL_MESSAGES }.last() - assertThat(updatedState.roomNotificationSettings?.mode).isEqualTo(RoomNotificationMode.ALL_MESSAGES) + assertThat(updatedState.roomNotificationSettings?.mode).isEqualTo( + RoomNotificationMode.ALL_MESSAGES + ) cancelAndIgnoreRemainingEvents() } } @Test fun `present - when set is favorite event is emitted, then the action is called`() = runTest { - val room = FakeMatrixRoom() + val setIsFavoriteResult = lambdaRecorder> { _ -> Result.success(Unit) } + val room = FakeMatrixRoom( + setIsFavoriteResult = setIsFavoriteResult, + canInviteResult = { Result.success(true) }, + canUserJoinCallResult = { Result.success(true) }, + canSendStateResult = { _, _ -> Result.success(true) }, + ) val analyticsService = FakeAnalyticsService() - val presenter = createRoomDetailsPresenter(room = room, analyticsService = analyticsService) + val presenter = + createRoomDetailsPresenter(room = room, analyticsService = analyticsService) presenter.test { val initialState = awaitItem() initialState.eventSink(RoomDetailsEvent.SetFavorite(true)) - assertThat(room.setIsFavoriteCalls).isEqualTo(listOf(true)) + setIsFavoriteResult.assertions().isCalledOnce().with(value(true)) initialState.eventSink(RoomDetailsEvent.SetFavorite(false)) - assertThat(room.setIsFavoriteCalls).isEqualTo(listOf(true, false)) + setIsFavoriteResult.assertions().isCalledExactly(2) + .withSequence( + listOf(value(true)), + listOf(value(false)), + ) assertThat(analyticsService.capturedEvents).containsExactly( Interaction(name = Interaction.Name.MobileRoomFavouriteToggle), Interaction(name = Interaction.Name.MobileRoomFavouriteToggle) @@ -459,7 +612,11 @@ class RoomDetailsPresenterTest { @Test fun `present - changes in room info updates the is favorite flag`() = runTest { - val room = aMatrixRoom() + val room = aMatrixRoom( + canInviteResult = { Result.success(true) }, + canUserJoinCallResult = { Result.success(true) }, + canSendStateResult = { _, _ -> Result.success(true) }, + ) val presenter = createRoomDetailsPresenter(room = room) presenter.test { room.givenRoomInfo(aRoomInfo(isFavorite = true)) diff --git a/features/roomdetails/impl/src/test/kotlin/io/element/android/features/roomdetails/edit/RoomDetailsEditPresenterTest.kt b/features/roomdetails/impl/src/test/kotlin/io/element/android/features/roomdetails/edit/RoomDetailsEditPresenterTest.kt index f287fe4ab4..5d8a43ca4b 100644 --- a/features/roomdetails/impl/src/test/kotlin/io/element/android/features/roomdetails/edit/RoomDetailsEditPresenterTest.kt +++ b/features/roomdetails/impl/src/test/kotlin/io/element/android/features/roomdetails/edit/RoomDetailsEditPresenterTest.kt @@ -39,6 +39,9 @@ import io.element.android.libraries.permissions.api.PermissionsPresenter import io.element.android.libraries.permissions.test.FakePermissionsPresenter import io.element.android.libraries.permissions.test.FakePermissionsPresenterFactory import io.element.android.tests.testutils.WarmUpRule +import io.element.android.tests.testutils.lambda.lambdaError +import io.element.android.tests.testutils.lambda.lambdaRecorder +import io.element.android.tests.testutils.lambda.value import io.mockk.every import io.mockk.mockk import io.mockk.mockkStatic @@ -98,6 +101,7 @@ class RoomDetailsEditPresenterTest { displayName = A_ROOM_NAME, rawName = A_ROOM_RAW_NAME, emitRoomInfo = true, + canSendStateResult = { _, _ -> Result.success(true) } ) val presenter = createRoomDetailsEditPresenter(room) moleculeFlow(RecompositionMode.Immediate) { @@ -120,11 +124,17 @@ class RoomDetailsEditPresenterTest { @Test fun `present - sets canChangeName if user has permission`() = runTest { - val room = aMatrixRoom(avatarUrl = AN_AVATAR_URL).apply { - givenCanSendStateResult(StateEventType.ROOM_NAME, Result.success(true)) - givenCanSendStateResult(StateEventType.ROOM_AVATAR, Result.success(false)) - givenCanSendStateResult(StateEventType.ROOM_TOPIC, Result.failure(Throwable("Oops"))) - } + val room = aMatrixRoom( + avatarUrl = AN_AVATAR_URL, + canSendStateResult = { _, stateEventType -> + when (stateEventType) { + StateEventType.ROOM_NAME -> Result.success(true) + StateEventType.ROOM_AVATAR -> Result.success(false) + StateEventType.ROOM_TOPIC -> Result.failure(Throwable("Oops")) + else -> lambdaError() + } + }, + ) val presenter = createRoomDetailsEditPresenter(room) moleculeFlow(RecompositionMode.Immediate) { presenter.present() @@ -144,11 +154,17 @@ class RoomDetailsEditPresenterTest { @Test fun `present - sets canChangeAvatar if user has permission`() = runTest { - val room = aMatrixRoom(avatarUrl = AN_AVATAR_URL).apply { - givenCanSendStateResult(StateEventType.ROOM_NAME, Result.success(false)) - givenCanSendStateResult(StateEventType.ROOM_AVATAR, Result.success(true)) - givenCanSendStateResult(StateEventType.ROOM_TOPIC, Result.failure(Throwable("Oops"))) - } + val room = aMatrixRoom( + avatarUrl = AN_AVATAR_URL, + canSendStateResult = { _, stateEventType -> + when (stateEventType) { + StateEventType.ROOM_NAME -> Result.success(false) + StateEventType.ROOM_AVATAR -> Result.success(true) + StateEventType.ROOM_TOPIC -> Result.failure(Throwable("Oops")) + else -> lambdaError() + } + } + ) val presenter = createRoomDetailsEditPresenter(room) moleculeFlow(RecompositionMode.Immediate) { presenter.present() @@ -168,11 +184,17 @@ class RoomDetailsEditPresenterTest { @Test fun `present - sets canChangeTopic if user has permission`() = runTest { - val room = aMatrixRoom(avatarUrl = AN_AVATAR_URL).apply { - givenCanSendStateResult(StateEventType.ROOM_NAME, Result.success(false)) - givenCanSendStateResult(StateEventType.ROOM_AVATAR, Result.failure(Throwable("Oops"))) - givenCanSendStateResult(StateEventType.ROOM_TOPIC, Result.success(true)) - } + val room = aMatrixRoom( + avatarUrl = AN_AVATAR_URL, + canSendStateResult = { _, stateEventType -> + when (stateEventType) { + StateEventType.ROOM_NAME -> Result.success(false) + StateEventType.ROOM_AVATAR -> Result.failure(Throwable("Oops")) + StateEventType.ROOM_TOPIC -> Result.success(true) + else -> lambdaError() + } + } + ) val presenter = createRoomDetailsEditPresenter(room) moleculeFlow(RecompositionMode.Immediate) { presenter.present() @@ -197,6 +219,7 @@ class RoomDetailsEditPresenterTest { displayName = "Name", avatarUrl = AN_AVATAR_URL, emitRoomInfo = true, + canSendStateResult = { _, _ -> Result.success(true) } ) val presenter = createRoomDetailsEditPresenter(room) moleculeFlow(RecompositionMode.Immediate) { @@ -240,6 +263,7 @@ class RoomDetailsEditPresenterTest { displayName = "Name", avatarUrl = AN_AVATAR_URL, emitRoomInfo = true, + canSendStateResult = { _, _ -> Result.success(true) } ) fakePickerProvider.givenResult(anotherAvatarUri) val presenter = createRoomDetailsEditPresenter(room) @@ -262,6 +286,7 @@ class RoomDetailsEditPresenterTest { displayName = "Name", avatarUrl = AN_AVATAR_URL, emitRoomInfo = true, + canSendStateResult = { _, _ -> Result.success(true) } ) fakePickerProvider.givenResult(anotherAvatarUri) val fakePermissionsPresenter = FakePermissionsPresenter() @@ -298,6 +323,7 @@ class RoomDetailsEditPresenterTest { displayName = "Name", avatarUrl = AN_AVATAR_URL, emitRoomInfo = true, + canSendStateResult = { _, _ -> Result.success(true) } ) fakePickerProvider.givenResult(roomAvatarUri) val presenter = createRoomDetailsEditPresenter(room) @@ -346,6 +372,7 @@ class RoomDetailsEditPresenterTest { displayName = "fallback", avatarUrl = null, emitRoomInfo = true, + canSendStateResult = { _, _ -> Result.success(true) } ) fakePickerProvider.givenResult(roomAvatarUri) val presenter = createRoomDetailsEditPresenter(room) @@ -389,11 +416,18 @@ class RoomDetailsEditPresenterTest { @Test fun `present - save changes room details if different`() = runTest { + val setNameResult = lambdaRecorder { _: String -> Result.success(Unit) } + val setTopicResult = lambdaRecorder { _: String -> Result.success(Unit) } + val removeAvatarResult = lambdaRecorder> { Result.success(Unit) } val room = aMatrixRoom( topic = "My topic", displayName = "Name", avatarUrl = AN_AVATAR_URL, emitRoomInfo = true, + setNameResult = setNameResult, + setTopicResult = setTopicResult, + removeAvatarResult = removeAvatarResult, + canSendStateResult = { _, _ -> Result.success(true) } ) val presenter = createRoomDetailsEditPresenter(room) moleculeFlow(RecompositionMode.Immediate) { @@ -405,16 +439,20 @@ class RoomDetailsEditPresenterTest { initialState.eventSink(RoomDetailsEditEvents.HandleAvatarAction(AvatarAction.Remove)) initialState.eventSink(RoomDetailsEditEvents.Save) skipItems(5) - assertThat(room.newName).isEqualTo("New name") - assertThat(room.newTopic).isEqualTo("New topic") - assertThat(room.newAvatarData).isNull() - assertThat(room.removedAvatar).isTrue() + setNameResult.assertions().isCalledOnce().with(value("New name")) + setTopicResult.assertions().isCalledOnce().with(value("New topic")) + removeAvatarResult.assertions().isCalledOnce() } } @Test fun `present - save doesn't change room details if they're the same trimmed`() = runTest { - val room = aMatrixRoom(topic = "My topic", displayName = "Name", avatarUrl = AN_AVATAR_URL) + val room = aMatrixRoom( + topic = "My topic", + displayName = "Name", + avatarUrl = AN_AVATAR_URL, + canSendStateResult = { _, _ -> Result.success(true) } + ) val presenter = createRoomDetailsEditPresenter(room) moleculeFlow(RecompositionMode.Immediate) { presenter.present() @@ -423,17 +461,18 @@ class RoomDetailsEditPresenterTest { initialState.eventSink(RoomDetailsEditEvents.UpdateRoomName(" Name ")) initialState.eventSink(RoomDetailsEditEvents.UpdateRoomTopic(" My topic ")) initialState.eventSink(RoomDetailsEditEvents.Save) - assertThat(room.newName).isNull() - assertThat(room.newTopic).isNull() - assertThat(room.newAvatarData).isNull() - assertThat(room.removedAvatar).isFalse() cancelAndIgnoreRemainingEvents() } } @Test fun `present - save doesn't change topic if it was unset and is now blank`() = runTest { - val room = aMatrixRoom(topic = null, displayName = "Name", avatarUrl = AN_AVATAR_URL) + val room = aMatrixRoom( + topic = null, + displayName = "Name", + avatarUrl = AN_AVATAR_URL, + canSendStateResult = { _, _ -> Result.success(true) } + ) val presenter = createRoomDetailsEditPresenter(room) moleculeFlow(RecompositionMode.Immediate) { presenter.present() @@ -441,17 +480,18 @@ class RoomDetailsEditPresenterTest { val initialState = awaitItem() initialState.eventSink(RoomDetailsEditEvents.UpdateRoomTopic("")) initialState.eventSink(RoomDetailsEditEvents.Save) - assertThat(room.newName).isNull() - assertThat(room.newTopic).isNull() - assertThat(room.newAvatarData).isNull() - assertThat(room.removedAvatar).isFalse() cancelAndIgnoreRemainingEvents() } } @Test fun `present - save doesn't change name if it's now empty`() = runTest { - val room = aMatrixRoom(topic = "My topic", displayName = "Name", avatarUrl = AN_AVATAR_URL) + val room = aMatrixRoom( + topic = "My topic", + displayName = "Name", + avatarUrl = AN_AVATAR_URL, + canSendStateResult = { _, _ -> Result.success(true) } + ) val presenter = createRoomDetailsEditPresenter(room) moleculeFlow(RecompositionMode.Immediate) { presenter.present() @@ -459,17 +499,20 @@ class RoomDetailsEditPresenterTest { val initialState = awaitItem() initialState.eventSink(RoomDetailsEditEvents.UpdateRoomName("")) initialState.eventSink(RoomDetailsEditEvents.Save) - assertThat(room.newName).isNull() - assertThat(room.newTopic).isNull() - assertThat(room.newAvatarData).isNull() - assertThat(room.removedAvatar).isFalse() cancelAndIgnoreRemainingEvents() } } @Test fun `present - save processes and sets avatar when processor returns successfully`() = runTest { - val room = aMatrixRoom(topic = "My topic", displayName = "Name", avatarUrl = AN_AVATAR_URL) + val updateAvatarResult = lambdaRecorder { _: String, _: ByteArray -> Result.success(Unit) } + val room = aMatrixRoom( + topic = "My topic", + displayName = "Name", + avatarUrl = AN_AVATAR_URL, + updateAvatarResult = updateAvatarResult, + canSendStateResult = { _, _ -> Result.success(true) } + ) givenPickerReturnsFile() val presenter = createRoomDetailsEditPresenter(room) moleculeFlow(RecompositionMode.Immediate) { @@ -478,17 +521,19 @@ class RoomDetailsEditPresenterTest { val initialState = awaitItem() initialState.eventSink(RoomDetailsEditEvents.HandleAvatarAction(AvatarAction.ChoosePhoto)) initialState.eventSink(RoomDetailsEditEvents.Save) - skipItems(3) - assertThat(room.newName).isNull() - assertThat(room.newTopic).isNull() - assertThat(room.newAvatarData).isSameInstanceAs(fakeFileContents) - assertThat(room.removedAvatar).isFalse() + skipItems(4) + updateAvatarResult.assertions().isCalledOnce().with(value("image/jpeg"), value(fakeFileContents)) } } @Test fun `present - save does not set avatar data if processor fails`() = runTest { - val room = aMatrixRoom(topic = "My topic", displayName = "Name", avatarUrl = AN_AVATAR_URL) + val room = aMatrixRoom( + topic = "My topic", + displayName = "Name", + avatarUrl = AN_AVATAR_URL, + canSendStateResult = { _, _ -> Result.success(true) } + ) fakePickerProvider.givenResult(anotherAvatarUri) fakeMediaPreProcessor.givenResult(Result.failure(Throwable("Oh no"))) val presenter = createRoomDetailsEditPresenter(room) @@ -498,11 +543,7 @@ class RoomDetailsEditPresenterTest { val initialState = awaitItem() initialState.eventSink(RoomDetailsEditEvents.HandleAvatarAction(AvatarAction.ChoosePhoto)) initialState.eventSink(RoomDetailsEditEvents.Save) - skipItems(2) - assertThat(room.newName).isNull() - assertThat(room.newTopic).isNull() - assertThat(room.newAvatarData).isNull() - assertThat(room.removedAvatar).isFalse() + skipItems(3) assertThat(awaitItem().saveAction).isInstanceOf(AsyncAction.Failure::class.java) } } @@ -514,9 +555,9 @@ class RoomDetailsEditPresenterTest { displayName = "Name", avatarUrl = AN_AVATAR_URL, emitRoomInfo = true, - ).apply { - givenSetNameResult(Result.failure(Throwable("!"))) - } + setNameResult = { Result.failure(Throwable("!")) }, + canSendStateResult = { _, _ -> Result.success(true) } + ) saveAndAssertFailure(room, RoomDetailsEditEvents.UpdateRoomName("New name")) } @@ -527,9 +568,9 @@ class RoomDetailsEditPresenterTest { displayName = "Name", avatarUrl = AN_AVATAR_URL, emitRoomInfo = true, - ).apply { - givenSetTopicResult(Result.failure(Throwable("!"))) - } + setTopicResult = { Result.failure(Throwable("!")) }, + canSendStateResult = { _, _ -> Result.success(true) } + ) saveAndAssertFailure(room, RoomDetailsEditEvents.UpdateRoomTopic("New topic")) } @@ -540,9 +581,9 @@ class RoomDetailsEditPresenterTest { displayName = "Name", avatarUrl = AN_AVATAR_URL, emitRoomInfo = true, - ).apply { - givenRemoveAvatarResult(Result.failure(Throwable("!"))) - } + removeAvatarResult = { Result.failure(Throwable("!")) }, + canSendStateResult = { _, _ -> Result.success(true) } + ) saveAndAssertFailure(room, RoomDetailsEditEvents.HandleAvatarAction(AvatarAction.Remove)) } @@ -554,18 +595,22 @@ class RoomDetailsEditPresenterTest { displayName = "Name", avatarUrl = AN_AVATAR_URL, emitRoomInfo = true, - ).apply { - givenUpdateAvatarResult(Result.failure(Throwable("!"))) - } + updateAvatarResult = { _, _ -> Result.failure(Throwable("!")) }, + canSendStateResult = { _, _ -> Result.success(true) } + ) saveAndAssertFailure(room, RoomDetailsEditEvents.HandleAvatarAction(AvatarAction.ChoosePhoto)) } @Test fun `present - CancelSaveChanges resets save action state`() = runTest { givenPickerReturnsFile() - val room = aMatrixRoom(topic = "My topic", displayName = "Name", avatarUrl = AN_AVATAR_URL).apply { - givenSetTopicResult(Result.failure(Throwable("!"))) - } + val room = aMatrixRoom( + topic = "My topic", + displayName = "Name", + avatarUrl = AN_AVATAR_URL, + setTopicResult = { Result.failure(Throwable("!")) }, + canSendStateResult = { _, _ -> Result.success(true) } + ) val presenter = createRoomDetailsEditPresenter(room) moleculeFlow(RecompositionMode.Immediate) { presenter.present() @@ -573,7 +618,7 @@ class RoomDetailsEditPresenterTest { val initialState = awaitItem() initialState.eventSink(RoomDetailsEditEvents.UpdateRoomTopic("foo")) initialState.eventSink(RoomDetailsEditEvents.Save) - skipItems(2) + skipItems(3) assertThat(awaitItem().saveAction).isInstanceOf(AsyncAction.Failure::class.java) initialState.eventSink(RoomDetailsEditEvents.CancelSaveChanges) assertThat(awaitItem().saveAction).isInstanceOf(AsyncAction.Uninitialized::class.java) diff --git a/features/roomdetails/impl/src/test/kotlin/io/element/android/features/roomdetails/members/RoomMemberListPresenterTest.kt b/features/roomdetails/impl/src/test/kotlin/io/element/android/features/roomdetails/members/RoomMemberListPresenterTest.kt index a352d8bf27..8ca8b7b810 100644 --- a/features/roomdetails/impl/src/test/kotlin/io/element/android/features/roomdetails/members/RoomMemberListPresenterTest.kt +++ b/features/roomdetails/impl/src/test/kotlin/io/element/android/features/roomdetails/members/RoomMemberListPresenterTest.kt @@ -52,7 +52,10 @@ class RoomMemberListPresenterTest { @Test fun `member loading is done automatically on start, but is async`() = runTest { - val room = FakeMatrixRoom().apply { + val room = FakeMatrixRoom( + updateMembersResult = { Result.success(Unit) }, + canInviteResult = { Result.success(true) } + ).apply { // Needed to avoid discarding the loaded members as a partial and invalid result givenRoomInfo(aRoomInfo(joinedMembersCount = 2)) } @@ -78,7 +81,12 @@ class RoomMemberListPresenterTest { @Test fun `open search`() = runTest { - val presenter = createPresenter() + val presenter = createPresenter( + matrixRoom = FakeMatrixRoom( + updateMembersResult = { Result.success(Unit) }, + canInviteResult = { Result.success(true) } + ) + ) moleculeFlow(RecompositionMode.Immediate) { presenter.present() }.test { @@ -93,7 +101,12 @@ class RoomMemberListPresenterTest { @Test fun `search for something which is not found`() = runTest { - val presenter = createPresenter() + val presenter = createPresenter( + matrixRoom = FakeMatrixRoom( + updateMembersResult = { Result.success(Unit) }, + canInviteResult = { Result.success(true) } + ) + ) moleculeFlow(RecompositionMode.Immediate) { presenter.present() }.test { @@ -112,7 +125,12 @@ class RoomMemberListPresenterTest { @Test fun `search for something which is found`() = runTest { - val presenter = createPresenter() + val presenter = createPresenter( + matrixRoom = FakeMatrixRoom( + updateMembersResult = { Result.success(Unit) }, + canInviteResult = { Result.success(true) } + ) + ) moleculeFlow(RecompositionMode.Immediate) { presenter.present() }.test { @@ -134,9 +152,10 @@ class RoomMemberListPresenterTest { @Test fun `present - asynchronously sets canInvite when user has correct power level`() = runTest { val presenter = createPresenter( - matrixRoom = FakeMatrixRoom().apply { - givenCanInviteResult(Result.success(true)) - } + matrixRoom = FakeMatrixRoom( + canInviteResult = { Result.success(true) }, + updateMembersResult = { Result.success(Unit) } + ) ) moleculeFlow(RecompositionMode.Immediate) { presenter.present() @@ -150,9 +169,10 @@ class RoomMemberListPresenterTest { @Test fun `present - asynchronously sets canInvite when user does not have correct power level`() = runTest { val presenter = createPresenter( - matrixRoom = FakeMatrixRoom().apply { - givenCanInviteResult(Result.success(false)) - } + matrixRoom = FakeMatrixRoom( + canInviteResult = { Result.success(false) }, + updateMembersResult = { Result.success(Unit) } + ) ) moleculeFlow(RecompositionMode.Immediate) { presenter.present() @@ -166,9 +186,10 @@ class RoomMemberListPresenterTest { @Test fun `present - asynchronously sets canInvite when power level check fails`() = runTest { val presenter = createPresenter( - matrixRoom = FakeMatrixRoom().apply { - givenCanInviteResult(Result.failure(Throwable("Eek"))) - } + matrixRoom = FakeMatrixRoom( + canInviteResult = { Result.failure(Throwable("Eek")) }, + updateMembersResult = { Result.success(Unit) } + ) ) moleculeFlow(RecompositionMode.Immediate) { presenter.present() @@ -183,7 +204,14 @@ class RoomMemberListPresenterTest { fun `present - RoomMemberSelected by default opens the room member details through the navigator`() = runTest { val navigator = FakeRoomMemberListNavigator() val moderationPresenter = FakeRoomMembersModerationPresenter(canDisplayModerationActions = false) - val presenter = createPresenter(moderationPresenter = moderationPresenter, navigator = navigator) + val presenter = createPresenter( + moderationPresenter = moderationPresenter, + navigator = navigator, + matrixRoom = FakeMatrixRoom( + updateMembersResult = { Result.success(Unit) }, + canInviteResult = { Result.success(true) } + ) + ) moleculeFlow(RecompositionMode.Immediate) { presenter.present() }.test { @@ -205,7 +233,14 @@ class RoomMemberListPresenterTest { val moderationPresenter = FakeRoomMembersModerationPresenter(canDisplayModerationActions = true).apply { givenState(capturingState) } - val presenter = createPresenter(moderationPresenter = moderationPresenter, navigator = navigator) + val presenter = createPresenter( + moderationPresenter = moderationPresenter, + navigator = navigator, + matrixRoom = FakeMatrixRoom( + updateMembersResult = { Result.success(Unit) }, + canInviteResult = { Result.success(true) } + ) + ) moleculeFlow(RecompositionMode.Immediate) { presenter.present() }.test { @@ -236,10 +271,12 @@ private fun TestScope.createDataSource( @ExperimentalCoroutinesApi private fun TestScope.createPresenter( coroutineDispatchers: CoroutineDispatchers = testCoroutineDispatchers(useUnconfinedTestDispatcher = true), - matrixRoom: MatrixRoom = FakeMatrixRoom(), + matrixRoom: MatrixRoom = FakeMatrixRoom( + updateMembersResult = { Result.success(Unit) } + ), roomMemberListDataSource: RoomMemberListDataSource = createDataSource(coroutineDispatchers = coroutineDispatchers), moderationPresenter: FakeRoomMembersModerationPresenter = FakeRoomMembersModerationPresenter(), - navigator: RoomMemberListNavigator = object : RoomMemberListNavigator { } + navigator: RoomMemberListNavigator = object : RoomMemberListNavigator {} ) = RoomMemberListPresenter( room = matrixRoom, roomMemberListDataSource = roomMemberListDataSource, diff --git a/features/roomdetails/impl/src/test/kotlin/io/element/android/features/roomdetails/members/details/RoomMemberDetailsPresenterTest.kt b/features/roomdetails/impl/src/test/kotlin/io/element/android/features/roomdetails/members/details/RoomMemberDetailsPresenterTest.kt index c9df8d381c..1012de62bd 100644 --- a/features/roomdetails/impl/src/test/kotlin/io/element/android/features/roomdetails/members/details/RoomMemberDetailsPresenterTest.kt +++ b/features/roomdetails/impl/src/test/kotlin/io/element/android/features/roomdetails/members/details/RoomMemberDetailsPresenterTest.kt @@ -34,6 +34,7 @@ import io.element.android.libraries.matrix.api.MatrixClient import io.element.android.libraries.matrix.api.core.UserId import io.element.android.libraries.matrix.api.room.MatrixRoom import io.element.android.libraries.matrix.api.room.MatrixRoomMembersState +import io.element.android.libraries.matrix.test.AN_EXCEPTION import io.element.android.libraries.matrix.test.A_ROOM_ID import io.element.android.libraries.matrix.test.A_THROWABLE import io.element.android.libraries.matrix.test.FakeMatrixClient @@ -53,9 +54,11 @@ class RoomMemberDetailsPresenterTest { @Test fun `present - returns the room member's data, then updates it if needed`() = runTest { val roomMember = aRoomMember(displayName = "Alice") - val room = aMatrixRoom().apply { - givenUserDisplayNameResult(Result.success("A custom name")) - givenUserAvatarUrlResult(Result.success("A custom avatar")) + val room = aMatrixRoom( + userDisplayNameResult = { Result.success("A custom name") }, + userAvatarUrlResult = { Result.success("A custom avatar") }, + getUpdatedMemberResult = { Result.success(roomMember) }, + ).apply { givenRoomMembersState(MatrixRoomMembersState.Ready(persistentListOf(roomMember))) } val presenter = createRoomMemberDetailsPresenter( @@ -82,11 +85,14 @@ class RoomMemberDetailsPresenterTest { @Test fun `present - will recover when retrieving room member details fails`() = runTest { val roomMember = aRoomMember(displayName = "Alice") - val room = aMatrixRoom().apply { - givenUserDisplayNameResult(Result.failure(Throwable())) - givenUserAvatarUrlResult(Result.failure(Throwable())) + val room = aMatrixRoom( + userDisplayNameResult = { Result.failure(Throwable()) }, + userAvatarUrlResult = { Result.failure(Throwable()) }, + getUpdatedMemberResult = { Result.failure(AN_EXCEPTION) }, + ).apply { givenRoomMembersState(MatrixRoomMembersState.Ready(persistentListOf(roomMember))) } + val presenter = createRoomMemberDetailsPresenter( room = room, roomMemberId = roomMember.userId @@ -105,9 +111,11 @@ class RoomMemberDetailsPresenterTest { @Test fun `present - will fallback to original data if the updated data is null`() = runTest { val roomMember = aRoomMember(displayName = "Alice") - val room = aMatrixRoom().apply { - givenUserDisplayNameResult(Result.success(null)) - givenUserAvatarUrlResult(Result.success(null)) + val room = aMatrixRoom( + userDisplayNameResult = { Result.success(null) }, + userAvatarUrlResult = { Result.success(null) }, + getUpdatedMemberResult = { Result.success(roomMember) } + ).apply { givenRoomMembersState(MatrixRoomMembersState.Ready(persistentListOf(roomMember))) } val presenter = createRoomMemberDetailsPresenter( @@ -128,10 +136,11 @@ class RoomMemberDetailsPresenterTest { @Test fun `present - will fallback to user profile if user is not a member of the room`() = runTest { val bobProfile = aMatrixUser("@bob:server.org", "Bob", avatarUrl = "anAvatarUrl") - val room = aMatrixRoom().apply { - givenUserDisplayNameResult(Result.failure(Exception("Not a member!"))) - givenUserAvatarUrlResult(Result.failure(Exception("Not a member!"))) - } + val room = aMatrixRoom( + userDisplayNameResult = { Result.failure(Exception("Not a member!")) }, + userAvatarUrlResult = { Result.failure(Exception("Not a member!")) }, + getUpdatedMemberResult = { Result.failure(AN_EXCEPTION) }, + ) val client = FakeMatrixClient().apply { givenGetProfileResult(bobProfile.userId, Result.success(bobProfile)) } @@ -154,7 +163,13 @@ class RoomMemberDetailsPresenterTest { @Test fun `present - BlockUser needing confirmation displays confirmation dialog`() = runTest { - val presenter = createRoomMemberDetailsPresenter() + val presenter = createRoomMemberDetailsPresenter( + room = aMatrixRoom( + getUpdatedMemberResult = { Result.failure(AN_EXCEPTION) }, + userDisplayNameResult = { Result.success("Alice") }, + userAvatarUrlResult = { Result.success("anAvatarUrl") }, + ) + ) moleculeFlow(RecompositionMode.Immediate) { presenter.present() }.test { @@ -176,6 +191,11 @@ class RoomMemberDetailsPresenterTest { val client = FakeMatrixClient() val roomMember = aRoomMember() val presenter = createRoomMemberDetailsPresenter( + room = aMatrixRoom( + getUpdatedMemberResult = { Result.failure(AN_EXCEPTION) }, + userDisplayNameResult = { Result.success("Alice") }, + userAvatarUrlResult = { Result.success("anAvatarUrl") }, + ), client = client, roomMemberId = roomMember.userId ) @@ -199,13 +219,21 @@ class RoomMemberDetailsPresenterTest { fun `present - BlockUser with error`() = runTest { val matrixClient = FakeMatrixClient() matrixClient.givenIgnoreUserResult(Result.failure(A_THROWABLE)) - val presenter = createRoomMemberDetailsPresenter(client = matrixClient) + val presenter = createRoomMemberDetailsPresenter( + client = matrixClient, + room = aMatrixRoom( + getUpdatedMemberResult = { Result.success(aRoomMember(displayName = "Alice")) }, + userDisplayNameResult = { Result.success("Alice") }, + userAvatarUrlResult = { Result.success("anAvatarUrl") }, + ), + ) moleculeFlow(RecompositionMode.Immediate) { presenter.present() }.test { val initialState = awaitFirstItem() initialState.eventSink(UserProfileEvents.BlockUser(needsConfirmation = false)) assertThat(awaitItem().isBlocked.isLoading()).isTrue() + skipItems(2) val errorState = awaitItem() assertThat(errorState.isBlocked.errorOrNull()).isEqualTo(A_THROWABLE) // Clear error @@ -218,13 +246,21 @@ class RoomMemberDetailsPresenterTest { fun `present - UnblockUser with error`() = runTest { val matrixClient = FakeMatrixClient() matrixClient.givenUnignoreUserResult(Result.failure(A_THROWABLE)) - val presenter = createRoomMemberDetailsPresenter(client = matrixClient) + val presenter = createRoomMemberDetailsPresenter( + room = aMatrixRoom( + getUpdatedMemberResult = { Result.success(aRoomMember(displayName = "Alice")) }, + userDisplayNameResult = { Result.success("Alice") }, + userAvatarUrlResult = { Result.success("anAvatarUrl") }, + ), + client = matrixClient, + ) moleculeFlow(RecompositionMode.Immediate) { presenter.present() }.test { val initialState = awaitFirstItem() initialState.eventSink(UserProfileEvents.UnblockUser(needsConfirmation = false)) assertThat(awaitItem().isBlocked.isLoading()).isTrue() + skipItems(2) val errorState = awaitItem() assertThat(errorState.isBlocked.errorOrNull()).isEqualTo(A_THROWABLE) // Clear error @@ -235,7 +271,13 @@ class RoomMemberDetailsPresenterTest { @Test fun `present - UnblockUser needing confirmation displays confirmation dialog`() = runTest { - val presenter = createRoomMemberDetailsPresenter() + val presenter = createRoomMemberDetailsPresenter( + room = aMatrixRoom( + getUpdatedMemberResult = { Result.failure(AN_EXCEPTION) }, + userDisplayNameResult = { Result.success("Alice") }, + userAvatarUrlResult = { Result.success("anAvatarUrl") }, + ), + ) moleculeFlow(RecompositionMode.Immediate) { presenter.present() }.test { @@ -255,7 +297,14 @@ class RoomMemberDetailsPresenterTest { @Test fun `present - start DM action complete scenario`() = runTest { val startDMAction = FakeStartDMAction() - val presenter = createRoomMemberDetailsPresenter(startDMAction = startDMAction) + val presenter = createRoomMemberDetailsPresenter( + room = aMatrixRoom( + getUpdatedMemberResult = { Result.success(aRoomMember(displayName = "Alice")) }, + userDisplayNameResult = { Result.success("Alice") }, + userAvatarUrlResult = { Result.success("anAvatarUrl") }, + ), + startDMAction = startDMAction, + ) moleculeFlow(RecompositionMode.Immediate) { presenter.present() }.test { @@ -268,6 +317,7 @@ class RoomMemberDetailsPresenterTest { startDMAction.givenExecuteResult(startDMFailureResult) initialState.eventSink(UserProfileEvents.StartDM) assertThat(awaitItem().startDmActionState).isInstanceOf(AsyncAction.Loading::class.java) + skipItems(2) awaitItem().also { state -> assertThat(state.startDmActionState).isEqualTo(startDMFailureResult) state.eventSink(UserProfileEvents.ClearStartDMState) @@ -292,8 +342,8 @@ class RoomMemberDetailsPresenterTest { } private fun createRoomMemberDetailsPresenter( + room: MatrixRoom, client: MatrixClient = FakeMatrixClient(), - room: MatrixRoom = aMatrixRoom(), roomMemberId: UserId = UserId("@alice:server.org"), startDMAction: StartDMAction = FakeStartDMAction() ): RoomMemberDetailsPresenter { diff --git a/features/roomdetails/impl/src/test/kotlin/io/element/android/features/roomdetails/members/moderation/DefaultRoomMembersModerationPresenterTest.kt b/features/roomdetails/impl/src/test/kotlin/io/element/android/features/roomdetails/members/moderation/DefaultRoomMembersModerationPresenterTest.kt index ae789f8958..5f704a23d4 100644 --- a/features/roomdetails/impl/src/test/kotlin/io/element/android/features/roomdetails/members/moderation/DefaultRoomMembersModerationPresenterTest.kt +++ b/features/roomdetails/impl/src/test/kotlin/io/element/android/features/roomdetails/members/moderation/DefaultRoomMembersModerationPresenterTest.kt @@ -54,29 +54,34 @@ class DefaultRoomMembersModerationPresenterTest { @Test fun `canDisplayModerationActions - when user can kick other users, FF is enabled and room is not a DM returns true`() = runTest { - val room = FakeMatrixRoom(isDirect = false, activeMemberCount = 10).apply { - givenCanKickResult(Result.success(true)) - } + val room = FakeMatrixRoom( + isDirect = false, + activeMemberCount = 10, + canKickResult = { Result.success(true) }, + canBanResult = { Result.success(true) }, + ) val presenter = createDefaultRoomMembersModerationPresenter(matrixRoom = room) assertThat(presenter.canDisplayModerationActions()).isTrue() } @Test fun `canDisplayModerationActions - when user can ban other users, FF is enabled and room is not a DM returns true`() = runTest { - val room = FakeMatrixRoom(isDirect = false, activeMemberCount = 10).apply { - givenCanBanResult(Result.success(true)) - } + val room = FakeMatrixRoom( + isDirect = false, + activeMemberCount = 10, + canBanResult = { Result.success(true) }, + ) val presenter = createDefaultRoomMembersModerationPresenter(matrixRoom = room) assertThat(presenter.canDisplayModerationActions()).isTrue() } @Test fun `present - SelectRoomMember when the current user has permissions displays member actions`() = runTest { - val room = FakeMatrixRoom().apply { - givenCanKickResult(Result.success(true)) - givenCanBanResult(Result.success(true)) - givenUserRoleResult(Result.success(RoomMember.Role.ADMIN)) - } + val room = FakeMatrixRoom( + canKickResult = { Result.success(true) }, + canBanResult = { Result.success(true) }, + userRoleResult = { Result.success(RoomMember.Role.ADMIN) }, + ) val selectedMember = aVictor() val presenter = createDefaultRoomMembersModerationPresenter(matrixRoom = room) moleculeFlow(RecompositionMode.Immediate) { @@ -98,11 +103,12 @@ class DefaultRoomMembersModerationPresenterTest { @Test fun `present - SelectRoomMember displays only view profile if selected member has same power level as the current user`() = runTest { - val room = FakeMatrixRoom(sessionId = A_USER_ID).apply { - givenCanKickResult(Result.success(true)) - givenCanBanResult(Result.success(true)) - givenUserRoleResult(Result.success(RoomMember.Role.ADMIN)) - } + val room = FakeMatrixRoom( + sessionId = A_USER_ID, + canKickResult = { Result.success(true) }, + canBanResult = { Result.success(true) }, + userRoleResult = { Result.success(RoomMember.Role.ADMIN) }, + ) val selectedMember = aRoomMember(A_USER_ID_2, powerLevel = 100L) val presenter = createDefaultRoomMembersModerationPresenter(matrixRoom = room) moleculeFlow(RecompositionMode.Immediate) { @@ -123,11 +129,11 @@ class DefaultRoomMembersModerationPresenterTest { @Test fun `present - SelectRoomMember displays an unban confirmation dialog when the member is banned`() = runTest { val selectedMember = aRoomMember(A_USER_ID_2, membership = RoomMembershipState.BAN) - val room = FakeMatrixRoom().apply { - givenCanKickResult(Result.success(true)) - givenCanBanResult(Result.success(true)) - givenUserRoleResult(Result.success(RoomMember.Role.ADMIN)) - } + val room = FakeMatrixRoom( + canKickResult = { Result.success(true) }, + canBanResult = { Result.success(true) }, + userRoleResult = { Result.success(RoomMember.Role.ADMIN) }, + ) val presenter = createDefaultRoomMembersModerationPresenter(matrixRoom = room) moleculeFlow(RecompositionMode.Immediate) { presenter.present() @@ -144,11 +150,12 @@ class DefaultRoomMembersModerationPresenterTest { @Test fun `present - Kick removes the user`() = runTest { val analyticsService = FakeAnalyticsService() - val room = FakeMatrixRoom().apply { - givenCanKickResult(Result.success(true)) - givenCanBanResult(Result.success(true)) - givenUserRoleResult(Result.success(RoomMember.Role.ADMIN)) - } + val room = FakeMatrixRoom( + canKickResult = { Result.success(true) }, + canBanResult = { Result.success(true) }, + userRoleResult = { Result.success(RoomMember.Role.ADMIN) }, + kickUserResult = { _, _ -> Result.success(Unit) }, + ) val selectedMember = aVictor() val presenter = createDefaultRoomMembersModerationPresenter(matrixRoom = room, analyticsService = analyticsService) moleculeFlow(RecompositionMode.Immediate) { @@ -171,11 +178,12 @@ class DefaultRoomMembersModerationPresenterTest { @Test fun `present - BanUser requires confirmation and then bans the user`() = runTest { val analyticsService = FakeAnalyticsService() - val room = FakeMatrixRoom().apply { - givenCanKickResult(Result.success(true)) - givenCanBanResult(Result.success(true)) - givenUserRoleResult(Result.success(RoomMember.Role.ADMIN)) - } + val room = FakeMatrixRoom( + canKickResult = { Result.success(true) }, + canBanResult = { Result.success(true) }, + userRoleResult = { Result.success(RoomMember.Role.ADMIN) }, + banUserResult = { _, _ -> Result.success(Unit) }, + ) val selectedMember = aVictor() val presenter = createDefaultRoomMembersModerationPresenter(matrixRoom = room, analyticsService = analyticsService) moleculeFlow(RecompositionMode.Immediate) { @@ -204,11 +212,13 @@ class DefaultRoomMembersModerationPresenterTest { fun `present - UnbanUser requires confirmation and then unbans the user`() = runTest { val analyticsService = FakeAnalyticsService() val selectedMember = aRoomMember(A_USER_ID_2, membership = RoomMembershipState.BAN) - val room = FakeMatrixRoom().apply { - givenCanKickResult(Result.success(true)) - givenCanBanResult(Result.success(true)) + val room = FakeMatrixRoom( + canKickResult = { Result.success(true) }, + canBanResult = { Result.success(true) }, + userRoleResult = { Result.success(RoomMember.Role.ADMIN) }, + unBanUserResult = { _, _ -> Result.success(Unit) }, + ).apply { givenRoomMembersState(MatrixRoomMembersState.Ready(persistentListOf(selectedMember))) - givenUserRoleResult(Result.success(RoomMember.Role.ADMIN)) } val presenter = createDefaultRoomMembersModerationPresenter(matrixRoom = room, analyticsService = analyticsService) moleculeFlow(RecompositionMode.Immediate) { @@ -231,10 +241,11 @@ class DefaultRoomMembersModerationPresenterTest { @Test fun `present - Reset removes the selected user and actions`() = runTest { - val room = FakeMatrixRoom().apply { - givenCanKickResult(Result.success(true)) - givenCanBanResult(Result.success(true)) - } + val room = FakeMatrixRoom( + canKickResult = { Result.success(true) }, + canBanResult = { Result.success(true) }, + userRoleResult = { Result.success(RoomMember.Role.USER) }, + ) val presenter = createDefaultRoomMembersModerationPresenter(matrixRoom = room) moleculeFlow(RecompositionMode.Immediate) { presenter.present() @@ -251,13 +262,14 @@ class DefaultRoomMembersModerationPresenterTest { @Test fun `present - Reset resets any async actions`() = runTest { - val room = FakeMatrixRoom().apply { - givenCanKickResult(Result.success(true)) - givenCanBanResult(Result.success(true)) - givenKickUserResult(Result.failure(Throwable("Eek"))) - givenBanUserResult(Result.failure(Throwable("Eek"))) - givenUnbanUserResult(Result.failure(Throwable("Eek"))) - } + val room = FakeMatrixRoom( + canKickResult = { Result.success(true) }, + canBanResult = { Result.success(true) }, + kickUserResult = { _, _ -> Result.failure(Throwable("Eek")) }, + banUserResult = { _, _ -> Result.failure(Throwable("Eek")) }, + unBanUserResult = { _, _ -> Result.failure(Throwable("Eek")) }, + userRoleResult = { Result.success(RoomMember.Role.USER) }, + ) val presenter = createDefaultRoomMembersModerationPresenter(matrixRoom = room) moleculeFlow(RecompositionMode.Immediate) { presenter.present() diff --git a/features/roomdetails/impl/src/test/kotlin/io/element/android/features/roomdetails/rolesandpermissions/RolesAndPermissionPresenterTest.kt b/features/roomdetails/impl/src/test/kotlin/io/element/android/features/roomdetails/rolesandpermissions/RolesAndPermissionPresenterTest.kt index 35353f0d1a..c2eb07002c 100644 --- a/features/roomdetails/impl/src/test/kotlin/io/element/android/features/roomdetails/rolesandpermissions/RolesAndPermissionPresenterTest.kt +++ b/features/roomdetails/impl/src/test/kotlin/io/element/android/features/roomdetails/rolesandpermissions/RolesAndPermissionPresenterTest.kt @@ -27,6 +27,7 @@ import io.element.android.libraries.architecture.AsyncAction import io.element.android.libraries.core.coroutine.CoroutineDispatchers import io.element.android.libraries.matrix.api.room.RoomMember import io.element.android.libraries.matrix.test.room.FakeMatrixRoom +import io.element.android.libraries.matrix.test.room.defaultRoomPowerLevels import io.element.android.services.analytics.test.FakeAnalyticsService import io.element.android.tests.testutils.testCoroutineDispatchers import kotlinx.coroutines.ExperimentalCoroutinesApi @@ -67,7 +68,12 @@ class RolesAndPermissionPresenterTest { @OptIn(ExperimentalCoroutinesApi::class) @Test fun `present - DemoteSelfTo changes own role to the specified one`() = runTest(StandardTestDispatcher()) { - val presenter = createRolesAndPermissionsPresenter(dispatchers = testCoroutineDispatchers()) + val presenter = createRolesAndPermissionsPresenter( + dispatchers = testCoroutineDispatchers(), + room = FakeMatrixRoom( + updateUserRoleResult = { Result.success(Unit) } + ), + ) moleculeFlow(RecompositionMode.Immediate) { presenter.present() }.test { @@ -85,9 +91,9 @@ class RolesAndPermissionPresenterTest { @OptIn(ExperimentalCoroutinesApi::class) @Test fun `present - DemoteSelfTo can handle failures and clean them`() = runTest(StandardTestDispatcher()) { - val room = FakeMatrixRoom().apply { - givenUpdateUserRoleResult(Result.failure(Exception("Failed to update role"))) - } + val room = FakeMatrixRoom( + updateUserRoleResult = { Result.failure(Exception("Failed to update role")) } + ) val presenter = createRolesAndPermissionsPresenter(room = room, dispatchers = testCoroutineDispatchers()) moleculeFlow(RecompositionMode.Immediate) { presenter.present() @@ -123,7 +129,12 @@ class RolesAndPermissionPresenterTest { @Test fun `present - ResetPermissions needs confirmation, then resets permissions`() = runTest { val analyticsService = FakeAnalyticsService() - val presenter = createRolesAndPermissionsPresenter(analyticsService = analyticsService) + val presenter = createRolesAndPermissionsPresenter( + analyticsService = analyticsService, + room = FakeMatrixRoom( + resetPowerLevelsResult = { Result.success(defaultRoomPowerLevels()) } + ) + ) moleculeFlow(RecompositionMode.Immediate) { presenter.present() }.test { diff --git a/features/roomdetails/impl/src/test/kotlin/io/element/android/features/roomdetails/rolesandpermissions/changeroles/ChangeRolesPresenterTest.kt b/features/roomdetails/impl/src/test/kotlin/io/element/android/features/roomdetails/rolesandpermissions/changeroles/ChangeRolesPresenterTest.kt index d4155d9924..71223c8ff3 100644 --- a/features/roomdetails/impl/src/test/kotlin/io/element/android/features/roomdetails/rolesandpermissions/changeroles/ChangeRolesPresenterTest.kt +++ b/features/roomdetails/impl/src/test/kotlin/io/element/android/features/roomdetails/rolesandpermissions/changeroles/ChangeRolesPresenterTest.kt @@ -275,7 +275,10 @@ class ChangeRolesPresenterTest { @Test fun `present - Save will display a confirmation when adding admins`() = runTest { - val room = FakeMatrixRoom().apply { + val room = FakeMatrixRoom( + updateUserRoleResult = { Result.success(Unit) }, + updateMembersResult = { Result.success(Unit) }, + ).apply { givenRoomMembersState(MatrixRoomMembersState.Ready(aRoomMemberList())) givenRoomInfo(aRoomInfo(userPowerLevels = persistentMapOf(A_USER_ID to 100))) } @@ -325,7 +328,10 @@ class ChangeRolesPresenterTest { @Test fun `present - Save will just save the data for moderators`() = runTest { val analyticsService = FakeAnalyticsService() - val room = FakeMatrixRoom().apply { + val room = FakeMatrixRoom( + updateUserRoleResult = { Result.success(Unit) }, + updateMembersResult = { Result.success(Unit) }, + ).apply { givenRoomMembersState(MatrixRoomMembersState.Ready(aRoomMemberList())) givenRoomInfo(aRoomInfo(userPowerLevels = persistentMapOf(A_USER_ID to 50))) } @@ -351,10 +357,11 @@ class ChangeRolesPresenterTest { @Test fun `present - Save can handle failures and ClearError clears them`() = runTest { - val room = FakeMatrixRoom().apply { + val room = FakeMatrixRoom( + updateUserRoleResult = { Result.failure(IllegalStateException("Failed")) } + ).apply { givenRoomMembersState(MatrixRoomMembersState.Ready(aRoomMemberList())) givenRoomInfo(aRoomInfo(userPowerLevels = persistentMapOf(A_USER_ID to 50))) - givenUpdateUserRoleResult(Result.failure(IllegalStateException("Failed"))) } val presenter = createChangeRolesPresenter(role = RoomMember.Role.MODERATOR, room = room) moleculeFlow(RecompositionMode.Immediate) { diff --git a/features/roomdetails/impl/src/test/kotlin/io/element/android/features/roomdetails/rolesandpermissions/permissions/ChangeRoomPermissionsPresenterTest.kt b/features/roomdetails/impl/src/test/kotlin/io/element/android/features/roomdetails/rolesandpermissions/permissions/ChangeRoomPermissionsPresenterTest.kt index c37d458d67..5d2ae18783 100644 --- a/features/roomdetails/impl/src/test/kotlin/io/element/android/features/roomdetails/rolesandpermissions/permissions/ChangeRoomPermissionsPresenterTest.kt +++ b/features/roomdetails/impl/src/test/kotlin/io/element/android/features/roomdetails/rolesandpermissions/permissions/ChangeRoomPermissionsPresenterTest.kt @@ -164,7 +164,13 @@ class ChangeRoomPermissionsPresenterTest { @Test fun `present - Save updates the current permissions and resets hasChanges`() = runTest { val analyticsService = FakeAnalyticsService() - val presenter = createChangeRoomPermissionsPresenter(analyticsService = analyticsService) + val presenter = createChangeRoomPermissionsPresenter( + analyticsService = analyticsService, + room = FakeMatrixRoom( + updatePowerLevelsResult = { Result.success(Unit) }, + powerLevelsResult = { Result.success(defaultPermissions()) } + ), + ) moleculeFlow(RecompositionMode.Immediate) { presenter.present() }.test { @@ -208,9 +214,9 @@ class ChangeRoomPermissionsPresenterTest { @Test fun `present - Save will fail if there are not current permissions`() = runTest { - val room = FakeMatrixRoom().apply { - givenPowerLevelsResult(Result.failure(IllegalStateException("Failed to load power levels"))) - } + val room = FakeMatrixRoom( + powerLevelsResult = { Result.failure(IllegalStateException("Failed to load power levels")) } + ) val presenter = createChangeRoomPermissionsPresenter(room = room) moleculeFlow(RecompositionMode.Immediate) { presenter.present() @@ -225,9 +231,10 @@ class ChangeRoomPermissionsPresenterTest { @Test fun `present - Save can handle failures and they can be cleared`() = runTest { - val room = FakeMatrixRoom().apply { - givenUpdatePowerLevelsResult(Result.failure(IllegalStateException("Failed to update power levels"))) - } + val room = FakeMatrixRoom( + powerLevelsResult = { Result.success(defaultPermissions()) }, + updatePowerLevelsResult = { Result.failure(IllegalStateException("Failed to update power levels")) }, + ) val presenter = createChangeRoomPermissionsPresenter(room = room) moleculeFlow(RecompositionMode.Immediate) { presenter.present() @@ -292,7 +299,9 @@ class ChangeRoomPermissionsPresenterTest { private fun createChangeRoomPermissionsPresenter( section: ChangeRoomPermissionsSection = ChangeRoomPermissionsSection.RoomDetails, - room: FakeMatrixRoom = FakeMatrixRoom(), + room: FakeMatrixRoom = FakeMatrixRoom( + powerLevelsResult = { Result.success(defaultPermissions()) } + ), analyticsService: FakeAnalyticsService = FakeAnalyticsService(), ) = ChangeRoomPermissionsPresenter( section = section, diff --git a/features/roomlist/impl/src/test/kotlin/io/element/android/features/roomlist/impl/RoomListPresenterTest.kt b/features/roomlist/impl/src/test/kotlin/io/element/android/features/roomlist/impl/RoomListPresenterTest.kt index b48a603a85..7a9a8b2744 100644 --- a/features/roomlist/impl/src/test/kotlin/io/element/android/features/roomlist/impl/RoomListPresenterTest.kt +++ b/features/roomlist/impl/src/test/kotlin/io/element/android/features/roomlist/impl/RoomListPresenterTest.kt @@ -441,7 +441,10 @@ class RoomListPresenterTest { @Test fun `present - when set is favorite event is emitted, then the action is called`() = runTest { val scope = CoroutineScope(coroutineContext + SupervisorJob()) - val room = FakeMatrixRoom() + val setIsFavoriteResult = lambdaRecorder { _: Boolean -> Result.success(Unit) } + val room = FakeMatrixRoom( + setIsFavoriteResult = setIsFavoriteResult + ) val analyticsService = FakeAnalyticsService() val client = FakeMatrixClient().apply { givenGetRoomResult(A_ROOM_ID, room) @@ -452,9 +455,13 @@ class RoomListPresenterTest { }.test { val initialState = awaitItem() initialState.eventSink(RoomListEvents.SetRoomIsFavorite(A_ROOM_ID, true)) - assertThat(room.setIsFavoriteCalls).isEqualTo(listOf(true)) + setIsFavoriteResult.assertions().isCalledOnce().with(value(true)) initialState.eventSink(RoomListEvents.SetRoomIsFavorite(A_ROOM_ID, false)) - assertThat(room.setIsFavoriteCalls).isEqualTo(listOf(true, false)) + setIsFavoriteResult.assertions().isCalledExactly(2) + .withSequence( + listOf(value(true)), + listOf(value(false)), + ) assertThat(analyticsService.capturedEvents).containsExactly( Interaction(name = Interaction.Name.MobileRoomListRoomContextMenuFavouriteToggle), Interaction(name = Interaction.Name.MobileRoomListRoomContextMenuFavouriteToggle) diff --git a/features/share/impl/src/test/kotlin/io/element/android/features/share/impl/SharePresenterTest.kt b/features/share/impl/src/test/kotlin/io/element/android/features/share/impl/SharePresenterTest.kt index 42c053bafb..8c91ea530c 100644 --- a/features/share/impl/src/test/kotlin/io/element/android/features/share/impl/SharePresenterTest.kt +++ b/features/share/impl/src/test/kotlin/io/element/android/features/share/impl/SharePresenterTest.kt @@ -28,6 +28,7 @@ import io.element.android.libraries.matrix.api.MatrixClient import io.element.android.libraries.matrix.test.A_MESSAGE import io.element.android.libraries.matrix.test.A_ROOM_ID import io.element.android.libraries.matrix.test.FakeMatrixClient +import io.element.android.libraries.matrix.test.media.FakeMediaUploadHandler import io.element.android.libraries.matrix.test.room.FakeMatrixRoom import io.element.android.libraries.mediaupload.api.MediaPreProcessor import io.element.android.libraries.mediaupload.test.FakeMediaPreProcessor @@ -92,7 +93,9 @@ class SharePresenterTest { @Test fun `present - send text ok`() = runTest { - val matrixRoom = FakeMatrixRoom() + val matrixRoom = FakeMatrixRoom( + sendMessageResult = { _, _, _ -> Result.success(Unit) }, + ) val matrixClient = FakeMatrixClient().apply { givenGetRoomResult(A_ROOM_ID, matrixRoom) } @@ -117,7 +120,9 @@ class SharePresenterTest { @Test fun `present - send media ok`() = runTest { - val matrixRoom = FakeMatrixRoom() + val matrixRoom = FakeMatrixRoom( + sendMediaResult = { Result.success(FakeMediaUploadHandler()) }, + ) val matrixClient = FakeMatrixClient().apply { givenGetRoomResult(A_ROOM_ID, matrixRoom) } diff --git a/gradle.properties b/gradle.properties index 9808f9eda1..b1f6468108 100644 --- a/gradle.properties +++ b/gradle.properties @@ -49,7 +49,7 @@ signing.element.nightly.keyPassword=Secret # Customise the Lint version to use a more recent version than the one bundled with AGP # https://googlesamples.github.io/android-custom-lint-rules/usage/newer-lint.md.html -android.experimental.lint.version=8.5.0-alpha07 +android.experimental.lint.version=8.7.0-alpha01 # Enable test fixture for all modules by default android.experimental.enableTestFixtures=true diff --git a/libraries/matrix/test/src/main/kotlin/io/element/android/libraries/matrix/test/room/FakeMatrixRoom.kt b/libraries/matrix/test/src/main/kotlin/io/element/android/libraries/matrix/test/room/FakeMatrixRoom.kt index d7a4b105b4..21c50e51a4 100644 --- a/libraries/matrix/test/src/main/kotlin/io/element/android/libraries/matrix/test/room/FakeMatrixRoom.kt +++ b/libraries/matrix/test/src/main/kotlin/io/element/android/libraries/matrix/test/room/FakeMatrixRoom.kt @@ -56,7 +56,7 @@ import io.element.android.libraries.matrix.test.A_SESSION_ID import io.element.android.libraries.matrix.test.media.FakeMediaUploadHandler import io.element.android.libraries.matrix.test.notificationsettings.FakeNotificationSettingsService import io.element.android.libraries.matrix.test.timeline.FakeTimeline -import io.element.android.libraries.matrix.test.widget.FakeMatrixWidgetDriver +import io.element.android.tests.testutils.lambda.lambdaError import io.element.android.tests.testutils.simulateLongTask import kotlinx.collections.immutable.ImmutableMap import kotlinx.collections.immutable.persistentMapOf @@ -84,126 +84,88 @@ class FakeMatrixRoom( override val activeMemberCount: Long = 234L, val notificationSettingsService: NotificationSettingsService = FakeNotificationSettingsService(), override val liveTimeline: Timeline = FakeTimeline(), - private var roomPermalinkResult: () -> Result = { Result.success("room link") }, - private var eventPermalinkResult: (EventId) -> Result = { Result.success("event link") }, - var sendCallNotificationIfNeededResult: () -> Result = { Result.success(Unit) }, - canRedactOwn: Boolean = false, - canRedactOther: Boolean = false, + private var roomPermalinkResult: () -> Result = { lambdaError() }, + private var eventPermalinkResult: (EventId) -> Result = { lambdaError() }, + private val sendCallNotificationIfNeededResult: () -> Result = { lambdaError() }, + private val userDisplayNameResult: () -> Result = { lambdaError() }, + private val userAvatarUrlResult: () -> Result = { lambdaError() }, + private val userRoleResult: () -> Result = { lambdaError() }, + private val getUpdatedMemberResult: (UserId) -> Result = { lambdaError() }, + private val joinRoomResult: () -> Result = { lambdaError() }, + private val inviteUserResult: (UserId) -> Result = { lambdaError() }, + private val canInviteResult: (UserId) -> Result = { lambdaError() }, + private val canKickResult: (UserId) -> Result = { lambdaError() }, + private val canBanResult: (UserId) -> Result = { lambdaError() }, + private val canRedactOwnResult: (UserId) -> Result = { lambdaError() }, + private val canRedactOtherResult: (UserId) -> Result = { lambdaError() }, + private val canSendStateResult: (UserId, StateEventType) -> Result = { _, _ -> lambdaError() }, + private val canUserSendMessageResult: (UserId, MessageEventType) -> Result = { _, _ -> lambdaError() }, + private val sendMediaResult: (ProgressCallback?) -> Result = { lambdaError() }, + private val setNameResult: (String) -> Result = { lambdaError() }, + private val setTopicResult: (String) -> Result = { lambdaError() }, + private val updateAvatarResult: (String, ByteArray) -> Result = { _, _ -> lambdaError() }, + private val removeAvatarResult: () -> Result = { lambdaError() }, + private val sendMessageResult: (String, String?, List) -> Result = { _, _, _ -> lambdaError() }, + private val updateUserRoleResult: () -> Result = { lambdaError() }, + private val toggleReactionResult: (String, EventId) -> Result = { _, _ -> lambdaError() }, + private val retrySendMessageResult: (TransactionId) -> Result = { lambdaError() }, + private val cancelSendResult: (TransactionId) -> Result = { lambdaError() }, + private val forwardEventResult: (EventId, List) -> Result = { _, _ -> lambdaError() }, + private val reportContentResult: (EventId, String, UserId?) -> Result = { _, _, _ -> lambdaError() }, + private val kickUserResult: (UserId, String?) -> Result = { _, _ -> lambdaError() }, + private val banUserResult: (UserId, String?) -> Result = { _, _ -> lambdaError() }, + private val unBanUserResult: (UserId, String?) -> Result = { _, _ -> lambdaError() }, + private val sendLocationResult: (String, String, String?, Int?, AssetType?) -> Result = { _, _, _, _, _ -> lambdaError() }, + private val createPollResult: (String, List, Int, PollKind) -> Result = { _, _, _, _ -> lambdaError() }, + private val editPollResult: (EventId, String, List, Int, PollKind) -> Result = { _, _, _, _, _ -> lambdaError() }, + private val sendPollResponseResult: (EventId, List) -> Result = { _, _ -> lambdaError() }, + private val endPollResult: (EventId, String) -> Result = { _, _ -> lambdaError() }, + private val progressCallbackValues: List> = emptyList(), + private val generateWidgetWebViewUrlResult: (MatrixWidgetSettings, String, String?, String?) -> Result = { _, _, _, _ -> lambdaError() }, + private val getWidgetDriverResult: (MatrixWidgetSettings) -> Result = { lambdaError() }, + private val canUserTriggerRoomNotificationResult: (UserId) -> Result = { lambdaError() }, + private val canUserJoinCallResult: (UserId) -> Result = { lambdaError() }, + private val setIsFavoriteResult: (Boolean) -> Result = { lambdaError() }, + private val powerLevelsResult: () -> Result = { lambdaError() }, + private val updatePowerLevelsResult: () -> Result = { lambdaError() }, + private val resetPowerLevelsResult: () -> Result = { lambdaError() }, + private val typingNoticeResult: (Boolean) -> Result = { lambdaError() }, + private val leaveRoomLambda: () -> Result = { lambdaError() }, + private val updateMembersResult: () -> Unit = { lambdaError() }, + private val getMembersResult: (Int) -> Result> = { lambdaError() }, + private val timelineFocusedOnEventResult: (EventId) -> Result = { lambdaError() }, + private val setSendQueueEnabledLambda: (Boolean) -> Unit = { _: Boolean -> }, + private val saveComposerDraftLambda: (ComposerDraft) -> Result = { _: ComposerDraft -> Result.success(Unit) }, + private val loadComposerDraftLambda: () -> Result = { Result.success(null) }, + private val clearComposerDraftLambda: () -> Result = { Result.success(Unit) }, ) : MatrixRoom { - private var ignoreResult: Result = Result.success(Unit) - private var unignoreResult: Result = Result.success(Unit) - private var userDisplayNameResult = Result.success(null) - private var userAvatarUrlResult = Result.success(null) - private var userRoleResult = Result.success(RoomMember.Role.USER) - private var getRoomMemberResult = Result.failure(IllegalStateException("Member not found")) - private var joinRoomResult = Result.success(Unit) - private var inviteUserResult = Result.success(Unit) - private var canInviteResult = Result.success(true) - private var canKickResult = Result.success(false) - private var canBanResult = Result.success(false) - private var canRedactOwnResult = Result.success(canRedactOwn) - private var canRedactOtherResult = Result.success(canRedactOther) - private val canSendStateResults = mutableMapOf>() - private val canSendEventResults = mutableMapOf>() - private var sendMediaResult = Result.success(FakeMediaUploadHandler()) - private var setNameResult = Result.success(Unit) - private var setTopicResult = Result.success(Unit) - private var updateAvatarResult = Result.success(Unit) - private var removeAvatarResult = Result.success(Unit) - private var updateUserRoleResult = Result.success(Unit) - private var toggleReactionResult = Result.success(Unit) - private var retrySendMessageResult = Result.success(Unit) - private var cancelSendResult = Result.success(true) - private var forwardEventResult = Result.success(Unit) - private var reportContentResult = Result.success(Unit) - private var kickUserResult = Result.success(Unit) - private var banUserResult = Result.success(Unit) - private var unBanUserResult = Result.success(Unit) - private var sendLocationResult = Result.success(Unit) - private var createPollResult = Result.success(Unit) - private var editPollResult = Result.success(Unit) - private var sendPollResponseResult = Result.success(Unit) - private var endPollResult = Result.success(Unit) - private var progressCallbackValues = emptyList>() - private var generateWidgetWebViewUrlResult = Result.success("https://call.element.io") - private var getWidgetDriverResult: Result = Result.success(FakeMatrixWidgetDriver()) - private var canUserTriggerRoomNotificationResult: Result = Result.success(true) - private var canUserJoinCallResult: Result = Result.success(true) - private var setIsFavoriteResult = Result.success(Unit) - private var powerLevelsResult = Result.success(defaultRoomPowerLevels()) - private var updatePowerLevelsResult = Result.success(Unit) - private var resetPowerLevelsResult = Result.success(defaultRoomPowerLevels()) - var sendMessageMentions = emptyList() - private val _typingRecord = mutableListOf() - val typingRecord: List - get() = _typingRecord - - var sendMediaCount = 0 - private set - - private val _myReactions = mutableSetOf() - val myReactions: Set = _myReactions - - var retrySendMessageCount: Int = 0 - private set - - var cancelSendCount: Int = 0 - private set - - var reportedContentCount: Int = 0 - private set - - private val _sentLocations = mutableListOf() - val sentLocations: List = _sentLocations - - private val _createPollInvocations = mutableListOf() - val createPollInvocations: List = _createPollInvocations - - private val _editPollInvocations = mutableListOf() - val editPollInvocations: List = _editPollInvocations - - private val _sendPollResponseInvocations = mutableListOf() - val sendPollResponseInvocations: List = _sendPollResponseInvocations - - private val _endPollInvocations = mutableListOf() - val endPollInvocations: List = _endPollInvocations - - var invitedUserId: UserId? = null - private set - - var newTopic: String? = null - private set - - var newName: String? = null - private set - - var newAvatarData: ByteArray? = null - private set - - var removedAvatar: Boolean = false - private set - - var leaveRoomLambda: (() -> Result) = { Result.success(Unit) } - private val _roomInfoFlow: MutableSharedFlow = MutableSharedFlow(replay = 1) override val roomInfoFlow: Flow = _roomInfoFlow + fun givenRoomInfo(roomInfo: MatrixRoomInfo) { + _roomInfoFlow.tryEmit(roomInfo) + } + private val _roomTypingMembersFlow: MutableSharedFlow> = MutableSharedFlow(replay = 1) override val roomTypingMembersFlow: Flow> = _roomTypingMembersFlow + fun givenRoomTypingMembers(typingMembers: List) { + _roomTypingMembersFlow.tryEmit(typingMembers) + } + override val membersStateFlow: MutableStateFlow = MutableStateFlow(MatrixRoomMembersState.Unknown) override val roomNotificationSettingsStateFlow: MutableStateFlow = MutableStateFlow(MatrixRoomNotificationSettingsState.Unknown) - override suspend fun updateMembers() = Unit + override suspend fun updateMembers() = updateMembersResult() override suspend fun getUpdatedMember(userId: UserId): Result { - return getRoomMemberResult + return getUpdatedMemberResult(userId) } override suspend fun getMembers(limit: Int): Result> { - return Result.success(emptyList()) + return getMembersResult(limit) } override suspend fun updateRoomNotificationSettings(): Result = simulateLongTask { @@ -214,76 +176,56 @@ class FakeMatrixRoom( override val syncUpdateFlow: StateFlow = MutableStateFlow(0L) - private var timelineFocusedOnEventResult: Result = Result.success(FakeTimeline()) - - fun givenTimelineFocusedOnEventResult(result: Result) { - timelineFocusedOnEventResult = result - } - override suspend fun timelineFocusedOnEvent(eventId: EventId): Result = simulateLongTask { - timelineFocusedOnEventResult + timelineFocusedOnEventResult(eventId) } override suspend fun subscribeToSync() = Unit override suspend fun powerLevels(): Result { - return powerLevelsResult + return powerLevelsResult() } override suspend fun updatePowerLevels(matrixRoomPowerLevels: MatrixRoomPowerLevels): Result = simulateLongTask { - updatePowerLevelsResult + updatePowerLevelsResult() } override suspend fun resetPowerLevels(): Result = simulateLongTask { - resetPowerLevelsResult + resetPowerLevelsResult() } override fun destroy() = Unit override suspend fun userDisplayName(userId: UserId): Result = simulateLongTask { - userDisplayNameResult + userDisplayNameResult() } override suspend fun userAvatarUrl(userId: UserId): Result = simulateLongTask { - userAvatarUrlResult + userAvatarUrlResult() } override suspend fun userRole(userId: UserId): Result { - return userRoleResult + return userRoleResult() } override suspend fun updateUsersRoles(changes: List): Result { - return updateUserRoleResult + return updateUserRoleResult() } override suspend fun sendMessage(body: String, htmlBody: String?, mentions: List) = simulateLongTask { - sendMessageMentions = mentions - Result.success(Unit) + sendMessageResult(body, htmlBody, mentions) } override suspend fun toggleReaction(emoji: String, eventId: EventId): Result { - if (toggleReactionResult.isFailure) { - // Don't do the toggle if we failed - return toggleReactionResult - } - - if (_myReactions.contains(emoji)) { - _myReactions.remove(emoji) - } else { - _myReactions.add(emoji) - } - - return toggleReactionResult + return toggleReactionResult(emoji, eventId) } override suspend fun retrySendMessage(transactionId: TransactionId): Result { - retrySendMessageCount++ - return retrySendMessageResult + return retrySendMessageResult(transactionId) } override suspend fun cancelSend(transactionId: TransactionId): Result { - cancelSendCount++ - return cancelSendResult + return cancelSendResult(transactionId) } override suspend fun getPermalink(): Result { @@ -299,48 +241,47 @@ class FakeMatrixRoom( } override suspend fun join(): Result { - return joinRoomResult + return joinRoomResult() } override suspend fun inviteUserById(id: UserId): Result = simulateLongTask { - invitedUserId = id - inviteUserResult + inviteUserResult(id) } override suspend fun canUserBan(userId: UserId): Result { - return canBanResult + return canBanResult(userId) } override suspend fun canUserKick(userId: UserId): Result { - return canKickResult + return canKickResult(userId) } override suspend fun canUserInvite(userId: UserId): Result { - return canInviteResult + return canInviteResult(userId) } override suspend fun canUserRedactOwn(userId: UserId): Result { - return canRedactOwnResult + return canRedactOwnResult(userId) } override suspend fun canUserRedactOther(userId: UserId): Result { - return canRedactOtherResult + return canRedactOtherResult(userId) } override suspend fun canUserSendState(userId: UserId, type: StateEventType): Result { - return canSendStateResults[type] ?: Result.failure(IllegalStateException("No fake answer")) + return canSendStateResult(userId, type) } override suspend fun canUserSendMessage(userId: UserId, type: MessageEventType): Result { - return canSendEventResults[type] ?: Result.failure(IllegalStateException("No fake answer")) + return canUserSendMessageResult(userId, type) } override suspend fun canUserTriggerRoomNotification(userId: UserId): Result { - return canUserTriggerRoomNotificationResult + return canUserTriggerRoomNotificationResult(userId) } override suspend fun canUserJoinCall(userId: UserId): Result { - return canUserJoinCallResult + return canUserJoinCallResult(userId) } override suspend fun sendImage( @@ -376,37 +317,31 @@ class FakeMatrixRoom( ): Result = fakeSendMedia(progressCallback) override suspend fun forwardEvent(eventId: EventId, roomIds: List): Result = simulateLongTask { - forwardEventResult + forwardEventResult(eventId, roomIds) } private suspend fun fakeSendMedia(progressCallback: ProgressCallback?): Result = simulateLongTask { - sendMediaResult.onSuccess { - progressCallbackValues.forEach { (current, total) -> - progressCallback?.onProgress(current, total) - delay(1) - } - sendMediaCount++ + progressCallbackValues.forEach { (current, total) -> + progressCallback?.onProgress(current, total) + delay(1) } + sendMediaResult(progressCallback) } override suspend fun updateAvatar(mimeType: String, data: ByteArray): Result = simulateLongTask { - newAvatarData = data - updateAvatarResult + updateAvatarResult(mimeType, data) } override suspend fun removeAvatar(): Result = simulateLongTask { - removedAvatar = true - removeAvatarResult + removeAvatarResult() } override suspend fun setName(name: String): Result = simulateLongTask { - newName = name - setNameResult + setNameResult(name) } override suspend fun setTopic(topic: String): Result = simulateLongTask { - newTopic = topic - setTopicResult + setTopicResult(topic) } override suspend fun reportContent( @@ -414,28 +349,23 @@ class FakeMatrixRoom( reason: String, blockUserId: UserId? ): Result = simulateLongTask { - reportedContentCount++ - return reportContentResult + return reportContentResult(eventId, reason, blockUserId) } override suspend fun kickUser(userId: UserId, reason: String?): Result { - return kickUserResult + return kickUserResult(userId, reason) } override suspend fun banUser(userId: UserId, reason: String?): Result { - return banUserResult + return banUserResult(userId, reason) } override suspend fun unbanUser(userId: UserId, reason: String?): Result { - return unBanUserResult + return unBanUserResult(userId, reason) } - val setIsFavoriteCalls = mutableListOf() - override suspend fun setIsFavorite(isFavorite: Boolean): Result { - return setIsFavoriteResult.also { - setIsFavoriteCalls.add(isFavorite) - } + return setIsFavoriteResult(isFavorite) } val markAsReadCalls = mutableListOf() @@ -460,8 +390,13 @@ class FakeMatrixRoom( zoomLevel: Int?, assetType: AssetType?, ): Result = simulateLongTask { - _sentLocations.add(SendLocationInvocation(body, geoUri, description, zoomLevel, assetType)) - return sendLocationResult + return sendLocationResult( + body, + geoUri, + description, + zoomLevel, + assetType, + ) } override suspend fun createPoll( @@ -470,8 +405,12 @@ class FakeMatrixRoom( maxSelections: Int, pollKind: PollKind ): Result = simulateLongTask { - _createPollInvocations.add(SavePollInvocation(question, answers, maxSelections, pollKind)) - return createPollResult + return createPollResult( + question, + answers, + maxSelections, + pollKind, + ) } override suspend fun editPoll( @@ -481,24 +420,27 @@ class FakeMatrixRoom( maxSelections: Int, pollKind: PollKind ): Result = simulateLongTask { - _editPollInvocations.add(SavePollInvocation(question, answers, maxSelections, pollKind)) - return editPollResult + return editPollResult( + pollStartId, + question, + answers, + maxSelections, + pollKind, + ) } override suspend fun sendPollResponse( pollStartId: EventId, answers: List ): Result = simulateLongTask { - _sendPollResponseInvocations.add(SendPollResponseInvocation(pollStartId, answers)) - return sendPollResponseResult + return sendPollResponseResult(pollStartId, answers) } override suspend fun endPoll( pollStartId: EventId, text: String ): Result = simulateLongTask { - _endPollInvocations.add(EndPollInvocation(pollStartId, text)) - return endPollResult + return endPollResult(pollStartId, text) } override suspend fun sendVoiceMessage( @@ -509,8 +451,7 @@ class FakeMatrixRoom( ): Result = fakeSendMedia(progressCallback) override suspend fun typingNotice(isTyping: Boolean): Result { - _typingRecord += isTyping - return Result.success(Unit) + return typingNoticeResult(isTyping) } override suspend fun generateWidgetWebViewUrl( @@ -518,228 +459,34 @@ class FakeMatrixRoom( clientId: String, languageTag: String?, theme: String?, - ): Result = generateWidgetWebViewUrlResult + ): Result = generateWidgetWebViewUrlResult( + widgetSettings, + clientId, + languageTag, + theme, + ) override suspend fun sendCallNotificationIfNeeded(): Result { return sendCallNotificationIfNeededResult() } - var setSendQueueEnabledLambda = { _: Boolean -> } override suspend fun setSendQueueEnabled(enabled: Boolean) = setSendQueueEnabledLambda(enabled) - var saveComposerDraftLambda = { _: ComposerDraft -> Result.success(Unit) } override suspend fun saveComposerDraft(composerDraft: ComposerDraft) = saveComposerDraftLambda(composerDraft) - var loadComposerDraftLambda = { Result.success(null) } override suspend fun loadComposerDraft() = loadComposerDraftLambda() - var clearComposerDraftLambda = { Result.success(Unit) } override suspend fun clearComposerDraft() = clearComposerDraftLambda() - override fun getWidgetDriver(widgetSettings: MatrixWidgetSettings): Result = getWidgetDriverResult + override fun getWidgetDriver(widgetSettings: MatrixWidgetSettings): Result { + return getWidgetDriverResult(widgetSettings) + } fun givenRoomMembersState(state: MatrixRoomMembersState) { membersStateFlow.value = state } - - fun givenGetRoomMemberResult(result: Result) { - getRoomMemberResult = result - } - - fun givenUserDisplayNameResult(displayName: Result) { - userDisplayNameResult = displayName - } - - fun givenUserAvatarUrlResult(avatarUrl: Result) { - userAvatarUrlResult = avatarUrl - } - - fun givenUserRoleResult(role: Result) { - userRoleResult = role - } - - fun givenUpdateUserRoleResult(result: Result) { - updateUserRoleResult = result - } - - fun givenJoinRoomResult(result: Result) { - joinRoomResult = result - } - - fun givenCanKickResult(result: Result) { - canKickResult = result - } - - fun givenCanBanResult(result: Result) { - canBanResult = result - } - - fun givenInviteUserResult(result: Result) { - inviteUserResult = result - } - - fun givenCanInviteResult(result: Result) { - canInviteResult = result - } - - fun givenCanSendStateResult(type: StateEventType, result: Result) { - canSendStateResults[type] = result - } - - fun givenCanSendEventResult(type: MessageEventType, result: Result) { - canSendEventResults[type] = result - } - - fun givenCanTriggerRoomNotification(result: Result) { - canUserTriggerRoomNotificationResult = result - } - - fun givenCanUserJoinCall(result: Result) { - canUserJoinCallResult = result - } - - fun givenIgnoreResult(result: Result) { - ignoreResult = result - } - - fun givenUnIgnoreResult(result: Result) { - unignoreResult = result - } - - fun givenSendMediaResult(result: Result) { - sendMediaResult = result - } - - fun givenUpdateAvatarResult(result: Result) { - updateAvatarResult = result - } - - fun givenRemoveAvatarResult(result: Result) { - removeAvatarResult = result - } - - fun givenSetNameResult(result: Result) { - setNameResult = result - } - - fun givenSetTopicResult(result: Result) { - setTopicResult = result - } - - fun givenToggleReactionResult(result: Result) { - toggleReactionResult = result - } - - fun givenRetrySendMessageResult(result: Result) { - retrySendMessageResult = result - } - - fun givenCancelSendResult(result: Result) { - cancelSendResult = result - } - - fun givenForwardEventResult(result: Result) { - forwardEventResult = result - } - - fun givenReportContentResult(result: Result) { - reportContentResult = result - } - - fun givenKickUserResult(result: Result) { - kickUserResult = result - } - - fun givenBanUserResult(result: Result) { - banUserResult = result - } - - fun givenUnbanUserResult(result: Result) { - unBanUserResult = result - } - - fun givenSendLocationResult(result: Result) { - sendLocationResult = result - } - - fun givenCreatePollResult(result: Result) { - createPollResult = result - } - - fun givenEditPollResult(result: Result) { - editPollResult = result - } - - fun givenSendPollResponseResult(result: Result) { - sendPollResponseResult = result - } - - fun givenEndPollResult(result: Result) { - endPollResult = result - } - - fun givenProgressCallbackValues(values: List>) { - progressCallbackValues = values - } - - fun givenGenerateWidgetWebViewUrlResult(result: Result) { - generateWidgetWebViewUrlResult = result - } - - fun givenGetWidgetDriverResult(result: Result) { - getWidgetDriverResult = result - } - - fun givenSetIsFavoriteResult(result: Result) { - setIsFavoriteResult = result - } - - fun givenRoomInfo(roomInfo: MatrixRoomInfo) { - _roomInfoFlow.tryEmit(roomInfo) - } - - fun givenRoomTypingMembers(typingMembers: List) { - _roomTypingMembersFlow.tryEmit(typingMembers) - } - - fun givenPowerLevelsResult(result: Result) { - powerLevelsResult = result - } - - fun givenUpdatePowerLevelsResult(result: Result) { - updatePowerLevelsResult = result - } - - fun givenResetPowerLevelsResult(result: Result) { - resetPowerLevelsResult = result - } } -data class SendLocationInvocation( - val body: String, - val geoUri: String, - val description: String?, - val zoomLevel: Int?, - val assetType: AssetType?, -) - -data class SavePollInvocation( - val question: String, - val answers: List, - val maxSelections: Int, - val pollKind: PollKind, -) - -data class SendPollResponseInvocation( - val pollStartId: EventId, - val answers: List, -) - -data class EndPollInvocation( - val pollStartId: EventId, - val text: String, -) - fun aRoomInfo( id: RoomId = A_ROOM_ID, name: String? = A_ROOM_NAME, diff --git a/libraries/mediaupload/api/build.gradle.kts b/libraries/mediaupload/api/build.gradle.kts index eed11265c1..4887d01d72 100644 --- a/libraries/mediaupload/api/build.gradle.kts +++ b/libraries/mediaupload/api/build.gradle.kts @@ -40,6 +40,7 @@ android { testImplementation(projects.libraries.matrix.test) testImplementation(projects.libraries.mediaupload.test) + testImplementation(projects.tests.testutils) testImplementation(libs.test.junit) testImplementation(libs.test.truth) testImplementation(libs.coroutines.test) diff --git a/libraries/mediaupload/api/src/test/kotlin/io/element/android/libraries/mediaupload/api/MediaSenderTest.kt b/libraries/mediaupload/api/src/test/kotlin/io/element/android/libraries/mediaupload/api/MediaSenderTest.kt index 20bdf034c1..21c5f0425a 100644 --- a/libraries/mediaupload/api/src/test/kotlin/io/element/android/libraries/mediaupload/api/MediaSenderTest.kt +++ b/libraries/mediaupload/api/src/test/kotlin/io/element/android/libraries/mediaupload/api/MediaSenderTest.kt @@ -19,9 +19,12 @@ package io.element.android.libraries.mediaupload.api import android.net.Uri import com.google.common.truth.Truth.assertThat import io.element.android.libraries.core.mimetype.MimeTypes +import io.element.android.libraries.matrix.api.core.ProgressCallback import io.element.android.libraries.matrix.api.room.MatrixRoom +import io.element.android.libraries.matrix.test.media.FakeMediaUploadHandler import io.element.android.libraries.matrix.test.room.FakeMatrixRoom import io.element.android.libraries.mediaupload.test.FakeMediaPreProcessor +import io.element.android.tests.testutils.lambda.lambdaRecorder import kotlinx.coroutines.ExperimentalCoroutinesApi import kotlinx.coroutines.launch import kotlinx.coroutines.test.StandardTestDispatcher @@ -46,13 +49,17 @@ class MediaSenderTest { @Test fun `given an attachment when sending it the MatrixRoom will call sendMedia`() = runTest { - val room = FakeMatrixRoom() + val sendMediaResult = lambdaRecorder> { + Result.success(FakeMediaUploadHandler()) + } + val room = FakeMatrixRoom( + sendMediaResult = sendMediaResult + ) val sender = aMediaSender(room = room) val uri = Uri.parse("content://image.jpg") sender.sendMedia(uri = uri, mimeType = MimeTypes.Jpeg, compressIfPossible = true) - - assertThat(room.sendMediaCount).isEqualTo(1) + sendMediaResult.assertions().isCalledOnce() } @Test @@ -70,9 +77,9 @@ class MediaSenderTest { @Test fun `given a failure in the media upload when sending the whole process fails`() = runTest { - val room = FakeMatrixRoom().apply { - givenSendMediaResult(Result.failure(Exception())) - } + val room = FakeMatrixRoom( + sendMediaResult = { Result.failure(Exception()) } + ) val sender = aMediaSender(room = room) val uri = Uri.parse("content://image.jpg") @@ -84,7 +91,9 @@ class MediaSenderTest { @OptIn(ExperimentalCoroutinesApi::class) @Test fun `given a cancellation in the media upload when sending the job is cancelled`() = runTest(StandardTestDispatcher()) { - val room = FakeMatrixRoom() + val room = FakeMatrixRoom( + sendMediaResult = { Result.success(FakeMediaUploadHandler()) } + ) val sender = aMediaSender(room = room) val sendJob = launch { val uri = Uri.parse("content://image.jpg") diff --git a/libraries/push/impl/src/test/kotlin/io/element/android/libraries/push/impl/notifications/NotificationBroadcastReceiverHandlerTest.kt b/libraries/push/impl/src/test/kotlin/io/element/android/libraries/push/impl/notifications/NotificationBroadcastReceiverHandlerTest.kt index d4706461d8..f4dedfad97 100644 --- a/libraries/push/impl/src/test/kotlin/io/element/android/libraries/push/impl/notifications/NotificationBroadcastReceiverHandlerTest.kt +++ b/libraries/push/impl/src/test/kotlin/io/element/android/libraries/push/impl/notifications/NotificationBroadcastReceiverHandlerTest.kt @@ -35,6 +35,7 @@ import io.element.android.libraries.matrix.test.FakeMatrixClient import io.element.android.libraries.matrix.test.FakeMatrixClientProvider import io.element.android.libraries.matrix.test.core.aBuildMeta import io.element.android.libraries.matrix.test.room.FakeMatrixRoom +import io.element.android.libraries.matrix.test.room.aRoomMember import io.element.android.libraries.matrix.test.timeline.FakeTimeline import io.element.android.libraries.preferences.api.store.SessionPreferencesStore import io.element.android.libraries.preferences.api.store.SessionPreferencesStoreFactory @@ -297,9 +298,9 @@ class NotificationBroadcastReceiverHandlerTest { @Test fun `Test reject room`() = runTest { val leaveRoom = lambdaRecorder> { Result.success(Unit) } - val matrixRoom = FakeMatrixRoom().apply { + val matrixRoom = FakeMatrixRoom( leaveRoomLambda = leaveRoom - } + ) val clearMembershipNotificationForRoomLambda = lambdaRecorder { _, _ -> } val fakeNotificationCleaner = FakeNotificationCleaner( clearMembershipNotificationForRoomLambda = clearMembershipNotificationForRoomLambda, @@ -342,7 +343,8 @@ class NotificationBroadcastReceiverHandlerTest { replyMessageLambda = replyMessage } val matrixRoom = FakeMatrixRoom( - liveTimeline = liveTimeline + liveTimeline = liveTimeline, + getUpdatedMemberResult = { Result.success(aRoomMember()) }, ) val onNotifiableEventReceivedResult = lambdaRecorder { _ -> } val onNotifiableEventReceived = FakeOnNotifiableEventReceived(onNotifiableEventReceivedResult = onNotifiableEventReceivedResult) @@ -400,7 +402,8 @@ class NotificationBroadcastReceiverHandlerTest { replyMessageLambda = replyMessage } val matrixRoom = FakeMatrixRoom( - liveTimeline = liveTimeline + liveTimeline = liveTimeline, + getUpdatedMemberResult = { Result.success(aRoomMember()) }, ) val onNotifiableEventReceivedResult = lambdaRecorder { _ -> } val onNotifiableEventReceived = FakeOnNotifiableEventReceived(onNotifiableEventReceivedResult = onNotifiableEventReceivedResult) From 95225698601f064b269b3155b5a32bf081d297c3 Mon Sep 17 00:00:00 2001 From: ElementBot <110224175+ElementBot@users.noreply.github.com> Date: Mon, 22 Jul 2024 09:59:47 +0100 Subject: [PATCH 08/15] Sync Strings (#3232) Co-authored-by: bmarty <3940906+bmarty@users.noreply.github.com> --- app/src/main/res/xml/locales_config.xml | 2 + .../src/main/res/values-pl/translations.xml | 7 + .../main/res/values-pt-rBR/translations.xml | 7 + .../src/main/res/values-pl/translations.xml | 10 + .../main/res/values-pt-rBR/translations.xml | 10 + .../src/main/res/values-de/translations.xml | 1 + .../src/main/res/values-pl/translations.xml | 6 + .../main/res/values-pt-rBR/translations.xml | 6 + .../src/main/res/values-pl/translations.xml | 14 + .../main/res/values-pt-rBR/translations.xml | 14 + .../src/main/res/values-pl/translations.xml | 11 + .../main/res/values-pt-rBR/translations.xml | 11 + .../src/main/res/values-pl/translations.xml | 9 + .../main/res/values-pt-rBR/translations.xml | 9 + .../src/main/res/values-pl/translations.xml | 7 + .../main/res/values-pt-rBR/translations.xml | 6 + .../src/main/res/values-ka/translations.xml | 16 + .../src/main/res/values-pl/translations.xml | 39 + .../main/res/values-pt-rBR/translations.xml | 22 + .../src/main/res/values-ka/translations.xml | 1 + .../src/main/res/values-pl/translations.xml | 43 + .../main/res/values-pt-rBR/translations.xml | 43 + .../src/main/res/values-ka/translations.xml | 10 + .../src/main/res/values-pl/translations.xml | 18 + .../main/res/values-pt-rBR/translations.xml | 8 + .../src/main/res/values-ka/translations.xml | 2 + .../src/main/res/values-pl/translations.xml | 50 + .../main/res/values-pt-rBR/translations.xml | 42 + .../src/main/res/values-pl/translations.xml | 9 + .../main/res/values-pt-rBR/translations.xml | 8 + .../src/main/res/values-ka/translations.xml | 8 + .../src/main/res/values-pl/translations.xml | 19 + .../main/res/values-pt-rBR/translations.xml | 12 + .../src/main/res/values-el/translations.xml | 4 +- .../src/main/res/values-it/translations.xml | 2 +- .../src/main/res/values-ka/translations.xml | 3 + .../src/main/res/values-pl/translations.xml | 49 + .../main/res/values-pt-rBR/translations.xml | 40 + .../src/main/res/values-pl/translations.xml | 7 + .../main/res/values-pt-rBR/translations.xml | 7 + .../src/main/res/values-pl/translations.xml | 16 + .../main/res/values-pt-rBR/translations.xml | 15 + .../src/main/res/values-el/translations.xml | 8 + .../src/main/res/values-ka/translations.xml | 3 + .../src/main/res/values-pl/translations.xml | 50 + .../main/res/values-pt-rBR/translations.xml | 46 + .../src/main/res/values-el/translations.xml | 3 +- .../src/main/res/values-ka/translations.xml | 2 + .../src/main/res/values-pl/translations.xml | 22 + .../main/res/values-pt-rBR/translations.xml | 19 + .../src/main/res/values-ka/translations.xml | 4 + .../src/main/res/values-pl/translations.xml | 44 + .../main/res/values-pt-rBR/translations.xml | 40 + .../src/main/res/values-pl/translations.xml | 8 + .../main/res/values-pt-rBR/translations.xml | 8 + .../src/main/res/values-pl/translations.xml | 10 + .../main/res/values-pt-rBR/translations.xml | 10 + .../src/main/res/values-ka/translations.xml | 3 + .../src/main/res/values-pl/translations.xml | 20 + .../main/res/values-pt-rBR/translations.xml | 17 + .../src/main/res/values-pl/translations.xml | 4 + .../main/res/values-pt-rBR/translations.xml | 4 + .../src/main/res/values-pl/translations.xml | 59 + .../main/res/values-pt-rBR/translations.xml | 57 + .../src/main/res/values-pl/translations.xml | 4 + .../main/res/values-pt-rBR/translations.xml | 4 + .../src/main/res/values-pl/translations.xml | 7 + .../main/res/values-pt-rBR/translations.xml | 7 + .../main/res/values-pt-rBR/translations.xml | 4 + .../src/main/res/values-ka/translations.xml | 1 + .../src/main/res/values-pl/translations.xml | 59 + .../main/res/values-pt-rBR/translations.xml | 51 + .../src/main/res/values-pl/translations.xml | 25 + .../main/res/values-pt-rBR/translations.xml | 23 + .../main/res/values-pt-rBR/translations.xml | 4 + .../src/main/res/values-be/translations.xml | 7 +- .../src/main/res/values-de/translations.xml | 1 + .../src/main/res/values-el/translations.xml | 9 + .../src/main/res/values-et/translations.xml | 8 + .../src/main/res/values-hu/translations.xml | 6 + .../src/main/res/values-ka/translations.xml | 35 + .../src/main/res/values-pl/translations.xml | 287 +++++ .../main/res/values-pt-rBR/translations.xml | 275 ++++ .../src/main/res/values-sk/translations.xml | 8 + .../src/main/res/values/localazy.xml | 8 + plugins/src/main/kotlin/extension/locales.kt | 2 + ...ll.impl.ui_IncomingCallScreen_Day_0_de.png | 4 +- ...es.joinroom.impl_JoinRoomView_Day_5_de.png | 4 +- ...es.joinroom.impl_JoinRoomView_Day_6_de.png | 4 +- ...ferences.impl.about_AboutView_Day_1_de.png | 3 + ...pl.members_RoomMemberListView_Day_8_de.png | 3 + ...omponents_RoomListContentView_Day_0_de.png | 4 +- ...pl.components_RoomSummaryRow_Day_29_de.png | 4 +- ...pl.components_RoomSummaryRow_Day_30_de.png | 4 +- ...pl.components_RoomSummaryRow_Day_31_de.png | 4 +- ....search_RoomListSearchContent_Day_2_de.png | 4 +- ...es.roomlist.impl_RoomListView_Day_0_de.png | 4 +- ...es.roomlist.impl_RoomListView_Day_1_de.png | 4 +- ...es.roomlist.impl_RoomListView_Day_2_de.png | 4 +- ...es.roomlist.impl_RoomListView_Day_6_de.png | 4 +- screenshots/html/data.js | 1130 +++++++++-------- 101 files changed, 2495 insertions(+), 588 deletions(-) create mode 100644 features/analytics/api/src/main/res/values-pl/translations.xml create mode 100644 features/analytics/api/src/main/res/values-pt-rBR/translations.xml create mode 100644 features/analytics/impl/src/main/res/values-pl/translations.xml create mode 100644 features/analytics/impl/src/main/res/values-pt-rBR/translations.xml create mode 100644 features/call/impl/src/main/res/values-pl/translations.xml create mode 100644 features/call/impl/src/main/res/values-pt-rBR/translations.xml create mode 100644 features/createroom/impl/src/main/res/values-pl/translations.xml create mode 100644 features/createroom/impl/src/main/res/values-pt-rBR/translations.xml create mode 100644 features/ftue/impl/src/main/res/values-pl/translations.xml create mode 100644 features/ftue/impl/src/main/res/values-pt-rBR/translations.xml create mode 100644 features/invite/impl/src/main/res/values-pl/translations.xml create mode 100644 features/invite/impl/src/main/res/values-pt-rBR/translations.xml create mode 100644 features/leaveroom/api/src/main/res/values-pl/translations.xml create mode 100644 features/leaveroom/api/src/main/res/values-pt-rBR/translations.xml create mode 100644 features/lockscreen/impl/src/main/res/values-pl/translations.xml create mode 100644 features/lockscreen/impl/src/main/res/values-pt-rBR/translations.xml create mode 100644 features/login/impl/src/main/res/values-pl/translations.xml create mode 100644 features/login/impl/src/main/res/values-pt-rBR/translations.xml create mode 100644 features/logout/impl/src/main/res/values-pl/translations.xml create mode 100644 features/logout/impl/src/main/res/values-pt-rBR/translations.xml create mode 100644 features/messages/impl/src/main/res/values-pl/translations.xml create mode 100644 features/messages/impl/src/main/res/values-pt-rBR/translations.xml create mode 100644 features/onboarding/impl/src/main/res/values-pl/translations.xml create mode 100644 features/onboarding/impl/src/main/res/values-pt-rBR/translations.xml create mode 100644 features/poll/impl/src/main/res/values-pl/translations.xml create mode 100644 features/poll/impl/src/main/res/values-pt-rBR/translations.xml create mode 100644 features/preferences/impl/src/main/res/values-pl/translations.xml create mode 100644 features/preferences/impl/src/main/res/values-pt-rBR/translations.xml create mode 100644 features/rageshake/api/src/main/res/values-pl/translations.xml create mode 100644 features/rageshake/api/src/main/res/values-pt-rBR/translations.xml create mode 100644 features/rageshake/impl/src/main/res/values-pl/translations.xml create mode 100644 features/rageshake/impl/src/main/res/values-pt-rBR/translations.xml create mode 100644 features/roomdetails/impl/src/main/res/values-pl/translations.xml create mode 100644 features/roomdetails/impl/src/main/res/values-pt-rBR/translations.xml create mode 100644 features/roomlist/impl/src/main/res/values-pl/translations.xml create mode 100644 features/roomlist/impl/src/main/res/values-pt-rBR/translations.xml create mode 100644 features/securebackup/impl/src/main/res/values-pl/translations.xml create mode 100644 features/securebackup/impl/src/main/res/values-pt-rBR/translations.xml create mode 100644 features/signedout/impl/src/main/res/values-pl/translations.xml create mode 100644 features/signedout/impl/src/main/res/values-pt-rBR/translations.xml create mode 100644 features/userprofile/shared/src/main/res/values-pl/translations.xml create mode 100644 features/userprofile/shared/src/main/res/values-pt-rBR/translations.xml create mode 100644 features/verifysession/impl/src/main/res/values-pl/translations.xml create mode 100644 features/verifysession/impl/src/main/res/values-pt-rBR/translations.xml create mode 100644 libraries/androidutils/src/main/res/values-pl/translations.xml create mode 100644 libraries/androidutils/src/main/res/values-pt-rBR/translations.xml create mode 100644 libraries/eventformatter/impl/src/main/res/values-pl/translations.xml create mode 100644 libraries/eventformatter/impl/src/main/res/values-pt-rBR/translations.xml create mode 100644 libraries/matrixui/src/main/res/values-pl/translations.xml create mode 100644 libraries/matrixui/src/main/res/values-pt-rBR/translations.xml create mode 100644 libraries/permissions/api/src/main/res/values-pl/translations.xml create mode 100644 libraries/permissions/api/src/main/res/values-pt-rBR/translations.xml create mode 100644 libraries/permissions/impl/src/main/res/values-pt-rBR/translations.xml create mode 100644 libraries/push/impl/src/main/res/values-pl/translations.xml create mode 100644 libraries/push/impl/src/main/res/values-pt-rBR/translations.xml create mode 100644 libraries/textcomposer/impl/src/main/res/values-pl/translations.xml create mode 100644 libraries/textcomposer/impl/src/main/res/values-pt-rBR/translations.xml create mode 100644 libraries/troubleshoot/impl/src/main/res/values-pt-rBR/translations.xml create mode 100644 libraries/ui-strings/src/main/res/values-pl/translations.xml create mode 100644 libraries/ui-strings/src/main/res/values-pt-rBR/translations.xml create mode 100644 screenshots/de/features.preferences.impl.about_AboutView_Day_1_de.png create mode 100644 screenshots/de/features.roomdetails.impl.members_RoomMemberListView_Day_8_de.png diff --git a/app/src/main/res/xml/locales_config.xml b/app/src/main/res/xml/locales_config.xml index 2884d43c88..fa0e1e2199 100644 --- a/app/src/main/res/xml/locales_config.xml +++ b/app/src/main/res/xml/locales_config.xml @@ -13,7 +13,9 @@ + + diff --git a/features/analytics/api/src/main/res/values-pl/translations.xml b/features/analytics/api/src/main/res/values-pl/translations.xml new file mode 100644 index 0000000000..26aa9c6073 --- /dev/null +++ b/features/analytics/api/src/main/res/values-pl/translations.xml @@ -0,0 +1,7 @@ + + + "Udostępniaj anonimowe dane dotyczące użytkowania, aby pomóc nam identyfikować problemy." + "Możesz przeczytać wszystkie nasze warunki %1$s." + "tutaj" + "Udostępniaj dane analityczne" + diff --git a/features/analytics/api/src/main/res/values-pt-rBR/translations.xml b/features/analytics/api/src/main/res/values-pt-rBR/translations.xml new file mode 100644 index 0000000000..4e7dc9775f --- /dev/null +++ b/features/analytics/api/src/main/res/values-pt-rBR/translations.xml @@ -0,0 +1,7 @@ + + + "Compartilhe dados de uso anônimos para nos ajudar a identificar problemas." + "Você pode ler todos os nossos termos %1$s ." + "aqui" + "Compartilhar dados de utilização" + diff --git a/features/analytics/impl/src/main/res/values-pl/translations.xml b/features/analytics/impl/src/main/res/values-pl/translations.xml new file mode 100644 index 0000000000..99e3e441bb --- /dev/null +++ b/features/analytics/impl/src/main/res/values-pl/translations.xml @@ -0,0 +1,10 @@ + + + "Nie będziemy rejestrować ani profilować żadnych danych osobistych" + "Udostępniaj anonimowe dane dotyczące użytkowania, aby pomóc nam identyfikować problemy." + "Możesz przeczytać wszystkie nasze warunki %1$s." + "tutaj" + "Możesz to wyłączyć w dowolnym momencie" + "Nie będziemy udostępniać Twoich danych podmiotom trzecim" + "Pomóż nam ulepszyć %1$s" + diff --git a/features/analytics/impl/src/main/res/values-pt-rBR/translations.xml b/features/analytics/impl/src/main/res/values-pt-rBR/translations.xml new file mode 100644 index 0000000000..b2fe6e00bc --- /dev/null +++ b/features/analytics/impl/src/main/res/values-pt-rBR/translations.xml @@ -0,0 +1,10 @@ + + + "Não registraremos nem criaremos perfil baseado em qualquer dado pessoal" + "Compartilhe dados de uso anônimos para nos ajudar a identificar problemas." + "Você pode ler todos os nossos termos %1$s ." + "aqui" + "Você pode desativar isso a qualquer momento" + "Não compartilharemos seus dados com terceiros" + "Ajude a melhorar o %1$s" + diff --git a/features/call/impl/src/main/res/values-de/translations.xml b/features/call/impl/src/main/res/values-de/translations.xml index d58a616780..6429dbe956 100644 --- a/features/call/impl/src/main/res/values-de/translations.xml +++ b/features/call/impl/src/main/res/values-de/translations.xml @@ -3,4 +3,5 @@ "Laufender Anruf" "Tippen, um zum Anruf zurückzukehren" "☎️ Anruf läuft" + "Eingehender Element Call" diff --git a/features/call/impl/src/main/res/values-pl/translations.xml b/features/call/impl/src/main/res/values-pl/translations.xml new file mode 100644 index 0000000000..27133cd91b --- /dev/null +++ b/features/call/impl/src/main/res/values-pl/translations.xml @@ -0,0 +1,6 @@ + + + "Połączenie w trakcie" + "Stuknij, aby wrócić do rozmowy" + "☎️ Rozmowa w toku" + diff --git a/features/call/impl/src/main/res/values-pt-rBR/translations.xml b/features/call/impl/src/main/res/values-pt-rBR/translations.xml new file mode 100644 index 0000000000..c3d90e4bb0 --- /dev/null +++ b/features/call/impl/src/main/res/values-pt-rBR/translations.xml @@ -0,0 +1,6 @@ + + + "Chamada em andamento" + "Toque para retornar à chamada" + "☎️ Chamada em andamento" + diff --git a/features/createroom/impl/src/main/res/values-pl/translations.xml b/features/createroom/impl/src/main/res/values-pl/translations.xml new file mode 100644 index 0000000000..eb64b46d8c --- /dev/null +++ b/features/createroom/impl/src/main/res/values-pl/translations.xml @@ -0,0 +1,14 @@ + + + "Nowy pokój" + "Zaproś znajomych" + "Wystąpił błąd podczas tworzenia pokoju" + "Wiadomości w tym pokoju są szyfrowane. Szyfrowania nie można później wyłączyć." + "Pokój prywatny (tylko zaproszenie)" + "Wiadomości nie są szyfrowane i każdy może je odczytać. Możesz aktywować szyfrowanie później." + "Pokój publiczny (każdy)" + "Nazwa pokoju" + "Utwórz pokój" + "Temat (opcjonalnie)" + "Wystąpił błąd podczas próby rozpoczęcia czatu" + diff --git a/features/createroom/impl/src/main/res/values-pt-rBR/translations.xml b/features/createroom/impl/src/main/res/values-pt-rBR/translations.xml new file mode 100644 index 0000000000..bc61411edc --- /dev/null +++ b/features/createroom/impl/src/main/res/values-pt-rBR/translations.xml @@ -0,0 +1,14 @@ + + + "Nova sala" + "Convidar pessoas" + "Ocorreu um erro ao criar a sala" + "As mensagens nesta sala serão criptografadas. A criptografia não pode ser desativada posteriormente." + "Sala privativa (somente por convite)" + "As mensagens não serão criptografadas e qualquer pessoa pode lê-las. Você pode ativar a criptografia posteriormente." + "Sala pública (qualquer pessoa)" + "Nome da sala" + "Criar uma sala" + "Tópico (opcional)" + "Ocorreu um erro ao tentar iniciar um chat" + diff --git a/features/ftue/impl/src/main/res/values-pl/translations.xml b/features/ftue/impl/src/main/res/values-pl/translations.xml new file mode 100644 index 0000000000..b1c1909ac2 --- /dev/null +++ b/features/ftue/impl/src/main/res/values-pl/translations.xml @@ -0,0 +1,11 @@ + + + "Możesz zmienić ustawienia później." + "Zezwól na powiadomienia i nie przegap żadnej wiadomości" + "Połączenia, ankiety, wyszukiwanie i inne zostaną dodane później w tym roku." + "Historia wiadomości dla pokoi szyfrowanych nie jest jeszcze dostępna." + "Chętnie poznamy Twoją opinię. Daj nam znać, co myślisz na stronie ustawień." + "Naprzód!" + "Oto, co musisz wiedzieć:" + "Witamy w %1$s!" + diff --git a/features/ftue/impl/src/main/res/values-pt-rBR/translations.xml b/features/ftue/impl/src/main/res/values-pt-rBR/translations.xml new file mode 100644 index 0000000000..1528027bd4 --- /dev/null +++ b/features/ftue/impl/src/main/res/values-pt-rBR/translations.xml @@ -0,0 +1,11 @@ + + + "Você pode alterar suas configurações mais tarde." + "Permita notificações e nunca perca uma mensagem" + "Chamadas, enquetes, pesquisa e muito mais serão adicionadas ainda este ano." + "O histórico de mensagens para salas criptografadas ainda não está disponível." + "Adoraríamos ouvir sua opinião. Deixe-nos saber o que você pensa através da página de configurações." + "Vamos lá!" + "Aqui está o que você precisa saber:" + "Bem-vindo ao %1$s!" + diff --git a/features/invite/impl/src/main/res/values-pl/translations.xml b/features/invite/impl/src/main/res/values-pl/translations.xml new file mode 100644 index 0000000000..e33b1ae106 --- /dev/null +++ b/features/invite/impl/src/main/res/values-pl/translations.xml @@ -0,0 +1,9 @@ + + + "Czy na pewno chcesz odrzucić zaproszenie do dołączenia do %1$s?" + "Odrzuć zaproszenie" + "Czy na pewno chcesz odrzucić rozmowę prywatną z %1$s?" + "Odrzuć czat" + "Brak zaproszeń" + "%1$s (%2$s) zaprosił Cię" + diff --git a/features/invite/impl/src/main/res/values-pt-rBR/translations.xml b/features/invite/impl/src/main/res/values-pt-rBR/translations.xml new file mode 100644 index 0000000000..9cd284690c --- /dev/null +++ b/features/invite/impl/src/main/res/values-pt-rBR/translations.xml @@ -0,0 +1,9 @@ + + + "Tem certeza de que deseja recusar o convite para ingressar em %1$s?" + "Recusar convite" + "Tem certeza de que deseja recusar esse chat privado com %1$s?" + "Recusar chat" + "Sem convites" + "%1$s(%2$s) convidou você" + diff --git a/features/leaveroom/api/src/main/res/values-pl/translations.xml b/features/leaveroom/api/src/main/res/values-pl/translations.xml new file mode 100644 index 0000000000..0fd8769389 --- /dev/null +++ b/features/leaveroom/api/src/main/res/values-pl/translations.xml @@ -0,0 +1,7 @@ + + + "Czy na pewno chcesz opuścić tę konwersację? Konwersacja nie jest publiczna i nie będziesz mógł dołączyć ponownie bez zaproszenia." + "Jesteś pewien, że chcesz opuścić ten pokój? Jesteś tu jedyną osobą. Jeśli wyjdziesz, nikt nie będzie mógł dołączyć, w tym Ty." + "Czy na pewno chcesz opuścić ten pokój? Ten pokój nie jest publiczny i nie będziesz mógł do niego wrócić bez zaproszenia." + "Jesteś pewien, że chcesz wyjść z tego pokoju?" + diff --git a/features/leaveroom/api/src/main/res/values-pt-rBR/translations.xml b/features/leaveroom/api/src/main/res/values-pt-rBR/translations.xml new file mode 100644 index 0000000000..bb4f35d07f --- /dev/null +++ b/features/leaveroom/api/src/main/res/values-pt-rBR/translations.xml @@ -0,0 +1,6 @@ + + + "Tem certeza de que deseja sair desta sala? Você é a única pessoa aqui. Se você sair, ninguém poderá ingressar no futuro, inclusive você." + "Tem certeza de que deseja sair desta sala? Esta sala não é pública e você não poderá entrar novamente sem um convite." + "Tem certeza de que deseja sair da sala?" + diff --git a/features/lockscreen/impl/src/main/res/values-ka/translations.xml b/features/lockscreen/impl/src/main/res/values-ka/translations.xml index 26fd97b671..022d4ee33c 100644 --- a/features/lockscreen/impl/src/main/res/values-ka/translations.xml +++ b/features/lockscreen/impl/src/main/res/values-ka/translations.xml @@ -1,12 +1,26 @@ + "ბიომეტრიული ავტორიზაცია" + "ბიომეტრიული განბლოკვა" + "განბლოკვა ბიომეტრიით" "დაგავიწყდათ PIN?" "PIN კოდის შეცვლა" "ბიომეტრიული განბლოკვის დაშვება" "პინ კოდის წაშლა" "დარწმუნებული ხართ, რომ გსურთ PIN-ის წაშლა?" "გსურთ PIN-ის წაშლა?" + "%1$s დაშვება" + "მირჩევნია PIN-ის გამოყენება" + "დაზოგეთ დრო და გამოიყენეთ %1$s აპლიკაციის განსაბლოკად." + "აირჩიეთ PIN" "დაადასტურეთ PIN" + "თქვენი ჩატების დამატებითი უსაფრთხოებისათვის დაბლოკეთ %1$s. + +აირჩიეთ რაიმე ისეთი, რაც დაგამახსოვრდებათ. თუ დაგავიწყდებათ ეს PIN, აპლიკაციიდან გამოხვალთ." + "თქვენ არ შეგიძლიათ აირჩიოთ ეს PIN კოდი უსაფრთხოების მიზეზების გამო" + "აირჩიეთ სხვა PIN" + "გთხოვთ შეიყვანოთ იგივე PIN ორჯერ" + "PIN-ები არ ემთხვევა" "გასაგრძელებლად საჭიროა ხელახლა შესვლა და ახალი PIN-ის შექმნა" "თქვენ ახლა გადიხართ…" @@ -17,5 +31,7 @@ "არასწორი PIN. თქვენ %1$d შანსი დაგრჩათ" "არასწორი PIN. თქვენ %1$d შანსი დაგრჩათ" + "გამოიყენეთ ბიომეტრია" + "გამოიყენეთ PIN" "გასვლა…" diff --git a/features/lockscreen/impl/src/main/res/values-pl/translations.xml b/features/lockscreen/impl/src/main/res/values-pl/translations.xml new file mode 100644 index 0000000000..1eb904b13e --- /dev/null +++ b/features/lockscreen/impl/src/main/res/values-pl/translations.xml @@ -0,0 +1,39 @@ + + + "uwierzytelnienie biometryczne" + "odblokowanie biometryczne" + "Odblokuj za pomocą biometrii" + "Nie pamiętasz kodu PIN?" + "Zmień kod PIN" + "Zezwól na uwierzytelnienie biometryczne" + "Usuń PIN" + "Czy na pewno chcesz usunąć PIN?" + "Usunąć PIN?" + "Zezwól na %1$s" + "Wolę korzystać z kodu PIN" + "Zaoszczędź sobie trochę czasu i korzystaj z %1$s do odblokowywania aplikacji" + "Wybierz PIN" + "Potwierdź PIN" + "Zablokuj %1$s, aby zwiększyć bezpieczeństwo swoich czatów. + +Wybierz coś łatwego do zapamiętania. Jeśli zapomnisz tego PINU, zostaniesz wylogowany z aplikacji." + "Nie możesz wybrać tego PINU ze względów bezpieczeństwa" + "Wybierz inny kod PIN" + "Wprowadź ten sam kod PIN dwa razy" + "PINY nie pasują do siebie" + "Aby kontynuować, zaloguj się ponownie i utwórz nowy kod PIN" + "Trwa wylogowywanie" + + "Masz %1$d próbę, żeby odblokować" + "Masz %1$d próby, żeby odblokować" + "Masz %1$d prób, żeby odblokować" + + + "Błędny PIN. Pozostała %1$d próba" + "Błędny PIN. Pozostały %1$d próby" + "Błędny PIN. Pozostało %1$d prób" + + "Użyj biometrii" + "Użyj kodu PIN" + "Wylogowywanie…" + diff --git a/features/lockscreen/impl/src/main/res/values-pt-rBR/translations.xml b/features/lockscreen/impl/src/main/res/values-pt-rBR/translations.xml new file mode 100644 index 0000000000..b7af1aba25 --- /dev/null +++ b/features/lockscreen/impl/src/main/res/values-pt-rBR/translations.xml @@ -0,0 +1,22 @@ + + + "Esqueceu o PIN?" + "Mudar código de PIN" + "Permitir desbloqueio biométrico" + "Remover PIN" + "Tem certeza de que quer remover o PIN?" + "Remover PIN?" + "Escolher PIN" + "Confirmar PIN" + "Os PINs não correspondem" + "Você está sendo desconectado" + + "Você tem %1$d tentativa de debloqueio" + "Você tem %1$d tentativas de debloqueio" + + + "PIN incorreto. Você tem mais %1$d chance" + "PIN incorreto. Você tem mais %1$d chances" + + "Saindo…" + diff --git a/features/login/impl/src/main/res/values-ka/translations.xml b/features/login/impl/src/main/res/values-ka/translations.xml index 2187fc9e95..84e97e0a34 100644 --- a/features/login/impl/src/main/res/values-ka/translations.xml +++ b/features/login/impl/src/main/res/values-ka/translations.xml @@ -27,6 +27,7 @@ "Matrix არის ღია ქსელი უსაფრთხო, დეცენტრალიზებული კომუნიკაციისთვის." "კეთილი იყოს თქვენი მობრძანება!" "შესვლა %1$s-ში" + "ხელახლა ცდა" "შეცვალეთ ანგარიშის მომწოდებელი" "კერძო სერვერი Element-ის თანამშრომლებისთვის." "Matrix არის ღია ქსელი უსაფრთხო, დეცენტრალიზებული კომუნიკაციისთვის." diff --git a/features/login/impl/src/main/res/values-pl/translations.xml b/features/login/impl/src/main/res/values-pl/translations.xml new file mode 100644 index 0000000000..8adfbcb8a8 --- /dev/null +++ b/features/login/impl/src/main/res/values-pl/translations.xml @@ -0,0 +1,43 @@ + + + "Zmień dostawcę konta" + "Adres serwera domowego" + "Wprowadź wyszukiwane hasło lub adres domeny." + "Szukaj serwera firmowego, społeczności lub prywatnego." + "Znajdź dostawcę konta" + "Tutaj będą przechowywane Twoje konwersacje - w podobnej formie jak wiadomości widnieją na skrzynce e-mail." + "Zamierzasz się zalogować %s" + "Tutaj będą przechowywane Twoje konwersacje - w podobnej formie jak wiadomości widnieją na skrzynce e-mail." + "Zamierzasz założyć konto na %s" + "Matrix.org jest ogromnym i darmowym serwerem na publicznej sieci Matrix zapewniający bezpieczną i zdecentralizowaną komunikację zarządzaną przez Fundację Matrix.org." + "Inne" + "Użyj innego dostawcy konta, takiego jak własny serwer lub konta służbowego." + "Zmień dostawcę konta" + "Nie mogliśmy połączyć się z tym serwerem domowym. Sprawdź, czy adres URL serwera został wprowadzony poprawnie. Jeśli adres URL jest poprawny, skontaktuj się z administratorem serwera w celu uzyskania dalszej pomocy." + "Ten serwer obecnie nie obsługuje technologii Sliding Sync." + "Adres URL serwera domowego" + "Możesz połączyć się tylko z serwerem, który obsługuje technologię Sliding Sync. Administrator serwera domowego będzie musiał ją skonfigurować. %1$s" + "Jaki jest adres Twojego serwera?" + "Wybierz swój serwer" + "To konto zostało dezaktywowane." + "Nieprawidłowa nazwa użytkownika i/lub hasło" + "To nie jest prawidłowy identyfikator użytkownika. Oczekiwany format: \'@user:homeserver.org\'" + "Wybrany serwer domowy nie obsługuje uwierzytelniania hasłem, ani OIDC. Skontaktuj się z jego administratorem lub wybierz inny serwer domowy." + "Wprowadź swoje dane" + "Matrix to otwarta sieć do bezpiecznej i zdecentralizowanej komunikacji." + "Witaj ponownie!" + "Zaloguj się do %1$s" + "Spróbuj ponownie" + "Zmień dostawcę konta" + "Serwer prywatny dla pracowników Element." + "Matrix to otwarta sieć do bezpiecznej i zdecentralizowanej komunikacji." + "Tutaj będą przechowywane Twoje konwersacje - w podobnej formie jak wiadomości widnieją na skrzynce e-mail." + "Zamierzasz się zalogować do %1$s" + "Zamierzasz utworzyć konto na %1$s" + "Obecnie istnieje duże zapotrzebowanie na %1$s na %2$s. Wróć do aplikacji za kilka dni i spróbuj ponownie. + +Dziękujemy za Twoją cierpliwość!" + "Witamy w %1$s!" + "Już prawie gotowe!" + "Witamy!" + diff --git a/features/login/impl/src/main/res/values-pt-rBR/translations.xml b/features/login/impl/src/main/res/values-pt-rBR/translations.xml new file mode 100644 index 0000000000..4cb9b4f7b0 --- /dev/null +++ b/features/login/impl/src/main/res/values-pt-rBR/translations.xml @@ -0,0 +1,43 @@ + + + "Alterar provedor da conta" + "Endereço do servidor" + "Insira um termo de pesquisa ou um endereço de domínio." + "Procure uma empresa, comunidade ou servidor privado." + "Encontre um provedor de contas" + "Aqui é onde suas conversas vão ficar — assim como você usa um provedor de e-mails para manter seus e-mails." + "Você está prestes a entrar em %s" + "Aqui é onde suas conversas vão ficar — assim como você usa um provedor de e-mails para manter seus e-mails." + "Você está prestes a criar uma conta em %s" + "O Matrix.org é um grande servidor gratuito na rede pública Matrix para comunicação segura e descentralizada, administrado pela Fundação Matrix.org." + "Outro" + "Use um provedor de conta diferente, como seu próprio servidor privado ou uma conta corporativa." + "Alterar provedor da conta" + "Não conseguimos acessar esse servidor. Verifique se você inseriu a URL do servidor corretamente. Se a URL estiver correta, entre em contato com o administrador do servidor para obter mais ajuda." + "Este servidor atualmente não oferece suporte à tecnologia sliding sync." + "URL do servidor" + "Você só pode se conectar a um servidor existente que ofereça suporte à tecnologia sliding sync. O administrador do seu servidor precisará configurá-lo. %1$s" + "Qual é o endereço do seu servidor?" + "Selecione seu servidor" + "Essa conta foi desativada." + "Nome de usuário e/ou senha incorretos" + "Esse não é um identificador de usuário válido. Formato esperado: \'@usuário:servidor.org\'" + "O servidor selecionado não suporta senha ou login no OIDC. Entre em contato com o administrador ou escolha outro servidor." + "Insira seus dados" + "A Matrix é uma rede aberta para comunicação segura e descentralizada." + "Bem-vindo de volta!" + "Iniciar sessão em %1$s" + "Tente novamente" + "Alterar provedor da conta" + "Um servidor privado para funcionários do Element." + "A Matrix é uma rede aberta para comunicação segura e descentralizada." + "Aqui é onde suas conversas vão ficar — assim como você usa um provedor de e-mails para manter seus e-mails." + "Você está prestes a fazer login em %1$s" + "Você está prestes a criar uma conta em %1$s" + "Há uma grande demanda por %1$s sobre %2$s no momento. Volte ao aplicativo em alguns dias e tente novamente. + +Obrigado pela sua paciência!" + "Bem-vindo ao %1$s!" + "Você está quase lá." + "Você está dentro." + diff --git a/features/logout/impl/src/main/res/values-ka/translations.xml b/features/logout/impl/src/main/res/values-ka/translations.xml index 2226fd240f..adf15b8e46 100644 --- a/features/logout/impl/src/main/res/values-ka/translations.xml +++ b/features/logout/impl/src/main/res/values-ka/translations.xml @@ -4,5 +4,15 @@ "გამოსვლა" "გამოსვლა" "გასვლა…" + "თქვენ აპირებთ გასვლას თქვენი ბოლო სესიიდან. თუ ახლა გამოხვალთ, დაკარგავთ წვდომას თქვენს დაშიფრულ შეტყობინებებზე." + "თქვენ გამორთეთ სარეზერვო ასლი" + "თქვენი გასაღებების სარეზერვო ასლის შექმნა მიმდინარეობდა იმ დროს, როდესაც გამოხვედით. დაკავშირდით ისევ ისე, რომ სარეზერვო ასლი შეიქმნას ანგარიშიდან გამოსვლის გარეშე." + "თქვენი გასაღებების სარეზერვო ასლი ჯერ კიდევ შექმნის პროცესშია" + "გთხოვთ დაელოდეთ ამის დასრულებას სისტემიდან გამოსვლამდე." + "თქვენი გასაღებების სარეზერვო ასლი ჯერ კიდევ შექმნის პროცესშია" "გამოსვლა" + "თქვენ აპირებთ გასვლას თქვენი ბოლო სესიიდან. თუ ახლა გამოხვალთ, დაკარგავთ წვდომას თქვენს დაშიფრულ შეტყობინებებზე." + "აღდგენა არ არის დაყენებული" + "თქვენ აპირებთ გასვლას თქვენი ბოლო სესიიდან. თუ ახლა გამოხვალთ, შესაძლოა დაკარგოთ წვდომა თქვენს დაშიფრულ შეტყობინებებზე." + "შეინახეთ თქვენი აღდგენის გასაღები?" diff --git a/features/logout/impl/src/main/res/values-pl/translations.xml b/features/logout/impl/src/main/res/values-pl/translations.xml new file mode 100644 index 0000000000..ca0d9dc4af --- /dev/null +++ b/features/logout/impl/src/main/res/values-pl/translations.xml @@ -0,0 +1,18 @@ + + + "Czy na pewno chcesz się wylogować?" + "Wyloguj się" + "Wyloguj się" + "Wylogowywanie…" + "Zamierzasz wylogować się ze swojej ostatniej sesji. Jeśli wylogujesz się teraz, stracisz dostęp do swoich wiadomości szyfrowanych." + "Wyłączyłeś backup" + "Twoje klucze były nadal archiwizowane po przejściu w tryb offline. Połącz się ponownie, aby zapisać w chmurze przed wylogowaniem." + "Twoje klucze są nadal archiwizowane" + "Zanim się wylogujesz, poczekaj na zakończenie operacji." + "Twoje klucze są nadal archiwizowane" + "Wyloguj się" + "Zamierzasz wylogować się ze swojej ostatniej sesji. Jeśli wylogujesz się teraz, stracisz dostęp do swoich wiadomości szyfrowanych." + "Nie ustawiono przywracania" + "Zamierzasz wylogować się ze swojej ostatniej sesji. Jeśli wylogujesz się teraz, stracisz dostęp do swoich wiadomości szyfrowanych." + "Czy zapisałeś swój klucz przywracania?" + diff --git a/features/logout/impl/src/main/res/values-pt-rBR/translations.xml b/features/logout/impl/src/main/res/values-pt-rBR/translations.xml new file mode 100644 index 0000000000..65ccf4ca6f --- /dev/null +++ b/features/logout/impl/src/main/res/values-pt-rBR/translations.xml @@ -0,0 +1,8 @@ + + + "Você tem certeza que deseja sair?" + "Sair" + "Sair" + "Saindo…" + "Sair" + diff --git a/features/messages/impl/src/main/res/values-ka/translations.xml b/features/messages/impl/src/main/res/values-ka/translations.xml index 080696776f..47261affcc 100644 --- a/features/messages/impl/src/main/res/values-ka/translations.xml +++ b/features/messages/impl/src/main/res/values-ka/translations.xml @@ -21,8 +21,10 @@ "გამოკითხვა" "ტექსტის ფორმატირება" "შეტყობინებების ისტორია ამჟამად მიუწვდომელია." + "შეტყობინებების ისტორია ამ ოთახში მიუწვდომელია. დაადასტურეთ ეს მოწყობილობა თქვენი შეტყობინებების ისტორიის სანახავად." "გსურთ მათი კვლავ მოწვევა?" "თქვენ მარტო ხართ ამ ჩატში" + "მთელი ოთახისათვის შეტყობინება" "ყველა" "Ხელახლა გაგზავნა" "თქვენი შეტყობინების გაგზავნა ვერ მოხერხდა" diff --git a/features/messages/impl/src/main/res/values-pl/translations.xml b/features/messages/impl/src/main/res/values-pl/translations.xml new file mode 100644 index 0000000000..ebb2b54369 --- /dev/null +++ b/features/messages/impl/src/main/res/values-pl/translations.xml @@ -0,0 +1,50 @@ + + + "Aktywności" + "Flagi" + "Jedzenie i napoje" + "Zwierzęta i natura" + "Obiekty" + "Buźki i osoby" + "Podróż i miejsca" + "Symbole" + "Zablokuj użytkownika" + "Sprawdź, czy chcesz ukryć wszystkie bieżące i przyszłe wiadomości od tego użytkownika." + "Ta wiadomość zostanie zgłoszona do administratora Twojego serwera domowego. Nie będzie mógł on przeczytać żadnych zaszyfrowanych wiadomości." + "Powód zgłoszenia treści" + "Kamera" + "Zrób zdjęcie" + "Nagraj film" + "Załącznik" + "Zdjęcia i filmy" + "Lokalizacja" + "Ankieta" + "Formatowanie tekstu" + "Historia wiadomości jest obecnie niedostępna." + "Historia wiadomości jest niedostępna w tym pokoju. Zweryfikuj to urządzenie, aby zobaczyć historię wiadomości." + "Czy chcesz zaprosić ich z powrotem?" + "Jesteś sam na tym czacie" + "Powiadom cały pokój" + "Wszyscy" + "Wyślij ponownie" + "Nie udało się wysłać wiadomości" + "Dodaj emoji" + "To jest początek %1$s" + "To jest początek tej konwersacji" + "Pokaż mniej" + "Skopiowano wiadomość" + "Nie masz uprawnień, aby pisać w tym pokoju" + "Pokaż mniej" + "Pokaż więcej" + "Nowe" + + "%1$d zmiana pokoju" + "%1$d zmian pokoju" + "%1$d zmiany pokoju" + + + "%1$s piszę" + "%1$s piszą" + "%1$s piszą" + + diff --git a/features/messages/impl/src/main/res/values-pt-rBR/translations.xml b/features/messages/impl/src/main/res/values-pt-rBR/translations.xml new file mode 100644 index 0000000000..6d324fd695 --- /dev/null +++ b/features/messages/impl/src/main/res/values-pt-rBR/translations.xml @@ -0,0 +1,42 @@ + + + "Atividades" + "Bandeiras" + "Comida & Bebida" + "Animais & Natureza" + "Objetos" + "Sorrisos & Pessoas" + "Viagens & Lugares" + "Símbolos" + "Bloquear usuário" + "Marque se você deseja ocultar todas as mensagens atuais e futuras desse usuário" + "Essa mensagem será reportada ao administrador do seu homeserver. Eles não conseguirão ler nenhuma mensagem criptografada." + "Motivo para denunciar este conteúdo" + "Câmera" + "Tirar foto" + "Gravar vídeo" + "Anexo" + "Biblioteca de fotos e vídeos" + "Localização" + "Enquete" + "Formatação de texto" + "O histórico de mensagens não está disponível no momento." + "Gostaria de convidá-los de volta?" + "Você está sozinho neste chat" + "Todos" + "Enviar novamente" + "Sua mensagem não foi enviada" + "Adicionar emoji" + "Este é o início do %1$s." + "Este é o início desta conversa." + "Mostrar menos" + "Mensagem copiada" + "Você não tem permissão para postar nesta sala" + "Mostrar menos" + "Mostrar mais" + "Novo" + + "%1$d mudança de sala" + "%1$d mudanças de salas" + + diff --git a/features/onboarding/impl/src/main/res/values-pl/translations.xml b/features/onboarding/impl/src/main/res/values-pl/translations.xml new file mode 100644 index 0000000000..5ac4d81c27 --- /dev/null +++ b/features/onboarding/impl/src/main/res/values-pl/translations.xml @@ -0,0 +1,9 @@ + + + "Zaloguj się ręcznie" + "Zaloguj się za pomocą kodu QR" + "Utwórz konto" + "Witamy w %1$s. Szybszy i prostszy niż kiedykolwiek." + "Witamy w %1$s. Doładowany, dla szybkości i prostoty." + "Be in your element" + diff --git a/features/onboarding/impl/src/main/res/values-pt-rBR/translations.xml b/features/onboarding/impl/src/main/res/values-pt-rBR/translations.xml new file mode 100644 index 0000000000..04a26fe212 --- /dev/null +++ b/features/onboarding/impl/src/main/res/values-pt-rBR/translations.xml @@ -0,0 +1,8 @@ + + + "Iniciar sessão manualmente" + "Iniciar sessão com código QR" + "Criar conta" + "Bem-vindo ao mais rápido %1$s de todos os tempos. Turbinado para velocidade e simplicidade." + "Bem-vindo ao %1$s. Turbinado, para velocidade e simplicidade" + diff --git a/features/poll/impl/src/main/res/values-ka/translations.xml b/features/poll/impl/src/main/res/values-ka/translations.xml index c2417983af..0cdbc950b8 100644 --- a/features/poll/impl/src/main/res/values-ka/translations.xml +++ b/features/poll/impl/src/main/res/values-ka/translations.xml @@ -4,8 +4,16 @@ "შედეგების ჩვენება მხოლოდ გამოკითხვის დასრულების შემდეგ" "ხმების დამალვა" "ვარიანტი %1$d" + "თქვენი ცვლილებები არ არის შენახული. დარწმუნებული ხართ, რომ გსურთ დაბრუნება?" "კითხვა ან თემა" "რას ეხება გამოკითხვა?" "გამოკითხვის შექმნა" + "დარწმუნებული ხართ, რომ გსურთ ამ გამოკითხვის წაშლა?" + "გამოკითხვის წაშლა" "გამოკითხვის რედაქტირება" + "მიმდინარე გამოკითხვები ვერ მოიძებნა." + "ბოლო გამოკითხვების მოძებნა ვერ მოხერხდა." + "მიმდინარე" + "წარსული" + "გამოკითხვები" diff --git a/features/poll/impl/src/main/res/values-pl/translations.xml b/features/poll/impl/src/main/res/values-pl/translations.xml new file mode 100644 index 0000000000..c6797b370e --- /dev/null +++ b/features/poll/impl/src/main/res/values-pl/translations.xml @@ -0,0 +1,19 @@ + + + "Dodaj opcję" + "Pokaż wyniki dopiero po zakończeniu ankiety" + "Ukryj głosy" + "Opcja %1$d" + "Twoje zmiany nie zostały zapisane. Czy na pewno chcesz wrócić?" + "Pytanie lub temat" + "Czego dotyczy ankieta?" + "Utwórz ankietę" + "Czy na pewno chcesz usunąć tę ankietę?" + "Usuń ankietę" + "Edytuj ankietę" + "Nie znaleziono ankiet w trakcie." + "Nie znaleziono ankiet." + "W trakcie" + "Przeszłe" + "Ankiety" + diff --git a/features/poll/impl/src/main/res/values-pt-rBR/translations.xml b/features/poll/impl/src/main/res/values-pt-rBR/translations.xml new file mode 100644 index 0000000000..058dab7d42 --- /dev/null +++ b/features/poll/impl/src/main/res/values-pt-rBR/translations.xml @@ -0,0 +1,12 @@ + + + "Adicionar opção" + "Mostrar resultados somente após o término da enquete" + "Ocultar votos" + "Opção %1$d" + "Pergunta ou tópico" + "Sobre o que é a enquete?" + "Criar enquete" + "Excluir Enquete" + "Editar enquete" + diff --git a/features/preferences/impl/src/main/res/values-el/translations.xml b/features/preferences/impl/src/main/res/values-el/translations.xml index 32659bca9f..9af59929fc 100644 --- a/features/preferences/impl/src/main/res/values-el/translations.xml +++ b/features/preferences/impl/src/main/res/values-el/translations.xml @@ -15,9 +15,11 @@ "Κοινή χρήση παρουσίας" "Εάν απενεργοποιηθεί, δεν θα μπορείς να στέλνεις ή να λαμβάνεις αποδεικτικά ανάγνωσης ή ειδοποιήσεις πληκτρολόγησης." "Ενεργοποίησε την επιλογή για προβολή πηγής μηνυμάτων στη ροή." + "Δεν έχεις αποκλεισμένους χρήστες" "Άρση αποκλεισμού" "Θα μπορείς να δεις ξανά όλα τα μηνύματα του." "Κατάργηση αποκλεισμού χρήστη" + "Άρση αποκλεισμού…" "Εμφανιζόμενο όνομα" "Το εμφανιζόμενο όνομά σου" "Παρουσιάστηκε ένα άγνωστο σφάλμα και οι πληροφορίες δεν μπορούσαν να αλλάξουν." @@ -45,7 +47,7 @@ "Αναφορές" "Όλα" "Αναφορές" - "Ειδοποιήσε με για" + "Ειδοποίησέ με για" "Ειδοποίηση για @room" "Για να λαμβάνεις ειδοποιήσεις, άλλαξε το %1$s ." "ρυθμίσεις συστήματος" diff --git a/features/preferences/impl/src/main/res/values-it/translations.xml b/features/preferences/impl/src/main/res/values-it/translations.xml index ea7395492c..5acfeff05b 100644 --- a/features/preferences/impl/src/main/res/values-it/translations.xml +++ b/features/preferences/impl/src/main/res/values-it/translations.xml @@ -13,7 +13,7 @@ "Ricevute di visualizzazione" "Se disattivato, le tue ricevute di visualizzazione non verranno inviate a nessuno. Riceverai comunque ricevute di visualizzazione da altri utenti." "Condividi presenza online" - "Se disattivato, non potrai inviare o ricevere ricevute di visualizzazione o notifiche di scrittura." + "Se disattivato, non potrai inviare o ricevere ricevute di lettura o notifiche di scrittura." "Attiva l\'opzione per visualizzare il codice sorgente del messaggio nella conversazione." "Non hai utenti bloccati" "Sblocca" diff --git a/features/preferences/impl/src/main/res/values-ka/translations.xml b/features/preferences/impl/src/main/res/values-ka/translations.xml index f27eac6d40..89c39c1c44 100644 --- a/features/preferences/impl/src/main/res/values-ka/translations.xml +++ b/features/preferences/impl/src/main/res/values-ka/translations.xml @@ -7,6 +7,7 @@ "დააყენეთ საბაზისო URL Element-ის ზარებისათვის." "არასწორი URL, გთხოვთ, დარწმუნდეთ, რომ შეიტანეთ პროტოკოლი (http/https) და სწორი მისამართი." "გამორთეთ მდიდარი ტექსტის რედაქტორი, რათა ხელით აკრიფოთ Markdown." + "ჩართეთ ოპცია რათა შეტყობინების წყაროს დროის ისტორია ნახოთ." "განბლოკვა" "თქვენ კვლავ შეძლებთ მათგან ყველა შეტყობინების ნახვას." "Მომხმარებლის განბლოკვა" @@ -32,6 +33,8 @@ "შეტყობინებების ჩართვა ამ მოწყობილობაზე" "კონფიგურაცია არ გამოსწორებულა, გთხოვთ, კვლავ სცადოთ." "ჯგუფური ჩატები" + "მოსაწვევები" + "თქვენი სახლის სერვერი არ უჭერს მხარს ამ პარამეტრს დაშიფრულ ოთახებში, ზოგიერთ ოთახში შეიძლება არ მიიღოთ შეტყობინება." "ხსენებები" "ყველა" "ხსენებები" diff --git a/features/preferences/impl/src/main/res/values-pl/translations.xml b/features/preferences/impl/src/main/res/values-pl/translations.xml new file mode 100644 index 0000000000..021d7595f1 --- /dev/null +++ b/features/preferences/impl/src/main/res/values-pl/translations.xml @@ -0,0 +1,49 @@ + + + "Upewnij się, że nie pominiesz żadnego połączenia. Zmień swoje ustawienia i zezwól na powiadomienia na blokadzie ekranu." + "Popraw jakość swoich rozmów" + "Wybierz sposób otrzymywania powiadomień" + "Tryb dewelopera" + "Włącz, aby uzyskać dostęp do funkcji dla deweloperów." + "Własny bazowy URL dla połączeń Element" + "Ustaw własny bazowy URL dla połączeń Element" + "Nieprawidłowy adres URL, upewnij się, że zawiera protokół (http/https) i poprawny adres." + "Wyłącz edytor tekstu bogatego, aby pisać tekst Markdown ręcznie." + "Włącz opcję, aby wyświetlić źródło wiadomości na osi czasu." + "Odblokuj" + "Będziesz mógł ponownie zobaczyć wszystkie wiadomości od tego użytkownika." + "Odblokuj użytkownika" + "Wyświetlana nazwa" + "Twoja wyświetlana nazwa" + "Wystąpił nieznany błąd przez co nie można było zmienić informacji." + "Nie można zaktualizować profilu" + "Edytuj profil" + "Aktualizowanie profilu…" + "Dodatkowe ustawienia" + "Połączenia audio i wideo" + "Niezgodność konfiguracji" + "Uprościliśmy Ustawienia powiadomień, aby ułatwić nawigowanie między opcjami. Niektóre ustawienia, które wybrałeś mogły zniknąć, lecz są wciąż aktywne. + +Niektóre ustawienia mogą ulec zmianie, jeśli kontynuujesz." + "Czaty prywatne" + "Ustawienia własne wybranego czatu" + "Wystąpił błąd podczas aktualizacji ustawienia powiadomień." + "Wszystkie wiadomości" + "Tylko wzmianki i słowa kluczowe" + "Na czatach prywatnych, powiadamiaj mnie przez" + "Na czatach grupowych powiadamiaj mnie przez" + "Włącz powiadomienia na tym urządzeniu" + "Konfiguracja nie została poprawiona, spróbuj ponownie." + "Czaty grupowe" + "Zaproszenia" + "Twój serwer domowy nie wspiera tej opcji w pokojach szyfrowanych, możesz nie otrzymać powiadomień z niektórych pokoi." + "Wzmianki" + "Wszystkie" + "Wzmianki" + "Powiadamiaj mnie przez" + "Powiadom mnie na @pokój" + "Aby otrzymywać powiadomienia, zmień swoje%1$s ." + "ustawienia systemowe" + "Powiadomienia systemowe wyłączone" + "Powiadomienia" + diff --git a/features/preferences/impl/src/main/res/values-pt-rBR/translations.xml b/features/preferences/impl/src/main/res/values-pt-rBR/translations.xml new file mode 100644 index 0000000000..2aa9704981 --- /dev/null +++ b/features/preferences/impl/src/main/res/values-pt-rBR/translations.xml @@ -0,0 +1,40 @@ + + + "Escolha como receber notificações" + "Modo de desenvolvedor" + "Habilite para ter acesso a recursos e funcionalidades para desenvolvedores." + "Desative o editor de rich text para digitar Markdown manualmente." + "Desbloquear" + "Você poderá ver todas as mensagens deles novamente." + "Desbloquear usuário" + "Nome de exibição" + "Seu nome de exibição" + "Um erro desconhecido foi encontrado e as informações não puderam ser alteradas." + "Não foi possível atualizar o perfil" + "Editar perfil" + "Atualizando o perfil…" + "Configurações adicionais" + "Chamadas de áudio e vídeo" + "Incompatibilidade de configuração" + "Simplificamos as configurações de notificações para facilitar a localização das opções. Algumas configurações personalizadas que você escolheu no passado não são mostradas aqui, mas ainda estão ativas. + +Se você continuar, algumas de suas configurações poderão mudar." + "Conversas privadas" + "Configuração personalizada por chat" + "Ocorreu um erro ao atualizar a configuração de notificação." + "Todas as mensagens" + "Somente menções e palavras-chave" + "Em conversas privadas, me notifique para" + "Em conversas em grupos, me notifique para" + "Ativar notificações neste dispositivo" + "A configuração não foi corrigida, tente novamente." + "Bate-papos em grupo" + "Menções" + "Todos" + "Menções" + "Me notifique para" + "Notifique-me em @room" + "configurações do sistema" + "Notificações do sistema desativadas" + "Notificações" + diff --git a/features/rageshake/api/src/main/res/values-pl/translations.xml b/features/rageshake/api/src/main/res/values-pl/translations.xml new file mode 100644 index 0000000000..d9b42eb749 --- /dev/null +++ b/features/rageshake/api/src/main/res/values-pl/translations.xml @@ -0,0 +1,7 @@ + + + "%1$s uległ awarii podczas ostatniego użycia. Czy chcesz przesłać nam raport o awarii?" + "Wygląda na to, że potrząsasz telefonem z frustracji. Czy chcesz otworzyć ekran zgłaszania błędów?" + "Gniewne wstrząsanie" + "Próg wykrywania" + diff --git a/features/rageshake/api/src/main/res/values-pt-rBR/translations.xml b/features/rageshake/api/src/main/res/values-pt-rBR/translations.xml new file mode 100644 index 0000000000..3985149a27 --- /dev/null +++ b/features/rageshake/api/src/main/res/values-pt-rBR/translations.xml @@ -0,0 +1,7 @@ + + + "%1$s fechou inesperadamente na última vez que foi usado. Gostaria de compartilhar um relatório de falhas conosco?" + "Você parece estar sacudindo o telefone em sinal de frustração. Você gostaria de abrir a tela de relatório de erros?" + "Rageshake" + "Limiar de deteção" + diff --git a/features/rageshake/impl/src/main/res/values-pl/translations.xml b/features/rageshake/impl/src/main/res/values-pl/translations.xml new file mode 100644 index 0000000000..04bf123498 --- /dev/null +++ b/features/rageshake/impl/src/main/res/values-pl/translations.xml @@ -0,0 +1,16 @@ + + + "Dołącz zrzut ekranu" + "Możecie skontaktować się ze mną, jeśli macie jakiekolwiek dodatkowe pytania." + "Napisz do mnie" + "Edytuj zrzut ekranu" + "Opisz problem. Co zrobiłeś? Czego oczekiwałeś? Co się stało zamiast tego. Podaj jak najwięcej szczegółów." + "Opisz problem…" + "Jeśli to możliwe, napisz zgłoszenje w języku angielskim." + "Wyślij logi awarii" + "Zezwól na logi" + "Wyślij zrzut ekranu" + "Logi zostaną dołączone do Twojej wiadomości, aby upewnić się, że wszystko działa poprawnie. Aby wysłać wiadomość bez logów, wyłącz to ustawienie." + "%1$s uległ awarii podczas ostatniego użycia. Czy chcesz przesłać nam raport o awarii?" + "Wyświetl logi" + diff --git a/features/rageshake/impl/src/main/res/values-pt-rBR/translations.xml b/features/rageshake/impl/src/main/res/values-pt-rBR/translations.xml new file mode 100644 index 0000000000..d046391f6a --- /dev/null +++ b/features/rageshake/impl/src/main/res/values-pt-rBR/translations.xml @@ -0,0 +1,15 @@ + + + "Anexar captura de tela" + "Você pode entrar em contato comigo se tiver alguma pergunta adicional." + "Entre em contato comigo" + "Editar captura de tela" + "Descreva o problema. O que você fez? O que você esperava que acontecesse? O que realmente aconteceu? Por favor, forneça o máximo de detalhes possível." + "Descreva o problema…" + "Se possível, escreva a descrição em inglês." + "Enviar registros de falhas" + "Permitir registros" + "Enviar captura de tela" + "Os registros serão incluídos com sua mensagem para garantir que tudo esteja funcionando corretamente. Para enviar sua mensagem sem registros, desative essa configuração." + "%1$s fechou inesperadamente na última vez que foi usado. Gostaria de compartilhar um relatório de falhas conosco?" + diff --git a/features/roomdetails/impl/src/main/res/values-el/translations.xml b/features/roomdetails/impl/src/main/res/values-el/translations.xml index 9262a346c5..2c1886ce40 100644 --- a/features/roomdetails/impl/src/main/res/values-el/translations.xml +++ b/features/roomdetails/impl/src/main/res/values-el/translations.xml @@ -4,6 +4,7 @@ "Ο οικιακός διακομιστής σου δεν υποστηρίζει αυτήν την επιλογή σε κρυπτογραφημένα δωμάτια, ενδέχεται να μην λάβεις ειδοποίηση σε ορισμένα δωμάτια." "Δημοσκοπήσεις" "Μόνο διαχειριστές" + "Αποκλεισμός ατόμων" "Αφαίρεση μηνυμάτων" "Όλοι" "Πρόσκληση ατόμων" @@ -58,17 +59,23 @@ "Πληροφορίες δωματίου" "Θέμα" "Ενημέρωση δωματίου…" + "Αποκλεισμός" "Δεν θα μπορεί να συμμετέχει ξανά σε αυτό το δωμάτιο εάν προσκληθεί." + "Θες σίγουρα να αποκλείσεις αυτό το μέλος;" + "Δεν υπάρχουν αποκλεισμένοι χρήστες σε αυτό το δωμάτιο." + "Αποκλεισμός του χρήστη %1$s" "%1$d άτομο" "%1$d άτομα" + "Αφαίρεση και αποκλεισμός μέλους" "Αφαίρεση από το δωμάτιο" "Αφαίρεση και αποκλεισμός μέλους" "Μόνο αφαίρεση μέλους" "Αφαίρεση μέλους και απαγόρευση συμμετοχής στο μέλλον;" "Αναίρεση αποκλεισμού" "Θα μπορεί να συμμετάσχει ξανά στο δωμάτιο εάν προσκληθεί." + "Άρση αποκλεισμού χρήστη" "Προβολή προφίλ" "Αποκλεισμένοι" "Μέλη" @@ -77,6 +84,7 @@ "Διαχειριστής" "Συντονιστής" "Μέλη δωματίου" + "Άρση αποκλεισμού %1$s" "Να επιτρέπεται η προσαρμοσμένη ρύθμιση" "Η ενεργοποίηση αυτής της ρύθμισης θα παρακάμψει την προεπιλεγμένη ρύθμιση" "Ειδοποιήσε με σε αυτήν τη συνομιλία για" diff --git a/features/roomdetails/impl/src/main/res/values-ka/translations.xml b/features/roomdetails/impl/src/main/res/values-ka/translations.xml index 75f7121b45..65ce26797e 100644 --- a/features/roomdetails/impl/src/main/res/values-ka/translations.xml +++ b/features/roomdetails/impl/src/main/res/values-ka/translations.xml @@ -1,6 +1,8 @@ "შეტყობინებების პარამეტრის განახლებისას მოხდა შეცდომა." + "თქვენი სახლის სერვერი არ უჭერს მხარს ამ პარამეტრს დაშიფრულ ოთახებში, ზოგიერთ ოთახში შეიძლება არ მიიღოთ შეტყობინება." + "გამოკითხვები" "ყველა" "თემის დამატება" "უკვე წევრია" @@ -39,6 +41,7 @@ "შეტყობინებების პარამეტრების ჩატვირთვისას მოხდა შეცდომა." "ნაგულისხმევი რეჟიმის აღდგენა ვერ მოხერხდა, გთხოვთ, სცადოთ ხელახლა." "რეჟიმის დაყენება ვერ მოხერხდა, გთხოვთ, სცადოთ ხელახლა." + "თქვენი სახლის სერვერი არ უჭერს მხარს ამ პარამეტრს დაშიფრულ ოთახებში, თქვენ არ მიიღებთ შეტყობინებას ამ ოთახში." "ყველა შეტყობინება" "მხოლოდ ხსენებები და საკვანძო სიტყვები" "ამ ოთახში, შემატყობინეთ:" diff --git a/features/roomdetails/impl/src/main/res/values-pl/translations.xml b/features/roomdetails/impl/src/main/res/values-pl/translations.xml new file mode 100644 index 0000000000..569e167d92 --- /dev/null +++ b/features/roomdetails/impl/src/main/res/values-pl/translations.xml @@ -0,0 +1,50 @@ + + + "Wystąpił błąd podczas aktualizacji ustawienia powiadomień." + "Twój serwer domowy nie wspiera tej opcji w pokojach szyfrowanych, możesz nie otrzymać powiadomień z niektórych pokoi." + "Ankiety" + "Wszyscy" + "Dodaj temat" + "Jest już członkiem" + "Już zaproszony" + "Edytuj pokój" + "Wystąpił nieznany błąd i nie można było zmienić informacji." + "Nie można zaktualizować pokoju" + "Wiadomości są zabezpieczone kłódkami. Tylko Ty i odbiorcy macie unikalne klucze do ich odblokowania." + "Szyfrowanie wiadomości włączone" + "Wystąpił błąd podczas ładowania ustawień powiadomień." + "Wyciszenie tego pokoju nie powiodło się, spróbuj ponownie." + "Nie udało się wyłączyć wyciszenia tego pokoju. Spróbuj ponownie." + "Zaproś znajomych" + "Opuść rozmowę" + "Opuść pokój" + "Niestandardowy" + "Domyślny" + "Powiadomienia" + "Nazwa pokoju" + "Bezpieczeństwo" + "Udostępnij pokój" + "Temat" + "Aktualizuję pokój…" + + "%1$d osoba" + "%1$d osoby" + "%1$d osób" + + "Oczekiwanie" + "Członkowie pokoju" + "Zezwalaj na ustawienia niestandardowe" + "Włączenie tej opcji nadpisze ustawienie domyślne" + "Powiadamiaj mnie o tym czacie przez" + "Możesz to zmienić w swoim %1$s." + "ustawienia globalne" + "Ustawienie domyślne" + "Usuń ustawienia własne" + "Wystąpił błąd podczas ładowania ustawień powiadomień." + "Nie udało się przywrócić trybu domyślnego, spróbuj ponownie." + "Nie udało się ustawić trybu, spróbuj ponownie." + "Twój serwer domowy nie wspiera tej opcji w pokojach szyfrowanych, możesz nie otrzymać powiadomień z tego pokoju." + "Wszystkie wiadomości" + "Tylko wzmianki i słowa kluczowe" + "W tym pokoju, powiadamiaj mnie przez" + diff --git a/features/roomdetails/impl/src/main/res/values-pt-rBR/translations.xml b/features/roomdetails/impl/src/main/res/values-pt-rBR/translations.xml new file mode 100644 index 0000000000..4989168201 --- /dev/null +++ b/features/roomdetails/impl/src/main/res/values-pt-rBR/translations.xml @@ -0,0 +1,46 @@ + + + "Ocorreu um erro ao atualizar a configuração de notificação." + "Todos" + "Adicionar tópico" + "Já é membro" + "Já foi convidado" + "Editar sala" + "Ocorreu um erro desconhecido e as informações não puderam ser alteradas." + "Não foi possível atualizar a sala" + "As mensagens são protegidas com bloqueios. Somente você e os destinatários têm as chaves exclusivas para desbloqueá-los." + "Criptografia de mensagens ativada" + "Ocorreu um erro ao carregar as configurações de notificação." + "Falha ao silenciar esta sala, tente novamente." + "Falha ao ativar o som desta sala. Tente novamente." + "Convidar pessoas" + "Sair da conversa" + "Sair da sala" + "Personalizado" + "Padrão" + "Notificações" + "Nome da sala" + "Segurança" + "Compartilhar sala" + "Tópico" + "Atualizando a sala…" + + "%1$d pessoa" + "%1$d pessoas" + + "Pendente" + "Membros da sala" + "Permitir configuração personalizada" + "Ativar isso substituirá sua configuração padrão" + "Me notifique nesta conversa para" + "Você pode alterá-lo no seu %1$s." + "configurações globais" + "Configuração padrão" + "Remover configuração personalizada" + "Ocorreu um erro ao carregar as configurações de notificação." + "Falha ao restaurar o modo padrão, tente novamente." + "Falha ao definir o modo, tente novamente." + "Todas as mensagens" + "Somente menções e palavras-chave" + "Nesta sala, notifique-me para" + diff --git a/features/roomlist/impl/src/main/res/values-el/translations.xml b/features/roomlist/impl/src/main/res/values-el/translations.xml index b3a4a8f04d..71aca711ad 100644 --- a/features/roomlist/impl/src/main/res/values-el/translations.xml +++ b/features/roomlist/impl/src/main/res/values-el/translations.xml @@ -25,12 +25,13 @@ "Μπορείς να καταργήσεις την επιλογή φίλτρων για να δεις τις άλλες συνομιλίες σου" "Δεν έχεις συνομιλίες για αυτήν την επιλογή" "Άτομα" + "Δεν έχεις ακόμα ΠΜ" "Δωμάτια" "Δεν είσαι ακόμα σε κανένα δωμάτιο" "Μη αναγνωσμένα" "Συγχαρητήρια! Δεν έχεις μη αναγνωσμένα μηνύματα!" - "Συζητήσεις" + "Συνομιλίες" "Επισήμανση ως αναγνωσμένου" "Επισήμανση ως μη αναγνωσμένου" "Περιήγηση σε όλα τα δωμάτια" diff --git a/features/roomlist/impl/src/main/res/values-ka/translations.xml b/features/roomlist/impl/src/main/res/values-ka/translations.xml index de6358f443..dac714cd0a 100644 --- a/features/roomlist/impl/src/main/res/values-ka/translations.xml +++ b/features/roomlist/impl/src/main/res/values-ka/translations.xml @@ -1,5 +1,7 @@ + "თქვენი ჩეთების სარეზერვო ასლი ამჟამად არ არის სინქრონიზებული. თქვენ უნდა შეიყვანოთ თქვენი აღდგენის გასაღები, რათა შეინარჩუნოთ წვდომა ჩეთების სარეზერვო ასლზე." + "შეიყვანეთ აღდგენის გასაღები" "დარწმუნებული ხართ, რომ გსურთ, უარი თქვათ მოწვევაზე %1$s-ში?" "მოწვევაზე უარის თქმა" "დარწმუნებული ხართ, რომ გსურთ, უარი თქვათ ჩატზე %1$s-თან?" diff --git a/features/roomlist/impl/src/main/res/values-pl/translations.xml b/features/roomlist/impl/src/main/res/values-pl/translations.xml new file mode 100644 index 0000000000..0ae62297a1 --- /dev/null +++ b/features/roomlist/impl/src/main/res/values-pl/translations.xml @@ -0,0 +1,22 @@ + + + "Twoja kopia zapasowa czatu jest obecnie niezsynchronizowana. Aby zachować dostęp do kopii zapasowej czatu, musisz potwierdzić klucz odzyskiwania." + "Potwierdź klucz odzyskiwania" + "Upewnij się, że nie pominiesz żadnego połączenia. Zmień swoje ustawienia i zezwól na powiadomienia na blokadzie ekranu." + "Popraw jakość swoich rozmów" + "Czy na pewno chcesz odrzucić zaproszenie do dołączenia do %1$s?" + "Odrzuć zaproszenie" + "Czy na pewno chcesz odrzucić rozmowę prywatną z %1$s?" + "Odrzuć czat" + "Brak zaproszeń" + "%1$s (%2$s) zaprosił Cię" + "Jest to jednorazowy proces, dziękujemy za czekanie." + "Konfigurowanie Twojego konta." + "Utwórz nową rozmowę lub pokój" + "Wyślij komuś wiadomość, aby rozpocząć." + "Brak czatów." + "Osoby" + "Wszystkie czaty" + "Wygląda na to, że używasz nowego urządzenia. Zweryfikuj się innym urządzeniem, aby uzyskać dostęp do zaszyfrowanych wiadomości." + "Potwierdź, że to Ty" + diff --git a/features/roomlist/impl/src/main/res/values-pt-rBR/translations.xml b/features/roomlist/impl/src/main/res/values-pt-rBR/translations.xml new file mode 100644 index 0000000000..6765199a70 --- /dev/null +++ b/features/roomlist/impl/src/main/res/values-pt-rBR/translations.xml @@ -0,0 +1,19 @@ + + + "Insira sua chave de recuperação" + "Tem certeza de que deseja recusar o convite para ingressar em %1$s?" + "Recusar convite" + "Tem certeza de que deseja recusar esse chat privado com %1$s?" + "Recusar chat" + "Sem convites" + "%1$s(%2$s) convidou você" + "Este é um processo único, obrigado por esperar." + "Configurando sua conta." + "Criar uma nova conversa ou sala" + "Comece enviando uma mensagem para alguém." + "Ainda não há conversas." + "Pessoas" + "Conversas" + "Parece que você está usando um novo dispositivo. Verifique com outro dispositivo para acessar suas mensagens criptografadas." + "Verifique se é você" + diff --git a/features/securebackup/impl/src/main/res/values-ka/translations.xml b/features/securebackup/impl/src/main/res/values-ka/translations.xml index e31153859c..6c1ed02eb5 100644 --- a/features/securebackup/impl/src/main/res/values-ka/translations.xml +++ b/features/securebackup/impl/src/main/res/values-ka/translations.xml @@ -22,10 +22,14 @@ "აღდგენის გასაღები შეიცვალა" "გსურთ აღდგენის გასაღების შეცვლა?" "დარწმუნდით, რომ ვერავინ ხედავს ამ ეკრანს!" + "გთხოვთ, სცადოთ ხელახლა, რათა თქვენი ჩეთის სარეზერვო ასლაზე წვდომა დაადასტუროთ" + "აღდგენის არასწორი გასაღები" "თუ თქვენ გაქვთ უსაფრთხოების გასაღები ან უსაფრთხოების ფრაზა, ეს ასევე იმუშავებს." "შეყვანა" "აღდგენის გასაღები დადასტურებულია" "შეიყვანეთ თქვენი აღდგენის გასაღები" + "დაკოპირებულია აღდგენის გასაღები" + "გენერირება…" "აღდგენის გასაღების შენახვა" "ჩაწერეთ თქვენი აღდგენის გასაღები სადმე უსაფრთხო ადგილას ან შეინახეთ პაროლის მენეჯერში." "აღდგენის გასაღების დასაკოპირებლად, დააწკაპუნეთ" diff --git a/features/securebackup/impl/src/main/res/values-pl/translations.xml b/features/securebackup/impl/src/main/res/values-pl/translations.xml new file mode 100644 index 0000000000..ca1589c5ac --- /dev/null +++ b/features/securebackup/impl/src/main/res/values-pl/translations.xml @@ -0,0 +1,44 @@ + + + "Wyłącz backup" + "Włącz backup" + "Backup zapewnia, że nie stracisz swojej historii wiadomości. %1$s" + "Backup" + "Zmień klucz przywracania" + "Wprowadź klucz przywracania" + "Backup czatu nie jest zsynchronizowany." + "Skonfiguruj przywracanie" + "Uzyskaj dostęp do swoich wiadomości szyfrowanych, jeśli utracisz wszystkie swoje urządzenia lub zostaniesz wylogowany z %1$s." + "Wyłącz" + "Utracisz dostęp do wiadomości szyfrowanych, jeśli zostaniesz wylogowany ze wszystkich urządzeń." + "Czy na pewno chcesz wyłączyć backup?" + "Wyłączenie backupu spowoduje usunięcie kopii klucza szyfrowania i wyłączenie innych funkcji bezpieczeństwa. W takim przypadku będziesz:" + "Posiadał historii wiadomości szyfrowanych na nowych urządzeniach" + "Utracisz dostęp do wiadomości szyfrowanych, jeśli zostaniesz wszędzie wylogowany z %1$s" + "Czy na pewno chcesz wyłączyć backup?" + "Uzyskaj nowy klucz przywracania, jeśli straciłeś dostęp do obecnego. Po zmianie klucza przywracania stary nie będzie już działał." + "Generuj nowy klucz przywracania" + "Upewnij się, że klucz przywracania będzie trzymany w bezpiecznym miejscu" + "Zmieniono klucz przywracania" + "Zmienić klucz przywracania?" + "Upewnij się, że nikt nie widzi tego ekranu!" + "Spróbuj ponownie, aby potwierdzić dostęp do backupu czatu." + "Nieprawidłowy klucz przywracania" + "To też zadziała, jeśli posiadasz klucz lub frazę bezpieczeństwa." + "Wprowadź…" + "Potwierdzono klucz przywracania" + "Wprowadź klucz przywracania" + "Skopiowano klucz przywracania" + "Generuję…" + "Zapisz klucz przywracania" + "Zapisz klucz przywracania w bezpiecznym miejscu lub zapisz go w menedżerze haseł." + "Stuknij, by skopiować klucz przywracania" + "Zapisz klucz przywracania" + "Po tym kroku nie będziesz mieć dostępu do nowego klucza przywracania." + "Czy zapisałeś swój klucz przywracania?" + "Backup czatu jest chroniony przez klucz przywracania. Jeśli potrzebujesz utworzyć nowy klucz, możesz to zrobić wybierając `Zmień klucz przywracania`." + "Wygeneruj klucz przywracania" + "Upewnij się, że klucz przywracania możesz przechowywać w bezpiecznym miejscu" + "Skonfigurowano przywracanie pomyślnie" + "Skonfiguruj przywracanie" + diff --git a/features/securebackup/impl/src/main/res/values-pt-rBR/translations.xml b/features/securebackup/impl/src/main/res/values-pt-rBR/translations.xml new file mode 100644 index 0000000000..786de3f4da --- /dev/null +++ b/features/securebackup/impl/src/main/res/values-pt-rBR/translations.xml @@ -0,0 +1,40 @@ + + + "Desativar o backup" + "Ativar o backup" + "O backup garante que você não perca seu histórico de mensagens. %1$s." + "Backup" + "Mudar chave de recuperação" + "Insira a chave de recuperação" + "Seu backup das conversas está atualmente fora de sincronia." + "Configurar a recuperação" + "Tenha acesso às suas mensagens criptografadas se você perder todos os seus dispositivos ou for desconectado do %1$s em qualquer lugar." + "Desligar" + "Você perderá suas mensagens criptografadas se estiver desconectado de todos os dispositivos." + "Tem certeza de que deseja desativar o backup?" + "Desativar o backup removerá o backup da chave de criptografia atual e desativará outros recursos de segurança. Neste caso, você irá:" + "Não ter histórico de mensagens criptografadas em novos dispositivos" + "Perder o acesso às suas mensagens criptografadas se você estiver desconectado %1$s em todos os lugares" + "Tem certeza de que deseja desativar o backup?" + "Obtenha uma nova chave de recuperação caso tenha perdido a existente. Depois de alterar sua chave de recuperação, a antiga não funcionará mais." + "Gere uma nova chave de recuperação" + "Certifique-se de que você pode armazenar sua chave de recuperação em algum lugar seguro" + "Chave de recuperação alterada" + "Alterar chave de recuperação?" + "Certifique-se de que ninguém possa ver essa tela!" + "Se você tiver uma chave de segurança ou frase de segurança, isso também funcionará." + "Inserir…" + "Chave de recuperação confirmada" + "Insira sua chave de recuperação" + "Salvar chave de recuperação" + "Anote sua chave de recuperação em algum lugar seguro ou salve-a em um gerenciador de senhas." + "Toque para copiar a chave de recuperação" + "Salve sua chave de recuperação" + "Você não poderá acessar sua nova chave de recuperação após essa etapa." + "Você salvou sua chave de recuperação?" + "Seu backup das conversas é protegido por uma chave de recuperação. Se precisar de uma nova chave de recuperação após a configuração, você pode recriá-la selecionando “Alterar chave de recuperação”." + "Gere sua chave de recuperação" + "Certifique-se de que você pode armazenar sua chave de recuperação em algum lugar seguro" + "Configuração de recuperação bem-sucedida" + "Configurar a recuperação" + diff --git a/features/signedout/impl/src/main/res/values-pl/translations.xml b/features/signedout/impl/src/main/res/values-pl/translations.xml new file mode 100644 index 0000000000..9b83e7d692 --- /dev/null +++ b/features/signedout/impl/src/main/res/values-pl/translations.xml @@ -0,0 +1,8 @@ + + + "Zmieniono hasło w innej sesji" + "Sesja została usunięta z innej sesji" + "Administrator serwera unieważnił Twój dostęp" + "Mogłeś zostać wylogowany z powodów wymienionych poniżej. Zaloguj się ponownie, aby dalej korzystać z %s." + "Zostałeś wylogowany" + diff --git a/features/signedout/impl/src/main/res/values-pt-rBR/translations.xml b/features/signedout/impl/src/main/res/values-pt-rBR/translations.xml new file mode 100644 index 0000000000..3c31806492 --- /dev/null +++ b/features/signedout/impl/src/main/res/values-pt-rBR/translations.xml @@ -0,0 +1,8 @@ + + + "Você alterou sua senha em outra sessão" + "Você excluiu essa sessão através de outra sessão" + "O administrador do seu servidor invalidou seu acesso" + "Você pode ter sido desconectado por um dos motivos listados abaixo. Faça login novamente para continuar usando %s." + "Você está desconectado" + diff --git a/features/userprofile/shared/src/main/res/values-pl/translations.xml b/features/userprofile/shared/src/main/res/values-pl/translations.xml new file mode 100644 index 0000000000..8ee9d296ac --- /dev/null +++ b/features/userprofile/shared/src/main/res/values-pl/translations.xml @@ -0,0 +1,10 @@ + + + "Zablokuj" + "Zablokowani użytkownicy nie będą mogli wysyłać Ci wiadomości, a wszystkie ich wiadomości zostaną ukryte. Możesz odblokować ich w dowolnym momencie." + "Zablokuj użytkownika" + "Odblokuj" + "Będziesz mógł ponownie zobaczyć wszystkie wiadomości od tego użytkownika." + "Odblokuj użytkownika" + "Wystąpił błąd podczas próby rozpoczęcia czatu" + diff --git a/features/userprofile/shared/src/main/res/values-pt-rBR/translations.xml b/features/userprofile/shared/src/main/res/values-pt-rBR/translations.xml new file mode 100644 index 0000000000..d5a26a77ca --- /dev/null +++ b/features/userprofile/shared/src/main/res/values-pt-rBR/translations.xml @@ -0,0 +1,10 @@ + + + "Bloquear" + "Usuários bloqueados não poderão enviar mensagens para você e todas as mensagens deles serão ocultadas. Você pode desbloqueá-los a qualquer momento." + "Bloquear usuário" + "Desbloquear" + "Você poderá ver todas as mensagens deles novamente." + "Desbloquear usuário" + "Ocorreu um erro ao tentar iniciar um chat" + diff --git a/features/verifysession/impl/src/main/res/values-ka/translations.xml b/features/verifysession/impl/src/main/res/values-ka/translations.xml index fb1f3c6db4..afd1b03a56 100644 --- a/features/verifysession/impl/src/main/res/values-ka/translations.xml +++ b/features/verifysession/impl/src/main/res/values-ka/translations.xml @@ -3,12 +3,15 @@ "რაღაცა არასწორადაა. ან მოთხოვნის ვადაა ამოწურული, ან მოთხოვნა უარყოფილი იყო." "დაადასტურეთ, რომ ქვემოთ მოყვანილი ემოჯიები შეესაბამება თქვენს სხვა სესიაზე ნაჩვენებს." "შეადარეთ ემოჯიები" + "დაადასტურეთ, რომ ქვემოთ მოცემული ნომრები ემთხვევა თქვენს სხვა სესიაზე ნაჩვენები ნომრებს." + "შეადარეთ რიცხვები" "თქვენი ახალი სესია დადასტურებულია. მას აქვს წვდომა დაშიფრულ შეტყობინებებზე და სხვა მომხმარებლები მას სანდოდ ხედავენ." "დაამტკიცეთ, რომ ეს თქვენ ხართ, რათა მიიღოთ წვდომა თქვენი დაშიფრული შეტყობინებების ისტორიასთან." "არსებული სესიის გახსნა" "დადასტურების ხელახლა ცდა" "მზად ვარ" "ველოდებით დამთხვევას" + "შეადარეთ ემოციების უნიკალური ნაკრები." "შეადარეთ უნიკალური ემოჯი, დარწმუნდით, რომ ისინი ერთი დ იმავე თანმიმდევრობით გამოჩნდნენ." "ისინი არ ემთხვევიან ერთმანეთს" "ისინი ემთხვევიან ერთმანეთს" diff --git a/features/verifysession/impl/src/main/res/values-pl/translations.xml b/features/verifysession/impl/src/main/res/values-pl/translations.xml new file mode 100644 index 0000000000..6f39abf905 --- /dev/null +++ b/features/verifysession/impl/src/main/res/values-pl/translations.xml @@ -0,0 +1,20 @@ + + + "Coś tu nie gra. Albo upłynął limit czasu, albo żądanie zostało odrzucone." + "Upewnij się, że poniższe emotikony pasują do tych wyświetlanych na innej sesji." + "Porównaj emotki" + "Upewnij się, że liczby poniżej pasują do tych wyświetlanych na innej sesji." + "Porównaj liczby" + "Twoja nowa sesja jest teraz zweryfikowana. Ma ona dostęp do Twoich zaszyfrowanych wiadomości, a inni użytkownicy będą widzieć ją jako zaufaną." + "Udowodnij, że to ty, aby uzyskać dostęp do historii zaszyfrowanych wiadomości." + "Otwórz istniejącą sesję" + "Ponów weryfikację" + "Jestem gotowy(a)" + "Oczekiwanie na dopasowanie" + "Porównaj unikalny zestaw emoji." + "Porównaj unikalne emoji, upewniając się, że pojawiły się w tej samej kolejności." + "Nie pasują do siebie" + "Pasują do siebie" + "Zaakceptuj prośbę o rozpoczęcie procesu weryfikacji w innej sesji, aby kontynuować." + "Oczekiwanie na zaakceptowanie żądania" + diff --git a/features/verifysession/impl/src/main/res/values-pt-rBR/translations.xml b/features/verifysession/impl/src/main/res/values-pt-rBR/translations.xml new file mode 100644 index 0000000000..9d4658be82 --- /dev/null +++ b/features/verifysession/impl/src/main/res/values-pt-rBR/translations.xml @@ -0,0 +1,17 @@ + + + "Algo não parece certo. Ou a solicitação atingiu o tempo limite ou a solicitação foi negada." + "Confirme se os emojis abaixo correspondem aos mostrados em sua outra sessão." + "Compare os emojis" + "Sua nova sessão está agora verificada. Ela tem acesso às suas mensagens criptografadas e outros usuários a verão como confiável." + "Prove que é você para acessar seu histórico de mensagens criptografadas." + "Abrir uma sessão existente" + "Repetir verificação" + "Estou pronto" + "Esperando para combinar" + "Compare os emojis únicos, garantindo que apareçam na mesma ordem." + "Eles não combinam" + "Eles combinam" + "Aceite a solicitação para iniciar o processo de verificação em sua outra sessão para continuar." + "Aguardando para aceitar a solicitação" + diff --git a/libraries/androidutils/src/main/res/values-pl/translations.xml b/libraries/androidutils/src/main/res/values-pl/translations.xml new file mode 100644 index 0000000000..6302f19472 --- /dev/null +++ b/libraries/androidutils/src/main/res/values-pl/translations.xml @@ -0,0 +1,4 @@ + + + "Nie znaleziono kompatybilnej aplikacji do obsługi tej akcji." + diff --git a/libraries/androidutils/src/main/res/values-pt-rBR/translations.xml b/libraries/androidutils/src/main/res/values-pt-rBR/translations.xml new file mode 100644 index 0000000000..cde5b743f6 --- /dev/null +++ b/libraries/androidutils/src/main/res/values-pt-rBR/translations.xml @@ -0,0 +1,4 @@ + + + "Nenhum aplicativo compatível foi encontrado para lidar com essa ação." + diff --git a/libraries/eventformatter/impl/src/main/res/values-pl/translations.xml b/libraries/eventformatter/impl/src/main/res/values-pl/translations.xml new file mode 100644 index 0000000000..0c3bddc3c1 --- /dev/null +++ b/libraries/eventformatter/impl/src/main/res/values-pl/translations.xml @@ -0,0 +1,59 @@ + + + "(zdjęcie profilowe też zostało zmienione)" + "%1$s zmienił swoje zdjęcie profilowe" + "Zmieniłeś swoje zdjęcie profilowe" + "%1$s zmienił swoją wyświetlaną nazwę z %2$s na %3$s" + "Zmieniłeś swoją wyświetlaną nazwę z %1$s na %2$s" + "%1$s usunął swoją wyświetlaną nazwę (byo to %2$s)" + "Usunąłeś swoją wyświetlaną nazwę (było to %1$s)" + "%1$s ustawił swoją wyświetlaną nazwę na %2$s" + "Ustawiłeś swoją wyświetlaną nazwę na %1$s" + "%1$s zmienił zdjęcie profilowe pokoju" + "Zmieniłeś zdjęcie profilowe pokoju" + "%1$s usunął zdjęcie profilowe pokoju" + "Usunąłeś zdjęcie profilowe pokoju" + "%1$s zbanował %2$s" + "Zbanowałeś %1$s" + "%1$s stworzył pokój" + "Stworzyłeś pokój" + "%1$s zaprosił %2$s" + "%1$s zaakceptował zaproszenie" + "Zaakceptowałeś zaproszenie" + "Zaprosiłeś %1$s" + "%1$s zaprosił Cię" + "%1$s dołączył do pokoju" + "Dołączyłeś(aś) do pokoju" + "%1$s prosi o możliwość dołączenia" + "%1$s zezwolił %2$s na dołączenie" + "Zezwoliłeś %1$s na dołączenie" + "Poprosiłeś o możliwość dołączenia" + "%1$s odrzucił prośbę %2$s o dołączenie" + "Odrzuciłeś prośbę %1$s o dołączenie" + "%1$s odrzucił Twoją prośbę o dołączenie" + "%1$s nie jest już zainteresowany dołączeniem" + "Anulowałeś prośbę o dołączenie" + "%1$s opuścił pokój" + "Opuściłeś pokój" + "%1$s zmienił nazwę pokoju na: %2$s" + "Zmieniłeś nazwę pokoju na: %1$s" + "%1$s usunął nazwę pokoju" + "Usunąłeś nazwę pokoju" + "%1$s nie wprowadził żadnych zmian" + "Nie wprowadzono żadnych zmian" + "%1$s odrzucił zaproszenie" + "Odrzuciłeś(aś) zaproszenie" + "%1$s usunął %2$s" + "Usunąłeś %1$s" + "%1$s wysłał zaproszenie do %2$s, aby dołączył do pokoju" + "Wysłano zaproszenie do %1$s, aby dołączył do pokoju" + "%1$s cofnął zaproszenie dla %2$s do tego pokoju" + "Odwołano zaproszenie %1$s, aby dołączył do pokoju" + "%1$s zmienił temat na: %2$s" + "Zmieniłeś temat na: %1$s" + "%1$s usunął temat pokoju" + "Usunąłeś temat pokoju" + "%1$s odbanował %2$s" + "Odbanowałeś %1$s" + "%1$s dokonał nieznanej zmiany w swoim członkostwie" + diff --git a/libraries/eventformatter/impl/src/main/res/values-pt-rBR/translations.xml b/libraries/eventformatter/impl/src/main/res/values-pt-rBR/translations.xml new file mode 100644 index 0000000000..8cb375f1b7 --- /dev/null +++ b/libraries/eventformatter/impl/src/main/res/values-pt-rBR/translations.xml @@ -0,0 +1,57 @@ + + + "(o avatar também foi alterado)" + "%1$s mudou seu avatar" + "Você mudou seu avatar" + "%1$s mudou seu nome de exibição de %2$s para %3$s" + "Você alterou seu nome de exibição de %1$s para %2$s" + "%1$s removeu seu nome de exibição (era %2$s)" + "Você removeu seu nome de exibição (era %1$s)" + "%1$s definiu seu nome de exibição como %2$s" + "Você definiu seu nome de exibição como %1$s" + "%1$s mudou o avatar da sala" + "Você mudou o avatar da sala" + "%1$s removeu o avatar da sala" + "Você removeu o avatar da sala" + "%1$s baniu %2$s" + "Você baniu %1$s" + "%1$s criou a sala" + "Você criou a sala" + "%1$s convidou %2$s" + "%1$s aceitou o convite" + "Você aceitou o convite" + "Você convidou %1$s" + "%1$s convidou você" + "%1$s entrou na sala" + "Você entrou na sala" + "%1$s solicitou entrada" + "%1$s permitiu que o %2$s entrar" + "Você permitiu que o %1$s entrasse" + "Você solicitou entrada" + "%1$s rejeitou a solicitação de %2$s para entrar" + "Você rejeitou a solicitação de %1$s para entrar" + "%1$s rejeitou sua solicitação para entrar" + "%1$s não está mais interessado em entrar" + "Você cancelou seu pedido para entrar" + "%1$s saiu da sala" + "Você saiu da sala" + "%1$s mudou o nome da sala para: %2$s" + "Você mudou o nome da sala para: %1$s" + "%1$s removeu o nome da sala" + "Você removeu o nome da sala" + "%1$s rejeitou o convite" + "Você rejeitou o convite" + "%1$s removido %2$s" + "Você removeu %1$s" + "%1$s enviou um convite para %2$s para entrar na sala" + "Você enviou um convite para %1$s para entrar na sala" + "%1$s revogou o convite para %2$s para entrar na sala" + "Você revogou o convite para %1$s para entrar na sala" + "%1$s mudou o tópico para: %2$s" + "Você mudou o tópico para: %1$s" + "%1$s removeu o tópico da sala" + "Você removeu o tópico da sala" + "%1$s desbaniu %2$s" + "Você desbaniu %1$s" + "%1$s fez uma alteração desconhecida em sua associação" + diff --git a/libraries/matrixui/src/main/res/values-pl/translations.xml b/libraries/matrixui/src/main/res/values-pl/translations.xml new file mode 100644 index 0000000000..3c5d9a0d7f --- /dev/null +++ b/libraries/matrixui/src/main/res/values-pl/translations.xml @@ -0,0 +1,4 @@ + + + "%1$s (%2$s) zaprosił Cię" + diff --git a/libraries/matrixui/src/main/res/values-pt-rBR/translations.xml b/libraries/matrixui/src/main/res/values-pt-rBR/translations.xml new file mode 100644 index 0000000000..5409152649 --- /dev/null +++ b/libraries/matrixui/src/main/res/values-pt-rBR/translations.xml @@ -0,0 +1,4 @@ + + + "%1$s(%2$s) convidou você" + diff --git a/libraries/permissions/api/src/main/res/values-pl/translations.xml b/libraries/permissions/api/src/main/res/values-pl/translations.xml new file mode 100644 index 0000000000..647eb9a7f8 --- /dev/null +++ b/libraries/permissions/api/src/main/res/values-pl/translations.xml @@ -0,0 +1,7 @@ + + + "Aby umożliwić aplikacji korzystanie z aparatu, prosimy o udzielenie zezwolenia w ustawieniach systemowych." + "Proszę nadać uprawnienia w ustawieniach systemowych." + "Aby umożliwić aplikacji korzystanie z mikrofonu, prosimy o udzielenie zezwolenia w ustawieniach systemowych." + "Aby aplikacja mogła wyświetlać powiadomienia, udziel uprawnienia w ustawieniach systemowych." + diff --git a/libraries/permissions/api/src/main/res/values-pt-rBR/translations.xml b/libraries/permissions/api/src/main/res/values-pt-rBR/translations.xml new file mode 100644 index 0000000000..ab2a74a945 --- /dev/null +++ b/libraries/permissions/api/src/main/res/values-pt-rBR/translations.xml @@ -0,0 +1,7 @@ + + + "Para permitir que o aplicativo use a câmera, conceda a permissão nas configurações do sistema." + "Por favor, conceda a permissão nas configurações do sistema." + "Para permitir que o aplicativo use o microfone, conceda a permissão nas configurações do sistema." + "Para permitir que o aplicativo exiba notificações, conceda a permissão nas configurações do sistema." + diff --git a/libraries/permissions/impl/src/main/res/values-pt-rBR/translations.xml b/libraries/permissions/impl/src/main/res/values-pt-rBR/translations.xml new file mode 100644 index 0000000000..c8834ddb23 --- /dev/null +++ b/libraries/permissions/impl/src/main/res/values-pt-rBR/translations.xml @@ -0,0 +1,4 @@ + + + "Verifique as permissões" + diff --git a/libraries/push/impl/src/main/res/values-ka/translations.xml b/libraries/push/impl/src/main/res/values-ka/translations.xml index 4f02db32fa..f829dfa8fa 100644 --- a/libraries/push/impl/src/main/res/values-ka/translations.xml +++ b/libraries/push/impl/src/main/res/values-ka/translations.xml @@ -21,6 +21,7 @@ "%d მოწვევები" "მოგიწვიათ ჩატში" + "მოგახსენათ: %1$s" "ახალი შეტყობინებები" "%d ახალი მესიჯი" diff --git a/libraries/push/impl/src/main/res/values-pl/translations.xml b/libraries/push/impl/src/main/res/values-pl/translations.xml new file mode 100644 index 0000000000..56d65b15cb --- /dev/null +++ b/libraries/push/impl/src/main/res/values-pl/translations.xml @@ -0,0 +1,59 @@ + + + "Zadzwoń" + "Nasłuchiwanie wydarzeń" + "Głośne powiadomienia" + "Dzwoniące połączenia" + "Ciche powiadomienia" + + "%1$s: %2$d wiadomość" + "%1$s: %2$d wiadomości" + "%1$s: %2$d wiadomości" + + + "%d powiadomienie" + "%d powiadomienia" + "%d powiadomień" + + "Powiadomienie" + "Przychodzące połączenie" + "** Nie udało się wysłać - proszę otworzyć pokój" + "Dołącz" + "Odrzuć" + + "%d zaproszenie" + "%d zaproszenia" + "%d zaproszeń" + + "Zaprosił(a) cię do czatu" + "Wspomniano o Tobie: %1$s" + "Nowe wiadomości" + + "%d nowa wiadomość" + "%d nowe wiadomości" + "%d nowych wiadomości" + + "Zareagował z %1$s" + "Szybka odpowiedź" + "Zaprosił Cię do dołączenia do pokoju" + "Ja" + "Wyświetlasz powiadomienie! Kliknij mnie!" + "%1$s: %2$s" + "%1$s: %2$s %3$s" + + "%d nieprzeczytana wiadomość" + "%d nieprzeczytane wiadomość" + "%d nieprzeczytanych wiadomości" + + "%1$s i %2$s" + "%1$s w %2$s" + "%1$s w %2$s i %3$s" + + "%d pokój" + "%d pokoje" + "%d pokoi" + + "Synchronizacja w tle" + "Usługi Google" + "Nie znaleziono usług Google Play. Powiadomienia mogą nie działać prawidłowo." + diff --git a/libraries/push/impl/src/main/res/values-pt-rBR/translations.xml b/libraries/push/impl/src/main/res/values-pt-rBR/translations.xml new file mode 100644 index 0000000000..dbdc30a031 --- /dev/null +++ b/libraries/push/impl/src/main/res/values-pt-rBR/translations.xml @@ -0,0 +1,51 @@ + + + "Chamada" + "Ouvindo eventos" + "Notificações barulhentas" + "Notificações silenciosas" + + "%1$s: %2$d mensagem" + "%1$s: %2$d mensagens" + + + "%d notificação" + "%d notificações" + + "Notificação" + "** Falha ao enviar - por favor, abra a sala" + "Entrar" + "Rejeitar" + + "%d convite" + "%d convites" + + "Convidou você para conversar" + "Novas mensagens" + + "%d nova mensagem" + "%d novas mensagens" + + "Reagiu com %1$s" + "Resposta rápida" + "Convidou você para entrar na sala" + "Eu" + "Você está visualizando a notificação! Clique em mim!" + "%1$s: %2$s" + "%1$s: %2$s %3$s" + + "%d mensagem notificada não lida" + "%d mensagens notificadas não lidas" + + "%1$s e %2$s" + "%1$s em %2$s" + "%1$s em %2$s e %3$s" + + "%d sala" + "%d salas" + + "Sincronização em segundo plano" + "Serviços do Google" + "O Google Play Services não foi encontrado. As notificações podem não funcionar corretamente." + "Erro: %1$s." + diff --git a/libraries/textcomposer/impl/src/main/res/values-pl/translations.xml b/libraries/textcomposer/impl/src/main/res/values-pl/translations.xml new file mode 100644 index 0000000000..484b3b622c --- /dev/null +++ b/libraries/textcomposer/impl/src/main/res/values-pl/translations.xml @@ -0,0 +1,25 @@ + + + "Dodaj załącznik" + "Przełącz listę punktową" + "Zamknij opcje formatowania" + "Przełącz blok kodu" + "Wiadomość…" + "Utwórz link" + "Edytuj link" + "Zastosuj pogrubiony format" + "Zastosuj format kursywy" + "Zastosuj format przekreślenia" + "Zastosuj format podkreślenia" + "Przełącz tryb pełnoekranowy" + "Wcięcie" + "Zastosuj format kodu wbudowanego" + "Wstaw łącze" + "Przełącz listę numerowaną" + "Otwórz opcje tworzenia" + "Przełącz cytat" + "Usuń link" + "Bez wcięcia" + "Link" + "Przytrzymaj, aby nagrywać" + diff --git a/libraries/textcomposer/impl/src/main/res/values-pt-rBR/translations.xml b/libraries/textcomposer/impl/src/main/res/values-pt-rBR/translations.xml new file mode 100644 index 0000000000..332f97e155 --- /dev/null +++ b/libraries/textcomposer/impl/src/main/res/values-pt-rBR/translations.xml @@ -0,0 +1,23 @@ + + + "Adicionar anexo" + "Alternar lista de marcadores" + "Fechar opções de formatação" + "Alternar bloco de código" + "Mensagem…" + "Criar um link" + "Editar link" + "Aplicar negrito" + "Aplicar formato itálico" + "Aplicar formato tachado" + "Aplicar sublinhado" + "Alternar o modo de tela cheia" + "Aplicar formato de código embutido" + "Definir link" + "Alternar lista numerada" + "Abrir opções de composição" + "Alternar citação" + "Remover link" + "Link" + "Segure para gravar" + diff --git a/libraries/troubleshoot/impl/src/main/res/values-pt-rBR/translations.xml b/libraries/troubleshoot/impl/src/main/res/values-pt-rBR/translations.xml new file mode 100644 index 0000000000..66f6e46cb3 --- /dev/null +++ b/libraries/troubleshoot/impl/src/main/res/values-pt-rBR/translations.xml @@ -0,0 +1,4 @@ + + + "Execute testes" + diff --git a/libraries/ui-strings/src/main/res/values-be/translations.xml b/libraries/ui-strings/src/main/res/values-be/translations.xml index bc59c712b9..b8a46a245b 100644 --- a/libraries/ui-strings/src/main/res/values-be/translations.xml +++ b/libraries/ui-strings/src/main/res/values-be/translations.xml @@ -82,6 +82,7 @@ "Добра" "Налады" "Адкрыць з дапамогай" + "Замацаваць" "Хуткі адказ" "Цытата" "Рэакцыя" @@ -222,7 +223,7 @@ "Поспех" "Прапановы" "Сінхранізацыя" - "Сістэма" + "Сістэмная" "Тэкст" "Паведамленні трэціх асоб" "Гутарка" @@ -260,6 +261,10 @@ "%1$s не мае дазволу на доступ да вашага мікрафона. Дазвольце доступ да запісу галасавога паведамлення." "Некаторыя паведамленні не былі адпраўлены" "Выбачце, адбылася памылка" + "Сапраўднасць гэтага зашыфраванага паведамлення не можа быць гарантаваная на гэтай прыладзе." + "Зашыфравана невядомай ці выдаленай прыладай." + "Зашыфравана прыладай, не пацверджанай яе ўладальнікам." + "Зашыфравана неправераным карыстальнікам." "🔐️ Далучайцеся да мяне %1$s" "Гэй, пагавары са мной у %1$s: %2$s" "%1$s Android" diff --git a/libraries/ui-strings/src/main/res/values-de/translations.xml b/libraries/ui-strings/src/main/res/values-de/translations.xml index 2779bead6f..e101fb1c8c 100644 --- a/libraries/ui-strings/src/main/res/values-de/translations.xml +++ b/libraries/ui-strings/src/main/res/values-de/translations.xml @@ -83,6 +83,7 @@ "Schnelle Antwort" "Zitat" "Reagieren" + "Ablehnen" "Entfernen" "Antworten" "Im Thread antworten" diff --git a/libraries/ui-strings/src/main/res/values-el/translations.xml b/libraries/ui-strings/src/main/res/values-el/translations.xml index 50f73c4b58..c06e4f8c22 100644 --- a/libraries/ui-strings/src/main/res/values-el/translations.xml +++ b/libraries/ui-strings/src/main/res/values-el/translations.xml @@ -80,6 +80,7 @@ "OK" "Ρυθμίσεις" "Άνοιγμα με" + "Καρφίτσωμα" "Γρήγορη απάντηση" "Παράθεση" "Αντέδρασε" @@ -117,6 +118,7 @@ "Στατιστικά στοιχεία" "Εμφάνιση" "Ήχος" + "Αποκλεισμένοι χρήστες" "Φυσαλίδες" "Κλήση σε εξέλιξη (δεν υποστηρίζεται)" "Η κλήση ξεκίνησε" @@ -255,6 +257,10 @@ "Το %1$s δεν έχει άδεια πρόσβασης στο μικρόφωνό σου. Ενεργοποίησε την πρόσβαση για εγγραφή φωνητικού μηνύματος." "Ορισμένα μηνύματα δεν έχουν σταλεί" "Λυπούμαστε, παρουσιάστηκε σφάλμα" + "Η αυθεντικότητα αυτού του κρυπτογραφημένου μηνύματος δεν είναι εγγυημένη σε αυτήν τη συσκευή." + "Κρυπτογραφημένο από άγνωστη ή διαγεγραμμένη συσκευή." + "Κρυπτογραφημένο από μια συσκευή που δεν έχει επαληθευτεί από τον ιδιοκτήτη της." + "Κρυπτογραφημένο από μη επαληθευμένο χρήστη." "🔐️ Έλα μαζί μου στο %1$s" "Γεια, μίλα μου στην εφαρμογή %1$s :%2$s" "%1$s Android" @@ -271,6 +277,9 @@ "Άρση αποκλεισμού" "Θα μπορείς να δεις ξανά όλα τα μηνύματα του." "Κατάργηση αποκλεισμού χρήστη" + "%1$s από %2$s" + "%1$s Καρφιτσωμένα μηνύματα" + "Προβολή Όλων" "Συνομιλία" "Κοινή χρήση τοποθεσίας" "Κοινή χρήση της τοποθεσίας μου" diff --git a/libraries/ui-strings/src/main/res/values-et/translations.xml b/libraries/ui-strings/src/main/res/values-et/translations.xml index dd76ad3d7e..d82d7cd5ab 100644 --- a/libraries/ui-strings/src/main/res/values-et/translations.xml +++ b/libraries/ui-strings/src/main/res/values-et/translations.xml @@ -80,6 +80,7 @@ "OK" "Seadistused" "Ava rakendusega" + "Kinnita" "Kiirvastus" "Tsiteeri" "Reageeri" @@ -256,6 +257,10 @@ Põhjus: %1$s." "Rakendusel %1$s puudub õigus sinu nutiseadme mikrofoni kasutada. Järgnevalt anna õigused heli salvestamiseks." "Mõned sõnumid on saatmata" "Vabandust, ilmnes viga" + "Selle krüptitud sõnumi tõepärasus pole selles seadmes tagatud." + "Krüptitud tundmatu või kustutatud seadme poolt." + "Krüptitud seadme poolt, mida tema omanik pole verifitseerinud." + "Krüptitud verifitseerimata kasutaja poolt." "🔐️ Liitu minuga rakenduses %1$s" "Hei, suhtle minuga %1$s võrgus: %2$s" "%1$s Android" @@ -272,6 +277,9 @@ Põhjus: %1$s." "Eemalda blokeering" "Nüüd näed sa jälle kõiki tema sõnumeid" "Eemalda kasutajalt blokeering" + "%1$s / %2$s" + "%1$s kinnitatud sõnumit" + "Näita kõiki" "Vestlus" "Jaga asukohta" "Jaga minu asukohta" diff --git a/libraries/ui-strings/src/main/res/values-hu/translations.xml b/libraries/ui-strings/src/main/res/values-hu/translations.xml index 9f973e7ef5..7692711037 100644 --- a/libraries/ui-strings/src/main/res/values-hu/translations.xml +++ b/libraries/ui-strings/src/main/res/values-hu/translations.xml @@ -80,6 +80,7 @@ "Rendben" "Beállítások megnyitása" "Megnyitás a következővel" + "Kitűzés" "Gyors válasz" "Idézet" "Reakció" @@ -168,6 +169,7 @@ Ok: %1$s." "Nincs találat" "Nincs szobanév" "Kapcsolat nélkül" + "Nyílt forráskódú licencek" "vagy" "Jelszó" "Emberek" @@ -255,6 +257,10 @@ Ok: %1$s." "Az %1$snek nincs engedélye, hogy hozzáférjen a mikrofonhoz. Engedélyezze, hogy tudjon hangüzenetet felvenni." "Néhány üzenet nem került elküldésre" "Elnézést, hiba történt" + "A titkosított üzenetek valódiságát ezen az eszközön nem lehet garantálni." + "Ismeretlen vagy törölt eszköz által titkosítva." + "A tulajdonos által nem ellenőrzött eszköz által titkosítva." + "Nem ellenőrzött felhasználó által titkosítva." "🔐️ Csatlakozz hozzám itt: %1$s" "Beszélgessünk itt: %1$s, %2$s" "%1$s Android" diff --git a/libraries/ui-strings/src/main/res/values-ka/translations.xml b/libraries/ui-strings/src/main/res/values-ka/translations.xml index fd0bc2c832..2661db369a 100644 --- a/libraries/ui-strings/src/main/res/values-ka/translations.xml +++ b/libraries/ui-strings/src/main/res/values-ka/translations.xml @@ -6,17 +6,31 @@ "%1$d ციფრი ჩაიწერა" "პაროლის დამალვა" + "ბოლოში გადასვლა" "მხოლოდ მოხსენიებები" "დადუმებულია" + "გვერდი %1$d" "პაუზა" "PIN ველი" "დაკვრა" "გამოკითხვა" "დასრულდა გამოკითხვა" + "რეაგირება %1$s-ით" + "რეაგირება სხვა ემოჯით" + "ნანახია %1$s-სა და %2$s-ს მიერ" + + "წაკითხულია %1$s და %2$d-ს ადამიანის მიერ" + "წაკითხულია %1$s და %2$d-ს ადამიანის მიერ" + + "წაიკითხეს: %s" + "შეეხეთ ყველაფრის საჩვენებლად" + "%1$s რეაქციის წაშლა" "ფაილების გაგზავნა" "პაროლის ჩვენება" + "დარეკვა" "მომხმარებლის მენიუ" "ხმოვანი შეტყობინების ჩაწერა." + "ჩაწერის შეწყვეტა" "მიღება" "დამატება ქრონოლოგიაში" "უკან" @@ -33,11 +47,14 @@ "შექმნა" "ოთახის შექმნა" "უარყოფა" + "გამოკითხვის წაშლა" "გამორთვა" "მზადაა" "რედაქტირება" "გამოკითხვის რედაქტირება" + "ჩართვა" "გამოკითხვის დასრულება" + "შეიყვანეთ PIN" "დაგავიწყდათ პაროლი?" "გადაგზავნა" "მოწვევა" @@ -49,6 +66,7 @@ "შეიტყვეთ მეტი" "დატოვება" "ოთახის დატოვება" + "მეტის ჩატვირთვა" "ანგარიშის მართვა" "მოწყობილობების მართვა" "შემდეგი" @@ -82,20 +100,25 @@ "დადასტურების დაწყება" "დააწკაპუნეთ რუკის ჩასატვირთად" "ფოტოს გადაღება" + "შეეხეთ ვარიანტების სანახავად" + "ხელახლა ცდა" "წყაროს ნახვა" "დიახ" "შესახებ" "მისაღები გამოყენების პოლიტიკა" "გაფართოებული პარამეტრები" "ანალიტიკა" + "გარეგნობა" "აუდიო" "ბუშტები" "ჩატის სარეზერვო ასლი" "საავტორო უფლება" "ოთახის შექმნა…" "დატოვა ოთახი" + "მუქი" "გაშიფვრის შეცდომა" "დეველოპერის პარამეტრები" + "პირდაპირი ჩატი" "(რედაქტირებულია)" "რედაქტირება" "* %1$s %2$s" @@ -112,6 +135,7 @@ "დააინსტალირეთ APK" "ეს Matrix ID ვერ მოიძებნა, ამიტომ მოწვევა შეიძლება არ იყოს მიღებული." "ოთახის დატოვება" + "ღია" "ბმული კოპირებულია გაცვლის ბუფერში" "იტვირთება…" @@ -119,6 +143,7 @@ "%1$d წევრები" "შეტყობინება" + "შეტყობინებაზე მოქმედებები" "შეტყობინებების ფორმა" "მესიჯი წაშლილია" "თანამედროვე" @@ -146,24 +171,31 @@ "განახლება…" "პასუხი %1$s-ს" "ხარვეზის შეტყობინება" + "შეტყობინება პრობლემაზე" "რეპორტი გაგზავნილია" "მდიდარი ტექსტის რედაქტორი" + "ოთახი" "ოთახის სახელი" "მაგ. თქვენი პროექტის სახელი" "ეკრანის დაბლოკვა" "ვიღაცის ძებნა" "ძიების შედეგები" "უსაფრთხოება" + "Ნანახი" "იგზავნება…" + "გაგზავნა ვერ მოხერხდა" + "გაგზავნილი" "სერვერი არ არის მხარდაჭერილი" "სერვერის ვებ-მისამართი" "პარამეტრები" "გაზიარებული მდებარეობა" + "გასვლა…" "ჩატის დაწყება…" "სტიკერი" "წარმატება" "შეთავაზებები" "სინქრონიზაცია" + "სისტემა" "ტექსტი" "მესამე პირის შენიშვნები" "თემა" @@ -178,9 +210,11 @@ "მომხმარებლის სახელი" "დადასტურება გაუქმდა" "დადასტურება დასრულებულია" + "დაადასტურეთ მოწყობილობა" "ვიდეო" "ხმოვანი შეტყობინება" "მოცდა…" + "ლოდინი ამ შეტყობინებისათვის" "დადასტურება" "შეცდომა" "წარმატება" @@ -189,6 +223,7 @@ "ვერ გამოვიდა რუკის %1$s ჩატვირთვა. გთხოვთ, მოგვიანებით სცადოთ." "შეტყობინებების ჩატვირთვა ვერ მოხერხდა" "%1$s ვერ მოახერხა თქვენი ადგილმდებარეობაზე წვდომა. გთხოვთ, მოგვიანებით სცადოთ." + "თქვენი ხმოვანი შეტყობინების ატვირთვა ვერ მოხერხდა." "%1$s არ აქვს თქვენს ადგილმდებარეობაზე წვდომის ნებართვა. შეგიძლიათ ჩართოთ წვდომა პარამეტრებში." "%1$s არ აქვს თქვენს ადგილმდებარეობაზე წვდომის ნებართვა. ჩართეთ წვდომა ქვემოთ" "%1$s არ აქვს თქვენს მიკროფონზე წვდომის ნებართვა. ჩართეთ წვდომა ხმოვანი შეტყობინების ჩასაწერად." diff --git a/libraries/ui-strings/src/main/res/values-pl/translations.xml b/libraries/ui-strings/src/main/res/values-pl/translations.xml new file mode 100644 index 0000000000..5580f93974 --- /dev/null +++ b/libraries/ui-strings/src/main/res/values-pl/translations.xml @@ -0,0 +1,287 @@ + + + "Usuń" + + "Wprowadzono %1$d cyfrę" + "Wprowadzono %1$d cyfry" + "Wprowadzono %1$d cyfr" + + "Ukryj hasło" + "Przejdź na dół" + "Tylko wzmianki" + "Wyciszone" + "Strona %1$d" + "Wstrzymaj" + "Pole PIN" + "Odtwórz" + "Ankieta" + "Zakończona ankieta" + "Zareaguj z %1$s" + "Zareaguj innym emoji" + "Odczytane przez %1$s i %2$s" + + "Odczytano przez %1$s i %2$d inną" + "Odczytano przez %1$s i %2$d innych" + "Odczytano przez %1$s i %2$d innych" + + "Odczytane przez %1$s" + "Stuknij, aby pokazać wszystkich" + "Usuń reakcję %1$s" + "Wyślij pliki" + "Pokaż hasło" + "Rozpocznij rozmowę" + "Menu użytkownika" + "Nagraj wiadomość głosową." + "Zatrzymaj nagrywanie" + "Akceptuj" + "Dodaj do osi czasu" + "Wróć" + "Zadzwoń" + "Anuluj" + "Wybierz zdjęcie" + "Wyczyść" + "Zamknij" + "Dokończ weryfikację" + "Potwierdź" + "Kontynuuj" + "Kopiuj" + "Kopiuj link" + "Kopiuj link do wiadomości" + "Utwórz" + "Utwórz pokój" + "Odrzuć" + "Usuń ankietę" + "Wyłącz" + "Odrzuć" + "Gotowe" + "Edytuj" + "Edytuj ankietę" + "Włącz" + "Zakończ ankietę" + "Wprowadź PIN" + "Nie pamiętasz hasła?" + "Dalej" + "Wróć" + "Zaproś" + "Zaproś znajomych" + "Zaproś znajomych do %1$s" + "Zaproś ludzi do %1$s" + "Zaproszenia" + "Dołącz" + "Dowiedz się więcej" + "Opuść" + "Opuść rozmowę" + "Opuść pokój" + "Załaduj więcej" + "Zarządzaj kontem" + "Zarządzaj urządzeniami" + "Wiadomość" + "Dalej" + "Nie" + "Nie teraz" + "Ok" + "Ustawienia" + "Otwórz za pomocą" + "Szybka odpowiedź" + "Cytuj" + "Dodaj reakcję" + "Odrzuć" + "Usuń" + "Odpowiedz" + "Odpowiedz w wątku" + "Zgłoś błąd" + "Zgłoś treść" + "Resetuj" + "Spróbuj ponownie" + "Ponów próbę odszyfrowania" + "Zapisz" + "Szukaj" + "Wyślij" + "Wyślij wiadomość" + "Udostępnij" + "Udostępnij link" + "Zaloguj się ponownie" + "Wyloguj się" + "Wyloguj się mimo to" + "Pomiń" + "Rozpocznij" + "Rozpocznij chat" + "Rozpocznij weryfikację" + "Stuknij, aby załadować mapę" + "Zrób zdjęcie" + "Stuknij, by wyświetlić opcje" + "Spróbuj ponownie" + "Wyświetl źródło" + "Tak" + "O programie" + "Polityka użytkowania" + "Ustawienia zaawansowane" + "Analityka" + "Wygląd" + "Dźwięk" + "Zablokowani użytkownicy" + "Bąbelki" + "Rozmowa w trakcie (niewspierane)" + "Rozpoczęto rozmowę" + "Backup czatu" + "Copyright" + "Tworzenie pokoju…" + "Opuścił pokój" + "Ciemny" + "Błąd deszyfrowania" + "Opcje programisty" + "Czat prywatny" + "Nie pokazuj ponownie" + "(edytowane)" + "Edytowanie" + "* %1$s %2$s" + "Szyfrowanie włączone" + "Wprowadź kod PIN" + "Błąd" + "Wystąpił błąd, możesz nie otrzymać powiadomień nowych wiadomości. Spróbuj naprawić powiadomienia w ustawieniach. + +Powód: %1$s." + "Wszyscy" + "Niepowodzenie" + "Ulubione" + "Ulubione" + "Plik" + "Plik zapisany do folderu Pobrane" + "Przekaż wiadomość" + "GIF" + "Zdjęcie" + "W odpowiedzi do %1$s" + "Zainstaluj APK" + "Nie można znaleźć identyfikatora Matrix ID, zaproszenie mogło nie dotrzeć." + "Opuszczanie pokoju" + "Jasny" + "Link został skopiowany do schowka" + "Ładowanie…" + + "%1$d członek" + "%1$d członki" + "%1$d członków" + + "Wiadomość" + "Akcje wiadomości" + "Układ wiadomości" + "Wiadomość usunięta" + "Nowoczesny" + "Wycisz" + "Brak wyników" + "Brak nazwy pokoju" + "Offline" + "Licencje open-source" + "lub" + "Hasło" + "Osoby" + "Link bezpośredni" + "Uprawnienie" + "Proszę czekać…" + "Jesteś pewien, że chcesz zakończyć tę ankietę?" + "Ankieta: %1$s" + "Łączna liczba głosów: %1$s" + "Wyniki zostaną wyświetlone po zakończeniu ankiety" + + "%d głos" + "%d głosy" + "%d głosów" + + "Polityka prywatności" + "Reakcja" + "Reakcje" + "Klucz przywracania" + "Odświeżanie…" + "Odpowiadanie do %1$s" + "Zgłoś błąd" + "Zgłoś problem" + "Zgłoszenie wysłane" + "Bogaty edytor tekstu" + "Pokój" + "Nazwa pokoju" + "np. nazwa projektu" + "Zapisano zmiany" + "Zapisywanie" + "Blokada ekranu" + "Wyszukaj kogoś" + "Wyniki wyszukiwania" + "Bezpieczeństwo" + "Wyświetlone przez" + "Wyślij do" + "Wysyłanie…" + "Błąd wysyłania" + "Wysłano" + "Serwer nie jest obsługiwany" + "Adres URL serwera" + "Ustawienia" + "Udostępniona lokalizacja" + "Wylogowywanie" + "Coś poszło nie tak" + "Rozpoczynanie czatu…" + "Naklejka" + "Sukces" + "Sugestie" + "Synchronizuję" + "System" + "Tekst" + "Informacje stron trzecich" + "Wątek" + "Temat" + "O czym jest ten pokój?" + "Nie można odszyfrować" + "Nie masz uprawnień do tej wiadomości" + "Nie udało się wysłać zaproszenia do jednego lub więcej użytkowników." + "Nie można wysłać zaproszeń" + "Odblokuj" + "Wyłącz wyciszenie" + "Nieobsługiwane zdarzenie" + "Nazwa użytkownika" + "Weryfikacja anulowana" + "Weryfikacja zakończona" + "Weryfikuj urządzenie" + "Film" + "Wiadomość głosowa" + "Oczekiwanie…" + "Oczekiwanie na tę wiadomość" + "Potwierdzenie" + "Błąd" + "Sukces" + "Ostrzeżenie" + "Zmiany nie zostały zapisane. Czy na pewno chcesz wrócić?" + "Zapisać zmiany?" + "Nie udało się utworzyć linku bezpośredniego" + "%1$s nie mogło wczytać mapy. Spróbuj ponownie później." + "Nie udało się załadować wiadomości" + "%1$s nie mógł uzyskać dostępu do Twojej lokalizacji. Spróbuj ponownie później." + "Nie udało się przesłać Twojej wiadomości głosowej." + "Nie znaleziono wiadomości" + "%1$s nie uzyskało uprawnienia do dostępu do twojej lokalizacji. Możesz włączyć dostęp w Ustawieniach." + "%1$s nie ma uprawnień dostępu do Twojej lokalizacji. Włącz dostęp poniżej." + "%1$s nie ma uprawnień dostępu do Twojego mikrofonu. Włącz dostęp, aby nagrać wiadomość głosową." + "Niektóre wiadomości nie zostały wysłane" + "Przepraszamy, wystąpił błąd" + "🔐️ Dołącz do mnie na %1$s" + "Hej, porozmawiajmy na %1$s: %2$s" + "%1$s Android" + "Gniewne wstrząsanie, aby zgłosić błąd" + "Nie udało się wybrać multimediów. Spróbuj ponownie." + "Przetwarzanie multimediów do przesłania nie powiodło się, spróbuj ponownie." + "Przesyłanie multimediów nie powiodło się, spróbuj ponownie." + "Przetwarzanie multimediów do przesłania nie powiodło się, spróbuj ponownie." + "Nie można pobrać danych użytkownika" + "Zablokuj" + "Zablokowani użytkownicy nie będą mogli wysyłać Ci wiadomości, a wszystkie ich wiadomości zostaną ukryte. Możesz odblokować ich w dowolnym momencie." + "Zablokuj użytkownika" + "Odblokuj" + "Będziesz mógł ponownie zobaczyć wszystkie wiadomości od tego użytkownika." + "Odblokuj użytkownika" + "Udostępnij lokalizację" + "Udostępnij moją lokalizację" + "Otwórz w Apple Maps" + "Otwórz w Google Maps" + "Otwórz w OpenStreetMap" + "Udostępnij tę lokalizację" + "Lokalizacja" + "Wersja: %1$s (%2$s)" + "pl" + diff --git a/libraries/ui-strings/src/main/res/values-pt-rBR/translations.xml b/libraries/ui-strings/src/main/res/values-pt-rBR/translations.xml new file mode 100644 index 0000000000..10cd8e39cf --- /dev/null +++ b/libraries/ui-strings/src/main/res/values-pt-rBR/translations.xml @@ -0,0 +1,275 @@ + + + "Excluir" + "Ocultar senha" + "Ir para o final" + "Apenas menções" + "Silenciado" + "Página %1$d" + "Pausar" + "Campo de PIN" + "Reproduzir" + "Enquete" + "Enquete encerrada" + "Reagir com %1$s" + "Reaja com outros emojis" + "Lido por %1$s e %2$s" + "Lido por %1$s" + "Toque para mostrar tudo" + "Remova a reação com %1$s" + "Enviar arquivos" + "Mostrar senha" + "Iniciar uma chamada" + "Menu do usuário" + "Gravar mensagem de voz." + "Parar gravação" + "Aceitar" + "Adicionar à linha do tempo" + "Voltar" + "Chamar" + "Cancelar" + "Escolher foto" + "Limpar" + "Fechar" + "Verificação completa" + "Confirmar" + "Continuar" + "Copiar" + "Copiar link" + "Copiar link para a mensagem" + "Criar" + "Criar uma sala" + "Recusar" + "Excluir Enquete" + "Desabilitar" + "Descartar" + "Concluído" + "Editar" + "Editar enquete" + "Habilitar" + "Encerrar enquete" + "Inserir PIN" + "Esqueceu a senha?" + "Encaminhar" + "Voltar" + "Convidar" + "Convidar pessoas" + "Convidar pessoas para %1$s" + "Convide pessoas para %1$s" + "Convites" + "Entrar" + "Saber mais" + "Sair" + "Sair da conversa" + "Sair da sala" + "Carregar mais" + "Gerenciar conta" + "Gerenciar dispositivos" + "Mensagem" + "Próximo" + "Não" + "Agora não" + "OK" + "Configurações" + "Abrir com" + "Fixar" + "Resposta rápida" + "Citação" + "Reagir" + "Recusar" + "Remover" + "Responder" + "Responder no tópico" + "Reportar erro" + "Denunciar conteúdo" + "Redefinir" + "Tentar novamente" + "Tente descriptografar novamente" + "Salvar" + "Pesquisar" + "Enviar" + "Enviar mensagem" + "Compartilhar" + "Compartilhar link" + "Iniciar sessão novamente" + "Sair" + "Sair mesmo assim" + "Pular" + "Começar" + "Iniciar bate-papo" + "Iniciar verificação" + "Toque para carregar o mapa" + "Tirar foto" + "Toque para opções" + "Tente novamente" + "Ver fonte" + "Sim" + "Sobre" + "Política de uso aceitável" + "Configurações avançadas" + "Telemetria" + "Aparência" + "Áudio" + "Usuários bloqueados" + "Bolhas" + "Chamada em progresso (sem suporte)" + "Chamada iniciada" + "Backup de conversas" + "Direitos autorais" + "Criando sala…" + "Saiu da sala" + "Escuro" + "Erro de descriptografia" + "Opções do desenvolvedor" + "Conversa privada" + "Não mostrar isto novamente" + "(editado)" + "Editando" + "* %1$s %2$s" + "Criptografia ativada" + "Insira seu PIN" + "Erro" + "Todos" + "Falhou" + "Favorito" + "Favoritado" + "Arquivo" + "Arquivo salvo em Downloads" + "Encaminhar mensagem" + "GIF" + "Imagem" + "Em resposta a %1$s" + "Instalar APK" + "Este ID Matrix não foi encontrado, então o convite pode não ser recebido" + "Saindo da sala" + "Claro" + "Link copiado para área de transferência" + "Carregando…" + + "%1$d membro" + "%1$d membros" + + "Mensagem" + "Ações de mensagem" + "Layout da mensagem" + "Mensagem removida" + "Moderno" + "Silenciar" + "Sem resultados" + "Sem nome de sala" + "Offline" + "Licenças de código aberto" + "ou" + "Senha" + "Pessoas" + "Link permanente" + "Permissão" + "Por favor, aguarde…" + "Tem certeza de que deseja encerrar esta enquete?" + "Enquete: %1$s" + "Total de votos: %1$s" + "Os resultados serão exibidos após o término da enquete" + + "%d voto" + "%d votos" + + "Política de Privacidade" + "Reação" + "Reações" + "Chave de recuperação" + "Atualizando…" + "Respondendo a %1$s" + "Reportar um erro" + "Reportar um problema" + "Relatório enviado" + "Editor de rich text" + "Sala" + "Nome da sala" + "por exemplo, o nome do seu projeto" + "Mudanças salvas" + "Salvando" + "Bloqueio de tela" + "Procurar alguém" + "Resultados da busca" + "Segurança" + "Visto por" + "Enviar para" + "Enviando…" + "Envio falhou" + "Enviado" + "Servidor não suportado" + "URL do Servidor" + "Configurações" + "Localização compartilhada" + "Saindo" + "Algo deu errado" + "Iniciando o chat…" + "Adesivo" + "Sucesso" + "Sugestões" + "Sincronizando" + "Sistema" + "Texto" + "Avisos de terceiros" + "Tópico" + "Tópico" + "Sobre o que é essa sala?" + "Não é possível descriptografar" + "Você não tem acesso a esta mensagem" + "Não foi possível enviar convites para um ou mais usuários." + "Não foi possível enviar o(s) convite(s)" + "Desbloquear" + "Desmutar" + "Evento não suportado" + "Nome do usuário" + "Verificação cancelada" + "Verificação concluída" + "Verificar dispositivo" + "Vídeo" + "Mensagem de voz" + "Esperando…" + "Aguardando esta mensagem" + "Confirmação" + "Erro" + "Sucesso" + "Aviso" + "Suas mudanças não foram salvas. Tem certeza de que você quer voltar?" + "Salvar mudanças?" + "Falha ao criar o link permanente" + "%1$s não conseguiu carregar o mapa. Por favor, tente novamente mais tarde." + "Falha ao carregar mensagens" + "%1$s não conseguiu acessar sua localização. Por favor, tente novamente mais tarde." + "Falha ao enviar sua mensagem de voz." + "Mensagem não encontrada" + "%1$s não tem permissão para acessar sua localização. Você pode ativar o acesso nas Configurações." + "%1$s não tem permissão para acessar sua localização. Habilite o acesso abaixo." + "Algumas mensagens não foram enviadas" + "Desculpe, ocorreu um erro" + "Criptografada por um dispositivo desconhecido ou apagado." + "Criptografado por um dispositivo que não foi verificado pelo seu dono." + "Criptografado por um usuário não verificado." + "🔐️ Junte-se a mim no %1$s" + "Ei, fale comigo em %1$s: %2$s" + "%1$s Android" + "Rageshake para relatar um bug" + "Falha ao selecionar a mídia, tente novamente." + "Falha ao processar mídia para upload. Tente novamente." + "Falha ao enviar mídia. Tente novamente." + "Falha ao processar mídia para upload. Tente novamente." + "Não foi possível recuperar os detalhes do usuário" + "Bloquear" + "Usuários bloqueados não poderão enviar mensagens para você e todas as mensagens deles serão ocultadas. Você pode desbloqueá-los a qualquer momento." + "Bloquear usuário" + "Desbloquear" + "Você poderá ver todas as mensagens deles novamente." + "Desbloquear usuário" + "Compartilhar localização" + "Compartilhar minha localização" + "Abrir no Apple Maps" + "Abrir no Google Maps" + "Abrir no OpenStreetMap" + "Compartilhe esta localização" + "Localização" + "Versão: %1$s (%2$s)" + "pt-br" + diff --git a/libraries/ui-strings/src/main/res/values-sk/translations.xml b/libraries/ui-strings/src/main/res/values-sk/translations.xml index b0afeacc8d..1eb3fa1c47 100644 --- a/libraries/ui-strings/src/main/res/values-sk/translations.xml +++ b/libraries/ui-strings/src/main/res/values-sk/translations.xml @@ -82,6 +82,7 @@ "OK" "Otvoriť nastavenia" "Otvoriť pomocou" + "Pripnúť" "Rýchla odpoveď" "Citovať" "Reagovať" @@ -260,6 +261,10 @@ Dôvod: %1$s." "%1$s nemá povolenie na prístup k vášmu mikrofónu. Povoľte prístup na nahrávanie hlasovej správy." "Niektoré správy neboli odoslané" "Prepáčte, vyskytla sa chyba" + "Pravosť tejto šifrovanej správy nie je možné zaručiť na tomto zariadení." + "Zašifrované neznámym alebo odstráneným zariadením." + "Šifrované zariadením, ktoré nie je overené jeho majiteľom." + "Šifrované neovereným používateľom." "🔐️ Pripojte sa ku mne na %1$s" "Ahoj, porozprávajte sa so mnou na %1$s: %2$s" "%1$s Android" @@ -276,6 +281,9 @@ Dôvod: %1$s." "Odblokovať" "Všetky správy od nich budete môcť opäť vidieť." "Odblokovať používateľa" + "%1$s z %2$s" + "%1$s Pripnutých správ" + "Zobraziť všetko" "Konverzácia" "Zdieľať polohu" "Zdieľať moju polohu" diff --git a/libraries/ui-strings/src/main/res/values/localazy.xml b/libraries/ui-strings/src/main/res/values/localazy.xml index c484bc6374..c5d8f46622 100644 --- a/libraries/ui-strings/src/main/res/values/localazy.xml +++ b/libraries/ui-strings/src/main/res/values/localazy.xml @@ -80,6 +80,7 @@ "OK" "Settings" "Open with" + "Pin" "Quick reply" "Quote" "React" @@ -256,6 +257,10 @@ Reason: %1$s." "%1$s does not have permission to access your microphone. Enable access to record a voice message." "Some messages have not been sent" "Sorry, an error occurred" + "The authenticity of this encrypted message can\'t be guaranteed on this device." + "Encrypted by an unknown or deleted device." + "Encrypted by a device not verified by its owner." + "Encrypted by an unverified user." "🔐️ Join me on %1$s" "Hey, talk to me on %1$s: %2$s" "%1$s Android" @@ -272,6 +277,9 @@ Reason: %1$s." "Unblock" "You\'ll be able to see all messages from them again." "Unblock user" + "%1$s of %2$s" + "%1$s Pinned messages" + "View All" "Chat" "Share location" "Share my location" diff --git a/plugins/src/main/kotlin/extension/locales.kt b/plugins/src/main/kotlin/extension/locales.kt index af0f685e62..18cd3d5531 100644 --- a/plugins/src/main/kotlin/extension/locales.kt +++ b/plugins/src/main/kotlin/extension/locales.kt @@ -16,7 +16,9 @@ val locales = setOf( "in", "it", "ka", + "pl", "pt", + "pt-rBR", "ro", "ru", "sk", diff --git a/screenshots/de/features.call.impl.ui_IncomingCallScreen_Day_0_de.png b/screenshots/de/features.call.impl.ui_IncomingCallScreen_Day_0_de.png index e66523ad20..0edabb595c 100644 --- a/screenshots/de/features.call.impl.ui_IncomingCallScreen_Day_0_de.png +++ b/screenshots/de/features.call.impl.ui_IncomingCallScreen_Day_0_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:0fbdd719abf34469fe3e3b517cc68c55eee49e86a79b9c87ac75d7ad42cbb41b -size 66701 +oid sha256:c6b0b146cbd6cb3d1781e289cb37098e8ec3ed840d90144e30661b6dcfc52dc2 +size 67697 diff --git a/screenshots/de/features.joinroom.impl_JoinRoomView_Day_5_de.png b/screenshots/de/features.joinroom.impl_JoinRoomView_Day_5_de.png index 60d32de9bf..17824149f3 100644 --- a/screenshots/de/features.joinroom.impl_JoinRoomView_Day_5_de.png +++ b/screenshots/de/features.joinroom.impl_JoinRoomView_Day_5_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:0744d5034d20fcdead4c13efc2c196fa42683c5c906a2f03f3895963bba2b077 -size 111554 +oid sha256:b1ba6af03637be89d0e9459c1586cad6f6cf6bcf72ae787d4f2d42262e17484e +size 112189 diff --git a/screenshots/de/features.joinroom.impl_JoinRoomView_Day_6_de.png b/screenshots/de/features.joinroom.impl_JoinRoomView_Day_6_de.png index 98bebb1d16..e402b05716 100644 --- a/screenshots/de/features.joinroom.impl_JoinRoomView_Day_6_de.png +++ b/screenshots/de/features.joinroom.impl_JoinRoomView_Day_6_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:767dac0e8558e6f96ca3f2cfc9991228e0708f88259c9a078079bbd2288e93f8 -size 120401 +oid sha256:63b72654e614e8121f44ddd7ffcafa32e0149572da48e06942e12209afc18da8 +size 121031 diff --git a/screenshots/de/features.preferences.impl.about_AboutView_Day_1_de.png b/screenshots/de/features.preferences.impl.about_AboutView_Day_1_de.png new file mode 100644 index 0000000000..a536bbcb87 --- /dev/null +++ b/screenshots/de/features.preferences.impl.about_AboutView_Day_1_de.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:1b5727816f00d86c4de5719f872e38d352d72c20d725457d2bc314269d9458a3 +size 19334 diff --git a/screenshots/de/features.roomdetails.impl.members_RoomMemberListView_Day_8_de.png b/screenshots/de/features.roomdetails.impl.members_RoomMemberListView_Day_8_de.png new file mode 100644 index 0000000000..8055489688 --- /dev/null +++ b/screenshots/de/features.roomdetails.impl.members_RoomMemberListView_Day_8_de.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:1f36c4fc25cfc9ba31e564d5c0f5520f4f3b08eb7bf839d6ed35bc4e1e1c9898 +size 21857 diff --git a/screenshots/de/features.roomlist.impl.components_RoomListContentView_Day_0_de.png b/screenshots/de/features.roomlist.impl.components_RoomListContentView_Day_0_de.png index c7d799cfc1..0bb97a8ca1 100644 --- a/screenshots/de/features.roomlist.impl.components_RoomListContentView_Day_0_de.png +++ b/screenshots/de/features.roomlist.impl.components_RoomListContentView_Day_0_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:ba8b30a4a308fdcccbf4c4cc59b250617b172c187e95190bf3534b3879b15888 -size 43244 +oid sha256:e4892d99758f54f2068d88ae1127dba04279e45cb7d37cb763102778342e5644 +size 43388 diff --git a/screenshots/de/features.roomlist.impl.components_RoomSummaryRow_Day_29_de.png b/screenshots/de/features.roomlist.impl.components_RoomSummaryRow_Day_29_de.png index f0c88d3ddf..8afde4ac90 100644 --- a/screenshots/de/features.roomlist.impl.components_RoomSummaryRow_Day_29_de.png +++ b/screenshots/de/features.roomlist.impl.components_RoomSummaryRow_Day_29_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:d10427ce684281390612c5d29f6112763115833769ec52301d0f4973df3ed9f6 -size 24660 +oid sha256:ad87fa6f2569c062f850a4d9baded2611a62863234d14f8d55f788565f4a69e0 +size 24913 diff --git a/screenshots/de/features.roomlist.impl.components_RoomSummaryRow_Day_30_de.png b/screenshots/de/features.roomlist.impl.components_RoomSummaryRow_Day_30_de.png index 31781f9682..e11b50f599 100644 --- a/screenshots/de/features.roomlist.impl.components_RoomSummaryRow_Day_30_de.png +++ b/screenshots/de/features.roomlist.impl.components_RoomSummaryRow_Day_30_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:a71c97854181e12f3e087e42fe5d78a664b676d589e4750f7bd3e781bde30f25 -size 16198 +oid sha256:8047e54fce6fead740d55b68fe3e7196456a662c9cec7c535188d5934db6fc14 +size 16432 diff --git a/screenshots/de/features.roomlist.impl.components_RoomSummaryRow_Day_31_de.png b/screenshots/de/features.roomlist.impl.components_RoomSummaryRow_Day_31_de.png index 12f8759a66..e97fb12608 100644 --- a/screenshots/de/features.roomlist.impl.components_RoomSummaryRow_Day_31_de.png +++ b/screenshots/de/features.roomlist.impl.components_RoomSummaryRow_Day_31_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:d77d9d8541a5d64606c7ec1373f410419337b7d5e8ebfa8a6938171a4c384f36 -size 23618 +oid sha256:d2e42363661590d5cfcc6c22c2411a978c54936a615c892adf2a97901f427276 +size 23767 diff --git a/screenshots/de/features.roomlist.impl.search_RoomListSearchContent_Day_2_de.png b/screenshots/de/features.roomlist.impl.search_RoomListSearchContent_Day_2_de.png index 65de793cee..8730001b88 100644 --- a/screenshots/de/features.roomlist.impl.search_RoomListSearchContent_Day_2_de.png +++ b/screenshots/de/features.roomlist.impl.search_RoomListSearchContent_Day_2_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:e22bf2f6d5f545208585fc06209a92a89a1cc11ffcce76c8544c60b2d1402fdc -size 45418 +oid sha256:753bb5fce99d8bfb7a48f4a588f72542876dc4b91aa412601a53e92c0c1945a2 +size 45580 diff --git a/screenshots/de/features.roomlist.impl_RoomListView_Day_0_de.png b/screenshots/de/features.roomlist.impl_RoomListView_Day_0_de.png index bd5652d305..1c21047f3e 100644 --- a/screenshots/de/features.roomlist.impl_RoomListView_Day_0_de.png +++ b/screenshots/de/features.roomlist.impl_RoomListView_Day_0_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:5e74213737770bebd0967daf2b9ac70fca4b60d2ccdb67a293834b8a93217c32 -size 81679 +oid sha256:3d70a66e47a821c047c3f2a90ad89c82030f8adb0955473c8ea6d0aa7f21c8a1 +size 81946 diff --git a/screenshots/de/features.roomlist.impl_RoomListView_Day_1_de.png b/screenshots/de/features.roomlist.impl_RoomListView_Day_1_de.png index bd5652d305..1c21047f3e 100644 --- a/screenshots/de/features.roomlist.impl_RoomListView_Day_1_de.png +++ b/screenshots/de/features.roomlist.impl_RoomListView_Day_1_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:5e74213737770bebd0967daf2b9ac70fca4b60d2ccdb67a293834b8a93217c32 -size 81679 +oid sha256:3d70a66e47a821c047c3f2a90ad89c82030f8adb0955473c8ea6d0aa7f21c8a1 +size 81946 diff --git a/screenshots/de/features.roomlist.impl_RoomListView_Day_2_de.png b/screenshots/de/features.roomlist.impl_RoomListView_Day_2_de.png index b6a26731b4..cba60e3f68 100644 --- a/screenshots/de/features.roomlist.impl_RoomListView_Day_2_de.png +++ b/screenshots/de/features.roomlist.impl_RoomListView_Day_2_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:256a146c03de0b5fe04aba624f73be082479e45d45236eb393bd8737a6a1e031 -size 81696 +oid sha256:d4b26596fcdbbdd32d379f18650d826773a351c39e0fedf4abcc2a36a03f9207 +size 81964 diff --git a/screenshots/de/features.roomlist.impl_RoomListView_Day_6_de.png b/screenshots/de/features.roomlist.impl_RoomListView_Day_6_de.png index 75b3ed3270..a485b1fcb6 100644 --- a/screenshots/de/features.roomlist.impl_RoomListView_Day_6_de.png +++ b/screenshots/de/features.roomlist.impl_RoomListView_Day_6_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:165fa9f52ab3e21ccaa8088dea1111c394408cb96ee335742ffa0fabc5415745 -size 103924 +oid sha256:f27f9e5960390f3940a1423e7e22494742c3aad535bb1b3453c1d9eae9f7dd5f +size 104133 diff --git a/screenshots/html/data.js b/screenshots/html/data.js index 5dfdc7048c..76259f7913 100644 --- a/screenshots/html/data.js +++ b/screenshots/html/data.js @@ -1,39 +1,40 @@ // Generated file, do not edit export const screenshots = [ ["en","en-dark","de",], -["features.preferences.impl.about_AboutView_Day_0_en","features.preferences.impl.about_AboutView_Night_0_en",19916,], +["features.preferences.impl.about_AboutView_Day_0_en","features.preferences.impl.about_AboutView_Night_0_en",19923,], +["features.preferences.impl.about_AboutView_Day_1_en","features.preferences.impl.about_AboutView_Night_1_en",19926,], ["features.invite.impl.response_AcceptDeclineInviteView_Day_0_en","features.invite.impl.response_AcceptDeclineInviteView_Night_0_en",0,], -["features.invite.impl.response_AcceptDeclineInviteView_Day_1_en","features.invite.impl.response_AcceptDeclineInviteView_Night_1_en",19916,], -["features.invite.impl.response_AcceptDeclineInviteView_Day_2_en","features.invite.impl.response_AcceptDeclineInviteView_Night_2_en",19916,], -["features.invite.impl.response_AcceptDeclineInviteView_Day_3_en","features.invite.impl.response_AcceptDeclineInviteView_Night_3_en",19916,], -["features.invite.impl.response_AcceptDeclineInviteView_Day_4_en","features.invite.impl.response_AcceptDeclineInviteView_Night_4_en",19916,], +["features.invite.impl.response_AcceptDeclineInviteView_Day_1_en","features.invite.impl.response_AcceptDeclineInviteView_Night_1_en",19923,], +["features.invite.impl.response_AcceptDeclineInviteView_Day_2_en","features.invite.impl.response_AcceptDeclineInviteView_Night_2_en",19923,], +["features.invite.impl.response_AcceptDeclineInviteView_Day_3_en","features.invite.impl.response_AcceptDeclineInviteView_Night_3_en",19923,], +["features.invite.impl.response_AcceptDeclineInviteView_Day_4_en","features.invite.impl.response_AcceptDeclineInviteView_Night_4_en",19923,], ["features.login.impl.accountprovider_AccountProviderView_Day_0_en","features.login.impl.accountprovider_AccountProviderView_Night_0_en",0,], ["features.login.impl.accountprovider_AccountProviderView_Day_1_en","features.login.impl.accountprovider_AccountProviderView_Night_1_en",0,], ["features.login.impl.accountprovider_AccountProviderView_Day_2_en","features.login.impl.accountprovider_AccountProviderView_Night_2_en",0,], ["features.login.impl.accountprovider_AccountProviderView_Day_3_en","features.login.impl.accountprovider_AccountProviderView_Night_3_en",0,], ["features.login.impl.accountprovider_AccountProviderView_Day_4_en","features.login.impl.accountprovider_AccountProviderView_Night_4_en",0,], -["features.createroom.impl.addpeople_AddPeopleView_Day_0_en","features.createroom.impl.addpeople_AddPeopleView_Night_0_en",19916,], -["features.createroom.impl.addpeople_AddPeopleView_Day_1_en","features.createroom.impl.addpeople_AddPeopleView_Night_1_en",19916,], -["features.createroom.impl.addpeople_AddPeopleView_Day_2_en","features.createroom.impl.addpeople_AddPeopleView_Night_2_en",19916,], -["features.createroom.impl.addpeople_AddPeopleView_Day_3_en","features.createroom.impl.addpeople_AddPeopleView_Night_3_en",19916,], -["features.preferences.impl.advanced_AdvancedSettingsView_Day_0_en","features.preferences.impl.advanced_AdvancedSettingsView_Night_0_en",19916,], -["features.preferences.impl.advanced_AdvancedSettingsView_Day_1_en","features.preferences.impl.advanced_AdvancedSettingsView_Night_1_en",19916,], -["features.preferences.impl.advanced_AdvancedSettingsView_Day_2_en","features.preferences.impl.advanced_AdvancedSettingsView_Night_2_en",19916,], -["features.preferences.impl.advanced_AdvancedSettingsView_Day_3_en","features.preferences.impl.advanced_AdvancedSettingsView_Night_3_en",19916,], -["features.analytics.impl_AnalyticsOptInView_Day_0_en","features.analytics.impl_AnalyticsOptInView_Night_0_en",19916,], -["features.analytics.api.preferences_AnalyticsPreferencesView_Day_0_en","features.analytics.api.preferences_AnalyticsPreferencesView_Night_0_en",19916,], -["features.preferences.impl.analytics_AnalyticsSettingsView_Day_0_en","features.preferences.impl.analytics_AnalyticsSettingsView_Night_0_en",19916,], -["services.apperror.impl_AppErrorView_Day_0_en","services.apperror.impl_AppErrorView_Night_0_en",19916,], +["features.createroom.impl.addpeople_AddPeopleView_Day_0_en","features.createroom.impl.addpeople_AddPeopleView_Night_0_en",19923,], +["features.createroom.impl.addpeople_AddPeopleView_Day_1_en","features.createroom.impl.addpeople_AddPeopleView_Night_1_en",19923,], +["features.createroom.impl.addpeople_AddPeopleView_Day_2_en","features.createroom.impl.addpeople_AddPeopleView_Night_2_en",19923,], +["features.createroom.impl.addpeople_AddPeopleView_Day_3_en","features.createroom.impl.addpeople_AddPeopleView_Night_3_en",19923,], +["features.preferences.impl.advanced_AdvancedSettingsView_Day_0_en","features.preferences.impl.advanced_AdvancedSettingsView_Night_0_en",19923,], +["features.preferences.impl.advanced_AdvancedSettingsView_Day_1_en","features.preferences.impl.advanced_AdvancedSettingsView_Night_1_en",19923,], +["features.preferences.impl.advanced_AdvancedSettingsView_Day_2_en","features.preferences.impl.advanced_AdvancedSettingsView_Night_2_en",19923,], +["features.preferences.impl.advanced_AdvancedSettingsView_Day_3_en","features.preferences.impl.advanced_AdvancedSettingsView_Night_3_en",19923,], +["features.analytics.impl_AnalyticsOptInView_Day_0_en","features.analytics.impl_AnalyticsOptInView_Night_0_en",19923,], +["features.analytics.api.preferences_AnalyticsPreferencesView_Day_0_en","features.analytics.api.preferences_AnalyticsPreferencesView_Night_0_en",19923,], +["features.preferences.impl.analytics_AnalyticsSettingsView_Day_0_en","features.preferences.impl.analytics_AnalyticsSettingsView_Night_0_en",19923,], +["services.apperror.impl_AppErrorView_Day_0_en","services.apperror.impl_AppErrorView_Night_0_en",19923,], ["libraries.designsystem.components.async_AsyncActionView_Day_0_en","libraries.designsystem.components.async_AsyncActionView_Night_0_en",0,], -["libraries.designsystem.components.async_AsyncActionView_Day_1_en","libraries.designsystem.components.async_AsyncActionView_Night_1_en",19916,], +["libraries.designsystem.components.async_AsyncActionView_Day_1_en","libraries.designsystem.components.async_AsyncActionView_Night_1_en",19923,], ["libraries.designsystem.components.async_AsyncActionView_Day_2_en","libraries.designsystem.components.async_AsyncActionView_Night_2_en",0,], -["libraries.designsystem.components.async_AsyncActionView_Day_3_en","libraries.designsystem.components.async_AsyncActionView_Night_3_en",19916,], +["libraries.designsystem.components.async_AsyncActionView_Day_3_en","libraries.designsystem.components.async_AsyncActionView_Night_3_en",19923,], ["libraries.designsystem.components.async_AsyncActionView_Day_4_en","libraries.designsystem.components.async_AsyncActionView_Night_4_en",0,], -["libraries.designsystem.components.async_AsyncFailure_Day_0_en","libraries.designsystem.components.async_AsyncFailure_Night_0_en",19916,], +["libraries.designsystem.components.async_AsyncFailure_Day_0_en","libraries.designsystem.components.async_AsyncFailure_Night_0_en",19923,], ["libraries.designsystem.components.async_AsyncIndicatorFailure_Day_0_en","libraries.designsystem.components.async_AsyncIndicatorFailure_Night_0_en",0,], ["libraries.designsystem.components.async_AsyncIndicatorLoading_Day_0_en","libraries.designsystem.components.async_AsyncIndicatorLoading_Night_0_en",0,], ["libraries.designsystem.components.async_AsyncLoading_Day_0_en","libraries.designsystem.components.async_AsyncLoading_Night_0_en",0,], -["features.messages.impl.messagecomposer_AttachmentSourcePickerMenu_Day_0_en","features.messages.impl.messagecomposer_AttachmentSourcePickerMenu_Night_0_en",19916,], +["features.messages.impl.messagecomposer_AttachmentSourcePickerMenu_Day_0_en","features.messages.impl.messagecomposer_AttachmentSourcePickerMenu_Night_0_en",19923,], ["libraries.matrix.ui.components_AttachmentThumbnail_Day_0_en","libraries.matrix.ui.components_AttachmentThumbnail_Night_0_en",0,], ["libraries.matrix.ui.components_AttachmentThumbnail_Day_1_en","libraries.matrix.ui.components_AttachmentThumbnail_Night_1_en",0,], ["libraries.matrix.ui.components_AttachmentThumbnail_Day_2_en","libraries.matrix.ui.components_AttachmentThumbnail_Night_2_en",0,], @@ -43,11 +44,11 @@ export const screenshots = [ ["libraries.matrix.ui.components_AttachmentThumbnail_Day_6_en","libraries.matrix.ui.components_AttachmentThumbnail_Night_6_en",0,], ["libraries.matrix.ui.components_AttachmentThumbnail_Day_7_en","libraries.matrix.ui.components_AttachmentThumbnail_Night_7_en",0,], ["libraries.matrix.ui.components_AttachmentThumbnail_Day_8_en","libraries.matrix.ui.components_AttachmentThumbnail_Night_8_en",0,], -["features.messages.impl.attachments.preview_AttachmentsView_0_en","",19916,], -["features.messages.impl.attachments.preview_AttachmentsView_1_en","",19916,], -["features.messages.impl.attachments.preview_AttachmentsView_2_en","",19916,], -["features.messages.impl.attachments.preview_AttachmentsView_3_en","",19916,], -["libraries.matrix.ui.components_AvatarActionBottomSheet_Day_0_en","libraries.matrix.ui.components_AvatarActionBottomSheet_Night_0_en",19916,], +["features.messages.impl.attachments.preview_AttachmentsView_0_en","",19923,], +["features.messages.impl.attachments.preview_AttachmentsView_1_en","",19923,], +["features.messages.impl.attachments.preview_AttachmentsView_2_en","",19923,], +["features.messages.impl.attachments.preview_AttachmentsView_3_en","",19923,], +["libraries.matrix.ui.components_AvatarActionBottomSheet_Day_0_en","libraries.matrix.ui.components_AvatarActionBottomSheet_Night_0_en",19923,], ["libraries.designsystem.components.avatar_Avatar_Avatars_0_en","",0,], ["libraries.designsystem.components.avatar_Avatar_Avatars_10_en","",0,], ["libraries.designsystem.components.avatar_Avatar_Avatars_11_en","",0,], @@ -127,13 +128,13 @@ export const screenshots = [ ["libraries.designsystem.components_Badge_Day_0_en","libraries.designsystem.components_Badge_Night_0_en",0,], ["libraries.designsystem.components_BigCheckmark_Day_0_en","libraries.designsystem.components_BigCheckmark_Night_0_en",0,], ["libraries.designsystem.components_BigIcon_Day_0_en","libraries.designsystem.components_BigIcon_Night_0_en",0,], -["features.preferences.impl.blockedusers_BlockedUsersView_Day_0_en","features.preferences.impl.blockedusers_BlockedUsersView_Night_0_en",19916,], -["features.preferences.impl.blockedusers_BlockedUsersView_Day_1_en","features.preferences.impl.blockedusers_BlockedUsersView_Night_1_en",19916,], -["features.preferences.impl.blockedusers_BlockedUsersView_Day_2_en","features.preferences.impl.blockedusers_BlockedUsersView_Night_2_en",19916,], -["features.preferences.impl.blockedusers_BlockedUsersView_Day_3_en","features.preferences.impl.blockedusers_BlockedUsersView_Night_3_en",19916,], -["features.preferences.impl.blockedusers_BlockedUsersView_Day_4_en","features.preferences.impl.blockedusers_BlockedUsersView_Night_4_en",19916,], -["features.preferences.impl.blockedusers_BlockedUsersView_Day_5_en","features.preferences.impl.blockedusers_BlockedUsersView_Night_5_en",19916,], -["features.preferences.impl.blockedusers_BlockedUsersView_Day_6_en","features.preferences.impl.blockedusers_BlockedUsersView_Night_6_en",19916,], +["features.preferences.impl.blockedusers_BlockedUsersView_Day_0_en","features.preferences.impl.blockedusers_BlockedUsersView_Night_0_en",19923,], +["features.preferences.impl.blockedusers_BlockedUsersView_Day_1_en","features.preferences.impl.blockedusers_BlockedUsersView_Night_1_en",19923,], +["features.preferences.impl.blockedusers_BlockedUsersView_Day_2_en","features.preferences.impl.blockedusers_BlockedUsersView_Night_2_en",19923,], +["features.preferences.impl.blockedusers_BlockedUsersView_Day_3_en","features.preferences.impl.blockedusers_BlockedUsersView_Night_3_en",19923,], +["features.preferences.impl.blockedusers_BlockedUsersView_Day_4_en","features.preferences.impl.blockedusers_BlockedUsersView_Night_4_en",19923,], +["features.preferences.impl.blockedusers_BlockedUsersView_Day_5_en","features.preferences.impl.blockedusers_BlockedUsersView_Night_5_en",19923,], +["features.preferences.impl.blockedusers_BlockedUsersView_Day_6_en","features.preferences.impl.blockedusers_BlockedUsersView_Night_6_en",19923,], ["libraries.designsystem.components_BloomInitials_Day_0_en","libraries.designsystem.components_BloomInitials_Night_0_en",0,], ["libraries.designsystem.components_BloomInitials_Day_1_en","libraries.designsystem.components_BloomInitials_Night_1_en",0,], ["libraries.designsystem.components_BloomInitials_Day_2_en","libraries.designsystem.components_BloomInitials_Night_2_en",0,], @@ -144,82 +145,84 @@ export const screenshots = [ ["libraries.designsystem.components_BloomInitials_Day_7_en","libraries.designsystem.components_BloomInitials_Night_7_en",0,], ["libraries.designsystem.components_Bloom_Day_0_en","libraries.designsystem.components_Bloom_Night_0_en",0,], ["libraries.designsystem.theme.components_BottomSheetDragHandle_Day_0_en","libraries.designsystem.theme.components_BottomSheetDragHandle_Night_0_en",0,], -["features.rageshake.impl.bugreport_BugReportView_Day_0_en","features.rageshake.impl.bugreport_BugReportView_Night_0_en",19916,], -["features.rageshake.impl.bugreport_BugReportView_Day_1_en","features.rageshake.impl.bugreport_BugReportView_Night_1_en",19916,], -["features.rageshake.impl.bugreport_BugReportView_Day_2_en","features.rageshake.impl.bugreport_BugReportView_Night_2_en",19916,], -["features.rageshake.impl.bugreport_BugReportView_Day_3_en","features.rageshake.impl.bugreport_BugReportView_Night_3_en",19916,], -["features.rageshake.impl.bugreport_BugReportView_Day_4_en","features.rageshake.impl.bugreport_BugReportView_Night_4_en",19916,], +["features.rageshake.impl.bugreport_BugReportView_Day_0_en","features.rageshake.impl.bugreport_BugReportView_Night_0_en",19923,], +["features.rageshake.impl.bugreport_BugReportView_Day_1_en","features.rageshake.impl.bugreport_BugReportView_Night_1_en",19923,], +["features.rageshake.impl.bugreport_BugReportView_Day_2_en","features.rageshake.impl.bugreport_BugReportView_Night_2_en",19923,], +["features.rageshake.impl.bugreport_BugReportView_Day_3_en","features.rageshake.impl.bugreport_BugReportView_Night_3_en",19923,], +["features.rageshake.impl.bugreport_BugReportView_Day_4_en","features.rageshake.impl.bugreport_BugReportView_Night_4_en",19923,], ["libraries.designsystem.atomic.molecules_ButtonColumnMolecule_Day_0_en","libraries.designsystem.atomic.molecules_ButtonColumnMolecule_Night_0_en",0,], ["libraries.designsystem.atomic.molecules_ButtonRowMolecule_Day_0_en","libraries.designsystem.atomic.molecules_ButtonRowMolecule_Night_0_en",0,], +["features.call.impl.ui_CallScreenPipView_Day_0_en","features.call.impl.ui_CallScreenPipView_Night_0_en",0,], +["features.call.impl.ui_CallScreenPipView_Day_1_en","features.call.impl.ui_CallScreenPipView_Night_1_en",0,], ["features.call.impl.ui_CallScreenView_Day_0_en","features.call.impl.ui_CallScreenView_Night_0_en",0,], -["features.call.impl.ui_CallScreenView_Day_1_en","features.call.impl.ui_CallScreenView_Night_1_en",19916,], -["features.call.impl.ui_CallScreenView_Day_2_en","features.call.impl.ui_CallScreenView_Night_2_en",19919,], -["features.login.impl.screens.changeaccountprovider_ChangeAccountProviderView_Day_0_en","features.login.impl.screens.changeaccountprovider_ChangeAccountProviderView_Night_0_en",19916,], -["features.roomdetails.impl.rolesandpermissions.changeroles_ChangeRolesView_Day_0_en","features.roomdetails.impl.rolesandpermissions.changeroles_ChangeRolesView_Night_0_en",19916,], -["features.roomdetails.impl.rolesandpermissions.changeroles_ChangeRolesView_Day_10_en","features.roomdetails.impl.rolesandpermissions.changeroles_ChangeRolesView_Night_10_en",19916,], -["features.roomdetails.impl.rolesandpermissions.changeroles_ChangeRolesView_Day_1_en","features.roomdetails.impl.rolesandpermissions.changeroles_ChangeRolesView_Night_1_en",19916,], -["features.roomdetails.impl.rolesandpermissions.changeroles_ChangeRolesView_Day_2_en","features.roomdetails.impl.rolesandpermissions.changeroles_ChangeRolesView_Night_2_en",19916,], -["features.roomdetails.impl.rolesandpermissions.changeroles_ChangeRolesView_Day_3_en","features.roomdetails.impl.rolesandpermissions.changeroles_ChangeRolesView_Night_3_en",19916,], -["features.roomdetails.impl.rolesandpermissions.changeroles_ChangeRolesView_Day_4_en","features.roomdetails.impl.rolesandpermissions.changeroles_ChangeRolesView_Night_4_en",19916,], -["features.roomdetails.impl.rolesandpermissions.changeroles_ChangeRolesView_Day_5_en","features.roomdetails.impl.rolesandpermissions.changeroles_ChangeRolesView_Night_5_en",19916,], -["features.roomdetails.impl.rolesandpermissions.changeroles_ChangeRolesView_Day_6_en","features.roomdetails.impl.rolesandpermissions.changeroles_ChangeRolesView_Night_6_en",19916,], -["features.roomdetails.impl.rolesandpermissions.changeroles_ChangeRolesView_Day_7_en","features.roomdetails.impl.rolesandpermissions.changeroles_ChangeRolesView_Night_7_en",19916,], -["features.roomdetails.impl.rolesandpermissions.changeroles_ChangeRolesView_Day_8_en","features.roomdetails.impl.rolesandpermissions.changeroles_ChangeRolesView_Night_8_en",19916,], -["features.roomdetails.impl.rolesandpermissions.changeroles_ChangeRolesView_Day_9_en","features.roomdetails.impl.rolesandpermissions.changeroles_ChangeRolesView_Night_9_en",19916,], -["features.roomdetails.impl.rolesandpermissions.permissions_ChangeRoomPermissionsView_Day_0_en","features.roomdetails.impl.rolesandpermissions.permissions_ChangeRoomPermissionsView_Night_0_en",19916,], -["features.roomdetails.impl.rolesandpermissions.permissions_ChangeRoomPermissionsView_Day_1_en","features.roomdetails.impl.rolesandpermissions.permissions_ChangeRoomPermissionsView_Night_1_en",19916,], -["features.roomdetails.impl.rolesandpermissions.permissions_ChangeRoomPermissionsView_Day_2_en","features.roomdetails.impl.rolesandpermissions.permissions_ChangeRoomPermissionsView_Night_2_en",19916,], -["features.roomdetails.impl.rolesandpermissions.permissions_ChangeRoomPermissionsView_Day_3_en","features.roomdetails.impl.rolesandpermissions.permissions_ChangeRoomPermissionsView_Night_3_en",19916,], -["features.roomdetails.impl.rolesandpermissions.permissions_ChangeRoomPermissionsView_Day_4_en","features.roomdetails.impl.rolesandpermissions.permissions_ChangeRoomPermissionsView_Night_4_en",19916,], -["features.roomdetails.impl.rolesandpermissions.permissions_ChangeRoomPermissionsView_Day_5_en","features.roomdetails.impl.rolesandpermissions.permissions_ChangeRoomPermissionsView_Night_5_en",19916,], -["features.roomdetails.impl.rolesandpermissions.permissions_ChangeRoomPermissionsView_Day_6_en","features.roomdetails.impl.rolesandpermissions.permissions_ChangeRoomPermissionsView_Night_6_en",19916,], +["features.call.impl.ui_CallScreenView_Day_1_en","features.call.impl.ui_CallScreenView_Night_1_en",19923,], +["features.call.impl.ui_CallScreenView_Day_2_en","features.call.impl.ui_CallScreenView_Night_2_en",19923,], +["features.login.impl.screens.changeaccountprovider_ChangeAccountProviderView_Day_0_en","features.login.impl.screens.changeaccountprovider_ChangeAccountProviderView_Night_0_en",19923,], +["features.roomdetails.impl.rolesandpermissions.changeroles_ChangeRolesView_Day_0_en","features.roomdetails.impl.rolesandpermissions.changeroles_ChangeRolesView_Night_0_en",19923,], +["features.roomdetails.impl.rolesandpermissions.changeroles_ChangeRolesView_Day_10_en","features.roomdetails.impl.rolesandpermissions.changeroles_ChangeRolesView_Night_10_en",19923,], +["features.roomdetails.impl.rolesandpermissions.changeroles_ChangeRolesView_Day_1_en","features.roomdetails.impl.rolesandpermissions.changeroles_ChangeRolesView_Night_1_en",19923,], +["features.roomdetails.impl.rolesandpermissions.changeroles_ChangeRolesView_Day_2_en","features.roomdetails.impl.rolesandpermissions.changeroles_ChangeRolesView_Night_2_en",19923,], +["features.roomdetails.impl.rolesandpermissions.changeroles_ChangeRolesView_Day_3_en","features.roomdetails.impl.rolesandpermissions.changeroles_ChangeRolesView_Night_3_en",19923,], +["features.roomdetails.impl.rolesandpermissions.changeroles_ChangeRolesView_Day_4_en","features.roomdetails.impl.rolesandpermissions.changeroles_ChangeRolesView_Night_4_en",19923,], +["features.roomdetails.impl.rolesandpermissions.changeroles_ChangeRolesView_Day_5_en","features.roomdetails.impl.rolesandpermissions.changeroles_ChangeRolesView_Night_5_en",19923,], +["features.roomdetails.impl.rolesandpermissions.changeroles_ChangeRolesView_Day_6_en","features.roomdetails.impl.rolesandpermissions.changeroles_ChangeRolesView_Night_6_en",19923,], +["features.roomdetails.impl.rolesandpermissions.changeroles_ChangeRolesView_Day_7_en","features.roomdetails.impl.rolesandpermissions.changeroles_ChangeRolesView_Night_7_en",19923,], +["features.roomdetails.impl.rolesandpermissions.changeroles_ChangeRolesView_Day_8_en","features.roomdetails.impl.rolesandpermissions.changeroles_ChangeRolesView_Night_8_en",19923,], +["features.roomdetails.impl.rolesandpermissions.changeroles_ChangeRolesView_Day_9_en","features.roomdetails.impl.rolesandpermissions.changeroles_ChangeRolesView_Night_9_en",19923,], +["features.roomdetails.impl.rolesandpermissions.permissions_ChangeRoomPermissionsView_Day_0_en","features.roomdetails.impl.rolesandpermissions.permissions_ChangeRoomPermissionsView_Night_0_en",19923,], +["features.roomdetails.impl.rolesandpermissions.permissions_ChangeRoomPermissionsView_Day_1_en","features.roomdetails.impl.rolesandpermissions.permissions_ChangeRoomPermissionsView_Night_1_en",19923,], +["features.roomdetails.impl.rolesandpermissions.permissions_ChangeRoomPermissionsView_Day_2_en","features.roomdetails.impl.rolesandpermissions.permissions_ChangeRoomPermissionsView_Night_2_en",19923,], +["features.roomdetails.impl.rolesandpermissions.permissions_ChangeRoomPermissionsView_Day_3_en","features.roomdetails.impl.rolesandpermissions.permissions_ChangeRoomPermissionsView_Night_3_en",19923,], +["features.roomdetails.impl.rolesandpermissions.permissions_ChangeRoomPermissionsView_Day_4_en","features.roomdetails.impl.rolesandpermissions.permissions_ChangeRoomPermissionsView_Night_4_en",19923,], +["features.roomdetails.impl.rolesandpermissions.permissions_ChangeRoomPermissionsView_Day_5_en","features.roomdetails.impl.rolesandpermissions.permissions_ChangeRoomPermissionsView_Night_5_en",19923,], +["features.roomdetails.impl.rolesandpermissions.permissions_ChangeRoomPermissionsView_Day_6_en","features.roomdetails.impl.rolesandpermissions.permissions_ChangeRoomPermissionsView_Night_6_en",19923,], ["features.login.impl.changeserver_ChangeServerView_Day_0_en","features.login.impl.changeserver_ChangeServerView_Night_0_en",0,], -["features.login.impl.changeserver_ChangeServerView_Day_1_en","features.login.impl.changeserver_ChangeServerView_Night_1_en",19916,], -["features.login.impl.changeserver_ChangeServerView_Day_2_en","features.login.impl.changeserver_ChangeServerView_Night_2_en",19916,], +["features.login.impl.changeserver_ChangeServerView_Day_1_en","features.login.impl.changeserver_ChangeServerView_Night_1_en",19923,], +["features.login.impl.changeserver_ChangeServerView_Day_2_en","features.login.impl.changeserver_ChangeServerView_Night_2_en",19923,], ["libraries.matrix.ui.components_CheckableResolvedUserRow_en","",0,], -["libraries.matrix.ui.components_CheckableUnresolvedUserRow_en","",19916,], +["libraries.matrix.ui.components_CheckableUnresolvedUserRow_en","",19923,], ["libraries.designsystem.theme.components_Checkboxes_Toggles_en","",0,], ["libraries.designsystem.theme.components_CircularProgressIndicator_Progress Indicators_en","",0,], ["libraries.designsystem.components_ClickableLinkText_Text_en","",0,], ["libraries.designsystem.theme_ColorAliases_Day_0_en","libraries.designsystem.theme_ColorAliases_Night_0_en",0,], ["libraries.textcomposer.components_ComposerOptionsButton_Day_0_en","libraries.textcomposer.components_ComposerOptionsButton_Night_0_en",0,], ["libraries.designsystem.components.avatar_CompositeAvatar_Avatars_en","",0,], -["features.createroom.impl.configureroom_ConfigureRoomView_Day_0_en","features.createroom.impl.configureroom_ConfigureRoomView_Night_0_en",19916,], -["features.createroom.impl.configureroom_ConfigureRoomView_Day_1_en","features.createroom.impl.configureroom_ConfigureRoomView_Night_1_en",19916,], +["features.createroom.impl.configureroom_ConfigureRoomView_Day_0_en","features.createroom.impl.configureroom_ConfigureRoomView_Night_0_en",19923,], +["features.createroom.impl.configureroom_ConfigureRoomView_Day_1_en","features.createroom.impl.configureroom_ConfigureRoomView_Night_1_en",19923,], ["features.preferences.impl.developer.tracing_ConfigureTracingView_Day_0_en","features.preferences.impl.developer.tracing_ConfigureTracingView_Night_0_en",0,], -["features.login.impl.screens.confirmaccountprovider_ConfirmAccountProviderView_Day_0_en","features.login.impl.screens.confirmaccountprovider_ConfirmAccountProviderView_Night_0_en",19916,], -["features.roomlist.impl.components_ConfirmRecoveryKeyBanner_Day_0_en","features.roomlist.impl.components_ConfirmRecoveryKeyBanner_Night_0_en",19916,], +["features.login.impl.screens.confirmaccountprovider_ConfirmAccountProviderView_Day_0_en","features.login.impl.screens.confirmaccountprovider_ConfirmAccountProviderView_Night_0_en",19923,], +["features.roomlist.impl.components_ConfirmRecoveryKeyBanner_Day_0_en","features.roomlist.impl.components_ConfirmRecoveryKeyBanner_Night_0_en",19923,], ["libraries.designsystem.components.dialogs_ConfirmationDialogContent_Dialogs_en","",0,], ["libraries.designsystem.components.dialogs_ConfirmationDialog_Day_0_en","libraries.designsystem.components.dialogs_ConfirmationDialog_Night_0_en",0,], ["features.networkmonitor.api.ui_ConnectivityIndicatorView_Day_0_en","features.networkmonitor.api.ui_ConnectivityIndicatorView_Night_0_en",0,], -["features.rageshake.api.crash_CrashDetectionView_Day_0_en","features.rageshake.api.crash_CrashDetectionView_Night_0_en",19916,], -["features.securebackup.impl.createkey_CreateNewRecoveryKeyView_Day_0_en","features.securebackup.impl.createkey_CreateNewRecoveryKeyView_Night_0_en",19916,], -["features.poll.impl.create_CreatePollView_Day_0_en","features.poll.impl.create_CreatePollView_Night_0_en",19916,], -["features.poll.impl.create_CreatePollView_Day_1_en","features.poll.impl.create_CreatePollView_Night_1_en",19916,], -["features.poll.impl.create_CreatePollView_Day_2_en","features.poll.impl.create_CreatePollView_Night_2_en",19916,], -["features.poll.impl.create_CreatePollView_Day_3_en","features.poll.impl.create_CreatePollView_Night_3_en",19916,], -["features.poll.impl.create_CreatePollView_Day_4_en","features.poll.impl.create_CreatePollView_Night_4_en",19916,], -["features.poll.impl.create_CreatePollView_Day_5_en","features.poll.impl.create_CreatePollView_Night_5_en",19916,], -["features.poll.impl.create_CreatePollView_Day_6_en","features.poll.impl.create_CreatePollView_Night_6_en",19916,], -["features.poll.impl.create_CreatePollView_Day_7_en","features.poll.impl.create_CreatePollView_Night_7_en",19916,], -["features.createroom.impl.root_CreateRoomRootView_Day_0_en","features.createroom.impl.root_CreateRoomRootView_Night_0_en",19916,], -["features.createroom.impl.root_CreateRoomRootView_Day_1_en","features.createroom.impl.root_CreateRoomRootView_Night_1_en",19916,], -["features.createroom.impl.root_CreateRoomRootView_Day_2_en","features.createroom.impl.root_CreateRoomRootView_Night_2_en",19916,], -["features.createroom.impl.root_CreateRoomRootView_Day_3_en","features.createroom.impl.root_CreateRoomRootView_Night_3_en",19916,], -["libraries.designsystem.theme.components.previews_DatePickerDark_DateTime pickers_en","",19916,], -["libraries.designsystem.theme.components.previews_DatePickerLight_DateTime pickers_en","",19916,], +["features.rageshake.api.crash_CrashDetectionView_Day_0_en","features.rageshake.api.crash_CrashDetectionView_Night_0_en",19923,], +["features.securebackup.impl.createkey_CreateNewRecoveryKeyView_Day_0_en","features.securebackup.impl.createkey_CreateNewRecoveryKeyView_Night_0_en",19923,], +["features.poll.impl.create_CreatePollView_Day_0_en","features.poll.impl.create_CreatePollView_Night_0_en",19923,], +["features.poll.impl.create_CreatePollView_Day_1_en","features.poll.impl.create_CreatePollView_Night_1_en",19923,], +["features.poll.impl.create_CreatePollView_Day_2_en","features.poll.impl.create_CreatePollView_Night_2_en",19923,], +["features.poll.impl.create_CreatePollView_Day_3_en","features.poll.impl.create_CreatePollView_Night_3_en",19923,], +["features.poll.impl.create_CreatePollView_Day_4_en","features.poll.impl.create_CreatePollView_Night_4_en",19923,], +["features.poll.impl.create_CreatePollView_Day_5_en","features.poll.impl.create_CreatePollView_Night_5_en",19923,], +["features.poll.impl.create_CreatePollView_Day_6_en","features.poll.impl.create_CreatePollView_Night_6_en",19923,], +["features.poll.impl.create_CreatePollView_Day_7_en","features.poll.impl.create_CreatePollView_Night_7_en",19923,], +["features.createroom.impl.root_CreateRoomRootView_Day_0_en","features.createroom.impl.root_CreateRoomRootView_Night_0_en",19923,], +["features.createroom.impl.root_CreateRoomRootView_Day_1_en","features.createroom.impl.root_CreateRoomRootView_Night_1_en",19923,], +["features.createroom.impl.root_CreateRoomRootView_Day_2_en","features.createroom.impl.root_CreateRoomRootView_Night_2_en",19923,], +["features.createroom.impl.root_CreateRoomRootView_Day_3_en","features.createroom.impl.root_CreateRoomRootView_Night_3_en",19923,], +["libraries.designsystem.theme.components.previews_DatePickerDark_DateTime pickers_en","",19923,], +["libraries.designsystem.theme.components.previews_DatePickerLight_DateTime pickers_en","",19923,], ["features.logout.impl.direct_DefaultDirectLogoutView_Day_0_en","features.logout.impl.direct_DefaultDirectLogoutView_Night_0_en",0,], -["features.logout.impl.direct_DefaultDirectLogoutView_Day_1_en","features.logout.impl.direct_DefaultDirectLogoutView_Night_1_en",19916,], -["features.logout.impl.direct_DefaultDirectLogoutView_Day_2_en","features.logout.impl.direct_DefaultDirectLogoutView_Night_2_en",19916,], -["features.logout.impl.direct_DefaultDirectLogoutView_Day_3_en","features.logout.impl.direct_DefaultDirectLogoutView_Night_3_en",19916,], +["features.logout.impl.direct_DefaultDirectLogoutView_Day_1_en","features.logout.impl.direct_DefaultDirectLogoutView_Night_1_en",19923,], +["features.logout.impl.direct_DefaultDirectLogoutView_Day_2_en","features.logout.impl.direct_DefaultDirectLogoutView_Night_2_en",19923,], +["features.logout.impl.direct_DefaultDirectLogoutView_Day_3_en","features.logout.impl.direct_DefaultDirectLogoutView_Night_3_en",19923,], ["features.logout.impl.direct_DefaultDirectLogoutView_Day_4_en","features.logout.impl.direct_DefaultDirectLogoutView_Night_4_en",0,], -["features.preferences.impl.notifications.edit_DefaultNotificationSettingOption_Day_0_en","features.preferences.impl.notifications.edit_DefaultNotificationSettingOption_Night_0_en",19916,], -["features.roomlist.impl.components_DefaultRoomListTopBarWithIndicator_Day_0_en","features.roomlist.impl.components_DefaultRoomListTopBarWithIndicator_Night_0_en",19916,], -["features.roomlist.impl.components_DefaultRoomListTopBar_Day_0_en","features.roomlist.impl.components_DefaultRoomListTopBar_Night_0_en",19916,], -["features.preferences.impl.developer_DeveloperSettingsView_Day_0_en","features.preferences.impl.developer_DeveloperSettingsView_Night_0_en",19916,], -["features.preferences.impl.developer_DeveloperSettingsView_Day_1_en","features.preferences.impl.developer_DeveloperSettingsView_Night_1_en",19916,], -["features.preferences.impl.developer_DeveloperSettingsView_Day_2_en","features.preferences.impl.developer_DeveloperSettingsView_Night_2_en",19916,], -["libraries.designsystem.atomic.molecules_DialogLikeBannerMolecule_Day_0_en","libraries.designsystem.atomic.molecules_DialogLikeBannerMolecule_Night_0_en",19916,], +["features.preferences.impl.notifications.edit_DefaultNotificationSettingOption_Day_0_en","features.preferences.impl.notifications.edit_DefaultNotificationSettingOption_Night_0_en",19923,], +["features.roomlist.impl.components_DefaultRoomListTopBarWithIndicator_Day_0_en","features.roomlist.impl.components_DefaultRoomListTopBarWithIndicator_Night_0_en",19923,], +["features.roomlist.impl.components_DefaultRoomListTopBar_Day_0_en","features.roomlist.impl.components_DefaultRoomListTopBar_Night_0_en",19923,], +["features.preferences.impl.developer_DeveloperSettingsView_Day_0_en","features.preferences.impl.developer_DeveloperSettingsView_Night_0_en",19923,], +["features.preferences.impl.developer_DeveloperSettingsView_Day_1_en","features.preferences.impl.developer_DeveloperSettingsView_Night_1_en",19923,], +["features.preferences.impl.developer_DeveloperSettingsView_Day_2_en","features.preferences.impl.developer_DeveloperSettingsView_Night_2_en",19923,], +["libraries.designsystem.atomic.molecules_DialogLikeBannerMolecule_Day_0_en","libraries.designsystem.atomic.molecules_DialogLikeBannerMolecule_Night_0_en",19923,], ["libraries.designsystem.theme.components_DialogWithDestructiveButton_Dialog with destructive button_Dialogs_en","",0,], ["libraries.designsystem.theme.components_DialogWithOnlyMessageAndOkButton_Dialog with only message and ok button_Dialogs_en","",0,], ["libraries.designsystem.theme.components_DialogWithThirdButton_Dialog with third button_Dialogs_en","",0,], @@ -231,12 +234,12 @@ export const screenshots = [ ["libraries.designsystem.text_DpScale_1_0f__en","",0,], ["libraries.designsystem.text_DpScale_1_5f__en","",0,], ["libraries.designsystem.theme.components_DropdownMenuItem_Menus_en","",0,], -["features.preferences.impl.notifications.edit_EditDefaultNotificationSettingView_Day_0_en","features.preferences.impl.notifications.edit_EditDefaultNotificationSettingView_Night_0_en",19916,], -["features.preferences.impl.notifications.edit_EditDefaultNotificationSettingView_Day_1_en","features.preferences.impl.notifications.edit_EditDefaultNotificationSettingView_Night_1_en",19916,], -["features.preferences.impl.notifications.edit_EditDefaultNotificationSettingView_Day_2_en","features.preferences.impl.notifications.edit_EditDefaultNotificationSettingView_Night_2_en",19916,], -["features.preferences.impl.notifications.edit_EditDefaultNotificationSettingView_Day_3_en","features.preferences.impl.notifications.edit_EditDefaultNotificationSettingView_Night_3_en",19916,], -["features.preferences.impl.notifications.edit_EditDefaultNotificationSettingView_Day_4_en","features.preferences.impl.notifications.edit_EditDefaultNotificationSettingView_Night_4_en",19916,], -["features.preferences.impl.user.editprofile_EditUserProfileView_Day_0_en","features.preferences.impl.user.editprofile_EditUserProfileView_Night_0_en",19916,], +["features.preferences.impl.notifications.edit_EditDefaultNotificationSettingView_Day_0_en","features.preferences.impl.notifications.edit_EditDefaultNotificationSettingView_Night_0_en",19923,], +["features.preferences.impl.notifications.edit_EditDefaultNotificationSettingView_Day_1_en","features.preferences.impl.notifications.edit_EditDefaultNotificationSettingView_Night_1_en",19923,], +["features.preferences.impl.notifications.edit_EditDefaultNotificationSettingView_Day_2_en","features.preferences.impl.notifications.edit_EditDefaultNotificationSettingView_Night_2_en",19923,], +["features.preferences.impl.notifications.edit_EditDefaultNotificationSettingView_Day_3_en","features.preferences.impl.notifications.edit_EditDefaultNotificationSettingView_Night_3_en",19923,], +["features.preferences.impl.notifications.edit_EditDefaultNotificationSettingView_Day_4_en","features.preferences.impl.notifications.edit_EditDefaultNotificationSettingView_Night_4_en",19923,], +["features.preferences.impl.user.editprofile_EditUserProfileView_Day_0_en","features.preferences.impl.user.editprofile_EditUserProfileView_Night_0_en",19923,], ["libraries.matrix.ui.components_EditableAvatarView_Day_0_en","libraries.matrix.ui.components_EditableAvatarView_Night_0_en",0,], ["libraries.matrix.ui.components_EditableAvatarView_Day_1_en","libraries.matrix.ui.components_EditableAvatarView_Night_1_en",0,], ["libraries.matrix.ui.components_EditableAvatarView_Day_2_en","libraries.matrix.ui.components_EditableAvatarView_Night_2_en",0,], @@ -246,27 +249,29 @@ export const screenshots = [ ["libraries.designsystem.atomic.atoms_ElementLogoAtomMedium_Day_0_en","libraries.designsystem.atomic.atoms_ElementLogoAtomMedium_Night_0_en",0,], ["features.messages.impl.timeline.components.customreaction_EmojiItem_Day_0_en","features.messages.impl.timeline.components.customreaction_EmojiItem_Night_0_en",0,], ["features.messages.impl.timeline.components.customreaction_EmojiPicker_Day_0_en","features.messages.impl.timeline.components.customreaction_EmojiPicker_Night_0_en",0,], -["features.messages.impl.timeline.components.virtual_EncryptedHistoryBannerView_Day_0_en","features.messages.impl.timeline.components.virtual_EncryptedHistoryBannerView_Night_0_en",19916,], -["libraries.designsystem.components.dialogs_ErrorDialogContent_Dialogs_en","",19916,], -["libraries.designsystem.components.dialogs_ErrorDialogWithDoNotShowAgain_Day_0_en","libraries.designsystem.components.dialogs_ErrorDialogWithDoNotShowAgain_Night_0_en",19916,], -["libraries.designsystem.components.dialogs_ErrorDialog_Day_0_en","libraries.designsystem.components.dialogs_ErrorDialog_Night_0_en",19916,], +["features.messages.impl.timeline.components.virtual_EncryptedHistoryBannerView_Day_0_en","features.messages.impl.timeline.components.virtual_EncryptedHistoryBannerView_Night_0_en",19923,], +["libraries.designsystem.components.dialogs_ErrorDialogContent_Dialogs_en","",19923,], +["libraries.designsystem.components.dialogs_ErrorDialogWithDoNotShowAgain_Day_0_en","libraries.designsystem.components.dialogs_ErrorDialogWithDoNotShowAgain_Night_0_en",19923,], +["libraries.designsystem.components.dialogs_ErrorDialog_Day_0_en","libraries.designsystem.components.dialogs_ErrorDialog_Night_0_en",19923,], ["features.messages.impl.timeline.debug_EventDebugInfoView_Day_0_en","features.messages.impl.timeline.debug_EventDebugInfoView_Night_0_en",0,], ["libraries.featureflag.ui_FeatureListView_Day_0_en","libraries.featureflag.ui_FeatureListView_Night_0_en",0,], +["libraries.designsystem.theme.components_FilledButtonLargeLowPadding_Buttons_en","",0,], ["libraries.designsystem.theme.components_FilledButtonLarge_Buttons_en","",0,], +["libraries.designsystem.theme.components_FilledButtonMediumLowPadding_Buttons_en","",0,], ["libraries.designsystem.theme.components_FilledButtonMedium_Buttons_en","",0,], ["libraries.designsystem.theme.components_FilledButtonSmall_Buttons_en","",0,], ["libraries.designsystem.theme.components_FloatingActionButton_Floating Action Buttons_en","",0,], ["libraries.designsystem.atomic.pages_FlowStepPage_Day_0_en","libraries.designsystem.atomic.pages_FlowStepPage_Night_0_en",0,], ["features.messages.impl.timeline.focus_FocusRequestStateView_Day_0_en","features.messages.impl.timeline.focus_FocusRequestStateView_Night_0_en",0,], -["features.messages.impl.timeline.focus_FocusRequestStateView_Day_1_en","features.messages.impl.timeline.focus_FocusRequestStateView_Night_1_en",19916,], -["features.messages.impl.timeline.focus_FocusRequestStateView_Day_2_en","features.messages.impl.timeline.focus_FocusRequestStateView_Night_2_en",19916,], -["features.messages.impl.timeline.focus_FocusRequestStateView_Day_3_en","features.messages.impl.timeline.focus_FocusRequestStateView_Night_3_en",19916,], +["features.messages.impl.timeline.focus_FocusRequestStateView_Day_1_en","features.messages.impl.timeline.focus_FocusRequestStateView_Night_1_en",19923,], +["features.messages.impl.timeline.focus_FocusRequestStateView_Day_2_en","features.messages.impl.timeline.focus_FocusRequestStateView_Night_2_en",19923,], +["features.messages.impl.timeline.focus_FocusRequestStateView_Day_3_en","features.messages.impl.timeline.focus_FocusRequestStateView_Night_3_en",19923,], ["libraries.textcomposer.components_FormattingOption_Day_0_en","libraries.textcomposer.components_FormattingOption_Night_0_en",0,], ["features.messages.impl.forward_ForwardMessagesView_Day_0_en","features.messages.impl.forward_ForwardMessagesView_Night_0_en",0,], ["features.messages.impl.forward_ForwardMessagesView_Day_1_en","features.messages.impl.forward_ForwardMessagesView_Night_1_en",0,], ["features.messages.impl.forward_ForwardMessagesView_Day_2_en","features.messages.impl.forward_ForwardMessagesView_Night_2_en",0,], -["features.messages.impl.forward_ForwardMessagesView_Day_3_en","features.messages.impl.forward_ForwardMessagesView_Night_3_en",19916,], -["features.roomlist.impl.components_FullScreenIntentPermissionBanner_Day_0_en","features.roomlist.impl.components_FullScreenIntentPermissionBanner_Night_0_en",19916,], +["features.messages.impl.forward_ForwardMessagesView_Day_3_en","features.messages.impl.forward_ForwardMessagesView_Night_3_en",19923,], +["features.roomlist.impl.components_FullScreenIntentPermissionBanner_Day_0_en","features.roomlist.impl.components_FullScreenIntentPermissionBanner_Night_0_en",19923,], ["libraries.designsystem.components.button_GradientFloatingActionButtonCircleShape_Day_0_en","libraries.designsystem.components.button_GradientFloatingActionButtonCircleShape_Night_0_en",0,], ["libraries.designsystem.components.button_GradientFloatingActionButton_Day_0_en","libraries.designsystem.components.button_GradientFloatingActionButton_Night_0_en",0,], ["features.messages.impl.timeline.components.group_GroupHeaderView_Day_0_en","features.messages.impl.timeline.components.group_GroupHeaderView_Night_0_en",0,], @@ -293,37 +298,37 @@ export const screenshots = [ ["libraries.matrix.ui.messages.reply_InReplyToView_Day_1_en","libraries.matrix.ui.messages.reply_InReplyToView_Night_1_en",0,], ["libraries.matrix.ui.messages.reply_InReplyToView_Day_2_en","libraries.matrix.ui.messages.reply_InReplyToView_Night_2_en",0,], ["libraries.matrix.ui.messages.reply_InReplyToView_Day_3_en","libraries.matrix.ui.messages.reply_InReplyToView_Night_3_en",0,], -["libraries.matrix.ui.messages.reply_InReplyToView_Day_4_en","libraries.matrix.ui.messages.reply_InReplyToView_Night_4_en",19916,], +["libraries.matrix.ui.messages.reply_InReplyToView_Day_4_en","libraries.matrix.ui.messages.reply_InReplyToView_Night_4_en",19923,], ["libraries.matrix.ui.messages.reply_InReplyToView_Day_5_en","libraries.matrix.ui.messages.reply_InReplyToView_Night_5_en",0,], ["libraries.matrix.ui.messages.reply_InReplyToView_Day_6_en","libraries.matrix.ui.messages.reply_InReplyToView_Night_6_en",0,], ["libraries.matrix.ui.messages.reply_InReplyToView_Day_7_en","libraries.matrix.ui.messages.reply_InReplyToView_Night_7_en",0,], -["libraries.matrix.ui.messages.reply_InReplyToView_Day_8_en","libraries.matrix.ui.messages.reply_InReplyToView_Night_8_en",19916,], +["libraries.matrix.ui.messages.reply_InReplyToView_Day_8_en","libraries.matrix.ui.messages.reply_InReplyToView_Night_8_en",19923,], ["libraries.matrix.ui.messages.reply_InReplyToView_Day_9_en","libraries.matrix.ui.messages.reply_InReplyToView_Night_9_en",0,], -["features.call.impl.ui_IncomingCallScreen_Day_0_en","features.call.impl.ui_IncomingCallScreen_Night_0_en",19916,], +["features.call.impl.ui_IncomingCallScreen_Day_0_en","features.call.impl.ui_IncomingCallScreen_Night_0_en",19923,], ["libraries.designsystem.atomic.molecules_InfoListItemMolecule_Day_0_en","libraries.designsystem.atomic.molecules_InfoListItemMolecule_Night_0_en",0,], ["libraries.designsystem.atomic.organisms_InfoListOrganism_Day_0_en","libraries.designsystem.atomic.organisms_InfoListOrganism_Night_0_en",0,], -["libraries.matrix.ui.components_InviteSenderView_Day_0_en","libraries.matrix.ui.components_InviteSenderView_Night_0_en",19916,], +["libraries.matrix.ui.components_InviteSenderView_Day_0_en","libraries.matrix.ui.components_InviteSenderView_Night_0_en",19923,], ["features.joinroom.impl_JoinRoomView_Day_0_en","features.joinroom.impl_JoinRoomView_Night_0_en",0,], ["features.joinroom.impl_JoinRoomView_Day_10_en","features.joinroom.impl_JoinRoomView_Night_10_en",0,], -["features.joinroom.impl_JoinRoomView_Day_1_en","features.joinroom.impl_JoinRoomView_Night_1_en",19916,], -["features.joinroom.impl_JoinRoomView_Day_2_en","features.joinroom.impl_JoinRoomView_Night_2_en",19916,], -["features.joinroom.impl_JoinRoomView_Day_3_en","features.joinroom.impl_JoinRoomView_Night_3_en",19916,], -["features.joinroom.impl_JoinRoomView_Day_4_en","features.joinroom.impl_JoinRoomView_Night_4_en",19916,], -["features.joinroom.impl_JoinRoomView_Day_5_en","features.joinroom.impl_JoinRoomView_Night_5_en",19916,], -["features.joinroom.impl_JoinRoomView_Day_6_en","features.joinroom.impl_JoinRoomView_Night_6_en",19916,], -["features.joinroom.impl_JoinRoomView_Day_7_en","features.joinroom.impl_JoinRoomView_Night_7_en",19916,], -["features.joinroom.impl_JoinRoomView_Day_8_en","features.joinroom.impl_JoinRoomView_Night_8_en",19916,], -["features.joinroom.impl_JoinRoomView_Day_9_en","features.joinroom.impl_JoinRoomView_Night_9_en",19916,], +["features.joinroom.impl_JoinRoomView_Day_1_en","features.joinroom.impl_JoinRoomView_Night_1_en",19923,], +["features.joinroom.impl_JoinRoomView_Day_2_en","features.joinroom.impl_JoinRoomView_Night_2_en",19923,], +["features.joinroom.impl_JoinRoomView_Day_3_en","features.joinroom.impl_JoinRoomView_Night_3_en",19923,], +["features.joinroom.impl_JoinRoomView_Day_4_en","features.joinroom.impl_JoinRoomView_Night_4_en",19923,], +["features.joinroom.impl_JoinRoomView_Day_5_en","features.joinroom.impl_JoinRoomView_Night_5_en",19923,], +["features.joinroom.impl_JoinRoomView_Day_6_en","features.joinroom.impl_JoinRoomView_Night_6_en",19923,], +["features.joinroom.impl_JoinRoomView_Day_7_en","features.joinroom.impl_JoinRoomView_Night_7_en",19923,], +["features.joinroom.impl_JoinRoomView_Day_8_en","features.joinroom.impl_JoinRoomView_Night_8_en",19923,], +["features.joinroom.impl_JoinRoomView_Day_9_en","features.joinroom.impl_JoinRoomView_Night_9_en",19923,], ["libraries.designsystem.components_LabelledCheckbox_Toggles_en","",0,], ["libraries.designsystem.components_LabelledOutlinedTextField_Day_0_en","libraries.designsystem.components_LabelledOutlinedTextField_Night_0_en",0,], ["libraries.designsystem.components_LabelledTextField_Day_0_en","libraries.designsystem.components_LabelledTextField_Night_0_en",0,], ["features.leaveroom.api_LeaveRoomView_Day_0_en","features.leaveroom.api_LeaveRoomView_Night_0_en",0,], -["features.leaveroom.api_LeaveRoomView_Day_1_en","features.leaveroom.api_LeaveRoomView_Night_1_en",19916,], -["features.leaveroom.api_LeaveRoomView_Day_2_en","features.leaveroom.api_LeaveRoomView_Night_2_en",19916,], -["features.leaveroom.api_LeaveRoomView_Day_3_en","features.leaveroom.api_LeaveRoomView_Night_3_en",19916,], -["features.leaveroom.api_LeaveRoomView_Day_4_en","features.leaveroom.api_LeaveRoomView_Night_4_en",19916,], -["features.leaveroom.api_LeaveRoomView_Day_5_en","features.leaveroom.api_LeaveRoomView_Night_5_en",19916,], -["features.leaveroom.api_LeaveRoomView_Day_6_en","features.leaveroom.api_LeaveRoomView_Night_6_en",19916,], +["features.leaveroom.api_LeaveRoomView_Day_1_en","features.leaveroom.api_LeaveRoomView_Night_1_en",19923,], +["features.leaveroom.api_LeaveRoomView_Day_2_en","features.leaveroom.api_LeaveRoomView_Night_2_en",19923,], +["features.leaveroom.api_LeaveRoomView_Day_3_en","features.leaveroom.api_LeaveRoomView_Night_3_en",19923,], +["features.leaveroom.api_LeaveRoomView_Day_4_en","features.leaveroom.api_LeaveRoomView_Night_4_en",19923,], +["features.leaveroom.api_LeaveRoomView_Day_5_en","features.leaveroom.api_LeaveRoomView_Night_5_en",19923,], +["features.leaveroom.api_LeaveRoomView_Day_6_en","features.leaveroom.api_LeaveRoomView_Night_6_en",19923,], ["libraries.designsystem.background_LightGradientBackground_Day_0_en","libraries.designsystem.background_LightGradientBackground_Night_0_en",0,], ["libraries.designsystem.theme.components_LinearProgressIndicator_Progress Indicators_en","",0,], ["libraries.designsystem.components.dialogs_ListDialogContent_Dialogs_en","",0,], @@ -374,28 +379,28 @@ export const screenshots = [ ["libraries.designsystem.theme.components_ListSupportingTextSmallPadding_List supporting text - small padding_List sections_en","",0,], ["libraries.textcomposer.components_LiveWaveformView_Day_0_en","libraries.textcomposer.components_LiveWaveformView_Night_0_en",0,], ["appnav.room.joined_LoadingRoomNodeView_Day_0_en","appnav.room.joined_LoadingRoomNodeView_Night_0_en",0,], -["appnav.room.joined_LoadingRoomNodeView_Day_1_en","appnav.room.joined_LoadingRoomNodeView_Night_1_en",19916,], -["features.lockscreen.impl.settings_LockScreenSettingsView_Day_0_en","features.lockscreen.impl.settings_LockScreenSettingsView_Night_0_en",19916,], -["features.lockscreen.impl.settings_LockScreenSettingsView_Day_1_en","features.lockscreen.impl.settings_LockScreenSettingsView_Night_1_en",19916,], -["features.lockscreen.impl.settings_LockScreenSettingsView_Day_2_en","features.lockscreen.impl.settings_LockScreenSettingsView_Night_2_en",19916,], +["appnav.room.joined_LoadingRoomNodeView_Day_1_en","appnav.room.joined_LoadingRoomNodeView_Night_1_en",19923,], +["features.lockscreen.impl.settings_LockScreenSettingsView_Day_0_en","features.lockscreen.impl.settings_LockScreenSettingsView_Night_0_en",19923,], +["features.lockscreen.impl.settings_LockScreenSettingsView_Day_1_en","features.lockscreen.impl.settings_LockScreenSettingsView_Night_1_en",19923,], +["features.lockscreen.impl.settings_LockScreenSettingsView_Day_2_en","features.lockscreen.impl.settings_LockScreenSettingsView_Night_2_en",19923,], ["appnav.loggedin_LoggedInView_Day_0_en","appnav.loggedin_LoggedInView_Night_0_en",0,], -["appnav.loggedin_LoggedInView_Day_1_en","appnav.loggedin_LoggedInView_Night_1_en",19916,], -["appnav.loggedin_LoggedInView_Day_2_en","appnav.loggedin_LoggedInView_Night_2_en",19916,], -["features.login.impl.screens.loginpassword_LoginPasswordView_Day_0_en","features.login.impl.screens.loginpassword_LoginPasswordView_Night_0_en",19916,], -["features.login.impl.screens.loginpassword_LoginPasswordView_Day_1_en","features.login.impl.screens.loginpassword_LoginPasswordView_Night_1_en",19916,], -["features.login.impl.screens.loginpassword_LoginPasswordView_Day_2_en","features.login.impl.screens.loginpassword_LoginPasswordView_Night_2_en",19916,], -["features.logout.impl_LogoutView_Day_0_en","features.logout.impl_LogoutView_Night_0_en",19916,], -["features.logout.impl_LogoutView_Day_1_en","features.logout.impl_LogoutView_Night_1_en",19916,], -["features.logout.impl_LogoutView_Day_2_en","features.logout.impl_LogoutView_Night_2_en",19916,], -["features.logout.impl_LogoutView_Day_3_en","features.logout.impl_LogoutView_Night_3_en",19916,], -["features.logout.impl_LogoutView_Day_4_en","features.logout.impl_LogoutView_Night_4_en",19916,], -["features.logout.impl_LogoutView_Day_5_en","features.logout.impl_LogoutView_Night_5_en",19916,], -["features.logout.impl_LogoutView_Day_6_en","features.logout.impl_LogoutView_Night_6_en",19916,], -["features.logout.impl_LogoutView_Day_7_en","features.logout.impl_LogoutView_Night_7_en",19916,], -["features.logout.impl_LogoutView_Day_8_en","features.logout.impl_LogoutView_Night_8_en",19916,], -["features.logout.impl_LogoutView_Day_9_en","features.logout.impl_LogoutView_Night_9_en",19916,], +["appnav.loggedin_LoggedInView_Day_1_en","appnav.loggedin_LoggedInView_Night_1_en",19923,], +["appnav.loggedin_LoggedInView_Day_2_en","appnav.loggedin_LoggedInView_Night_2_en",19923,], +["features.login.impl.screens.loginpassword_LoginPasswordView_Day_0_en","features.login.impl.screens.loginpassword_LoginPasswordView_Night_0_en",19923,], +["features.login.impl.screens.loginpassword_LoginPasswordView_Day_1_en","features.login.impl.screens.loginpassword_LoginPasswordView_Night_1_en",19923,], +["features.login.impl.screens.loginpassword_LoginPasswordView_Day_2_en","features.login.impl.screens.loginpassword_LoginPasswordView_Night_2_en",19923,], +["features.logout.impl_LogoutView_Day_0_en","features.logout.impl_LogoutView_Night_0_en",19923,], +["features.logout.impl_LogoutView_Day_1_en","features.logout.impl_LogoutView_Night_1_en",19923,], +["features.logout.impl_LogoutView_Day_2_en","features.logout.impl_LogoutView_Night_2_en",19923,], +["features.logout.impl_LogoutView_Day_3_en","features.logout.impl_LogoutView_Night_3_en",19923,], +["features.logout.impl_LogoutView_Day_4_en","features.logout.impl_LogoutView_Night_4_en",19923,], +["features.logout.impl_LogoutView_Day_5_en","features.logout.impl_LogoutView_Night_5_en",19923,], +["features.logout.impl_LogoutView_Day_6_en","features.logout.impl_LogoutView_Night_6_en",19923,], +["features.logout.impl_LogoutView_Day_7_en","features.logout.impl_LogoutView_Night_7_en",19923,], +["features.logout.impl_LogoutView_Day_8_en","features.logout.impl_LogoutView_Night_8_en",19923,], +["features.logout.impl_LogoutView_Day_9_en","features.logout.impl_LogoutView_Night_9_en",19923,], ["libraries.designsystem.components.button_MainActionButton_Buttons_en","",0,], -["libraries.textcomposer_MarkdownTextComposerEdit_Day_0_en","libraries.textcomposer_MarkdownTextComposerEdit_Night_0_en",19916,], +["libraries.textcomposer_MarkdownTextComposerEdit_Day_0_en","libraries.textcomposer_MarkdownTextComposerEdit_Night_0_en",19923,], ["libraries.textcomposer.components.markdown_MarkdownTextInput_Day_0_en","libraries.textcomposer.components.markdown_MarkdownTextInput_Night_0_en",0,], ["libraries.matrix.ui.components_MatrixUserHeaderPlaceholder_Day_0_en","libraries.matrix.ui.components_MatrixUserHeaderPlaceholder_Night_0_en",0,], ["libraries.matrix.ui.components_MatrixUserHeader_Day_0_en","libraries.matrix.ui.components_MatrixUserHeader_Night_0_en",0,], @@ -405,7 +410,7 @@ export const screenshots = [ ["libraries.mediaviewer.api.viewer_MediaViewerView_0_en","",0,], ["libraries.mediaviewer.api.viewer_MediaViewerView_10_en","",0,], ["libraries.mediaviewer.api.viewer_MediaViewerView_1_en","",0,], -["libraries.mediaviewer.api.viewer_MediaViewerView_2_en","",19916,], +["libraries.mediaviewer.api.viewer_MediaViewerView_2_en","",19923,], ["libraries.mediaviewer.api.viewer_MediaViewerView_3_en","",0,], ["libraries.mediaviewer.api.viewer_MediaViewerView_4_en","",0,], ["libraries.mediaviewer.api.viewer_MediaViewerView_5_en","",0,], @@ -414,11 +419,11 @@ export const screenshots = [ ["libraries.mediaviewer.api.viewer_MediaViewerView_8_en","",0,], ["libraries.mediaviewer.api.viewer_MediaViewerView_9_en","",0,], ["libraries.designsystem.theme.components_MediumTopAppBar_App Bars_en","",0,], -["libraries.textcomposer.mentions_MentionSpan_Day_0_en","libraries.textcomposer.mentions_MentionSpan_Night_0_en",0,], -["features.messages.impl.mentions_MentionSuggestionsPickerView_Day_0_en","features.messages.impl.mentions_MentionSuggestionsPickerView_Night_0_en",19916,], +["libraries.textcomposer.mentions_MentionSpanTheme_Day_0_en","libraries.textcomposer.mentions_MentionSpanTheme_Night_0_en",0,], +["features.messages.impl.mentions_MentionSuggestionsPickerView_Day_0_en","features.messages.impl.mentions_MentionSuggestionsPickerView_Night_0_en",19923,], ["libraries.designsystem.theme.components.previews_Menu_Menus_en","",0,], ["features.messages.impl.messagecomposer_MessageComposerViewVoice_Day_0_en","features.messages.impl.messagecomposer_MessageComposerViewVoice_Night_0_en",0,], -["features.messages.impl.messagecomposer_MessageComposerView_Day_0_en","features.messages.impl.messagecomposer_MessageComposerView_Night_0_en",19916,], +["features.messages.impl.messagecomposer_MessageComposerView_Day_0_en","features.messages.impl.messagecomposer_MessageComposerView_Night_0_en",19923,], ["features.messages.impl.timeline.components_MessageEventBubble_Day_0_en","features.messages.impl.timeline.components_MessageEventBubble_Night_0_en",0,], ["features.messages.impl.timeline.components_MessageEventBubble_Day_10_en","features.messages.impl.timeline.components_MessageEventBubble_Night_10_en",0,], ["features.messages.impl.timeline.components_MessageEventBubble_Day_11_en","features.messages.impl.timeline.components_MessageEventBubble_Night_11_en",0,], @@ -442,25 +447,25 @@ export const screenshots = [ ["features.messages.impl.timeline.components_MessagesReactionButton_Day_1_en","features.messages.impl.timeline.components_MessagesReactionButton_Night_1_en",0,], ["features.messages.impl.timeline.components_MessagesReactionButton_Day_2_en","features.messages.impl.timeline.components_MessagesReactionButton_Night_2_en",0,], ["features.messages.impl.timeline.components_MessagesReactionButton_Day_3_en","features.messages.impl.timeline.components_MessagesReactionButton_Night_3_en",0,], -["features.messages.impl.typing_MessagesViewWithTyping_Day_0_en","features.messages.impl.typing_MessagesViewWithTyping_Night_0_en",19916,], -["features.messages.impl.typing_MessagesViewWithTyping_Day_1_en","features.messages.impl.typing_MessagesViewWithTyping_Night_1_en",19916,], +["features.messages.impl.typing_MessagesViewWithTyping_Day_0_en","features.messages.impl.typing_MessagesViewWithTyping_Night_0_en",19923,], +["features.messages.impl.typing_MessagesViewWithTyping_Day_1_en","features.messages.impl.typing_MessagesViewWithTyping_Night_1_en",19923,], ["features.messages.impl.typing_MessagesViewWithTyping_Day_2_en","features.messages.impl.typing_MessagesViewWithTyping_Night_2_en",0,], -["features.messages.impl_MessagesView_Day_0_en","features.messages.impl_MessagesView_Night_0_en",19916,], -["features.messages.impl_MessagesView_Day_10_en","features.messages.impl_MessagesView_Night_10_en",19916,], -["features.messages.impl_MessagesView_Day_11_en","features.messages.impl_MessagesView_Night_11_en",19916,], -["features.messages.impl_MessagesView_Day_12_en","features.messages.impl_MessagesView_Night_12_en",19916,], +["features.messages.impl_MessagesView_Day_0_en","features.messages.impl_MessagesView_Night_0_en",19923,], +["features.messages.impl_MessagesView_Day_10_en","features.messages.impl_MessagesView_Night_10_en",19923,], +["features.messages.impl_MessagesView_Day_11_en","features.messages.impl_MessagesView_Night_11_en",19923,], +["features.messages.impl_MessagesView_Day_12_en","features.messages.impl_MessagesView_Night_12_en",19923,], ["features.messages.impl_MessagesView_Day_1_en","features.messages.impl_MessagesView_Night_1_en",0,], -["features.messages.impl_MessagesView_Day_2_en","features.messages.impl_MessagesView_Night_2_en",19916,], -["features.messages.impl_MessagesView_Day_3_en","features.messages.impl_MessagesView_Night_3_en",19916,], -["features.messages.impl_MessagesView_Day_4_en","features.messages.impl_MessagesView_Night_4_en",19916,], -["features.messages.impl_MessagesView_Day_5_en","features.messages.impl_MessagesView_Night_5_en",19916,], -["features.messages.impl_MessagesView_Day_6_en","features.messages.impl_MessagesView_Night_6_en",19916,], -["features.messages.impl_MessagesView_Day_7_en","features.messages.impl_MessagesView_Night_7_en",19916,], -["features.messages.impl_MessagesView_Day_8_en","features.messages.impl_MessagesView_Night_8_en",19916,], -["features.messages.impl_MessagesView_Day_9_en","features.messages.impl_MessagesView_Night_9_en",19916,], -["features.roomlist.impl.migration_MigrationScreenView_Day_0_en","features.roomlist.impl.migration_MigrationScreenView_Night_0_en",19916,], +["features.messages.impl_MessagesView_Day_2_en","features.messages.impl_MessagesView_Night_2_en",19923,], +["features.messages.impl_MessagesView_Day_3_en","features.messages.impl_MessagesView_Night_3_en",19923,], +["features.messages.impl_MessagesView_Day_4_en","features.messages.impl_MessagesView_Night_4_en",19923,], +["features.messages.impl_MessagesView_Day_5_en","features.messages.impl_MessagesView_Night_5_en",19923,], +["features.messages.impl_MessagesView_Day_6_en","features.messages.impl_MessagesView_Night_6_en",19923,], +["features.messages.impl_MessagesView_Day_7_en","features.messages.impl_MessagesView_Night_7_en",19923,], +["features.messages.impl_MessagesView_Day_8_en","features.messages.impl_MessagesView_Night_8_en",19923,], +["features.messages.impl_MessagesView_Day_9_en","features.messages.impl_MessagesView_Night_9_en",19923,], +["features.roomlist.impl.migration_MigrationScreenView_Day_0_en","features.roomlist.impl.migration_MigrationScreenView_Night_0_en",19923,], ["features.migration.impl_MigrationView_Day_0_en","features.migration.impl_MigrationView_Night_0_en",0,], -["features.migration.impl_MigrationView_Day_1_en","features.migration.impl_MigrationView_Night_1_en",19916,], +["features.migration.impl_MigrationView_Day_1_en","features.migration.impl_MigrationView_Night_1_en",19923,], ["libraries.designsystem.theme.components_ModalBottomSheetDark_Bottom Sheets_en","",0,], ["libraries.designsystem.theme.components_ModalBottomSheetLight_Bottom Sheets_en","",0,], ["appicon.element_MonochromeIcon_en","",0,], @@ -469,30 +474,32 @@ export const screenshots = [ ["libraries.designsystem.components.list_MutipleSelectionListItemSelectedTrailingContent_Multiple selection List item - selection in trailing content_List items_en","",0,], ["libraries.designsystem.components.list_MutipleSelectionListItemSelected_Multiple selection List item - selection in supporting text_List items_en","",0,], ["libraries.designsystem.components.list_MutipleSelectionListItem_Multiple selection List item - no selection_List items_en","",0,], -["features.preferences.impl.notifications_NotificationSettingsView_Day_0_en","features.preferences.impl.notifications_NotificationSettingsView_Night_0_en",19916,], -["features.preferences.impl.notifications_NotificationSettingsView_Day_10_en","features.preferences.impl.notifications_NotificationSettingsView_Night_10_en",19916,], -["features.preferences.impl.notifications_NotificationSettingsView_Day_11_en","features.preferences.impl.notifications_NotificationSettingsView_Night_11_en",19916,], -["features.preferences.impl.notifications_NotificationSettingsView_Day_12_en","features.preferences.impl.notifications_NotificationSettingsView_Night_12_en",19916,], -["features.preferences.impl.notifications_NotificationSettingsView_Day_1_en","features.preferences.impl.notifications_NotificationSettingsView_Night_1_en",19916,], -["features.preferences.impl.notifications_NotificationSettingsView_Day_2_en","features.preferences.impl.notifications_NotificationSettingsView_Night_2_en",19916,], -["features.preferences.impl.notifications_NotificationSettingsView_Day_3_en","features.preferences.impl.notifications_NotificationSettingsView_Night_3_en",19916,], -["features.preferences.impl.notifications_NotificationSettingsView_Day_4_en","features.preferences.impl.notifications_NotificationSettingsView_Night_4_en",19916,], -["features.preferences.impl.notifications_NotificationSettingsView_Day_5_en","features.preferences.impl.notifications_NotificationSettingsView_Night_5_en",19916,], -["features.preferences.impl.notifications_NotificationSettingsView_Day_6_en","features.preferences.impl.notifications_NotificationSettingsView_Night_6_en",19916,], -["features.preferences.impl.notifications_NotificationSettingsView_Day_7_en","features.preferences.impl.notifications_NotificationSettingsView_Night_7_en",19916,], -["features.preferences.impl.notifications_NotificationSettingsView_Day_8_en","features.preferences.impl.notifications_NotificationSettingsView_Night_8_en",19916,], -["features.preferences.impl.notifications_NotificationSettingsView_Day_9_en","features.preferences.impl.notifications_NotificationSettingsView_Night_9_en",19916,], -["features.ftue.impl.notifications_NotificationsOptInView_Day_0_en","features.ftue.impl.notifications_NotificationsOptInView_Night_0_en",19916,], +["features.preferences.impl.notifications_NotificationSettingsView_Day_0_en","features.preferences.impl.notifications_NotificationSettingsView_Night_0_en",19923,], +["features.preferences.impl.notifications_NotificationSettingsView_Day_10_en","features.preferences.impl.notifications_NotificationSettingsView_Night_10_en",19923,], +["features.preferences.impl.notifications_NotificationSettingsView_Day_11_en","features.preferences.impl.notifications_NotificationSettingsView_Night_11_en",19923,], +["features.preferences.impl.notifications_NotificationSettingsView_Day_12_en","features.preferences.impl.notifications_NotificationSettingsView_Night_12_en",19923,], +["features.preferences.impl.notifications_NotificationSettingsView_Day_1_en","features.preferences.impl.notifications_NotificationSettingsView_Night_1_en",19923,], +["features.preferences.impl.notifications_NotificationSettingsView_Day_2_en","features.preferences.impl.notifications_NotificationSettingsView_Night_2_en",19923,], +["features.preferences.impl.notifications_NotificationSettingsView_Day_3_en","features.preferences.impl.notifications_NotificationSettingsView_Night_3_en",19923,], +["features.preferences.impl.notifications_NotificationSettingsView_Day_4_en","features.preferences.impl.notifications_NotificationSettingsView_Night_4_en",19923,], +["features.preferences.impl.notifications_NotificationSettingsView_Day_5_en","features.preferences.impl.notifications_NotificationSettingsView_Night_5_en",19923,], +["features.preferences.impl.notifications_NotificationSettingsView_Day_6_en","features.preferences.impl.notifications_NotificationSettingsView_Night_6_en",19923,], +["features.preferences.impl.notifications_NotificationSettingsView_Day_7_en","features.preferences.impl.notifications_NotificationSettingsView_Night_7_en",19923,], +["features.preferences.impl.notifications_NotificationSettingsView_Day_8_en","features.preferences.impl.notifications_NotificationSettingsView_Night_8_en",19923,], +["features.preferences.impl.notifications_NotificationSettingsView_Day_9_en","features.preferences.impl.notifications_NotificationSettingsView_Night_9_en",19923,], +["features.ftue.impl.notifications_NotificationsOptInView_Day_0_en","features.ftue.impl.notifications_NotificationsOptInView_Night_0_en",19923,], ["features.login.impl.oidc.webview_OidcView_Day_0_en","features.login.impl.oidc.webview_OidcView_Night_0_en",0,], ["features.login.impl.oidc.webview_OidcView_Day_1_en","features.login.impl.oidc.webview_OidcView_Night_1_en",0,], ["libraries.designsystem.atomic.pages_OnBoardingPage_Day_0_en","libraries.designsystem.atomic.pages_OnBoardingPage_Night_0_en",0,], -["features.onboarding.impl_OnBoardingView_Day_0_en","features.onboarding.impl_OnBoardingView_Night_0_en",19916,], -["features.onboarding.impl_OnBoardingView_Day_1_en","features.onboarding.impl_OnBoardingView_Night_1_en",19916,], -["features.onboarding.impl_OnBoardingView_Day_2_en","features.onboarding.impl_OnBoardingView_Night_2_en",19916,], -["features.onboarding.impl_OnBoardingView_Day_3_en","features.onboarding.impl_OnBoardingView_Night_3_en",19916,], -["features.onboarding.impl_OnBoardingView_Day_4_en","features.onboarding.impl_OnBoardingView_Night_4_en",19916,], +["features.onboarding.impl_OnBoardingView_Day_0_en","features.onboarding.impl_OnBoardingView_Night_0_en",19923,], +["features.onboarding.impl_OnBoardingView_Day_1_en","features.onboarding.impl_OnBoardingView_Night_1_en",19923,], +["features.onboarding.impl_OnBoardingView_Day_2_en","features.onboarding.impl_OnBoardingView_Night_2_en",19923,], +["features.onboarding.impl_OnBoardingView_Day_3_en","features.onboarding.impl_OnBoardingView_Night_3_en",19923,], +["features.onboarding.impl_OnBoardingView_Day_4_en","features.onboarding.impl_OnBoardingView_Night_4_en",19923,], ["libraries.designsystem.background_OnboardingBackground_Day_0_en","libraries.designsystem.background_OnboardingBackground_Night_0_en",0,], +["libraries.designsystem.theme.components_OutlinedButtonLargeLowPadding_Buttons_en","",0,], ["libraries.designsystem.theme.components_OutlinedButtonLarge_Buttons_en","",0,], +["libraries.designsystem.theme.components_OutlinedButtonMediumLowPadding_Buttons_en","",0,], ["libraries.designsystem.theme.components_OutlinedButtonMedium_Buttons_en","",0,], ["libraries.designsystem.theme.components_OutlinedButtonSmall_Buttons_en","",0,], ["libraries.designsystem.theme.components_OutlinedTextFieldsDark_TextFields_en","",0,], @@ -503,47 +510,47 @@ export const screenshots = [ ["libraries.designsystem.components_PageTitleWithIconFull_Day_3_en","libraries.designsystem.components_PageTitleWithIconFull_Night_3_en",0,], ["libraries.designsystem.components_PageTitleWithIconFull_Day_4_en","libraries.designsystem.components_PageTitleWithIconFull_Night_4_en",0,], ["libraries.designsystem.components_PageTitleWithIconMinimal_Day_0_en","libraries.designsystem.components_PageTitleWithIconMinimal_Night_0_en",0,], -["features.roomdetails.impl.rolesandpermissions.changeroles_PendingMemberRowWithLongName_Day_0_en","features.roomdetails.impl.rolesandpermissions.changeroles_PendingMemberRowWithLongName_Night_0_en",19916,], -["libraries.permissions.api_PermissionsView_Day_0_en","libraries.permissions.api_PermissionsView_Night_0_en",19916,], -["libraries.permissions.api_PermissionsView_Day_1_en","libraries.permissions.api_PermissionsView_Night_1_en",19916,], -["libraries.permissions.api_PermissionsView_Day_2_en","libraries.permissions.api_PermissionsView_Night_2_en",19916,], -["libraries.permissions.api_PermissionsView_Day_3_en","libraries.permissions.api_PermissionsView_Night_3_en",19916,], +["features.roomdetails.impl.rolesandpermissions.changeroles_PendingMemberRowWithLongName_Day_0_en","features.roomdetails.impl.rolesandpermissions.changeroles_PendingMemberRowWithLongName_Night_0_en",19923,], +["libraries.permissions.api_PermissionsView_Day_0_en","libraries.permissions.api_PermissionsView_Night_0_en",19923,], +["libraries.permissions.api_PermissionsView_Day_1_en","libraries.permissions.api_PermissionsView_Night_1_en",19923,], +["libraries.permissions.api_PermissionsView_Day_2_en","libraries.permissions.api_PermissionsView_Night_2_en",19923,], +["libraries.permissions.api_PermissionsView_Day_3_en","libraries.permissions.api_PermissionsView_Night_3_en",19923,], ["features.lockscreen.impl.components_PinEntryTextField_Day_0_en","features.lockscreen.impl.components_PinEntryTextField_Night_0_en",0,], ["libraries.designsystem.components_PinIcon_Day_0_en","libraries.designsystem.components_PinIcon_Night_0_en",0,], ["features.lockscreen.impl.unlock.keypad_PinKeypad_Day_0_en","features.lockscreen.impl.unlock.keypad_PinKeypad_Night_0_en",0,], -["features.lockscreen.impl.unlock_PinUnlockViewInApp_Day_0_en","features.lockscreen.impl.unlock_PinUnlockViewInApp_Night_0_en",19916,], -["features.lockscreen.impl.unlock_PinUnlockViewInApp_Day_1_en","features.lockscreen.impl.unlock_PinUnlockViewInApp_Night_1_en",19916,], -["features.lockscreen.impl.unlock_PinUnlockViewInApp_Day_2_en","features.lockscreen.impl.unlock_PinUnlockViewInApp_Night_2_en",19916,], -["features.lockscreen.impl.unlock_PinUnlockViewInApp_Day_3_en","features.lockscreen.impl.unlock_PinUnlockViewInApp_Night_3_en",19916,], -["features.lockscreen.impl.unlock_PinUnlockViewInApp_Day_4_en","features.lockscreen.impl.unlock_PinUnlockViewInApp_Night_4_en",19916,], -["features.lockscreen.impl.unlock_PinUnlockViewInApp_Day_5_en","features.lockscreen.impl.unlock_PinUnlockViewInApp_Night_5_en",19916,], -["features.lockscreen.impl.unlock_PinUnlockViewInApp_Day_6_en","features.lockscreen.impl.unlock_PinUnlockViewInApp_Night_6_en",19916,], -["features.lockscreen.impl.unlock_PinUnlockView_Day_0_en","features.lockscreen.impl.unlock_PinUnlockView_Night_0_en",19916,], -["features.lockscreen.impl.unlock_PinUnlockView_Day_1_en","features.lockscreen.impl.unlock_PinUnlockView_Night_1_en",19916,], -["features.lockscreen.impl.unlock_PinUnlockView_Day_2_en","features.lockscreen.impl.unlock_PinUnlockView_Night_2_en",19916,], -["features.lockscreen.impl.unlock_PinUnlockView_Day_3_en","features.lockscreen.impl.unlock_PinUnlockView_Night_3_en",19916,], -["features.lockscreen.impl.unlock_PinUnlockView_Day_4_en","features.lockscreen.impl.unlock_PinUnlockView_Night_4_en",19916,], -["features.lockscreen.impl.unlock_PinUnlockView_Day_5_en","features.lockscreen.impl.unlock_PinUnlockView_Night_5_en",19916,], -["features.lockscreen.impl.unlock_PinUnlockView_Day_6_en","features.lockscreen.impl.unlock_PinUnlockView_Night_6_en",19916,], +["features.lockscreen.impl.unlock_PinUnlockViewInApp_Day_0_en","features.lockscreen.impl.unlock_PinUnlockViewInApp_Night_0_en",19923,], +["features.lockscreen.impl.unlock_PinUnlockViewInApp_Day_1_en","features.lockscreen.impl.unlock_PinUnlockViewInApp_Night_1_en",19923,], +["features.lockscreen.impl.unlock_PinUnlockViewInApp_Day_2_en","features.lockscreen.impl.unlock_PinUnlockViewInApp_Night_2_en",19923,], +["features.lockscreen.impl.unlock_PinUnlockViewInApp_Day_3_en","features.lockscreen.impl.unlock_PinUnlockViewInApp_Night_3_en",19923,], +["features.lockscreen.impl.unlock_PinUnlockViewInApp_Day_4_en","features.lockscreen.impl.unlock_PinUnlockViewInApp_Night_4_en",19923,], +["features.lockscreen.impl.unlock_PinUnlockViewInApp_Day_5_en","features.lockscreen.impl.unlock_PinUnlockViewInApp_Night_5_en",19923,], +["features.lockscreen.impl.unlock_PinUnlockViewInApp_Day_6_en","features.lockscreen.impl.unlock_PinUnlockViewInApp_Night_6_en",19923,], +["features.lockscreen.impl.unlock_PinUnlockView_Day_0_en","features.lockscreen.impl.unlock_PinUnlockView_Night_0_en",19923,], +["features.lockscreen.impl.unlock_PinUnlockView_Day_1_en","features.lockscreen.impl.unlock_PinUnlockView_Night_1_en",19923,], +["features.lockscreen.impl.unlock_PinUnlockView_Day_2_en","features.lockscreen.impl.unlock_PinUnlockView_Night_2_en",19923,], +["features.lockscreen.impl.unlock_PinUnlockView_Day_3_en","features.lockscreen.impl.unlock_PinUnlockView_Night_3_en",19923,], +["features.lockscreen.impl.unlock_PinUnlockView_Day_4_en","features.lockscreen.impl.unlock_PinUnlockView_Night_4_en",19923,], +["features.lockscreen.impl.unlock_PinUnlockView_Day_5_en","features.lockscreen.impl.unlock_PinUnlockView_Night_5_en",19923,], +["features.lockscreen.impl.unlock_PinUnlockView_Day_6_en","features.lockscreen.impl.unlock_PinUnlockView_Night_6_en",19923,], ["libraries.designsystem.atomic.atoms_PlaceholderAtom_Day_0_en","libraries.designsystem.atomic.atoms_PlaceholderAtom_Night_0_en",0,], -["features.poll.api.pollcontent_PollAnswerViewDisclosedNotSelected_Day_0_en","features.poll.api.pollcontent_PollAnswerViewDisclosedNotSelected_Night_0_en",19916,], -["features.poll.api.pollcontent_PollAnswerViewDisclosedSelected_Day_0_en","features.poll.api.pollcontent_PollAnswerViewDisclosedSelected_Night_0_en",19916,], -["features.poll.api.pollcontent_PollAnswerViewEndedSelected_Day_0_en","features.poll.api.pollcontent_PollAnswerViewEndedSelected_Night_0_en",19916,], -["features.poll.api.pollcontent_PollAnswerViewEndedWinnerNotSelected_Day_0_en","features.poll.api.pollcontent_PollAnswerViewEndedWinnerNotSelected_Night_0_en",19916,], -["features.poll.api.pollcontent_PollAnswerViewEndedWinnerSelected_Day_0_en","features.poll.api.pollcontent_PollAnswerViewEndedWinnerSelected_Night_0_en",19916,], +["features.poll.api.pollcontent_PollAnswerViewDisclosedNotSelected_Day_0_en","features.poll.api.pollcontent_PollAnswerViewDisclosedNotSelected_Night_0_en",19923,], +["features.poll.api.pollcontent_PollAnswerViewDisclosedSelected_Day_0_en","features.poll.api.pollcontent_PollAnswerViewDisclosedSelected_Night_0_en",19923,], +["features.poll.api.pollcontent_PollAnswerViewEndedSelected_Day_0_en","features.poll.api.pollcontent_PollAnswerViewEndedSelected_Night_0_en",19923,], +["features.poll.api.pollcontent_PollAnswerViewEndedWinnerNotSelected_Day_0_en","features.poll.api.pollcontent_PollAnswerViewEndedWinnerNotSelected_Night_0_en",19923,], +["features.poll.api.pollcontent_PollAnswerViewEndedWinnerSelected_Day_0_en","features.poll.api.pollcontent_PollAnswerViewEndedWinnerSelected_Night_0_en",19923,], ["features.poll.api.pollcontent_PollAnswerViewUndisclosedNotSelected_Day_0_en","features.poll.api.pollcontent_PollAnswerViewUndisclosedNotSelected_Night_0_en",0,], ["features.poll.api.pollcontent_PollAnswerViewUndisclosedSelected_Day_0_en","features.poll.api.pollcontent_PollAnswerViewUndisclosedSelected_Night_0_en",0,], -["features.poll.api.pollcontent_PollContentViewCreatorEditable_Day_0_en","features.poll.api.pollcontent_PollContentViewCreatorEditable_Night_0_en",19916,], -["features.poll.api.pollcontent_PollContentViewCreatorEnded_Day_0_en","features.poll.api.pollcontent_PollContentViewCreatorEnded_Night_0_en",19916,], -["features.poll.api.pollcontent_PollContentViewCreator_Day_0_en","features.poll.api.pollcontent_PollContentViewCreator_Night_0_en",19916,], -["features.poll.api.pollcontent_PollContentViewDisclosed_Day_0_en","features.poll.api.pollcontent_PollContentViewDisclosed_Night_0_en",19916,], -["features.poll.api.pollcontent_PollContentViewEnded_Day_0_en","features.poll.api.pollcontent_PollContentViewEnded_Night_0_en",19916,], -["features.poll.api.pollcontent_PollContentViewUndisclosed_Day_0_en","features.poll.api.pollcontent_PollContentViewUndisclosed_Night_0_en",19916,], -["features.poll.impl.history_PollHistoryView_Day_0_en","features.poll.impl.history_PollHistoryView_Night_0_en",19916,], -["features.poll.impl.history_PollHistoryView_Day_1_en","features.poll.impl.history_PollHistoryView_Night_1_en",19916,], -["features.poll.impl.history_PollHistoryView_Day_2_en","features.poll.impl.history_PollHistoryView_Night_2_en",19916,], -["features.poll.impl.history_PollHistoryView_Day_3_en","features.poll.impl.history_PollHistoryView_Night_3_en",19916,], -["features.poll.impl.history_PollHistoryView_Day_4_en","features.poll.impl.history_PollHistoryView_Night_4_en",19916,], +["features.poll.api.pollcontent_PollContentViewCreatorEditable_Day_0_en","features.poll.api.pollcontent_PollContentViewCreatorEditable_Night_0_en",19923,], +["features.poll.api.pollcontent_PollContentViewCreatorEnded_Day_0_en","features.poll.api.pollcontent_PollContentViewCreatorEnded_Night_0_en",19923,], +["features.poll.api.pollcontent_PollContentViewCreator_Day_0_en","features.poll.api.pollcontent_PollContentViewCreator_Night_0_en",19923,], +["features.poll.api.pollcontent_PollContentViewDisclosed_Day_0_en","features.poll.api.pollcontent_PollContentViewDisclosed_Night_0_en",19923,], +["features.poll.api.pollcontent_PollContentViewEnded_Day_0_en","features.poll.api.pollcontent_PollContentViewEnded_Night_0_en",19923,], +["features.poll.api.pollcontent_PollContentViewUndisclosed_Day_0_en","features.poll.api.pollcontent_PollContentViewUndisclosed_Night_0_en",19923,], +["features.poll.impl.history_PollHistoryView_Day_0_en","features.poll.impl.history_PollHistoryView_Night_0_en",19923,], +["features.poll.impl.history_PollHistoryView_Day_1_en","features.poll.impl.history_PollHistoryView_Night_1_en",19923,], +["features.poll.impl.history_PollHistoryView_Day_2_en","features.poll.impl.history_PollHistoryView_Night_2_en",19923,], +["features.poll.impl.history_PollHistoryView_Day_3_en","features.poll.impl.history_PollHistoryView_Night_3_en",19923,], +["features.poll.impl.history_PollHistoryView_Day_4_en","features.poll.impl.history_PollHistoryView_Night_4_en",19923,], ["libraries.designsystem.components.preferences_PreferenceCategory_Preferences_en","",0,], ["libraries.designsystem.components.preferences_PreferenceCheckbox_Preferences_en","",0,], ["libraries.designsystem.components.preferences_PreferenceDivider_Preferences_en","",0,], @@ -559,181 +566,182 @@ export const screenshots = [ ["libraries.designsystem.components.preferences_PreferenceTextLight_Preferences_en","",0,], ["libraries.designsystem.components.preferences_PreferenceTextWithEndBadgeDark_Preferences_en","",0,], ["libraries.designsystem.components.preferences_PreferenceTextWithEndBadgeLight_Preferences_en","",0,], -["features.preferences.impl.root_PreferencesRootViewDark_0_en","",19916,], -["features.preferences.impl.root_PreferencesRootViewDark_1_en","",19916,], -["features.preferences.impl.root_PreferencesRootViewLight_0_en","",19916,], -["features.preferences.impl.root_PreferencesRootViewLight_1_en","",19916,], +["features.preferences.impl.root_PreferencesRootViewDark_0_en","",19923,], +["features.preferences.impl.root_PreferencesRootViewDark_1_en","",19923,], +["features.preferences.impl.root_PreferencesRootViewLight_0_en","",19923,], +["features.preferences.impl.root_PreferencesRootViewLight_1_en","",19923,], ["features.messages.impl.timeline.components.event_ProgressButton_Day_0_en","features.messages.impl.timeline.components.event_ProgressButton_Night_0_en",0,], -["libraries.designsystem.components_ProgressDialogContent_Dialogs_en","",19916,], -["libraries.designsystem.components_ProgressDialog_Day_0_en","libraries.designsystem.components_ProgressDialog_Night_0_en",19916,], -["features.login.impl.screens.qrcode.confirmation_QrCodeConfirmationView_Day_0_en","features.login.impl.screens.qrcode.confirmation_QrCodeConfirmationView_Night_0_en",19916,], -["features.login.impl.screens.qrcode.confirmation_QrCodeConfirmationView_Day_1_en","features.login.impl.screens.qrcode.confirmation_QrCodeConfirmationView_Night_1_en",19916,], -["features.login.impl.screens.qrcode.confirmation_QrCodeConfirmationView_Day_2_en","features.login.impl.screens.qrcode.confirmation_QrCodeConfirmationView_Night_2_en",19916,], -["features.login.impl.screens.qrcode.error_QrCodeErrorView_Day_0_en","features.login.impl.screens.qrcode.error_QrCodeErrorView_Night_0_en",19916,], -["features.login.impl.screens.qrcode.error_QrCodeErrorView_Day_1_en","features.login.impl.screens.qrcode.error_QrCodeErrorView_Night_1_en",19916,], -["features.login.impl.screens.qrcode.error_QrCodeErrorView_Day_2_en","features.login.impl.screens.qrcode.error_QrCodeErrorView_Night_2_en",19916,], -["features.login.impl.screens.qrcode.error_QrCodeErrorView_Day_3_en","features.login.impl.screens.qrcode.error_QrCodeErrorView_Night_3_en",19916,], -["features.login.impl.screens.qrcode.error_QrCodeErrorView_Day_4_en","features.login.impl.screens.qrcode.error_QrCodeErrorView_Night_4_en",19916,], -["features.login.impl.screens.qrcode.error_QrCodeErrorView_Day_5_en","features.login.impl.screens.qrcode.error_QrCodeErrorView_Night_5_en",19916,], -["features.login.impl.screens.qrcode.error_QrCodeErrorView_Day_6_en","features.login.impl.screens.qrcode.error_QrCodeErrorView_Night_6_en",19916,], -["features.login.impl.screens.qrcode.intro_QrCodeIntroView_Day_0_en","features.login.impl.screens.qrcode.intro_QrCodeIntroView_Night_0_en",19916,], -["features.login.impl.screens.qrcode.intro_QrCodeIntroView_Day_1_en","features.login.impl.screens.qrcode.intro_QrCodeIntroView_Night_1_en",19916,], -["features.login.impl.screens.qrcode.scan_QrCodeScanView_Day_0_en","features.login.impl.screens.qrcode.scan_QrCodeScanView_Night_0_en",19916,], -["features.login.impl.screens.qrcode.scan_QrCodeScanView_Day_1_en","features.login.impl.screens.qrcode.scan_QrCodeScanView_Night_1_en",19916,], -["features.login.impl.screens.qrcode.scan_QrCodeScanView_Day_2_en","features.login.impl.screens.qrcode.scan_QrCodeScanView_Night_2_en",19916,], -["features.login.impl.screens.qrcode.scan_QrCodeScanView_Day_3_en","features.login.impl.screens.qrcode.scan_QrCodeScanView_Night_3_en",19916,], +["libraries.designsystem.components_ProgressDialogContent_Dialogs_en","",19923,], +["libraries.designsystem.components_ProgressDialog_Day_0_en","libraries.designsystem.components_ProgressDialog_Night_0_en",19923,], +["features.login.impl.screens.qrcode.confirmation_QrCodeConfirmationView_Day_0_en","features.login.impl.screens.qrcode.confirmation_QrCodeConfirmationView_Night_0_en",19923,], +["features.login.impl.screens.qrcode.confirmation_QrCodeConfirmationView_Day_1_en","features.login.impl.screens.qrcode.confirmation_QrCodeConfirmationView_Night_1_en",19923,], +["features.login.impl.screens.qrcode.confirmation_QrCodeConfirmationView_Day_2_en","features.login.impl.screens.qrcode.confirmation_QrCodeConfirmationView_Night_2_en",19923,], +["features.login.impl.screens.qrcode.error_QrCodeErrorView_Day_0_en","features.login.impl.screens.qrcode.error_QrCodeErrorView_Night_0_en",19923,], +["features.login.impl.screens.qrcode.error_QrCodeErrorView_Day_1_en","features.login.impl.screens.qrcode.error_QrCodeErrorView_Night_1_en",19923,], +["features.login.impl.screens.qrcode.error_QrCodeErrorView_Day_2_en","features.login.impl.screens.qrcode.error_QrCodeErrorView_Night_2_en",19923,], +["features.login.impl.screens.qrcode.error_QrCodeErrorView_Day_3_en","features.login.impl.screens.qrcode.error_QrCodeErrorView_Night_3_en",19923,], +["features.login.impl.screens.qrcode.error_QrCodeErrorView_Day_4_en","features.login.impl.screens.qrcode.error_QrCodeErrorView_Night_4_en",19923,], +["features.login.impl.screens.qrcode.error_QrCodeErrorView_Day_5_en","features.login.impl.screens.qrcode.error_QrCodeErrorView_Night_5_en",19923,], +["features.login.impl.screens.qrcode.error_QrCodeErrorView_Day_6_en","features.login.impl.screens.qrcode.error_QrCodeErrorView_Night_6_en",19923,], +["features.login.impl.screens.qrcode.intro_QrCodeIntroView_Day_0_en","features.login.impl.screens.qrcode.intro_QrCodeIntroView_Night_0_en",19923,], +["features.login.impl.screens.qrcode.intro_QrCodeIntroView_Day_1_en","features.login.impl.screens.qrcode.intro_QrCodeIntroView_Night_1_en",19923,], +["features.login.impl.screens.qrcode.scan_QrCodeScanView_Day_0_en","features.login.impl.screens.qrcode.scan_QrCodeScanView_Night_0_en",19923,], +["features.login.impl.screens.qrcode.scan_QrCodeScanView_Day_1_en","features.login.impl.screens.qrcode.scan_QrCodeScanView_Night_1_en",19923,], +["features.login.impl.screens.qrcode.scan_QrCodeScanView_Day_2_en","features.login.impl.screens.qrcode.scan_QrCodeScanView_Night_2_en",19923,], +["features.login.impl.screens.qrcode.scan_QrCodeScanView_Day_3_en","features.login.impl.screens.qrcode.scan_QrCodeScanView_Night_3_en",19923,], ["libraries.designsystem.theme.components_RadioButton_Toggles_en","",0,], -["features.rageshake.api.detection_RageshakeDialogContent_Day_0_en","features.rageshake.api.detection_RageshakeDialogContent_Night_0_en",19916,], -["features.rageshake.api.preferences_RageshakePreferencesView_Day_0_en","features.rageshake.api.preferences_RageshakePreferencesView_Night_0_en",19916,], +["features.rageshake.api.detection_RageshakeDialogContent_Day_0_en","features.rageshake.api.detection_RageshakeDialogContent_Night_0_en",19923,], +["features.rageshake.api.preferences_RageshakePreferencesView_Day_0_en","features.rageshake.api.preferences_RageshakePreferencesView_Night_0_en",19923,], ["features.rageshake.api.preferences_RageshakePreferencesView_Day_1_en","features.rageshake.api.preferences_RageshakePreferencesView_Night_1_en",0,], -["features.messages.impl.timeline.components.receipt.bottomsheet_ReadReceiptBottomSheet_Day_0_en","features.messages.impl.timeline.components.receipt.bottomsheet_ReadReceiptBottomSheet_Night_0_en",19916,], -["features.messages.impl.timeline.components.receipt.bottomsheet_ReadReceiptBottomSheet_Day_1_en","features.messages.impl.timeline.components.receipt.bottomsheet_ReadReceiptBottomSheet_Night_1_en",19916,], -["features.messages.impl.timeline.components.receipt.bottomsheet_ReadReceiptBottomSheet_Day_2_en","features.messages.impl.timeline.components.receipt.bottomsheet_ReadReceiptBottomSheet_Night_2_en",19916,], -["features.messages.impl.timeline.components.receipt.bottomsheet_ReadReceiptBottomSheet_Day_3_en","features.messages.impl.timeline.components.receipt.bottomsheet_ReadReceiptBottomSheet_Night_3_en",19916,], -["features.messages.impl.timeline.components.receipt.bottomsheet_ReadReceiptBottomSheet_Day_4_en","features.messages.impl.timeline.components.receipt.bottomsheet_ReadReceiptBottomSheet_Night_4_en",19916,], -["features.messages.impl.timeline.components.receipt.bottomsheet_ReadReceiptBottomSheet_Day_5_en","features.messages.impl.timeline.components.receipt.bottomsheet_ReadReceiptBottomSheet_Night_5_en",19916,], -["features.securebackup.impl.setup.views_RecoveryKeyView_Day_0_en","features.securebackup.impl.setup.views_RecoveryKeyView_Night_0_en",19916,], -["features.securebackup.impl.setup.views_RecoveryKeyView_Day_10_en","features.securebackup.impl.setup.views_RecoveryKeyView_Night_10_en",19916,], -["features.securebackup.impl.setup.views_RecoveryKeyView_Day_11_en","features.securebackup.impl.setup.views_RecoveryKeyView_Night_11_en",19916,], -["features.securebackup.impl.setup.views_RecoveryKeyView_Day_1_en","features.securebackup.impl.setup.views_RecoveryKeyView_Night_1_en",19916,], -["features.securebackup.impl.setup.views_RecoveryKeyView_Day_2_en","features.securebackup.impl.setup.views_RecoveryKeyView_Night_2_en",19916,], -["features.securebackup.impl.setup.views_RecoveryKeyView_Day_3_en","features.securebackup.impl.setup.views_RecoveryKeyView_Night_3_en",19916,], -["features.securebackup.impl.setup.views_RecoveryKeyView_Day_4_en","features.securebackup.impl.setup.views_RecoveryKeyView_Night_4_en",19916,], -["features.securebackup.impl.setup.views_RecoveryKeyView_Day_5_en","features.securebackup.impl.setup.views_RecoveryKeyView_Night_5_en",19916,], -["features.securebackup.impl.setup.views_RecoveryKeyView_Day_6_en","features.securebackup.impl.setup.views_RecoveryKeyView_Night_6_en",19916,], -["features.securebackup.impl.setup.views_RecoveryKeyView_Day_7_en","features.securebackup.impl.setup.views_RecoveryKeyView_Night_7_en",19916,], -["features.securebackup.impl.setup.views_RecoveryKeyView_Day_8_en","features.securebackup.impl.setup.views_RecoveryKeyView_Night_8_en",19916,], -["features.securebackup.impl.setup.views_RecoveryKeyView_Day_9_en","features.securebackup.impl.setup.views_RecoveryKeyView_Night_9_en",19916,], +["features.messages.impl.timeline.components.receipt.bottomsheet_ReadReceiptBottomSheet_Day_0_en","features.messages.impl.timeline.components.receipt.bottomsheet_ReadReceiptBottomSheet_Night_0_en",19923,], +["features.messages.impl.timeline.components.receipt.bottomsheet_ReadReceiptBottomSheet_Day_1_en","features.messages.impl.timeline.components.receipt.bottomsheet_ReadReceiptBottomSheet_Night_1_en",19923,], +["features.messages.impl.timeline.components.receipt.bottomsheet_ReadReceiptBottomSheet_Day_2_en","features.messages.impl.timeline.components.receipt.bottomsheet_ReadReceiptBottomSheet_Night_2_en",19923,], +["features.messages.impl.timeline.components.receipt.bottomsheet_ReadReceiptBottomSheet_Day_3_en","features.messages.impl.timeline.components.receipt.bottomsheet_ReadReceiptBottomSheet_Night_3_en",19923,], +["features.messages.impl.timeline.components.receipt.bottomsheet_ReadReceiptBottomSheet_Day_4_en","features.messages.impl.timeline.components.receipt.bottomsheet_ReadReceiptBottomSheet_Night_4_en",19923,], +["features.messages.impl.timeline.components.receipt.bottomsheet_ReadReceiptBottomSheet_Day_5_en","features.messages.impl.timeline.components.receipt.bottomsheet_ReadReceiptBottomSheet_Night_5_en",19923,], +["features.securebackup.impl.setup.views_RecoveryKeyView_Day_0_en","features.securebackup.impl.setup.views_RecoveryKeyView_Night_0_en",19923,], +["features.securebackup.impl.setup.views_RecoveryKeyView_Day_10_en","features.securebackup.impl.setup.views_RecoveryKeyView_Night_10_en",19923,], +["features.securebackup.impl.setup.views_RecoveryKeyView_Day_11_en","features.securebackup.impl.setup.views_RecoveryKeyView_Night_11_en",19923,], +["features.securebackup.impl.setup.views_RecoveryKeyView_Day_1_en","features.securebackup.impl.setup.views_RecoveryKeyView_Night_1_en",19923,], +["features.securebackup.impl.setup.views_RecoveryKeyView_Day_2_en","features.securebackup.impl.setup.views_RecoveryKeyView_Night_2_en",19923,], +["features.securebackup.impl.setup.views_RecoveryKeyView_Day_3_en","features.securebackup.impl.setup.views_RecoveryKeyView_Night_3_en",19923,], +["features.securebackup.impl.setup.views_RecoveryKeyView_Day_4_en","features.securebackup.impl.setup.views_RecoveryKeyView_Night_4_en",19923,], +["features.securebackup.impl.setup.views_RecoveryKeyView_Day_5_en","features.securebackup.impl.setup.views_RecoveryKeyView_Night_5_en",19923,], +["features.securebackup.impl.setup.views_RecoveryKeyView_Day_6_en","features.securebackup.impl.setup.views_RecoveryKeyView_Night_6_en",19923,], +["features.securebackup.impl.setup.views_RecoveryKeyView_Day_7_en","features.securebackup.impl.setup.views_RecoveryKeyView_Night_7_en",19923,], +["features.securebackup.impl.setup.views_RecoveryKeyView_Day_8_en","features.securebackup.impl.setup.views_RecoveryKeyView_Night_8_en",19923,], +["features.securebackup.impl.setup.views_RecoveryKeyView_Day_9_en","features.securebackup.impl.setup.views_RecoveryKeyView_Night_9_en",19923,], ["libraries.designsystem.atomic.atoms_RedIndicatorAtom_Day_0_en","libraries.designsystem.atomic.atoms_RedIndicatorAtom_Night_0_en",0,], ["features.messages.impl.timeline.components_ReplySwipeIndicator_Day_0_en","features.messages.impl.timeline.components_ReplySwipeIndicator_Night_0_en",0,], -["features.messages.impl.report_ReportMessageView_Day_0_en","features.messages.impl.report_ReportMessageView_Night_0_en",19916,], -["features.messages.impl.report_ReportMessageView_Day_1_en","features.messages.impl.report_ReportMessageView_Night_1_en",19916,], -["features.messages.impl.report_ReportMessageView_Day_2_en","features.messages.impl.report_ReportMessageView_Night_2_en",19916,], -["features.messages.impl.report_ReportMessageView_Day_3_en","features.messages.impl.report_ReportMessageView_Night_3_en",19916,], -["features.messages.impl.report_ReportMessageView_Day_4_en","features.messages.impl.report_ReportMessageView_Night_4_en",19916,], -["features.messages.impl.report_ReportMessageView_Day_5_en","features.messages.impl.report_ReportMessageView_Night_5_en",19916,], -["libraries.designsystem.components.dialogs_RetryDialogContent_Dialogs_en","",19916,], -["libraries.designsystem.components.dialogs_RetryDialog_Day_0_en","libraries.designsystem.components.dialogs_RetryDialog_Night_0_en",19916,], -["features.roomdetails.impl.rolesandpermissions_RolesAndPermissionsView_Day_0_en","features.roomdetails.impl.rolesandpermissions_RolesAndPermissionsView_Night_0_en",19916,], -["features.roomdetails.impl.rolesandpermissions_RolesAndPermissionsView_Day_1_en","features.roomdetails.impl.rolesandpermissions_RolesAndPermissionsView_Night_1_en",19916,], -["features.roomdetails.impl.rolesandpermissions_RolesAndPermissionsView_Day_2_en","features.roomdetails.impl.rolesandpermissions_RolesAndPermissionsView_Night_2_en",19916,], -["features.roomdetails.impl.rolesandpermissions_RolesAndPermissionsView_Day_3_en","features.roomdetails.impl.rolesandpermissions_RolesAndPermissionsView_Night_3_en",19916,], -["features.roomdetails.impl.rolesandpermissions_RolesAndPermissionsView_Day_4_en","features.roomdetails.impl.rolesandpermissions_RolesAndPermissionsView_Night_4_en",19916,], -["features.roomdetails.impl.rolesandpermissions_RolesAndPermissionsView_Day_5_en","features.roomdetails.impl.rolesandpermissions_RolesAndPermissionsView_Night_5_en",19916,], -["features.roomdetails.impl.rolesandpermissions_RolesAndPermissionsView_Day_6_en","features.roomdetails.impl.rolesandpermissions_RolesAndPermissionsView_Night_6_en",19916,], -["features.roomdetails.impl.rolesandpermissions_RolesAndPermissionsView_Day_7_en","features.roomdetails.impl.rolesandpermissions_RolesAndPermissionsView_Night_7_en",19916,], +["features.messages.impl.report_ReportMessageView_Day_0_en","features.messages.impl.report_ReportMessageView_Night_0_en",19923,], +["features.messages.impl.report_ReportMessageView_Day_1_en","features.messages.impl.report_ReportMessageView_Night_1_en",19923,], +["features.messages.impl.report_ReportMessageView_Day_2_en","features.messages.impl.report_ReportMessageView_Night_2_en",19923,], +["features.messages.impl.report_ReportMessageView_Day_3_en","features.messages.impl.report_ReportMessageView_Night_3_en",19923,], +["features.messages.impl.report_ReportMessageView_Day_4_en","features.messages.impl.report_ReportMessageView_Night_4_en",19923,], +["features.messages.impl.report_ReportMessageView_Day_5_en","features.messages.impl.report_ReportMessageView_Night_5_en",19923,], +["libraries.designsystem.components.dialogs_RetryDialogContent_Dialogs_en","",19923,], +["libraries.designsystem.components.dialogs_RetryDialog_Day_0_en","libraries.designsystem.components.dialogs_RetryDialog_Night_0_en",19923,], +["features.roomdetails.impl.rolesandpermissions_RolesAndPermissionsView_Day_0_en","features.roomdetails.impl.rolesandpermissions_RolesAndPermissionsView_Night_0_en",19923,], +["features.roomdetails.impl.rolesandpermissions_RolesAndPermissionsView_Day_1_en","features.roomdetails.impl.rolesandpermissions_RolesAndPermissionsView_Night_1_en",19923,], +["features.roomdetails.impl.rolesandpermissions_RolesAndPermissionsView_Day_2_en","features.roomdetails.impl.rolesandpermissions_RolesAndPermissionsView_Night_2_en",19923,], +["features.roomdetails.impl.rolesandpermissions_RolesAndPermissionsView_Day_3_en","features.roomdetails.impl.rolesandpermissions_RolesAndPermissionsView_Night_3_en",19923,], +["features.roomdetails.impl.rolesandpermissions_RolesAndPermissionsView_Day_4_en","features.roomdetails.impl.rolesandpermissions_RolesAndPermissionsView_Night_4_en",19923,], +["features.roomdetails.impl.rolesandpermissions_RolesAndPermissionsView_Day_5_en","features.roomdetails.impl.rolesandpermissions_RolesAndPermissionsView_Night_5_en",19923,], +["features.roomdetails.impl.rolesandpermissions_RolesAndPermissionsView_Day_6_en","features.roomdetails.impl.rolesandpermissions_RolesAndPermissionsView_Night_6_en",19923,], +["features.roomdetails.impl.rolesandpermissions_RolesAndPermissionsView_Day_7_en","features.roomdetails.impl.rolesandpermissions_RolesAndPermissionsView_Night_7_en",19923,], ["features.roomaliasresolver.impl_RoomAliasResolverView_Day_0_en","features.roomaliasresolver.impl_RoomAliasResolverView_Night_0_en",0,], ["features.roomaliasresolver.impl_RoomAliasResolverView_Day_1_en","features.roomaliasresolver.impl_RoomAliasResolverView_Night_1_en",0,], -["features.roomaliasresolver.impl_RoomAliasResolverView_Day_2_en","features.roomaliasresolver.impl_RoomAliasResolverView_Night_2_en",19916,], +["features.roomaliasresolver.impl_RoomAliasResolverView_Day_2_en","features.roomaliasresolver.impl_RoomAliasResolverView_Night_2_en",19923,], ["features.roomdetails.impl.components_RoomBadgeNegative_Day_0_en","features.roomdetails.impl.components_RoomBadgeNegative_Night_0_en",0,], ["features.roomdetails.impl.components_RoomBadgeNeutral_Day_0_en","features.roomdetails.impl.components_RoomBadgeNeutral_Night_0_en",0,], ["features.roomdetails.impl.components_RoomBadgePositive_Day_0_en","features.roomdetails.impl.components_RoomBadgePositive_Night_0_en",0,], -["features.roomdetails.impl_RoomDetailsDark_0_en","",19916,], -["features.roomdetails.impl_RoomDetailsDark_10_en","",19916,], -["features.roomdetails.impl_RoomDetailsDark_11_en","",19916,], -["features.roomdetails.impl_RoomDetailsDark_12_en","",19916,], -["features.roomdetails.impl_RoomDetailsDark_1_en","",19916,], -["features.roomdetails.impl_RoomDetailsDark_2_en","",19916,], -["features.roomdetails.impl_RoomDetailsDark_3_en","",19916,], -["features.roomdetails.impl_RoomDetailsDark_4_en","",19916,], -["features.roomdetails.impl_RoomDetailsDark_5_en","",19916,], -["features.roomdetails.impl_RoomDetailsDark_6_en","",19916,], -["features.roomdetails.impl_RoomDetailsDark_7_en","",19916,], -["features.roomdetails.impl_RoomDetailsDark_8_en","",19916,], -["features.roomdetails.impl_RoomDetailsDark_9_en","",19916,], -["features.roomdetails.impl.edit_RoomDetailsEditView_Day_0_en","features.roomdetails.impl.edit_RoomDetailsEditView_Night_0_en",19916,], -["features.roomdetails.impl.edit_RoomDetailsEditView_Day_1_en","features.roomdetails.impl.edit_RoomDetailsEditView_Night_1_en",19916,], -["features.roomdetails.impl.edit_RoomDetailsEditView_Day_2_en","features.roomdetails.impl.edit_RoomDetailsEditView_Night_2_en",19916,], -["features.roomdetails.impl.edit_RoomDetailsEditView_Day_3_en","features.roomdetails.impl.edit_RoomDetailsEditView_Night_3_en",19916,], -["features.roomdetails.impl.edit_RoomDetailsEditView_Day_4_en","features.roomdetails.impl.edit_RoomDetailsEditView_Night_4_en",19916,], -["features.roomdetails.impl.edit_RoomDetailsEditView_Day_5_en","features.roomdetails.impl.edit_RoomDetailsEditView_Night_5_en",19916,], -["features.roomdetails.impl.edit_RoomDetailsEditView_Day_6_en","features.roomdetails.impl.edit_RoomDetailsEditView_Night_6_en",19916,], -["features.roomdetails.impl.edit_RoomDetailsEditView_Day_7_en","features.roomdetails.impl.edit_RoomDetailsEditView_Night_7_en",19916,], -["features.roomdetails.impl_RoomDetails_0_en","",19916,], -["features.roomdetails.impl_RoomDetails_10_en","",19916,], -["features.roomdetails.impl_RoomDetails_11_en","",19916,], -["features.roomdetails.impl_RoomDetails_12_en","",19916,], -["features.roomdetails.impl_RoomDetails_1_en","",19916,], -["features.roomdetails.impl_RoomDetails_2_en","",19916,], -["features.roomdetails.impl_RoomDetails_3_en","",19916,], -["features.roomdetails.impl_RoomDetails_4_en","",19916,], -["features.roomdetails.impl_RoomDetails_5_en","",19916,], -["features.roomdetails.impl_RoomDetails_6_en","",19916,], -["features.roomdetails.impl_RoomDetails_7_en","",19916,], -["features.roomdetails.impl_RoomDetails_8_en","",19916,], -["features.roomdetails.impl_RoomDetails_9_en","",19916,], -["features.roomdirectory.impl.root_RoomDirectoryView_Day_0_en","features.roomdirectory.impl.root_RoomDirectoryView_Night_0_en",19916,], -["features.roomdirectory.impl.root_RoomDirectoryView_Day_1_en","features.roomdirectory.impl.root_RoomDirectoryView_Night_1_en",19916,], -["features.roomdirectory.impl.root_RoomDirectoryView_Day_2_en","features.roomdirectory.impl.root_RoomDirectoryView_Night_2_en",19916,], -["features.roomdetails.impl.invite_RoomInviteMembersView_Day_0_en","features.roomdetails.impl.invite_RoomInviteMembersView_Night_0_en",19916,], -["features.roomdetails.impl.invite_RoomInviteMembersView_Day_1_en","features.roomdetails.impl.invite_RoomInviteMembersView_Night_1_en",19916,], -["features.roomdetails.impl.invite_RoomInviteMembersView_Day_2_en","features.roomdetails.impl.invite_RoomInviteMembersView_Night_2_en",19916,], -["features.roomdetails.impl.invite_RoomInviteMembersView_Day_3_en","features.roomdetails.impl.invite_RoomInviteMembersView_Night_3_en",19916,], -["features.roomdetails.impl.invite_RoomInviteMembersView_Day_4_en","features.roomdetails.impl.invite_RoomInviteMembersView_Night_4_en",19916,], -["features.roomdetails.impl.invite_RoomInviteMembersView_Day_5_en","features.roomdetails.impl.invite_RoomInviteMembersView_Night_5_en",19916,], -["features.roomdetails.impl.invite_RoomInviteMembersView_Day_6_en","features.roomdetails.impl.invite_RoomInviteMembersView_Night_6_en",19916,], -["features.roomdetails.impl.invite_RoomInviteMembersView_Day_7_en","features.roomdetails.impl.invite_RoomInviteMembersView_Night_7_en",19916,], -["features.roomlist.impl.components_RoomListContentView_Day_0_en","features.roomlist.impl.components_RoomListContentView_Night_0_en",19916,], -["features.roomlist.impl.components_RoomListContentView_Day_1_en","features.roomlist.impl.components_RoomListContentView_Night_1_en",19916,], +["features.roomdetails.impl_RoomDetailsDark_0_en","",19923,], +["features.roomdetails.impl_RoomDetailsDark_10_en","",19923,], +["features.roomdetails.impl_RoomDetailsDark_11_en","",19923,], +["features.roomdetails.impl_RoomDetailsDark_12_en","",19923,], +["features.roomdetails.impl_RoomDetailsDark_1_en","",19923,], +["features.roomdetails.impl_RoomDetailsDark_2_en","",19923,], +["features.roomdetails.impl_RoomDetailsDark_3_en","",19923,], +["features.roomdetails.impl_RoomDetailsDark_4_en","",19923,], +["features.roomdetails.impl_RoomDetailsDark_5_en","",19923,], +["features.roomdetails.impl_RoomDetailsDark_6_en","",19923,], +["features.roomdetails.impl_RoomDetailsDark_7_en","",19923,], +["features.roomdetails.impl_RoomDetailsDark_8_en","",19923,], +["features.roomdetails.impl_RoomDetailsDark_9_en","",19923,], +["features.roomdetails.impl.edit_RoomDetailsEditView_Day_0_en","features.roomdetails.impl.edit_RoomDetailsEditView_Night_0_en",19923,], +["features.roomdetails.impl.edit_RoomDetailsEditView_Day_1_en","features.roomdetails.impl.edit_RoomDetailsEditView_Night_1_en",19923,], +["features.roomdetails.impl.edit_RoomDetailsEditView_Day_2_en","features.roomdetails.impl.edit_RoomDetailsEditView_Night_2_en",19923,], +["features.roomdetails.impl.edit_RoomDetailsEditView_Day_3_en","features.roomdetails.impl.edit_RoomDetailsEditView_Night_3_en",19923,], +["features.roomdetails.impl.edit_RoomDetailsEditView_Day_4_en","features.roomdetails.impl.edit_RoomDetailsEditView_Night_4_en",19923,], +["features.roomdetails.impl.edit_RoomDetailsEditView_Day_5_en","features.roomdetails.impl.edit_RoomDetailsEditView_Night_5_en",19923,], +["features.roomdetails.impl.edit_RoomDetailsEditView_Day_6_en","features.roomdetails.impl.edit_RoomDetailsEditView_Night_6_en",19923,], +["features.roomdetails.impl.edit_RoomDetailsEditView_Day_7_en","features.roomdetails.impl.edit_RoomDetailsEditView_Night_7_en",19923,], +["features.roomdetails.impl_RoomDetails_0_en","",19923,], +["features.roomdetails.impl_RoomDetails_10_en","",19923,], +["features.roomdetails.impl_RoomDetails_11_en","",19923,], +["features.roomdetails.impl_RoomDetails_12_en","",19923,], +["features.roomdetails.impl_RoomDetails_1_en","",19923,], +["features.roomdetails.impl_RoomDetails_2_en","",19923,], +["features.roomdetails.impl_RoomDetails_3_en","",19923,], +["features.roomdetails.impl_RoomDetails_4_en","",19923,], +["features.roomdetails.impl_RoomDetails_5_en","",19923,], +["features.roomdetails.impl_RoomDetails_6_en","",19923,], +["features.roomdetails.impl_RoomDetails_7_en","",19923,], +["features.roomdetails.impl_RoomDetails_8_en","",19923,], +["features.roomdetails.impl_RoomDetails_9_en","",19923,], +["features.roomdirectory.impl.root_RoomDirectoryView_Day_0_en","features.roomdirectory.impl.root_RoomDirectoryView_Night_0_en",19923,], +["features.roomdirectory.impl.root_RoomDirectoryView_Day_1_en","features.roomdirectory.impl.root_RoomDirectoryView_Night_1_en",19923,], +["features.roomdirectory.impl.root_RoomDirectoryView_Day_2_en","features.roomdirectory.impl.root_RoomDirectoryView_Night_2_en",19923,], +["features.roomdetails.impl.invite_RoomInviteMembersView_Day_0_en","features.roomdetails.impl.invite_RoomInviteMembersView_Night_0_en",19923,], +["features.roomdetails.impl.invite_RoomInviteMembersView_Day_1_en","features.roomdetails.impl.invite_RoomInviteMembersView_Night_1_en",19923,], +["features.roomdetails.impl.invite_RoomInviteMembersView_Day_2_en","features.roomdetails.impl.invite_RoomInviteMembersView_Night_2_en",19923,], +["features.roomdetails.impl.invite_RoomInviteMembersView_Day_3_en","features.roomdetails.impl.invite_RoomInviteMembersView_Night_3_en",19923,], +["features.roomdetails.impl.invite_RoomInviteMembersView_Day_4_en","features.roomdetails.impl.invite_RoomInviteMembersView_Night_4_en",19923,], +["features.roomdetails.impl.invite_RoomInviteMembersView_Day_5_en","features.roomdetails.impl.invite_RoomInviteMembersView_Night_5_en",19923,], +["features.roomdetails.impl.invite_RoomInviteMembersView_Day_6_en","features.roomdetails.impl.invite_RoomInviteMembersView_Night_6_en",19923,], +["features.roomdetails.impl.invite_RoomInviteMembersView_Day_7_en","features.roomdetails.impl.invite_RoomInviteMembersView_Night_7_en",19923,], +["features.roomlist.impl.components_RoomListContentView_Day_0_en","features.roomlist.impl.components_RoomListContentView_Night_0_en",19923,], +["features.roomlist.impl.components_RoomListContentView_Day_1_en","features.roomlist.impl.components_RoomListContentView_Night_1_en",19923,], ["features.roomlist.impl.components_RoomListContentView_Day_2_en","features.roomlist.impl.components_RoomListContentView_Night_2_en",0,], -["features.roomlist.impl.components_RoomListContentView_Day_3_en","features.roomlist.impl.components_RoomListContentView_Night_3_en",19916,], -["features.roomlist.impl.components_RoomListContentView_Day_4_en","features.roomlist.impl.components_RoomListContentView_Night_4_en",19916,], -["features.roomlist.impl.filters_RoomListFiltersView_Day_0_en","features.roomlist.impl.filters_RoomListFiltersView_Night_0_en",19916,], -["features.roomlist.impl.filters_RoomListFiltersView_Day_1_en","features.roomlist.impl.filters_RoomListFiltersView_Night_1_en",19916,], -["features.roomlist.impl_RoomListModalBottomSheetContent_Day_0_en","features.roomlist.impl_RoomListModalBottomSheetContent_Night_0_en",19916,], -["features.roomlist.impl_RoomListModalBottomSheetContent_Day_1_en","features.roomlist.impl_RoomListModalBottomSheetContent_Night_1_en",19916,], -["features.roomlist.impl_RoomListModalBottomSheetContent_Day_2_en","features.roomlist.impl_RoomListModalBottomSheetContent_Night_2_en",19916,], +["features.roomlist.impl.components_RoomListContentView_Day_3_en","features.roomlist.impl.components_RoomListContentView_Night_3_en",19923,], +["features.roomlist.impl.components_RoomListContentView_Day_4_en","features.roomlist.impl.components_RoomListContentView_Night_4_en",19923,], +["features.roomlist.impl.filters_RoomListFiltersView_Day_0_en","features.roomlist.impl.filters_RoomListFiltersView_Night_0_en",19923,], +["features.roomlist.impl.filters_RoomListFiltersView_Day_1_en","features.roomlist.impl.filters_RoomListFiltersView_Night_1_en",19923,], +["features.roomlist.impl_RoomListModalBottomSheetContent_Day_0_en","features.roomlist.impl_RoomListModalBottomSheetContent_Night_0_en",19923,], +["features.roomlist.impl_RoomListModalBottomSheetContent_Day_1_en","features.roomlist.impl_RoomListModalBottomSheetContent_Night_1_en",19923,], +["features.roomlist.impl_RoomListModalBottomSheetContent_Day_2_en","features.roomlist.impl_RoomListModalBottomSheetContent_Night_2_en",19923,], ["features.roomlist.impl.search_RoomListSearchContent_Day_0_en","features.roomlist.impl.search_RoomListSearchContent_Night_0_en",0,], -["features.roomlist.impl.search_RoomListSearchContent_Day_1_en","features.roomlist.impl.search_RoomListSearchContent_Night_1_en",19916,], -["features.roomlist.impl.search_RoomListSearchContent_Day_2_en","features.roomlist.impl.search_RoomListSearchContent_Night_2_en",19916,], -["features.roomlist.impl_RoomListView_Day_0_en","features.roomlist.impl_RoomListView_Night_0_en",19916,], +["features.roomlist.impl.search_RoomListSearchContent_Day_1_en","features.roomlist.impl.search_RoomListSearchContent_Night_1_en",19923,], +["features.roomlist.impl.search_RoomListSearchContent_Day_2_en","features.roomlist.impl.search_RoomListSearchContent_Night_2_en",19923,], +["features.roomlist.impl_RoomListView_Day_0_en","features.roomlist.impl_RoomListView_Night_0_en",19923,], ["features.roomlist.impl_RoomListView_Day_10_en","features.roomlist.impl_RoomListView_Night_10_en",0,], -["features.roomlist.impl_RoomListView_Day_1_en","features.roomlist.impl_RoomListView_Night_1_en",19916,], -["features.roomlist.impl_RoomListView_Day_2_en","features.roomlist.impl_RoomListView_Night_2_en",19916,], -["features.roomlist.impl_RoomListView_Day_3_en","features.roomlist.impl_RoomListView_Night_3_en",19916,], -["features.roomlist.impl_RoomListView_Day_4_en","features.roomlist.impl_RoomListView_Night_4_en",19916,], -["features.roomlist.impl_RoomListView_Day_5_en","features.roomlist.impl_RoomListView_Night_5_en",19916,], -["features.roomlist.impl_RoomListView_Day_6_en","features.roomlist.impl_RoomListView_Night_6_en",19916,], -["features.roomlist.impl_RoomListView_Day_7_en","features.roomlist.impl_RoomListView_Night_7_en",19916,], +["features.roomlist.impl_RoomListView_Day_1_en","features.roomlist.impl_RoomListView_Night_1_en",19923,], +["features.roomlist.impl_RoomListView_Day_2_en","features.roomlist.impl_RoomListView_Night_2_en",19923,], +["features.roomlist.impl_RoomListView_Day_3_en","features.roomlist.impl_RoomListView_Night_3_en",19923,], +["features.roomlist.impl_RoomListView_Day_4_en","features.roomlist.impl_RoomListView_Night_4_en",19923,], +["features.roomlist.impl_RoomListView_Day_5_en","features.roomlist.impl_RoomListView_Night_5_en",19923,], +["features.roomlist.impl_RoomListView_Day_6_en","features.roomlist.impl_RoomListView_Night_6_en",19923,], +["features.roomlist.impl_RoomListView_Day_7_en","features.roomlist.impl_RoomListView_Night_7_en",19923,], ["features.roomlist.impl_RoomListView_Day_8_en","features.roomlist.impl_RoomListView_Night_8_en",0,], -["features.roomlist.impl_RoomListView_Day_9_en","features.roomlist.impl_RoomListView_Night_9_en",19916,], -["features.roomdetails.impl.members_RoomMemberListViewBanned_Day_0_en","features.roomdetails.impl.members_RoomMemberListViewBanned_Night_0_en",19916,], -["features.roomdetails.impl.members_RoomMemberListViewBanned_Day_1_en","features.roomdetails.impl.members_RoomMemberListViewBanned_Night_1_en",19916,], -["features.roomdetails.impl.members_RoomMemberListViewBanned_Day_2_en","features.roomdetails.impl.members_RoomMemberListViewBanned_Night_2_en",19916,], -["features.roomdetails.impl.members_RoomMemberListView_Day_0_en","features.roomdetails.impl.members_RoomMemberListView_Night_0_en",19916,], -["features.roomdetails.impl.members_RoomMemberListView_Day_1_en","features.roomdetails.impl.members_RoomMemberListView_Night_1_en",19916,], -["features.roomdetails.impl.members_RoomMemberListView_Day_2_en","features.roomdetails.impl.members_RoomMemberListView_Night_2_en",19916,], -["features.roomdetails.impl.members_RoomMemberListView_Day_3_en","features.roomdetails.impl.members_RoomMemberListView_Night_3_en",19916,], -["features.roomdetails.impl.members_RoomMemberListView_Day_4_en","features.roomdetails.impl.members_RoomMemberListView_Night_4_en",19916,], +["features.roomlist.impl_RoomListView_Day_9_en","features.roomlist.impl_RoomListView_Night_9_en",19923,], +["features.roomdetails.impl.members_RoomMemberListViewBanned_Day_0_en","features.roomdetails.impl.members_RoomMemberListViewBanned_Night_0_en",19923,], +["features.roomdetails.impl.members_RoomMemberListViewBanned_Day_1_en","features.roomdetails.impl.members_RoomMemberListViewBanned_Night_1_en",19923,], +["features.roomdetails.impl.members_RoomMemberListViewBanned_Day_2_en","features.roomdetails.impl.members_RoomMemberListViewBanned_Night_2_en",19923,], +["features.roomdetails.impl.members_RoomMemberListView_Day_0_en","features.roomdetails.impl.members_RoomMemberListView_Night_0_en",19923,], +["features.roomdetails.impl.members_RoomMemberListView_Day_1_en","features.roomdetails.impl.members_RoomMemberListView_Night_1_en",19923,], +["features.roomdetails.impl.members_RoomMemberListView_Day_2_en","features.roomdetails.impl.members_RoomMemberListView_Night_2_en",19923,], +["features.roomdetails.impl.members_RoomMemberListView_Day_3_en","features.roomdetails.impl.members_RoomMemberListView_Night_3_en",19923,], +["features.roomdetails.impl.members_RoomMemberListView_Day_4_en","features.roomdetails.impl.members_RoomMemberListView_Night_4_en",19923,], ["features.roomdetails.impl.members_RoomMemberListView_Day_5_en","features.roomdetails.impl.members_RoomMemberListView_Night_5_en",0,], -["features.roomdetails.impl.members_RoomMemberListView_Day_6_en","features.roomdetails.impl.members_RoomMemberListView_Night_6_en",19916,], -["features.roomdetails.impl.members_RoomMemberListView_Day_7_en","features.roomdetails.impl.members_RoomMemberListView_Night_7_en",19916,], +["features.roomdetails.impl.members_RoomMemberListView_Day_6_en","features.roomdetails.impl.members_RoomMemberListView_Night_6_en",19923,], +["features.roomdetails.impl.members_RoomMemberListView_Day_7_en","features.roomdetails.impl.members_RoomMemberListView_Night_7_en",19923,], +["features.roomdetails.impl.members_RoomMemberListView_Day_8_en","features.roomdetails.impl.members_RoomMemberListView_Night_8_en",19926,], ["libraries.designsystem.atomic.molecules_RoomMembersCountMolecule_Day_0_en","libraries.designsystem.atomic.molecules_RoomMembersCountMolecule_Night_0_en",0,], -["features.roomdetails.impl.members.moderation_RoomMembersModerationView_Day_0_en","features.roomdetails.impl.members.moderation_RoomMembersModerationView_Night_0_en",19916,], -["features.roomdetails.impl.members.moderation_RoomMembersModerationView_Day_1_en","features.roomdetails.impl.members.moderation_RoomMembersModerationView_Night_1_en",19916,], -["features.roomdetails.impl.members.moderation_RoomMembersModerationView_Day_2_en","features.roomdetails.impl.members.moderation_RoomMembersModerationView_Night_2_en",19916,], -["features.roomdetails.impl.members.moderation_RoomMembersModerationView_Day_3_en","features.roomdetails.impl.members.moderation_RoomMembersModerationView_Night_3_en",19916,], -["features.roomdetails.impl.members.moderation_RoomMembersModerationView_Day_4_en","features.roomdetails.impl.members.moderation_RoomMembersModerationView_Night_4_en",19916,], -["features.roomdetails.impl.members.moderation_RoomMembersModerationView_Day_5_en","features.roomdetails.impl.members.moderation_RoomMembersModerationView_Night_5_en",19916,], -["features.roomdetails.impl.members.moderation_RoomMembersModerationView_Day_6_en","features.roomdetails.impl.members.moderation_RoomMembersModerationView_Night_6_en",19916,], -["features.roomdetails.impl.members.moderation_RoomMembersModerationView_Day_7_en","features.roomdetails.impl.members.moderation_RoomMembersModerationView_Night_7_en",19916,], -["features.roomdetails.impl.members.moderation_RoomMembersModerationView_Day_8_en","features.roomdetails.impl.members.moderation_RoomMembersModerationView_Night_8_en",19916,], +["features.roomdetails.impl.members.moderation_RoomMembersModerationView_Day_0_en","features.roomdetails.impl.members.moderation_RoomMembersModerationView_Night_0_en",19923,], +["features.roomdetails.impl.members.moderation_RoomMembersModerationView_Day_1_en","features.roomdetails.impl.members.moderation_RoomMembersModerationView_Night_1_en",19923,], +["features.roomdetails.impl.members.moderation_RoomMembersModerationView_Day_2_en","features.roomdetails.impl.members.moderation_RoomMembersModerationView_Night_2_en",19923,], +["features.roomdetails.impl.members.moderation_RoomMembersModerationView_Day_3_en","features.roomdetails.impl.members.moderation_RoomMembersModerationView_Night_3_en",19923,], +["features.roomdetails.impl.members.moderation_RoomMembersModerationView_Day_4_en","features.roomdetails.impl.members.moderation_RoomMembersModerationView_Night_4_en",19923,], +["features.roomdetails.impl.members.moderation_RoomMembersModerationView_Day_5_en","features.roomdetails.impl.members.moderation_RoomMembersModerationView_Night_5_en",19923,], +["features.roomdetails.impl.members.moderation_RoomMembersModerationView_Day_6_en","features.roomdetails.impl.members.moderation_RoomMembersModerationView_Night_6_en",19923,], +["features.roomdetails.impl.members.moderation_RoomMembersModerationView_Day_7_en","features.roomdetails.impl.members.moderation_RoomMembersModerationView_Night_7_en",19923,], +["features.roomdetails.impl.members.moderation_RoomMembersModerationView_Day_8_en","features.roomdetails.impl.members.moderation_RoomMembersModerationView_Night_8_en",19923,], ["features.roomdetails.impl.members.moderation_RoomMembersModerationView_Day_9_en","features.roomdetails.impl.members.moderation_RoomMembersModerationView_Night_9_en",0,], -["features.roomdetails.impl.notificationsettings_RoomNotificationSettingsOption_Day_0_en","features.roomdetails.impl.notificationsettings_RoomNotificationSettingsOption_Night_0_en",19916,], -["features.roomdetails.impl.notificationsettings_RoomNotificationSettingsView_Day_0_en","features.roomdetails.impl.notificationsettings_RoomNotificationSettingsView_Night_0_en",19916,], -["features.roomdetails.impl.notificationsettings_RoomNotificationSettingsView_Day_1_en","features.roomdetails.impl.notificationsettings_RoomNotificationSettingsView_Night_1_en",19916,], -["features.roomdetails.impl.notificationsettings_RoomNotificationSettingsView_Day_2_en","features.roomdetails.impl.notificationsettings_RoomNotificationSettingsView_Night_2_en",19916,], -["features.roomdetails.impl.notificationsettings_RoomNotificationSettingsView_Day_3_en","features.roomdetails.impl.notificationsettings_RoomNotificationSettingsView_Night_3_en",19916,], -["features.roomdetails.impl.notificationsettings_RoomNotificationSettingsView_Day_4_en","features.roomdetails.impl.notificationsettings_RoomNotificationSettingsView_Night_4_en",19916,], -["features.roomdetails.impl.notificationsettings_RoomNotificationSettingsView_Day_5_en","features.roomdetails.impl.notificationsettings_RoomNotificationSettingsView_Night_5_en",19916,], -["features.roomdetails.impl.notificationsettings_RoomNotificationSettingsView_Day_6_en","features.roomdetails.impl.notificationsettings_RoomNotificationSettingsView_Night_6_en",19916,], -["features.createroom.impl.components_RoomPrivacyOption_Day_0_en","features.createroom.impl.components_RoomPrivacyOption_Night_0_en",19916,], -["libraries.roomselect.impl_RoomSelectView_Day_0_en","libraries.roomselect.impl_RoomSelectView_Night_0_en",19916,], -["libraries.roomselect.impl_RoomSelectView_Day_1_en","libraries.roomselect.impl_RoomSelectView_Night_1_en",19916,], -["libraries.roomselect.impl_RoomSelectView_Day_2_en","libraries.roomselect.impl_RoomSelectView_Night_2_en",19916,], -["libraries.roomselect.impl_RoomSelectView_Day_3_en","libraries.roomselect.impl_RoomSelectView_Night_3_en",19916,], -["libraries.roomselect.impl_RoomSelectView_Day_4_en","libraries.roomselect.impl_RoomSelectView_Night_4_en",19916,], -["libraries.roomselect.impl_RoomSelectView_Day_5_en","libraries.roomselect.impl_RoomSelectView_Night_5_en",19916,], +["features.roomdetails.impl.notificationsettings_RoomNotificationSettingsOption_Day_0_en","features.roomdetails.impl.notificationsettings_RoomNotificationSettingsOption_Night_0_en",19923,], +["features.roomdetails.impl.notificationsettings_RoomNotificationSettingsView_Day_0_en","features.roomdetails.impl.notificationsettings_RoomNotificationSettingsView_Night_0_en",19923,], +["features.roomdetails.impl.notificationsettings_RoomNotificationSettingsView_Day_1_en","features.roomdetails.impl.notificationsettings_RoomNotificationSettingsView_Night_1_en",19923,], +["features.roomdetails.impl.notificationsettings_RoomNotificationSettingsView_Day_2_en","features.roomdetails.impl.notificationsettings_RoomNotificationSettingsView_Night_2_en",19923,], +["features.roomdetails.impl.notificationsettings_RoomNotificationSettingsView_Day_3_en","features.roomdetails.impl.notificationsettings_RoomNotificationSettingsView_Night_3_en",19923,], +["features.roomdetails.impl.notificationsettings_RoomNotificationSettingsView_Day_4_en","features.roomdetails.impl.notificationsettings_RoomNotificationSettingsView_Night_4_en",19923,], +["features.roomdetails.impl.notificationsettings_RoomNotificationSettingsView_Day_5_en","features.roomdetails.impl.notificationsettings_RoomNotificationSettingsView_Night_5_en",19923,], +["features.roomdetails.impl.notificationsettings_RoomNotificationSettingsView_Day_6_en","features.roomdetails.impl.notificationsettings_RoomNotificationSettingsView_Night_6_en",19923,], +["features.createroom.impl.components_RoomPrivacyOption_Day_0_en","features.createroom.impl.components_RoomPrivacyOption_Night_0_en",19923,], +["libraries.roomselect.impl_RoomSelectView_Day_0_en","libraries.roomselect.impl_RoomSelectView_Night_0_en",19923,], +["libraries.roomselect.impl_RoomSelectView_Day_1_en","libraries.roomselect.impl_RoomSelectView_Night_1_en",19923,], +["libraries.roomselect.impl_RoomSelectView_Day_2_en","libraries.roomselect.impl_RoomSelectView_Night_2_en",19923,], +["libraries.roomselect.impl_RoomSelectView_Day_3_en","libraries.roomselect.impl_RoomSelectView_Night_3_en",19923,], +["libraries.roomselect.impl_RoomSelectView_Day_4_en","libraries.roomselect.impl_RoomSelectView_Night_4_en",19923,], +["libraries.roomselect.impl_RoomSelectView_Day_5_en","libraries.roomselect.impl_RoomSelectView_Night_5_en",19923,], ["features.roomlist.impl.components_RoomSummaryPlaceholderRow_Day_0_en","features.roomlist.impl.components_RoomSummaryPlaceholderRow_Night_0_en",0,], ["features.roomlist.impl.components_RoomSummaryRow_Day_0_en","features.roomlist.impl.components_RoomSummaryRow_Night_0_en",0,], ["features.roomlist.impl.components_RoomSummaryRow_Day_10_en","features.roomlist.impl.components_RoomSummaryRow_Night_10_en",0,], @@ -756,10 +764,10 @@ export const screenshots = [ ["features.roomlist.impl.components_RoomSummaryRow_Day_26_en","features.roomlist.impl.components_RoomSummaryRow_Night_26_en",0,], ["features.roomlist.impl.components_RoomSummaryRow_Day_27_en","features.roomlist.impl.components_RoomSummaryRow_Night_27_en",0,], ["features.roomlist.impl.components_RoomSummaryRow_Day_28_en","features.roomlist.impl.components_RoomSummaryRow_Night_28_en",0,], -["features.roomlist.impl.components_RoomSummaryRow_Day_29_en","features.roomlist.impl.components_RoomSummaryRow_Night_29_en",19916,], -["features.roomlist.impl.components_RoomSummaryRow_Day_2_en","features.roomlist.impl.components_RoomSummaryRow_Night_2_en",19916,], -["features.roomlist.impl.components_RoomSummaryRow_Day_30_en","features.roomlist.impl.components_RoomSummaryRow_Night_30_en",19916,], -["features.roomlist.impl.components_RoomSummaryRow_Day_31_en","features.roomlist.impl.components_RoomSummaryRow_Night_31_en",19916,], +["features.roomlist.impl.components_RoomSummaryRow_Day_29_en","features.roomlist.impl.components_RoomSummaryRow_Night_29_en",19923,], +["features.roomlist.impl.components_RoomSummaryRow_Day_2_en","features.roomlist.impl.components_RoomSummaryRow_Night_2_en",19923,], +["features.roomlist.impl.components_RoomSummaryRow_Day_30_en","features.roomlist.impl.components_RoomSummaryRow_Night_30_en",19923,], +["features.roomlist.impl.components_RoomSummaryRow_Day_31_en","features.roomlist.impl.components_RoomSummaryRow_Night_31_en",19923,], ["features.roomlist.impl.components_RoomSummaryRow_Day_3_en","features.roomlist.impl.components_RoomSummaryRow_Night_3_en",0,], ["features.roomlist.impl.components_RoomSummaryRow_Day_4_en","features.roomlist.impl.components_RoomSummaryRow_Night_4_en",0,], ["features.roomlist.impl.components_RoomSummaryRow_Day_5_en","features.roomlist.impl.components_RoomSummaryRow_Night_5_en",0,], @@ -767,64 +775,64 @@ export const screenshots = [ ["features.roomlist.impl.components_RoomSummaryRow_Day_7_en","features.roomlist.impl.components_RoomSummaryRow_Night_7_en",0,], ["features.roomlist.impl.components_RoomSummaryRow_Day_8_en","features.roomlist.impl.components_RoomSummaryRow_Night_8_en",0,], ["features.roomlist.impl.components_RoomSummaryRow_Day_9_en","features.roomlist.impl.components_RoomSummaryRow_Night_9_en",0,], -["appnav.root_RootView_Day_0_en","appnav.root_RootView_Night_0_en",19916,], -["appnav.root_RootView_Day_1_en","appnav.root_RootView_Night_1_en",19916,], -["appnav.root_RootView_Day_2_en","appnav.root_RootView_Night_2_en",19916,], +["appnav.root_RootView_Day_0_en","appnav.root_RootView_Night_0_en",19923,], +["appnav.root_RootView_Day_1_en","appnav.root_RootView_Night_1_en",19923,], +["appnav.root_RootView_Day_2_en","appnav.root_RootView_Night_2_en",19923,], ["appicon.enterprise_RoundIcon_en","",0,], ["appicon.element_RoundIcon_en","",0,], ["libraries.designsystem.atomic.atoms_RoundedIconAtom_Day_0_en","libraries.designsystem.atomic.atoms_RoundedIconAtom_Night_0_en",0,], -["features.verifysession.impl.emoji_SasEmojis_Day_0_en","features.verifysession.impl.emoji_SasEmojis_Night_0_en",19916,], -["features.login.impl.screens.searchaccountprovider_SearchAccountProviderView_Day_0_en","features.login.impl.screens.searchaccountprovider_SearchAccountProviderView_Night_0_en",19916,], -["features.login.impl.screens.searchaccountprovider_SearchAccountProviderView_Day_1_en","features.login.impl.screens.searchaccountprovider_SearchAccountProviderView_Night_1_en",19916,], +["features.verifysession.impl.emoji_SasEmojis_Day_0_en","features.verifysession.impl.emoji_SasEmojis_Night_0_en",19923,], +["features.login.impl.screens.searchaccountprovider_SearchAccountProviderView_Day_0_en","features.login.impl.screens.searchaccountprovider_SearchAccountProviderView_Night_0_en",19923,], +["features.login.impl.screens.searchaccountprovider_SearchAccountProviderView_Day_1_en","features.login.impl.screens.searchaccountprovider_SearchAccountProviderView_Night_1_en",19923,], ["libraries.designsystem.theme.components_SearchBarActiveNoneQuery_Search views_en","",0,], ["libraries.designsystem.theme.components_SearchBarActiveWithContent_Search views_en","",0,], -["libraries.designsystem.theme.components_SearchBarActiveWithNoResults_Search views_en","",19916,], +["libraries.designsystem.theme.components_SearchBarActiveWithNoResults_Search views_en","",19923,], ["libraries.designsystem.theme.components_SearchBarActiveWithQueryNoBackButton_Search views_en","",0,], ["libraries.designsystem.theme.components_SearchBarActiveWithQuery_Search views_en","",0,], ["libraries.designsystem.theme.components_SearchBarInactive_Search views_en","",0,], -["features.createroom.impl.components_SearchMultipleUsersResultItem_en","",19916,], -["features.createroom.impl.components_SearchSingleUserResultItem_en","",19916,], -["features.securebackup.impl.disable_SecureBackupDisableView_Day_0_en","features.securebackup.impl.disable_SecureBackupDisableView_Night_0_en",19916,], -["features.securebackup.impl.disable_SecureBackupDisableView_Day_1_en","features.securebackup.impl.disable_SecureBackupDisableView_Night_1_en",19916,], -["features.securebackup.impl.disable_SecureBackupDisableView_Day_2_en","features.securebackup.impl.disable_SecureBackupDisableView_Night_2_en",19916,], -["features.securebackup.impl.disable_SecureBackupDisableView_Day_3_en","features.securebackup.impl.disable_SecureBackupDisableView_Night_3_en",19916,], -["features.securebackup.impl.enable_SecureBackupEnableView_Day_0_en","features.securebackup.impl.enable_SecureBackupEnableView_Night_0_en",19916,], -["features.securebackup.impl.enable_SecureBackupEnableView_Day_1_en","features.securebackup.impl.enable_SecureBackupEnableView_Night_1_en",19916,], -["features.securebackup.impl.enable_SecureBackupEnableView_Day_2_en","features.securebackup.impl.enable_SecureBackupEnableView_Night_2_en",19916,], -["features.securebackup.impl.enter_SecureBackupEnterRecoveryKeyView_Day_0_en","features.securebackup.impl.enter_SecureBackupEnterRecoveryKeyView_Night_0_en",19916,], -["features.securebackup.impl.enter_SecureBackupEnterRecoveryKeyView_Day_1_en","features.securebackup.impl.enter_SecureBackupEnterRecoveryKeyView_Night_1_en",19916,], -["features.securebackup.impl.enter_SecureBackupEnterRecoveryKeyView_Day_2_en","features.securebackup.impl.enter_SecureBackupEnterRecoveryKeyView_Night_2_en",19916,], -["features.securebackup.impl.enter_SecureBackupEnterRecoveryKeyView_Day_3_en","features.securebackup.impl.enter_SecureBackupEnterRecoveryKeyView_Night_3_en",19916,], -["features.securebackup.impl.root_SecureBackupRootView_Day_0_en","features.securebackup.impl.root_SecureBackupRootView_Night_0_en",19916,], -["features.securebackup.impl.root_SecureBackupRootView_Day_1_en","features.securebackup.impl.root_SecureBackupRootView_Night_1_en",19916,], -["features.securebackup.impl.root_SecureBackupRootView_Day_2_en","features.securebackup.impl.root_SecureBackupRootView_Night_2_en",19916,], -["features.securebackup.impl.root_SecureBackupRootView_Day_3_en","features.securebackup.impl.root_SecureBackupRootView_Night_3_en",19916,], -["features.securebackup.impl.root_SecureBackupRootView_Day_4_en","features.securebackup.impl.root_SecureBackupRootView_Night_4_en",19916,], -["features.securebackup.impl.root_SecureBackupRootView_Day_5_en","features.securebackup.impl.root_SecureBackupRootView_Night_5_en",19916,], -["features.securebackup.impl.root_SecureBackupRootView_Day_6_en","features.securebackup.impl.root_SecureBackupRootView_Night_6_en",19916,], -["features.securebackup.impl.root_SecureBackupRootView_Day_7_en","features.securebackup.impl.root_SecureBackupRootView_Night_7_en",19916,], -["features.securebackup.impl.root_SecureBackupRootView_Day_8_en","features.securebackup.impl.root_SecureBackupRootView_Night_8_en",19916,], -["features.securebackup.impl.setup_SecureBackupSetupViewChange_Day_0_en","features.securebackup.impl.setup_SecureBackupSetupViewChange_Night_0_en",19916,], -["features.securebackup.impl.setup_SecureBackupSetupViewChange_Day_1_en","features.securebackup.impl.setup_SecureBackupSetupViewChange_Night_1_en",19916,], -["features.securebackup.impl.setup_SecureBackupSetupViewChange_Day_2_en","features.securebackup.impl.setup_SecureBackupSetupViewChange_Night_2_en",19916,], -["features.securebackup.impl.setup_SecureBackupSetupViewChange_Day_3_en","features.securebackup.impl.setup_SecureBackupSetupViewChange_Night_3_en",19916,], -["features.securebackup.impl.setup_SecureBackupSetupViewChange_Day_4_en","features.securebackup.impl.setup_SecureBackupSetupViewChange_Night_4_en",19916,], -["features.securebackup.impl.setup_SecureBackupSetupView_Day_0_en","features.securebackup.impl.setup_SecureBackupSetupView_Night_0_en",19916,], -["features.securebackup.impl.setup_SecureBackupSetupView_Day_1_en","features.securebackup.impl.setup_SecureBackupSetupView_Night_1_en",19916,], -["features.securebackup.impl.setup_SecureBackupSetupView_Day_2_en","features.securebackup.impl.setup_SecureBackupSetupView_Night_2_en",19916,], -["features.securebackup.impl.setup_SecureBackupSetupView_Day_3_en","features.securebackup.impl.setup_SecureBackupSetupView_Night_3_en",19916,], -["features.securebackup.impl.setup_SecureBackupSetupView_Day_4_en","features.securebackup.impl.setup_SecureBackupSetupView_Night_4_en",19916,], +["features.createroom.impl.components_SearchMultipleUsersResultItem_en","",19923,], +["features.createroom.impl.components_SearchSingleUserResultItem_en","",19923,], +["features.securebackup.impl.disable_SecureBackupDisableView_Day_0_en","features.securebackup.impl.disable_SecureBackupDisableView_Night_0_en",19923,], +["features.securebackup.impl.disable_SecureBackupDisableView_Day_1_en","features.securebackup.impl.disable_SecureBackupDisableView_Night_1_en",19923,], +["features.securebackup.impl.disable_SecureBackupDisableView_Day_2_en","features.securebackup.impl.disable_SecureBackupDisableView_Night_2_en",19923,], +["features.securebackup.impl.disable_SecureBackupDisableView_Day_3_en","features.securebackup.impl.disable_SecureBackupDisableView_Night_3_en",19923,], +["features.securebackup.impl.enable_SecureBackupEnableView_Day_0_en","features.securebackup.impl.enable_SecureBackupEnableView_Night_0_en",19923,], +["features.securebackup.impl.enable_SecureBackupEnableView_Day_1_en","features.securebackup.impl.enable_SecureBackupEnableView_Night_1_en",19923,], +["features.securebackup.impl.enable_SecureBackupEnableView_Day_2_en","features.securebackup.impl.enable_SecureBackupEnableView_Night_2_en",19923,], +["features.securebackup.impl.enter_SecureBackupEnterRecoveryKeyView_Day_0_en","features.securebackup.impl.enter_SecureBackupEnterRecoveryKeyView_Night_0_en",19923,], +["features.securebackup.impl.enter_SecureBackupEnterRecoveryKeyView_Day_1_en","features.securebackup.impl.enter_SecureBackupEnterRecoveryKeyView_Night_1_en",19923,], +["features.securebackup.impl.enter_SecureBackupEnterRecoveryKeyView_Day_2_en","features.securebackup.impl.enter_SecureBackupEnterRecoveryKeyView_Night_2_en",19923,], +["features.securebackup.impl.enter_SecureBackupEnterRecoveryKeyView_Day_3_en","features.securebackup.impl.enter_SecureBackupEnterRecoveryKeyView_Night_3_en",19923,], +["features.securebackup.impl.root_SecureBackupRootView_Day_0_en","features.securebackup.impl.root_SecureBackupRootView_Night_0_en",19923,], +["features.securebackup.impl.root_SecureBackupRootView_Day_1_en","features.securebackup.impl.root_SecureBackupRootView_Night_1_en",19923,], +["features.securebackup.impl.root_SecureBackupRootView_Day_2_en","features.securebackup.impl.root_SecureBackupRootView_Night_2_en",19923,], +["features.securebackup.impl.root_SecureBackupRootView_Day_3_en","features.securebackup.impl.root_SecureBackupRootView_Night_3_en",19923,], +["features.securebackup.impl.root_SecureBackupRootView_Day_4_en","features.securebackup.impl.root_SecureBackupRootView_Night_4_en",19923,], +["features.securebackup.impl.root_SecureBackupRootView_Day_5_en","features.securebackup.impl.root_SecureBackupRootView_Night_5_en",19923,], +["features.securebackup.impl.root_SecureBackupRootView_Day_6_en","features.securebackup.impl.root_SecureBackupRootView_Night_6_en",19923,], +["features.securebackup.impl.root_SecureBackupRootView_Day_7_en","features.securebackup.impl.root_SecureBackupRootView_Night_7_en",19923,], +["features.securebackup.impl.root_SecureBackupRootView_Day_8_en","features.securebackup.impl.root_SecureBackupRootView_Night_8_en",19923,], +["features.securebackup.impl.setup_SecureBackupSetupViewChange_Day_0_en","features.securebackup.impl.setup_SecureBackupSetupViewChange_Night_0_en",19923,], +["features.securebackup.impl.setup_SecureBackupSetupViewChange_Day_1_en","features.securebackup.impl.setup_SecureBackupSetupViewChange_Night_1_en",19923,], +["features.securebackup.impl.setup_SecureBackupSetupViewChange_Day_2_en","features.securebackup.impl.setup_SecureBackupSetupViewChange_Night_2_en",19923,], +["features.securebackup.impl.setup_SecureBackupSetupViewChange_Day_3_en","features.securebackup.impl.setup_SecureBackupSetupViewChange_Night_3_en",19923,], +["features.securebackup.impl.setup_SecureBackupSetupViewChange_Day_4_en","features.securebackup.impl.setup_SecureBackupSetupViewChange_Night_4_en",19923,], +["features.securebackup.impl.setup_SecureBackupSetupView_Day_0_en","features.securebackup.impl.setup_SecureBackupSetupView_Night_0_en",19923,], +["features.securebackup.impl.setup_SecureBackupSetupView_Day_1_en","features.securebackup.impl.setup_SecureBackupSetupView_Night_1_en",19923,], +["features.securebackup.impl.setup_SecureBackupSetupView_Day_2_en","features.securebackup.impl.setup_SecureBackupSetupView_Night_2_en",19923,], +["features.securebackup.impl.setup_SecureBackupSetupView_Day_3_en","features.securebackup.impl.setup_SecureBackupSetupView_Night_3_en",19923,], +["features.securebackup.impl.setup_SecureBackupSetupView_Day_4_en","features.securebackup.impl.setup_SecureBackupSetupView_Night_4_en",19923,], ["libraries.matrix.ui.components_SelectedRoom_Day_0_en","libraries.matrix.ui.components_SelectedRoom_Night_0_en",0,], ["libraries.matrix.ui.components_SelectedRoom_Day_1_en","libraries.matrix.ui.components_SelectedRoom_Night_1_en",0,], ["libraries.matrix.ui.components_SelectedUserCannotRemove_Day_0_en","libraries.matrix.ui.components_SelectedUserCannotRemove_Night_0_en",0,], ["libraries.matrix.ui.components_SelectedUser_Day_0_en","libraries.matrix.ui.components_SelectedUser_Night_0_en",0,], ["libraries.matrix.ui.components_SelectedUsersRowList_Day_0_en","libraries.matrix.ui.components_SelectedUsersRowList_Night_0_en",0,], ["libraries.textcomposer.components_SendButton_Day_0_en","libraries.textcomposer.components_SendButton_Night_0_en",0,], -["features.location.impl.send_SendLocationView_Day_0_en","features.location.impl.send_SendLocationView_Night_0_en",19916,], -["features.location.impl.send_SendLocationView_Day_1_en","features.location.impl.send_SendLocationView_Night_1_en",19916,], -["features.location.impl.send_SendLocationView_Day_2_en","features.location.impl.send_SendLocationView_Night_2_en",19916,], -["features.location.impl.send_SendLocationView_Day_3_en","features.location.impl.send_SendLocationView_Night_3_en",19916,], -["features.location.impl.send_SendLocationView_Day_4_en","features.location.impl.send_SendLocationView_Night_4_en",19916,], +["features.location.impl.send_SendLocationView_Day_0_en","features.location.impl.send_SendLocationView_Night_0_en",19923,], +["features.location.impl.send_SendLocationView_Day_1_en","features.location.impl.send_SendLocationView_Night_1_en",19923,], +["features.location.impl.send_SendLocationView_Day_2_en","features.location.impl.send_SendLocationView_Night_2_en",19923,], +["features.location.impl.send_SendLocationView_Day_3_en","features.location.impl.send_SendLocationView_Night_3_en",19923,], +["features.location.impl.send_SendLocationView_Day_4_en","features.location.impl.send_SendLocationView_Night_4_en",19923,], ["libraries.matrix.ui.messages.sender_SenderName_Day_0_en","libraries.matrix.ui.messages.sender_SenderName_Night_0_en",0,], ["libraries.matrix.ui.messages.sender_SenderName_Day_1_en","libraries.matrix.ui.messages.sender_SenderName_Night_1_en",0,], ["libraries.matrix.ui.messages.sender_SenderName_Day_2_en","libraries.matrix.ui.messages.sender_SenderName_Night_2_en",0,], @@ -834,37 +842,37 @@ export const screenshots = [ ["libraries.matrix.ui.messages.sender_SenderName_Day_6_en","libraries.matrix.ui.messages.sender_SenderName_Night_6_en",0,], ["libraries.matrix.ui.messages.sender_SenderName_Day_7_en","libraries.matrix.ui.messages.sender_SenderName_Night_7_en",0,], ["libraries.matrix.ui.messages.sender_SenderName_Day_8_en","libraries.matrix.ui.messages.sender_SenderName_Night_8_en",0,], -["features.lockscreen.impl.setup.biometric_SetupBiometricView_Day_0_en","features.lockscreen.impl.setup.biometric_SetupBiometricView_Night_0_en",19916,], -["features.lockscreen.impl.setup.pin_SetupPinView_Day_0_en","features.lockscreen.impl.setup.pin_SetupPinView_Night_0_en",19916,], -["features.lockscreen.impl.setup.pin_SetupPinView_Day_1_en","features.lockscreen.impl.setup.pin_SetupPinView_Night_1_en",19916,], -["features.lockscreen.impl.setup.pin_SetupPinView_Day_2_en","features.lockscreen.impl.setup.pin_SetupPinView_Night_2_en",19916,], -["features.lockscreen.impl.setup.pin_SetupPinView_Day_3_en","features.lockscreen.impl.setup.pin_SetupPinView_Night_3_en",19916,], -["features.lockscreen.impl.setup.pin_SetupPinView_Day_4_en","features.lockscreen.impl.setup.pin_SetupPinView_Night_4_en",19916,], +["features.lockscreen.impl.setup.biometric_SetupBiometricView_Day_0_en","features.lockscreen.impl.setup.biometric_SetupBiometricView_Night_0_en",19923,], +["features.lockscreen.impl.setup.pin_SetupPinView_Day_0_en","features.lockscreen.impl.setup.pin_SetupPinView_Night_0_en",19923,], +["features.lockscreen.impl.setup.pin_SetupPinView_Day_1_en","features.lockscreen.impl.setup.pin_SetupPinView_Night_1_en",19923,], +["features.lockscreen.impl.setup.pin_SetupPinView_Day_2_en","features.lockscreen.impl.setup.pin_SetupPinView_Night_2_en",19923,], +["features.lockscreen.impl.setup.pin_SetupPinView_Day_3_en","features.lockscreen.impl.setup.pin_SetupPinView_Night_3_en",19923,], +["features.lockscreen.impl.setup.pin_SetupPinView_Day_4_en","features.lockscreen.impl.setup.pin_SetupPinView_Night_4_en",19923,], ["features.share.impl_ShareView_Day_0_en","features.share.impl_ShareView_Night_0_en",0,], ["features.share.impl_ShareView_Day_1_en","features.share.impl_ShareView_Night_1_en",0,], ["features.share.impl_ShareView_Day_2_en","features.share.impl_ShareView_Night_2_en",0,], -["features.share.impl_ShareView_Day_3_en","features.share.impl_ShareView_Night_3_en",19916,], +["features.share.impl_ShareView_Day_3_en","features.share.impl_ShareView_Night_3_en",19923,], ["features.messages.impl.actionlist_SheetContent_Day_0_en","features.messages.impl.actionlist_SheetContent_Night_0_en",0,], ["features.messages.impl.timeline.components.reactionsummary_SheetContent_Day_0_en","features.messages.impl.timeline.components.reactionsummary_SheetContent_Night_0_en",0,], -["features.messages.impl.actionlist_SheetContent_Day_10_en","features.messages.impl.actionlist_SheetContent_Night_10_en",19916,], +["features.messages.impl.actionlist_SheetContent_Day_10_en","features.messages.impl.actionlist_SheetContent_Night_10_en",19923,], ["features.messages.impl.actionlist_SheetContent_Day_1_en","features.messages.impl.actionlist_SheetContent_Night_1_en",0,], -["features.messages.impl.actionlist_SheetContent_Day_2_en","features.messages.impl.actionlist_SheetContent_Night_2_en",19916,], -["features.messages.impl.actionlist_SheetContent_Day_3_en","features.messages.impl.actionlist_SheetContent_Night_3_en",19916,], -["features.messages.impl.actionlist_SheetContent_Day_4_en","features.messages.impl.actionlist_SheetContent_Night_4_en",19916,], -["features.messages.impl.actionlist_SheetContent_Day_5_en","features.messages.impl.actionlist_SheetContent_Night_5_en",19916,], -["features.messages.impl.actionlist_SheetContent_Day_6_en","features.messages.impl.actionlist_SheetContent_Night_6_en",19916,], -["features.messages.impl.actionlist_SheetContent_Day_7_en","features.messages.impl.actionlist_SheetContent_Night_7_en",19916,], -["features.messages.impl.actionlist_SheetContent_Day_8_en","features.messages.impl.actionlist_SheetContent_Night_8_en",19916,], -["features.messages.impl.actionlist_SheetContent_Day_9_en","features.messages.impl.actionlist_SheetContent_Night_9_en",19916,], -["features.location.impl.show_ShowLocationView_Day_0_en","features.location.impl.show_ShowLocationView_Night_0_en",19916,], -["features.location.impl.show_ShowLocationView_Day_1_en","features.location.impl.show_ShowLocationView_Night_1_en",19916,], -["features.location.impl.show_ShowLocationView_Day_2_en","features.location.impl.show_ShowLocationView_Night_2_en",19916,], -["features.location.impl.show_ShowLocationView_Day_3_en","features.location.impl.show_ShowLocationView_Night_3_en",19916,], -["features.location.impl.show_ShowLocationView_Day_4_en","features.location.impl.show_ShowLocationView_Night_4_en",19916,], -["features.location.impl.show_ShowLocationView_Day_5_en","features.location.impl.show_ShowLocationView_Night_5_en",19916,], -["features.location.impl.show_ShowLocationView_Day_6_en","features.location.impl.show_ShowLocationView_Night_6_en",19916,], -["features.location.impl.show_ShowLocationView_Day_7_en","features.location.impl.show_ShowLocationView_Night_7_en",19916,], -["features.signedout.impl_SignedOutView_Day_0_en","features.signedout.impl_SignedOutView_Night_0_en",19916,], +["features.messages.impl.actionlist_SheetContent_Day_2_en","features.messages.impl.actionlist_SheetContent_Night_2_en",19923,], +["features.messages.impl.actionlist_SheetContent_Day_3_en","features.messages.impl.actionlist_SheetContent_Night_3_en",19923,], +["features.messages.impl.actionlist_SheetContent_Day_4_en","features.messages.impl.actionlist_SheetContent_Night_4_en",19923,], +["features.messages.impl.actionlist_SheetContent_Day_5_en","features.messages.impl.actionlist_SheetContent_Night_5_en",19923,], +["features.messages.impl.actionlist_SheetContent_Day_6_en","features.messages.impl.actionlist_SheetContent_Night_6_en",19923,], +["features.messages.impl.actionlist_SheetContent_Day_7_en","features.messages.impl.actionlist_SheetContent_Night_7_en",19923,], +["features.messages.impl.actionlist_SheetContent_Day_8_en","features.messages.impl.actionlist_SheetContent_Night_8_en",19923,], +["features.messages.impl.actionlist_SheetContent_Day_9_en","features.messages.impl.actionlist_SheetContent_Night_9_en",19923,], +["features.location.impl.show_ShowLocationView_Day_0_en","features.location.impl.show_ShowLocationView_Night_0_en",19923,], +["features.location.impl.show_ShowLocationView_Day_1_en","features.location.impl.show_ShowLocationView_Night_1_en",19923,], +["features.location.impl.show_ShowLocationView_Day_2_en","features.location.impl.show_ShowLocationView_Night_2_en",19923,], +["features.location.impl.show_ShowLocationView_Day_3_en","features.location.impl.show_ShowLocationView_Night_3_en",19923,], +["features.location.impl.show_ShowLocationView_Day_4_en","features.location.impl.show_ShowLocationView_Night_4_en",19923,], +["features.location.impl.show_ShowLocationView_Day_5_en","features.location.impl.show_ShowLocationView_Night_5_en",19923,], +["features.location.impl.show_ShowLocationView_Day_6_en","features.location.impl.show_ShowLocationView_Night_6_en",19923,], +["features.location.impl.show_ShowLocationView_Day_7_en","features.location.impl.show_ShowLocationView_Night_7_en",19923,], +["features.signedout.impl_SignedOutView_Day_0_en","features.signedout.impl_SignedOutView_Night_0_en",19923,], ["libraries.designsystem.components.dialogs_SingleSelectionDialogContent_Dialogs_en","",0,], ["libraries.designsystem.components.dialogs_SingleSelectionDialog_Day_0_en","libraries.designsystem.components.dialogs_SingleSelectionDialog_Night_0_en",0,], ["libraries.designsystem.components.list_SingleSelectionListItemCustomFormattert_Single selection List item - custom formatter_List items_en","",0,], @@ -873,7 +881,7 @@ export const screenshots = [ ["libraries.designsystem.components.list_SingleSelectionListItemUnselectedWithSupportingText_Single selection List item - no selection, supporting text_List items_en","",0,], ["libraries.designsystem.components.list_SingleSelectionListItem_Single selection List item - no selection_List items_en","",0,], ["libraries.designsystem.theme.components_Sliders_Sliders_en","",0,], -["features.login.impl.dialogs_SlidingSyncNotSupportedDialog_Day_0_en","features.login.impl.dialogs_SlidingSyncNotSupportedDialog_Night_0_en",19916,], +["features.login.impl.dialogs_SlidingSyncNotSupportedDialog_Day_0_en","features.login.impl.dialogs_SlidingSyncNotSupportedDialog_Night_0_en",19923,], ["libraries.designsystem.theme.components_SnackbarWithActionAndCloseButton_Snackbar with action and close button_Snackbars_en","",0,], ["libraries.designsystem.theme.components_SnackbarWithActionOnNewLineAndCloseButton_Snackbar with action and close button on new line_Snackbars_en","",0,], ["libraries.designsystem.theme.components_SnackbarWithActionOnNewLine_Snackbar with action on new line_Snackbars_en","",0,], @@ -883,34 +891,36 @@ export const screenshots = [ ["libraries.designsystem.modifiers_SquareSizeModifierLargeHeight_en","",0,], ["libraries.designsystem.modifiers_SquareSizeModifierLargeWidth_en","",0,], ["features.location.api.internal_StaticMapPlaceholder_Day_0_en","features.location.api.internal_StaticMapPlaceholder_Night_0_en",0,], -["features.location.api.internal_StaticMapPlaceholder_Day_1_en","features.location.api.internal_StaticMapPlaceholder_Night_1_en",19916,], +["features.location.api.internal_StaticMapPlaceholder_Day_1_en","features.location.api.internal_StaticMapPlaceholder_Night_1_en",19923,], ["features.location.api_StaticMapView_Day_0_en","features.location.api_StaticMapView_Night_0_en",0,], ["libraries.designsystem.atomic.pages_SunsetPage_Day_0_en","libraries.designsystem.atomic.pages_SunsetPage_Night_0_en",0,], ["libraries.designsystem.components.button_SuperButton_Day_0_en","libraries.designsystem.components.button_SuperButton_Night_0_en",0,], ["libraries.designsystem.theme.components_Surface_en","",0,], ["libraries.designsystem.theme.components_Switch_Toggles_en","",0,], -["appnav.loggedin_SyncStateView_Day_0_en","appnav.loggedin_SyncStateView_Night_0_en",19916,], +["appnav.loggedin_SyncStateView_Day_0_en","appnav.loggedin_SyncStateView_Night_0_en",19923,], +["libraries.designsystem.theme.components_TextButtonLargeLowPadding_Buttons_en","",0,], ["libraries.designsystem.theme.components_TextButtonLarge_Buttons_en","",0,], +["libraries.designsystem.theme.components_TextButtonMediumLowPadding_Buttons_en","",0,], ["libraries.designsystem.theme.components_TextButtonMedium_Buttons_en","",0,], ["libraries.designsystem.theme.components_TextButtonSmall_Buttons_en","",0,], -["libraries.textcomposer_TextComposerEdit_Day_0_en","libraries.textcomposer_TextComposerEdit_Night_0_en",19916,], -["libraries.textcomposer_TextComposerFormatting_Day_0_en","libraries.textcomposer_TextComposerFormatting_Night_0_en",19916,], -["libraries.textcomposer_TextComposerLinkDialogCreateLinkWithoutText_Day_0_en","libraries.textcomposer_TextComposerLinkDialogCreateLinkWithoutText_Night_0_en",19916,], -["libraries.textcomposer_TextComposerLinkDialogCreateLink_Day_0_en","libraries.textcomposer_TextComposerLinkDialogCreateLink_Night_0_en",19916,], -["libraries.textcomposer_TextComposerLinkDialogEditLink_Day_0_en","libraries.textcomposer_TextComposerLinkDialogEditLink_Night_0_en",19916,], -["libraries.textcomposer_TextComposerReply_Day_0_en","libraries.textcomposer_TextComposerReply_Night_0_en",19916,], -["libraries.textcomposer_TextComposerReply_Day_10_en","libraries.textcomposer_TextComposerReply_Night_10_en",19916,], -["libraries.textcomposer_TextComposerReply_Day_11_en","libraries.textcomposer_TextComposerReply_Night_11_en",19916,], -["libraries.textcomposer_TextComposerReply_Day_1_en","libraries.textcomposer_TextComposerReply_Night_1_en",19916,], -["libraries.textcomposer_TextComposerReply_Day_2_en","libraries.textcomposer_TextComposerReply_Night_2_en",19916,], -["libraries.textcomposer_TextComposerReply_Day_3_en","libraries.textcomposer_TextComposerReply_Night_3_en",19916,], -["libraries.textcomposer_TextComposerReply_Day_4_en","libraries.textcomposer_TextComposerReply_Night_4_en",19916,], -["libraries.textcomposer_TextComposerReply_Day_5_en","libraries.textcomposer_TextComposerReply_Night_5_en",19916,], -["libraries.textcomposer_TextComposerReply_Day_6_en","libraries.textcomposer_TextComposerReply_Night_6_en",19916,], -["libraries.textcomposer_TextComposerReply_Day_7_en","libraries.textcomposer_TextComposerReply_Night_7_en",19916,], -["libraries.textcomposer_TextComposerReply_Day_8_en","libraries.textcomposer_TextComposerReply_Night_8_en",19916,], -["libraries.textcomposer_TextComposerReply_Day_9_en","libraries.textcomposer_TextComposerReply_Night_9_en",19916,], -["libraries.textcomposer_TextComposerSimple_Day_0_en","libraries.textcomposer_TextComposerSimple_Night_0_en",19916,], +["libraries.textcomposer_TextComposerEdit_Day_0_en","libraries.textcomposer_TextComposerEdit_Night_0_en",19923,], +["libraries.textcomposer_TextComposerFormatting_Day_0_en","libraries.textcomposer_TextComposerFormatting_Night_0_en",19923,], +["libraries.textcomposer_TextComposerLinkDialogCreateLinkWithoutText_Day_0_en","libraries.textcomposer_TextComposerLinkDialogCreateLinkWithoutText_Night_0_en",19923,], +["libraries.textcomposer_TextComposerLinkDialogCreateLink_Day_0_en","libraries.textcomposer_TextComposerLinkDialogCreateLink_Night_0_en",19923,], +["libraries.textcomposer_TextComposerLinkDialogEditLink_Day_0_en","libraries.textcomposer_TextComposerLinkDialogEditLink_Night_0_en",19923,], +["libraries.textcomposer_TextComposerReply_Day_0_en","libraries.textcomposer_TextComposerReply_Night_0_en",19923,], +["libraries.textcomposer_TextComposerReply_Day_10_en","libraries.textcomposer_TextComposerReply_Night_10_en",19923,], +["libraries.textcomposer_TextComposerReply_Day_11_en","libraries.textcomposer_TextComposerReply_Night_11_en",19923,], +["libraries.textcomposer_TextComposerReply_Day_1_en","libraries.textcomposer_TextComposerReply_Night_1_en",19923,], +["libraries.textcomposer_TextComposerReply_Day_2_en","libraries.textcomposer_TextComposerReply_Night_2_en",19923,], +["libraries.textcomposer_TextComposerReply_Day_3_en","libraries.textcomposer_TextComposerReply_Night_3_en",19923,], +["libraries.textcomposer_TextComposerReply_Day_4_en","libraries.textcomposer_TextComposerReply_Night_4_en",19923,], +["libraries.textcomposer_TextComposerReply_Day_5_en","libraries.textcomposer_TextComposerReply_Night_5_en",19923,], +["libraries.textcomposer_TextComposerReply_Day_6_en","libraries.textcomposer_TextComposerReply_Night_6_en",19923,], +["libraries.textcomposer_TextComposerReply_Day_7_en","libraries.textcomposer_TextComposerReply_Night_7_en",19923,], +["libraries.textcomposer_TextComposerReply_Day_8_en","libraries.textcomposer_TextComposerReply_Night_8_en",19923,], +["libraries.textcomposer_TextComposerReply_Day_9_en","libraries.textcomposer_TextComposerReply_Night_9_en",19923,], +["libraries.textcomposer_TextComposerSimple_Day_0_en","libraries.textcomposer_TextComposerSimple_Night_0_en",19923,], ["libraries.textcomposer_TextComposerVoice_Day_0_en","libraries.textcomposer_TextComposerVoice_Night_0_en",0,], ["libraries.designsystem.theme.components_TextDark_Text_en","",0,], ["libraries.designsystem.theme.components_TextFieldDark_TextFields_en","",0,], @@ -922,38 +932,38 @@ export const screenshots = [ ["libraries.designsystem.theme.components_TextFieldValueTextFieldDark_TextFields_en","",0,], ["libraries.textcomposer.components_TextFormatting_Day_0_en","libraries.textcomposer.components_TextFormatting_Night_0_en",0,], ["libraries.designsystem.theme.components_TextLight_Text_en","",0,], -["libraries.designsystem.theme.components.previews_TimePickerHorizontal_DateTime pickers_en","",19916,], -["libraries.designsystem.theme.components.previews_TimePickerVerticalDark_DateTime pickers_en","",19916,], -["libraries.designsystem.theme.components.previews_TimePickerVerticalLight_DateTime pickers_en","",19916,], +["libraries.designsystem.theme.components.previews_TimePickerHorizontal_DateTime pickers_en","",19923,], +["libraries.designsystem.theme.components.previews_TimePickerVerticalDark_DateTime pickers_en","",19923,], +["libraries.designsystem.theme.components.previews_TimePickerVerticalLight_DateTime pickers_en","",19923,], ["features.messages.impl.timeline.components_TimelineEventTimestampView_Day_0_en","features.messages.impl.timeline.components_TimelineEventTimestampView_Night_0_en",0,], ["features.messages.impl.timeline.components_TimelineEventTimestampView_Day_1_en","features.messages.impl.timeline.components_TimelineEventTimestampView_Night_1_en",0,], ["features.messages.impl.timeline.components_TimelineEventTimestampView_Day_2_en","features.messages.impl.timeline.components_TimelineEventTimestampView_Night_2_en",0,], -["features.messages.impl.timeline.components_TimelineEventTimestampView_Day_3_en","features.messages.impl.timeline.components_TimelineEventTimestampView_Night_3_en",19916,], -["features.messages.impl.timeline.components_TimelineEventTimestampView_Day_4_en","features.messages.impl.timeline.components_TimelineEventTimestampView_Night_4_en",19916,], +["features.messages.impl.timeline.components_TimelineEventTimestampView_Day_3_en","features.messages.impl.timeline.components_TimelineEventTimestampView_Night_3_en",19923,], +["features.messages.impl.timeline.components_TimelineEventTimestampView_Day_4_en","features.messages.impl.timeline.components_TimelineEventTimestampView_Night_4_en",19923,], ["features.messages.impl.timeline.components.event_TimelineImageWithCaptionRow_Day_0_en","features.messages.impl.timeline.components.event_TimelineImageWithCaptionRow_Night_0_en",0,], ["features.messages.impl.timeline.components.event_TimelineItemAudioView_Day_0_en","features.messages.impl.timeline.components.event_TimelineItemAudioView_Night_0_en",0,], ["features.messages.impl.timeline.components.event_TimelineItemAudioView_Day_1_en","features.messages.impl.timeline.components.event_TimelineItemAudioView_Night_1_en",0,], ["features.messages.impl.timeline.components.event_TimelineItemAudioView_Day_2_en","features.messages.impl.timeline.components.event_TimelineItemAudioView_Night_2_en",0,], -["features.messages.impl.timeline.components_TimelineItemCallNotifyView_Day_0_en","features.messages.impl.timeline.components_TimelineItemCallNotifyView_Night_0_en",19916,], +["features.messages.impl.timeline.components_TimelineItemCallNotifyView_Day_0_en","features.messages.impl.timeline.components_TimelineItemCallNotifyView_Night_0_en",19923,], ["features.messages.impl.timeline.components.virtual_TimelineItemDaySeparatorView_Day_0_en","features.messages.impl.timeline.components.virtual_TimelineItemDaySeparatorView_Night_0_en",0,], ["features.messages.impl.timeline.components.virtual_TimelineItemDaySeparatorView_Day_1_en","features.messages.impl.timeline.components.virtual_TimelineItemDaySeparatorView_Night_1_en",0,], -["features.messages.impl.timeline.components.event_TimelineItemEncryptedView_Day_0_en","features.messages.impl.timeline.components.event_TimelineItemEncryptedView_Night_0_en",19916,], -["features.messages.impl.timeline.components.event_TimelineItemEncryptedView_Day_1_en","features.messages.impl.timeline.components.event_TimelineItemEncryptedView_Night_1_en",19916,], -["features.messages.impl.timeline.components.event_TimelineItemEncryptedView_Day_2_en","features.messages.impl.timeline.components.event_TimelineItemEncryptedView_Night_2_en",19916,], +["features.messages.impl.timeline.components.event_TimelineItemEncryptedView_Day_0_en","features.messages.impl.timeline.components.event_TimelineItemEncryptedView_Night_0_en",19923,], +["features.messages.impl.timeline.components.event_TimelineItemEncryptedView_Day_1_en","features.messages.impl.timeline.components.event_TimelineItemEncryptedView_Night_1_en",19923,], +["features.messages.impl.timeline.components.event_TimelineItemEncryptedView_Day_2_en","features.messages.impl.timeline.components.event_TimelineItemEncryptedView_Night_2_en",19923,], ["features.messages.impl.timeline.components_TimelineItemEventRowDisambiguated_Day_0_en","features.messages.impl.timeline.components_TimelineItemEventRowDisambiguated_Night_0_en",0,], ["features.messages.impl.timeline.components_TimelineItemEventRowForDirectRoom_Day_0_en","features.messages.impl.timeline.components_TimelineItemEventRowForDirectRoom_Night_0_en",0,], ["features.messages.impl.timeline.components_TimelineItemEventRowLongSenderName_en","",0,], ["features.messages.impl.timeline.components_TimelineItemEventRowTimestamp_Day_0_en","features.messages.impl.timeline.components_TimelineItemEventRowTimestamp_Night_0_en",0,], ["features.messages.impl.timeline.components_TimelineItemEventRowTimestamp_Day_1_en","features.messages.impl.timeline.components_TimelineItemEventRowTimestamp_Night_1_en",0,], ["features.messages.impl.timeline.components_TimelineItemEventRowTimestamp_Day_2_en","features.messages.impl.timeline.components_TimelineItemEventRowTimestamp_Night_2_en",0,], -["features.messages.impl.timeline.components_TimelineItemEventRowTimestamp_Day_3_en","features.messages.impl.timeline.components_TimelineItemEventRowTimestamp_Night_3_en",19916,], -["features.messages.impl.timeline.components_TimelineItemEventRowTimestamp_Day_4_en","features.messages.impl.timeline.components_TimelineItemEventRowTimestamp_Night_4_en",19916,], -["features.messages.impl.timeline.components_TimelineItemEventRowWithManyReactions_Day_0_en","features.messages.impl.timeline.components_TimelineItemEventRowWithManyReactions_Night_0_en",19916,], +["features.messages.impl.timeline.components_TimelineItemEventRowTimestamp_Day_3_en","features.messages.impl.timeline.components_TimelineItemEventRowTimestamp_Night_3_en",19923,], +["features.messages.impl.timeline.components_TimelineItemEventRowTimestamp_Day_4_en","features.messages.impl.timeline.components_TimelineItemEventRowTimestamp_Night_4_en",19923,], +["features.messages.impl.timeline.components_TimelineItemEventRowWithManyReactions_Day_0_en","features.messages.impl.timeline.components_TimelineItemEventRowWithManyReactions_Night_0_en",19923,], ["features.messages.impl.timeline.components_TimelineItemEventRowWithRR_Day_0_en","features.messages.impl.timeline.components_TimelineItemEventRowWithRR_Night_0_en",0,], ["features.messages.impl.timeline.components_TimelineItemEventRowWithRR_Day_1_en","features.messages.impl.timeline.components_TimelineItemEventRowWithRR_Night_1_en",0,], ["features.messages.impl.timeline.components_TimelineItemEventRowWithRR_Day_2_en","features.messages.impl.timeline.components_TimelineItemEventRowWithRR_Night_2_en",0,], -["features.messages.impl.timeline.components_TimelineItemEventRowWithReplyInformative_Day_0_en","features.messages.impl.timeline.components_TimelineItemEventRowWithReplyInformative_Night_0_en",19916,], -["features.messages.impl.timeline.components_TimelineItemEventRowWithReplyInformative_Day_1_en","features.messages.impl.timeline.components_TimelineItemEventRowWithReplyInformative_Night_1_en",19916,], +["features.messages.impl.timeline.components_TimelineItemEventRowWithReplyInformative_Day_0_en","features.messages.impl.timeline.components_TimelineItemEventRowWithReplyInformative_Night_0_en",19923,], +["features.messages.impl.timeline.components_TimelineItemEventRowWithReplyInformative_Day_1_en","features.messages.impl.timeline.components_TimelineItemEventRowWithReplyInformative_Night_1_en",19923,], ["features.messages.impl.timeline.components_TimelineItemEventRowWithReplyOther_Day_0_en","features.messages.impl.timeline.components_TimelineItemEventRowWithReplyOther_Night_0_en",0,], ["features.messages.impl.timeline.components_TimelineItemEventRowWithReplyOther_Day_1_en","features.messages.impl.timeline.components_TimelineItemEventRowWithReplyOther_Night_1_en",0,], ["features.messages.impl.timeline.components_TimelineItemEventRowWithReply_Day_0_en","features.messages.impl.timeline.components_TimelineItemEventRowWithReply_Night_0_en",0,], @@ -962,36 +972,36 @@ export const screenshots = [ ["features.messages.impl.timeline.components_TimelineItemEventRowWithReply_Day_1_en","features.messages.impl.timeline.components_TimelineItemEventRowWithReply_Night_1_en",0,], ["features.messages.impl.timeline.components_TimelineItemEventRowWithReply_Day_2_en","features.messages.impl.timeline.components_TimelineItemEventRowWithReply_Night_2_en",0,], ["features.messages.impl.timeline.components_TimelineItemEventRowWithReply_Day_3_en","features.messages.impl.timeline.components_TimelineItemEventRowWithReply_Night_3_en",0,], -["features.messages.impl.timeline.components_TimelineItemEventRowWithReply_Day_4_en","features.messages.impl.timeline.components_TimelineItemEventRowWithReply_Night_4_en",19916,], +["features.messages.impl.timeline.components_TimelineItemEventRowWithReply_Day_4_en","features.messages.impl.timeline.components_TimelineItemEventRowWithReply_Night_4_en",19923,], ["features.messages.impl.timeline.components_TimelineItemEventRowWithReply_Day_5_en","features.messages.impl.timeline.components_TimelineItemEventRowWithReply_Night_5_en",0,], ["features.messages.impl.timeline.components_TimelineItemEventRowWithReply_Day_6_en","features.messages.impl.timeline.components_TimelineItemEventRowWithReply_Night_6_en",0,], ["features.messages.impl.timeline.components_TimelineItemEventRowWithReply_Day_7_en","features.messages.impl.timeline.components_TimelineItemEventRowWithReply_Night_7_en",0,], -["features.messages.impl.timeline.components_TimelineItemEventRowWithReply_Day_8_en","features.messages.impl.timeline.components_TimelineItemEventRowWithReply_Night_8_en",19916,], +["features.messages.impl.timeline.components_TimelineItemEventRowWithReply_Day_8_en","features.messages.impl.timeline.components_TimelineItemEventRowWithReply_Night_8_en",19923,], ["features.messages.impl.timeline.components_TimelineItemEventRowWithReply_Day_9_en","features.messages.impl.timeline.components_TimelineItemEventRowWithReply_Night_9_en",0,], ["features.messages.impl.timeline.components_TimelineItemEventRow_Day_0_en","features.messages.impl.timeline.components_TimelineItemEventRow_Night_0_en",0,], -["features.messages.impl.timeline.components_TimelineItemEventTimestampBelow_en","",19916,], +["features.messages.impl.timeline.components_TimelineItemEventTimestampBelow_en","",19923,], ["features.messages.impl.timeline.components.event_TimelineItemFileView_Day_0_en","features.messages.impl.timeline.components.event_TimelineItemFileView_Night_0_en",0,], ["features.messages.impl.timeline.components.event_TimelineItemFileView_Day_1_en","features.messages.impl.timeline.components.event_TimelineItemFileView_Night_1_en",0,], ["features.messages.impl.timeline.components.event_TimelineItemFileView_Day_2_en","features.messages.impl.timeline.components.event_TimelineItemFileView_Night_2_en",0,], -["features.messages.impl.timeline.components_TimelineItemGroupedEventsRowContentCollapse_Day_0_en","features.messages.impl.timeline.components_TimelineItemGroupedEventsRowContentCollapse_Night_0_en",19916,], -["features.messages.impl.timeline.components_TimelineItemGroupedEventsRowContentExpanded_Day_0_en","features.messages.impl.timeline.components_TimelineItemGroupedEventsRowContentExpanded_Night_0_en",19916,], +["features.messages.impl.timeline.components_TimelineItemGroupedEventsRowContentCollapse_Day_0_en","features.messages.impl.timeline.components_TimelineItemGroupedEventsRowContentCollapse_Night_0_en",19923,], +["features.messages.impl.timeline.components_TimelineItemGroupedEventsRowContentExpanded_Day_0_en","features.messages.impl.timeline.components_TimelineItemGroupedEventsRowContentExpanded_Night_0_en",19923,], ["features.messages.impl.timeline.components.event_TimelineItemImageView_Day_0_en","features.messages.impl.timeline.components.event_TimelineItemImageView_Night_0_en",0,], ["features.messages.impl.timeline.components.event_TimelineItemImageView_Day_1_en","features.messages.impl.timeline.components.event_TimelineItemImageView_Night_1_en",0,], ["features.messages.impl.timeline.components.event_TimelineItemImageView_Day_2_en","features.messages.impl.timeline.components.event_TimelineItemImageView_Night_2_en",0,], ["features.messages.impl.timeline.components.event_TimelineItemInformativeView_Day_0_en","features.messages.impl.timeline.components.event_TimelineItemInformativeView_Night_0_en",0,], -["features.messages.impl.timeline.components.event_TimelineItemLegacyCallInviteView_Day_0_en","features.messages.impl.timeline.components.event_TimelineItemLegacyCallInviteView_Night_0_en",19916,], +["features.messages.impl.timeline.components.event_TimelineItemLegacyCallInviteView_Day_0_en","features.messages.impl.timeline.components.event_TimelineItemLegacyCallInviteView_Night_0_en",19923,], ["features.messages.impl.timeline.components.event_TimelineItemLocationView_Day_0_en","features.messages.impl.timeline.components.event_TimelineItemLocationView_Night_0_en",0,], ["features.messages.impl.timeline.components.event_TimelineItemLocationView_Day_1_en","features.messages.impl.timeline.components.event_TimelineItemLocationView_Night_1_en",0,], -["features.messages.impl.timeline.components.event_TimelineItemPollView_Day_0_en","features.messages.impl.timeline.components.event_TimelineItemPollView_Night_0_en",19916,], -["features.messages.impl.timeline.components.event_TimelineItemPollView_Day_1_en","features.messages.impl.timeline.components.event_TimelineItemPollView_Night_1_en",19916,], -["features.messages.impl.timeline.components.event_TimelineItemPollView_Day_2_en","features.messages.impl.timeline.components.event_TimelineItemPollView_Night_2_en",19916,], -["features.messages.impl.timeline.components.event_TimelineItemPollView_Day_3_en","features.messages.impl.timeline.components.event_TimelineItemPollView_Night_3_en",19916,], -["features.messages.impl.timeline.components_TimelineItemReactionsLayout_Day_0_en","features.messages.impl.timeline.components_TimelineItemReactionsLayout_Night_0_en",19916,], +["features.messages.impl.timeline.components.event_TimelineItemPollView_Day_0_en","features.messages.impl.timeline.components.event_TimelineItemPollView_Night_0_en",19923,], +["features.messages.impl.timeline.components.event_TimelineItemPollView_Day_1_en","features.messages.impl.timeline.components.event_TimelineItemPollView_Night_1_en",19923,], +["features.messages.impl.timeline.components.event_TimelineItemPollView_Day_2_en","features.messages.impl.timeline.components.event_TimelineItemPollView_Night_2_en",19923,], +["features.messages.impl.timeline.components.event_TimelineItemPollView_Day_3_en","features.messages.impl.timeline.components.event_TimelineItemPollView_Night_3_en",19923,], +["features.messages.impl.timeline.components_TimelineItemReactionsLayout_Day_0_en","features.messages.impl.timeline.components_TimelineItemReactionsLayout_Night_0_en",19923,], ["features.messages.impl.timeline.components_TimelineItemReactionsViewFew_Day_0_en","features.messages.impl.timeline.components_TimelineItemReactionsViewFew_Night_0_en",0,], -["features.messages.impl.timeline.components_TimelineItemReactionsViewIncoming_Day_0_en","features.messages.impl.timeline.components_TimelineItemReactionsViewIncoming_Night_0_en",19916,], -["features.messages.impl.timeline.components_TimelineItemReactionsViewOutgoing_Day_0_en","features.messages.impl.timeline.components_TimelineItemReactionsViewOutgoing_Night_0_en",19916,], +["features.messages.impl.timeline.components_TimelineItemReactionsViewIncoming_Day_0_en","features.messages.impl.timeline.components_TimelineItemReactionsViewIncoming_Night_0_en",19923,], +["features.messages.impl.timeline.components_TimelineItemReactionsViewOutgoing_Day_0_en","features.messages.impl.timeline.components_TimelineItemReactionsViewOutgoing_Night_0_en",19923,], ["features.messages.impl.timeline.components_TimelineItemReactionsView_Day_0_en","features.messages.impl.timeline.components_TimelineItemReactionsView_Night_0_en",0,], -["features.messages.impl.timeline.components.virtual_TimelineItemReadMarkerView_Day_0_en","features.messages.impl.timeline.components.virtual_TimelineItemReadMarkerView_Night_0_en",19916,], +["features.messages.impl.timeline.components.virtual_TimelineItemReadMarkerView_Day_0_en","features.messages.impl.timeline.components.virtual_TimelineItemReadMarkerView_Night_0_en",19923,], ["features.messages.impl.timeline.components.receipt_TimelineItemReadReceiptView_Day_0_en","features.messages.impl.timeline.components.receipt_TimelineItemReadReceiptView_Night_0_en",0,], ["features.messages.impl.timeline.components.receipt_TimelineItemReadReceiptView_Day_1_en","features.messages.impl.timeline.components.receipt_TimelineItemReadReceiptView_Night_1_en",0,], ["features.messages.impl.timeline.components.receipt_TimelineItemReadReceiptView_Day_2_en","features.messages.impl.timeline.components.receipt_TimelineItemReadReceiptView_Night_2_en",0,], @@ -1000,8 +1010,8 @@ export const screenshots = [ ["features.messages.impl.timeline.components.receipt_TimelineItemReadReceiptView_Day_5_en","features.messages.impl.timeline.components.receipt_TimelineItemReadReceiptView_Night_5_en",0,], ["features.messages.impl.timeline.components.receipt_TimelineItemReadReceiptView_Day_6_en","features.messages.impl.timeline.components.receipt_TimelineItemReadReceiptView_Night_6_en",0,], ["features.messages.impl.timeline.components.receipt_TimelineItemReadReceiptView_Day_7_en","features.messages.impl.timeline.components.receipt_TimelineItemReadReceiptView_Night_7_en",0,], -["features.messages.impl.timeline.components.event_TimelineItemRedactedView_Day_0_en","features.messages.impl.timeline.components.event_TimelineItemRedactedView_Night_0_en",19916,], -["features.messages.impl.timeline.components.virtual_TimelineItemRoomBeginningView_Day_0_en","features.messages.impl.timeline.components.virtual_TimelineItemRoomBeginningView_Night_0_en",19916,], +["features.messages.impl.timeline.components.event_TimelineItemRedactedView_Day_0_en","features.messages.impl.timeline.components.event_TimelineItemRedactedView_Night_0_en",19923,], +["features.messages.impl.timeline.components.virtual_TimelineItemRoomBeginningView_Day_0_en","features.messages.impl.timeline.components.virtual_TimelineItemRoomBeginningView_Night_0_en",19923,], ["features.messages.impl.timeline.components_TimelineItemStateEventRow_Day_0_en","features.messages.impl.timeline.components_TimelineItemStateEventRow_Night_0_en",0,], ["features.messages.impl.timeline.components.event_TimelineItemStateView_Day_0_en","features.messages.impl.timeline.components.event_TimelineItemStateView_Night_0_en",0,], ["features.messages.impl.timeline.components.event_TimelineItemStickerView_Day_0_en","features.messages.impl.timeline.components.event_TimelineItemStickerView_Night_0_en",0,], @@ -1013,7 +1023,7 @@ export const screenshots = [ ["features.messages.impl.timeline.components.event_TimelineItemTextView_Day_3_en","features.messages.impl.timeline.components.event_TimelineItemTextView_Night_3_en",0,], ["features.messages.impl.timeline.components.event_TimelineItemTextView_Day_4_en","features.messages.impl.timeline.components.event_TimelineItemTextView_Night_4_en",0,], ["features.messages.impl.timeline.components.event_TimelineItemTextView_Day_5_en","features.messages.impl.timeline.components.event_TimelineItemTextView_Night_5_en",0,], -["features.messages.impl.timeline.components.event_TimelineItemUnknownView_Day_0_en","features.messages.impl.timeline.components.event_TimelineItemUnknownView_Night_0_en",19916,], +["features.messages.impl.timeline.components.event_TimelineItemUnknownView_Day_0_en","features.messages.impl.timeline.components.event_TimelineItemUnknownView_Night_0_en",19923,], ["features.messages.impl.timeline.components.event_TimelineItemVideoView_Day_0_en","features.messages.impl.timeline.components.event_TimelineItemVideoView_Night_0_en",0,], ["features.messages.impl.timeline.components.event_TimelineItemVideoView_Day_1_en","features.messages.impl.timeline.components.event_TimelineItemVideoView_Night_1_en",0,], ["features.messages.impl.timeline.components.event_TimelineItemVideoView_Day_2_en","features.messages.impl.timeline.components.event_TimelineItemVideoView_Night_2_en",0,], @@ -1035,79 +1045,79 @@ export const screenshots = [ ["features.messages.impl.timeline.components.event_TimelineItemVoiceView_Day_9_en","features.messages.impl.timeline.components.event_TimelineItemVoiceView_Night_9_en",0,], ["features.messages.impl.timeline.components.virtual_TimelineLoadingMoreIndicator_Day_0_en","features.messages.impl.timeline.components.virtual_TimelineLoadingMoreIndicator_Night_0_en",0,], ["features.messages.impl.timeline.components.event_TimelineVideoWithCaptionRow_Day_0_en","features.messages.impl.timeline.components.event_TimelineVideoWithCaptionRow_Night_0_en",0,], -["features.messages.impl.timeline_TimelineView_Day_0_en","features.messages.impl.timeline_TimelineView_Night_0_en",19916,], +["features.messages.impl.timeline_TimelineView_Day_0_en","features.messages.impl.timeline_TimelineView_Night_0_en",19923,], ["features.messages.impl.timeline_TimelineView_Day_10_en","features.messages.impl.timeline_TimelineView_Night_10_en",0,], -["features.messages.impl.timeline_TimelineView_Day_11_en","features.messages.impl.timeline_TimelineView_Night_11_en",19916,], -["features.messages.impl.timeline_TimelineView_Day_12_en","features.messages.impl.timeline_TimelineView_Night_12_en",19916,], -["features.messages.impl.timeline_TimelineView_Day_13_en","features.messages.impl.timeline_TimelineView_Night_13_en",19916,], -["features.messages.impl.timeline_TimelineView_Day_14_en","features.messages.impl.timeline_TimelineView_Night_14_en",19916,], -["features.messages.impl.timeline_TimelineView_Day_15_en","features.messages.impl.timeline_TimelineView_Night_15_en",19916,], -["features.messages.impl.timeline_TimelineView_Day_16_en","features.messages.impl.timeline_TimelineView_Night_16_en",19916,], -["features.messages.impl.timeline_TimelineView_Day_1_en","features.messages.impl.timeline_TimelineView_Night_1_en",19916,], +["features.messages.impl.timeline_TimelineView_Day_11_en","features.messages.impl.timeline_TimelineView_Night_11_en",19923,], +["features.messages.impl.timeline_TimelineView_Day_12_en","features.messages.impl.timeline_TimelineView_Night_12_en",19923,], +["features.messages.impl.timeline_TimelineView_Day_13_en","features.messages.impl.timeline_TimelineView_Night_13_en",19923,], +["features.messages.impl.timeline_TimelineView_Day_14_en","features.messages.impl.timeline_TimelineView_Night_14_en",19923,], +["features.messages.impl.timeline_TimelineView_Day_15_en","features.messages.impl.timeline_TimelineView_Night_15_en",19923,], +["features.messages.impl.timeline_TimelineView_Day_16_en","features.messages.impl.timeline_TimelineView_Night_16_en",19923,], +["features.messages.impl.timeline_TimelineView_Day_1_en","features.messages.impl.timeline_TimelineView_Night_1_en",19923,], ["features.messages.impl.timeline_TimelineView_Day_2_en","features.messages.impl.timeline_TimelineView_Night_2_en",0,], ["features.messages.impl.timeline_TimelineView_Day_3_en","features.messages.impl.timeline_TimelineView_Night_3_en",0,], -["features.messages.impl.timeline_TimelineView_Day_4_en","features.messages.impl.timeline_TimelineView_Night_4_en",19916,], +["features.messages.impl.timeline_TimelineView_Day_4_en","features.messages.impl.timeline_TimelineView_Night_4_en",19923,], ["features.messages.impl.timeline_TimelineView_Day_5_en","features.messages.impl.timeline_TimelineView_Night_5_en",0,], -["features.messages.impl.timeline_TimelineView_Day_6_en","features.messages.impl.timeline_TimelineView_Night_6_en",19916,], +["features.messages.impl.timeline_TimelineView_Day_6_en","features.messages.impl.timeline_TimelineView_Night_6_en",19923,], ["features.messages.impl.timeline_TimelineView_Day_7_en","features.messages.impl.timeline_TimelineView_Night_7_en",0,], -["features.messages.impl.timeline_TimelineView_Day_8_en","features.messages.impl.timeline_TimelineView_Night_8_en",19916,], +["features.messages.impl.timeline_TimelineView_Day_8_en","features.messages.impl.timeline_TimelineView_Night_8_en",19923,], ["features.messages.impl.timeline_TimelineView_Day_9_en","features.messages.impl.timeline_TimelineView_Night_9_en",0,], ["libraries.designsystem.theme.components_TopAppBar_App Bars_en","",0,], -["libraries.troubleshoot.impl_TroubleshootNotificationsView_Day_0_en","libraries.troubleshoot.impl_TroubleshootNotificationsView_Night_0_en",19916,], -["libraries.troubleshoot.impl_TroubleshootNotificationsView_Day_1_en","libraries.troubleshoot.impl_TroubleshootNotificationsView_Night_1_en",19916,], -["libraries.troubleshoot.impl_TroubleshootNotificationsView_Day_2_en","libraries.troubleshoot.impl_TroubleshootNotificationsView_Night_2_en",19916,], -["libraries.troubleshoot.impl_TroubleshootNotificationsView_Day_3_en","libraries.troubleshoot.impl_TroubleshootNotificationsView_Night_3_en",19916,], -["libraries.troubleshoot.impl_TroubleshootNotificationsView_Day_4_en","libraries.troubleshoot.impl_TroubleshootNotificationsView_Night_4_en",19916,], -["libraries.troubleshoot.impl_TroubleshootNotificationsView_Day_5_en","libraries.troubleshoot.impl_TroubleshootNotificationsView_Night_5_en",19916,], -["libraries.troubleshoot.impl_TroubleshootNotificationsView_Day_6_en","libraries.troubleshoot.impl_TroubleshootNotificationsView_Night_6_en",19916,], -["libraries.troubleshoot.impl_TroubleshootNotificationsView_Day_7_en","libraries.troubleshoot.impl_TroubleshootNotificationsView_Night_7_en",19916,], +["libraries.troubleshoot.impl_TroubleshootNotificationsView_Day_0_en","libraries.troubleshoot.impl_TroubleshootNotificationsView_Night_0_en",19923,], +["libraries.troubleshoot.impl_TroubleshootNotificationsView_Day_1_en","libraries.troubleshoot.impl_TroubleshootNotificationsView_Night_1_en",19923,], +["libraries.troubleshoot.impl_TroubleshootNotificationsView_Day_2_en","libraries.troubleshoot.impl_TroubleshootNotificationsView_Night_2_en",19923,], +["libraries.troubleshoot.impl_TroubleshootNotificationsView_Day_3_en","libraries.troubleshoot.impl_TroubleshootNotificationsView_Night_3_en",19923,], +["libraries.troubleshoot.impl_TroubleshootNotificationsView_Day_4_en","libraries.troubleshoot.impl_TroubleshootNotificationsView_Night_4_en",19923,], +["libraries.troubleshoot.impl_TroubleshootNotificationsView_Day_5_en","libraries.troubleshoot.impl_TroubleshootNotificationsView_Night_5_en",19923,], +["libraries.troubleshoot.impl_TroubleshootNotificationsView_Day_6_en","libraries.troubleshoot.impl_TroubleshootNotificationsView_Night_6_en",19923,], +["libraries.troubleshoot.impl_TroubleshootNotificationsView_Day_7_en","libraries.troubleshoot.impl_TroubleshootNotificationsView_Night_7_en",19923,], ["features.messages.impl.typing_TypingNotificationView_Day_0_en","features.messages.impl.typing_TypingNotificationView_Night_0_en",0,], -["features.messages.impl.typing_TypingNotificationView_Day_1_en","features.messages.impl.typing_TypingNotificationView_Night_1_en",19916,], -["features.messages.impl.typing_TypingNotificationView_Day_2_en","features.messages.impl.typing_TypingNotificationView_Night_2_en",19916,], -["features.messages.impl.typing_TypingNotificationView_Day_3_en","features.messages.impl.typing_TypingNotificationView_Night_3_en",19916,], -["features.messages.impl.typing_TypingNotificationView_Day_4_en","features.messages.impl.typing_TypingNotificationView_Night_4_en",19916,], -["features.messages.impl.typing_TypingNotificationView_Day_5_en","features.messages.impl.typing_TypingNotificationView_Night_5_en",19916,], -["features.messages.impl.typing_TypingNotificationView_Day_6_en","features.messages.impl.typing_TypingNotificationView_Night_6_en",19916,], +["features.messages.impl.typing_TypingNotificationView_Day_1_en","features.messages.impl.typing_TypingNotificationView_Night_1_en",19923,], +["features.messages.impl.typing_TypingNotificationView_Day_2_en","features.messages.impl.typing_TypingNotificationView_Night_2_en",19923,], +["features.messages.impl.typing_TypingNotificationView_Day_3_en","features.messages.impl.typing_TypingNotificationView_Night_3_en",19923,], +["features.messages.impl.typing_TypingNotificationView_Day_4_en","features.messages.impl.typing_TypingNotificationView_Night_4_en",19923,], +["features.messages.impl.typing_TypingNotificationView_Day_5_en","features.messages.impl.typing_TypingNotificationView_Night_5_en",19923,], +["features.messages.impl.typing_TypingNotificationView_Day_6_en","features.messages.impl.typing_TypingNotificationView_Night_6_en",19923,], ["features.messages.impl.typing_TypingNotificationView_Day_7_en","features.messages.impl.typing_TypingNotificationView_Night_7_en",0,], ["features.messages.impl.typing_TypingNotificationView_Day_8_en","features.messages.impl.typing_TypingNotificationView_Night_8_en",0,], ["libraries.designsystem.atomic.atoms_UnreadIndicatorAtom_Day_0_en","libraries.designsystem.atomic.atoms_UnreadIndicatorAtom_Night_0_en",0,], -["libraries.matrix.ui.components_UnresolvedUserRow_en","",19916,], +["libraries.matrix.ui.components_UnresolvedUserRow_en","",19923,], ["libraries.matrix.ui.components_UnsavedAvatar_Day_0_en","libraries.matrix.ui.components_UnsavedAvatar_Night_0_en",0,], ["libraries.designsystem.components.avatar_UserAvatarColors_Day_0_en","libraries.designsystem.components.avatar_UserAvatarColors_Night_0_en",0,], -["features.roomdetails.impl.notificationsettings_UserDefinedRoomNotificationSettingsView_Day_0_en","features.roomdetails.impl.notificationsettings_UserDefinedRoomNotificationSettingsView_Night_0_en",19916,], -["features.createroom.impl.components_UserListView_Day_0_en","features.createroom.impl.components_UserListView_Night_0_en",19916,], -["features.createroom.impl.components_UserListView_Day_1_en","features.createroom.impl.components_UserListView_Night_1_en",19916,], -["features.createroom.impl.components_UserListView_Day_2_en","features.createroom.impl.components_UserListView_Night_2_en",19916,], +["features.roomdetails.impl.notificationsettings_UserDefinedRoomNotificationSettingsView_Day_0_en","features.roomdetails.impl.notificationsettings_UserDefinedRoomNotificationSettingsView_Night_0_en",19923,], +["features.createroom.impl.components_UserListView_Day_0_en","features.createroom.impl.components_UserListView_Night_0_en",19923,], +["features.createroom.impl.components_UserListView_Day_1_en","features.createroom.impl.components_UserListView_Night_1_en",19923,], +["features.createroom.impl.components_UserListView_Day_2_en","features.createroom.impl.components_UserListView_Night_2_en",19923,], ["features.createroom.impl.components_UserListView_Day_3_en","features.createroom.impl.components_UserListView_Night_3_en",0,], ["features.createroom.impl.components_UserListView_Day_4_en","features.createroom.impl.components_UserListView_Night_4_en",0,], ["features.createroom.impl.components_UserListView_Day_5_en","features.createroom.impl.components_UserListView_Night_5_en",0,], ["features.createroom.impl.components_UserListView_Day_6_en","features.createroom.impl.components_UserListView_Night_6_en",0,], -["features.createroom.impl.components_UserListView_Day_7_en","features.createroom.impl.components_UserListView_Night_7_en",19916,], +["features.createroom.impl.components_UserListView_Day_7_en","features.createroom.impl.components_UserListView_Night_7_en",19923,], ["features.createroom.impl.components_UserListView_Day_8_en","features.createroom.impl.components_UserListView_Night_8_en",0,], -["features.createroom.impl.components_UserListView_Day_9_en","features.createroom.impl.components_UserListView_Night_9_en",19916,], +["features.createroom.impl.components_UserListView_Day_9_en","features.createroom.impl.components_UserListView_Night_9_en",19923,], ["features.preferences.impl.user_UserPreferences_Day_0_en","features.preferences.impl.user_UserPreferences_Night_0_en",0,], ["features.preferences.impl.user_UserPreferences_Day_1_en","features.preferences.impl.user_UserPreferences_Night_1_en",0,], ["features.preferences.impl.user_UserPreferences_Day_2_en","features.preferences.impl.user_UserPreferences_Night_2_en",0,], ["features.userprofile.shared_UserProfileHeaderSection_Day_0_en","features.userprofile.shared_UserProfileHeaderSection_Night_0_en",0,], -["features.userprofile.shared_UserProfileView_Day_0_en","features.userprofile.shared_UserProfileView_Night_0_en",19916,], -["features.userprofile.shared_UserProfileView_Day_1_en","features.userprofile.shared_UserProfileView_Night_1_en",19916,], -["features.userprofile.shared_UserProfileView_Day_2_en","features.userprofile.shared_UserProfileView_Night_2_en",19916,], -["features.userprofile.shared_UserProfileView_Day_3_en","features.userprofile.shared_UserProfileView_Night_3_en",19916,], -["features.userprofile.shared_UserProfileView_Day_4_en","features.userprofile.shared_UserProfileView_Night_4_en",19916,], -["features.userprofile.shared_UserProfileView_Day_5_en","features.userprofile.shared_UserProfileView_Night_5_en",19916,], -["features.userprofile.shared_UserProfileView_Day_6_en","features.userprofile.shared_UserProfileView_Night_6_en",19916,], -["features.userprofile.shared_UserProfileView_Day_7_en","features.userprofile.shared_UserProfileView_Night_7_en",19916,], -["features.userprofile.shared_UserProfileView_Day_8_en","features.userprofile.shared_UserProfileView_Night_8_en",19916,], -["features.verifysession.impl_VerifySelfSessionView_Day_0_en","features.verifysession.impl_VerifySelfSessionView_Night_0_en",19916,], -["features.verifysession.impl_VerifySelfSessionView_Day_1_en","features.verifysession.impl_VerifySelfSessionView_Night_1_en",19916,], -["features.verifysession.impl_VerifySelfSessionView_Day_2_en","features.verifysession.impl_VerifySelfSessionView_Night_2_en",19916,], -["features.verifysession.impl_VerifySelfSessionView_Day_3_en","features.verifysession.impl_VerifySelfSessionView_Night_3_en",19916,], -["features.verifysession.impl_VerifySelfSessionView_Day_4_en","features.verifysession.impl_VerifySelfSessionView_Night_4_en",19916,], -["features.verifysession.impl_VerifySelfSessionView_Day_5_en","features.verifysession.impl_VerifySelfSessionView_Night_5_en",19916,], -["features.verifysession.impl_VerifySelfSessionView_Day_6_en","features.verifysession.impl_VerifySelfSessionView_Night_6_en",19916,], -["features.verifysession.impl_VerifySelfSessionView_Day_7_en","features.verifysession.impl_VerifySelfSessionView_Night_7_en",19916,], -["features.verifysession.impl_VerifySelfSessionView_Day_8_en","features.verifysession.impl_VerifySelfSessionView_Night_8_en",19916,], -["features.verifysession.impl_VerifySelfSessionView_Day_9_en","features.verifysession.impl_VerifySelfSessionView_Night_9_en",19916,], +["features.userprofile.shared_UserProfileView_Day_0_en","features.userprofile.shared_UserProfileView_Night_0_en",19923,], +["features.userprofile.shared_UserProfileView_Day_1_en","features.userprofile.shared_UserProfileView_Night_1_en",19923,], +["features.userprofile.shared_UserProfileView_Day_2_en","features.userprofile.shared_UserProfileView_Night_2_en",19923,], +["features.userprofile.shared_UserProfileView_Day_3_en","features.userprofile.shared_UserProfileView_Night_3_en",19923,], +["features.userprofile.shared_UserProfileView_Day_4_en","features.userprofile.shared_UserProfileView_Night_4_en",19923,], +["features.userprofile.shared_UserProfileView_Day_5_en","features.userprofile.shared_UserProfileView_Night_5_en",19923,], +["features.userprofile.shared_UserProfileView_Day_6_en","features.userprofile.shared_UserProfileView_Night_6_en",19923,], +["features.userprofile.shared_UserProfileView_Day_7_en","features.userprofile.shared_UserProfileView_Night_7_en",19923,], +["features.userprofile.shared_UserProfileView_Day_8_en","features.userprofile.shared_UserProfileView_Night_8_en",19923,], +["features.verifysession.impl_VerifySelfSessionView_Day_0_en","features.verifysession.impl_VerifySelfSessionView_Night_0_en",19923,], +["features.verifysession.impl_VerifySelfSessionView_Day_1_en","features.verifysession.impl_VerifySelfSessionView_Night_1_en",19923,], +["features.verifysession.impl_VerifySelfSessionView_Day_2_en","features.verifysession.impl_VerifySelfSessionView_Night_2_en",19923,], +["features.verifysession.impl_VerifySelfSessionView_Day_3_en","features.verifysession.impl_VerifySelfSessionView_Night_3_en",19923,], +["features.verifysession.impl_VerifySelfSessionView_Day_4_en","features.verifysession.impl_VerifySelfSessionView_Night_4_en",19923,], +["features.verifysession.impl_VerifySelfSessionView_Day_5_en","features.verifysession.impl_VerifySelfSessionView_Night_5_en",19923,], +["features.verifysession.impl_VerifySelfSessionView_Day_6_en","features.verifysession.impl_VerifySelfSessionView_Night_6_en",19923,], +["features.verifysession.impl_VerifySelfSessionView_Day_7_en","features.verifysession.impl_VerifySelfSessionView_Night_7_en",19923,], +["features.verifysession.impl_VerifySelfSessionView_Day_8_en","features.verifysession.impl_VerifySelfSessionView_Night_8_en",19923,], +["features.verifysession.impl_VerifySelfSessionView_Day_9_en","features.verifysession.impl_VerifySelfSessionView_Night_9_en",19923,], ["libraries.designsystem.ruler_VerticalRuler_Day_0_en","libraries.designsystem.ruler_VerticalRuler_Night_0_en",0,], ["features.viewfolder.impl.file_ViewFileView_Day_0_en","features.viewfolder.impl.file_ViewFileView_Night_0_en",0,], ["features.viewfolder.impl.file_ViewFileView_Day_1_en","features.viewfolder.impl.file_ViewFileView_Night_1_en",0,], @@ -1121,12 +1131,12 @@ export const screenshots = [ ["libraries.textcomposer.components_VoiceMessageRecorderButton_Day_0_en","libraries.textcomposer.components_VoiceMessageRecorderButton_Night_0_en",0,], ["libraries.textcomposer.components_VoiceMessageRecording_Day_0_en","libraries.textcomposer.components_VoiceMessageRecording_Night_0_en",0,], ["libraries.textcomposer.components_VoiceMessage_Day_0_en","libraries.textcomposer.components_VoiceMessage_Night_0_en",0,], -["features.login.impl.screens.waitlistscreen_WaitListView_Day_0_en","features.login.impl.screens.waitlistscreen_WaitListView_Night_0_en",19916,], -["features.login.impl.screens.waitlistscreen_WaitListView_Day_1_en","features.login.impl.screens.waitlistscreen_WaitListView_Night_1_en",19916,], -["features.login.impl.screens.waitlistscreen_WaitListView_Day_2_en","features.login.impl.screens.waitlistscreen_WaitListView_Night_2_en",19916,], -["features.login.impl.screens.waitlistscreen_WaitListView_Day_3_en","features.login.impl.screens.waitlistscreen_WaitListView_Night_3_en",19916,], -["features.login.impl.screens.waitlistscreen_WaitListView_Day_4_en","features.login.impl.screens.waitlistscreen_WaitListView_Night_4_en",19916,], +["features.login.impl.screens.waitlistscreen_WaitListView_Day_0_en","features.login.impl.screens.waitlistscreen_WaitListView_Night_0_en",19923,], +["features.login.impl.screens.waitlistscreen_WaitListView_Day_1_en","features.login.impl.screens.waitlistscreen_WaitListView_Night_1_en",19923,], +["features.login.impl.screens.waitlistscreen_WaitListView_Day_2_en","features.login.impl.screens.waitlistscreen_WaitListView_Night_2_en",19923,], +["features.login.impl.screens.waitlistscreen_WaitListView_Day_3_en","features.login.impl.screens.waitlistscreen_WaitListView_Night_3_en",19923,], +["features.login.impl.screens.waitlistscreen_WaitListView_Day_4_en","features.login.impl.screens.waitlistscreen_WaitListView_Night_4_en",19923,], ["libraries.designsystem.components.media_WaveformPlaybackView_Day_0_en","libraries.designsystem.components.media_WaveformPlaybackView_Night_0_en",0,], -["features.ftue.impl.welcome_WelcomeView_Day_0_en","features.ftue.impl.welcome_WelcomeView_Night_0_en",19916,], +["features.ftue.impl.welcome_WelcomeView_Day_0_en","features.ftue.impl.welcome_WelcomeView_Night_0_en",19923,], ["libraries.designsystem.ruler_WithRulers_Day_0_en","libraries.designsystem.ruler_WithRulers_Night_0_en",0,], ]; From 1b016946ea75cb8f159f4a2fd2cb5df3b85b0454 Mon Sep 17 00:00:00 2001 From: Jorge Martin Espinosa Date: Mon, 22 Jul 2024 11:09:20 +0200 Subject: [PATCH 09/15] Fix linkification not working for `Spanned` strings in text messages (#3233) * Fix linkification not working for `Spanned` string instead of `Spannable`. This issue was found as a regression after upgrading the RTE version to `2.37.7`. * Fix and add tests --- .../TimelineItemContentMessageFactory.kt | 18 +-- .../TimelineItemContentMessageFactoryTest.kt | 103 +++++++++++++++++- 2 files changed, 107 insertions(+), 14 deletions(-) diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/factories/event/TimelineItemContentMessageFactory.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/factories/event/TimelineItemContentMessageFactory.kt index 48141ccc03..9d9542d595 100644 --- a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/factories/event/TimelineItemContentMessageFactory.kt +++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/factories/event/TimelineItemContentMessageFactory.kt @@ -264,27 +264,27 @@ class TimelineItemContentMessageFactory @Inject constructor( } private fun CharSequence.withFixedURLSpans(): CharSequence { - if (this !is Spannable) return this + val spannable = this.toSpannable() // Get all URL spans, as they will be removed by LinkifyCompat.addLinks - val oldURLSpans = getSpans(0, length).associateWith { - val start = getSpanStart(it) - val end = getSpanEnd(it) + val oldURLSpans = spannable.getSpans(0, length).associateWith { + val start = spannable.getSpanStart(it) + val end = spannable.getSpanEnd(it) Pair(start, end) } // Find and set as URLSpans any links present in the text - LinkifyCompat.addLinks(this, Linkify.WEB_URLS or Linkify.PHONE_NUMBERS or Linkify.EMAIL_ADDRESSES) + LinkifyCompat.addLinks(spannable, Linkify.WEB_URLS or Linkify.PHONE_NUMBERS or Linkify.EMAIL_ADDRESSES) // Restore old spans, remove new ones if there is a conflict for ((urlSpan, location) in oldURLSpans) { val (start, end) = location - val addedSpans = getSpans(start, end).orEmpty() + val addedSpans = spannable.getSpans(start, end).orEmpty() if (addedSpans.isNotEmpty()) { for (span in addedSpans) { - removeSpan(span) + spannable.removeSpan(span) } } - setSpan(urlSpan, start, end, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE) + spannable.setSpan(urlSpan, start, end, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE) } - return this + return spannable } } diff --git a/features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/timeline/factories/event/TimelineItemContentMessageFactoryTest.kt b/features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/timeline/factories/event/TimelineItemContentMessageFactoryTest.kt index 59cd3cf383..ffb247ed1a 100644 --- a/features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/timeline/factories/event/TimelineItemContentMessageFactoryTest.kt +++ b/features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/timeline/factories/event/TimelineItemContentMessageFactoryTest.kt @@ -20,9 +20,11 @@ import android.net.Uri import android.text.SpannableString import android.text.SpannableStringBuilder import android.text.Spanned +import android.text.SpannedString import android.text.style.URLSpan import androidx.core.text.buildSpannedString import androidx.core.text.inSpans +import androidx.core.text.toSpannable import com.google.common.truth.Truth.assertThat import io.element.android.features.location.api.Location import io.element.android.features.messages.impl.timeline.model.event.TimelineItemAudioContent @@ -74,6 +76,7 @@ import io.element.android.libraries.mediaviewer.api.util.FileExtensionExtractorW import kotlinx.collections.immutable.persistentListOf import kotlinx.collections.immutable.toImmutableList import kotlinx.coroutines.test.runTest +import org.junit.Assert.fail import org.junit.Test import org.junit.runner.RunWith import org.robolectric.RobolectricTestRunner @@ -195,7 +198,7 @@ class TimelineItemContentMessageFactoryTest { inSpans(URLSpan("https://matrix.org")) { append("and manually added link") } - } + }.toSpannable() val sut = createTimelineItemContentMessageFactory( htmlConverterTransform = { expected } ) @@ -610,7 +613,7 @@ class TimelineItemContentMessageFactoryTest { senderDisambiguatedDisplayName = "Bob", eventId = AN_EVENT_ID, ) - assertThat((result as TimelineItemNoticeContent).formattedBody).isEqualTo("formatted") + (result as TimelineItemNoticeContent).formattedBody.assertSpannedEquals(SpannedString("formatted")) } @Test @@ -644,7 +647,8 @@ class TimelineItemContentMessageFactoryTest { senderDisambiguatedDisplayName = "Bob", eventId = AN_EVENT_ID, ) - assertThat((result as TimelineItemEmoteContent).formattedBody).isEqualTo(SpannableString("* Bob formatted")) + + (result as TimelineItemEmoteContent).formattedBody.assertSpannedEquals(SpannableString("* Bob formatted")) } @Test @@ -654,7 +658,7 @@ class TimelineItemContentMessageFactoryTest { inSpans(URLSpan("https://www.example.org")) { append("me@matrix.org") } - } + }.toSpannable() val sut = createTimelineItemContentMessageFactory( htmlConverterTransform = { expectedSpanned }, permalinkParser = FakePermalinkParser { PermalinkData.FallbackLink(Uri.EMPTY) } @@ -669,7 +673,59 @@ class TimelineItemContentMessageFactoryTest { senderDisambiguatedDisplayName = "Bob", eventId = AN_EVENT_ID, ) - assertThat((result as TimelineItemTextContent).formattedBody).isEqualTo(expectedSpanned) + (result as TimelineItemTextContent).formattedBody.assertSpannedEquals(expectedSpanned) + } + + @Test + fun `a message with plain URL in a formatted body Spanned format gets linkified too`() = runTest { + val expectedSpanned = buildSpannedString { + append("Test ") + inSpansWithFlags(URLSpan("https://www.example.org"), flags = Spanned.SPAN_EXCLUSIVE_EXCLUSIVE) { + append("https://www.example.org") + } + } + val sut = createTimelineItemContentMessageFactory( + htmlConverterTransform = { expectedSpanned }, + permalinkParser = FakePermalinkParser { PermalinkData.FallbackLink(Uri.EMPTY) } + ) + val result = sut.create( + content = createMessageContent( + type = TextMessageType( + body = "Test [me@matrix.org](https://www.example.org)", + formatted = FormattedBody(MessageFormat.HTML, "Test https://www.example.org") + ) + ), + senderDisambiguatedDisplayName = "Bob", + eventId = AN_EVENT_ID, + ) + (result as TimelineItemTextContent).formattedBody.assertSpannedEquals(expectedSpanned) + } + + @Test + fun `a message with plain URL in a formatted body with plain text format gets linkified too`() = runTest { + val resultString = "Test https://www.example.org" + val expectedSpanned = buildSpannedString { + append("Test ") + inSpansWithFlags(URLSpan("https://www.example.org"), flags = Spanned.SPAN_EXCLUSIVE_EXCLUSIVE) { + append("https://www.example.org") + } + }.toSpannable() + val sut = createTimelineItemContentMessageFactory( + htmlConverterTransform = { resultString }, + permalinkParser = FakePermalinkParser { PermalinkData.FallbackLink(Uri.EMPTY) } + ) + val result = sut.create( + content = createMessageContent( + type = TextMessageType( + body = "Test [me@matrix.org](https://www.example.org)", + formatted = FormattedBody(MessageFormat.HTML, "Test https://www.example.org") + ) + ), + senderDisambiguatedDisplayName = "Bob", + eventId = AN_EVENT_ID, + ) + + (result as TimelineItemTextContent).formattedBody.assertSpannedEquals(expectedSpanned) } private fun createMessageContent( @@ -718,3 +774,40 @@ class TimelineItemContentMessageFactoryTest { fileExtensionExtractor = FileExtensionExtractorWithoutValidation() ) } + +private inline fun SpannableStringBuilder.inSpansWithFlags(span: Any, flags: Int, action: SpannableStringBuilder.() -> Unit) { + val start = this.length + action() + val end = this.length + setSpan(span, start, end, flags) +} + +fun CharSequence?.assertSpannedEquals(other: CharSequence?) { + if (this == null && other == null) { + return + } else if (this is Spanned && other is Spanned) { + assertThat(this.toString()).isEqualTo(other.toString()) + assertThat(this.length).isEqualTo(other.length) + val thisSpans = this.getSpans(0, this.length, Any::class.java) + val otherSpans = other.getSpans(0, other.length, Any::class.java) + if (thisSpans.size != otherSpans.size) { + fail("Expected ${thisSpans.size} spans, got ${otherSpans.size}") + } + thisSpans.forEachIndexed { index, span -> + val otherSpan = otherSpans[index] + // URLSpans don't have a proper `equals` implementation, so we compare the URL instead + if (span is URLSpan && otherSpan is URLSpan) { + assertThat(span.url).isEqualTo(otherSpan.url) + } else { + assertThat(span).isEqualTo(otherSpan) + } + assertThat(this.getSpanStart(span)).isEqualTo(other.getSpanStart(otherSpan)) + assertThat(this.getSpanEnd(span)).isEqualTo(other.getSpanEnd(otherSpan)) + assertThat(this.getSpanFlags(span)).isEqualTo(other.getSpanFlags(otherSpan)) + } + } else { + val thisString = this?.toString() ?: "null" + val otherString = other?.toString() ?: "null" + fail("Expected Spanned, got $thisString and $otherString") + } +} From a072cc752493725b28aba4dd5df676a26cf47480 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Tue, 23 Jul 2024 14:48:18 +0000 Subject: [PATCH 10/15] Update dependency org.matrix.rustcomponents:sdk-android to v0.2.34 --- gradle/libs.versions.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 97f6585b34..a1fede3e54 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -163,7 +163,7 @@ jsoup = "org.jsoup:jsoup:1.18.1" appyx_core = { module = "com.bumble.appyx:core", version.ref = "appyx" } molecule-runtime = "app.cash.molecule:molecule-runtime:2.0.0" timber = "com.jakewharton.timber:timber:5.0.1" -matrix_sdk = "org.matrix.rustcomponents:sdk-android:0.2.33" +matrix_sdk = "org.matrix.rustcomponents:sdk-android:0.2.34" matrix_richtexteditor = { module = "io.element.android:wysiwyg", version.ref = "wysiwyg" } matrix_richtexteditor_compose = { module = "io.element.android:wysiwyg-compose", version.ref = "wysiwyg" } sqldelight-driver-android = { module = "app.cash.sqldelight:android-driver", version.ref = "sqldelight" } From f5d215ba0f718b59416003447ff56577b356310f Mon Sep 17 00:00:00 2001 From: ganfra Date: Wed, 24 Jul 2024 11:49:16 +0200 Subject: [PATCH 11/15] Edit : fallback to room.edit when timeline item is not found. --- .../MessageComposerPresenter.kt | 8 +++ .../MessageComposerPresenterTest.kt | 62 ++++++++++++++++ .../libraries/matrix/api/room/MatrixRoom.kt | 2 + .../matrix/api/timeline/TimelineException.kt | 1 + .../matrix/impl/room/RustMatrixRoom.kt | 9 +++ .../matrix/impl/timeline/RustTimeline.kt | 72 +++++++------------ .../matrix/impl/util/MessageEventContent.kt | 36 ++++++++++ .../matrix/test/room/FakeMatrixRoom.kt | 5 ++ 8 files changed, 148 insertions(+), 47 deletions(-) create mode 100644 libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/util/MessageEventContent.kt diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/messagecomposer/MessageComposerPresenter.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/messagecomposer/MessageComposerPresenter.kt index 7bd6bd1867..d0e50d114c 100644 --- a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/messagecomposer/MessageComposerPresenter.kt +++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/messagecomposer/MessageComposerPresenter.kt @@ -60,6 +60,7 @@ import io.element.android.libraries.matrix.api.room.Mention import io.element.android.libraries.matrix.api.room.draft.ComposerDraft import io.element.android.libraries.matrix.api.room.draft.ComposerDraftType import io.element.android.libraries.matrix.api.room.isDm +import io.element.android.libraries.matrix.api.timeline.TimelineException import io.element.android.libraries.matrix.ui.messages.RoomMemberProfilesCache import io.element.android.libraries.matrix.ui.messages.reply.InReplyToDetails import io.element.android.libraries.matrix.ui.messages.reply.map @@ -436,7 +437,14 @@ class MessageComposerPresenter @Inject constructor( val eventId = capturedMode.eventId val transactionId = capturedMode.transactionId timelineController.invokeOnCurrentTimeline { + // First try to edit the message in the current timeline editMessage(eventId, transactionId, message.markdown, message.html, message.mentions) + .onFailure { cause -> + if (cause is TimelineException.EventNotFound && eventId != null) { + // if the event is not found in the timeline, try to edit the message directly + room.editMessage(eventId, message.markdown, message.html, message.mentions) + } + } } } diff --git a/features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/textcomposer/MessageComposerPresenterTest.kt b/features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/textcomposer/MessageComposerPresenterTest.kt index b944ea3d95..dcb09fb7c8 100644 --- a/features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/textcomposer/MessageComposerPresenterTest.kt +++ b/features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/textcomposer/MessageComposerPresenterTest.kt @@ -56,6 +56,7 @@ import io.element.android.libraries.matrix.api.room.Mention import io.element.android.libraries.matrix.api.room.RoomMembershipState import io.element.android.libraries.matrix.api.room.draft.ComposerDraft import io.element.android.libraries.matrix.api.room.draft.ComposerDraftType +import io.element.android.libraries.matrix.api.timeline.TimelineException import io.element.android.libraries.matrix.api.timeline.item.event.InReplyTo import io.element.android.libraries.matrix.test.ANOTHER_MESSAGE import io.element.android.libraries.matrix.test.AN_EVENT_ID @@ -417,6 +418,67 @@ class MessageComposerPresenterTest { } } + @Test + fun `present - edit sent message event not found`() = runTest { + val timelineEditMessageLambda = lambdaRecorder { _: EventId?, _: TransactionId?, _: String, _: String?, _: List -> + Result.failure(TimelineException.EventNotFound) + } + val timeline = FakeTimeline().apply { + this.editMessageLambda = timelineEditMessageLambda + } + val roomEditMessageLambda = lambdaRecorder { _: EventId?, _: String, _: String?, _: List -> + Result.success(Unit) + } + val fakeMatrixRoom = FakeMatrixRoom( + liveTimeline = timeline, + typingNoticeResult = { Result.success(Unit) } + ).apply { + this.editMessageLambda = roomEditMessageLambda + } + val presenter = createPresenter( + this, + fakeMatrixRoom, + ) + moleculeFlow(RecompositionMode.Immediate) { + val state = presenter.present() + remember(state, state.textEditorState.messageHtml()) { state } + }.test { + val initialState = awaitFirstItem() + assertThat(initialState.textEditorState.messageHtml()).isEqualTo("") + val mode = anEditMode() + initialState.eventSink.invoke(MessageComposerEvents.SetMode(mode)) + val withMessageState = awaitItem() + assertThat(withMessageState.mode).isEqualTo(mode) + assertThat(withMessageState.textEditorState.messageHtml()).isEqualTo(A_MESSAGE) + withMessageState.textEditorState.setHtml(ANOTHER_MESSAGE) + val withEditedMessageState = awaitItem() + assertThat(withEditedMessageState.textEditorState.messageHtml()).isEqualTo(ANOTHER_MESSAGE) + withEditedMessageState.eventSink.invoke(MessageComposerEvents.SendMessage) + skipItems(1) + val messageSentState = awaitItem() + assertThat(messageSentState.textEditorState.messageHtml()).isEqualTo("") + + advanceUntilIdle() + + assert(timelineEditMessageLambda) + .isCalledOnce() + .with(value(AN_EVENT_ID), value(null), value(ANOTHER_MESSAGE), value(ANOTHER_MESSAGE), any()) + + assert(roomEditMessageLambda) + .isCalledOnce() + .with(value(AN_EVENT_ID), value(ANOTHER_MESSAGE), value(ANOTHER_MESSAGE), any()) + + assertThat(analyticsService.capturedEvents).containsExactly( + Composer( + inThread = false, + isEditing = true, + isReply = false, + messageType = Composer.MessageType.Text, + ) + ) + } + } + @Test fun `present - edit not sent message`() = runTest { val editMessageLambda = lambdaRecorder { _: EventId?, _: TransactionId?, _: String, _: String?, _: List -> diff --git a/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/room/MatrixRoom.kt b/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/room/MatrixRoom.kt index 926df6ae21..378ada5b16 100644 --- a/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/room/MatrixRoom.kt +++ b/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/room/MatrixRoom.kt @@ -126,6 +126,8 @@ interface MatrixRoom : Closeable { suspend fun sendMessage(body: String, htmlBody: String?, mentions: List): Result + suspend fun editMessage(eventId: EventId, body: String, htmlBody: String?, mentions: List): Result + suspend fun sendImage( file: File, thumbnailFile: File?, diff --git a/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/timeline/TimelineException.kt b/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/timeline/TimelineException.kt index e3970619cd..ba44de0ba3 100644 --- a/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/timeline/TimelineException.kt +++ b/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/timeline/TimelineException.kt @@ -18,4 +18,5 @@ package io.element.android.libraries.matrix.api.timeline sealed class TimelineException : Exception() { data object CannotPaginate : TimelineException() + data object EventNotFound : TimelineException() } diff --git a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/room/RustMatrixRoom.kt b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/room/RustMatrixRoom.kt index 0a09ea005e..b594bba5e4 100644 --- a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/room/RustMatrixRoom.kt +++ b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/room/RustMatrixRoom.kt @@ -56,6 +56,7 @@ import io.element.android.libraries.matrix.impl.room.member.RoomMemberMapper import io.element.android.libraries.matrix.impl.room.powerlevels.RoomPowerLevelsMapper import io.element.android.libraries.matrix.impl.timeline.RustTimeline import io.element.android.libraries.matrix.impl.timeline.toRustReceiptType +import io.element.android.libraries.matrix.impl.util.MessageEventContent import io.element.android.libraries.matrix.impl.util.mxCallbackFlow import io.element.android.libraries.matrix.impl.widget.RustWidgetDriver import io.element.android.libraries.matrix.impl.widget.generateWidgetWebViewUrl @@ -324,6 +325,14 @@ class RustMatrixRoom( } } + override suspend fun editMessage(eventId: EventId, body: String, htmlBody: String?, mentions: List): Result = withContext(roomDispatcher) { + runCatching { + MessageEventContent.from(body, htmlBody, mentions).use { newContent -> + innerRoom.edit(eventId.value, newContent) + } + } + } + override suspend fun sendMessage(body: String, htmlBody: String?, mentions: List): Result { return liveTimeline.sendMessage(body, htmlBody, mentions) } diff --git a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/timeline/RustTimeline.kt b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/timeline/RustTimeline.kt index 00c79bf687..b57efc5603 100644 --- a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/timeline/RustTimeline.kt +++ b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/timeline/RustTimeline.kt @@ -42,7 +42,6 @@ import io.element.android.libraries.matrix.impl.media.toMSC3246range import io.element.android.libraries.matrix.impl.poll.toInner import io.element.android.libraries.matrix.impl.room.RoomContentForwarder import io.element.android.libraries.matrix.impl.room.location.toInner -import io.element.android.libraries.matrix.impl.room.map import io.element.android.libraries.matrix.impl.timeline.item.event.EventTimelineItemMapper import io.element.android.libraries.matrix.impl.timeline.item.event.TimelineEventContentMapper import io.element.android.libraries.matrix.impl.timeline.item.virtual.VirtualTimelineItemMapper @@ -51,6 +50,7 @@ import io.element.android.libraries.matrix.impl.timeline.postprocessor.LoadingIn import io.element.android.libraries.matrix.impl.timeline.postprocessor.RoomBeginningPostProcessor import io.element.android.libraries.matrix.impl.timeline.postprocessor.TimelineEncryptedHistoryPostProcessor import io.element.android.libraries.matrix.impl.timeline.reply.InReplyToMapper +import io.element.android.libraries.matrix.impl.util.MessageEventContent import io.element.android.services.toolbox.api.systemclock.SystemClock import kotlinx.coroutines.CompletableDeferred import kotlinx.coroutines.CoroutineDispatcher @@ -70,12 +70,10 @@ import kotlinx.coroutines.flow.onEach import kotlinx.coroutines.flow.onStart import kotlinx.coroutines.launch import kotlinx.coroutines.withContext +import org.matrix.rustcomponents.sdk.EventTimelineItem import org.matrix.rustcomponents.sdk.FormattedBody import org.matrix.rustcomponents.sdk.MessageFormat -import org.matrix.rustcomponents.sdk.RoomMessageEventContentWithoutRelation import org.matrix.rustcomponents.sdk.SendAttachmentJoinHandle -import org.matrix.rustcomponents.sdk.messageEventContentFromHtml -import org.matrix.rustcomponents.sdk.messageEventContentFromMarkdown import org.matrix.rustcomponents.sdk.use import timber.log.Timber import uniffi.matrix_sdk_ui.LiveBackPaginationStatus @@ -266,7 +264,7 @@ class RustTimeline( } override suspend fun sendMessage(body: String, htmlBody: String?, mentions: List): Result = withContext(dispatcher) { - messageEventContentFromParts(body, htmlBody).withMentions(mentions.map()).use { content -> + MessageEventContent.from(body, htmlBody, mentions).use { content -> runCatching { inner.send(content) } @@ -275,20 +273,8 @@ class RustTimeline( override suspend fun redactEvent(eventId: EventId?, transactionId: TransactionId?, reason: String?): Result = withContext(dispatcher) { runCatching { - when { - eventId != null -> { - inner.getEventTimelineItemByEventId(eventId.value).use { - inner.redactEvent(item = it, reason = reason) - } - } - transactionId != null -> { - inner.getEventTimelineItemByTransactionId(transactionId.value).use { - inner.redactEvent(item = it, reason = reason) - } - } - else -> { - error("Either eventId or transactionId must be non-null") - } + getEventTimelineItem(eventId, transactionId).use { item -> + inner.redactEvent(item = item, reason = reason) } } } @@ -302,26 +288,11 @@ class RustTimeline( ): Result = withContext(dispatcher) { runCatching { - when { - originalEventId != null -> { - inner.getEventTimelineItemByEventId(originalEventId.value).use { - inner.edit( - newContent = messageEventContentFromParts(body, htmlBody).withMentions(mentions.map()), - item = it, - ) - } - } - transactionId != null -> { - inner.getEventTimelineItemByTransactionId(transactionId.value).use { - inner.edit( - newContent = messageEventContentFromParts(body, htmlBody).withMentions(mentions.map()), - item = it, - ) - } - } - else -> { - error("Either originalEventId or transactionId must be non null") - } + getEventTimelineItem(originalEventId, transactionId).use { item -> + inner.edit( + newContent = MessageEventContent.from(body, htmlBody, mentions), + item = item, + ) } } } @@ -334,7 +305,7 @@ class RustTimeline( fromNotification: Boolean, ): Result = withContext(dispatcher) { runCatching { - val msg = messageEventContentFromParts(body, htmlBody).withMentions(mentions.map()) + val msg = MessageEventContent.from(body, htmlBody, mentions) inner.sendReply(msg, eventId.value) } } @@ -361,6 +332,20 @@ class RustTimeline( } } + @Throws + private suspend fun getEventTimelineItem(eventId: EventId?, transactionId: TransactionId?): EventTimelineItem { + return try { + when { + eventId != null -> inner.getEventTimelineItemByEventId(eventId.value) + transactionId != null -> inner.getEventTimelineItemByTransactionId(transactionId.value) + else -> error("Either eventId or transactionId must be non-null") + } + } catch (e: Exception) { + Timber.e(e, "Failed to get event timeline item") + throw TimelineException.EventNotFound + } + } + override suspend fun sendVideo( file: File, thumbnailFile: File?, @@ -517,13 +502,6 @@ class RustTimeline( ) } - private fun messageEventContentFromParts(body: String, htmlBody: String?): RoomMessageEventContentWithoutRelation = - if (htmlBody != null) { - messageEventContentFromHtml(body, htmlBody) - } else { - messageEventContentFromMarkdown(body) - } - private fun sendAttachment(files: List, handle: () -> SendAttachmentJoinHandle): Result { return runCatching { MediaUploadHandlerImpl(files, handle()) diff --git a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/util/MessageEventContent.kt b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/util/MessageEventContent.kt new file mode 100644 index 0000000000..e1728bb528 --- /dev/null +++ b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/util/MessageEventContent.kt @@ -0,0 +1,36 @@ +/* + * Copyright (c) 2024 New Vector Ltd + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package io.element.android.libraries.matrix.impl.util + +import io.element.android.libraries.matrix.api.room.Mention +import io.element.android.libraries.matrix.impl.room.map +import org.matrix.rustcomponents.sdk.RoomMessageEventContentWithoutRelation +import org.matrix.rustcomponents.sdk.messageEventContentFromHtml +import org.matrix.rustcomponents.sdk.messageEventContentFromMarkdown + +/** + * Creates a [RoomMessageEventContentWithoutRelation] from a body, an html body and a list of mentions. + */ +object MessageEventContent { + fun from(body: String, htmlBody: String?, mentions: List): RoomMessageEventContentWithoutRelation { + return if (htmlBody != null) { + messageEventContentFromHtml(body, htmlBody) + } else { + messageEventContentFromMarkdown(body) + }.withMentions(mentions.map()) + } +} diff --git a/libraries/matrix/test/src/main/kotlin/io/element/android/libraries/matrix/test/room/FakeMatrixRoom.kt b/libraries/matrix/test/src/main/kotlin/io/element/android/libraries/matrix/test/room/FakeMatrixRoom.kt index 21c50e51a4..cfd0267516 100644 --- a/libraries/matrix/test/src/main/kotlin/io/element/android/libraries/matrix/test/room/FakeMatrixRoom.kt +++ b/libraries/matrix/test/src/main/kotlin/io/element/android/libraries/matrix/test/room/FakeMatrixRoom.kt @@ -212,6 +212,11 @@ class FakeMatrixRoom( return updateUserRoleResult() } + var editMessageLambda: (EventId, String, String?, List) -> Result = { _, _, _, _ -> lambdaError() } + override suspend fun editMessage(eventId: EventId, body: String, htmlBody: String?, mentions: List): Result { + return editMessageLambda(eventId, body, htmlBody, mentions) + } + override suspend fun sendMessage(body: String, htmlBody: String?, mentions: List) = simulateLongTask { sendMessageResult(body, htmlBody, mentions) } From 472c864a381d452bc6521f0f78696519d9adefc1 Mon Sep 17 00:00:00 2001 From: ganfra Date: Wed, 24 Jul 2024 14:34:12 +0200 Subject: [PATCH 12/15] Setting version for the release 0.5.0 --- plugins/src/main/kotlin/Versions.kt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/plugins/src/main/kotlin/Versions.kt b/plugins/src/main/kotlin/Versions.kt index df1e90a378..9fb6df696a 100644 --- a/plugins/src/main/kotlin/Versions.kt +++ b/plugins/src/main/kotlin/Versions.kt @@ -51,12 +51,12 @@ import org.gradle.jvm.toolchain.JavaLanguageVersion // Note: 2 digits max for each value private const val versionMajor = 0 -private const val versionMinor = 4 +private const val versionMinor = 5 // Note: even values are reserved for regular release, odd values for hotfix release. // When creating a hotfix, you should decrease the value, since the current value // is the value for the next regular release. -private const val versionPatch = 17 +private const val versionPatch = 0 object Versions { val versionCode = 4_000_000 + versionMajor * 1_00_00 + versionMinor * 1_00 + versionPatch From 6f8d01331c1781ec39d79246db2ae489ef50c1eb Mon Sep 17 00:00:00 2001 From: ganfra Date: Wed, 24 Jul 2024 14:35:47 +0200 Subject: [PATCH 13/15] Adding fastlane file for version 0.5.0 --- fastlane/metadata/android/en-US/changelogs/40005000.txt | 2 ++ 1 file changed, 2 insertions(+) create mode 100644 fastlane/metadata/android/en-US/changelogs/40005000.txt diff --git a/fastlane/metadata/android/en-US/changelogs/40005000.txt b/fastlane/metadata/android/en-US/changelogs/40005000.txt new file mode 100644 index 0000000000..dd8c30a1b9 --- /dev/null +++ b/fastlane/metadata/android/en-US/changelogs/40005000.txt @@ -0,0 +1,2 @@ +Main changes in this version: mostly bug fixes and performance improvements. +Full changelog: https://github.com/element-hq/element-x-android/releases \ No newline at end of file From 1e7da96f3615fbc0f3f5f48086e3de2dcfd2d8e0 Mon Sep 17 00:00:00 2001 From: ganfra Date: Wed, 24 Jul 2024 14:38:34 +0200 Subject: [PATCH 14/15] version++ --- plugins/src/main/kotlin/Versions.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/src/main/kotlin/Versions.kt b/plugins/src/main/kotlin/Versions.kt index 9fb6df696a..e5df6fe90c 100644 --- a/plugins/src/main/kotlin/Versions.kt +++ b/plugins/src/main/kotlin/Versions.kt @@ -56,7 +56,7 @@ private const val versionMinor = 5 // Note: even values are reserved for regular release, odd values for hotfix release. // When creating a hotfix, you should decrease the value, since the current value // is the value for the next regular release. -private const val versionPatch = 0 +private const val versionPatch = 1 object Versions { val versionCode = 4_000_000 + versionMajor * 1_00_00 + versionMinor * 1_00 + versionPatch From 9f94ce8b313ed98647b37e3dad2b3696137d20ff Mon Sep 17 00:00:00 2001 From: ganfra Date: Wed, 24 Jul 2024 16:29:08 +0200 Subject: [PATCH 15/15] Changelog for version 0.5.0 --- CHANGES.md | 77 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 77 insertions(+) diff --git a/CHANGES.md b/CHANGES.md index c2c2641b34..2661597461 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -1,3 +1,80 @@ +Changes in Element X v0.5.0 (2024-07-24) +========================================= + +### 🙌 Improvements +* Add icon for "Mark as read" and "Mark as unread" actions. by @bmarty in https://github.com/element-hq/element-x-android/pull/3144 +* Add support for Picture In Picture for Element Call by @bmarty in https://github.com/element-hq/element-x-android/pull/3159 +* Set pin grace period to 2 minutes by @bmarty in https://github.com/element-hq/element-x-android/pull/3172 +* Unify the way we decide whether a room is a DM or a group room by @jmartinesp in https://github.com/element-hq/element-x-android/pull/3100 +* Subscribe to `RoomListItems` in the visible range by @jmartinesp in https://github.com/element-hq/element-x-android/pull/3169 +* Improve pip and add feature flag. by @bmarty in https://github.com/element-hq/element-x-android/pull/3199 +* Open Source licenses: add color for links. by @bmarty in https://github.com/element-hq/element-x-android/pull/3215 +* Cancel ringing call notification on call cancellation by @jmartinesp in https://github.com/element-hq/element-x-android/pull/3047 + +### 🐛 Bugfixes +* Fix `MainActionButton` layout for long texts by @jmartinesp in https://github.com/element-hq/element-x-android/pull/3158 +* Always follow the desired theme for Pin, Incoming Call and Element Call screens by @bmarty in https://github.com/element-hq/element-x-android/pull/3165 +* Fix empty screen issue after clearing the cache by @bmarty in https://github.com/element-hq/element-x-android/pull/3163 +* Restore intentional mentions in the markdown/plain text editor by @jmartinesp in https://github.com/element-hq/element-x-android/pull/3193 +* Fix crash in the room list after a forced log out in background by @jmartinesp in https://github.com/element-hq/element-x-android/pull/3180 +* Clear existing notification when a room is marked as read by @bmarty in https://github.com/element-hq/element-x-android/pull/3203 +* Fix crash when Pin code screen is displayed by @bmarty in https://github.com/element-hq/element-x-android/pull/3205 +* Fix pillification not working for non formatted message bodies by @jmartinesp in https://github.com/element-hq/element-x-android/pull/3201 +* Update grammar on Matrix Ids to be more spec compliant and render error instead of infinite loading in room member list screen by @bmarty in https://github.com/element-hq/element-x-android/pull/3206 +* Reduce the risk of text truncation in buttons. by @bmarty in https://github.com/element-hq/element-x-android/pull/3209 +* Ensure that the manual dark theme is rendering correctly regarding -night resource and keyboard by @bmarty in https://github.com/element-hq/element-x-android/pull/3216 +* Fix rendering issue of SunsetPage in dark mode by @bmarty in https://github.com/element-hq/element-x-android/pull/3217 +* Fix linkification not working for `Spanned` strings in text messages by @jmartinesp in https://github.com/element-hq/element-x-android/pull/3233 +* Edit : fallback to room.edit when timeline item is not found. by @ganfra in https://github.com/element-hq/element-x-android/pull/3239 + +### 🗣 Translations +* Sync Strings by @ElementBot in https://github.com/element-hq/element-x-android/pull/3156 +* Sync Strings by @ElementBot in https://github.com/element-hq/element-x-android/pull/3192 +* Sync Strings by @ElementBot in https://github.com/element-hq/element-x-android/pull/3232 + +### 🧱 Build +* Remove Showkase processor not found warning from Danger by @jmartinesp in https://github.com/element-hq/element-x-android/pull/3148 +* Set targetSDK to 34 by @bmarty in https://github.com/element-hq/element-x-android/pull/3149 +* Add a local copy of `inplace-fix.py` and `fix-pg-map-id.py` by @bmarty in https://github.com/element-hq/element-x-android/pull/3167 +* Only add private SSH keys and clone submodules in the original repo by @jmartinesp in https://github.com/element-hq/element-x-android/pull/3225 +* Fix CI for forks by @jmartinesp in https://github.com/element-hq/element-x-android/pull/3226 + +### Dependency upgrades +* Update dependency io.element.android:compound-android to v0.0.7 by @renovate in https://github.com/element-hq/element-x-android/pull/3143 +* Update dependency org.matrix.rustcomponents:sdk-android to v0.2.31 by @renovate in https://github.com/element-hq/element-x-android/pull/3145 +* Update dependency com.squareup:kotlinpoet to v1.18.0 by @renovate in https://github.com/element-hq/element-x-android/pull/3150 +* Update dependency org.robolectric:robolectric to v4.13 by @renovate in https://github.com/element-hq/element-x-android/pull/3157 +* Update plugin dependencycheck to v10.0.2 by @renovate in https://github.com/element-hq/element-x-android/pull/3154 +* Update wysiwyg to v2.37.5 by @renovate in https://github.com/element-hq/element-x-android/pull/3162 +* Update plugin sonarqube to v5.1.0.4882 by @renovate in https://github.com/element-hq/element-x-android/pull/3139 +* Update dependency org.jsoup:jsoup to v1.18.1 by @renovate in https://github.com/element-hq/element-x-android/pull/3171 +* Update dependency com.google.firebase:firebase-bom to v33.1.2 by @renovate in https://github.com/element-hq/element-x-android/pull/3178 +* Update telephoto to v0.12.0 by @renovate in https://github.com/element-hq/element-x-android/pull/3191 +* Update dependency com.google.truth:truth to v1.4.4 by @renovate in https://github.com/element-hq/element-x-android/pull/3187 +* Update dependency com.squareup:kotlinpoet to v1.18.1 by @renovate in https://github.com/element-hq/element-x-android/pull/3194 +* Update dependency io.mockk:mockk to v1.13.12 by @renovate in https://github.com/element-hq/element-x-android/pull/3198 +* Update dependency io.sentry:sentry-android to v7.12.0 by @renovate in https://github.com/element-hq/element-x-android/pull/3200 +* Update plugin dependencycheck to v10.0.3 by @renovate in https://github.com/element-hq/element-x-android/pull/3204 +* Update dependency gradle to v8.9 by @renovate in https://github.com/element-hq/element-x-android/pull/3177 +* Update dependency org.matrix.rustcomponents:sdk-android to v0.2.32 by @renovate in https://github.com/element-hq/element-x-android/pull/3202 +* Update coil to v2.7.0 by @renovate in https://github.com/element-hq/element-x-android/pull/3210 +* Update dependency org.matrix.rustcomponents:sdk-android to v0.2.33 by @renovate in https://github.com/element-hq/element-x-android/pull/3220 +* Update wysiwyg to v2.37.7 by @renovate in https://github.com/element-hq/element-x-android/pull/3218 +* Update telephoto to v0.12.1 by @renovate in https://github.com/element-hq/element-x-android/pull/3230 +* Update dependency org.matrix.rustcomponents:sdk-android to v0.2.34 by @renovate in https://github.com/element-hq/element-x-android/pull/3237 + +### Others +* Reduce delay when selecting room list filters by @jmartinesp in https://github.com/element-hq/element-x-android/pull/3160 +* Add `--alignment-preserved true` when signing APK for F-Droid. by @bmarty in https://github.com/element-hq/element-x-android/pull/3161 +* Ensure that all callback plugins are invoked. by @bmarty in https://github.com/element-hq/element-x-android/pull/3146 +* Add generated screen to show open source licenses in Gplay variant by @bmarty in https://github.com/element-hq/element-x-android/pull/3207 +* Performance : improve time to open a room. by @ganfra in https://github.com/element-hq/element-x-android/pull/3186 +* Add logging to help debug forced logout issues by @jmartinesp in https://github.com/element-hq/element-x-android/pull/3208 +* Use the right filename for log files so they're sorted in rageshakes by @jmartinesp in https://github.com/element-hq/element-x-android/pull/3219 +* Compose : add immutability to some Reaction classes by @ganfra in https://github.com/element-hq/element-x-android/pull/3224 +* Fix stickers display text on room summary by @surakin in https://github.com/element-hq/element-x-android/pull/3221 +* Rework FakeMatrixRoom so that it contains only lambdas. by @bmarty in https://github.com/element-hq/element-x-android/pull/3229 + Changes in Element X v0.4.16 (2024-07-05) =========================================