diff --git a/.gitattributes b/.gitattributes index 0542767eff..2062142284 100644 --- a/.gitattributes +++ b/.gitattributes @@ -1 +1,2 @@ **/snapshots/**/*.png filter=lfs diff=lfs merge=lfs -text +**/docs/images-lfs/*.png filter=lfs diff=lfs merge=lfs -text diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 7d895d0fda..9579e81997 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -2,9 +2,10 @@ name: APK Build on: workflow_dispatch: - pull_request: { } + pull_request: + merge_group: push: - branches: [ main, develop ] + branches: [ develop ] # Enrich gradle.properties for CI/CD env: @@ -13,14 +14,17 @@ env: jobs: debug: - name: Build debug APKs + name: Build APKs runs-on: ubuntu-latest - if: github.ref != 'refs/heads/main' + # Skip for `main` and the merge queue if the branch is up to date with `develop` + if: github.ref != 'refs/heads/main' && github.event.merge_group.base_ref != 'refs/heads/develop' strategy: + matrix: + variant: [debug, release, nightly, samples] fail-fast: false # Allow all jobs on develop. Just one per PR. concurrency: - group: ${{ github.ref == 'refs/heads/develop' && format('build-develop-{0}', github.sha) || format('build-debug-{0}', github.ref) }} + group: ${{ github.ref == 'refs/heads/develop' && format('build-develop-{0}-{1}', matrix.variant, github.sha) || format('build-{0}-{1}', matrix.variant, github.ref) }} cancel-in-progress: true steps: - uses: actions/checkout@v3 @@ -34,14 +38,18 @@ jobs: distribution: 'temurin' # See 'Supported distributions' for available options java-version: '17' - name: Configure gradle - uses: gradle/gradle-build-action@v2.6.1 + uses: gradle/gradle-build-action@v2.7.0 with: cache-read-only: ${{ github.ref != 'refs/heads/develop' }} - name: Assemble debug APK + if: ${{ matrix.variant == 'debug' }} env: ELEMENT_ANDROID_MAPTILER_API_KEY: ${{ secrets.MAPTILER_KEY }} - run: ./gradlew assembleDebug $CI_GRADLE_ARG_PROPERTIES - - name: Upload debug APKs + ELEMENT_ANDROID_MAPTILER_LIGHT_MAP_ID: ${{ secrets.MAPTILER_LIGHT_MAP_ID }} + ELEMENT_ANDROID_MAPTILER_DARK_MAP_ID: ${{ secrets.MAPTILER_DARK_MAP_ID }} + run: ./gradlew assembleDebug -PallWarningsAsErrors=true $CI_GRADLE_ARG_PROPERTIES + - name: Upload APK APKs + if: ${{ matrix.variant == 'debug' }} uses: actions/upload-artifact@v3 with: name: elementx-debug @@ -53,12 +61,12 @@ jobs: continue-on-error: true env: token: ${{ secrets.DIAWI_TOKEN }} - if: ${{ github.event_name == 'pull_request' && env.token != '' }} + if: ${{ matrix.variant == 'debug' && github.event_name == 'pull_request' && env.token != '' }} with: token: ${{ env.token }} file: app/build/outputs/apk/debug/app-arm64-v8a-debug.apk - name: Add or update PR comment with QR Code to download APK. - if: ${{ github.event_name == 'pull_request' && steps.diawi.conclusion == 'success' }} + if: ${{ matrix.variant == 'debug' && github.event_name == 'pull_request' && steps.diawi.conclusion == 'success' }} uses: NejcZdovc/comment-pr@v2 with: message: | @@ -70,8 +78,11 @@ jobs: env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - name: Compile release sources - run: ./gradlew compileReleaseSources $CI_GRADLE_ARG_PROPERTIES + if: ${{ matrix.variant == 'release' }} + run: ./gradlew compileReleaseSources -PallWarningsAsErrors=true $CI_GRADLE_ARG_PROPERTIES - name: Compile nightly sources - run: ./gradlew compileNightlySources $CI_GRADLE_ARG_PROPERTIES + if: ${{ matrix.variant == 'nightly' }} + run: ./gradlew compileNightlySources -PallWarningsAsErrors=true $CI_GRADLE_ARG_PROPERTIES - name: Compile samples minimal + if: ${{ matrix.variant == 'samples' }} run: ./gradlew :samples:minimal:assemble $CI_GRADLE_ARG_PROPERTIES diff --git a/.github/workflows/danger.yml b/.github/workflows/danger.yml index 223a273b68..4d997ec632 100644 --- a/.github/workflows/danger.yml +++ b/.github/workflows/danger.yml @@ -1,17 +1,19 @@ name: Danger CI -on: [pull_request] +on: [pull_request, merge_group] jobs: build: runs-on: ubuntu-latest + # Don't run in the merge queue again if the branch is up to date with `develop` + if: github.event.merge_group.base_ref != 'refs/heads/develop' name: Danger main check steps: - uses: actions/checkout@v3 - run: | npm install --save-dev @babel/plugin-transform-flow-strip-types - name: Danger - uses: danger/danger-js@11.2.6 + uses: danger/danger-js@11.2.8 with: args: "--dangerfile ./tools/danger/dangerfile.js" env: diff --git a/.github/workflows/gradle-wrapper-validation.yml b/.github/workflows/gradle-wrapper-validation.yml index 7b68c0077d..c1e478b15c 100644 --- a/.github/workflows/gradle-wrapper-validation.yml +++ b/.github/workflows/gradle-wrapper-validation.yml @@ -1,12 +1,15 @@ name: "Validate Gradle Wrapper" on: - pull_request: { } + pull_request: + merge_group: push: branches: [ main, develop ] jobs: validation: name: "Validation" + # Don't run in the merge queue again if the branch is up to date with `develop` + if: github.event.merge_group.base_ref != 'refs/heads/develop' runs-on: ubuntu-latest # No concurrency required, this is a prerequisite to other actions and should run every time. steps: diff --git a/.github/workflows/maestro.yml b/.github/workflows/maestro.yml index 0349e373bb..74fb1cfc83 100644 --- a/.github/workflows/maestro.yml +++ b/.github/workflows/maestro.yml @@ -38,16 +38,14 @@ jobs: run: ./gradlew assembleDebug $CI_GRADLE_ARG_PROPERTIES env: ELEMENT_ANDROID_MAPTILER_API_KEY: ${{ secrets.MAPTILER_KEY }} - - name: Upload debug APKs - uses: actions/upload-artifact@v3 - with: - name: elementx-debug - path: | - app/build/outputs/apk/debug/*.apk + ELEMENT_ANDROID_MAPTILER_LIGHT_MAP_ID: ${{ secrets.MAPTILER_LIGHT_MAP_ID }} + ELEMENT_ANDROID_MAPTILER_DARK_MAP_ID: ${{ secrets.MAPTILER_DARK_MAP_ID }} - uses: mobile-dev-inc/action-maestro-cloud@v1.4.1 with: api-key: ${{ secrets.MAESTRO_CLOUD_API_KEY }} - app-file: app/build/outputs/apk/debug/app-universal-debug.apk + # Doc says (https://github.com/mobile-dev-inc/action-maestro-cloud#android): + # app-file should point to an x86 compatible APK file, so upload the x86_64 one (much smaller than the universal APK). + app-file: app/build/outputs/apk/debug/app-x86_64-debug.apk env: | USERNAME=maestroelement PASSWORD=${{ secrets.MATRIX_MAESTRO_ACCOUNT_PASSWORD }} diff --git a/.github/workflows/nightly.yml b/.github/workflows/nightly.yml index 95c2deb8eb..85c9ed1422 100644 --- a/.github/workflows/nightly.yml +++ b/.github/workflows/nightly.yml @@ -1,4 +1,4 @@ -name: Build and release nightly APK +name: Build and release nightly application on: workflow_dispatch: @@ -12,7 +12,7 @@ env: jobs: nightly: - name: Build and publish nightly APK to Firebase + name: Build and publish nightly bundle to Firebase runs-on: ubuntu-latest if: ${{ github.repository == 'vector-im/element-x-android' }} steps: @@ -31,18 +31,21 @@ jobs: sed 's/CHANGES\.md/CHANGES_NIGHTLY\.md/' towncrier.toml.bak > towncrier.toml rm towncrier.toml.bak yes n | towncrier build --version nightly - - name: Build and upload Nightly APK + - name: Build and upload Nightly application run: | ./gradlew assembleNightly appDistributionUploadNightly $CI_GRADLE_ARG_PROPERTIES env: ELEMENT_ANDROID_MAPTILER_API_KEY: ${{ secrets.MAPTILER_KEY }} + ELEMENT_ANDROID_MAPTILER_LIGHT_MAP_ID: ${{ secrets.MAPTILER_LIGHT_MAP_ID }} + ELEMENT_ANDROID_MAPTILER_DARK_MAP_ID: ${{ secrets.MAPTILER_DARK_MAP_ID }} ELEMENT_ANDROID_NIGHTLY_KEYID: ${{ secrets.ELEMENT_ANDROID_NIGHTLY_KEYID }} ELEMENT_ANDROID_NIGHTLY_KEYPASSWORD: ${{ secrets.ELEMENT_ANDROID_NIGHTLY_KEYPASSWORD }} ELEMENT_ANDROID_NIGHTLY_STOREPASSWORD: ${{ secrets.ELEMENT_ANDROID_NIGHTLY_STOREPASSWORD }} FIREBASE_TOKEN: ${{ secrets.ELEMENT_ANDROID_NIGHTLY_FIREBASE_TOKEN }} - name: Additionally upload Nightly APK to browserstack for testing continue-on-error: true # don't block anything by this upload failing (for now) - run: curl -u "$BROWSERSTACK_USERNAME:$BROWSERSTACK_PASSWORD" -X POST "https://api-cloud.browserstack.com/app-automate/upload" -F "file=@app/build/outputs/apk/nightly/app-universal-nightly.apk" -F "custom_id=element-x-android-nightly" + run: | + curl -u "$BROWSERSTACK_USERNAME:$BROWSERSTACK_PASSWORD" -X POST "https://api-cloud.browserstack.com/app-automate/upload" -F "file=@app/build/outputs/apk/nightly/app-universal-nightly.apk" -F "custom_id=element-x-android-nightly" env: BROWSERSTACK_USERNAME: ${{ secrets.ELEMENT_ANDROID_BROWSERSTACK_USERNAME }} BROWSERSTACK_PASSWORD: ${{ secrets.ELEMENT_ANDROID_BROWSERSTACK_ACCESS_KEY }} diff --git a/.github/workflows/nightlyReports.yml b/.github/workflows/nightlyReports.yml index ce7b763ef1..5c70a3d385 100644 --- a/.github/workflows/nightlyReports.yml +++ b/.github/workflows/nightlyReports.yml @@ -62,7 +62,7 @@ jobs: distribution: 'temurin' # See 'Supported distributions' for available options java-version: '17' - name: Configure gradle - uses: gradle/gradle-build-action@v2.6.1 + uses: gradle/gradle-build-action@v2.7.0 with: cache-read-only: ${{ github.ref != 'refs/heads/develop' }} - name: Dependency analysis diff --git a/.github/workflows/quality.yml b/.github/workflows/quality.yml index 94b8b7ff4e..1efa0ae215 100644 --- a/.github/workflows/quality.yml +++ b/.github/workflows/quality.yml @@ -2,7 +2,8 @@ name: Code Quality Checks on: workflow_dispatch: - pull_request: { } + pull_request: + merge_group: push: branches: [ main, develop ] @@ -15,6 +16,8 @@ jobs: checkScript: name: Search for forbidden patterns runs-on: ubuntu-latest + # Don't run in the merge queue again if the branch is up to date with `develop` + if: github.event.merge_group.base_ref != 'refs/heads/develop' steps: - uses: actions/checkout@v3 - name: Run code quality check suite @@ -23,6 +26,8 @@ jobs: check: name: Project Check Suite runs-on: ubuntu-latest + # Don't run in the merge queue again if the branch is up to date with `develop` + if: github.event.merge_group.base_ref != 'refs/heads/develop' # Allow all jobs on main and develop. Just one per PR. concurrency: group: ${{ github.ref == 'refs/heads/main' && format('check-main-{0}', github.sha) || github.ref == 'refs/heads/develop' && format('check-develop-{0}', github.sha) || format('check-{0}', github.ref) }} @@ -39,7 +44,7 @@ jobs: distribution: 'temurin' # See 'Supported distributions' for available options java-version: '17' - name: Configure gradle - uses: gradle/gradle-build-action@v2.6.1 + uses: gradle/gradle-build-action@v2.7.0 with: cache-read-only: ${{ github.ref != 'refs/heads/develop' }} - name: Run code quality check suite @@ -65,7 +70,7 @@ jobs: yarn add danger-plugin-lint-report --dev - name: Danger lint if: always() - uses: danger/danger-js@11.2.6 + uses: danger/danger-js@11.2.8 with: args: "--dangerfile ./tools/danger/dangerfile-lint.js" env: diff --git a/.github/workflows/recordScreenshots.yml b/.github/workflows/recordScreenshots.yml index d088b3ad94..54e35bbaff 100644 --- a/.github/workflows/recordScreenshots.yml +++ b/.github/workflows/recordScreenshots.yml @@ -24,7 +24,7 @@ jobs: java-version: '17' # Add gradle cache, this should speed up the process - name: Configure gradle - uses: gradle/gradle-build-action@v2.6.1 + uses: gradle/gradle-build-action@v2.7.0 with: cache-read-only: ${{ github.ref != 'refs/heads/develop' }} - name: Record screenshots diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml new file mode 100644 index 0000000000..8ab294bc72 --- /dev/null +++ b/.github/workflows/release.yml @@ -0,0 +1,40 @@ +name: Create release App Bundle + +on: + workflow_dispatch: + push: + branches: [ main ] + +# Enrich gradle.properties for CI/CD +env: + GRADLE_OPTS: -Dorg.gradle.jvmargs="-Xmx3072m -Dfile.encoding=UTF-8 -XX:+HeapDumpOnOutOfMemoryError" -Dkotlin.daemon.jvm.options="-Xmx2560m" -Dkotlin.incremental=false + CI_GRADLE_ARG_PROPERTIES: --stacktrace -PpreDexEnable=false --max-workers 2 --no-daemon + +jobs: + release: + name: Create App Bundle + runs-on: ubuntu-latest + concurrency: + group: ${{ github.ref == 'refs/head/main' && format('build-release-main-{0}', github.sha) }} + cancel-in-progress: true + steps: + - uses: actions/checkout@v3 + - name: Use JDK 17 + uses: actions/setup-java@v3 + with: + distribution: 'temurin' # See 'Supported distributions' for available options + java-version: '17' + - name: Configure gradle + uses: gradle/gradle-build-action@v2.7.0 + - name: Create app bundle + env: + ELEMENT_ANDROID_MAPTILER_API_KEY: ${{ secrets.MAPTILER_KEY }} + ELEMENT_ANDROID_MAPTILER_LIGHT_MAP_ID: ${{ secrets.MAPTILER_LIGHT_MAP_ID }} + ELEMENT_ANDROID_MAPTILER_DARK_MAP_ID: ${{ secrets.MAPTILER_DARK_MAP_ID }} + run: ./gradlew bundleRelease $CI_GRADLE_ARG_PROPERTIES + - name: Upload bundle as artifact + uses: actions/upload-artifact@v3 + with: + name: elementx-app-bundle-unsigned + path: | + app/build/outputs/bundle/release/app-release.aab diff --git a/.github/workflows/sonar.yml b/.github/workflows/sonar.yml new file mode 100644 index 0000000000..24e5b5ad9b --- /dev/null +++ b/.github/workflows/sonar.yml @@ -0,0 +1,51 @@ +name: Code Quality Checks + +on: + workflow_dispatch: + pull_request: + merge_group: + push: + branches: [ main, develop ] + +# Enrich gradle.properties for CI/CD +env: + GRADLE_OPTS: -Dorg.gradle.jvmargs="-Xmx3072m -Dfile.encoding=UTF-8 -XX:+HeapDumpOnOutOfMemoryError" -XX:MaxMetaspaceSize=512m -Dkotlin.daemon.jvm.options="-Xmx2g" -Dkotlin.incremental=false + CI_GRADLE_ARG_PROPERTIES: --stacktrace -PpreDexEnable=false --max-workers 2 --no-daemon --warn + +jobs: + sonar: + name: Project Check Suite + runs-on: ubuntu-latest + # Don't run in the merge queue again if the branch is up to date with `develop` + if: github.event.merge_group.base_ref != 'refs/heads/develop' + # Allow all jobs on main and develop. Just one per PR. + concurrency: + group: ${{ github.ref == 'refs/heads/main' && format('sonar-main-{0}', github.sha) || github.ref == 'refs/heads/develop' && format('sonar-develop-{0}', github.sha) || format('sonar-{0}', github.ref) }} + cancel-in-progress: true + steps: + - uses: actions/checkout@v3 + with: + # Ensure we are building the branch and not the branch after being merged on develop + # https://github.com/actions/checkout/issues/881 + ref: ${{ github.event_name == 'pull_request' && github.event.pull_request.head.sha || github.ref }} + - name: Use JDK 17 + uses: actions/setup-java@v3 + with: + distribution: 'temurin' # See 'Supported distributions' for available options + java-version: '17' + - name: Configure gradle + uses: gradle/gradle-build-action@v2.7.0 + with: + cache-read-only: ${{ github.ref != 'refs/heads/develop' }} + - name: 🔊 Publish results to Sonar + env: + SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }} + ORG_GRADLE_PROJECT_SONAR_LOGIN: ${{ secrets.SONAR_TOKEN }} + if: ${{ always() && env.SONAR_TOKEN != '' && env.ORG_GRADLE_PROJECT_SONAR_LOGIN != '' }} + run: ./gradlew sonar $CI_GRADLE_ARG_PROPERTIES + - name: Prepare Danger + if: always() + run: | + npm install --save-dev @babel/core + npm install --save-dev @babel/plugin-transform-flow-strip-types + yarn add danger-plugin-lint-report --dev diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index 04fd393e25..97a739f747 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -2,7 +2,8 @@ name: Test on: workflow_dispatch: - pull_request: { } + pull_request: + merge_group: push: branches: [ main, develop ] @@ -15,6 +16,8 @@ jobs: tests: name: Runs unit tests runs-on: ubuntu-latest + # Don't run in the merge queue again if the branch is up to date with `develop` + if: github.event.merge_group.base_ref != 'refs/heads/develop' # Allow all jobs on main and develop. Just one per PR. concurrency: @@ -33,7 +36,7 @@ jobs: distribution: 'temurin' # See 'Supported distributions' for available options java-version: '17' - name: Configure gradle - uses: gradle/gradle-build-action@v2.6.1 + uses: gradle/gradle-build-action@v2.7.0 with: cache-read-only: ${{ github.ref != 'refs/heads/develop' }} diff --git a/.github/workflows/validate-lfs.yml b/.github/workflows/validate-lfs.yml index 25fe50359c..63ded8f4e1 100644 --- a/.github/workflows/validate-lfs.yml +++ b/.github/workflows/validate-lfs.yml @@ -1,10 +1,12 @@ name: Validate Git LFS -on: [pull_request] +on: [pull_request, merge_group] jobs: build: runs-on: ubuntu-latest + # Don't run in the merge queue again if the branch is up to date with `develop` + if: github.event.merge_group.base_ref != 'refs/heads/develop' name: Validate steps: - uses: nschloe/action-cached-lfs-checkout@v1.2.1 diff --git a/.gitignore b/.gitignore index 70599626ce..0b61f0aaaf 100644 --- a/.gitignore +++ b/.gitignore @@ -38,6 +38,7 @@ captures/ # IntelliJ *.iml .idea/.name +.idea/androidTestResultsUserPreferences.xml .idea/assetWizardSettings.xml .idea/compiler.xml .idea/deploymentTargetDropDown.xml diff --git a/.idea/dictionaries/shared.xml b/.idea/dictionaries/shared.xml index aafe02a2c8..2fc10f455b 100644 --- a/.idea/dictionaries/shared.xml +++ b/.idea/dictionaries/shared.xml @@ -8,6 +8,7 @@ measurables onboarding placeables + posthog showkase snackbar swipeable diff --git a/.maestro/README.md b/.maestro/README.md index cd1f0658a7..9d9090744c 100644 --- a/.maestro/README.md +++ b/.maestro/README.md @@ -18,7 +18,7 @@ To setup, please refer at [https://maestro.mobile.dev](https://maestro.mobile.de From root dir of the project -*Note: Since ElementX does not allow account creation nor room creation, we have to use an existing account with an existing room to run maestro test suite. So to run locally, please replace `user` and `123` with your test matrix.org account credentials, and `my room` with one of a room this account has join. Note that the test will send messages to this room.* +*Note: Since Element X does not allow account creation, we have to use an existing account to run maestro test suite. So to run locally, please replace `user` and `123` with your test matrix.org account credentials, and `my room` with one of a room this account has joined. Note that the test will send messages to this room.* ```shell maestro test \ @@ -39,7 +39,7 @@ Test result will be printed on the console, and screenshots will be generated at Tests are yaml files. Generally each yaml file should leave the app in the same screen than at the beginning. -Start the ElementX app and run this command to help writing test. +Start the Element X app and run this command to help writing test. ```shell maestro studio diff --git a/CHANGES.md b/CHANGES.md index e04dbb63c8..03766ed66b 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -1,3 +1,24 @@ +Changes in Element X v0.1.2 (2023-08-16) +======================================== + +Bugfixes 🐛 +---------- + - Filter push notifications using push rules. ([#640](https://github.com/vector-im/element-x-android/issues/640)) + - Use `for` instead of `forEach` in `DefaultDiffCacheInvalidator` to improve performance. ([#1035](https://github.com/vector-im/element-x-android/issues/1035)) + +In development 🚧 +---------------- + - [Poll] Render start event in the timeline ([#1031](https://github.com/vector-im/element-x-android/issues/1031)) + +Other changes +------------- + - Add Button component based on Compound designs ([#1021](https://github.com/vector-im/element-x-android/issues/1021)) + - Compound: implement dialogs. ([#1043](https://github.com/vector-im/element-x-android/issues/1043)) + - Compound: customise `IconButton` component. ([#1049](https://github.com/vector-im/element-x-android/issues/1049)) + - Compound: implement `DropdownMenu` customisations. ([#1050](https://github.com/vector-im/element-x-android/issues/1050)) + - Compound: implement Snackbar component. ([#1054](https://github.com/vector-im/element-x-android/issues/1054)) + + Changes in Element X v0.1.0 (2023-07-19) ======================================== diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index f50c8f2a89..d83826f9f1 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -13,6 +13,7 @@ * [Kotlin](#kotlin) * [Changelog](#changelog) * [Code quality](#code-quality) + * [detekt](#detekt) * [ktlint](#ktlint) * [knit](#knit) * [lint](#lint) @@ -50,7 +51,7 @@ Note: please make sure that the configuration is `app` and not `samples.minimal` ## Strings -The strings of the project are managed externally using [https://localazy.com](https://localazy.com) and shared with ElementX iOS. +The strings of the project are managed externally using [https://localazy.com](https://localazy.com) and shared with Element X iOS. ### I want to add new strings to the project @@ -60,14 +61,12 @@ Please follow the naming rules for the key. More details in [the dedicated secti ### I want to help translating Element -Please note that the Localazy project is not open yet for external contributions. - To help translating, please go to [https://localazy.com/p/element](https://localazy.com/p/element). -- If you want to fix an issue with an English string, please open an issue on the github project of ElementX (Android or iOS). Only the core team can modify or add English strings. +- If you want to fix an issue with an English string, please open an issue on the github project of Element X (Android or iOS). Only the core team can modify or add English strings. - If you want to fix an issue in other languages, or add a missing translation, or even add a new language, please go to [https://localazy.com/p/element](https://localazy.com/p/element). -More informations can be found [in this README.md](./tools/localazy/README.md). +More information can be found [in this README.md](./tools/localazy/README.md). ## I want to submit a PR to fix an issue @@ -101,11 +100,17 @@ See https://github.com/twisted/towncrier#news-fragments if you need more details Make sure the following commands execute without any error:
-./gradlew check
+./tools/quality/check.sh
 
Some separate commands can also be run, see below. +#### detekt + +
+./gradlew detekt
+
+ #### ktlint
@@ -153,7 +158,7 @@ Make sure the following commands execute without any error:
 
 ### Tests
 
-Element X is currently supported on Android Lollipop (API 21+): please test your change on an Android device (or Android emulator) running with API 21. Many issues can happen (including crashes) on older devices.
+Element X is currently supported on Android Marshmallow (API 23+): please test your change on an Android device (or Android emulator) running with API 23. Many issues can happen (including crashes) on older devices.
 Also, if possible, please test your change on a real device. Testing on Android emulator may not be sufficient.
 
 You should consider adding Unit tests with your PR, and also integration tests (AndroidTest). Please refer to [this document](./docs/integration_tests.md) to install and run the integration test environment.
@@ -166,7 +171,18 @@ For instance, when updating the image `src` of an ImageView, please also conside
 
 ### Jetpack Compose
 
-When adding or editing `@Composable`, make sure that you create a `@Preview` function, with suffix `Preview`. This will also create a UI test automatically.
+When adding or editing `@Composable`, make sure that you create an internal function annotated with `@DayNightPreviews`, with a name suffixed by `Preview`, and having `ElementPreview` as the root composable.
+
+Example:
+```kotlin
+@DayNightPreviews
+@Composable
+internal fun PinIconPreview() = ElementPreview {
+    PinIcon()
+}
+```
+
+This will allow to preview the composable in both light and dark mode in Android Studio. This will also automatically add UI tests. The GitHub action [Record screenshots](https://github.com/vector-im/element-x-android/actions/workflows/recordScreenshots.yml) has to be run to record the new screenshots. The PR reviewer can trigger this for you if you're not part of the core team. 
 
 ### Authors
 
diff --git a/README.md b/README.md
index e31acf87b8..f24efcd828 100644
--- a/README.md
+++ b/README.md
@@ -3,14 +3,18 @@
 [![Vulnerabilities](https://sonarcloud.io/api/project_badges/measure?project=vector-im_element-x-android&metric=vulnerabilities)](https://sonarcloud.io/summary/new_code?id=vector-im_element-x-android)
 [![Bugs](https://sonarcloud.io/api/project_badges/measure?project=vector-im_element-x-android&metric=bugs)](https://sonarcloud.io/summary/new_code?id=vector-im_element-x-android)
 [![codecov](https://codecov.io/github/vector-im/element-x-android/branch/develop/graph/badge.svg?token=ecwvia7amV)](https://codecov.io/github/vector-im/element-x-android)
-[![Element Android Matrix room #element-android:matrix.org](https://img.shields.io/matrix/element-android:matrix.org.svg?label=%23element-android:matrix.org&logo=matrix&server_fqdn=matrix.org)](https://matrix.to/#/#element-android:matrix.org)
-[![Weblate](https://translate.element.io/widgets/element-android/-/svg-badge.svg)](https://translate.element.io/engage/element-android/?utm_source=widget)
+[![Element X_Android Matrix room #element-x-android:matrix.org](https://img.shields.io/matrix/element-x-android:matrix.org.svg?label=%23element-x-android:matrix.org&logo=matrix&server_fqdn=matrix.org)](https://matrix.to/#/#element-x-android:matrix.org)
+[![Localazy](https://img.shields.io/endpoint?url=https%3A%2F%2Fconnect.localazy.com%2Fstatus%2Felement%2Fdata%3Fcontent%3Dall%26title%3Dlocalazy%26logo%3Dtrue)](https://localazy.com/p/element)
 
-# element-x-android
+# Element X Android
 
-ElementX Android is a [Matrix](https://matrix.org/) Android Client provided by [Element](https://element.io/). This app is currently in a pre-alpha release stage with only basic functionality.
+Element X Android is a [Matrix](https://matrix.org/) Android Client provided by [element.io](https://element.io/). This app is currently in a pre-alpha release stage with only basic functionalities.
 
-The application is a total rewrite of [Element-Android](https://github.com/vector-im/element-android) using the [Matrix Rust SDK](https://github.com/matrix-org/matrix-rust-sdk) underneath and targeting devices running Android 6+. The UI layer is written using Jetpack compose.
+The application is a total rewrite of [Element-Android](https://github.com/vector-im/element-android) using the [Matrix Rust SDK](https://github.com/matrix-org/matrix-rust-sdk) underneath and targeting devices running Android 6+. The UI layer is written using [Jetpack Compose](https://developer.android.com/jetpack/compose), and the navigation is managed using [Appyx](https://github.com/bumble-tech/appyx).
+
+Learn more about why we are building Element X in our blog post: [https://element.io/blog/element-x-experience-the-future-of-element/](https://element.io/blog/element-x-experience-the-future-of-element/).
+
+## Table of contents
 
 
 
@@ -28,24 +32,41 @@ The application is a total rewrite of [Element-Android](https://github.com/vecto
 
 Here are some early screenshots of the application:
 
-|||||
+
+
+|||||
 |-|-|-|-|
+|||||
 
 ## Rust SDK
 
-ElementX leverages the [Matrix Rust SDK](https://github.com/matrix-org/matrix-rust-sdk) through an FFI layer that the final client can directly import and use.
+Element X leverages the [Matrix Rust SDK](https://github.com/matrix-org/matrix-rust-sdk) through an FFI layer that the final client can directly import and use.
 
 We're doing this as a way to share code between platforms and while we've seen promising results it's still in the experimental stage and bound to change.
 
 ## Status
 
-This project is in work in progress. The app does not cover yet all functionalities we expect.
+This project is in work in progress. The app does not cover yet all functionalities we expect. The list of supported features can be found in [this issue](https://github.com/vector-im/element-x-android/issues/911).
 
 ## Contributing
 
-Please see our [contribution guide](CONTRIBUTING.md).
+Want to get actively involved in the project? You're more than welcome! A good way to start is to check the issues that are labelled with the [good first issue](https://github.com/vector-im/element-x-android/issues?q=is%3Aissue+is%3Aopen+label%3A%22good+first+issue%22) label. Let us know by commenting the issue that you're starting working on it.
 
-Come chat with the community in the dedicated Matrix [room](https://matrix.to/#/#element-android:matrix.org).
+But first make sure to read our [contribution guide](CONTRIBUTING.md) first.
+
+You can also come chat with the community in the Matrix [room](https://matrix.to/#/#element-x-android:matrix.org) dedicated to the project.
 
 ## Build instructions
 
@@ -54,9 +75,9 @@ Makes sure to select the `app` configuration when building (as we also have samp
 
 ## Support
 
-When you are experiencing an issue on ElementX Android, please first search in [GitHub issues](https://github.com/vector-im/element-x-android/issues)
-and then in [#element-android:matrix.org](https://matrix.to/#/#element-android:matrix.org).
-If after your research you still have a question, ask at [#element-android:matrix.org](https://matrix.to/#/#element-android:matrix.org). Otherwise feel free to create a GitHub issue if you encounter a bug or a crash, by explaining clearly in detail what happened. You can also perform bug reporting (Rageshake) from the Element application by shaking your phone or going to the application settings. This is especially recommended when you encounter a crash.
+When you are experiencing an issue on Element X Android, please first search in [GitHub issues](https://github.com/vector-im/element-x-android/issues)
+and then in [#element-x-android:matrix.org](https://matrix.to/#/#element-x-android:matrix.org).
+If after your research you still have a question, ask at [#element-x-android:matrix.org](https://matrix.to/#/#element-x-android:matrix.org). Otherwise feel free to create a GitHub issue if you encounter a bug or a crash, by explaining clearly in detail what happened. You can also perform bug reporting from the application settings. This is especially recommended when you encounter a crash.
 
 ## Copyright & License
 
diff --git a/app/build.gradle.kts b/app/build.gradle.kts
index 6a28adecf1..19bb2ea84b 100644
--- a/app/build.gradle.kts
+++ b/app/build.gradle.kts
@@ -129,6 +129,8 @@ android {
                 // "App Distribution found more than 1 output file for this variant.
                 // Please contact firebase-support@google.com for help using APK splits with App Distribution."
                 artifactPath = "$rootDir/app/build/outputs/apk/nightly/app-universal-nightly.apk"
+                // artifactType = "AAB"
+                // artifactPath = "$rootDir/app/build/outputs/bundle/nightly/app-nightly.aab"
                 // This file will be generated by the GitHub action
                 releaseNotesFile = "CHANGES_NIGHTLY.md"
                 groups = "external-testers"
diff --git a/app/src/main/kotlin/io/element/android/x/ElementXApplication.kt b/app/src/main/kotlin/io/element/android/x/ElementXApplication.kt
index ec3259fb7c..da8592771c 100644
--- a/app/src/main/kotlin/io/element/android/x/ElementXApplication.kt
+++ b/app/src/main/kotlin/io/element/android/x/ElementXApplication.kt
@@ -24,8 +24,7 @@ import io.element.android.x.di.DaggerAppComponent
 import io.element.android.x.info.logApplicationInfo
 import io.element.android.x.initializer.CrashInitializer
 import io.element.android.x.initializer.EmojiInitializer
-import io.element.android.x.initializer.MatrixInitializer
-import io.element.android.x.initializer.TimberInitializer
+import io.element.android.x.initializer.TracingInitializer
 
 class ElementXApplication : Application(), DaggerComponentOwner {
 
@@ -39,8 +38,7 @@ class ElementXApplication : Application(), DaggerComponentOwner {
         appComponent = DaggerAppComponent.factory().create(applicationContext)
         AppInitializer.getInstance(this).apply {
             initializeComponent(CrashInitializer::class.java)
-            initializeComponent(TimberInitializer::class.java)
-            initializeComponent(MatrixInitializer::class.java)
+            initializeComponent(TracingInitializer::class.java)
             initializeComponent(EmojiInitializer::class.java)
         }
         logApplicationInfo()
diff --git a/app/src/main/kotlin/io/element/android/x/di/AppBindings.kt b/app/src/main/kotlin/io/element/android/x/di/AppBindings.kt
index 4d75d8601e..5fb3523d6e 100644
--- a/app/src/main/kotlin/io/element/android/x/di/AppBindings.kt
+++ b/app/src/main/kotlin/io/element/android/x/di/AppBindings.kt
@@ -17,11 +17,15 @@
 package io.element.android.x.di
 
 import com.squareup.anvil.annotations.ContributesTo
+import io.element.android.features.rageshake.api.reporter.BugReporter
 import io.element.android.libraries.designsystem.utils.SnackbarDispatcher
 import io.element.android.libraries.di.AppScope
+import io.element.android.libraries.matrix.api.tracing.TracingService
 
 @ContributesTo(AppScope::class)
 interface AppBindings {
     fun mainDaggerComponentOwner(): MainDaggerComponentsOwner
     fun snackbarDispatcher(): SnackbarDispatcher
+    fun tracingService(): TracingService
+    fun bugReporter(): BugReporter
 }
diff --git a/app/src/main/kotlin/io/element/android/x/icon/IconPreview.kt b/app/src/main/kotlin/io/element/android/x/icon/IconPreview.kt
index 49c2cc5782..52e3af1aab 100644
--- a/app/src/main/kotlin/io/element/android/x/icon/IconPreview.kt
+++ b/app/src/main/kotlin/io/element/android/x/icon/IconPreview.kt
@@ -28,7 +28,7 @@ import io.element.android.x.R
 
 @Preview
 @Composable
-fun IconPreview(
+internal fun IconPreview(
     modifier: Modifier = Modifier,
 ) {
     Box(modifier = modifier) {
@@ -39,7 +39,7 @@ fun IconPreview(
 
 @Preview
 @Composable
-fun RoundIconPreview(
+internal fun RoundIconPreview(
     modifier: Modifier = Modifier,
 ) {
     Box(modifier = modifier.clip(shape = CircleShape)) {
diff --git a/app/src/main/kotlin/io/element/android/x/initializer/MatrixInitializer.kt b/app/src/main/kotlin/io/element/android/x/initializer/MatrixInitializer.kt
deleted file mode 100644
index 5eebc88756..0000000000
--- a/app/src/main/kotlin/io/element/android/x/initializer/MatrixInitializer.kt
+++ /dev/null
@@ -1,36 +0,0 @@
-/*
- * Copyright (c) 2022 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
- *
- *     http://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.x.initializer
-
-import android.content.Context
-import androidx.startup.Initializer
-import io.element.android.libraries.matrix.impl.tracing.setupTracing
-import io.element.android.libraries.matrix.api.tracing.TracingConfigurations
-import io.element.android.x.BuildConfig
-
-class MatrixInitializer : Initializer {
-
-    override fun create(context: Context) {
-        if (BuildConfig.DEBUG) {
-            setupTracing(TracingConfigurations.debug)
-        } else {
-            setupTracing(TracingConfigurations.release)
-        }
-    }
-
-    override fun dependencies(): List>> = listOf(TimberInitializer::class.java)
-}
diff --git a/app/src/main/kotlin/io/element/android/x/initializer/TracingInitializer.kt b/app/src/main/kotlin/io/element/android/x/initializer/TracingInitializer.kt
new file mode 100644
index 0000000000..068d439994
--- /dev/null
+++ b/app/src/main/kotlin/io/element/android/x/initializer/TracingInitializer.kt
@@ -0,0 +1,57 @@
+/*
+ * Copyright (c) 2022 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
+ *
+ *     http://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.x.initializer
+
+import android.content.Context
+import androidx.startup.Initializer
+import io.element.android.libraries.architecture.bindings
+import io.element.android.libraries.matrix.api.tracing.TracingConfiguration
+import io.element.android.libraries.matrix.api.tracing.TracingFilterConfigurations
+import io.element.android.libraries.matrix.api.tracing.WriteToFilesConfiguration
+import io.element.android.x.BuildConfig
+import io.element.android.x.di.AppBindings
+import timber.log.Timber
+
+class TracingInitializer : Initializer {
+
+    override fun create(context: Context) {
+        val appBindings = context.bindings()
+        val tracingService = appBindings.tracingService()
+        val bugReporter = appBindings.bugReporter()
+        Timber.plant(tracingService.createTimberTree())
+        val tracingConfiguration = if (BuildConfig.DEBUG) {
+            TracingConfiguration(
+                filterConfiguration = TracingFilterConfigurations.debug,
+                writesToLogcat = true,
+                writesToFilesConfiguration = WriteToFilesConfiguration.Disabled
+            )
+        } else {
+            TracingConfiguration(
+                filterConfiguration = TracingFilterConfigurations.release,
+                writesToLogcat = false,
+                writesToFilesConfiguration = WriteToFilesConfiguration.Enabled(
+                    directory = bugReporter.logDirectory().absolutePath,
+                    filenamePrefix = "logs"
+                )
+            )
+        }
+        bugReporter.cleanLogDirectoryIfNeeded()
+        tracingService.setupTracing(tracingConfiguration)
+    }
+
+    override fun dependencies(): List>> = mutableListOf()
+}
diff --git a/appnav/build.gradle.kts b/appnav/build.gradle.kts
index 6abc3c656b..cffd318fb1 100644
--- a/appnav/build.gradle.kts
+++ b/appnav/build.gradle.kts
@@ -65,6 +65,8 @@ dependencies {
     testImplementation(libs.test.truth)
     testImplementation(libs.test.turbine)
     testImplementation(projects.libraries.matrix.test)
+    testImplementation(projects.features.networkmonitor.test)
+    testImplementation(projects.tests.testutils)
     testImplementation(projects.features.rageshake.test)
     testImplementation(projects.features.rageshake.impl)
     testImplementation(projects.services.appnavstate.test)
diff --git a/appnav/src/main/kotlin/io/element/android/appnav/LoggedInEventProcessor.kt b/appnav/src/main/kotlin/io/element/android/appnav/LoggedInEventProcessor.kt
index 64c9ec7c4f..e55f059d14 100644
--- a/appnav/src/main/kotlin/io/element/android/appnav/LoggedInEventProcessor.kt
+++ b/appnav/src/main/kotlin/io/element/android/appnav/LoggedInEventProcessor.kt
@@ -58,7 +58,8 @@ class LoggedInEventProcessor @Inject constructor(
                 .filter { it }
                 .onEach {
                     displayMessage(CommonStrings.common_verification_complete)
-                }.launchIn(this)
+                }
+                .launchIn(this)
         }
     }
 
diff --git a/appnav/src/main/kotlin/io/element/android/appnav/LoggedInFlowNode.kt b/appnav/src/main/kotlin/io/element/android/appnav/LoggedInFlowNode.kt
index 4130e5da23..7943151a5e 100644
--- a/appnav/src/main/kotlin/io/element/android/appnav/LoggedInFlowNode.kt
+++ b/appnav/src/main/kotlin/io/element/android/appnav/LoggedInFlowNode.kt
@@ -44,14 +44,14 @@ import io.element.android.appnav.loggedin.LoggedInNode
 import io.element.android.appnav.room.RoomFlowNode
 import io.element.android.appnav.room.RoomLoadedFlowNode
 import io.element.android.features.createroom.api.CreateRoomEntryPoint
+import io.element.android.features.ftue.api.FtueEntryPoint
+import io.element.android.features.ftue.api.state.FtueState
 import io.element.android.features.invitelist.api.InviteListEntryPoint
 import io.element.android.features.networkmonitor.api.NetworkMonitor
 import io.element.android.features.networkmonitor.api.NetworkStatus
 import io.element.android.features.preferences.api.PreferencesEntryPoint
 import io.element.android.features.roomlist.api.RoomListEntryPoint
 import io.element.android.features.verifysession.api.VerifySessionEntryPoint
-import io.element.android.features.ftue.api.FtueEntryPoint
-import io.element.android.features.ftue.api.state.FtueState
 import io.element.android.libraries.architecture.BackstackNode
 import io.element.android.libraries.architecture.NodeInputs
 import io.element.android.libraries.architecture.animation.rememberDefaultTransitionHandler
@@ -69,10 +69,12 @@ import io.element.android.libraries.matrix.ui.di.MatrixUIBindings
 import io.element.android.libraries.push.api.notifications.NotificationDrawerManager
 import io.element.android.services.appnavstate.api.AppNavigationStateService
 import kotlinx.coroutines.CoroutineScope
+import kotlinx.coroutines.FlowPreview
 import kotlinx.coroutines.flow.combine
-import kotlinx.coroutines.flow.distinctUntilChanged
+import kotlinx.coroutines.flow.debounce
 import kotlinx.coroutines.launch
 import kotlinx.parcelize.Parcelize
+import timber.log.Timber
 
 @ContributesNode(AppScope::class)
 class LoggedInFlowNode @AssistedInject constructor(
@@ -100,13 +102,13 @@ class LoggedInFlowNode @AssistedInject constructor(
 ) {
 
     interface Callback : Plugin {
-        fun onOpenBugReport() = Unit
+        fun onOpenBugReport()
     }
 
     interface LifecycleCallback : NodeLifecycleCallback {
-        fun onFlowCreated(identifier: String, client: MatrixClient) = Unit
+        fun onFlowCreated(identifier: String, client: MatrixClient)
 
-        fun onFlowReleased(identifier: String, client: MatrixClient) = Unit
+        fun onFlowReleased(identifier: String, client: MatrixClient)
     }
 
     data class Inputs(
@@ -123,7 +125,6 @@ class LoggedInFlowNode @AssistedInject constructor(
 
     override fun onBuilt() {
         super.onBuilt()
-
         lifecycle.subscribe(
             onCreate = {
                 plugins().forEach { it.onFlowCreated(id, inputs.matrixClient) }
@@ -138,14 +139,12 @@ class LoggedInFlowNode @AssistedInject constructor(
                     backstack.push(NavTarget.Ftue)
                 }
             },
-            onResume = {
-                lifecycleScope.launch {
-                    syncService.startSync()
+            onStop = {
+                //Counterpart startSync is done in observeSyncStateAndNetworkStatus method.
+                coroutineScope.launch {
+                    syncService.stopSync()
                 }
             },
-            onPause = {
-                syncService.stopSync()
-            },
             onDestroy = {
                 plugins().forEach { it.onFlowReleased(id, inputs.matrixClient) }
                 appNavigationStateService.onLeavingSpace(id)
@@ -153,22 +152,23 @@ class LoggedInFlowNode @AssistedInject constructor(
                 loggedInFlowProcessor.stopObserving()
             }
         )
-
         observeSyncStateAndNetworkStatus()
     }
 
+    @OptIn(FlowPreview::class)
     private fun observeSyncStateAndNetworkStatus() {
         lifecycleScope.launch {
-            repeatOnLifecycle(Lifecycle.State.RESUMED) {
+            repeatOnLifecycle(Lifecycle.State.STARTED) {
                 combine(
-                    syncService.syncState,
+                    // small debounce to avoid spamming startSync when the state is changing quickly in case of error.
+                    syncService.syncState.debounce(100),
                     networkMonitor.connectivity
                 ) { syncState, networkStatus ->
-                    syncState == SyncState.Error && networkStatus == NetworkStatus.Online
+                    Pair(syncState, networkStatus)
                 }
-                    .distinctUntilChanged()
-                    .collect { restartSync ->
-                        if (restartSync) {
+                    .collect { (syncState, networkStatus) ->
+                        Timber.d("Sync state: $syncState, network status: $networkStatus")
+                        if (syncState != SyncState.Running && networkStatus == NetworkStatus.Online) {
                             syncService.startSync()
                         }
                     }
@@ -305,7 +305,8 @@ class LoggedInFlowNode @AssistedInject constructor(
                         override fun onFtueFlowFinished() {
                             backstack.pop()
                         }
-                    }).build()
+                    })
+                    .build()
             }
         }
     }
@@ -350,3 +351,4 @@ class LoggedInFlowNode @AssistedInject constructor(
         backstack.push(NavTarget.InviteList)
     }
 }
+
diff --git a/appnav/src/main/kotlin/io/element/android/appnav/intent/IntentResolver.kt b/appnav/src/main/kotlin/io/element/android/appnav/intent/IntentResolver.kt
index 6a3d8ff9dd..b567395c1e 100644
--- a/appnav/src/main/kotlin/io/element/android/appnav/intent/IntentResolver.kt
+++ b/appnav/src/main/kotlin/io/element/android/appnav/intent/IntentResolver.kt
@@ -21,8 +21,6 @@ import io.element.android.features.login.api.oidc.OidcAction
 import io.element.android.features.login.api.oidc.OidcIntentResolver
 import io.element.android.libraries.deeplink.DeeplinkData
 import io.element.android.libraries.deeplink.DeeplinkParser
-import io.element.android.libraries.matrix.api.core.RoomId
-import io.element.android.libraries.matrix.api.core.SessionId
 import timber.log.Timber
 import javax.inject.Inject
 
diff --git a/appnav/src/main/kotlin/io/element/android/appnav/loggedin/LoggedInPresenter.kt b/appnav/src/main/kotlin/io/element/android/appnav/loggedin/LoggedInPresenter.kt
index 8910cc3976..6d386a17e5 100644
--- a/appnav/src/main/kotlin/io/element/android/appnav/loggedin/LoggedInPresenter.kt
+++ b/appnav/src/main/kotlin/io/element/android/appnav/loggedin/LoggedInPresenter.kt
@@ -21,16 +21,27 @@ import android.os.Build
 import androidx.compose.runtime.Composable
 import androidx.compose.runtime.LaunchedEffect
 import androidx.compose.runtime.collectAsState
+import androidx.compose.runtime.getValue
+import androidx.compose.runtime.mutableStateOf
+import androidx.compose.runtime.remember
+import androidx.compose.runtime.setValue
+import io.element.android.features.networkmonitor.api.NetworkMonitor
+import io.element.android.features.networkmonitor.api.NetworkStatus
 import io.element.android.libraries.architecture.Presenter
 import io.element.android.libraries.matrix.api.MatrixClient
+import io.element.android.libraries.matrix.api.roomlist.RoomListService
 import io.element.android.libraries.permissions.api.PermissionsPresenter
 import io.element.android.libraries.permissions.noop.NoopPermissionsPresenter
 import io.element.android.libraries.push.api.PushService
+import kotlinx.coroutines.delay
 import javax.inject.Inject
 
+private const val DELAY_BEFORE_SHOWING_SYNC_SPINNER_IN_MILLIS = 1500L
+
 class LoggedInPresenter @Inject constructor(
     private val matrixClient: MatrixClient,
     private val permissionsPresenterFactory: PermissionsPresenter.Factory,
+    private val networkMonitor: NetworkMonitor,
     private val pushService: PushService,
 ) : Presenter {
 
@@ -53,18 +64,25 @@ class LoggedInPresenter @Inject constructor(
             pushService.registerWith(matrixClient, pushProvider, distributor)
         }
 
-        val syncState = matrixClient.syncService().syncState.collectAsState()
+        val roomListState by matrixClient.roomListService.state.collectAsState()
+        val networkStatus by networkMonitor.connectivity.collectAsState()
         val permissionsState = postNotificationPermissionsPresenter.present()
-
-        // fun handleEvents(event: LoggedInEvents) {
-        //     when (event) {
-        //     }
-        // }
-
+        var showSyncSpinner by remember {
+            mutableStateOf(false)
+        }
+        LaunchedEffect(roomListState, networkStatus) {
+            showSyncSpinner = when {
+                networkStatus == NetworkStatus.Offline -> false
+                roomListState == RoomListService.State.Running -> false
+                else -> {
+                    delay(DELAY_BEFORE_SHOWING_SYNC_SPINNER_IN_MILLIS)
+                    true
+                }
+            }
+        }
         return LoggedInState(
-            syncState = syncState.value,
+            showSyncSpinner = showSyncSpinner,
             permissionsState = permissionsState,
-            // eventSink = ::handleEvents
         )
     }
 }
diff --git a/appnav/src/main/kotlin/io/element/android/appnav/loggedin/LoggedInState.kt b/appnav/src/main/kotlin/io/element/android/appnav/loggedin/LoggedInState.kt
index 075242cddb..bb06952a50 100644
--- a/appnav/src/main/kotlin/io/element/android/appnav/loggedin/LoggedInState.kt
+++ b/appnav/src/main/kotlin/io/element/android/appnav/loggedin/LoggedInState.kt
@@ -16,11 +16,9 @@
 
 package io.element.android.appnav.loggedin
 
-import io.element.android.libraries.matrix.api.sync.SyncState
 import io.element.android.libraries.permissions.api.PermissionsState
 
 data class LoggedInState(
-    val syncState: SyncState,
+    val showSyncSpinner: Boolean,
     val permissionsState: PermissionsState,
-    // val eventSink: (LoggedInEvents) -> Unit
 )
diff --git a/appnav/src/main/kotlin/io/element/android/appnav/loggedin/LoggedInStateProvider.kt b/appnav/src/main/kotlin/io/element/android/appnav/loggedin/LoggedInStateProvider.kt
index e8a8a4762c..3cfb03f123 100644
--- a/appnav/src/main/kotlin/io/element/android/appnav/loggedin/LoggedInStateProvider.kt
+++ b/appnav/src/main/kotlin/io/element/android/appnav/loggedin/LoggedInStateProvider.kt
@@ -17,22 +17,20 @@
 package io.element.android.appnav.loggedin
 
 import androidx.compose.ui.tooling.preview.PreviewParameterProvider
-import io.element.android.libraries.matrix.api.sync.SyncState
 import io.element.android.libraries.permissions.api.createDummyPostNotificationPermissionsState
 
 open class LoggedInStateProvider : PreviewParameterProvider {
     override val values: Sequence
         get() = sequenceOf(
-            aLoggedInState(),
-            aLoggedInState(syncState = SyncState.Idle),
+            aLoggedInState(false),
+            aLoggedInState(true),
             // Add other state here
         )
 }
 
 fun aLoggedInState(
-    syncState: SyncState = SyncState.Running,
+    showSyncSpinner: Boolean = true,
 ) = LoggedInState(
-    syncState = syncState,
+    showSyncSpinner = showSyncSpinner,
     permissionsState = createDummyPostNotificationPermissionsState(),
-    // eventSink = {}
 )
diff --git a/appnav/src/main/kotlin/io/element/android/appnav/loggedin/LoggedInView.kt b/appnav/src/main/kotlin/io/element/android/appnav/loggedin/LoggedInView.kt
index 60784ea4ed..0ade93a795 100644
--- a/appnav/src/main/kotlin/io/element/android/appnav/loggedin/LoggedInView.kt
+++ b/appnav/src/main/kotlin/io/element/android/appnav/loggedin/LoggedInView.kt
@@ -47,7 +47,7 @@ fun LoggedInView(
             modifier = Modifier
                 .padding(top = 8.dp)
                 .align(Alignment.TopCenter),
-            syncState = state.syncState,
+            isVisible = state.showSyncSpinner,
         )
         PermissionsView(
             state = state.permissionsState,
@@ -58,7 +58,7 @@ fun LoggedInView(
 
 @DayNightPreviews
 @Composable
-fun LoggedInViewPreview(@PreviewParameter(LoggedInStateProvider::class) state: LoggedInState) = ElementPreview {
+internal fun LoggedInViewPreview(@PreviewParameter(LoggedInStateProvider::class) state: LoggedInState) = ElementPreview {
     LoggedInView(
         state = state
     )
diff --git a/appnav/src/main/kotlin/io/element/android/appnav/loggedin/SyncStateView.kt b/appnav/src/main/kotlin/io/element/android/appnav/loggedin/SyncStateView.kt
index 5108bb8716..6d045a431a 100644
--- a/appnav/src/main/kotlin/io/element/android/appnav/loggedin/SyncStateView.kt
+++ b/appnav/src/main/kotlin/io/element/android/appnav/loggedin/SyncStateView.kt
@@ -38,19 +38,18 @@ import io.element.android.libraries.designsystem.preview.ElementPreview
 import io.element.android.libraries.designsystem.theme.components.CircularProgressIndicator
 import io.element.android.libraries.designsystem.theme.components.Surface
 import io.element.android.libraries.designsystem.theme.components.Text
-import io.element.android.libraries.matrix.api.sync.SyncState
 import io.element.android.libraries.theme.ElementTheme
 import io.element.android.libraries.ui.strings.CommonStrings
 
 @Composable
 fun SyncStateView(
-    syncState: SyncState,
+    isVisible: Boolean,
     modifier: Modifier = Modifier
 ) {
     val animationSpec = spring(stiffness = 500F)
     AnimatedVisibility(
         modifier = modifier,
-        visible = syncState.mustBeVisible(),
+        visible = isVisible,
         enter = fadeIn(animationSpec = animationSpec),
         exit = fadeOut(animationSpec = animationSpec),
     ) {
@@ -60,15 +59,15 @@ fun SyncStateView(
         ) {
             Row(
                 modifier = Modifier
-                    .background(color = ElementTheme.colors.bgSubtleSecondary)
-                    .padding(horizontal = 24.dp, vertical = 10.dp),
+                        .background(color = ElementTheme.colors.bgSubtleSecondary)
+                        .padding(horizontal = 24.dp, vertical = 10.dp),
                 verticalAlignment = Alignment.CenterVertically,
                 horizontalArrangement = Arrangement.spacedBy(10.dp)
             ) {
                 CircularProgressIndicator(
                     modifier = Modifier
-                        .progressSemantics()
-                        .size(12.dp),
+                            .progressSemantics()
+                            .size(12.dp),
                     color = ElementTheme.colors.textPrimary,
                     strokeWidth = 1.5.dp,
                 )
@@ -82,20 +81,13 @@ fun SyncStateView(
     }
 }
 
-private fun SyncState.mustBeVisible() = when (this) {
-    SyncState.Idle -> true /* Cold start of the app */
-    SyncState.Running -> false
-    SyncState.Error -> false /* In this case, the network error banner can be displayed */
-    SyncState.Terminated -> true /* The app is resumed and the sync is started again */
-}
-
 @DayNightPreviews
 @Composable
-fun SyncStateViewPreview() = ElementPreview {
+internal fun SyncStateViewPreview() = ElementPreview {
     // Add a box to see the shadow
     Box(modifier = Modifier.padding(24.dp)) {
         SyncStateView(
-            syncState = SyncState.Idle
+            isVisible = true
         )
     }
 }
diff --git a/appnav/src/main/kotlin/io/element/android/appnav/room/LoadingRoomNodeView.kt b/appnav/src/main/kotlin/io/element/android/appnav/room/LoadingRoomNodeView.kt
index e8d68a3e94..558f64424a 100644
--- a/appnav/src/main/kotlin/io/element/android/appnav/room/LoadingRoomNodeView.kt
+++ b/appnav/src/main/kotlin/io/element/android/appnav/room/LoadingRoomNodeView.kt
@@ -16,19 +16,13 @@
 
 package io.element.android.appnav.room
 
-import androidx.compose.foundation.background
 import androidx.compose.foundation.layout.Box
 import androidx.compose.foundation.layout.Column
 import androidx.compose.foundation.layout.ExperimentalLayoutApi
-import androidx.compose.foundation.layout.Row
-import androidx.compose.foundation.layout.Spacer
 import androidx.compose.foundation.layout.WindowInsets
 import androidx.compose.foundation.layout.consumeWindowInsets
 import androidx.compose.foundation.layout.fillMaxSize
 import androidx.compose.foundation.layout.padding
-import androidx.compose.foundation.layout.size
-import androidx.compose.foundation.layout.width
-import androidx.compose.foundation.shape.CircleShape
 import androidx.compose.material3.ExperimentalMaterial3Api
 import androidx.compose.runtime.Composable
 import androidx.compose.ui.Alignment
@@ -37,9 +31,8 @@ import androidx.compose.ui.res.stringResource
 import androidx.compose.ui.tooling.preview.Preview
 import androidx.compose.ui.tooling.preview.PreviewParameter
 import androidx.compose.ui.unit.dp
-import androidx.compose.ui.unit.sp
 import io.element.android.features.networkmonitor.api.ui.ConnectivityIndicatorView
-import io.element.android.libraries.designsystem.atomic.atoms.PlaceholderAtom
+import io.element.android.libraries.designsystem.atomic.molecules.IconTitlePlaceholdersRowMolecule
 import io.element.android.libraries.designsystem.components.avatar.AvatarSize
 import io.element.android.libraries.designsystem.components.button.BackButton
 import io.element.android.libraries.designsystem.preview.ElementPreviewDark
@@ -48,7 +41,6 @@ import io.element.android.libraries.designsystem.theme.components.CircularProgre
 import io.element.android.libraries.designsystem.theme.components.Scaffold
 import io.element.android.libraries.designsystem.theme.components.Text
 import io.element.android.libraries.designsystem.theme.components.TopAppBar
-import io.element.android.libraries.designsystem.theme.placeholderBackground
 import io.element.android.libraries.theme.ElementTheme
 import io.element.android.libraries.ui.strings.CommonStrings
 
@@ -103,20 +95,7 @@ private fun LoadingRoomTopBar(
             BackButton(onClick = onBackClicked)
         },
         title = {
-            Row(
-                verticalAlignment = Alignment.CenterVertically
-            ) {
-                Box(
-                    modifier = Modifier
-                        .size(AvatarSize.TimelineRoom.dp)
-                        .align(Alignment.CenterVertically)
-                        .background(color = ElementTheme.colors.placeholderBackground, shape = CircleShape)
-                )
-                Spacer(modifier = Modifier.width(8.dp))
-                PlaceholderAtom(width = 20.dp, height = 7.dp)
-                Spacer(modifier = Modifier.width(7.dp))
-                PlaceholderAtom(width = 45.dp, height = 7.dp)
-            }
+            IconTitlePlaceholdersRowMolecule(iconSize = AvatarSize.TimelineRoom.dp)
         },
         windowInsets = WindowInsets(0.dp),
     )
@@ -124,12 +103,12 @@ private fun LoadingRoomTopBar(
 
 @Preview
 @Composable
-fun LoadingRoomNodeViewLightPreview(@PreviewParameter(LoadingRoomStateProvider::class) state: LoadingRoomState) =
+internal fun LoadingRoomNodeViewLightPreview(@PreviewParameter(LoadingRoomStateProvider::class) state: LoadingRoomState) =
     ElementPreviewLight { ContentToPreview(state) }
 
 @Preview
 @Composable
-fun LoadingRoomNodeViewDarkPreview(@PreviewParameter(LoadingRoomStateProvider::class) state: LoadingRoomState) =
+internal fun LoadingRoomNodeViewDarkPreview(@PreviewParameter(LoadingRoomStateProvider::class) state: LoadingRoomState) =
     ElementPreviewDark { ContentToPreview(state) }
 
 @Composable
diff --git a/appnav/src/main/kotlin/io/element/android/appnav/room/RoomFlowNode.kt b/appnav/src/main/kotlin/io/element/android/appnav/room/RoomFlowNode.kt
index 20ec9f48b4..661d3c5433 100644
--- a/appnav/src/main/kotlin/io/element/android/appnav/room/RoomFlowNode.kt
+++ b/appnav/src/main/kotlin/io/element/android/appnav/room/RoomFlowNode.kt
@@ -96,7 +96,8 @@ class RoomFlowNode @AssistedInject constructor(
                 } else {
                     backstack.newRoot(NavTarget.Loading)
                 }
-            }.launchIn(lifecycleScope)
+            }
+            .launchIn(lifecycleScope)
     }
 
     override fun resolve(navTarget: NavTarget, buildContext: BuildContext): Node {
diff --git a/appnav/src/main/kotlin/io/element/android/appnav/room/RoomLoadedFlowNode.kt b/appnav/src/main/kotlin/io/element/android/appnav/room/RoomLoadedFlowNode.kt
index 73a8579b07..d00c4791f7 100644
--- a/appnav/src/main/kotlin/io/element/android/appnav/room/RoomLoadedFlowNode.kt
+++ b/appnav/src/main/kotlin/io/element/android/appnav/room/RoomLoadedFlowNode.kt
@@ -20,6 +20,7 @@ import android.os.Parcelable
 import androidx.compose.runtime.Composable
 import androidx.compose.runtime.DisposableEffect
 import androidx.compose.ui.Modifier
+import androidx.lifecycle.Lifecycle
 import androidx.lifecycle.lifecycleScope
 import com.bumble.appyx.core.composable.Children
 import com.bumble.appyx.core.lifecycle.subscribe
@@ -74,8 +75,8 @@ class RoomLoadedFlowNode @AssistedInject constructor(
     }
 
     interface LifecycleCallback : NodeLifecycleCallback {
-        fun onFlowCreated(identifier: String, room: MatrixRoom) = Unit
-        fun onFlowReleased(identifier: String, room: MatrixRoom) = Unit
+        fun onFlowCreated(identifier: String, room: MatrixRoom)
+        fun onFlowReleased(identifier: String, room: MatrixRoom)
     }
 
     data class Inputs(
@@ -114,7 +115,8 @@ class RoomLoadedFlowNode @AssistedInject constructor(
         room.updateMembers()
             .onFailure {
                 Timber.e(it, "Fail to fetch members for room ${room.roomId}")
-            }.onSuccess {
+            }
+            .onSuccess {
                 Timber.v("Success fetching members for room ${room.roomId}")
             }
     }
@@ -161,13 +163,16 @@ class RoomLoadedFlowNode @AssistedInject constructor(
 
     @Composable
     override fun View(modifier: Modifier) {
-        // Rely on the View Lifecycle instead of the Node Lifecycle,
+        // Rely on the View Lifecycle in addition to the Node Lifecycle,
         // because this node enters 'onDestroy' before his children, so it can leads to
         // using the room in a child node where it's already closed.
         DisposableEffect(Unit) {
-            inputs.room.open()
+            inputs.room.subscribeToSync()
             onDispose {
-                inputs.room.close()
+                inputs.room.unsubscribeFromSync()
+                if (lifecycle.currentState == Lifecycle.State.DESTROYED) {
+                    inputs.room.destroy()
+                }
             }
         }
         Children(
diff --git a/appnav/src/test/kotlin/io/element/android/appnav/RootPresenterTest.kt b/appnav/src/test/kotlin/io/element/android/appnav/RootPresenterTest.kt
index 0efa9e7f3b..dad9365921 100644
--- a/appnav/src/test/kotlin/io/element/android/appnav/RootPresenterTest.kt
+++ b/appnav/src/test/kotlin/io/element/android/appnav/RootPresenterTest.kt
@@ -16,7 +16,7 @@
 
 package io.element.android.appnav
 
-import app.cash.molecule.RecompositionClock
+import app.cash.molecule.RecompositionMode
 import app.cash.molecule.moleculeFlow
 import app.cash.turbine.test
 import com.google.common.truth.Truth.assertThat
@@ -38,7 +38,7 @@ class RootPresenterTest {
     @Test
     fun `present - initial state`() = runTest {
         val presenter = createPresenter()
-        moleculeFlow(RecompositionClock.Immediate) {
+        moleculeFlow(RecompositionMode.Immediate) {
             presenter.present()
         }.test {
             skipItems(1)
@@ -54,7 +54,7 @@ class RootPresenterTest {
                 showError("Bad news", "Something bad happened")
             }
         )
-        moleculeFlow(RecompositionClock.Immediate) {
+        moleculeFlow(RecompositionMode.Immediate) {
             presenter.present()
         }.test {
             skipItems(1)
diff --git a/appnav/src/test/kotlin/io/element/android/appnav/loggedin/LoggedInPresenterTest.kt b/appnav/src/test/kotlin/io/element/android/appnav/loggedin/LoggedInPresenterTest.kt
index 83bda0ad82..4abc89e7ee 100644
--- a/appnav/src/test/kotlin/io/element/android/appnav/loggedin/LoggedInPresenterTest.kt
+++ b/appnav/src/test/kotlin/io/element/android/appnav/loggedin/LoggedInPresenterTest.kt
@@ -16,17 +16,22 @@
 
 package io.element.android.appnav.loggedin
 
-import app.cash.molecule.RecompositionClock
+import app.cash.molecule.RecompositionMode
 import app.cash.molecule.moleculeFlow
 import app.cash.turbine.test
 import com.google.common.truth.Truth.assertThat
+import io.element.android.features.networkmonitor.api.NetworkStatus
+import io.element.android.features.networkmonitor.test.FakeNetworkMonitor
 import io.element.android.libraries.matrix.api.MatrixClient
+import io.element.android.libraries.matrix.api.roomlist.RoomListService
 import io.element.android.libraries.matrix.test.FakeMatrixClient
+import io.element.android.libraries.matrix.test.roomlist.FakeRoomListService
 import io.element.android.libraries.permissions.api.PermissionsPresenter
 import io.element.android.libraries.permissions.noop.NoopPermissionsPresenter
 import io.element.android.libraries.push.api.PushService
 import io.element.android.libraries.pushproviders.api.Distributor
 import io.element.android.libraries.pushproviders.api.PushProvider
+import io.element.android.tests.testutils.consumeItemsUntilPredicate
 import kotlinx.coroutines.test.runTest
 import org.junit.Test
 
@@ -34,7 +39,7 @@ class LoggedInPresenterTest {
     @Test
     fun `present - initial state`() = runTest {
         val presenter = createPresenter()
-        moleculeFlow(RecompositionClock.Immediate) {
+        moleculeFlow(RecompositionMode.Immediate) {
             presenter.present()
         }.test {
             val initialState = awaitItem()
@@ -42,14 +47,33 @@ class LoggedInPresenterTest {
         }
     }
 
-    private fun createPresenter(): LoggedInPresenter {
+    @Test
+    fun `present - show sync spinner`() = runTest {
+        val roomListService = FakeRoomListService()
+        val presenter = createPresenter(roomListService, NetworkStatus.Online)
+        moleculeFlow(RecompositionMode.Immediate) {
+            presenter.present()
+        }.test {
+            val initialState = awaitItem()
+            assertThat(initialState.showSyncSpinner).isFalse()
+            consumeItemsUntilPredicate { it.showSyncSpinner }
+            roomListService.postState(RoomListService.State.Running)
+            consumeItemsUntilPredicate { !it.showSyncSpinner }
+        }
+    }
+
+    private fun createPresenter(
+        roomListService: RoomListService = FakeRoomListService(),
+        networkStatus: NetworkStatus = NetworkStatus.Offline
+    ): LoggedInPresenter {
         return LoggedInPresenter(
-            matrixClient = FakeMatrixClient(),
+            matrixClient = FakeMatrixClient(roomListService = roomListService),
             permissionsPresenterFactory = object : PermissionsPresenter.Factory {
                 override fun create(permission: String): PermissionsPresenter {
                     return NoopPermissionsPresenter()
                 }
             },
+            networkMonitor = FakeNetworkMonitor(networkStatus),
             pushService = object : PushService {
                 override fun notificationStyleChanged() {
                 }
diff --git a/appnav/src/test/kotlin/io/element/android/appnav/room/LoadingRoomStateFlowFactoryTest.kt b/appnav/src/test/kotlin/io/element/android/appnav/room/LoadingRoomStateFlowFactoryTest.kt
index 17b6f6deb9..f56367e5f8 100644
--- a/appnav/src/test/kotlin/io/element/android/appnav/room/LoadingRoomStateFlowFactoryTest.kt
+++ b/appnav/src/test/kotlin/io/element/android/appnav/room/LoadingRoomStateFlowFactoryTest.kt
@@ -18,12 +18,12 @@ package io.element.android.appnav.room
 
 import app.cash.turbine.test
 import com.google.common.truth.Truth
-import io.element.android.libraries.matrix.api.room.RoomSummaryDataSource
+import io.element.android.libraries.matrix.api.roomlist.RoomList
 import io.element.android.libraries.matrix.test.A_ROOM_ID
 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.room.FakeMatrixRoom
-import io.element.android.libraries.matrix.test.room.FakeRoomSummaryDataSource
+import io.element.android.libraries.matrix.test.roomlist.FakeRoomListService
 import kotlinx.coroutines.test.runTest
 import org.junit.Test
 
@@ -47,29 +47,29 @@ class LoadingRoomStateFlowFactoryTest {
     @Test
     fun `flow should emit Loading and then Loaded when there is a room in cache after SS is loaded`() = runTest {
         val room = FakeMatrixRoom(sessionId= A_SESSION_ID, roomId = A_ROOM_ID)
-        val roomSummaryDataSource = FakeRoomSummaryDataSource()
-        val matrixClient = FakeMatrixClient(A_SESSION_ID, roomSummaryDataSource = roomSummaryDataSource)
+        val roomListService = FakeRoomListService()
+        val matrixClient = FakeMatrixClient(A_SESSION_ID, roomListService = roomListService)
         val flowFactory = LoadingRoomStateFlowFactory(matrixClient)
         flowFactory
             .create(this, A_ROOM_ID)
             .test {
                 Truth.assertThat(awaitItem()).isEqualTo(LoadingRoomState.Loading)
                 matrixClient.givenGetRoomResult(A_ROOM_ID, room)
-                roomSummaryDataSource.postLoadingState(RoomSummaryDataSource.LoadingState.Loaded(1))
+                roomListService.postAllRoomsLoadingState(RoomList.LoadingState.Loaded(1))
                 Truth.assertThat(awaitItem()).isEqualTo(LoadingRoomState.Loaded(room))
             }
     }
 
     @Test
     fun `flow should emit Loading and then Error when there is no room in cache after SS is loaded`() = runTest {
-        val roomSummaryDataSource = FakeRoomSummaryDataSource()
-        val matrixClient = FakeMatrixClient(A_SESSION_ID, roomSummaryDataSource = roomSummaryDataSource)
+        val roomListService = FakeRoomListService()
+        val matrixClient = FakeMatrixClient(A_SESSION_ID, roomListService = roomListService)
         val flowFactory = LoadingRoomStateFlowFactory(matrixClient)
         flowFactory
             .create(this, A_ROOM_ID)
             .test {
                 Truth.assertThat(awaitItem()).isEqualTo(LoadingRoomState.Loading)
-                roomSummaryDataSource.postLoadingState(RoomSummaryDataSource.LoadingState.Loaded(1))
+                roomListService.postAllRoomsLoadingState(RoomList.LoadingState.Loaded(1))
                 Truth.assertThat(awaitItem()).isEqualTo(LoadingRoomState.Error)
             }
     }
diff --git a/build.gradle.kts b/build.gradle.kts
index c03881144e..a50b7673e4 100644
--- a/build.gradle.kts
+++ b/build.gradle.kts
@@ -56,7 +56,7 @@ allprojects {
         // activate all available (even unstable) rules.
         allRules = true
         // point to your custom config defining rules to run, overwriting default behavior
-        config = files("$rootDir/tools/detekt/detekt.yml")
+        config.from(files("$rootDir/tools/detekt/detekt.yml"))
     }
     dependencies {
         detektPlugins("io.nlopez.compose.rules:detekt:0.1.12")
@@ -90,6 +90,14 @@ allprojects {
     apply {
         plugin("org.owasp.dependencycheck")
     }
+
+    tasks.withType {
+        // Warnings are potential errors, so stop ignoring them
+        // This is disabled by default, but the CI will enforce this.
+        // You can override by passing `-PallWarningsAsErrors=true` in the command line
+        // Or add a line with "allWarningsAsErrors=true" in your ~/.gradle/gradle.properties file
+        kotlinOptions.allWarningsAsErrors = project.properties["allWarningsAsErrors"] == "true"
+    }
 }
 
 // To run a sonar analysis:
diff --git a/docs/_developer_onboarding.md b/docs/_developer_onboarding.md
index 9198137577..8a587b5a08 100644
--- a/docs/_developer_onboarding.md
+++ b/docs/_developer_onboarding.md
@@ -145,7 +145,7 @@ Then you can launch the build script from the matrix-rust-components-kotlin repo
 - `-m` Option to select the gradle module to build. Default is sdk.
 - `-t` Option to to select an android target to build against. Default will build for all targets.
 
-So for example to build the sdk against aarch64-linux-android target and copy the generated aar to ElementX project:
+So for example to build the sdk against aarch64-linux-android target and copy the generated aar to Element X project:
 
 ```shell
 ./scripts/build.sh -p [YOUR MATRIX RUST SDK PATH] -t aarch64-linux-android -o [YOUR element-x-android PATH]/libraries/rustsdk/matrix-rust-sdk.aar
@@ -313,7 +313,7 @@ suffix `Presenter`,states MUST have a suffix `State`, etc. Also we want to have
 
 ### Push
 
-**Note** Firebase Push is not yet implemented on the project.
+**Note** Firebase is implemented, but Unified Push is not yet fully implemented on the project, so this is not possible to choose this push provider in the app at the moment.
 
 Please see the dedicated [documentation](notifications.md) for more details.
 
@@ -342,8 +342,7 @@ We have 3 tests frameworks in place, and this should be sufficient to guarantee
   file [TemplateView.kt](../features/template/src/main/kotlin/io/element/android/features/template/TemplateView.kt). We create PreviewProvider to provide
   different states. See for instance the
   file [TemplateStateProvider.kt](../features/template/src/main/kotlin/io/element/android/features/template/TemplateStateProvider.kt)
-    - Tests on presenter with [Molecule](https://github.com/cashapp/molecule) and [Turbine](https://github.com/cashapp/turbine). See in the template the
-      class [TemplatePresenterTests](../features/template/src/test/kotlin/io/element/android/features/template/TemplatePresenterTests.kt).
+- Tests on presenter with [Molecule](https://github.com/cashapp/molecule) and [Turbine](https://github.com/cashapp/turbine). See in the template the class [TemplatePresenterTests](../features/template/src/test/kotlin/io/element/android/features/template/TemplatePresenterTests.kt).
 
 **Note** For now we want to avoid using class mocking (with library such as *mockk*), because this should be not necessary. We prefer to create Fake
 implementation of our interfaces. Mocking can be used to mock Android framework classes though, such as `Bitmap` for instance.
diff --git a/docs/images-lfs/screen_1_dark.png b/docs/images-lfs/screen_1_dark.png
new file mode 100644
index 0000000000..8bdcd59305
--- /dev/null
+++ b/docs/images-lfs/screen_1_dark.png
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:4515f7589c422197a82672cdc3e64814ccca9a9a022b806facee44dd67d51ff2
+size 1116864
diff --git a/docs/images-lfs/screen_1_light.png b/docs/images-lfs/screen_1_light.png
new file mode 100644
index 0000000000..8eba38af82
--- /dev/null
+++ b/docs/images-lfs/screen_1_light.png
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:2afb667a8b679f4395c28407b014f074e8b74745f6ecdd6ad699a6650cee2bc7
+size 771160
diff --git a/docs/images-lfs/screen_2_dark.png b/docs/images-lfs/screen_2_dark.png
new file mode 100644
index 0000000000..9a0102940f
--- /dev/null
+++ b/docs/images-lfs/screen_2_dark.png
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:910f9ab58a197a16b1295cd6b65d406ebfff1298c9c128a326edf1ec834d7fa7
+size 332936
diff --git a/docs/images-lfs/screen_2_light.png b/docs/images-lfs/screen_2_light.png
new file mode 100644
index 0000000000..1dd3106e5c
--- /dev/null
+++ b/docs/images-lfs/screen_2_light.png
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:f7b80b9124c5c04c9db3824b68ab35883d41d05918abd415f7565f87d2713cfa
+size 338455
diff --git a/docs/images-lfs/screen_3_dark.png b/docs/images-lfs/screen_3_dark.png
new file mode 100644
index 0000000000..ccc17333e7
--- /dev/null
+++ b/docs/images-lfs/screen_3_dark.png
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:dadff79ae955ab1da5c0a0567960fc567526ad0d8d2ea418d8adacf3a7a400cc
+size 243201
diff --git a/docs/images-lfs/screen_3_light.png b/docs/images-lfs/screen_3_light.png
new file mode 100644
index 0000000000..2116f1dc4c
--- /dev/null
+++ b/docs/images-lfs/screen_3_light.png
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:e2f328b3e8bf2ebe4abc4c130e28f6fc2351f5ac339be0819e5fddb657f4a560
+size 246731
diff --git a/docs/images-lfs/screen_4_dark.png b/docs/images-lfs/screen_4_dark.png
new file mode 100644
index 0000000000..5bd122a9ea
--- /dev/null
+++ b/docs/images-lfs/screen_4_dark.png
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:519fb54f0070833b2a4671e1f0fc7b2ec60930d69b592b8a760f52a73dc4fe38
+size 132247
diff --git a/docs/images-lfs/screen_4_light.png b/docs/images-lfs/screen_4_light.png
new file mode 100644
index 0000000000..ee82f3be0a
--- /dev/null
+++ b/docs/images-lfs/screen_4_light.png
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:f683a228d7168c75d6f42c353c1a0e169cb22cb8fa6696e9e3ffeb80854b2441
+size 131610
diff --git a/docs/images/screen1.png b/docs/images/screen1.png
deleted file mode 100644
index 9f9d7747ff..0000000000
Binary files a/docs/images/screen1.png and /dev/null differ
diff --git a/docs/images/screen2.png b/docs/images/screen2.png
deleted file mode 100644
index a5733003d6..0000000000
Binary files a/docs/images/screen2.png and /dev/null differ
diff --git a/docs/images/screen3.png b/docs/images/screen3.png
deleted file mode 100644
index 3edb49d086..0000000000
Binary files a/docs/images/screen3.png and /dev/null differ
diff --git a/docs/images/screen4.png b/docs/images/screen4.png
deleted file mode 100644
index 53da801a1b..0000000000
Binary files a/docs/images/screen4.png and /dev/null differ
diff --git a/docs/maps.md b/docs/maps.md
index cc00905986..789d455f22 100644
--- a/docs/maps.md
+++ b/docs/maps.md
@@ -27,16 +27,21 @@ Place your API key in `local.properties` with the key
 services.maptiler.apikey=abCd3fGhijK1mN0pQr5t
 ```
 
+Optionally you can also place your custom MapTyler style ids for light and dark maps
+in the `local.properties` with the keys `services.maptiler.lightMapId` and
+`services.maptiler.darkMapId`. If you don't specify these, the default MapTiler "basic-v2"
+styles will be used.
+
 ## Making releasable builds with MapTiler
 
 To insert the MapTiler API key when building an APK, set the
 `ELEMENT_ANDROID_MAPTILER_API_KEY` environment variable in your build
-environment. 
+environment.
+If you've added custom styles also set the `ELEMENT_ANDROID_MAPTILER_LIGHT_MAP_ID`
+and `ELEMENT_ANDROID_MAPTILER_DARK_MAP_ID` environment variables accordingly.
 
 ## Using other map sources or MapTiler styles
 
-If you wish to use an alternative map provider, or custom MapTiler styles,
-you can customise the functions in
-`features/location/api/src/main/kotlin/io/element/android/features/location/api/internal/MapUrls.kt`. 
-We've kept this file small and self contained to minimise the chances of merge
-collisions in forks.
+If you wish to use an alternative map provider, you can provide your own implementations of
+`TileServerStyleUriBuilder` and `StaticMapUrlBuilder` in
+`features/location/api/src/main/kotlin/io/element/android/features/location/api/internal/`.
diff --git a/docs/nightly_build.md b/docs/nightly_build.md
index 9abd59a67b..91ea10b530 100644
--- a/docs/nightly_build.md
+++ b/docs/nightly_build.md
@@ -10,11 +10,11 @@
 
 ## Configuration
 
-The nightly build will contain what's on develop, in release mode, for the main variant. It is signed using a dedicated signature, and has a dedicated appId (`io.element.android.x.nightly`), so it can be installed along with the production version of ElementX Android. The only other difference compared to ElementX Android is a different app name. We do not want to change the app name since it will also affect some strings in the app, and we do want to do that. (TODO today, the app name is changed.)
+The nightly build will contain what's on develop, in release mode, for the main variant. It is signed using a dedicated signature, and has a dedicated appId (`io.element.android.x.nightly`), so it can be installed along with the production version of Element X Android. The only other difference compared to ElementX Android is a different app name. We do not want to change the app name since it will also affect some strings in the app, and we do want to do that. (TODO today, the app name is changed.)
 
 Nightly builds are built and released to Firebase every days, and automatically.
 
-This is recommended to exclusively use this app, with your main account, instead of ElementX Android, and fallback to ElementX Android just in case of regression, to discover as soon as possible any regression, and report it to the team. To avoid double notification, you may want to disable the notification from the Element Android production version. Just open Element Android, navigate to `Settings/Notifications` and uncheck `Enable notifications for this session` (TODO Not supported yet).
+This is recommended to exclusively use this app, with your main account, instead of Element X Android, and fallback to ElementX Android just in case of regression, to discover as soon as possible any regression, and report it to the team. To avoid double notification, you may want to disable the notification from the Element Android production version. Just open Element Android, navigate to `Settings/Notifications` and uncheck `Enable notifications for this session` (TODO Not supported yet).
 
 *Note:* Due to a limitation of Firebase, the nightly build is the universal build, which means that the size of the APK is a bit bigger, but this should not have any other side effect.
 
diff --git a/docs/screenshot_testing.md b/docs/screenshot_testing.md
index 37299af7fc..79ecad20dd 100644
--- a/docs/screenshot_testing.md
+++ b/docs/screenshot_testing.md
@@ -13,7 +13,7 @@
 ## Overview
 
 - Screenshot tests are tests which record the content of a rendered screen and verify subsequent runs to check if the screen renders differently.
-- ElementX uses [Paparazzi](https://github.com/cashapp/paparazzi) to render, record and verify Composable. All Composable Preview will be use to make screenshot test, thanks to the usage of [Showkase](https://github.com/airbnb/Showkase).
+- Element X uses [Paparazzi](https://github.com/cashapp/paparazzi) to render, record and verify Composable. All Composable Preview will be use to make screenshot test, thanks to the usage of [Showkase](https://github.com/airbnb/Showkase).
 - The screenshot verification occurs on every pull request as part of the `tests.yml` workflow.
 
 ## Setup
@@ -30,6 +30,14 @@ If installed correctly, `git push` and `git pull` will now include LFS content.
 
 ## Recording
 
+Recording of screenshots is done by triggering the GitHub action [Record screenshots](https://github.com/vector-im/element-x-android/actions/workflows/recordScreenshots.yml), to avoid differences of generated binary files (png images) depending on developers' environment.
+
+So basically, you will create a branch, do some commits with your work on it, then push your branch, trigger the GitHub action to record the screenshots (only if you think preview may have changed), and finally create a pull request. The GitHub action will record the screenshots and commit the changes to the branch.
+
+You can still record the screenshots locally, but please do not commit the changes.
+
+To record the screenshot locally, run the following command:
+
 ```shell
 ./gradlew recordPaparazziDebug
 ```
diff --git a/fastlane/metadata/android/en-US/changelogs/40001020.txt b/fastlane/metadata/android/en-US/changelogs/40001020.txt
new file mode 100644
index 0000000000..8aacdd89af
--- /dev/null
+++ b/fastlane/metadata/android/en-US/changelogs/40001020.txt
@@ -0,0 +1,2 @@
+First release of Element X 🚀!
+Full changelog: https://github.com/vector-im/element-x-android/releases
diff --git a/features/analytics/api/src/main/kotlin/io/element/android/features/analytics/api/preferences/AnalyticsPreferencesView.kt b/features/analytics/api/src/main/kotlin/io/element/android/features/analytics/api/preferences/AnalyticsPreferencesView.kt
index f6d77226b9..5aa9287d86 100644
--- a/features/analytics/api/src/main/kotlin/io/element/android/features/analytics/api/preferences/AnalyticsPreferencesView.kt
+++ b/features/analytics/api/src/main/kotlin/io/element/android/features/analytics/api/preferences/AnalyticsPreferencesView.kt
@@ -81,12 +81,12 @@ fun buildAnnotatedStringWithColoredPart(
 
 @Preview
 @Composable
-fun AnalyticsPreferencesViewLightPreview(@PreviewParameter(AnalyticsPreferencesStateProvider::class) state: AnalyticsPreferencesState) =
+internal fun AnalyticsPreferencesViewLightPreview(@PreviewParameter(AnalyticsPreferencesStateProvider::class) state: AnalyticsPreferencesState) =
     ElementPreviewLight { ContentToPreview(state) }
 
 @Preview
 @Composable
-fun AnalyticsPreferencesViewDarkPreview(@PreviewParameter(AnalyticsPreferencesStateProvider::class) state: AnalyticsPreferencesState) =
+internal fun AnalyticsPreferencesViewDarkPreview(@PreviewParameter(AnalyticsPreferencesStateProvider::class) state: AnalyticsPreferencesState) =
     ElementPreviewDark { ContentToPreview(state) }
 
 @Composable
diff --git a/features/analytics/impl/build.gradle.kts b/features/analytics/impl/build.gradle.kts
index 3bf58ab636..8356bb38bb 100644
--- a/features/analytics/impl/build.gradle.kts
+++ b/features/analytics/impl/build.gradle.kts
@@ -52,6 +52,4 @@ dependencies {
     testImplementation(projects.libraries.matrix.test)
     testImplementation(projects.features.analytics.test)
     testImplementation(projects.features.analytics.impl)
-
-    androidTestImplementation(libs.test.junitext)
 }
diff --git a/features/analytics/impl/src/main/kotlin/io/element/android/features/analytics/impl/AnalyticsOptInView.kt b/features/analytics/impl/src/main/kotlin/io/element/android/features/analytics/impl/AnalyticsOptInView.kt
index a27e6e7399..54b9add785 100644
--- a/features/analytics/impl/src/main/kotlin/io/element/android/features/analytics/impl/AnalyticsOptInView.kt
+++ b/features/analytics/impl/src/main/kotlin/io/element/android/features/analytics/impl/AnalyticsOptInView.kt
@@ -54,6 +54,7 @@ import io.element.android.libraries.designsystem.preview.ElementPreviewDark
 import io.element.android.libraries.designsystem.preview.ElementPreviewLight
 import io.element.android.libraries.designsystem.text.buildAnnotatedStringWithStyledPart
 import io.element.android.libraries.designsystem.theme.components.Button
+import io.element.android.libraries.designsystem.theme.components.ButtonSize
 import io.element.android.libraries.designsystem.theme.components.Icon
 import io.element.android.libraries.designsystem.theme.components.Text
 import io.element.android.libraries.designsystem.theme.components.TextButton
@@ -188,29 +189,28 @@ private fun AnalyticsOptInFooter(
         modifier = modifier,
     ) {
         Button(
+            text = stringResource(id = CommonStrings.action_ok),
             onClick = onTermsAccepted,
             modifier = Modifier.fillMaxWidth(),
-        ) {
-            Text(text = stringResource(id = CommonStrings.action_ok))
-        }
+        )
         TextButton(
+            text = stringResource(id = CommonStrings.action_not_now),
+            size = ButtonSize.Medium,
             onClick = onTermsDeclined,
             modifier = Modifier.fillMaxWidth(),
-        ) {
-            Text(text = stringResource(id = CommonStrings.action_not_now))
-        }
+        )
     }
 }
 
 @Preview
 @Composable
-fun AnalyticsOptInViewLightPreview(@PreviewParameter(AnalyticsOptInStateProvider::class) state: AnalyticsOptInState) = ElementPreviewLight {
+internal fun AnalyticsOptInViewLightPreview(@PreviewParameter(AnalyticsOptInStateProvider::class) state: AnalyticsOptInState) = ElementPreviewLight {
     ContentToPreview(state)
 }
 
 @Preview
 @Composable
-fun AnalyticsOptInViewDarkPreview(@PreviewParameter(AnalyticsOptInStateProvider::class) state: AnalyticsOptInState) = ElementPreviewDark {
+internal fun AnalyticsOptInViewDarkPreview(@PreviewParameter(AnalyticsOptInStateProvider::class) state: AnalyticsOptInState) = ElementPreviewDark {
     ContentToPreview(state)
 }
 
diff --git a/features/analytics/impl/src/main/res/values-de/translations.xml b/features/analytics/impl/src/main/res/values-de/translations.xml
index 979048344f..44890927a4 100644
--- a/features/analytics/impl/src/main/res/values-de/translations.xml
+++ b/features/analytics/impl/src/main/res/values-de/translations.xml
@@ -1,10 +1,10 @@
 
 
-  "Wir erfassen und analysieren ""keine"" Account-Daten"
+  "Wir werden keine personenbezogenen Daten aufzeichnen oder auswerten"
   "Teile anonyme Nutzungsdaten, um uns bei der Identifizierung von Problemen zu helfen."
-  "Sie können alle unsere Nutzerbedingungen %1$s lesen."
+  "Du kannst alle unsere Nutzerbedingungen %1$s lesen."
   "hier"
-  "Sie können die Analyse jederzeit in den Einstellungen deaktivieren"
+  "Du kannst dies jederzeit deaktivieren"
   "Wir geben ""keine"" Informationen an Dritte weiter"
-  "Helfen Sie %1$s zu verbessern"
+  "Hilf uns, %1$s zu verbessern"
 
diff --git a/features/analytics/impl/src/main/res/values-ru/translations.xml b/features/analytics/impl/src/main/res/values-ru/translations.xml
new file mode 100644
index 0000000000..805cba6bf2
--- /dev/null
+++ b/features/analytics/impl/src/main/res/values-ru/translations.xml
@@ -0,0 +1,10 @@
+
+
+  "Мы не будем записывать или профилировать какие-либо персональные данные"
+  "Предоставлять анонимные данные об использовании, чтобы помочь нам выявить проблемы."
+  "Вы можете ознакомиться со всеми нашими условиями %1$s."
+  "здесь"
+  "Вы можете отключить эту функцию в любое время"
+  "Мы не будем передавать ваши данные третьим лицам"
+  "Помогите улучшить %1$s"
+
diff --git a/features/analytics/impl/src/main/res/values-zh-rTW/translations.xml b/features/analytics/impl/src/main/res/values-zh-rTW/translations.xml
new file mode 100644
index 0000000000..3259b10fbd
--- /dev/null
+++ b/features/analytics/impl/src/main/res/values-zh-rTW/translations.xml
@@ -0,0 +1,4 @@
+
+
+  "您可以在任何時候關閉它"
+
diff --git a/features/analytics/impl/src/test/kotlin/io/element/android/features/analytics/impl/AnalyticsOptInPresenterTest.kt b/features/analytics/impl/src/test/kotlin/io/element/android/features/analytics/impl/AnalyticsOptInPresenterTest.kt
index a8e42ceb01..541e5858bd 100644
--- a/features/analytics/impl/src/test/kotlin/io/element/android/features/analytics/impl/AnalyticsOptInPresenterTest.kt
+++ b/features/analytics/impl/src/test/kotlin/io/element/android/features/analytics/impl/AnalyticsOptInPresenterTest.kt
@@ -16,7 +16,7 @@
 
 package io.element.android.features.analytics.impl
 
-import app.cash.molecule.RecompositionClock
+import app.cash.molecule.RecompositionMode
 import app.cash.molecule.moleculeFlow
 import app.cash.turbine.test
 import com.google.common.truth.Truth.assertThat
@@ -35,7 +35,7 @@ class AnalyticsOptInPresenterTest {
             aBuildMeta(),
             analyticsService
         )
-        moleculeFlow(RecompositionClock.Immediate) {
+        moleculeFlow(RecompositionMode.Immediate) {
             presenter.present()
         }.test {
             val initialState = awaitItem()
@@ -53,7 +53,7 @@ class AnalyticsOptInPresenterTest {
             aBuildMeta(),
             analyticsService
         )
-        moleculeFlow(RecompositionClock.Immediate) {
+        moleculeFlow(RecompositionMode.Immediate) {
             presenter.present()
         }.test {
             val initialState = awaitItem()
diff --git a/features/analytics/impl/src/test/kotlin/io/element/android/features/analytics/impl/preferences/AnalyticsPreferencesPresenterTest.kt b/features/analytics/impl/src/test/kotlin/io/element/android/features/analytics/impl/preferences/AnalyticsPreferencesPresenterTest.kt
index 8469abe769..d0914932bb 100644
--- a/features/analytics/impl/src/test/kotlin/io/element/android/features/analytics/impl/preferences/AnalyticsPreferencesPresenterTest.kt
+++ b/features/analytics/impl/src/test/kotlin/io/element/android/features/analytics/impl/preferences/AnalyticsPreferencesPresenterTest.kt
@@ -16,7 +16,7 @@
 
 package io.element.android.features.analytics.impl.preferences
 
-import app.cash.molecule.RecompositionClock
+import app.cash.molecule.RecompositionMode
 import app.cash.molecule.moleculeFlow
 import app.cash.turbine.test
 import com.google.common.truth.Truth.assertThat
@@ -33,7 +33,7 @@ class AnalyticsPreferencesPresenterTest {
             FakeAnalyticsService(isEnabled = true, didAskUserConsent = true),
             aBuildMeta()
         )
-        moleculeFlow(RecompositionClock.Immediate) {
+        moleculeFlow(RecompositionMode.Immediate) {
             presenter.present()
         }.test {
             skipItems(1)
@@ -48,7 +48,7 @@ class AnalyticsPreferencesPresenterTest {
             FakeAnalyticsService(isEnabled = false, didAskUserConsent = false),
             aBuildMeta()
         )
-        moleculeFlow(RecompositionClock.Immediate) {
+        moleculeFlow(RecompositionMode.Immediate) {
             presenter.present()
         }.test {
             val initialState = awaitItem()
@@ -62,7 +62,7 @@ class AnalyticsPreferencesPresenterTest {
             FakeAnalyticsService(isEnabled = true, didAskUserConsent = true),
             aBuildMeta()
         )
-        moleculeFlow(RecompositionClock.Immediate) {
+        moleculeFlow(RecompositionMode.Immediate) {
             presenter.present()
         }.test {
             skipItems(1)
diff --git a/features/analytics/test/src/main/kotlin/io/element/android/features/analytics/test/FakeAnalyticsService.kt b/features/analytics/test/src/main/kotlin/io/element/android/features/analytics/test/FakeAnalyticsService.kt
index 6e84c58d2a..9e3fe8bb59 100644
--- a/features/analytics/test/src/main/kotlin/io/element/android/features/analytics/test/FakeAnalyticsService.kt
+++ b/features/analytics/test/src/main/kotlin/io/element/android/features/analytics/test/FakeAnalyticsService.kt
@@ -33,7 +33,7 @@ class FakeAnalyticsService(
     private val didAskUserConsentFlow = MutableStateFlow(didAskUserConsent)
     val capturedEvents = mutableListOf()
 
-    override fun getAvailableAnalyticsProviders(): List = emptyList()
+    override fun getAvailableAnalyticsProviders(): Set = emptySet()
 
     override fun getUserConsent(): Flow = isEnabledFlow
 
diff --git a/features/createroom/impl/build.gradle.kts b/features/createroom/impl/build.gradle.kts
index 8bb343c10a..fe2970dd80 100644
--- a/features/createroom/impl/build.gradle.kts
+++ b/features/createroom/impl/build.gradle.kts
@@ -66,7 +66,5 @@ dependencies {
     testImplementation(projects.libraries.mediaupload.test)
     testImplementation(projects.libraries.usersearch.test)
 
-    androidTestImplementation(libs.test.junitext)
-
     ksp(libs.showkase.processor)
 }
diff --git a/features/createroom/impl/src/main/kotlin/io/element/android/features/createroom/impl/addpeople/AddPeopleView.kt b/features/createroom/impl/src/main/kotlin/io/element/android/features/createroom/impl/addpeople/AddPeopleView.kt
index da1f43391b..e5f701036e 100644
--- a/features/createroom/impl/src/main/kotlin/io/element/android/features/createroom/impl/addpeople/AddPeopleView.kt
+++ b/features/createroom/impl/src/main/kotlin/io/element/android/features/createroom/impl/addpeople/AddPeopleView.kt
@@ -28,7 +28,6 @@ import androidx.compose.ui.Modifier
 import androidx.compose.ui.res.stringResource
 import androidx.compose.ui.tooling.preview.Preview
 import androidx.compose.ui.tooling.preview.PreviewParameter
-import androidx.compose.ui.unit.dp
 import io.element.android.features.createroom.impl.R
 import io.element.android.features.createroom.impl.components.UserListView
 import io.element.android.features.createroom.impl.userlist.UserListEvents
@@ -36,7 +35,6 @@ import io.element.android.features.createroom.impl.userlist.UserListState
 import io.element.android.libraries.designsystem.components.button.BackButton
 import io.element.android.libraries.designsystem.preview.ElementPreviewDark
 import io.element.android.libraries.designsystem.preview.ElementPreviewLight
-import io.element.android.libraries.designsystem.theme.aliasButtonText
 import io.element.android.libraries.designsystem.theme.aliasScreenTitle
 import io.element.android.libraries.designsystem.theme.components.Scaffold
 import io.element.android.libraries.designsystem.theme.components.Text
@@ -103,16 +101,11 @@ fun AddPeopleViewTopBar(
         },
         navigationIcon = { BackButton(onClick = onBackPressed) },
         actions = {
+            val textActionResId = if (hasSelectedUsers) CommonStrings.action_next else CommonStrings.action_skip
             TextButton(
-                modifier = Modifier.padding(horizontal = 8.dp),
+                text = stringResource(id = textActionResId),
                 onClick = onNextPressed,
-            ) {
-                val textActionResId = if (hasSelectedUsers) CommonStrings.action_next else CommonStrings.action_skip
-                Text(
-                    text = stringResource(id = textActionResId),
-                    style = ElementTheme.typography.aliasButtonText,
-                )
-            }
+            )
         }
     )
 }
diff --git a/features/createroom/impl/src/main/kotlin/io/element/android/features/createroom/impl/components/RoomPrivacyOption.kt b/features/createroom/impl/src/main/kotlin/io/element/android/features/createroom/impl/components/RoomPrivacyOption.kt
index ee664673f8..302f72d514 100644
--- a/features/createroom/impl/src/main/kotlin/io/element/android/features/createroom/impl/components/RoomPrivacyOption.kt
+++ b/features/createroom/impl/src/main/kotlin/io/element/android/features/createroom/impl/components/RoomPrivacyOption.kt
@@ -30,7 +30,6 @@ import androidx.compose.ui.Modifier
 import androidx.compose.ui.semantics.Role
 import androidx.compose.ui.tooling.preview.Preview
 import androidx.compose.ui.unit.dp
-import androidx.compose.ui.unit.sp
 import io.element.android.features.createroom.impl.configureroom.RoomPrivacyItem
 import io.element.android.features.createroom.impl.configureroom.roomPrivacyItems
 import io.element.android.libraries.designsystem.preview.ElementPreviewDark
@@ -94,11 +93,11 @@ fun RoomPrivacyOption(
 
 @Preview
 @Composable
-fun RoomPrivacyOptionLightPreview() = ElementPreviewLight { ContentToPreview() }
+internal fun RoomPrivacyOptionLightPreview() = ElementPreviewLight { ContentToPreview() }
 
 @Preview
 @Composable
-fun RoomPrivacyOptionDarkPreview() = ElementPreviewDark { ContentToPreview() }
+internal fun RoomPrivacyOptionDarkPreview() = ElementPreviewDark { ContentToPreview() }
 
 @Composable
 private fun ContentToPreview() {
diff --git a/features/createroom/impl/src/main/kotlin/io/element/android/features/createroom/impl/configureroom/ConfigureRoomView.kt b/features/createroom/impl/src/main/kotlin/io/element/android/features/createroom/impl/configureroom/ConfigureRoomView.kt
index 9ac8f0fbde..d1f29559bd 100644
--- a/features/createroom/impl/src/main/kotlin/io/element/android/features/createroom/impl/configureroom/ConfigureRoomView.kt
+++ b/features/createroom/impl/src/main/kotlin/io/element/android/features/createroom/impl/configureroom/ConfigureRoomView.kt
@@ -29,6 +29,7 @@ import androidx.compose.foundation.layout.imePadding
 import androidx.compose.foundation.layout.padding
 import androidx.compose.foundation.rememberScrollState
 import androidx.compose.foundation.selection.selectableGroup
+import androidx.compose.foundation.text.KeyboardOptions
 import androidx.compose.foundation.verticalScroll
 import androidx.compose.material.ExperimentalMaterialApi
 import androidx.compose.material.ModalBottomSheetValue
@@ -43,6 +44,7 @@ import androidx.compose.ui.focus.FocusManager
 import androidx.compose.ui.input.pointer.pointerInput
 import androidx.compose.ui.platform.LocalFocusManager
 import androidx.compose.ui.res.stringResource
+import androidx.compose.ui.text.input.KeyboardCapitalization
 import androidx.compose.ui.tooling.preview.Preview
 import androidx.compose.ui.tooling.preview.PreviewParameter
 import androidx.compose.ui.unit.dp
@@ -55,7 +57,6 @@ import io.element.android.libraries.designsystem.components.button.BackButton
 import io.element.android.libraries.designsystem.components.dialogs.RetryDialog
 import io.element.android.libraries.designsystem.preview.ElementPreviewDark
 import io.element.android.libraries.designsystem.preview.ElementPreviewLight
-import io.element.android.libraries.designsystem.theme.aliasButtonText
 import io.element.android.libraries.designsystem.theme.aliasScreenTitle
 import io.element.android.libraries.designsystem.theme.components.Scaffold
 import io.element.android.libraries.designsystem.theme.components.Text
@@ -193,15 +194,10 @@ fun ConfigureRoomToolbar(
         navigationIcon = { BackButton(onClick = onBackPressed) },
         actions = {
             TextButton(
-                modifier = Modifier.padding(horizontal = 8.dp),
+                text = stringResource(CommonStrings.action_create),
                 enabled = isNextActionEnabled,
                 onClick = onNextPressed,
-            ) {
-                Text(
-                    text = stringResource(CommonStrings.action_create),
-                    style = ElementTheme.typography.aliasButtonText,
-                )
-            }
+            )
         }
     )
 }
@@ -247,6 +243,9 @@ fun RoomTopic(
         placeholder = stringResource(CommonStrings.common_topic_placeholder),
         onValueChange = onTopicChanged,
         maxLines = 3,
+        keyboardOptions = KeyboardOptions(
+            capitalization = KeyboardCapitalization.Sentences,
+        ),
     )
 }
 
@@ -277,12 +276,12 @@ private fun Modifier.clearFocusOnTap(focusManager: FocusManager): Modifier =
 
 @Preview
 @Composable
-fun ConfigureRoomViewLightPreview(@PreviewParameter(ConfigureRoomStateProvider::class) state: ConfigureRoomState) =
+internal fun ConfigureRoomViewLightPreview(@PreviewParameter(ConfigureRoomStateProvider::class) state: ConfigureRoomState) =
     ElementPreviewLight { ContentToPreview(state) }
 
 @Preview
 @Composable
-fun ConfigureRoomViewDarkPreview(@PreviewParameter(ConfigureRoomStateProvider::class) state: ConfigureRoomState) =
+internal fun ConfigureRoomViewDarkPreview(@PreviewParameter(ConfigureRoomStateProvider::class) state: ConfigureRoomState) =
     ElementPreviewDark { ContentToPreview(state) }
 
 @Composable
diff --git a/features/createroom/impl/src/main/kotlin/io/element/android/features/createroom/impl/root/CreateRoomRootStateProvider.kt b/features/createroom/impl/src/main/kotlin/io/element/android/features/createroom/impl/root/CreateRoomRootStateProvider.kt
index d1484b7a4f..7a3bf6ef03 100644
--- a/features/createroom/impl/src/main/kotlin/io/element/android/features/createroom/impl/root/CreateRoomRootStateProvider.kt
+++ b/features/createroom/impl/src/main/kotlin/io/element/android/features/createroom/impl/root/CreateRoomRootStateProvider.kt
@@ -41,7 +41,7 @@ open class CreateRoomRootStateProvider : PreviewParameterProvider"Inviter des amis sur Element"
   "Inviter des personnes"
   "Une erreur s\'est produite lors de la création du salon"
-  "Les messages dans ce salon sont chiffrés. Une fopis activé, le chiffrement ne peut pas être désactivé."
+  "Les messages dans ce salon sont chiffrés. Une fois activé, le chiffrement ne peut pas être désactivé."
   "Salon privé (sur invitation uniquement)"
   "Les messages ne sont pas chiffrés et n\'importe qui peut les lire. Vous pouvez activer le chiffrement ultérieurement."
   "Salon public (n’importe qui)"
diff --git a/features/createroom/impl/src/main/res/values-ru/translations.xml b/features/createroom/impl/src/main/res/values-ru/translations.xml
new file mode 100644
index 0000000000..7837f9e7de
--- /dev/null
+++ b/features/createroom/impl/src/main/res/values-ru/translations.xml
@@ -0,0 +1,15 @@
+
+
+  "Новая комната"
+  "Пригласите друзей в Element"
+  "Пригласить людей"
+  "Произошла ошибка при создании комнаты"
+  "Сообщения в этой комнате зашифрованы. Отключить шифрование впоследствии невозможно."
+  "Приватная комната (только по приглашению)"
+  "Сообщения не зашифрованы, и каждый может их прочитать. Вы можете включить шифрование позже."
+  "Публичная комната (любой)"
+  "Название комнаты"
+  "Тема (необязательно)"
+  "Произошла ошибка при попытке открытия комнаты"
+  "Создать комнату"
+
diff --git a/features/createroom/impl/src/main/res/values-zh-rTW/translations.xml b/features/createroom/impl/src/main/res/values-zh-rTW/translations.xml
new file mode 100644
index 0000000000..dd8afaf2e7
--- /dev/null
+++ b/features/createroom/impl/src/main/res/values-zh-rTW/translations.xml
@@ -0,0 +1,7 @@
+
+
+  "邀請朋友使用 Element"
+  "聊天室名稱"
+  "主題(非必填)"
+  "建立聊天室"
+
diff --git a/features/createroom/impl/src/test/kotlin/io/element/android/features/createroom/impl/addpeople/AddPeoplePresenterTests.kt b/features/createroom/impl/src/test/kotlin/io/element/android/features/createroom/impl/addpeople/AddPeoplePresenterTests.kt
index fe8c7b7462..43cf6cff4d 100644
--- a/features/createroom/impl/src/test/kotlin/io/element/android/features/createroom/impl/addpeople/AddPeoplePresenterTests.kt
+++ b/features/createroom/impl/src/test/kotlin/io/element/android/features/createroom/impl/addpeople/AddPeoplePresenterTests.kt
@@ -16,7 +16,7 @@
 
 package io.element.android.features.createroom.impl.addpeople
 
-import app.cash.molecule.RecompositionClock
+import app.cash.molecule.RecompositionMode
 import app.cash.molecule.moleculeFlow
 import app.cash.turbine.test
 import com.google.common.truth.Truth.assertThat
@@ -43,7 +43,7 @@ class AddPeoplePresenterTests {
 
     @Test
     fun `present - initial state`() = runTest {
-        moleculeFlow(RecompositionClock.Immediate) {
+        moleculeFlow(RecompositionMode.Immediate) {
             presenter.present()
         }.test {
             // TODO This doesn't actually test anything...
diff --git a/features/createroom/impl/src/test/kotlin/io/element/android/features/createroom/impl/configureroom/ConfigureRoomPresenterTests.kt b/features/createroom/impl/src/test/kotlin/io/element/android/features/createroom/impl/configureroom/ConfigureRoomPresenterTests.kt
index 9b6ac2e067..1703cf4142 100644
--- a/features/createroom/impl/src/test/kotlin/io/element/android/features/createroom/impl/configureroom/ConfigureRoomPresenterTests.kt
+++ b/features/createroom/impl/src/test/kotlin/io/element/android/features/createroom/impl/configureroom/ConfigureRoomPresenterTests.kt
@@ -17,7 +17,7 @@
 package io.element.android.features.createroom.impl.configureroom
 
 import android.net.Uri
-import app.cash.molecule.RecompositionClock
+import app.cash.molecule.RecompositionMode
 import app.cash.molecule.moleculeFlow
 import app.cash.turbine.test
 import com.google.common.truth.Truth.assertThat
@@ -93,7 +93,7 @@ class ConfigureRoomPresenterTests {
 
     @Test
     fun `present - initial state`() = runTest {
-        moleculeFlow(RecompositionClock.Immediate) {
+        moleculeFlow(RecompositionMode.Immediate) {
             presenter.present()
         }.test {
             val initialState = awaitItem()
@@ -108,7 +108,7 @@ class ConfigureRoomPresenterTests {
 
     @Test
     fun `present - create room button is enabled only if the required fields are completed`() = runTest {
-        moleculeFlow(RecompositionClock.Immediate) {
+        moleculeFlow(RecompositionMode.Immediate) {
             presenter.present()
         }.test {
             val initialState = awaitItem()
@@ -133,7 +133,7 @@ class ConfigureRoomPresenterTests {
 
     @Test
     fun `present - state is updated when fields are changed`() = runTest {
-        moleculeFlow(RecompositionClock.Immediate) {
+        moleculeFlow(RecompositionMode.Immediate) {
             presenter.present()
         }.test {
             val initialState = awaitItem()
@@ -203,7 +203,7 @@ class ConfigureRoomPresenterTests {
 
     @Test
     fun `present - trigger create room action`() = runTest {
-        moleculeFlow(RecompositionClock.Immediate) {
+        moleculeFlow(RecompositionMode.Immediate) {
             presenter.present()
         }.test {
             val initialState = awaitItem()
@@ -221,7 +221,7 @@ class ConfigureRoomPresenterTests {
 
     @Test
     fun `present - record analytics when creating room`() = runTest {
-        moleculeFlow(RecompositionClock.Immediate) {
+        moleculeFlow(RecompositionMode.Immediate) {
             presenter.present()
         }.test {
             val initialState = awaitItem()
@@ -240,7 +240,7 @@ class ConfigureRoomPresenterTests {
 
     @Test
     fun `present - trigger create room with upload error and retry`() = runTest {
-        moleculeFlow(RecompositionClock.Immediate) {
+        moleculeFlow(RecompositionMode.Immediate) {
             presenter.present()
         }.test {
             skipItems(1)
@@ -265,7 +265,7 @@ class ConfigureRoomPresenterTests {
 
     @Test
     fun `present - trigger retry and cancel actions`() = runTest {
-        moleculeFlow(RecompositionClock.Immediate) {
+        moleculeFlow(RecompositionMode.Immediate) {
             presenter.present()
         }.test {
             val initialState = awaitItem()
diff --git a/features/createroom/impl/src/test/kotlin/io/element/android/features/createroom/impl/root/CreateRoomRootPresenterTests.kt b/features/createroom/impl/src/test/kotlin/io/element/android/features/createroom/impl/root/CreateRoomRootPresenterTests.kt
index 8976c77b8e..002e8c77fd 100644
--- a/features/createroom/impl/src/test/kotlin/io/element/android/features/createroom/impl/root/CreateRoomRootPresenterTests.kt
+++ b/features/createroom/impl/src/test/kotlin/io/element/android/features/createroom/impl/root/CreateRoomRootPresenterTests.kt
@@ -16,7 +16,7 @@
 
 package io.element.android.features.createroom.impl.root
 
-import app.cash.molecule.RecompositionClock
+import app.cash.molecule.RecompositionMode
 import app.cash.molecule.moleculeFlow
 import app.cash.turbine.test
 import com.google.common.truth.Truth.assertThat
@@ -27,8 +27,6 @@ import io.element.android.features.createroom.impl.userlist.FakeUserListPresente
 import io.element.android.features.createroom.impl.userlist.UserListDataStore
 import io.element.android.features.createroom.impl.userlist.aUserListState
 import io.element.android.libraries.architecture.Async
-import io.element.android.libraries.core.meta.BuildMeta
-import io.element.android.libraries.core.meta.BuildType
 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.user.MatrixUser
@@ -68,7 +66,7 @@ class CreateRoomRootPresenterTests {
 
     @Test
     fun `present - initial state`() = runTest {
-        moleculeFlow(RecompositionClock.Immediate) {
+        moleculeFlow(RecompositionMode.Immediate) {
             presenter.present()
         }.test {
             val initialState = awaitItem()
@@ -82,7 +80,7 @@ class CreateRoomRootPresenterTests {
 
     @Test
     fun `present - trigger create DM action`() = runTest {
-        moleculeFlow(RecompositionClock.Immediate) {
+        moleculeFlow(RecompositionMode.Immediate) {
             presenter.present()
         }.test {
             val initialState = awaitItem()
@@ -102,7 +100,7 @@ class CreateRoomRootPresenterTests {
 
     @Test
     fun `present - creating a DM records analytics event`() = runTest {
-        moleculeFlow(RecompositionClock.Immediate) {
+        moleculeFlow(RecompositionMode.Immediate) {
             presenter.present()
         }.test {
             val initialState = awaitItem()
@@ -123,7 +121,7 @@ class CreateRoomRootPresenterTests {
 
     @Test
     fun `present - trigger retrieve DM action`() = runTest {
-        moleculeFlow(RecompositionClock.Immediate) {
+        moleculeFlow(RecompositionMode.Immediate) {
             presenter.present()
         }.test {
             val initialState = awaitItem()
@@ -142,7 +140,7 @@ class CreateRoomRootPresenterTests {
 
     @Test
     fun `present - trigger retry create DM action`() = runTest {
-        moleculeFlow(RecompositionClock.Immediate) {
+        moleculeFlow(RecompositionMode.Immediate) {
             presenter.present()
         }.test {
             val initialState = awaitItem()
diff --git a/features/createroom/impl/src/test/kotlin/io/element/android/features/createroom/impl/userlist/DefaultUserListPresenterTests.kt b/features/createroom/impl/src/test/kotlin/io/element/android/features/createroom/impl/userlist/DefaultUserListPresenterTests.kt
index 745bdf74f9..3561387dcf 100644
--- a/features/createroom/impl/src/test/kotlin/io/element/android/features/createroom/impl/userlist/DefaultUserListPresenterTests.kt
+++ b/features/createroom/impl/src/test/kotlin/io/element/android/features/createroom/impl/userlist/DefaultUserListPresenterTests.kt
@@ -16,7 +16,7 @@
 
 package io.element.android.features.createroom.impl.userlist
 
-import app.cash.molecule.RecompositionClock
+import app.cash.molecule.RecompositionMode
 import app.cash.molecule.moleculeFlow
 import app.cash.turbine.test
 import com.google.common.truth.Truth.assertThat
@@ -41,7 +41,7 @@ class DefaultUserListPresenterTests {
                 userRepository,
                 UserListDataStore(),
             )
-        moleculeFlow(RecompositionClock.Immediate) {
+        moleculeFlow(RecompositionMode.Immediate) {
             presenter.present()
         }.test {
             skipItems(1)
@@ -62,7 +62,7 @@ class DefaultUserListPresenterTests {
                 userRepository,
                 UserListDataStore(),
             )
-        moleculeFlow(RecompositionClock.Immediate) {
+        moleculeFlow(RecompositionMode.Immediate) {
             presenter.present()
         }.test {
             skipItems(1)
@@ -83,7 +83,7 @@ class DefaultUserListPresenterTests {
                 userRepository,
                 UserListDataStore(),
             )
-        moleculeFlow(RecompositionClock.Immediate) {
+        moleculeFlow(RecompositionMode.Immediate) {
             presenter.present()
         }.test {
             skipItems(1)
@@ -119,7 +119,7 @@ class DefaultUserListPresenterTests {
                 userRepository,
                 UserListDataStore(),
             )
-        moleculeFlow(RecompositionClock.Immediate) {
+        moleculeFlow(RecompositionMode.Immediate) {
             presenter.present()
         }.test {
             skipItems(1)
@@ -158,7 +158,7 @@ class DefaultUserListPresenterTests {
                 userRepository,
                 UserListDataStore(),
             )
-        moleculeFlow(RecompositionClock.Immediate) {
+        moleculeFlow(RecompositionMode.Immediate) {
             presenter.present()
         }.test {
             skipItems(1)
@@ -183,7 +183,7 @@ class DefaultUserListPresenterTests {
                 userRepository,
                 UserListDataStore(),
             )
-        moleculeFlow(RecompositionClock.Immediate) {
+        moleculeFlow(RecompositionMode.Immediate) {
             presenter.present()
         }.test {
             skipItems(1)
diff --git a/features/ftue/impl/src/main/kotlin/io/element/android/features/ftue/impl/welcome/WelcomeView.kt b/features/ftue/impl/src/main/kotlin/io/element/android/features/ftue/impl/welcome/WelcomeView.kt
index 7397e5ecc5..eebef5b3f2 100644
--- a/features/ftue/impl/src/main/kotlin/io/element/android/features/ftue/impl/welcome/WelcomeView.kt
+++ b/features/ftue/impl/src/main/kotlin/io/element/android/features/ftue/impl/welcome/WelcomeView.kt
@@ -97,9 +97,11 @@ fun WelcomeView(
             }
         },
         footer = {
-            Button(modifier = Modifier.fillMaxWidth(), onClick = onContinueClicked) {
-                Text(text = stringResource(CommonStrings.action_continue))
-            }
+            Button(
+                text = stringResource(CommonStrings.action_continue),
+                modifier = Modifier.fillMaxWidth(),
+                onClick = onContinueClicked
+            )
             Spacer(modifier = Modifier.height(32.dp))
         }
     )
diff --git a/features/ftue/impl/src/main/res/values-de/translations.xml b/features/ftue/impl/src/main/res/values-de/translations.xml
new file mode 100644
index 0000000000..0f2efc1c57
--- /dev/null
+++ b/features/ftue/impl/src/main/res/values-de/translations.xml
@@ -0,0 +1,9 @@
+
+
+  "Anrufe, Standortfreigabe, Suche und mehr werden später in diesem Jahr hinzugefügt."
+  "Der Nachrichtenverlauf für verschlüsselte Räume wird in diesem Update nicht verfügbar sein."
+  "Wir würden uns freuen, wenn du uns über die Einstellungsseite deine Meinung mitteilst."
+  "Los geht\'s!"
+  "Folgendes musst du wissen:"
+  "Willkommen bei %1$s!"
+
diff --git a/features/ftue/impl/src/main/res/values-fr/translations.xml b/features/ftue/impl/src/main/res/values-fr/translations.xml
new file mode 100644
index 0000000000..313a6a533f
--- /dev/null
+++ b/features/ftue/impl/src/main/res/values-fr/translations.xml
@@ -0,0 +1,8 @@
+
+
+  "L’historique des messages pour les salons chiffrés ne sera pas disponible dans cette mise à jour."
+  "Nous serions ravis d’avoir votre avis, n’hésitez pas à nous le partager via la page des paramètres."
+  "C’est parti !"
+  "Voici ce qu’il faut savoir :"
+  "Bienvenue sur %1$s !"
+
diff --git a/features/ftue/impl/src/main/res/values-ru/translations.xml b/features/ftue/impl/src/main/res/values-ru/translations.xml
new file mode 100644
index 0000000000..db4fcd21fc
--- /dev/null
+++ b/features/ftue/impl/src/main/res/values-ru/translations.xml
@@ -0,0 +1,9 @@
+
+
+  "Звонки, опросы, поиск и многое другое будут добавлены позже в этом году."
+  "История сообщений для зашифрованных комнат в этом обновлении будет недоступна."
+  "Мы будем рады услышать ваше мнение, сообщите нам об этом через страницу настроек."
+  "Поехали!"
+  "Вот что вам необходимо знать:"
+  "Добро пожаловать в %1$s!"
+
diff --git a/features/ftue/impl/src/main/res/values-sk/translations.xml b/features/ftue/impl/src/main/res/values-sk/translations.xml
new file mode 100644
index 0000000000..2438518334
--- /dev/null
+++ b/features/ftue/impl/src/main/res/values-sk/translations.xml
@@ -0,0 +1,9 @@
+
+
+  "Hovory, ankety, vyhľadávanie a ďalšie funkcie pribudnú neskôr v tomto roku."
+  "História správ pre zašifrované miestnosti nebude v tejto aktualizácii k dispozícii."
+  "Radi by sme od vás počuli, dajte nám vedieť, čo si myslíte, prostredníctvom stránky nastavení."
+  "Poďme na to!"
+  "Tu je to, čo potrebujete vedieť:"
+  "Vitajte v %1$s!"
+
diff --git a/features/ftue/impl/src/main/res/values-zh-rTW/translations.xml b/features/ftue/impl/src/main/res/values-zh-rTW/translations.xml
new file mode 100644
index 0000000000..6c5d482cb8
--- /dev/null
+++ b/features/ftue/impl/src/main/res/values-zh-rTW/translations.xml
@@ -0,0 +1,4 @@
+
+
+  "開始吧!"
+
diff --git a/features/ftue/impl/src/main/res/values/localazy.xml b/features/ftue/impl/src/main/res/values/localazy.xml
index 17999e7158..05cc72034e 100644
--- a/features/ftue/impl/src/main/res/values/localazy.xml
+++ b/features/ftue/impl/src/main/res/values/localazy.xml
@@ -1,6 +1,6 @@
 
 
-  "Calls, location sharing, search and more will be added later this year."
+  "Calls, polls, search and more will be added later this year."
   "Message history for encrypted rooms won’t be available in this update."
   "We’d love to hear from you, let us know what you think via the settings page."
   "Let\'s go!"
diff --git a/features/ftue/impl/src/test/kotlin/io/element/android/features/ftue/impl/DefaultFtueStateTests.kt b/features/ftue/impl/src/test/kotlin/io/element/android/features/ftue/impl/DefaultFtueStateTests.kt
index ce1683e8e5..cfd489ea2a 100644
--- a/features/ftue/impl/src/test/kotlin/io/element/android/features/ftue/impl/DefaultFtueStateTests.kt
+++ b/features/ftue/impl/src/test/kotlin/io/element/android/features/ftue/impl/DefaultFtueStateTests.kt
@@ -25,7 +25,6 @@ import io.element.android.services.analytics.api.AnalyticsService
 import kotlinx.coroutines.CoroutineScope
 import kotlinx.coroutines.SupervisorJob
 import kotlinx.coroutines.cancel
-import kotlinx.coroutines.test.TestScope
 import kotlinx.coroutines.test.runTest
 import org.junit.Test
 
diff --git a/features/invitelist/impl/src/main/kotlin/io/element/android/features/invitelist/impl/InviteListPresenter.kt b/features/invitelist/impl/src/main/kotlin/io/element/android/features/invitelist/impl/InviteListPresenter.kt
index 21a57b48a7..8c43b815ae 100644
--- a/features/invitelist/impl/src/main/kotlin/io/element/android/features/invitelist/impl/InviteListPresenter.kt
+++ b/features/invitelist/impl/src/main/kotlin/io/element/android/features/invitelist/impl/InviteListPresenter.kt
@@ -36,7 +36,7 @@ import io.element.android.libraries.designsystem.components.avatar.AvatarData
 import io.element.android.libraries.designsystem.components.avatar.AvatarSize
 import io.element.android.libraries.matrix.api.MatrixClient
 import io.element.android.libraries.matrix.api.core.RoomId
-import io.element.android.libraries.matrix.api.room.RoomSummary
+import io.element.android.libraries.matrix.api.roomlist.RoomSummary
 import io.element.android.libraries.push.api.notifications.NotificationDrawerManager
 import io.element.android.services.analytics.api.AnalyticsService
 import io.element.android.services.analytics.api.extensions.toAnalyticsJoinedRoom
@@ -56,8 +56,9 @@ class InviteListPresenter @Inject constructor(
     @Composable
     override fun present(): InviteListState {
         val invites by client
-            .roomSummaryDataSource
-            .inviteRooms()
+            .roomListService
+            .invites()
+            .summaries
             .collectAsState()
 
         var seenInvites by remember { mutableStateOf>(emptySet()) }
@@ -152,8 +153,7 @@ class InviteListPresenter @Inject constructor(
             client.getRoom(roomId)?.use {
                 it.leave().getOrThrow()
                 notificationDrawerManager.clearMembershipNotificationForRoom(client.sessionId, roomId)
-            }
-            Unit
+            }.let { }
         }.runCatchingUpdatingState(declinedAction)
     }
 
diff --git a/features/invitelist/impl/src/main/kotlin/io/element/android/features/invitelist/impl/InviteListView.kt b/features/invitelist/impl/src/main/kotlin/io/element/android/features/invitelist/impl/InviteListView.kt
index e2e5927a66..a129668305 100644
--- a/features/invitelist/impl/src/main/kotlin/io/element/android/features/invitelist/impl/InviteListView.kt
+++ b/features/invitelist/impl/src/main/kotlin/io/element/android/features/invitelist/impl/InviteListView.kt
@@ -86,7 +86,6 @@ fun InviteListView(
             title = stringResource(titleResource),
             submitText = stringResource(CommonStrings.action_decline),
             cancelText = stringResource(CommonStrings.action_cancel),
-            emphasizeSubmitButton = true,
             onSubmitClicked = { state.eventSink(InviteListEvents.ConfirmDeclineInvite) },
             onDismiss = { state.eventSink(InviteListEvents.CancelDeclineInvite) }
         )
diff --git a/features/invitelist/impl/src/main/kotlin/io/element/android/features/invitelist/impl/components/InviteSummaryRow.kt b/features/invitelist/impl/src/main/kotlin/io/element/android/features/invitelist/impl/components/InviteSummaryRow.kt
index c2bbd5b023..c677fe158f 100644
--- a/features/invitelist/impl/src/main/kotlin/io/element/android/features/invitelist/impl/components/InviteSummaryRow.kt
+++ b/features/invitelist/impl/src/main/kotlin/io/element/android/features/invitelist/impl/components/InviteSummaryRow.kt
@@ -20,7 +20,6 @@ import androidx.compose.foundation.layout.Arrangement
 import androidx.compose.foundation.layout.Box
 import androidx.compose.foundation.layout.Column
 import androidx.compose.foundation.layout.IntrinsicSize
-import androidx.compose.foundation.layout.PaddingValues
 import androidx.compose.foundation.layout.Row
 import androidx.compose.foundation.layout.Spacer
 import androidx.compose.foundation.layout.fillMaxWidth
@@ -49,8 +48,8 @@ import io.element.android.libraries.designsystem.atomic.atoms.UnreadIndicatorAto
 import io.element.android.libraries.designsystem.components.avatar.Avatar
 import io.element.android.libraries.designsystem.preview.ElementPreviewDark
 import io.element.android.libraries.designsystem.preview.ElementPreviewLight
-import io.element.android.libraries.designsystem.theme.aliasButtonText
 import io.element.android.libraries.designsystem.theme.components.Button
+import io.element.android.libraries.designsystem.theme.components.ButtonSize
 import io.element.android.libraries.designsystem.theme.components.OutlinedButton
 import io.element.android.libraries.designsystem.theme.components.Text
 import io.element.android.libraries.theme.ElementTheme
@@ -133,23 +132,19 @@ internal fun DefaultInviteSummaryRow(
             // CTAs
             Row(Modifier.padding(top = 12.dp)) {
                 OutlinedButton(
-                    content = { Text(stringResource(CommonStrings.action_decline), style = ElementTheme.typography.aliasButtonText) },
+                    text = stringResource(CommonStrings.action_decline),
                     onClick = onDeclineClicked,
-                    modifier = Modifier
-                        .weight(1f)
-                        .heightIn(max = 36.dp),
-                    contentPadding = PaddingValues(horizontal = 24.dp, vertical = 0.dp),
+                    modifier = Modifier.weight(1f),
+                    size = ButtonSize.Medium,
                 )
 
                 Spacer(modifier = Modifier.width(12.dp))
 
                 Button(
-                    content = { Text(stringResource(CommonStrings.action_accept), style = ElementTheme.typography.aliasButtonText) },
+                    text = stringResource(CommonStrings.action_accept),
                     onClick = onAcceptClicked,
-                    modifier = Modifier
-                        .weight(1f)
-                        .heightIn(max = 36.dp),
-                    contentPadding = PaddingValues(horizontal = 24.dp, vertical = 0.dp),
+                    modifier = Modifier.weight(1f),
+                    size = ButtonSize.Medium,
                 )
             }
         }
diff --git a/features/invitelist/impl/src/main/res/values-de/translations.xml b/features/invitelist/impl/src/main/res/values-de/translations.xml
index 1e2fcc2e86..2cec59d6a0 100644
--- a/features/invitelist/impl/src/main/res/values-de/translations.xml
+++ b/features/invitelist/impl/src/main/res/values-de/translations.xml
@@ -1,8 +1,8 @@
 
 
-  "Möchten Sie den Beitritt zu %1$s wirklich ablehnen?"
+  "Möchtest du den Beitritt zu %1$s wirklich ablehnen?"
   "Einladung ablehnen"
-  "Möchten Sie den Chat mit %1$s wirklich ablehnen?"
+  "Möchtest du den privaten Chat mit %1$s wirklich ablehnen?"
   "Chat ablehnen"
   "Keine Einladungen"
   "%1$s (%2$s) hat dich eingeladen"
diff --git a/features/invitelist/impl/src/main/res/values-ru/translations.xml b/features/invitelist/impl/src/main/res/values-ru/translations.xml
new file mode 100644
index 0000000000..0f1c30cb09
--- /dev/null
+++ b/features/invitelist/impl/src/main/res/values-ru/translations.xml
@@ -0,0 +1,9 @@
+
+
+  "Вы уверены, что хотите отклонить приглашение в %1$s?"
+  "Отклонить приглашение"
+  "Вы уверены, что хотите отказаться от приватного общения с %1$s?"
+  "Отклонить чат"
+  "Нет приглашений"
+  "%1$s (%2$s) пригласил вас"
+
diff --git a/features/invitelist/impl/src/test/kotlin/io/element/android/features/invitelist/impl/InviteListPresenterTests.kt b/features/invitelist/impl/src/test/kotlin/io/element/android/features/invitelist/impl/InviteListPresenterTests.kt
index 1dd9068a1f..f3eef2784c 100644
--- a/features/invitelist/impl/src/test/kotlin/io/element/android/features/invitelist/impl/InviteListPresenterTests.kt
+++ b/features/invitelist/impl/src/test/kotlin/io/element/android/features/invitelist/impl/InviteListPresenterTests.kt
@@ -16,7 +16,7 @@
 
 package io.element.android.features.invitelist.impl
 
-import app.cash.molecule.RecompositionClock
+import app.cash.molecule.RecompositionMode
 import app.cash.molecule.moleculeFlow
 import app.cash.turbine.test
 import com.google.common.truth.Truth
@@ -30,8 +30,8 @@ import io.element.android.libraries.matrix.api.MatrixClient
 import io.element.android.libraries.matrix.api.core.RoomId
 import io.element.android.libraries.matrix.api.room.RoomMember
 import io.element.android.libraries.matrix.api.room.RoomMembershipState
-import io.element.android.libraries.matrix.api.room.RoomSummary
-import io.element.android.libraries.matrix.api.room.RoomSummaryDetails
+import io.element.android.libraries.matrix.api.roomlist.RoomSummary
+import io.element.android.libraries.matrix.api.roomlist.RoomSummaryDetails
 import io.element.android.libraries.matrix.test.AN_AVATAR_URL
 import io.element.android.libraries.matrix.test.A_ROOM_ID
 import io.element.android.libraries.matrix.test.A_ROOM_ID_2
@@ -40,7 +40,7 @@ import io.element.android.libraries.matrix.test.A_USER_ID
 import io.element.android.libraries.matrix.test.A_USER_NAME
 import io.element.android.libraries.matrix.test.FakeMatrixClient
 import io.element.android.libraries.matrix.test.room.FakeMatrixRoom
-import io.element.android.libraries.matrix.test.room.FakeRoomSummaryDataSource
+import io.element.android.libraries.matrix.test.roomlist.FakeRoomListService
 import io.element.android.libraries.push.api.notifications.NotificationDrawerManager
 import io.element.android.libraries.push.test.notifications.FakeNotificationDrawerManager
 import io.element.android.services.analytics.api.AnalyticsService
@@ -51,17 +51,17 @@ class InviteListPresenterTests {
 
     @Test
     fun `present - starts empty, adds invites when received`() = runTest {
-        val roomSummaryDataSource = FakeRoomSummaryDataSource()
+        val roomListService = FakeRoomListService()
         val presenter = createPresenter(
-            FakeMatrixClient(roomSummaryDataSource = roomSummaryDataSource)
+            FakeMatrixClient(roomListService = roomListService)
         )
-        moleculeFlow(RecompositionClock.Immediate) {
+        moleculeFlow(RecompositionMode.Immediate) {
             presenter.present()
         }.test {
             val initialState = awaitItem()
             Truth.assertThat(initialState.inviteList).isEmpty()
 
-            roomSummaryDataSource.postInviteRooms(listOf(aRoomSummary()))
+            roomListService.postInviteRooms(listOf(aRoomSummary()))
 
             val withInviteState = awaitItem()
             Truth.assertThat(withInviteState.inviteList.size).isEqualTo(1)
@@ -72,11 +72,11 @@ class InviteListPresenterTests {
 
     @Test
     fun `present - uses user ID and avatar for direct invites`() = runTest {
-        val roomSummaryDataSource = FakeRoomSummaryDataSource().withDirectChatInvitation()
+        val roomListService = FakeRoomListService().withDirectChatInvitation()
         val presenter = createPresenter(
-            FakeMatrixClient(roomSummaryDataSource = roomSummaryDataSource)
+            FakeMatrixClient(roomListService = roomListService)
         )
-        moleculeFlow(RecompositionClock.Immediate) {
+        moleculeFlow(RecompositionMode.Immediate) {
             presenter.present()
         }.test {
             val withInviteState = awaitItem()
@@ -98,11 +98,11 @@ class InviteListPresenterTests {
 
     @Test
     fun `present - includes sender details for room invites`() = runTest {
-        val roomSummaryDataSource = FakeRoomSummaryDataSource().withRoomInvitation()
+        val roomListService = FakeRoomListService().withRoomInvitation()
         val presenter = createPresenter(
-            FakeMatrixClient(roomSummaryDataSource = roomSummaryDataSource)
+            FakeMatrixClient(roomListService = roomListService)
         )
-        moleculeFlow(RecompositionClock.Immediate) {
+        moleculeFlow(RecompositionMode.Immediate) {
             presenter.present()
         }.test {
             val withInviteState = awaitItem()
@@ -122,16 +122,16 @@ class InviteListPresenterTests {
 
     @Test
     fun `present - shows confirm dialog for declining direct chat invites`() = runTest {
-        val roomSummaryDataSource = FakeRoomSummaryDataSource().withDirectChatInvitation()
+        val roomListService = FakeRoomListService().withDirectChatInvitation()
         val presenter = InviteListPresenter(
             FakeMatrixClient(
-                roomSummaryDataSource = roomSummaryDataSource,
+                roomListService = roomListService,
             ),
             FakeSeenInvitesStore(),
             FakeAnalyticsService(),
             FakeNotificationDrawerManager()
         )
-        moleculeFlow(RecompositionClock.Immediate) {
+        moleculeFlow(RecompositionMode.Immediate) {
             presenter.present()
         }.test {
             val originalState = awaitItem()
@@ -148,11 +148,11 @@ class InviteListPresenterTests {
 
     @Test
     fun `present - shows confirm dialog for declining room invites`() = runTest {
-        val roomSummaryDataSource = FakeRoomSummaryDataSource().withRoomInvitation()
+        val roomListService = FakeRoomListService().withRoomInvitation()
         val presenter = createPresenter(
-            FakeMatrixClient(roomSummaryDataSource = roomSummaryDataSource)
+            FakeMatrixClient(roomListService = roomListService)
         )
-        moleculeFlow(RecompositionClock.Immediate) {
+        moleculeFlow(RecompositionMode.Immediate) {
             presenter.present()
         }.test {
             val originalState = awaitItem()
@@ -169,11 +169,11 @@ class InviteListPresenterTests {
 
     @Test
     fun `present - hides confirm dialog when cancelling`() = runTest {
-        val roomSummaryDataSource = FakeRoomSummaryDataSource().withRoomInvitation()
+        val roomListService = FakeRoomListService().withRoomInvitation()
         val presenter = createPresenter(
-            FakeMatrixClient(roomSummaryDataSource = roomSummaryDataSource)
+            FakeMatrixClient(roomListService = roomListService)
         )
-        moleculeFlow(RecompositionClock.Immediate) {
+        moleculeFlow(RecompositionMode.Immediate) {
             presenter.present()
         }.test {
             val originalState = awaitItem()
@@ -190,16 +190,16 @@ class InviteListPresenterTests {
 
     @Test
     fun `present - declines invite after confirming`() = runTest {
-        val roomSummaryDataSource = FakeRoomSummaryDataSource().withRoomInvitation()
+        val roomListService = FakeRoomListService().withRoomInvitation()
         val fakeNotificationDrawerManager = FakeNotificationDrawerManager()
         val client = FakeMatrixClient(
-            roomSummaryDataSource = roomSummaryDataSource,
+            roomListService = roomListService,
         )
         val room = FakeMatrixRoom()
         val presenter = createPresenter(client = client, notificationDrawerManager = fakeNotificationDrawerManager)
         client.givenGetRoomResult(A_ROOM_ID, room)
 
-        moleculeFlow(RecompositionClock.Immediate) {
+        moleculeFlow(RecompositionMode.Immediate) {
             presenter.present()
         }.test {
             val originalState = awaitItem()
@@ -217,9 +217,9 @@ class InviteListPresenterTests {
 
     @Test
     fun `present - declines invite after confirming and sets state on error`() = runTest {
-        val roomSummaryDataSource = FakeRoomSummaryDataSource().withRoomInvitation()
+        val roomListService = FakeRoomListService().withRoomInvitation()
         val client = FakeMatrixClient(
-            roomSummaryDataSource = roomSummaryDataSource,
+            roomListService = roomListService,
         )
         val room = FakeMatrixRoom()
         val presenter = createPresenter(client)
@@ -227,7 +227,7 @@ class InviteListPresenterTests {
         room.givenLeaveRoomError(ex)
         client.givenGetRoomResult(A_ROOM_ID, room)
 
-        moleculeFlow(RecompositionClock.Immediate) {
+        moleculeFlow(RecompositionMode.Immediate) {
             presenter.present()
         }.test {
             val originalState = awaitItem()
@@ -247,9 +247,9 @@ class InviteListPresenterTests {
 
     @Test
     fun `present - dismisses declining error state`() = runTest {
-        val roomSummaryDataSource = FakeRoomSummaryDataSource().withRoomInvitation()
+        val roomListService = FakeRoomListService().withRoomInvitation()
         val client = FakeMatrixClient(
-            roomSummaryDataSource = roomSummaryDataSource,
+            roomListService = roomListService,
         )
         val room = FakeMatrixRoom()
         val presenter = createPresenter(client)
@@ -257,7 +257,7 @@ class InviteListPresenterTests {
         room.givenLeaveRoomError(ex)
         client.givenGetRoomResult(A_ROOM_ID, room)
 
-        moleculeFlow(RecompositionClock.Immediate) {
+        moleculeFlow(RecompositionMode.Immediate) {
             presenter.present()
         }.test {
             val originalState = awaitItem()
@@ -279,16 +279,16 @@ class InviteListPresenterTests {
 
     @Test
     fun `present - accepts invites and sets state on success`() = runTest {
-        val roomSummaryDataSource = FakeRoomSummaryDataSource().withRoomInvitation()
+        val roomListService = FakeRoomListService().withRoomInvitation()
         val fakeNotificationDrawerManager = FakeNotificationDrawerManager()
         val client = FakeMatrixClient(
-            roomSummaryDataSource = roomSummaryDataSource,
+            roomListService = roomListService,
         )
         val room = FakeMatrixRoom()
         val presenter = createPresenter(client = client, notificationDrawerManager = fakeNotificationDrawerManager)
         client.givenGetRoomResult(A_ROOM_ID, room)
 
-        moleculeFlow(RecompositionClock.Immediate) {
+        moleculeFlow(RecompositionMode.Immediate) {
             presenter.present()
         }.test {
             val originalState = awaitItem()
@@ -303,9 +303,9 @@ class InviteListPresenterTests {
 
     @Test
     fun `present - accepts invites and sets state on error`() = runTest {
-        val roomSummaryDataSource = FakeRoomSummaryDataSource().withRoomInvitation()
+        val roomListService = FakeRoomListService().withRoomInvitation()
         val client = FakeMatrixClient(
-            roomSummaryDataSource = roomSummaryDataSource,
+            roomListService = roomListService,
         )
         val room = FakeMatrixRoom()
         val presenter = createPresenter(client)
@@ -313,7 +313,7 @@ class InviteListPresenterTests {
         room.givenJoinRoomResult(Result.failure(ex))
         client.givenGetRoomResult(A_ROOM_ID, room)
 
-        moleculeFlow(RecompositionClock.Immediate) {
+        moleculeFlow(RecompositionMode.Immediate) {
             presenter.present()
         }.test {
             val originalState = awaitItem()
@@ -325,9 +325,9 @@ class InviteListPresenterTests {
 
     @Test
     fun `present - dismisses accepting error state`() = runTest {
-        val roomSummaryDataSource = FakeRoomSummaryDataSource().withRoomInvitation()
+        val roomListService = FakeRoomListService().withRoomInvitation()
         val client = FakeMatrixClient(
-            roomSummaryDataSource = roomSummaryDataSource,
+            roomListService = roomListService,
         )
         val room = FakeMatrixRoom()
         val presenter = createPresenter(client)
@@ -335,7 +335,7 @@ class InviteListPresenterTests {
         room.givenJoinRoomResult(Result.failure(ex))
         client.givenGetRoomResult(A_ROOM_ID, room)
 
-        moleculeFlow(RecompositionClock.Immediate) {
+        moleculeFlow(RecompositionMode.Immediate) {
             presenter.present()
         }.test {
             val originalState = awaitItem()
@@ -352,35 +352,35 @@ class InviteListPresenterTests {
 
     @Test
     fun `present - stores seen invites when received`() = runTest {
-        val roomSummaryDataSource = FakeRoomSummaryDataSource()
+        val roomListService = FakeRoomListService()
         val store = FakeSeenInvitesStore()
         val presenter = InviteListPresenter(
             FakeMatrixClient(
-                roomSummaryDataSource = roomSummaryDataSource,
+                roomListService = roomListService,
             ),
             store,
             FakeAnalyticsService(),
             FakeNotificationDrawerManager()
         )
-        moleculeFlow(RecompositionClock.Immediate) {
+        moleculeFlow(RecompositionMode.Immediate) {
             presenter.present()
         }.test {
             awaitItem()
 
             // When one invite is received, that ID is saved
-            roomSummaryDataSource.postInviteRooms(listOf(aRoomSummary()))
+            roomListService.postInviteRooms(listOf(aRoomSummary()))
 
             awaitItem()
             Truth.assertThat(store.getProvidedRoomIds()).isEqualTo(setOf(A_ROOM_ID))
 
             // When a second is added, both are saved
-            roomSummaryDataSource.postInviteRooms(listOf(aRoomSummary(), aRoomSummary(A_ROOM_ID_2)))
+            roomListService.postInviteRooms(listOf(aRoomSummary(), aRoomSummary(A_ROOM_ID_2)))
 
             awaitItem()
             Truth.assertThat(store.getProvidedRoomIds()).isEqualTo(setOf(A_ROOM_ID, A_ROOM_ID_2))
 
             // When they're both dismissed, an empty set is saved
-            roomSummaryDataSource.postInviteRooms(listOf())
+            roomListService.postInviteRooms(listOf())
 
             awaitItem()
             Truth.assertThat(store.getProvidedRoomIds()).isEmpty()
@@ -389,23 +389,23 @@ class InviteListPresenterTests {
 
     @Test
     fun `present - marks invite as new if they're unseen`() = runTest {
-        val roomSummaryDataSource = FakeRoomSummaryDataSource()
+        val roomListService = FakeRoomListService()
         val store = FakeSeenInvitesStore()
         store.publishRoomIds(setOf(A_ROOM_ID))
         val presenter = InviteListPresenter(
             FakeMatrixClient(
-                roomSummaryDataSource = roomSummaryDataSource,
+                roomListService = roomListService,
             ),
             store,
             FakeAnalyticsService(),
             FakeNotificationDrawerManager()
         )
-        moleculeFlow(RecompositionClock.Immediate) {
+        moleculeFlow(RecompositionMode.Immediate) {
             presenter.present()
         }.test {
             awaitItem()
 
-            roomSummaryDataSource.postInviteRooms(listOf(aRoomSummary(), aRoomSummary(A_ROOM_ID_2)))
+            roomListService.postInviteRooms(listOf(aRoomSummary(), aRoomSummary(A_ROOM_ID_2)))
             skipItems(1)
 
             val withInviteState = awaitItem()
@@ -417,7 +417,7 @@ class InviteListPresenterTests {
         }
     }
 
-    private suspend fun FakeRoomSummaryDataSource.withRoomInvitation(): FakeRoomSummaryDataSource {
+    private suspend fun FakeRoomListService.withRoomInvitation(): FakeRoomListService {
         postInviteRooms(
             listOf(
                 RoomSummary.Filled(
@@ -446,7 +446,7 @@ class InviteListPresenterTests {
         return this
     }
 
-    private suspend fun FakeRoomSummaryDataSource.withDirectChatInvitation(): FakeRoomSummaryDataSource {
+    private suspend fun FakeRoomListService.withDirectChatInvitation(): FakeRoomListService {
         postInviteRooms(
             listOf(
                 RoomSummary.Filled(
diff --git a/features/leaveroom/impl/src/test/kotlin/io/element/android/features/leaveroom/impl/LeaveRoomPresenterImplTest.kt b/features/leaveroom/impl/src/test/kotlin/io/element/android/features/leaveroom/impl/LeaveRoomPresenterImplTest.kt
index 03eeb3adc6..3075d3c686 100644
--- a/features/leaveroom/impl/src/test/kotlin/io/element/android/features/leaveroom/impl/LeaveRoomPresenterImplTest.kt
+++ b/features/leaveroom/impl/src/test/kotlin/io/element/android/features/leaveroom/impl/LeaveRoomPresenterImplTest.kt
@@ -16,7 +16,7 @@
 
 package io.element.android.features.leaveroom.impl
 
-import app.cash.molecule.RecompositionClock
+import app.cash.molecule.RecompositionMode
 import app.cash.molecule.moleculeFlow
 import app.cash.turbine.test
 import com.google.common.truth.Truth.assertThat
@@ -40,7 +40,7 @@ class LeaveRoomPresenterImplTest {
     @Test
     fun `present - initial state hides all dialogs`() = runTest {
         val presenter = createPresenter()
-        moleculeFlow(RecompositionClock.Immediate) {
+        moleculeFlow(RecompositionMode.Immediate) {
             presenter.present()
         }.test {
             val initialState = awaitItem()
@@ -60,7 +60,7 @@ class LeaveRoomPresenterImplTest {
                 )
             }
         )
-        moleculeFlow(RecompositionClock.Immediate) {
+        moleculeFlow(RecompositionMode.Immediate) {
             presenter.present()
         }.test {
             val initialState = awaitItem()
@@ -80,7 +80,7 @@ class LeaveRoomPresenterImplTest {
                 )
             }
         )
-        moleculeFlow(RecompositionClock.Immediate) {
+        moleculeFlow(RecompositionMode.Immediate) {
             presenter.present()
         }.test {
             val initialState = awaitItem()
@@ -100,7 +100,7 @@ class LeaveRoomPresenterImplTest {
                 )
             }
         )
-        moleculeFlow(RecompositionClock.Immediate) {
+        moleculeFlow(RecompositionMode.Immediate) {
             presenter.present()
         }.test {
             val initialState = awaitItem()
@@ -122,7 +122,7 @@ class LeaveRoomPresenterImplTest {
             },
             roomMembershipObserver = roomMembershipObserver
         )
-        moleculeFlow(RecompositionClock.Immediate) {
+        moleculeFlow(RecompositionMode.Immediate) {
             presenter.present()
         }.test {
             val initialState = awaitItem()
@@ -145,7 +145,7 @@ class LeaveRoomPresenterImplTest {
                 )
             }
         )
-        moleculeFlow(RecompositionClock.Immediate) {
+        moleculeFlow(RecompositionMode.Immediate) {
             presenter.present()
         }.test {
             val initialState = awaitItem()
@@ -167,7 +167,7 @@ class LeaveRoomPresenterImplTest {
                 )
             }
         )
-        moleculeFlow(RecompositionClock.Immediate) {
+        moleculeFlow(RecompositionMode.Immediate) {
             presenter.present()
         }.test {
             val initialState = awaitItem()
@@ -191,7 +191,7 @@ class LeaveRoomPresenterImplTest {
                 )
             }
         )
-        moleculeFlow(RecompositionClock.Immediate) {
+        moleculeFlow(RecompositionMode.Immediate) {
             presenter.present()
         }.test {
             val initialState = awaitItem()
diff --git a/features/location/api/build.gradle.kts b/features/location/api/build.gradle.kts
index 6de297fe77..bef0e77b67 100644
--- a/features/location/api/build.gradle.kts
+++ b/features/location/api/build.gradle.kts
@@ -22,12 +22,12 @@ plugins {
     id("kotlin-parcelize")
 }
 
-fun readLocalProperty(name: String) = Properties().apply {
+fun readLocalProperty(name: String): String? = Properties().apply {
     try {
         load(rootProject.file("local.properties").reader())
     } catch (ignored: java.io.IOException) {
     }
-}[name]
+}.getProperty(name)
 
 android {
     namespace = "io.element.android.features.location.api"
@@ -37,9 +37,23 @@ android {
             type = "string",
             name = "maptiler_api_key",
             value = System.getenv("ELEMENT_ANDROID_MAPTILER_API_KEY")
-                ?: readLocalProperty("services.maptiler.apikey") as? String
+                ?: readLocalProperty("services.maptiler.apikey")
                 ?: ""
         )
+        resValue(
+            type = "string",
+            name = "maptiler_light_map_id",
+            value = System.getenv("ELEMENT_ANDROID_MAPTILER_LIGHT_MAP_ID")
+                ?: readLocalProperty("services.maptiler.lightMapId")
+                ?: "basic-v2" // fall back to maptiler's default light map.
+        )
+        resValue(
+            type = "string",
+            name = "maptiler_dark_map_id",
+            value = System.getenv("ELEMENT_ANDROID_MAPTILER_DARK_MAP_ID")
+                ?: readLocalProperty("services.maptiler.darkMapId")
+                ?: "basic-v2-dark" // fall back to maptiler's default dark map.
+        )
     }
 }
 
diff --git a/features/location/api/src/main/kotlin/io/element/android/features/location/api/StaticMapView.kt b/features/location/api/src/main/kotlin/io/element/android/features/location/api/StaticMapView.kt
index 14390d0f4f..50d400092a 100644
--- a/features/location/api/src/main/kotlin/io/element/android/features/location/api/StaticMapView.kt
+++ b/features/location/api/src/main/kotlin/io/element/android/features/location/api/StaticMapView.kt
@@ -29,16 +29,16 @@ import androidx.compose.ui.Modifier
 import androidx.compose.ui.graphics.Color
 import androidx.compose.ui.layout.ContentScale
 import androidx.compose.ui.platform.LocalContext
-import androidx.compose.ui.unit.IntOffset
+import androidx.compose.ui.platform.LocalDensity
 import androidx.compose.ui.unit.dp
 import coil.compose.AsyncImagePainter
 import coil.compose.rememberAsyncImagePainter
 import coil.request.ImageRequest
 import io.element.android.features.location.api.internal.StaticMapPlaceholder
-import io.element.android.features.location.api.internal.staticMapUrl
+import io.element.android.features.location.api.internal.StaticMapUrlBuilder
+import io.element.android.features.location.api.internal.centerBottomEdge
 import io.element.android.libraries.designsystem.preview.DayNightPreviews
 import io.element.android.libraries.designsystem.preview.ElementPreview
-import io.element.android.libraries.designsystem.text.toDp
 import io.element.android.libraries.designsystem.theme.components.Icon
 import io.element.android.libraries.theme.ElementTheme
 import timber.log.Timber
@@ -65,23 +65,22 @@ fun StaticMapView(
     ) {
         val context = LocalContext.current
         var retryHash by remember { mutableStateOf(0) }
+        val builder = remember { StaticMapUrlBuilder(context) }
         val painter = rememberAsyncImagePainter(
             model = if (constraints.isZero) {
                 // Avoid building a URL if any of the size constraints is zero (else it will thrown an exception).
                 null
             } else {
-                ImageRequest.Builder(LocalContext.current)
+                ImageRequest.Builder(context)
                     .data(
-                        staticMapUrl(
-                            context = context,
+                        builder.build(
                             lat = lat,
                             lon = lon,
                             zoom = zoom,
                             darkMode = darkMode,
-                            // Size the map based on DP rather than pixels, as otherwise the features and attribution
-                            // end up being illegibly tiny on high density displays.
-                            width = constraints.maxWidth.toDp().value.toInt(),
-                            height = constraints.maxHeight.toDp().value.toInt(),
+                            width = constraints.maxWidth,
+                            height = constraints.maxHeight,
+                            density = LocalDensity.current.density,
                         )
                     )
                     .size(width = constraints.maxWidth, height = constraints.maxHeight)
@@ -106,13 +105,7 @@ fun StaticMapView(
                 resourceId = DesignSystemR.drawable.pin,
                 contentDescription = null,
                 tint = Color.Unspecified,
-                modifier = Modifier.align { size, space, _ ->
-                    // Center bottom edge of pin (i.e. its arrow) to center of screen
-                    IntOffset(
-                        x = (space.width - size.width) / 2,
-                        y = (space.height / 2) - size.height,
-                    )
-                }
+                modifier = Modifier.centerBottomEdge(this),
             )
         } else {
             StaticMapPlaceholder(
@@ -127,7 +120,7 @@ fun StaticMapView(
 
 @DayNightPreviews
 @Composable
-fun StaticMapViewPreview() = ElementPreview {
+internal fun StaticMapViewPreview() = ElementPreview {
     StaticMapView(
         lat = 0.0,
         lon = 0.0,
diff --git a/features/location/api/src/main/kotlin/io/element/android/features/location/api/internal/MapTilerConfig.kt b/features/location/api/src/main/kotlin/io/element/android/features/location/api/internal/MapTilerConfig.kt
new file mode 100644
index 0000000000..9e20d5179b
--- /dev/null
+++ b/features/location/api/src/main/kotlin/io/element/android/features/location/api/internal/MapTilerConfig.kt
@@ -0,0 +1,30 @@
+/*
+ * Copyright (c) 2023 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
+ *
+ *     http://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.features.location.api.internal
+
+import android.content.Context
+import io.element.android.features.location.api.R
+
+internal const val MAPTILER_BASE_URL = "https://api.maptiler.com/maps"
+
+internal fun Context.mapId(darkMode: Boolean) = when (darkMode) {
+    true -> getString(R.string.maptiler_dark_map_id)
+    false -> getString(R.string.maptiler_light_map_id)
+}
+
+internal val Context.apiKey: String
+    get() = getString(R.string.maptiler_api_key)
diff --git a/features/location/api/src/main/kotlin/io/element/android/features/location/api/internal/MapTilerStaticMapUrlBuilder.kt b/features/location/api/src/main/kotlin/io/element/android/features/location/api/internal/MapTilerStaticMapUrlBuilder.kt
new file mode 100644
index 0000000000..927e890248
--- /dev/null
+++ b/features/location/api/src/main/kotlin/io/element/android/features/location/api/internal/MapTilerStaticMapUrlBuilder.kt
@@ -0,0 +1,93 @@
+/*
+ * Copyright (c) 2023 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
+ *
+ *     http://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.features.location.api.internal
+
+import android.content.Context
+import kotlin.math.roundToInt
+
+/**
+ * Builds an URL for MapTiler's Static Maps API.
+ *
+ * https://docs.maptiler.com/cloud/api/static-maps/
+ */
+internal class MapTilerStaticMapUrlBuilder(
+    private val apiKey: String,
+    private val lightMapId: String,
+    private val darkMapId: String,
+) : StaticMapUrlBuilder {
+
+    constructor(context: Context) : this(
+        apiKey = context.apiKey,
+        lightMapId = context.mapId(darkMode = false),
+        darkMapId = context.mapId(darkMode = true),
+    )
+
+    override fun build(
+        lat: Double,
+        lon: Double,
+        zoom: Double,
+        darkMode: Boolean,
+        width: Int,
+        height: Int,
+        density: Float
+    ): String {
+        val mapId = if (darkMode) darkMapId else lightMapId
+        val finalZoom = zoom.coerceIn(zoomRange)
+
+        // Request @2x density for xhdpi and above (xhdpi == 320dpi == 2x density).
+        val is2x = density >= 2
+
+        // Scale requested width/height according to the reported display density.
+        val (finalWidth, finalHeight) = coerceWidthAndHeight(
+            width = (width / density).roundToInt(),
+            height = (height / density).roundToInt(),
+            is2x = is2x,
+        )
+
+        val scale = if (is2x) "@2x" else ""
+
+        // Since Maptiler doesn't support arbitrary dpi scaling, we stick to 2x sized
+        // images even on displays with density higher than 2x, thereby yielding an
+        // image smaller than the available space in pixels.
+        // The resulting image will have to be scaled to fit the available space in order
+        // to keep the perceived content size constant at the expense of sharpness.
+        return "$MAPTILER_BASE_URL/${mapId}/static/${lon},${lat},${finalZoom}/${finalWidth}x${finalHeight}${scale}.webp?key=${apiKey}&attribution=bottomleft"
+    }
+}
+
+private fun coerceWidthAndHeight(width: Int, height: Int, is2x: Boolean): Pair {
+    if (width <= 0 || height <= 0) {
+        // This effectively yields an URL which asks for a 0x0 image which will result in an HTTP error,
+        // but it's better than e.g. asking for a 1x1 image which would be unreadable and increase usage costs.
+        return 0 to 0
+    }
+    val aspectRatio = width.toDouble() / height.toDouble()
+    val range = if (is2x) widthHeightRange2x else widthHeightRange
+    return if (width >= height) {
+        width.coerceIn(range).let { coercedWidth ->
+            coercedWidth to (coercedWidth / aspectRatio).roundToInt()
+        }
+    } else {
+        height.coerceIn(range).let { coercedHeight ->
+            (coercedHeight * aspectRatio).roundToInt() to coercedHeight
+        }
+    }
+}
+
+private val widthHeightRange = 1..2048 // API will error if outside 1-2048 range @1x.
+private val widthHeightRange2x = 1..1024 // API will error if outside 1-1024 range @2x.
+private val zoomRange = 0.0..22.0 // API will error if outside 0-22 range.
diff --git a/features/location/api/src/main/kotlin/io/element/android/features/location/api/internal/MapTilerTileServerStyleUriBuilder.kt b/features/location/api/src/main/kotlin/io/element/android/features/location/api/internal/MapTilerTileServerStyleUriBuilder.kt
new file mode 100644
index 0000000000..6972e45330
--- /dev/null
+++ b/features/location/api/src/main/kotlin/io/element/android/features/location/api/internal/MapTilerTileServerStyleUriBuilder.kt
@@ -0,0 +1,39 @@
+/*
+ * Copyright (c) 2023 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
+ *
+ *     http://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.
+ */
+
+@file:JvmName("TileServerStyleUriBuilderKt")
+
+package io.element.android.features.location.api.internal
+
+import android.content.Context
+
+internal class MapTilerTileServerStyleUriBuilder(
+    private val apiKey: String,
+    private val lightMapId: String,
+    private val darkMapId: String,
+) : TileServerStyleUriBuilder {
+
+    constructor(context: Context) : this(
+        apiKey = context.apiKey,
+        lightMapId = context.mapId(darkMode = false),
+        darkMapId = context.mapId(darkMode = true),
+    )
+
+    override fun build(darkMode: Boolean): String {
+        val mapId = if (darkMode) darkMapId else lightMapId
+        return "${MAPTILER_BASE_URL}/${mapId}/style.json?key=${apiKey}"
+    }
+}
diff --git a/features/location/api/src/main/kotlin/io/element/android/features/location/api/internal/MapUrls.kt b/features/location/api/src/main/kotlin/io/element/android/features/location/api/internal/MapUrls.kt
deleted file mode 100644
index b6f21a4512..0000000000
--- a/features/location/api/src/main/kotlin/io/element/android/features/location/api/internal/MapUrls.kt
+++ /dev/null
@@ -1,74 +0,0 @@
-/*
- * Copyright (c) 2023 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
- *
- *     http://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.features.location.api.internal
-
-import android.content.Context
-import androidx.compose.runtime.Composable
-import androidx.compose.runtime.remember
-import androidx.compose.ui.platform.LocalContext
-import io.element.android.features.location.api.R
-import io.element.android.libraries.theme.ElementTheme
-
-/**
- * Provides the URL to an image that contains a statically-generated map of the given location.
- */
-fun staticMapUrl(
-    context: Context,
-    lat: Double,
-    lon: Double,
-    zoom: Double,
-    width: Int,
-    height: Int,
-    darkMode: Boolean,
-): String {
-    return "${baseUrl(darkMode)}/static/${lon},${lat},${zoom}/${width}x${height}@2x.webp?key=${context.apiKey}&attribution=bottomleft"
-}
-
-/**
- * Utility function to remember the tile server URL based on the current theme.
- */
-@Composable
-fun rememberTileStyleUrl(): String {
-    val context = LocalContext.current
-    val darkMode = !ElementTheme.isLightTheme
-    return remember(darkMode) {
-        tileStyleUrl(
-            context = context,
-            darkMode = darkMode
-        )
-    }
-}
-
-/**
- * Provides the URL to a MapLibre style document, used for rendering dynamic maps.
- */
-private fun tileStyleUrl(
-    context: Context,
-    darkMode: Boolean,
-): String {
-    return "${baseUrl(darkMode)}/style.json?key=${context.apiKey}"
-}
-
-private fun baseUrl(darkMode: Boolean) =
-    "https://api.maptiler.com/maps/" +
-        if (darkMode)
-            "dea61faf-292b-4774-9660-58fcef89a7f3"
-        else
-            "9bc819c8-e627-474a-a348-ec144fe3d810"
-
-private val Context.apiKey: String
-    get() = getString(R.string.maptiler_api_key)
diff --git a/features/location/api/src/main/kotlin/io/element/android/features/location/api/internal/ModifierCenterBottomEdge.kt b/features/location/api/src/main/kotlin/io/element/android/features/location/api/internal/ModifierCenterBottomEdge.kt
new file mode 100644
index 0000000000..736f24e609
--- /dev/null
+++ b/features/location/api/src/main/kotlin/io/element/android/features/location/api/internal/ModifierCenterBottomEdge.kt
@@ -0,0 +1,36 @@
+/*
+ * Copyright (c) 2023 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
+ *
+ *     http://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.features.location.api.internal
+
+import androidx.compose.foundation.layout.BoxScope
+import androidx.compose.ui.Modifier
+import androidx.compose.ui.unit.IntOffset
+
+/**
+ * Horizontally aligns the content to the center of the space.
+ * Vertically aligns the bottom edge of the content to the center of the space.
+ */
+fun Modifier.centerBottomEdge(scope: BoxScope): Modifier = with(scope) {
+    then(
+        Modifier.align { size, space, _ ->
+            IntOffset(
+                x = (space.width - size.width) / 2,
+                y = space.height / 2 - size.height,
+            )
+        }
+    )
+}
diff --git a/features/location/api/src/main/kotlin/io/element/android/features/location/api/internal/StaticMapPlaceholder.kt b/features/location/api/src/main/kotlin/io/element/android/features/location/api/internal/StaticMapPlaceholder.kt
index d36ead5b28..84349d97c9 100644
--- a/features/location/api/src/main/kotlin/io/element/android/features/location/api/internal/StaticMapPlaceholder.kt
+++ b/features/location/api/src/main/kotlin/io/element/android/features/location/api/internal/StaticMapPlaceholder.kt
@@ -79,7 +79,7 @@ internal fun StaticMapPlaceholder(
 
 @DayNightPreviews
 @Composable
-fun StaticMapPlaceholderPreview(
+internal fun StaticMapPlaceholderPreview(
     @PreviewParameter(BooleanParameterProvider::class) values: Boolean
 ) = ElementPreview {
     StaticMapPlaceholder(
diff --git a/features/location/api/src/main/kotlin/io/element/android/features/location/api/internal/StaticMapUrlBuilder.kt b/features/location/api/src/main/kotlin/io/element/android/features/location/api/internal/StaticMapUrlBuilder.kt
new file mode 100644
index 0000000000..8c29b5c13d
--- /dev/null
+++ b/features/location/api/src/main/kotlin/io/element/android/features/location/api/internal/StaticMapUrlBuilder.kt
@@ -0,0 +1,36 @@
+/*
+ * Copyright (c) 2023 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
+ *
+ *     http://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.features.location.api.internal
+
+import android.content.Context
+
+/**
+ * Builds an URL for a 3rd party service provider static maps API.
+ */
+interface StaticMapUrlBuilder {
+    fun build(
+        lat: Double,
+        lon: Double,
+        zoom: Double,
+        darkMode: Boolean,
+        width: Int,
+        height: Int,
+        density: Float,
+    ): String
+}
+
+fun StaticMapUrlBuilder(context: Context): StaticMapUrlBuilder = MapTilerStaticMapUrlBuilder(context = context)
diff --git a/features/location/api/src/main/kotlin/io/element/android/features/location/api/internal/TileServerStyleUriBuilder.kt b/features/location/api/src/main/kotlin/io/element/android/features/location/api/internal/TileServerStyleUriBuilder.kt
new file mode 100644
index 0000000000..ece32cbf5a
--- /dev/null
+++ b/features/location/api/src/main/kotlin/io/element/android/features/location/api/internal/TileServerStyleUriBuilder.kt
@@ -0,0 +1,50 @@
+/*
+ * Copyright (c) 2023 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
+ *
+ *     http://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.features.location.api.internal
+
+import android.content.Context
+import androidx.compose.runtime.Composable
+import androidx.compose.runtime.remember
+import androidx.compose.ui.platform.LocalContext
+import io.element.android.libraries.theme.ElementTheme
+
+/**
+ * Builds a style URI for a MapLibre compatible tile server.
+ *
+ * Used for rendering dynamic maps.
+ */
+interface TileServerStyleUriBuilder {
+    fun build(
+        darkMode: Boolean,
+    ): String
+}
+
+fun TileServerStyleUriBuilder(context: Context): TileServerStyleUriBuilder = MapTilerTileServerStyleUriBuilder(context = context)
+
+/**
+ * Provides and remembers a style URI for a MapLibre compatible tile server.
+ *
+ * Used for rendering dynamic maps.
+ */
+@Composable
+fun rememberTileStyleUrl(): String {
+    val context = LocalContext.current
+    val darkMode = !ElementTheme.isLightTheme
+    return remember(darkMode) {
+        TileServerStyleUriBuilder(context).build(darkMode)
+    }
+}
diff --git a/features/location/api/src/test/kotlin/io/element/android/features/location/api/internal/MapTilerStaticMapUrlBuilderTest.kt b/features/location/api/src/test/kotlin/io/element/android/features/location/api/internal/MapTilerStaticMapUrlBuilderTest.kt
new file mode 100644
index 0000000000..c359777ee7
--- /dev/null
+++ b/features/location/api/src/test/kotlin/io/element/android/features/location/api/internal/MapTilerStaticMapUrlBuilderTest.kt
@@ -0,0 +1,191 @@
+/*
+ * Copyright (c) 2023 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
+ *
+ *     http://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.features.location.api.internal
+
+import com.google.common.truth.Truth.assertThat
+import org.junit.Test
+
+class MapTilerStaticMapUrlBuilderTest {
+
+    private val builder = MapTilerStaticMapUrlBuilder(
+        apiKey = "anApiKey",
+        lightMapId = "aLightMapId",
+        darkMapId = "aDarkMapId",
+    )
+
+    @Test
+    fun `static map 1x density`() {
+        assertThat(
+            builder.build(
+                lat = 1.23,
+                lon = -4.56,
+                zoom = 7.8,
+                darkMode = false,
+                width = 800,
+                height = 600,
+                density = 1f,
+            )
+        ).isEqualTo("https://api.maptiler.com/maps/aLightMapId/static/-4.56,1.23,7.8/800x600.webp?key=anApiKey&attribution=bottomleft")
+    }
+
+    @Test
+    fun `static map 1,5x density`() {
+        assertThat(
+            builder.build(
+                lat = 1.23,
+                lon = -4.56,
+                zoom = 7.8,
+                darkMode = false,
+                width = 1200,
+                height = 900,
+                density = 1.5f,
+            )
+        ).isEqualTo("https://api.maptiler.com/maps/aLightMapId/static/-4.56,1.23,7.8/800x600.webp?key=anApiKey&attribution=bottomleft")
+    }
+
+    @Test
+    fun `static map 2x density`() {
+        assertThat(
+            builder.build(
+                lat = 1.23,
+                lon = -4.56,
+                zoom = 7.8,
+                darkMode = false,
+                width = 1600,
+                height = 1200,
+                density = 2f,
+            )
+        ).isEqualTo("https://api.maptiler.com/maps/aLightMapId/static/-4.56,1.23,7.8/800x600@2x.webp?key=anApiKey&attribution=bottomleft")
+    }
+
+    @Test
+    fun `static map 3x density`() {
+        assertThat(
+            builder.build(
+                lat = 1.23,
+                lon = -4.56,
+                zoom = 7.8,
+                darkMode = false,
+                width = 2400,
+                height = 1800,
+                density = 3f,
+            )
+        ).isEqualTo("https://api.maptiler.com/maps/aLightMapId/static/-4.56,1.23,7.8/800x600@2x.webp?key=anApiKey&attribution=bottomleft")
+    }
+
+    @Test
+    fun `too big image is coerced keeping aspect ratio`() {
+        assertThat(
+            builder.build(
+                lat = 1.23,
+                lon = -4.56,
+                zoom = 7.8,
+                darkMode = false,
+                width = 4096,
+                height = 2048,
+                density = 1f,
+            )
+        ).isEqualTo("https://api.maptiler.com/maps/aLightMapId/static/-4.56,1.23,7.8/2048x1024.webp?key=anApiKey&attribution=bottomleft")
+
+        assertThat(
+            builder.build(
+                lat = 1.23,
+                lon = -4.56,
+                zoom = 7.8,
+                darkMode = false,
+                width = 2048,
+                height = 4096,
+                density = 1f,
+            )
+        ).isEqualTo("https://api.maptiler.com/maps/aLightMapId/static/-4.56,1.23,7.8/1024x2048.webp?key=anApiKey&attribution=bottomleft")
+
+        assertThat(
+            builder.build(
+                lat = 1.23,
+                lon = -4.56,
+                zoom = 7.8,
+                darkMode = false,
+                width = 4096,
+                height = 2048,
+                density = 2f,
+            )
+        ).isEqualTo("https://api.maptiler.com/maps/aLightMapId/static/-4.56,1.23,7.8/1024x512@2x.webp?key=anApiKey&attribution=bottomleft")
+
+        assertThat(
+            builder.build(
+                lat = 1.23,
+                lon = -4.56,
+                zoom = 7.8,
+                darkMode = false,
+                width = 2048,
+                height = 4096,
+                density = 2f,
+            )
+        ).isEqualTo("https://api.maptiler.com/maps/aLightMapId/static/-4.56,1.23,7.8/512x1024@2x.webp?key=anApiKey&attribution=bottomleft")
+
+        assertThat(
+            builder.build(
+                lat = 1.23,
+                lon = -4.56,
+                zoom = 7.8,
+                darkMode = false,
+                width = Int.MAX_VALUE,
+                height = Int.MAX_VALUE,
+                density = 2f,
+            )
+        ).isEqualTo("https://api.maptiler.com/maps/aLightMapId/static/-4.56,1.23,7.8/1024x1024@2x.webp?key=anApiKey&attribution=bottomleft")
+    }
+
+    @Test
+    fun `too small image is coerced to 0x0`() {
+        assertThat(
+            builder.build(
+                lat = 1.23,
+                lon = -4.56,
+                zoom = 7.8,
+                darkMode = false,
+                width = 0,
+                height = 0,
+                density = 1f,
+            )
+        ).isEqualTo("https://api.maptiler.com/maps/aLightMapId/static/-4.56,1.23,7.8/0x0.webp?key=anApiKey&attribution=bottomleft")
+
+        assertThat(
+            builder.build(
+                lat = 1.23,
+                lon = -4.56,
+                zoom = 7.8,
+                darkMode = false,
+                width = 0,
+                height = 0,
+                density = 2f,
+            )
+        ).isEqualTo("https://api.maptiler.com/maps/aLightMapId/static/-4.56,1.23,7.8/0x0@2x.webp?key=anApiKey&attribution=bottomleft")
+
+        assertThat(
+            builder.build(
+                lat = 1.23,
+                lon = -4.56,
+                zoom = 7.8,
+                darkMode = false,
+                width = Int.MIN_VALUE,
+                height = Int.MIN_VALUE,
+                density = 1f,
+            )
+        ).isEqualTo("https://api.maptiler.com/maps/aLightMapId/static/-4.56,1.23,7.8/0x0.webp?key=anApiKey&attribution=bottomleft")
+    }
+}
diff --git a/features/location/api/src/test/kotlin/io/element/android/features/location/api/internal/MapTilerTileServerStyleUriBuilderTest.kt b/features/location/api/src/test/kotlin/io/element/android/features/location/api/internal/MapTilerTileServerStyleUriBuilderTest.kt
new file mode 100644
index 0000000000..abff83c582
--- /dev/null
+++ b/features/location/api/src/test/kotlin/io/element/android/features/location/api/internal/MapTilerTileServerStyleUriBuilderTest.kt
@@ -0,0 +1,43 @@
+/*
+ * Copyright (c) 2023 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
+ *
+ *     http://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.features.location.api.internal
+
+import com.google.common.truth.Truth.assertThat
+import org.junit.Test
+
+class MapTilerTileServerStyleUriBuilderTest {
+
+    private val builder = MapTilerTileServerStyleUriBuilder(
+        apiKey = "anApiKey",
+        lightMapId = "aLightMapId",
+        darkMapId = "aDarkMapId",
+    )
+
+    @Test
+    fun `light map uri`() {
+        assertThat(
+            builder.build(darkMode = false)
+        ).isEqualTo("https://api.maptiler.com/maps/aLightMapId/style.json?key=anApiKey")
+    }
+
+    @Test
+    fun `dark map uri`() {
+        assertThat(
+            builder.build(darkMode = true)
+        ).isEqualTo("https://api.maptiler.com/maps/aDarkMapId/style.json?key=anApiKey")
+    }
+}
diff --git a/features/location/impl/build.gradle.kts b/features/location/impl/build.gradle.kts
index 1158b5f152..e808eed11c 100644
--- a/features/location/impl/build.gradle.kts
+++ b/features/location/impl/build.gradle.kts
@@ -45,7 +45,6 @@ dependencies {
     implementation(projects.libraries.uiStrings)
     implementation(libs.dagger)
     implementation(projects.anvilannotations)
-    implementation(projects.services.toolbox.api)
     anvil(projects.anvilcodegen)
     ksp(libs.showkase.processor)
 
diff --git a/features/location/impl/src/main/kotlin/io/element/android/features/location/impl/MapDefaults.kt b/features/location/impl/src/main/kotlin/io/element/android/features/location/impl/MapDefaults.kt
index ac99be1f59..4709c78538 100644
--- a/features/location/impl/src/main/kotlin/io/element/android/features/location/impl/MapDefaults.kt
+++ b/features/location/impl/src/main/kotlin/io/element/android/features/location/impl/MapDefaults.kt
@@ -20,6 +20,7 @@ import android.Manifest
 import android.view.Gravity
 import androidx.compose.runtime.Composable
 import androidx.compose.runtime.ReadOnlyComposable
+import androidx.compose.ui.graphics.Color
 import com.mapbox.mapboxsdk.camera.CameraPosition
 import com.mapbox.mapboxsdk.geometry.LatLng
 import io.element.android.libraries.maplibre.compose.MapLocationSettings
@@ -53,6 +54,13 @@ object MapDefaults {
     val locationSettings: MapLocationSettings
         get() = MapLocationSettings(
             locationEnabled = false,
+            backgroundTintColor = Color.White,
+            foregroundTintColor = Color.Black,
+            backgroundStaleTintColor = Color.White,
+            foregroundStaleTintColor = Color.Black,
+            accuracyColor = Color.Black,
+            pulseEnabled = true,
+            pulseColor = Color.Black,
         )
 
     val centerCameraPosition = CameraPosition.Builder()
diff --git a/features/location/impl/src/main/kotlin/io/element/android/features/location/impl/send/SendLocationPresenter.kt b/features/location/impl/src/main/kotlin/io/element/android/features/location/impl/send/SendLocationPresenter.kt
index d06124539c..595e26e32e 100644
--- a/features/location/impl/src/main/kotlin/io/element/android/features/location/impl/send/SendLocationPresenter.kt
+++ b/features/location/impl/src/main/kotlin/io/element/android/features/location/impl/send/SendLocationPresenter.kt
@@ -36,12 +36,7 @@ import io.element.android.libraries.core.meta.BuildMeta
 import io.element.android.libraries.matrix.api.room.MatrixRoom
 import io.element.android.libraries.matrix.api.room.location.AssetType
 import io.element.android.services.analytics.api.AnalyticsService
-import io.element.android.services.toolbox.api.systemclock.SystemClock
 import kotlinx.coroutines.launch
-import java.time.Instant
-import java.time.ZoneOffset
-import java.time.ZonedDateTime
-import java.time.format.DateTimeFormatter
 import javax.inject.Inject
 
 class SendLocationPresenter @Inject constructor(
@@ -50,7 +45,6 @@ class SendLocationPresenter @Inject constructor(
     private val analyticsService: AnalyticsService,
     private val messageComposerContext: MessageComposerContext,
     private val locationActions: LocationActions,
-    private val systemClock: SystemClock,
     private val buildMeta: BuildMeta,
 ) : Presenter {
 
@@ -115,7 +109,7 @@ class SendLocationPresenter @Inject constructor(
             SendLocationState.Mode.PinLocation -> {
                 val geoUri = event.cameraPosition.toGeoUri()
                 room.sendLocation(
-                    body = generateBody(geoUri, systemClock.epochMillis()),
+                    body = generateBody(geoUri),
                     geoUri = geoUri,
                     description = null,
                     zoomLevel = MapDefaults.DEFAULT_ZOOM.toInt(),
@@ -134,7 +128,7 @@ class SendLocationPresenter @Inject constructor(
             SendLocationState.Mode.SenderLocation -> {
                 val geoUri = event.toGeoUri()
                 room.sendLocation(
-                    body = generateBody(geoUri, systemClock.epochMillis()),
+                    body = generateBody(geoUri),
                     geoUri = geoUri,
                     description = null,
                     zoomLevel = MapDefaults.DEFAULT_ZOOM.toInt(),
@@ -158,7 +152,4 @@ private fun SendLocationEvents.SendLocation.toGeoUri(): String = location?.toGeo
 
 private fun SendLocationEvents.SendLocation.CameraPosition.toGeoUri(): String = "geo:$lat,$lon"
 
-private fun generateBody(uri: String, epochMillis: Long): String {
-    val timestamp = ZonedDateTime.ofInstant(Instant.ofEpochMilli(epochMillis), ZoneOffset.UTC).format(DateTimeFormatter.ISO_INSTANT)
-    return "Location was shared at $uri as of $timestamp"
-}
+private fun generateBody(uri: String): String = "Location was shared at $uri"
diff --git a/features/location/impl/src/main/kotlin/io/element/android/features/location/impl/send/SendLocationView.kt b/features/location/impl/src/main/kotlin/io/element/android/features/location/impl/send/SendLocationView.kt
index 1a30c996a8..cfb30a5523 100644
--- a/features/location/impl/src/main/kotlin/io/element/android/features/location/impl/send/SendLocationView.kt
+++ b/features/location/impl/src/main/kotlin/io/element/android/features/location/impl/send/SendLocationView.kt
@@ -28,7 +28,6 @@ import androidx.compose.foundation.layout.height
 import androidx.compose.foundation.layout.navigationBars
 import androidx.compose.foundation.layout.padding
 import androidx.compose.material.icons.Icons
-import androidx.compose.material.icons.filled.LocationOn
 import androidx.compose.material.icons.filled.LocationSearching
 import androidx.compose.material.icons.filled.MyLocation
 import androidx.compose.material3.ExperimentalMaterial3Api
@@ -43,12 +42,13 @@ import androidx.compose.ui.Modifier
 import androidx.compose.ui.graphics.Color
 import androidx.compose.ui.res.stringResource
 import androidx.compose.ui.tooling.preview.PreviewParameter
-import androidx.compose.ui.unit.IntOffset
 import androidx.compose.ui.unit.dp
 import com.mapbox.mapboxsdk.camera.CameraPosition
 import io.element.android.features.location.api.Location
+import io.element.android.features.location.api.internal.centerBottomEdge
 import io.element.android.features.location.api.internal.rememberTileStyleUrl
 import io.element.android.features.location.impl.MapDefaults
+import io.element.android.features.location.impl.R
 import io.element.android.libraries.designsystem.components.button.BackButton
 import io.element.android.libraries.designsystem.components.dialogs.ConfirmationDialog
 import io.element.android.libraries.designsystem.preview.DayNightPreviews
@@ -156,7 +156,11 @@ fun SendLocationView(
                     navigateUp()
                 },
                 leadingContent = {
-                    Icon(Icons.Default.LocationOn, null)
+                    Icon(
+                        resourceId = R.drawable.pin_small,
+                        contentDescription = null,
+                        tint = Color.Unspecified,
+                    )
                 },
             )
             Spacer(modifier = Modifier.height(16.dp + navBarPadding))
@@ -201,13 +205,7 @@ fun SendLocationView(
                 resourceId = DesignSystemR.drawable.pin,
                 contentDescription = null,
                 tint = Color.Unspecified,
-                modifier = Modifier.align { size, space, _ ->
-                    // Center bottom edge of pin (i.e. its arrow) to center of screen
-                    IntOffset(
-                        x = (space.width - size.width) / 2,
-                        y = (space.height / 2) - size.height,
-                    )
-                }
+                modifier = Modifier.centerBottomEdge(this),
             )
             FloatingActionButton(
                 onClick = { state.eventSink(SendLocationEvents.SwitchToMyLocationMode) },
@@ -226,7 +224,7 @@ fun SendLocationView(
 
 @DayNightPreviews
 @Composable
-fun SendLocationViewPreview(
+internal fun SendLocationViewPreview(
     @PreviewParameter(SendLocationStateProvider::class) state: SendLocationState
 ) = ElementPreview {
     SendLocationView(
diff --git a/features/location/impl/src/main/kotlin/io/element/android/features/location/impl/show/ShowLocationStateProvider.kt b/features/location/impl/src/main/kotlin/io/element/android/features/location/impl/show/ShowLocationStateProvider.kt
index 1865c6b9a4..73bb2d37a4 100644
--- a/features/location/impl/src/main/kotlin/io/element/android/features/location/impl/show/ShowLocationStateProvider.kt
+++ b/features/location/impl/src/main/kotlin/io/element/android/features/location/impl/show/ShowLocationStateProvider.kt
@@ -50,6 +50,13 @@ class ShowLocationStateProvider : PreviewParameterProvider {
                 isTrackMyLocation = false,
                 eventSink = {},
             ),
+            ShowLocationState(
+                Location(1.23, 2.34, 4f),
+                description = "For some reason I decided to to write a small essay that wraps at just two lines!",
+                hasLocationPermission = false,
+                isTrackMyLocation = false,
+                eventSink = {},
+            ),
             ShowLocationState(
                 Location(1.23, 2.34, 4f),
                 description = "For some reason I decided to write a small essay in the location description. " +
diff --git a/features/location/impl/src/main/kotlin/io/element/android/features/location/impl/show/ShowLocationView.kt b/features/location/impl/src/main/kotlin/io/element/android/features/location/impl/show/ShowLocationView.kt
index 7726bbf9cc..0e114a43b9 100644
--- a/features/location/impl/src/main/kotlin/io/element/android/features/location/impl/show/ShowLocationView.kt
+++ b/features/location/impl/src/main/kotlin/io/element/android/features/location/impl/show/ShowLocationView.kt
@@ -40,7 +40,6 @@ import com.mapbox.mapboxsdk.camera.CameraPosition
 import com.mapbox.mapboxsdk.geometry.LatLng
 import io.element.android.features.location.api.internal.rememberTileStyleUrl
 import io.element.android.features.location.impl.MapDefaults
-import io.element.android.features.location.impl.send.SendLocationState
 import io.element.android.libraries.designsystem.components.button.BackButton
 import io.element.android.libraries.designsystem.preview.ElementPreviewDark
 import io.element.android.libraries.designsystem.preview.ElementPreviewLight
diff --git a/features/location/impl/src/main/res/drawable-night/pin_small.xml b/features/location/impl/src/main/res/drawable-night/pin_small.xml
new file mode 100644
index 0000000000..2e8a54b70e
--- /dev/null
+++ b/features/location/impl/src/main/res/drawable-night/pin_small.xml
@@ -0,0 +1,19 @@
+
+  
+  
+  
+    
+    
+  
+
diff --git a/features/location/impl/src/main/res/drawable/pin_small.xml b/features/location/impl/src/main/res/drawable/pin_small.xml
new file mode 100644
index 0000000000..0e277a1ed2
--- /dev/null
+++ b/features/location/impl/src/main/res/drawable/pin_small.xml
@@ -0,0 +1,19 @@
+
+  
+  
+  
+    
+    
+  
+
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 45c99b556a..0aa89e89ba 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
@@ -16,7 +16,7 @@
 
 package io.element.android.features.location.impl.send
 
-import app.cash.molecule.RecompositionClock
+import app.cash.molecule.RecompositionMode
 import app.cash.molecule.moleculeFlow
 import app.cash.turbine.test
 import com.google.common.truth.Truth
@@ -34,7 +34,6 @@ 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.MessageComposerMode
-import io.element.android.services.toolbox.api.systemclock.SystemClock
 import kotlinx.coroutines.delay
 import kotlinx.coroutines.test.runTest
 import org.junit.Test
@@ -46,7 +45,6 @@ class SendLocationPresenterTest {
     private val fakeAnalyticsService = FakeAnalyticsService()
     private val messageComposerContextFake = MessageComposerContextFake()
     private val fakeLocationActions = FakeLocationActions()
-    private val fakeSystemClock = SystemClock { 0L }
     private val fakeBuildMeta = aBuildMeta(applicationName = "app name")
     private val sendLocationPresenter: SendLocationPresenter = SendLocationPresenter(
         permissionsPresenterFactory = object : PermissionsPresenter.Factory {
@@ -56,7 +54,6 @@ class SendLocationPresenterTest {
         analyticsService = fakeAnalyticsService,
         messageComposerContext = messageComposerContextFake,
         locationActions = fakeLocationActions,
-        systemClock = fakeSystemClock,
         buildMeta = fakeBuildMeta,
     )
 
@@ -69,7 +66,7 @@ class SendLocationPresenterTest {
             )
         )
 
-        moleculeFlow(RecompositionClock.Immediate) {
+        moleculeFlow(RecompositionMode.Immediate) {
             sendLocationPresenter.present()
         }.test {
 
@@ -96,7 +93,7 @@ class SendLocationPresenterTest {
             )
         )
 
-        moleculeFlow(RecompositionClock.Immediate) {
+        moleculeFlow(RecompositionMode.Immediate) {
             sendLocationPresenter.present()
         }.test {
 
@@ -123,7 +120,7 @@ class SendLocationPresenterTest {
             )
         )
 
-        moleculeFlow(RecompositionClock.Immediate) {
+        moleculeFlow(RecompositionMode.Immediate) {
             sendLocationPresenter.present()
         }.test {
             val initialState = awaitItem()
@@ -149,7 +146,7 @@ class SendLocationPresenterTest {
             )
         )
 
-        moleculeFlow(RecompositionClock.Immediate) {
+        moleculeFlow(RecompositionMode.Immediate) {
             sendLocationPresenter.present()
         }.test {
             val initialState = awaitItem()
@@ -175,7 +172,7 @@ class SendLocationPresenterTest {
             )
         )
 
-        moleculeFlow(RecompositionClock.Immediate) {
+        moleculeFlow(RecompositionMode.Immediate) {
             sendLocationPresenter.present()
         }.test {
             // Skip initial state
@@ -206,7 +203,7 @@ class SendLocationPresenterTest {
             )
         )
 
-        moleculeFlow(RecompositionClock.Immediate) {
+        moleculeFlow(RecompositionMode.Immediate) {
             sendLocationPresenter.present()
         }.test {
             // Skip initial state
@@ -234,7 +231,7 @@ class SendLocationPresenterTest {
             )
         )
 
-        moleculeFlow(RecompositionClock.Immediate) {
+        moleculeFlow(RecompositionMode.Immediate) {
             sendLocationPresenter.present()
         }.test {
             // Skip initial state
@@ -265,7 +262,7 @@ class SendLocationPresenterTest {
             )
         )
 
-        moleculeFlow(RecompositionClock.Immediate) {
+        moleculeFlow(RecompositionMode.Immediate) {
             sendLocationPresenter.present()
         }.test {
             // Skip initial state
@@ -292,7 +289,7 @@ class SendLocationPresenterTest {
             Truth.assertThat(fakeMatrixRoom.sentLocations.size).isEqualTo(1)
             Truth.assertThat(fakeMatrixRoom.sentLocations.last()).isEqualTo(
                 SendLocationInvocation(
-                    body = "Location was shared at geo:3.0,4.0;u=5.0 as of 1970-01-01T00:00:00Z",
+                    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,
@@ -322,7 +319,7 @@ class SendLocationPresenterTest {
             )
         )
 
-        moleculeFlow(RecompositionClock.Immediate) {
+        moleculeFlow(RecompositionMode.Immediate) {
             sendLocationPresenter.present()
         }.test {
             // Skip initial state
@@ -349,7 +346,7 @@ class SendLocationPresenterTest {
             Truth.assertThat(fakeMatrixRoom.sentLocations.size).isEqualTo(1)
             Truth.assertThat(fakeMatrixRoom.sentLocations.last()).isEqualTo(
                 SendLocationInvocation(
-                    body = "Location was shared at geo:0.0,1.0 as of 1970-01-01T00:00:00Z",
+                    body = "Location was shared at geo:0.0,1.0",
                     geoUri = "geo:0.0,1.0",
                     description = null,
                     zoomLevel = 15,
@@ -384,7 +381,7 @@ class SendLocationPresenterTest {
             )
         }
 
-        moleculeFlow(RecompositionClock.Immediate) {
+        moleculeFlow(RecompositionMode.Immediate) {
             sendLocationPresenter.present()
         }.test {
             // Skip initial state
@@ -431,7 +428,7 @@ class SendLocationPresenterTest {
             )
         }
 
-        moleculeFlow(RecompositionClock.Immediate) {
+        moleculeFlow(RecompositionMode.Immediate) {
             sendLocationPresenter.present()
         }.test {
             // Skip initial state
@@ -451,7 +448,7 @@ class SendLocationPresenterTest {
 
     @Test
     fun `application name is in state`() = runTest {
-        moleculeFlow(RecompositionClock.Immediate) {
+        moleculeFlow(RecompositionMode.Immediate) {
             sendLocationPresenter.present()
         }.test {
             val initialState = awaitItem()
diff --git a/features/location/impl/src/test/kotlin/io/element/android/features/location/impl/show/ShowLocationPresenterTest.kt b/features/location/impl/src/test/kotlin/io/element/android/features/location/impl/show/ShowLocationPresenterTest.kt
index 47f0e2ccea..7fff766a9f 100644
--- a/features/location/impl/src/test/kotlin/io/element/android/features/location/impl/show/ShowLocationPresenterTest.kt
+++ b/features/location/impl/src/test/kotlin/io/element/android/features/location/impl/show/ShowLocationPresenterTest.kt
@@ -16,7 +16,7 @@
 
 package io.element.android.features.location.impl.show
 
-import app.cash.molecule.RecompositionClock
+import app.cash.molecule.RecompositionMode
 import app.cash.molecule.moleculeFlow
 import app.cash.turbine.test
 import com.google.common.truth.Truth
@@ -44,7 +44,7 @@ class ShowLocationPresenterTest {
 
     @Test
     fun `emits initial state with no location permission`() = runTest {
-        moleculeFlow(RecompositionClock.Immediate) {
+        moleculeFlow(RecompositionMode.Immediate) {
             presenter.present()
         }.test {
             val initialState = awaitItem()
@@ -59,7 +59,7 @@ class ShowLocationPresenterTest {
     fun `emits initial state with location permission`() = runTest {
         permissionsPresenterFake.givenState(PermissionsState(permissions = PermissionsState.Permissions.AllGranted))
 
-        moleculeFlow(RecompositionClock.Immediate) {
+        moleculeFlow(RecompositionMode.Immediate) {
             presenter.present()
         }.test {
             val initialState = awaitItem()
@@ -74,7 +74,7 @@ class ShowLocationPresenterTest {
     fun `emits initial state with partial location permission`() = runTest {
         permissionsPresenterFake.givenState(PermissionsState(permissions = PermissionsState.Permissions.SomeGranted))
 
-        moleculeFlow(RecompositionClock.Immediate) {
+        moleculeFlow(RecompositionMode.Immediate) {
             presenter.present()
         }.test {
             val initialState = awaitItem()
@@ -87,7 +87,7 @@ class ShowLocationPresenterTest {
 
     @Test
     fun `uses action to share location`() = runTest {
-        moleculeFlow(RecompositionClock.Immediate) {
+        moleculeFlow(RecompositionMode.Immediate) {
             presenter.present()
         }.test {
             val initialState = awaitItem()
@@ -102,7 +102,7 @@ class ShowLocationPresenterTest {
     fun `centers on user location`() = runTest {
         permissionsPresenterFake.givenState(PermissionsState(permissions = PermissionsState.Permissions.AllGranted))
 
-        moleculeFlow(RecompositionClock.Immediate) {
+        moleculeFlow(RecompositionMode.Immediate) {
             presenter.present()
         }.test {
             val initialState = awaitItem()
diff --git a/features/login/impl/build.gradle.kts b/features/login/impl/build.gradle.kts
index f9bbb390e6..4a4c6756aa 100644
--- a/features/login/impl/build.gradle.kts
+++ b/features/login/impl/build.gradle.kts
@@ -61,6 +61,4 @@ dependencies {
     testImplementation(libs.test.turbine)
     testImplementation(projects.libraries.matrix.test)
     testImplementation(projects.tests.testutils)
-
-    androidTestImplementation(libs.test.junitext)
 }
diff --git a/features/login/impl/src/main/kotlin/io/element/android/features/login/impl/accountprovider/AccountProviderView.kt b/features/login/impl/src/main/kotlin/io/element/android/features/login/impl/accountprovider/AccountProviderView.kt
index 3362beac40..ecc2f996cb 100644
--- a/features/login/impl/src/main/kotlin/io/element/android/features/login/impl/accountprovider/AccountProviderView.kt
+++ b/features/login/impl/src/main/kotlin/io/element/android/features/login/impl/accountprovider/AccountProviderView.kt
@@ -30,7 +30,6 @@ import androidx.compose.runtime.Composable
 import androidx.compose.ui.Alignment
 import androidx.compose.ui.Modifier
 import androidx.compose.ui.graphics.Color
-import androidx.compose.ui.text.style.TextAlign
 import androidx.compose.ui.tooling.preview.Preview
 import androidx.compose.ui.tooling.preview.PreviewParameter
 import androidx.compose.ui.unit.dp
@@ -115,12 +114,12 @@ fun AccountProviderView(
 
 @Preview
 @Composable
-fun AccountProviderViewLightPreview(@PreviewParameter(AccountProviderProvider::class) item: AccountProvider) =
+internal fun AccountProviderViewLightPreview(@PreviewParameter(AccountProviderProvider::class) item: AccountProvider) =
     ElementPreviewLight { ContentToPreview(item) }
 
 @Preview
 @Composable
-fun AccountProviderViewDarkPreview(@PreviewParameter(AccountProviderProvider::class) item: AccountProvider) =
+internal fun AccountProviderViewDarkPreview(@PreviewParameter(AccountProviderProvider::class) item: AccountProvider) =
     ElementPreviewDark { ContentToPreview(item) }
 
 @Composable
diff --git a/features/login/impl/src/main/kotlin/io/element/android/features/login/impl/changeserver/ChangeServerView.kt b/features/login/impl/src/main/kotlin/io/element/android/features/login/impl/changeserver/ChangeServerView.kt
index f9e9624503..ffa337fba7 100644
--- a/features/login/impl/src/main/kotlin/io/element/android/features/login/impl/changeserver/ChangeServerView.kt
+++ b/features/login/impl/src/main/kotlin/io/element/android/features/login/impl/changeserver/ChangeServerView.kt
@@ -71,12 +71,12 @@ fun ChangeServerView(
 
 @Preview
 @Composable
-fun ChangeServerViewLightPreview(@PreviewParameter(ChangeServerStateProvider::class) state: ChangeServerState) =
+internal fun ChangeServerViewLightPreview(@PreviewParameter(ChangeServerStateProvider::class) state: ChangeServerState) =
     ElementPreviewLight { ContentToPreview(state) }
 
 @Preview
 @Composable
-fun ChangeServerViewDarkPreview(@PreviewParameter(ChangeServerStateProvider::class) state: ChangeServerState) =
+internal fun ChangeServerViewDarkPreview(@PreviewParameter(ChangeServerStateProvider::class) state: ChangeServerState) =
     ElementPreviewDark { ContentToPreview(state) }
 
 @Composable
diff --git a/features/login/impl/src/main/kotlin/io/element/android/features/login/impl/dialogs/SlidingSyncNotSupportedDialog.kt b/features/login/impl/src/main/kotlin/io/element/android/features/login/impl/dialogs/SlidingSyncNotSupportedDialog.kt
index 5beb14b0b4..6ef5be06ab 100644
--- a/features/login/impl/src/main/kotlin/io/element/android/features/login/impl/dialogs/SlidingSyncNotSupportedDialog.kt
+++ b/features/login/impl/src/main/kotlin/io/element/android/features/login/impl/dialogs/SlidingSyncNotSupportedDialog.kt
@@ -35,7 +35,6 @@ internal fun SlidingSyncNotSupportedDialog(
         submitText = stringResource(CommonStrings.action_learn_more),
         onSubmitClicked = onLearnMoreClicked,
         onCancelClicked = onDismiss,
-        emphasizeSubmitButton = true,
         title = stringResource(CommonStrings.dialog_title_error),
         content = stringResource(R.string.screen_change_server_error_no_sliding_sync_message),
     )
diff --git a/features/login/impl/src/main/kotlin/io/element/android/features/login/impl/oidc/customtab/CustomTabHandler.kt b/features/login/impl/src/main/kotlin/io/element/android/features/login/impl/oidc/customtab/CustomTabHandler.kt
index 48c674e0a0..b83c0eb1ac 100644
--- a/features/login/impl/src/main/kotlin/io/element/android/features/login/impl/oidc/customtab/CustomTabHandler.kt
+++ b/features/login/impl/src/main/kotlin/io/element/android/features/login/impl/oidc/customtab/CustomTabHandler.kt
@@ -41,8 +41,7 @@ class CustomTabHandler @Inject constructor(
         if (packageName != null) {
             customTabsServiceConnection = object : CustomTabsServiceConnection() {
                 override fun onCustomTabsServiceConnected(name: ComponentName, client: CustomTabsClient) {
-                    customTabsClient = client
-                        .also { it.warmup(0L) }
+                    customTabsClient = client.apply { warmup(0L) }
                     prefetchUrl(url)
                 }
 
diff --git a/features/login/impl/src/main/kotlin/io/element/android/features/login/impl/oidc/webview/OidcView.kt b/features/login/impl/src/main/kotlin/io/element/android/features/login/impl/oidc/webview/OidcView.kt
index c1235b76c5..1b7486e814 100644
--- a/features/login/impl/src/main/kotlin/io/element/android/features/login/impl/oidc/webview/OidcView.kt
+++ b/features/login/impl/src/main/kotlin/io/element/android/features/login/impl/oidc/webview/OidcView.kt
@@ -100,12 +100,12 @@ fun OidcView(
 
 @Preview
 @Composable
-fun OidcViewLightPreview(@PreviewParameter(OidcStateProvider::class) state: OidcState) =
+internal fun OidcViewLightPreview(@PreviewParameter(OidcStateProvider::class) state: OidcState) =
     ElementPreviewLight { ContentToPreview(state) }
 
 @Preview
 @Composable
-fun OidcViewDarkPreview(@PreviewParameter(OidcStateProvider::class) state: OidcState) =
+internal fun OidcViewDarkPreview(@PreviewParameter(OidcStateProvider::class) state: OidcState) =
     ElementPreviewDark { ContentToPreview(state) }
 
 @Composable
diff --git a/features/login/impl/src/main/kotlin/io/element/android/features/login/impl/screens/changeaccountprovider/ChangeAccountProviderView.kt b/features/login/impl/src/main/kotlin/io/element/android/features/login/impl/screens/changeaccountprovider/ChangeAccountProviderView.kt
index 0f444350c9..0e35f9eda5 100644
--- a/features/login/impl/src/main/kotlin/io/element/android/features/login/impl/screens/changeaccountprovider/ChangeAccountProviderView.kt
+++ b/features/login/impl/src/main/kotlin/io/element/android/features/login/impl/screens/changeaccountprovider/ChangeAccountProviderView.kt
@@ -127,12 +127,12 @@ fun ChangeAccountProviderView(
 
 @Preview
 @Composable
-fun ChangeAccountProviderViewLightPreview(@PreviewParameter(ChangeAccountProviderStateProvider::class) state: ChangeAccountProviderState) =
+internal fun ChangeAccountProviderViewLightPreview(@PreviewParameter(ChangeAccountProviderStateProvider::class) state: ChangeAccountProviderState) =
     ElementPreviewLight { ContentToPreview(state) }
 
 @Preview
 @Composable
-fun ChangeAccountProviderViewDarkPreview(@PreviewParameter(ChangeAccountProviderStateProvider::class) state: ChangeAccountProviderState) =
+internal fun ChangeAccountProviderViewDarkPreview(@PreviewParameter(ChangeAccountProviderStateProvider::class) state: ChangeAccountProviderState) =
     ElementPreviewDark { ContentToPreview(state) }
 
 @Composable
diff --git a/features/login/impl/src/main/kotlin/io/element/android/features/login/impl/screens/confirmaccountprovider/ConfirmAccountProviderPresenter.kt b/features/login/impl/src/main/kotlin/io/element/android/features/login/impl/screens/confirmaccountprovider/ConfirmAccountProviderPresenter.kt
index 123d3013c7..1a021ad605 100644
--- a/features/login/impl/src/main/kotlin/io/element/android/features/login/impl/screens/confirmaccountprovider/ConfirmAccountProviderPresenter.kt
+++ b/features/login/impl/src/main/kotlin/io/element/android/features/login/impl/screens/confirmaccountprovider/ConfirmAccountProviderPresenter.kt
@@ -92,7 +92,7 @@ class ConfirmAccountProviderPresenter @AssistedInject constructor(
                 } else if (matrixHomeServerDetails.supportsPasswordLogin) {
                     LoginFlow.PasswordLogin
                 } else {
-                    throw IllegalStateException("Unsupported login flow")
+                    error("Unsupported login flow")
                 }
             }.getOrThrow()
         }.runCatchingUpdatingState(loginFlowAction, errorTransform = ChangeServerError::from)
diff --git a/features/login/impl/src/main/kotlin/io/element/android/features/login/impl/screens/confirmaccountprovider/ConfirmAccountProviderView.kt b/features/login/impl/src/main/kotlin/io/element/android/features/login/impl/screens/confirmaccountprovider/ConfirmAccountProviderView.kt
index 2bc002b3fc..239ee3c6ac 100644
--- a/features/login/impl/src/main/kotlin/io/element/android/features/login/impl/screens/confirmaccountprovider/ConfirmAccountProviderView.kt
+++ b/features/login/impl/src/main/kotlin/io/element/android/features/login/impl/screens/confirmaccountprovider/ConfirmAccountProviderView.kt
@@ -36,11 +36,10 @@ import io.element.android.libraries.architecture.Async
 import io.element.android.libraries.designsystem.atomic.molecules.ButtonColumnMolecule
 import io.element.android.libraries.designsystem.atomic.molecules.IconTitleSubtitleMolecule
 import io.element.android.libraries.designsystem.atomic.pages.HeaderFooterPage
-import io.element.android.libraries.designsystem.components.button.ButtonWithProgress
 import io.element.android.libraries.designsystem.components.dialogs.ErrorDialog
 import io.element.android.libraries.designsystem.preview.ElementPreviewDark
 import io.element.android.libraries.designsystem.preview.ElementPreviewLight
-import io.element.android.libraries.designsystem.theme.components.Text
+import io.element.android.libraries.designsystem.theme.components.Button
 import io.element.android.libraries.designsystem.theme.components.TextButton
 import io.element.android.libraries.matrix.api.auth.OidcDetails
 import io.element.android.libraries.testtags.TestTags
@@ -87,7 +86,7 @@ fun ConfirmAccountProviderView(
         },
         footer = {
             ButtonColumnMolecule {
-                ButtonWithProgress(
+                Button(
                     text = stringResource(id = R.string.screen_account_provider_continue),
                     showProgress = isLoading,
                     onClick = { eventSink.invoke(ConfirmAccountProviderEvents.Continue) },
@@ -97,14 +96,13 @@ fun ConfirmAccountProviderView(
                         .testTag(TestTags.loginContinue)
                 )
                 TextButton(
+                    text = stringResource(id = R.string.screen_account_provider_change),
                     onClick = onChange,
                     enabled = true,
                     modifier = Modifier
                         .fillMaxWidth()
                         .testTag(TestTags.loginChangeServer)
-                ) {
-                    Text(text = stringResource(id = R.string.screen_account_provider_change))
-                }
+                )
             }
         }
     ) {
@@ -143,12 +141,12 @@ fun ConfirmAccountProviderView(
 
 @Preview
 @Composable
-fun ConfirmAccountProviderViewLightPreview(@PreviewParameter(ConfirmAccountProviderStateProvider::class) state: ConfirmAccountProviderState) =
+internal fun ConfirmAccountProviderViewLightPreview(@PreviewParameter(ConfirmAccountProviderStateProvider::class) state: ConfirmAccountProviderState) =
     ElementPreviewLight { ContentToPreview(state) }
 
 @Preview
 @Composable
-fun ConfirmAccountProviderViewDarkPreview(@PreviewParameter(ConfirmAccountProviderStateProvider::class) state: ConfirmAccountProviderState) =
+internal fun ConfirmAccountProviderViewDarkPreview(@PreviewParameter(ConfirmAccountProviderStateProvider::class) state: ConfirmAccountProviderState) =
     ElementPreviewDark { ContentToPreview(state) }
 
 @Composable
diff --git a/features/login/impl/src/main/kotlin/io/element/android/features/login/impl/screens/loginpassword/LoginPasswordState.kt b/features/login/impl/src/main/kotlin/io/element/android/features/login/impl/screens/loginpassword/LoginPasswordState.kt
index c8fa2f4ad3..cf4e0d8ee5 100644
--- a/features/login/impl/src/main/kotlin/io/element/android/features/login/impl/screens/loginpassword/LoginPasswordState.kt
+++ b/features/login/impl/src/main/kotlin/io/element/android/features/login/impl/screens/loginpassword/LoginPasswordState.kt
@@ -30,7 +30,8 @@ data class LoginPasswordState(
 ) {
     val submitEnabled: Boolean
         get() = loginAction !is Async.Failure &&
-            ((formState.login.isNotEmpty() && formState.password.isNotEmpty()))
+            formState.login.isNotEmpty() &&
+            formState.password.isNotEmpty()
 }
 
 @Parcelize
diff --git a/features/login/impl/src/main/kotlin/io/element/android/features/login/impl/screens/loginpassword/LoginPasswordView.kt b/features/login/impl/src/main/kotlin/io/element/android/features/login/impl/screens/loginpassword/LoginPasswordView.kt
index d62506ff75..d06ab86b06 100644
--- a/features/login/impl/src/main/kotlin/io/element/android/features/login/impl/screens/loginpassword/LoginPasswordView.kt
+++ b/features/login/impl/src/main/kotlin/io/element/android/features/login/impl/screens/loginpassword/LoginPasswordView.kt
@@ -60,11 +60,11 @@ import io.element.android.features.login.impl.error.loginError
 import io.element.android.libraries.architecture.Async
 import io.element.android.libraries.designsystem.atomic.molecules.IconTitleSubtitleMolecule
 import io.element.android.libraries.designsystem.components.button.BackButton
-import io.element.android.libraries.designsystem.components.button.ButtonWithProgress
 import io.element.android.libraries.designsystem.components.dialogs.ErrorDialog
 import io.element.android.libraries.designsystem.components.form.textFieldState
 import io.element.android.libraries.designsystem.preview.ElementPreviewDark
 import io.element.android.libraries.designsystem.preview.ElementPreviewLight
+import io.element.android.libraries.designsystem.theme.components.Button
 import io.element.android.libraries.designsystem.theme.components.Icon
 import io.element.android.libraries.designsystem.theme.components.IconButton
 import io.element.android.libraries.designsystem.theme.components.OutlinedTextField
@@ -141,7 +141,7 @@ fun LoginPasswordView(
             // Flexible spacing to keep the submit button at the bottom
             Spacer(modifier = Modifier.weight(1f))
             // Submit
-            ButtonWithProgress(
+            Button(
                 text = stringResource(R.string.screen_login_submit),
                 showProgress = isLoading,
                 onClick = ::submit,
diff --git a/features/login/impl/src/main/kotlin/io/element/android/features/login/impl/screens/searchaccountprovider/SearchAccountProviderView.kt b/features/login/impl/src/main/kotlin/io/element/android/features/login/impl/screens/searchaccountprovider/SearchAccountProviderView.kt
index 84c5bf4fac..8cfaae2a9e 100644
--- a/features/login/impl/src/main/kotlin/io/element/android/features/login/impl/screens/searchaccountprovider/SearchAccountProviderView.kt
+++ b/features/login/impl/src/main/kotlin/io/element/android/features/login/impl/screens/searchaccountprovider/SearchAccountProviderView.kt
@@ -211,12 +211,12 @@ private fun HomeserverData.toAccountProvider(): AccountProvider {
 
 @Preview
 @Composable
-fun SearchAccountProviderViewLightPreview(@PreviewParameter(SearchAccountProviderStateProvider::class) state: SearchAccountProviderState) =
+internal fun SearchAccountProviderViewLightPreview(@PreviewParameter(SearchAccountProviderStateProvider::class) state: SearchAccountProviderState) =
     ElementPreviewLight { ContentToPreview(state) }
 
 @Preview
 @Composable
-fun SearchAccountProviderViewDarkPreview(@PreviewParameter(SearchAccountProviderStateProvider::class) state: SearchAccountProviderState) =
+internal fun SearchAccountProviderViewDarkPreview(@PreviewParameter(SearchAccountProviderStateProvider::class) state: SearchAccountProviderState) =
     ElementPreviewDark { ContentToPreview(state) }
 
 @Composable
diff --git a/features/login/impl/src/main/kotlin/io/element/android/features/login/impl/screens/waitlistscreen/WaitListStateProvider.kt b/features/login/impl/src/main/kotlin/io/element/android/features/login/impl/screens/waitlistscreen/WaitListStateProvider.kt
index 5907ff1acf..94a38fa406 100644
--- a/features/login/impl/src/main/kotlin/io/element/android/features/login/impl/screens/waitlistscreen/WaitListStateProvider.kt
+++ b/features/login/impl/src/main/kotlin/io/element/android/features/login/impl/screens/waitlistscreen/WaitListStateProvider.kt
@@ -25,7 +25,7 @@ open class WaitListStateProvider : PreviewParameterProvider {
         get() = sequenceOf(
             aWaitListState(loginAction = Async.Uninitialized),
             aWaitListState(loginAction = Async.Loading()),
-            aWaitListState(loginAction = Async.Failure(Throwable())),
+            aWaitListState(loginAction = Async.Failure(Throwable("error"))),
             aWaitListState(loginAction = Async.Failure(Throwable(message = "IO_ELEMENT_X_WAIT_LIST"))),
             aWaitListState(loginAction = Async.Success(SessionId("@alice:element.io"))),
             // Add other state here
diff --git a/features/login/impl/src/main/kotlin/io/element/android/features/login/impl/screens/waitlistscreen/WaitListView.kt b/features/login/impl/src/main/kotlin/io/element/android/features/login/impl/screens/waitlistscreen/WaitListView.kt
index 73fbaf30f9..025a67516d 100644
--- a/features/login/impl/src/main/kotlin/io/element/android/features/login/impl/screens/waitlistscreen/WaitListView.kt
+++ b/features/login/impl/src/main/kotlin/io/element/android/features/login/impl/screens/waitlistscreen/WaitListView.kt
@@ -29,7 +29,6 @@ import androidx.compose.foundation.layout.padding
 import androidx.compose.foundation.layout.size
 import androidx.compose.foundation.layout.systemBarsPadding
 import androidx.compose.foundation.layout.widthIn
-import androidx.compose.material3.ButtonDefaults
 import androidx.compose.runtime.Composable
 import androidx.compose.ui.Alignment
 import androidx.compose.ui.BiasAbsoluteAlignment
@@ -52,7 +51,6 @@ import io.element.android.libraries.architecture.Async
 import io.element.android.libraries.designsystem.components.dialogs.RetryDialog
 import io.element.android.libraries.designsystem.preview.ElementPreviewDark
 import io.element.android.libraries.designsystem.preview.ElementPreviewLight
-import io.element.android.libraries.designsystem.theme.aliasButtonText
 import io.element.android.libraries.designsystem.theme.components.Button
 import io.element.android.libraries.designsystem.theme.components.CircularProgressIndicator
 import io.element.android.libraries.designsystem.theme.components.Text
@@ -141,18 +139,10 @@ private fun WaitListContent(
             .padding(horizontal = 16.dp, vertical = 16.dp)
     ) {
         if (state.loginAction !is Async.Success) {
-            TextButton(
-                onClick = onCancelClicked,
-                colors = ButtonDefaults.buttonColors(
-                    containerColor = Color.White,
-                    contentColor = Color.Black,
-                    disabledContainerColor = Color.White,
-                    disabledContentColor = Color.Black,
-                ),
-            ) {
-                Text(
+            ElementTheme(darkTheme = true) {
+                TextButton(
                     text = stringResource(CommonStrings.action_cancel),
-                    style = ElementTheme.typography.aliasButtonText,
+                    onClick = onCancelClicked,
                 )
             }
         }
@@ -208,22 +198,14 @@ private fun WaitListContent(
             }
         }
         if (state.loginAction is Async.Success) {
-            Button(
-                onClick = { state.eventSink.invoke(WaitListEvents.Continue) },
-                colors = ButtonDefaults.buttonColors(
-                    containerColor = Color.White,
-                    contentColor = Color.Black,
-                    disabledContainerColor = Color.White,
-                    disabledContentColor = Color.Black,
-                ),
-                modifier = Modifier
-                    .fillMaxWidth()
-                    .align(Alignment.BottomCenter)
-                    .padding(bottom = 8.dp)
-            ) {
-                Text(
+            ElementTheme(darkTheme = true) {
+                Button(
                     text = stringResource(id = CommonStrings.action_continue),
-                    style = ElementTheme.typography.aliasButtonText,
+                    onClick = { state.eventSink.invoke(WaitListEvents.Continue) },
+                    modifier = Modifier
+                        .fillMaxWidth()
+                        .align(Alignment.BottomCenter)
+                        .padding(bottom = 8.dp),
                 )
             }
         }
diff --git a/features/login/impl/src/main/res/drawable/ic_homeserver.xml b/features/login/impl/src/main/res/drawable/ic_homeserver.xml
deleted file mode 100644
index ee061f7007..0000000000
--- a/features/login/impl/src/main/res/drawable/ic_homeserver.xml
+++ /dev/null
@@ -1,13 +0,0 @@
-
-  
-    
-    
-  
-
diff --git a/features/login/impl/src/main/res/drawable/onboarding_icon_light.png b/features/login/impl/src/main/res/drawable/onboarding_icon_light.png
deleted file mode 100644
index ffd8631c47..0000000000
Binary files a/features/login/impl/src/main/res/drawable/onboarding_icon_light.png and /dev/null differ
diff --git a/features/login/impl/src/main/res/values-de/translations.xml b/features/login/impl/src/main/res/values-de/translations.xml
index efc7c0cf3c..965cc30c4e 100644
--- a/features/login/impl/src/main/res/values-de/translations.xml
+++ b/features/login/impl/src/main/res/values-de/translations.xml
@@ -3,13 +3,13 @@
   "Kontoanbieter wechseln"
   "Weiter"
   "Adresse des Homeservers"
-  "Geben Sie einen Suchbegriff oder eine Domainadresse ein."
+  "Gib einen Suchbegriff oder eine Domainadresse ein."
   "Suche nach einem Unternehmen, einer Community oder einem privaten Server."
-  "Finde einen Accountanbieter"
+  "Finde einen Kontoanbieter"
   "Hier werden deine Konversationen stattfinden — genauso wie du einen E-Mail-Anbieter verwenden würdest, um deine E-Mails aufzubewahren."
   "Du bist dabei dich bei %s anzumelden"
   "Hier werden deine Konversationen stattfinden — genauso wie du einen E-Mail-Anbieter verwenden würdest, um deine E-Mails aufzubewahren."
-  "Du bist dabei einen Account auf %s zu erstellen"
+  "Du bist dabei ein Konto auf %s zu erstellen"
   "Matrix.org ist ein offenes Netzwerk für sichere, dezentralisierte Kommunikation."
   "Andere"
   "Verwende einen anderen Kontoanbieter, z. B. deinen eigenen privaten Server oder ein Arbeitskonto."
@@ -31,7 +31,7 @@
   "Matrix ist ein offenes Netzwerk für sichere, dezentrale Kommunikation"
   "Hier werden deine Konversationen stattfinden — genau so wie du einen E-Mail-Anbieter verwenden würdest, um deine E-Mails aufzubewahren."
   "Du bist dabei dich bei %1$s anzumelden"
-  "Du bist dabei einen Account auf %1$s zu erstellen"
+  "Du bist dabei ein Konto auf %1$s zu erstellen"
   "Im Moment besteht eine hohe Nachfrage nach %1$s auf %2$s. Besuche die App in ein paar Tagen wieder und versuche es erneut.
 
 Vielen Dank für deine Geduld!"
diff --git a/features/login/impl/src/main/res/values-ru/translations.xml b/features/login/impl/src/main/res/values-ru/translations.xml
new file mode 100644
index 0000000000..33514e9f09
--- /dev/null
+++ b/features/login/impl/src/main/res/values-ru/translations.xml
@@ -0,0 +1,47 @@
+
+
+  "Переключить аккаунт"
+  "Продолжить"
+  "Адрес домашнего сервера"
+  "Введите поисковый запрос или адрес домена."
+  "Поиск компании, сообщества или частного сервера."
+  "Поиск сервера учетной записи"
+  "Здесь будут храниться ваши разговоры - точно так же, как вы используете почтового провайдера для хранения своих писем."
+  "Вы собираетесь войти в %s"
+  "Здесь будут храниться ваши разговоры - точно так же, как вы используете почтового провайдера для хранения своих писем."
+  "Вы собираетесь создать учетную запись на %s"
+  "Matrix.org — это открытая сеть для безопасной децентрализованной связи."
+  "Другое"
+  "Используйте другого поставщика учетных записей, например, собственный частный сервер или рабочую учетную запись."
+  "Сменить поставщика учетной записи"
+  "Нам не удалось связаться с этим домашним сервером. Убедитесь, что вы правильно ввели URL-адрес домашнего сервера. Если URL-адрес указан правильно, обратитесь к администратору домашнего сервера за дополнительной помощью."
+  "В настоящее время этот сервер не поддерживает скользящую синхронизацию."
+  "URL-адрес домашнего сервера"
+  "Вы можете подключиться только к существующему серверу, поддерживающему скользящую синхронизацию. Администратору домашнего сервера потребуется настроить его. %1$s"
+  "Какой адрес у вашего сервера?"
+  "Данная учетная запись была деактивирована."
+  "Неверное имя пользователя и/или пароль"
+  "Это не корректный идентификатор пользователя. Ожидаемый формат: \'@user:homeserver.org\'"
+  "Выбранный домашний сервер не поддерживает пароль или логин OIDC. Пожалуйста, свяжитесь с администратором или выберите другой домашний сервер."
+  "Введите сведения о себе"
+  "Рады видеть вас снова!"
+  "Войти в %1$s"
+  "Сменить учетную запись"
+  "Частный сервер для сотрудников Element."
+  "Matrix — это открытая сеть для безопасной децентрализованной связи."
+  "Здесь будут храниться ваши разговоры - точно так же, как вы используете почтового провайдера для хранения своих писем."
+  "Вы собираетесь войти в %1$s"
+  "Вы собираетесь создать учетную запись на %1$s"
+  "В настоящее время существует высокий спрос на %1$s на %2$s. Вернитесь в приложение через несколько дней и попробуйте снова.
+
+Спасибо за терпение!"
+  "Добро пожаловать в %1$s!"
+  "Почти готово!"
+  "Вы зарегистрированы!"
+  "Продолжить"
+  "Выберите свой сервер"
+  "Пароль"
+  "Продолжить"
+  "Matrix — это открытая сеть для безопасной децентрализованной связи."
+  "Имя пользователя"
+
diff --git a/features/login/impl/src/main/res/values-sk/translations.xml b/features/login/impl/src/main/res/values-sk/translations.xml
index 2cdaf596e1..2969e4ecb0 100644
--- a/features/login/impl/src/main/res/values-sk/translations.xml
+++ b/features/login/impl/src/main/res/values-sk/translations.xml
@@ -6,9 +6,9 @@
   "Zadajte hľadaný výraz alebo adresu domény."
   "Vyhľadať spoločnosť, komunitu alebo súkromný server."
   "Nájsť poskytovateľa účtu"
-  "Tu budú žiť vaše konverzácie - podobne ako používate poskytovateľa e-mailových služieb na uchovávanie e-mailov."
+  "Tu budú žiť vaše konverzácie — podobne ako používate poskytovateľa e-mailových služieb na uchovávanie e-mailov."
   "Chystáte sa prihlásiť do %s"
-  "Tu budú žiť vaše konverzácie - podobne ako používate poskytovateľa e-mailových služieb na uchovávanie e-mailov."
+  "Tu budú žiť vaše konverzácie — podobne ako používate poskytovateľa e-mailových služieb na uchovávanie e-mailov."
   "Chystáte sa vytvoriť účet na %s"
   "Matrix.org je otvorená sieť pre bezpečnú a decentralizovanú komunikáciu."
   "Iný"
diff --git a/features/login/impl/src/main/res/values-zh-rTW/translations.xml b/features/login/impl/src/main/res/values-zh-rTW/translations.xml
new file mode 100644
index 0000000000..ae2ccae3f5
--- /dev/null
+++ b/features/login/impl/src/main/res/values-zh-rTW/translations.xml
@@ -0,0 +1,16 @@
+
+
+  "繼續"
+  "您即將登入%s"
+  "您即將在 %s 建立帳號"
+  "其他"
+  "歡迎回來!"
+  "您即將登入 %1$s"
+  "您即將在 %1$s 建立帳號"
+  "歡迎使用 %1$s!"
+  "繼續"
+  "選擇您的伺服器"
+  "密碼"
+  "繼續"
+  "使用者名稱"
+
diff --git a/features/login/impl/src/test/kotlin/io/element/android/features/login/impl/changeserver/ChangeServerPresenterTest.kt b/features/login/impl/src/test/kotlin/io/element/android/features/login/impl/changeserver/ChangeServerPresenterTest.kt
index 9aefafb382..009ab31dcd 100644
--- a/features/login/impl/src/test/kotlin/io/element/android/features/login/impl/changeserver/ChangeServerPresenterTest.kt
+++ b/features/login/impl/src/test/kotlin/io/element/android/features/login/impl/changeserver/ChangeServerPresenterTest.kt
@@ -16,7 +16,7 @@
 
 package io.element.android.features.login.impl.changeserver
 
-import app.cash.molecule.RecompositionClock
+import app.cash.molecule.RecompositionMode
 import app.cash.molecule.moleculeFlow
 import app.cash.turbine.test
 import com.google.common.truth.Truth.assertThat
@@ -36,7 +36,7 @@ class ChangeServerPresenterTest {
             FakeAuthenticationService(),
             AccountProviderDataSource()
         )
-        moleculeFlow(RecompositionClock.Immediate) {
+        moleculeFlow(RecompositionMode.Immediate) {
             presenter.present()
         }.test {
             val initialState = awaitItem()
@@ -51,7 +51,7 @@ class ChangeServerPresenterTest {
             authenticationService,
             AccountProviderDataSource()
         )
-        moleculeFlow(RecompositionClock.Immediate) {
+        moleculeFlow(RecompositionMode.Immediate) {
             presenter.present()
         }.test {
             val initialState = awaitItem()
@@ -72,7 +72,7 @@ class ChangeServerPresenterTest {
             authenticationService,
             AccountProviderDataSource()
         )
-        moleculeFlow(RecompositionClock.Immediate) {
+        moleculeFlow(RecompositionMode.Immediate) {
             presenter.present()
         }.test {
             val initialState = awaitItem()
diff --git a/features/login/impl/src/test/kotlin/io/element/android/features/login/impl/oidc/webview/OidcPresenterTest.kt b/features/login/impl/src/test/kotlin/io/element/android/features/login/impl/oidc/webview/OidcPresenterTest.kt
index 5756cd13d2..32d1c6918a 100644
--- a/features/login/impl/src/test/kotlin/io/element/android/features/login/impl/oidc/webview/OidcPresenterTest.kt
+++ b/features/login/impl/src/test/kotlin/io/element/android/features/login/impl/oidc/webview/OidcPresenterTest.kt
@@ -18,7 +18,7 @@
 
 package io.element.android.features.login.impl.oidc.webview
 
-import app.cash.molecule.RecompositionClock
+import app.cash.molecule.RecompositionMode
 import app.cash.molecule.moleculeFlow
 import app.cash.turbine.test
 import com.google.common.truth.Truth.assertThat
@@ -38,7 +38,7 @@ class OidcPresenterTest {
             A_OIDC_DATA,
             FakeAuthenticationService(),
         )
-        moleculeFlow(RecompositionClock.Immediate) {
+        moleculeFlow(RecompositionMode.Immediate) {
             presenter.present()
         }.test {
             val initialState = awaitItem()
@@ -53,7 +53,7 @@ class OidcPresenterTest {
             A_OIDC_DATA,
             FakeAuthenticationService(),
         )
-        moleculeFlow(RecompositionClock.Immediate) {
+        moleculeFlow(RecompositionMode.Immediate) {
             presenter.present()
         }.test {
             val initialState = awaitItem()
@@ -73,7 +73,7 @@ class OidcPresenterTest {
             authenticationService,
         )
         authenticationService.givenOidcCancelError(A_THROWABLE)
-        moleculeFlow(RecompositionClock.Immediate) {
+        moleculeFlow(RecompositionMode.Immediate) {
             presenter.present()
         }.test {
             val initialState = awaitItem()
@@ -92,7 +92,7 @@ class OidcPresenterTest {
             A_OIDC_DATA,
             FakeAuthenticationService(),
         )
-        moleculeFlow(RecompositionClock.Immediate) {
+        moleculeFlow(RecompositionMode.Immediate) {
             presenter.present()
         }.test {
             val initialState = awaitItem()
@@ -110,7 +110,7 @@ class OidcPresenterTest {
             A_OIDC_DATA,
             FakeAuthenticationService(),
         )
-        moleculeFlow(RecompositionClock.Immediate) {
+        moleculeFlow(RecompositionMode.Immediate) {
             presenter.present()
         }.test {
             val initialState = awaitItem()
@@ -129,7 +129,7 @@ class OidcPresenterTest {
             authenticationService,
         )
         authenticationService.givenLoginError(A_THROWABLE)
-        moleculeFlow(RecompositionClock.Immediate) {
+        moleculeFlow(RecompositionMode.Immediate) {
             presenter.present()
         }.test {
             val initialState = awaitItem()
diff --git a/features/login/impl/src/test/kotlin/io/element/android/features/login/impl/screens/changeaccountprovider/ChangeAccountProviderPresenterTest.kt b/features/login/impl/src/test/kotlin/io/element/android/features/login/impl/screens/changeaccountprovider/ChangeAccountProviderPresenterTest.kt
index 086428257a..f807355cb1 100644
--- a/features/login/impl/src/test/kotlin/io/element/android/features/login/impl/screens/changeaccountprovider/ChangeAccountProviderPresenterTest.kt
+++ b/features/login/impl/src/test/kotlin/io/element/android/features/login/impl/screens/changeaccountprovider/ChangeAccountProviderPresenterTest.kt
@@ -16,7 +16,7 @@
 
 package io.element.android.features.login.impl.screens.changeaccountprovider
 
-import app.cash.molecule.RecompositionClock
+import app.cash.molecule.RecompositionMode
 import app.cash.molecule.moleculeFlow
 import app.cash.turbine.test
 import com.google.common.truth.Truth.assertThat
@@ -37,7 +37,7 @@ class ChangeAccountProviderPresenterTest {
         val presenter = ChangeAccountProviderPresenter(
             changeServerPresenter
         )
-        moleculeFlow(RecompositionClock.Immediate) {
+        moleculeFlow(RecompositionMode.Immediate) {
             presenter.present()
         }.test {
             val initialState = awaitItem()
diff --git a/features/login/impl/src/test/kotlin/io/element/android/features/login/impl/screens/confirmaccountprovider/ConfirmAccountProviderPresenterTest.kt b/features/login/impl/src/test/kotlin/io/element/android/features/login/impl/screens/confirmaccountprovider/ConfirmAccountProviderPresenterTest.kt
index 131d0d9298..76a3ad3d22 100644
--- a/features/login/impl/src/test/kotlin/io/element/android/features/login/impl/screens/confirmaccountprovider/ConfirmAccountProviderPresenterTest.kt
+++ b/features/login/impl/src/test/kotlin/io/element/android/features/login/impl/screens/confirmaccountprovider/ConfirmAccountProviderPresenterTest.kt
@@ -16,7 +16,7 @@
 
 package io.element.android.features.login.impl.screens.confirmaccountprovider
 
-import app.cash.molecule.RecompositionClock
+import app.cash.molecule.RecompositionMode
 import app.cash.molecule.moleculeFlow
 import app.cash.turbine.test
 import com.google.common.truth.Truth.assertThat
@@ -38,7 +38,7 @@ class ConfirmAccountProviderPresenterTest {
             AccountProviderDataSource(),
             FakeAuthenticationService(),
         )
-        moleculeFlow(RecompositionClock.Immediate) {
+        moleculeFlow(RecompositionMode.Immediate) {
             presenter.present()
         }.test {
             val initialState = awaitItem()
@@ -58,7 +58,7 @@ class ConfirmAccountProviderPresenterTest {
             authServer,
         )
         authServer.givenHomeserver(A_HOMESERVER)
-        moleculeFlow(RecompositionClock.Immediate) {
+        moleculeFlow(RecompositionMode.Immediate) {
             presenter.present()
         }.test {
             val initialState = awaitItem()
@@ -82,7 +82,7 @@ class ConfirmAccountProviderPresenterTest {
             authServer,
         )
         authServer.givenHomeserver(A_HOMESERVER_OIDC)
-        moleculeFlow(RecompositionClock.Immediate) {
+        moleculeFlow(RecompositionMode.Immediate) {
             presenter.present()
         }.test {
             val initialState = awaitItem()
@@ -105,7 +105,7 @@ class ConfirmAccountProviderPresenterTest {
             AccountProviderDataSource(),
             authServer,
         )
-        moleculeFlow(RecompositionClock.Immediate) {
+        moleculeFlow(RecompositionMode.Immediate) {
             presenter.present()
         }.test {
             val initialState = awaitItem()
@@ -126,7 +126,7 @@ class ConfirmAccountProviderPresenterTest {
             AccountProviderDataSource(),
             authenticationService,
         )
-        moleculeFlow(RecompositionClock.Immediate) {
+        moleculeFlow(RecompositionMode.Immediate) {
             presenter.present()
         }.test {
             val initialState = awaitItem()
diff --git a/features/login/impl/src/test/kotlin/io/element/android/features/login/impl/screens/loginpassword/LoginPasswordPresenterTest.kt b/features/login/impl/src/test/kotlin/io/element/android/features/login/impl/screens/loginpassword/LoginPasswordPresenterTest.kt
index afd4b542e4..421eb869b0 100644
--- a/features/login/impl/src/test/kotlin/io/element/android/features/login/impl/screens/loginpassword/LoginPasswordPresenterTest.kt
+++ b/features/login/impl/src/test/kotlin/io/element/android/features/login/impl/screens/loginpassword/LoginPasswordPresenterTest.kt
@@ -16,7 +16,7 @@
 
 package io.element.android.features.login.impl.screens.loginpassword
 
-import app.cash.molecule.RecompositionClock
+import app.cash.molecule.RecompositionMode
 import app.cash.molecule.moleculeFlow
 import app.cash.turbine.test
 import com.google.common.truth.Truth.assertThat
@@ -45,7 +45,7 @@ class LoginPasswordPresenterTest {
             accountProviderDataSource,
             loginUserStory,
         )
-        moleculeFlow(RecompositionClock.Immediate) {
+        moleculeFlow(RecompositionMode.Immediate) {
             presenter.present()
         }.test {
             val initialState = awaitItem()
@@ -67,7 +67,7 @@ class LoginPasswordPresenterTest {
             loginUserStory,
         )
         authenticationService.givenHomeserver(A_HOMESERVER)
-        moleculeFlow(RecompositionClock.Immediate) {
+        moleculeFlow(RecompositionMode.Immediate) {
             presenter.present()
         }.test {
             val initialState = awaitItem()
@@ -93,7 +93,7 @@ class LoginPasswordPresenterTest {
             loginUserStory,
         )
         authenticationService.givenHomeserver(A_HOMESERVER)
-        moleculeFlow(RecompositionClock.Immediate) {
+        moleculeFlow(RecompositionMode.Immediate) {
             presenter.present()
         }.test {
             assertThat(loginUserStory.loginFlowIsDone.value).isFalse()
@@ -122,7 +122,7 @@ class LoginPasswordPresenterTest {
             loginUserStory,
         )
         authenticationService.givenHomeserver(A_HOMESERVER)
-        moleculeFlow(RecompositionClock.Immediate) {
+        moleculeFlow(RecompositionMode.Immediate) {
             presenter.present()
         }.test {
             val initialState = awaitItem()
@@ -150,7 +150,7 @@ class LoginPasswordPresenterTest {
             loginUserStory,
         )
         authenticationService.givenHomeserver(A_HOMESERVER)
-        moleculeFlow(RecompositionClock.Immediate) {
+        moleculeFlow(RecompositionMode.Immediate) {
             presenter.present()
         }.test {
             val initialState = awaitItem()
diff --git a/features/login/impl/src/test/kotlin/io/element/android/features/login/impl/screens/searchaccountprovider/SearchAccountProviderPresenterTest.kt b/features/login/impl/src/test/kotlin/io/element/android/features/login/impl/screens/searchaccountprovider/SearchAccountProviderPresenterTest.kt
index 9163f247f5..ae6ae4d344 100644
--- a/features/login/impl/src/test/kotlin/io/element/android/features/login/impl/screens/searchaccountprovider/SearchAccountProviderPresenterTest.kt
+++ b/features/login/impl/src/test/kotlin/io/element/android/features/login/impl/screens/searchaccountprovider/SearchAccountProviderPresenterTest.kt
@@ -16,7 +16,7 @@
 
 package io.element.android.features.login.impl.screens.searchaccountprovider
 
-import app.cash.molecule.RecompositionClock
+import app.cash.molecule.RecompositionMode
 import app.cash.molecule.moleculeFlow
 import app.cash.turbine.test
 import com.google.common.truth.Truth.assertThat
@@ -46,7 +46,7 @@ class SearchAccountProviderPresenterTest {
             HomeserverResolver(testCoroutineDispatchers(), fakeWellknownRequest),
             changeServerPresenter
         )
-        moleculeFlow(RecompositionClock.Immediate) {
+        moleculeFlow(RecompositionMode.Immediate) {
             presenter.present()
         }.test {
             val initialState = awaitItem()
@@ -66,7 +66,7 @@ class SearchAccountProviderPresenterTest {
             HomeserverResolver(testCoroutineDispatchers(), fakeWellknownRequest),
             changeServerPresenter
         )
-        moleculeFlow(RecompositionClock.Immediate) {
+        moleculeFlow(RecompositionMode.Immediate) {
             presenter.present()
         }.test {
             val initialState = awaitItem()
@@ -90,7 +90,7 @@ class SearchAccountProviderPresenterTest {
             HomeserverResolver(testCoroutineDispatchers(), fakeWellknownRequest),
             changeServerPresenter
         )
-        moleculeFlow(RecompositionClock.Immediate) {
+        moleculeFlow(RecompositionMode.Immediate) {
             presenter.present()
         }.test {
             val initialState = awaitItem()
@@ -125,7 +125,7 @@ class SearchAccountProviderPresenterTest {
             HomeserverResolver(testCoroutineDispatchers(), fakeWellknownRequest),
             changeServerPresenter
         )
-        moleculeFlow(RecompositionClock.Immediate) {
+        moleculeFlow(RecompositionMode.Immediate) {
             presenter.present()
         }.test {
             val initialState = awaitItem()
@@ -160,7 +160,7 @@ class SearchAccountProviderPresenterTest {
             HomeserverResolver(testCoroutineDispatchers(), fakeWellknownRequest),
             changeServerPresenter
         )
-        moleculeFlow(RecompositionClock.Immediate) {
+        moleculeFlow(RecompositionMode.Immediate) {
             presenter.present()
         }.test {
             val initialState = awaitItem()
diff --git a/features/login/impl/src/test/kotlin/io/element/android/features/login/impl/screens/waitlistscreen/WaitListPresenterTest.kt b/features/login/impl/src/test/kotlin/io/element/android/features/login/impl/screens/waitlistscreen/WaitListPresenterTest.kt
index 389ac52176..507e8cec8b 100644
--- a/features/login/impl/src/test/kotlin/io/element/android/features/login/impl/screens/waitlistscreen/WaitListPresenterTest.kt
+++ b/features/login/impl/src/test/kotlin/io/element/android/features/login/impl/screens/waitlistscreen/WaitListPresenterTest.kt
@@ -16,7 +16,7 @@
 
 package io.element.android.features.login.impl.screens.waitlistscreen
 
-import app.cash.molecule.RecompositionClock
+import app.cash.molecule.RecompositionMode
 import app.cash.molecule.moleculeFlow
 import app.cash.turbine.test
 import com.google.common.truth.Truth.assertThat
@@ -46,7 +46,7 @@ class WaitListPresenterTest {
             authenticationService,
             loginUserStory,
         )
-        moleculeFlow(RecompositionClock.Immediate) {
+        moleculeFlow(RecompositionMode.Immediate) {
             presenter.present()
         }.test {
             val initialState = awaitItem()
@@ -68,7 +68,7 @@ class WaitListPresenterTest {
             authenticationService,
             loginUserStory,
         )
-        moleculeFlow(RecompositionClock.Immediate) {
+        moleculeFlow(RecompositionMode.Immediate) {
             presenter.present()
         }.test {
             val initialState = awaitItem()
@@ -97,7 +97,7 @@ class WaitListPresenterTest {
             authenticationService,
             loginUserStory,
         )
-        moleculeFlow(RecompositionClock.Immediate) {
+        moleculeFlow(RecompositionMode.Immediate) {
             presenter.present()
         }.test {
             assertThat(loginUserStory.loginFlowIsDone.value).isFalse()
diff --git a/features/logout/api/src/main/res/values-ru/translations.xml b/features/logout/api/src/main/res/values-ru/translations.xml
new file mode 100644
index 0000000000..3991e27251
--- /dev/null
+++ b/features/logout/api/src/main/res/values-ru/translations.xml
@@ -0,0 +1,8 @@
+
+
+  "Вы уверены, что вы хотите выйти?"
+  "Выйти"
+  "Выполняется выход…"
+  "Выйти"
+  "Выйти"
+
diff --git a/features/logout/api/src/main/res/values-zh-rTW/translations.xml b/features/logout/api/src/main/res/values-zh-rTW/translations.xml
new file mode 100644
index 0000000000..df722a9467
--- /dev/null
+++ b/features/logout/api/src/main/res/values-zh-rTW/translations.xml
@@ -0,0 +1,8 @@
+
+
+  "您確定要登出嗎?"
+  "登出"
+  "正在登出…"
+  "登出"
+  "登出"
+
diff --git a/features/logout/impl/build.gradle.kts b/features/logout/impl/build.gradle.kts
index 88d8282875..464695e169 100644
--- a/features/logout/impl/build.gradle.kts
+++ b/features/logout/impl/build.gradle.kts
@@ -48,6 +48,4 @@ dependencies {
     testImplementation(libs.test.truth)
     testImplementation(libs.test.turbine)
     testImplementation(projects.libraries.matrix.test)
-
-    androidTestImplementation(libs.test.junitext)
 }
diff --git a/features/logout/impl/src/test/kotlin/io/element/android/features/logout/impl/LogoutPreferencePresenterTest.kt b/features/logout/impl/src/test/kotlin/io/element/android/features/logout/impl/LogoutPreferencePresenterTest.kt
index bed33006d6..29df521cb1 100644
--- a/features/logout/impl/src/test/kotlin/io/element/android/features/logout/impl/LogoutPreferencePresenterTest.kt
+++ b/features/logout/impl/src/test/kotlin/io/element/android/features/logout/impl/LogoutPreferencePresenterTest.kt
@@ -16,7 +16,7 @@
 
 package io.element.android.features.logout.impl
 
-import app.cash.molecule.RecompositionClock
+import app.cash.molecule.RecompositionMode
 import app.cash.molecule.moleculeFlow
 import app.cash.turbine.test
 import com.google.common.truth.Truth.assertThat
@@ -34,7 +34,7 @@ class LogoutPreferencePresenterTest {
         val presenter = DefaultLogoutPreferencePresenter(
             FakeMatrixClient(),
         )
-        moleculeFlow(RecompositionClock.Immediate) {
+        moleculeFlow(RecompositionMode.Immediate) {
             presenter.present()
         }.test {
             val initialState = awaitItem()
@@ -47,7 +47,7 @@ class LogoutPreferencePresenterTest {
         val presenter = DefaultLogoutPreferencePresenter(
             FakeMatrixClient(),
         )
-        moleculeFlow(RecompositionClock.Immediate) {
+        moleculeFlow(RecompositionMode.Immediate) {
             presenter.present()
         }.test {
             val initialState = awaitItem()
@@ -65,7 +65,7 @@ class LogoutPreferencePresenterTest {
         val presenter = DefaultLogoutPreferencePresenter(
             matrixClient,
         )
-        moleculeFlow(RecompositionClock.Immediate) {
+        moleculeFlow(RecompositionMode.Immediate) {
             presenter.present()
         }.test {
             val initialState = awaitItem()
diff --git a/features/messages/impl/build.gradle.kts b/features/messages/impl/build.gradle.kts
index 7488820f7d..4746cff1de 100644
--- a/features/messages/impl/build.gradle.kts
+++ b/features/messages/impl/build.gradle.kts
@@ -34,6 +34,7 @@ dependencies {
     anvil(projects.anvilcodegen)
     api(projects.features.messages.api)
     implementation(projects.features.location.api)
+    implementation(projects.features.poll.api)
     implementation(projects.libraries.androidutils)
     implementation(projects.libraries.core)
     implementation(projects.libraries.architecture)
@@ -52,7 +53,6 @@ dependencies {
     implementation(libs.coil.compose)
     implementation(libs.datetime)
     implementation(libs.accompanist.flowlayout)
-    implementation(libs.androidx.recyclerview)
     implementation(libs.jsoup)
     implementation(libs.androidx.constraintlayout)
     implementation(libs.androidx.constraintlayout.compose)
@@ -78,6 +78,5 @@ dependencies {
     testImplementation(projects.libraries.mediapickers.test)
     testImplementation(libs.test.mockk)
 
-    androidTestImplementation(libs.test.junitext)
     ksp(libs.showkase.processor)
 }
diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/MessagesPresenter.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/MessagesPresenter.kt
index a0a3e3a286..8a374471e3 100644
--- a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/MessagesPresenter.kt
+++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/MessagesPresenter.kt
@@ -21,10 +21,8 @@ import androidx.compose.runtime.Composable
 import androidx.compose.runtime.LaunchedEffect
 import androidx.compose.runtime.MutableState
 import androidx.compose.runtime.collectAsState
-import androidx.compose.runtime.derivedStateOf
 import androidx.compose.runtime.getValue
 import androidx.compose.runtime.mutableStateOf
-import androidx.compose.runtime.produceState
 import androidx.compose.runtime.remember
 import androidx.compose.runtime.rememberCoroutineScope
 import androidx.compose.runtime.saveable.rememberSaveable
@@ -41,6 +39,7 @@ import io.element.android.features.messages.impl.messagecomposer.MessageComposer
 import io.element.android.features.messages.impl.timeline.TimelineEvents
 import io.element.android.features.messages.impl.timeline.TimelinePresenter
 import io.element.android.features.messages.impl.timeline.components.customreaction.CustomReactionPresenter
+import io.element.android.features.messages.impl.timeline.components.reactionsummary.ReactionSummaryPresenter
 import io.element.android.features.messages.impl.timeline.components.retrysendmenu.RetrySendMenuPresenter
 import io.element.android.features.messages.impl.timeline.model.TimelineItem
 import io.element.android.features.messages.impl.timeline.model.event.TimelineItemAudioContent
@@ -48,6 +47,7 @@ import io.element.android.features.messages.impl.timeline.model.event.TimelineIt
 import io.element.android.features.messages.impl.timeline.model.event.TimelineItemFileContent
 import io.element.android.features.messages.impl.timeline.model.event.TimelineItemImageContent
 import io.element.android.features.messages.impl.timeline.model.event.TimelineItemLocationContent
+import io.element.android.features.messages.impl.timeline.model.event.TimelineItemPollContent
 import io.element.android.features.messages.impl.timeline.model.event.TimelineItemRedactedContent
 import io.element.android.features.messages.impl.timeline.model.event.TimelineItemStateContent
 import io.element.android.features.messages.impl.timeline.model.event.TimelineItemTextBasedContent
@@ -72,10 +72,12 @@ import io.element.android.libraries.matrix.api.room.MatrixRoomMembersState
 import io.element.android.libraries.matrix.api.room.MessageEventType
 import io.element.android.libraries.matrix.ui.components.AttachmentThumbnailInfo
 import io.element.android.libraries.matrix.ui.components.AttachmentThumbnailType
+import io.element.android.libraries.matrix.ui.room.canRedactAsState
 import io.element.android.libraries.matrix.ui.room.canSendMessageAsState
 import io.element.android.libraries.textcomposer.MessageComposerMode
 import kotlinx.coroutines.CoroutineScope
 import kotlinx.coroutines.launch
+import kotlinx.coroutines.withContext
 import timber.log.Timber
 
 class MessagesPresenter @AssistedInject constructor(
@@ -84,6 +86,7 @@ class MessagesPresenter @AssistedInject constructor(
     private val timelinePresenter: TimelinePresenter,
     private val actionListPresenter: ActionListPresenter,
     private val customReactionPresenter: CustomReactionPresenter,
+    private val reactionSummaryPresenter: ReactionSummaryPresenter,
     private val retrySendMenuPresenter: RetrySendMenuPresenter,
     private val networkMonitor: NetworkMonitor,
     private val snackbarDispatcher: SnackbarDispatcher,
@@ -105,32 +108,31 @@ class MessagesPresenter @AssistedInject constructor(
         val timelineState = timelinePresenter.present()
         val actionListState = actionListPresenter.present()
         val customReactionState = customReactionPresenter.present()
+        val reactionSummaryState = reactionSummaryPresenter.present()
         val retryState = retrySendMenuPresenter.present()
 
         val syncUpdateFlow = room.syncUpdateFlow.collectAsState()
         val userHasPermissionToSendMessage by room.canSendMessageAsState(type = MessageEventType.ROOM_MESSAGE, updateKey = syncUpdateFlow.value)
-        val roomName by produceState(initialValue = room.displayName, key1 = syncUpdateFlow.value) {
-            value = room.displayName
-        }
-        val roomAvatar by produceState(initialValue = room.avatarData(), key1 = syncUpdateFlow.value) {
-            value = room.avatarData()
+        val userHasPermissionToRedact by room.canRedactAsState(updateKey = syncUpdateFlow.value)
+        var roomName: Async by remember { mutableStateOf(Async.Uninitialized) }
+        var roomAvatar: Async by remember { mutableStateOf(Async.Uninitialized) }
+        LaunchedEffect(syncUpdateFlow.value) {
+            withContext(dispatchers.io) {
+                roomName = Async.Success(room.displayName)
+                roomAvatar = Async.Success(room.avatarData())
+            }
         }
         var hasDismissedInviteDialog by rememberSaveable {
             mutableStateOf(false)
         }
 
         val inviteProgress = remember { mutableStateOf>(Async.Uninitialized) }
-
-        val showReinvitePrompt by remember(
-            hasDismissedInviteDialog,
-            composerState.hasFocus,
-            syncUpdateFlow,
-        ) {
-            derivedStateOf {
-                !hasDismissedInviteDialog && composerState.hasFocus && room.isDirect && room.activeMemberCount == 1L
+        var showReinvitePrompt by remember { mutableStateOf(false) }
+        LaunchedEffect(hasDismissedInviteDialog, composerState.hasFocus, syncUpdateFlow) {
+            withContext(dispatchers.io) {
+                showReinvitePrompt = !hasDismissedInviteDialog && composerState.hasFocus && room.isDirect && room.activeMemberCount == 1L
             }
         }
-
         val networkConnectionStatus by networkMonitor.connectivity.collectAsState()
 
         val snackbarMessage by snackbarDispatcher.collectSnackbarMessageAsState()
@@ -163,10 +165,12 @@ class MessagesPresenter @AssistedInject constructor(
             roomName = roomName,
             roomAvatar = roomAvatar,
             userHasPermissionToSendMessage = userHasPermissionToSendMessage,
+            userHasPermissionToRedact = userHasPermissionToRedact,
             composerState = composerState,
             timelineState = timelineState,
             actionListState = actionListState,
             customReactionState = customReactionState,
+            reactionSummaryState = reactionSummaryState,
             retrySendMenuState = retryState,
             hasNetworkConnection = networkConnectionStatus == NetworkStatus.Online,
             snackbarMessage = snackbarMessage,
@@ -274,6 +278,7 @@ class MessagesPresenter @AssistedInject constructor(
             is TimelineItemLocationContent -> AttachmentThumbnailInfo(
                 type = AttachmentThumbnailType.Location,
             )
+            is TimelineItemPollContent, // TODO Polls: handle reply to
             is TimelineItemTextBasedContent,
             is TimelineItemRedactedContent,
             is TimelineItemStateContent,
diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/MessagesState.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/MessagesState.kt
index 8a067a3a26..d22d54e7f3 100644
--- a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/MessagesState.kt
+++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/MessagesState.kt
@@ -21,6 +21,7 @@ import io.element.android.features.messages.impl.actionlist.ActionListState
 import io.element.android.features.messages.impl.messagecomposer.MessageComposerState
 import io.element.android.features.messages.impl.timeline.TimelineState
 import io.element.android.features.messages.impl.timeline.components.customreaction.CustomReactionState
+import io.element.android.features.messages.impl.timeline.components.reactionsummary.ReactionSummaryState
 import io.element.android.features.messages.impl.timeline.components.retrysendmenu.RetrySendMenuState
 import io.element.android.libraries.architecture.Async
 import io.element.android.libraries.designsystem.components.avatar.AvatarData
@@ -30,13 +31,15 @@ import io.element.android.libraries.matrix.api.core.RoomId
 @Immutable
 data class MessagesState(
     val roomId: RoomId,
-    val roomName: String,
-    val roomAvatar: AvatarData,
+    val roomName: Async,
+    val roomAvatar: Async,
     val userHasPermissionToSendMessage: Boolean,
+    val userHasPermissionToRedact: Boolean,
     val composerState: MessageComposerState,
     val timelineState: TimelineState,
     val actionListState: ActionListState,
     val customReactionState: CustomReactionState,
+    val reactionSummaryState: ReactionSummaryState,
     val retrySendMenuState: RetrySendMenuState,
     val hasNetworkConnection: Boolean,
     val snackbarMessage: SnackbarMessage?,
diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/MessagesStateProvider.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/MessagesStateProvider.kt
index d0ddcf68f4..9b3f5073a1 100644
--- a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/MessagesStateProvider.kt
+++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/MessagesStateProvider.kt
@@ -22,6 +22,7 @@ import io.element.android.features.messages.impl.messagecomposer.aMessageCompose
 import io.element.android.features.messages.impl.timeline.aTimelineItemList
 import io.element.android.features.messages.impl.timeline.aTimelineState
 import io.element.android.features.messages.impl.timeline.components.customreaction.CustomReactionState
+import io.element.android.features.messages.impl.timeline.components.reactionsummary.ReactionSummaryState
 import io.element.android.features.messages.impl.timeline.components.retrysendmenu.RetrySendMenuState
 import io.element.android.features.messages.impl.timeline.model.event.aTimelineItemTextContent
 import io.element.android.libraries.architecture.Async
@@ -29,6 +30,7 @@ import io.element.android.libraries.designsystem.components.avatar.AvatarData
 import io.element.android.libraries.designsystem.components.avatar.AvatarSize
 import io.element.android.libraries.matrix.api.core.RoomId
 import io.element.android.libraries.textcomposer.MessageComposerMode
+import kotlinx.collections.immutable.persistentSetOf
 
 open class MessagesStateProvider : PreviewParameterProvider {
     override val values: Sequence
@@ -38,14 +40,19 @@ open class MessagesStateProvider : PreviewParameterProvider {
             aMessagesState().copy(composerState = aMessageComposerState().copy(showAttachmentSourcePicker = true)),
             aMessagesState().copy(userHasPermissionToSendMessage = false),
             aMessagesState().copy(showReinvitePrompt = true),
+            aMessagesState().copy(
+                roomName = Async.Uninitialized,
+                roomAvatar = Async.Uninitialized,
+            ),
         )
 }
 
 fun aMessagesState() = MessagesState(
     roomId = RoomId("!id:domain"),
-    roomName = "Room name",
-    roomAvatar = AvatarData("!id:domain", "Room name", size = AvatarSize.TimelineRoom),
+    roomName = Async.Success("Room name"),
+    roomAvatar = Async.Success(AvatarData("!id:domain", "Room name", size = AvatarSize.TimelineRoom)),
     userHasPermissionToSendMessage = true,
+    userHasPermissionToRedact = false,
     composerState = aMessageComposerState().copy(
         text = "Hello",
         isFullScreen = false,
@@ -62,6 +69,11 @@ fun aMessagesState() = MessagesState(
     customReactionState = CustomReactionState(
         selectedEventId = null,
         eventSink = {},
+        selectedEmoji = persistentSetOf(),
+    ),
+    reactionSummaryState = ReactionSummaryState(
+        target = null,
+        eventSink = {},
     ),
     hasNetworkConnection = true,
     snackbarMessage = null,
diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/MessagesView.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/MessagesView.kt
index 6d8f2792e0..b007d59e36 100644
--- a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/MessagesView.kt
+++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/MessagesView.kt
@@ -35,7 +35,6 @@ import androidx.compose.foundation.layout.width
 import androidx.compose.foundation.layout.wrapContentHeight
 import androidx.compose.material3.ExperimentalMaterial3Api
 import androidx.compose.material3.MaterialTheme
-import androidx.compose.material3.SnackbarHost
 import androidx.compose.runtime.Composable
 import androidx.compose.runtime.LaunchedEffect
 import androidx.compose.ui.Alignment
@@ -43,13 +42,11 @@ import androidx.compose.ui.Modifier
 import androidx.compose.ui.platform.LocalView
 import androidx.compose.ui.res.stringResource
 import androidx.compose.ui.text.font.FontStyle
-import androidx.compose.ui.text.font.FontWeight
 import androidx.compose.ui.text.style.TextAlign
 import androidx.compose.ui.text.style.TextOverflow
 import androidx.compose.ui.tooling.preview.Preview
 import androidx.compose.ui.tooling.preview.PreviewParameter
 import androidx.compose.ui.unit.dp
-import androidx.compose.ui.unit.sp
 import io.element.android.features.messages.impl.actionlist.ActionListEvents
 import io.element.android.features.messages.impl.actionlist.ActionListView
 import io.element.android.features.messages.impl.actionlist.model.TimelineItemAction
@@ -59,15 +56,19 @@ import io.element.android.features.messages.impl.messagecomposer.MessageComposer
 import io.element.android.features.messages.impl.timeline.TimelineView
 import io.element.android.features.messages.impl.timeline.components.customreaction.CustomReactionBottomSheet
 import io.element.android.features.messages.impl.timeline.components.customreaction.CustomReactionEvents
+import io.element.android.features.messages.impl.timeline.components.reactionsummary.ReactionSummaryEvents
+import io.element.android.features.messages.impl.timeline.components.reactionsummary.ReactionSummaryView
 import io.element.android.features.messages.impl.timeline.components.retrysendmenu.RetrySendMenuEvents
 import io.element.android.features.messages.impl.timeline.components.retrysendmenu.RetrySendMessageMenu
 import io.element.android.features.messages.impl.timeline.model.TimelineItem
 import io.element.android.features.networkmonitor.api.ui.ConnectivityIndicatorView
 import io.element.android.libraries.androidutils.ui.hideKeyboard
+import io.element.android.libraries.designsystem.atomic.molecules.IconTitlePlaceholdersRowMolecule
 import io.element.android.libraries.designsystem.components.ProgressDialog
 import io.element.android.libraries.designsystem.components.ProgressDialogType
 import io.element.android.libraries.designsystem.components.avatar.Avatar
 import io.element.android.libraries.designsystem.components.avatar.AvatarData
+import io.element.android.libraries.designsystem.components.avatar.AvatarSize
 import io.element.android.libraries.designsystem.components.button.BackButton
 import io.element.android.libraries.designsystem.components.dialogs.ConfirmationDialog
 import io.element.android.libraries.designsystem.preview.ElementPreviewDark
@@ -76,6 +77,7 @@ import io.element.android.libraries.designsystem.theme.components.Scaffold
 import io.element.android.libraries.designsystem.theme.components.Text
 import io.element.android.libraries.designsystem.theme.components.TopAppBar
 import io.element.android.libraries.designsystem.utils.LogCompositions
+import io.element.android.libraries.designsystem.utils.SnackbarHost
 import io.element.android.libraries.designsystem.utils.rememberSnackbarHostState
 import io.element.android.libraries.matrix.api.core.UserId
 import io.element.android.libraries.matrix.api.timeline.item.event.LocalEventSendState
@@ -115,7 +117,7 @@ fun MessagesView(
     fun onMessageLongClicked(event: TimelineItem.Event) {
         Timber.v("OnMessageLongClicked= ${event.id}")
         localView.hideKeyboard()
-        state.actionListState.eventSink(ActionListEvents.ComputeForMessage(event))
+        state.actionListState.eventSink(ActionListEvents.ComputeForMessage(event, state.userHasPermissionToRedact))
     }
 
     fun onActionSelected(action: TimelineItemAction, event: TimelineItem.Event) {
@@ -127,8 +129,14 @@ fun MessagesView(
         state.eventSink(MessagesEvents.ToggleReaction(emoji, event.eventId))
     }
 
-    fun onMoreReactionsClicked(event: TimelineItem.Event): Unit =
-        state.customReactionState.eventSink(CustomReactionEvents.UpdateSelectedEvent(event.eventId))
+    fun onEmojiReactionLongClicked(emoji: String, event: TimelineItem.Event) {
+        if (event.eventId == null) return
+        state.reactionSummaryState.eventSink(ReactionSummaryEvents.ShowReactionSummary(event.eventId, event.reactionsState.reactions, emoji))
+    }
+
+    fun onMoreReactionsClicked(event: TimelineItem.Event) {
+        state.customReactionState.eventSink(CustomReactionEvents.UpdateSelectedEvent(event))
+    }
 
     Scaffold(
         modifier = modifier,
@@ -137,8 +145,8 @@ fun MessagesView(
             Column {
                 ConnectivityIndicatorView(isOnline = state.hasNetworkConnection)
                 MessagesViewTopBar(
-                    roomTitle = state.roomName,
-                    roomAvatar = state.roomAvatar,
+                    roomName = state.roomName.dataOrNull(),
+                    roomAvatar = state.roomAvatar.dataOrNull(),
                     onBackPressed = onBackPressed,
                     onRoomDetailsClicked = onRoomDetailsClicked,
                 )
@@ -159,6 +167,7 @@ fun MessagesView(
                     }
                 },
                 onReactionClicked = ::onEmojiReactionClicked,
+                onReactionLongClicked = ::onEmojiReactionLongClicked,
                 onMoreReactionsClicked = ::onMoreReactionsClicked,
                 onSendLocationClicked = onSendLocationClicked,
                 onSwipeToReply = { targetEvent ->
@@ -178,7 +187,7 @@ fun MessagesView(
         state = state.actionListState,
         onActionSelected = ::onActionSelected,
         onCustomReactionClicked = { event ->
-            state.customReactionState.eventSink(CustomReactionEvents.UpdateSelectedEvent(event.eventId))
+            state.customReactionState.eventSink(CustomReactionEvents.UpdateSelectedEvent(event))
         },
         onEmojiReactionClicked = ::onEmojiReactionClicked,
     )
@@ -193,6 +202,7 @@ fun MessagesView(
         }
     )
 
+    ReactionSummaryView(state = state.reactionSummaryState)
     RetrySendMessageMenu(
         state = state.retrySendMenuState
     )
@@ -203,14 +213,13 @@ fun MessagesView(
 }
 
 @Composable
-fun ReinviteDialog(state: MessagesState) {
+private fun ReinviteDialog(state: MessagesState) {
     if (state.showReinvitePrompt) {
         ConfirmationDialog(
             title = stringResource(id = R.string.screen_room_invite_again_alert_title),
             content = stringResource(id = R.string.screen_room_invite_again_alert_message),
             cancelText = stringResource(id = CommonStrings.action_cancel),
             submitText = stringResource(id = CommonStrings.action_invite),
-            emphasizeSubmitButton = true,
             onSubmitClicked = { state.eventSink(MessagesEvents.InviteDialogDismissed(InviteDialogAction.Invite)) },
             onDismiss = { state.eventSink(MessagesEvents.InviteDialogDismissed(InviteDialogAction.Cancel)) }
         )
@@ -240,11 +249,12 @@ private fun AttachmentStateView(
 }
 
 @Composable
-fun MessagesViewContent(
+private fun MessagesViewContent(
     state: MessagesState,
     onMessageClicked: (TimelineItem.Event) -> Unit,
     onUserDataClicked: (UserId) -> Unit,
     onReactionClicked: (key: String, TimelineItem.Event) -> Unit,
+    onReactionLongClicked: (key: String, TimelineItem.Event) -> Unit,
     onMoreReactionsClicked: (TimelineItem.Event) -> Unit,
     onMessageLongClicked: (TimelineItem.Event) -> Unit,
     onTimestampClicked: (TimelineItem.Event) -> Unit,
@@ -268,6 +278,7 @@ fun MessagesViewContent(
                 onUserDataClicked = onUserDataClicked,
                 onTimestampClicked = onTimestampClicked,
                 onReactionClicked = onReactionClicked,
+                onReactionLongClicked = onReactionLongClicked,
                 onMoreReactionsClicked = onMoreReactionsClicked,
                 onSwipeToReply = onSwipeToReply,
             )
@@ -288,9 +299,9 @@ fun MessagesViewContent(
 
 @OptIn(ExperimentalMaterial3Api::class)
 @Composable
-fun MessagesViewTopBar(
-    roomTitle: String,
-    roomAvatar: AvatarData,
+private fun MessagesViewTopBar(
+    roomName: String?,
+    roomAvatar: AvatarData?,
     modifier: Modifier = Modifier,
     onRoomDetailsClicked: () -> Unit = {},
     onBackPressed: () -> Unit = {},
@@ -301,17 +312,17 @@ fun MessagesViewTopBar(
             BackButton(onClick = onBackPressed)
         },
         title = {
-            Row(
-                modifier = Modifier.clickable { onRoomDetailsClicked() },
-                verticalAlignment = Alignment.CenterVertically
-            ) {
-                Avatar(roomAvatar)
-                Spacer(modifier = Modifier.width(8.dp))
-                Text(
-                    text = roomTitle,
-                    style = ElementTheme.typography.fontBodyLgMedium,
-                    maxLines = 1,
-                    overflow = TextOverflow.Ellipsis
+            val titleModifier = Modifier.clickable { onRoomDetailsClicked() }
+            if (roomName != null && roomAvatar != null) {
+                RoomAvatarAndNameRow(
+                    roomName = roomName,
+                    roomAvatar = roomAvatar,
+                    modifier = titleModifier
+                )
+            } else {
+                IconTitlePlaceholdersRowMolecule(
+                    iconSize = AvatarSize.TimelineRoom.dp,
+                    modifier = titleModifier
                 )
             }
         },
@@ -320,7 +331,28 @@ fun MessagesViewTopBar(
 }
 
 @Composable
-fun CantSendMessageBanner(
+private fun RoomAvatarAndNameRow(
+    roomName: String,
+    roomAvatar: AvatarData,
+    modifier: Modifier = Modifier
+) {
+    Row(
+        modifier = modifier,
+        verticalAlignment = Alignment.CenterVertically
+    ) {
+        Avatar(roomAvatar)
+        Spacer(modifier = Modifier.width(8.dp))
+        Text(
+            text = roomName,
+            style = ElementTheme.typography.fontBodyLgMedium,
+            maxLines = 1,
+            overflow = TextOverflow.Ellipsis
+        )
+    }
+}
+
+@Composable
+private fun CantSendMessageBanner(
     modifier: Modifier = Modifier,
 ) {
     Row(
diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/actionlist/ActionListEvents.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/actionlist/ActionListEvents.kt
index a6244a72e3..3c796036e7 100644
--- a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/actionlist/ActionListEvents.kt
+++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/actionlist/ActionListEvents.kt
@@ -20,5 +20,5 @@ import io.element.android.features.messages.impl.timeline.model.TimelineItem
 
 sealed interface ActionListEvents {
     object Clear : ActionListEvents
-    data class ComputeForMessage(val event: TimelineItem.Event) : ActionListEvents
+    data class ComputeForMessage(val event: TimelineItem.Event, val canRedact: Boolean) : ActionListEvents
 }
diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/actionlist/ActionListPresenter.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/actionlist/ActionListPresenter.kt
index 56e9f48dde..f71c750c22 100644
--- a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/actionlist/ActionListPresenter.kt
+++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/actionlist/ActionListPresenter.kt
@@ -28,9 +28,9 @@ import io.element.android.features.messages.impl.timeline.model.TimelineItem
 import io.element.android.features.messages.impl.timeline.model.event.TimelineItemRedactedContent
 import io.element.android.features.messages.impl.timeline.model.event.TimelineItemStateContent
 import io.element.android.features.messages.impl.timeline.model.event.canBeCopied
+import io.element.android.features.messages.impl.timeline.model.event.canReact
 import io.element.android.libraries.architecture.Presenter
 import io.element.android.libraries.core.meta.BuildMeta
-import io.element.android.libraries.matrix.api.timeline.item.event.LocalEventSendState
 import kotlinx.collections.immutable.toImmutableList
 import kotlinx.coroutines.CoroutineScope
 import kotlinx.coroutines.launch
@@ -49,13 +49,20 @@ class ActionListPresenter @Inject constructor(
         }
 
         val displayEmojiReactions by remember {
-            derivedStateOf { (target.value as? ActionListState.Target.Success)?.event?.isRemote == true }
+            derivedStateOf {
+                val event = (target.value as? ActionListState.Target.Success)?.event
+                event?.isRemote == true && event.content.canReact()
+            }
         }
 
         fun handleEvents(event: ActionListEvents) {
             when (event) {
                 ActionListEvents.Clear -> target.value = ActionListState.Target.None
-                is ActionListEvents.ComputeForMessage -> localCoroutineScope.computeForMessage(event.event, target)
+                is ActionListEvents.ComputeForMessage -> localCoroutineScope.computeForMessage(
+                    timelineItem = event.event,
+                    userCanRedact = event.canRedact,
+                    target = target,
+                )
             }
         }
 
@@ -66,7 +73,11 @@ class ActionListPresenter @Inject constructor(
         )
     }
 
-    private fun CoroutineScope.computeForMessage(timelineItem: TimelineItem.Event, target: MutableState) = launch {
+    private fun CoroutineScope.computeForMessage(
+        timelineItem: TimelineItem.Event,
+        userCanRedact: Boolean,
+        target: MutableState
+    ) = launch {
         target.value = ActionListState.Target.Loading(timelineItem)
         val actions =
             when (timelineItem.content) {
@@ -103,7 +114,7 @@ class ActionListPresenter @Inject constructor(
                     if (!timelineItem.isMine) {
                         add(TimelineItemAction.ReportContent)
                     }
-                    if (timelineItem.isMine) {
+                    if (timelineItem.isMine || userCanRedact) {
                         add(TimelineItemAction.Redact)
                     }
                 }
diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/actionlist/ActionListView.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/actionlist/ActionListView.kt
index fd2ad94345..4838d2fdbf 100644
--- a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/actionlist/ActionListView.kt
+++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/actionlist/ActionListView.kt
@@ -31,6 +31,7 @@ import androidx.compose.foundation.layout.size
 import androidx.compose.foundation.layout.width
 import androidx.compose.foundation.lazy.LazyColumn
 import androidx.compose.foundation.lazy.items
+import androidx.compose.foundation.shape.CircleShape
 import androidx.compose.foundation.shape.RoundedCornerShape
 import androidx.compose.material.ExperimentalMaterialApi
 import androidx.compose.material.ListItem
@@ -61,6 +62,7 @@ import io.element.android.features.messages.impl.timeline.model.event.TimelineIt
 import io.element.android.features.messages.impl.timeline.model.event.TimelineItemFileContent
 import io.element.android.features.messages.impl.timeline.model.event.TimelineItemImageContent
 import io.element.android.features.messages.impl.timeline.model.event.TimelineItemLocationContent
+import io.element.android.features.messages.impl.timeline.model.event.TimelineItemPollContent
 import io.element.android.features.messages.impl.timeline.model.event.TimelineItemRedactedContent
 import io.element.android.features.messages.impl.timeline.model.event.TimelineItemStateContent
 import io.element.android.features.messages.impl.timeline.model.event.TimelineItemTextBasedContent
@@ -235,6 +237,7 @@ private fun MessageSummary(event: TimelineItem.Event, modifier: Modifier = Modif
     val textContent = remember(event.content) { formatter.format(event) }
 
     when (event.content) {
+        is TimelineItemPollContent, // TODO Polls: handle summary
         is TimelineItemTextBasedContent,
         is TimelineItemStateContent,
         is TimelineItemEncryptedContent,
@@ -342,7 +345,7 @@ internal fun EmojiReactionsRow(
 ) {
     Row(
         horizontalArrangement = Arrangement.SpaceBetween,
-        modifier = modifier.padding(horizontal = 28.dp, vertical = 16.dp)
+        modifier = modifier.padding(horizontal = 24.dp, vertical = 16.dp)
     ) {
         // TODO use most recently used emojis here when available from the Rust SDK
         val defaultEmojis = sequenceOf(
@@ -352,21 +355,25 @@ internal fun EmojiReactionsRow(
             val isHighlighted = highlightedEmojis.contains(emoji)
             EmojiButton(emoji, isHighlighted, onEmojiReactionClicked)
         }
-
-        Icon(
-            imageVector = Icons.Outlined.AddReaction,
-            contentDescription = "Emojis",
-            tint = MaterialTheme.colorScheme.secondary,
+        Box(
             modifier = Modifier
-                .size(24.dp)
-                .align(Alignment.CenterVertically)
-                .clickable(
-                    enabled = true,
-                    onClick = onCustomReactionClicked,
-                    indication = rememberRipple(bounded = false, radius = emojiRippleRadius),
-                    interactionSource = remember { MutableInteractionSource() }
-                )
-        )
+                .size(48.dp),
+            contentAlignment = Alignment.Center
+        ) {
+            Icon(
+                imageVector = Icons.Outlined.AddReaction,
+                contentDescription = "Emojis",
+                tint = MaterialTheme.colorScheme.secondary,
+                modifier = Modifier
+                    .size(24.dp)
+                    .clickable(
+                        enabled = true,
+                        onClick = onCustomReactionClicked,
+                        indication = rememberRipple(bounded = false, radius = emojiRippleRadius),
+                        interactionSource = remember { MutableInteractionSource() }
+                    )
+            )
+        }
     }
 }
 
@@ -385,12 +392,13 @@ private fun EmojiButton(
     Box(
         modifier = modifier
             .size(48.dp)
-            .background(backgroundColor, RoundedCornerShape(24.dp)),
+            .background(backgroundColor, CircleShape),
+
         contentAlignment = Alignment.Center
     ) {
         Text(
             emoji,
-            fontSize = 28.dp.toSp(),
+            fontSize = 24.dp.toSp(),
             color = Color.White,
             modifier = Modifier
                 .clickable(
@@ -405,7 +413,7 @@ private fun EmojiButton(
 
 @DayNightPreviews
 @Composable
-fun SheetContentPreview(
+internal fun SheetContentPreview(
     @PreviewParameter(ActionListStateProvider::class) state: ActionListState
 ) = ElementPreview {
     SheetContent(
diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/attachments/preview/AttachmentsPreviewStateProvider.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/attachments/preview/AttachmentsPreviewStateProvider.kt
index ee41ace4b0..de7f5cd47b 100644
--- a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/attachments/preview/AttachmentsPreviewStateProvider.kt
+++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/attachments/preview/AttachmentsPreviewStateProvider.kt
@@ -30,7 +30,7 @@ open class AttachmentsPreviewStateProvider : PreviewParameterProvider> by remember { mutableStateOf(SearchBarResultState.NotSearching()) }
         val forwardingActionState: MutableState>> = remember { mutableStateOf(Async.Uninitialized) }
 
-        val summaries by client.roomSummaryDataSource.allRooms().collectAsState()
+        val summaries by client.roomListService.allRooms().summaries.collectAsState()
 
         LaunchedEffect(query, summaries) {
             val filteredSummaries = summaries.filterIsInstance()
diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/forward/ForwardMessagesState.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/forward/ForwardMessagesState.kt
index 7540766097..953a7897f6 100644
--- a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/forward/ForwardMessagesState.kt
+++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/forward/ForwardMessagesState.kt
@@ -18,7 +18,7 @@ package io.element.android.features.messages.impl.forward
 
 import io.element.android.libraries.designsystem.theme.components.SearchBarResultState
 import io.element.android.libraries.matrix.api.core.RoomId
-import io.element.android.libraries.matrix.api.room.RoomSummaryDetails
+import io.element.android.libraries.matrix.api.roomlist.RoomSummaryDetails
 import kotlinx.collections.immutable.ImmutableList
 
 data class ForwardMessagesState(
diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/forward/ForwardMessagesStateProvider.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/forward/ForwardMessagesStateProvider.kt
index 75aacea616..56d7f63eb1 100644
--- a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/forward/ForwardMessagesStateProvider.kt
+++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/forward/ForwardMessagesStateProvider.kt
@@ -20,7 +20,7 @@ import androidx.compose.ui.tooling.preview.PreviewParameterProvider
 import io.element.android.libraries.designsystem.theme.components.SearchBarResultState
 import io.element.android.libraries.matrix.api.core.RoomId
 import io.element.android.libraries.matrix.api.room.RoomMember
-import io.element.android.libraries.matrix.api.room.RoomSummaryDetails
+import io.element.android.libraries.matrix.api.roomlist.RoomSummaryDetails
 import io.element.android.libraries.matrix.api.room.message.RoomMessage
 import kotlinx.collections.immutable.ImmutableList
 import kotlinx.collections.immutable.persistentListOf
diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/forward/ForwardMessagesView.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/forward/ForwardMessagesView.kt
index 230965312e..0f00a6f090 100644
--- a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/forward/ForwardMessagesView.kt
+++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/forward/ForwardMessagesView.kt
@@ -63,7 +63,7 @@ import io.element.android.libraries.designsystem.theme.components.TopAppBar
 import io.element.android.libraries.designsystem.theme.roomListRoomMessage
 import io.element.android.libraries.designsystem.theme.roomListRoomName
 import io.element.android.libraries.matrix.api.core.RoomId
-import io.element.android.libraries.matrix.api.room.RoomSummaryDetails
+import io.element.android.libraries.matrix.api.roomlist.RoomSummaryDetails
 import io.element.android.libraries.matrix.ui.components.SelectedRoom
 import io.element.android.libraries.theme.ElementTheme
 import io.element.android.libraries.ui.strings.CommonStrings
@@ -82,6 +82,7 @@ fun ForwardMessagesView(
         return
     }
 
+    @Suppress("UNUSED_PARAMETER")
     fun onRoomRemoved(roomSummaryDetails: RoomSummaryDetails) {
         // TODO toggle selection when multi-selection is enabled
         state.eventSink(ForwardMessagesEvents.RemoveSelectedRoom)
@@ -122,11 +123,10 @@ fun ForwardMessagesView(
                 },
                 actions = {
                     TextButton(
+                        text = stringResource(CommonStrings.action_send),
                         enabled = state.selectedRooms.isNotEmpty(),
                         onClick = { state.eventSink(ForwardMessagesEvents.ForwardEvent) }
-                    ) {
-                        Text(text = stringResource(CommonStrings.action_send))
-                    }
+                    )
                 }
             )
         }
@@ -282,12 +282,12 @@ private fun ForwardingErrorDialog(onDismiss: () -> Unit, modifier: Modifier = Mo
 
 @Preview
 @Composable
-fun ForwardMessagesViewLightPreview(@PreviewParameter(ForwardMessagesStateProvider::class) state: ForwardMessagesState) =
+internal fun ForwardMessagesViewLightPreview(@PreviewParameter(ForwardMessagesStateProvider::class) state: ForwardMessagesState) =
     ElementPreviewLight { ContentToPreview(state) }
 
 @Preview
 @Composable
-fun ForwardMessagesViewDarkPreview(@PreviewParameter(ForwardMessagesStateProvider::class) state: ForwardMessagesState) =
+internal fun ForwardMessagesViewDarkPreview(@PreviewParameter(ForwardMessagesStateProvider::class) state: ForwardMessagesState) =
     ElementPreviewDark { ContentToPreview(state) }
 
 @Composable
diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/media/viewer/MediaViewerPresenter.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/media/viewer/MediaViewerPresenter.kt
index 7cc73ef32e..13a9ff3bee 100644
--- a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/media/viewer/MediaViewerPresenter.kt
+++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/media/viewer/MediaViewerPresenter.kt
@@ -103,14 +103,17 @@ class MediaViewerPresenter @AssistedInject constructor(
         )
             .onSuccess {
                 mediaFile.value = it
-            }.mapCatching { mediaFile ->
+            }
+            .mapCatching { mediaFile ->
                 localMediaFactory.createFromMediaFile(
                     mediaFile = mediaFile,
                     mediaInfo = inputs.mediaInfo
                 )
-            }.onSuccess {
+            }
+            .onSuccess {
                 localMedia.value = Async.Success(it)
-            }.onFailure {
+            }
+            .onFailure {
                 localMedia.value = Async.Failure(it)
             }
     }
diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/media/viewer/MediaViewerStateProvider.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/media/viewer/MediaViewerStateProvider.kt
index 820a34d8d4..1042261be8 100644
--- a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/media/viewer/MediaViewerStateProvider.kt
+++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/media/viewer/MediaViewerStateProvider.kt
@@ -32,7 +32,7 @@ open class MediaViewerStateProvider : PreviewParameterProvider
         get() = sequenceOf(
             aMediaViewerState(),
             aMediaViewerState(Async.Loading()),
-            aMediaViewerState(Async.Failure(IllegalStateException())),
+            aMediaViewerState(Async.Failure(IllegalStateException("error"))),
             aMediaViewerState(
                 Async.Success(
                     LocalMedia(Uri.EMPTY, anImageInfo())
diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/media/viewer/MediaViewerView.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/media/viewer/MediaViewerView.kt
index 5964c2ced7..66f15225f7 100644
--- a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/media/viewer/MediaViewerView.kt
+++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/media/viewer/MediaViewerView.kt
@@ -34,9 +34,6 @@ import androidx.compose.material.icons.filled.OpenInNew
 import androidx.compose.material.icons.filled.Share
 import androidx.compose.material3.ExperimentalMaterial3Api
 import androidx.compose.material3.LinearProgressIndicator
-import androidx.compose.material3.MaterialTheme
-import androidx.compose.material3.Snackbar
-import androidx.compose.material3.SnackbarHost
 import androidx.compose.runtime.Composable
 import androidx.compose.runtime.LaunchedEffect
 import androidx.compose.runtime.getValue
@@ -57,7 +54,6 @@ import io.element.android.features.messages.impl.media.local.LocalMediaView
 import io.element.android.features.messages.impl.media.local.MediaInfo
 import io.element.android.features.messages.impl.media.local.rememberLocalMediaViewState
 import io.element.android.libraries.architecture.Async
-import io.element.android.libraries.core.mimetype.MimeTypes
 import io.element.android.libraries.designsystem.components.button.BackButton
 import io.element.android.libraries.designsystem.components.dialogs.RetryDialog
 import io.element.android.libraries.designsystem.preview.ElementPreviewDark
@@ -65,6 +61,7 @@ import io.element.android.libraries.designsystem.theme.components.Icon
 import io.element.android.libraries.designsystem.theme.components.IconButton
 import io.element.android.libraries.designsystem.theme.components.Scaffold
 import io.element.android.libraries.designsystem.theme.components.TopAppBar
+import io.element.android.libraries.designsystem.utils.SnackbarHost
 import io.element.android.libraries.designsystem.utils.rememberSnackbarHostState
 import io.element.android.libraries.matrix.api.media.MediaSource
 import io.element.android.libraries.matrix.ui.media.MediaRequestData
@@ -100,15 +97,7 @@ fun MediaViewerView(
                 eventSink = state.eventSink
             )
         },
-        snackbarHost = {
-            SnackbarHost(snackbarHostState) { data ->
-                Snackbar(
-                    snackbarData = data,
-                    containerColor = MaterialTheme.colorScheme.surfaceVariant,
-                    contentColor = MaterialTheme.colorScheme.primary
-                )
-            }
-        },
+        snackbarHost = { SnackbarHost(snackbarHostState) },
     ) {
         Column(
             modifier = Modifier
@@ -256,7 +245,7 @@ private fun ErrorView(
 
 @Preview
 @Composable
-fun MediaViewerViewDarkPreview(@PreviewParameter(MediaViewerStateProvider::class) state: MediaViewerState) =
+internal fun MediaViewerViewDarkPreview(@PreviewParameter(MediaViewerStateProvider::class) state: MediaViewerState) =
     ElementPreviewDark { ContentToPreview(state) }
 
 @Composable
diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/messagecomposer/AttachmentsBottomSheet.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/messagecomposer/AttachmentsBottomSheet.kt
index c8324ec677..b554ef98f4 100644
--- a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/messagecomposer/AttachmentsBottomSheet.kt
+++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/messagecomposer/AttachmentsBottomSheet.kt
@@ -83,7 +83,7 @@ internal fun AttachmentsBottomSheet(
             onDismissRequest = { isVisible = false }
         ) {
             AttachmentSourcePickerMenu(
-                eventSink = state.eventSink,
+                state = state,
                 onSendLocationClicked = onSendLocationClicked,
             )
         }
@@ -93,7 +93,7 @@ internal fun AttachmentsBottomSheet(
 @OptIn(ExperimentalMaterialApi::class)
 @Composable
 internal fun AttachmentSourcePickerMenu(
-    eventSink: (MessageComposerEvents) -> Unit,
+    state: MessageComposerState,
     onSendLocationClicked: () -> Unit,
     modifier: Modifier = Modifier,
 ) {
@@ -102,33 +102,35 @@ internal fun AttachmentSourcePickerMenu(
 //        .navigationBarsPadding() - FIXME after https://issuetracker.google.com/issues/275849044
     ) {
         ListItem(
-            modifier = Modifier.clickable { eventSink(MessageComposerEvents.PickAttachmentSource.FromGallery) },
+            modifier = Modifier.clickable { state.eventSink(MessageComposerEvents.PickAttachmentSource.FromGallery) },
             icon = { Icon(Icons.Default.Collections, null) },
             text = { Text(stringResource(R.string.screen_room_attachment_source_gallery)) },
         )
         ListItem(
-            modifier = Modifier.clickable { eventSink(MessageComposerEvents.PickAttachmentSource.FromFiles) },
+            modifier = Modifier.clickable { state.eventSink(MessageComposerEvents.PickAttachmentSource.FromFiles) },
             icon = { Icon(Icons.Default.AttachFile, null) },
             text = { Text(stringResource(R.string.screen_room_attachment_source_files)) },
         )
         ListItem(
-            modifier = Modifier.clickable { eventSink(MessageComposerEvents.PickAttachmentSource.PhotoFromCamera) },
+            modifier = Modifier.clickable { state.eventSink(MessageComposerEvents.PickAttachmentSource.PhotoFromCamera) },
             icon = { Icon(Icons.Default.PhotoCamera, null) },
             text = { Text(stringResource(R.string.screen_room_attachment_source_camera_photo)) },
         )
         ListItem(
-            modifier = Modifier.clickable { eventSink(MessageComposerEvents.PickAttachmentSource.VideoFromCamera) },
+            modifier = Modifier.clickable { state.eventSink(MessageComposerEvents.PickAttachmentSource.VideoFromCamera) },
             icon = { Icon(Icons.Default.Videocam, null) },
             text = { Text(stringResource(R.string.screen_room_attachment_source_camera_video)) },
         )
-        ListItem(
-            modifier = Modifier.clickable {
-                eventSink(MessageComposerEvents.PickAttachmentSource.Location)
-                onSendLocationClicked()
-            },
-            icon = { Icon(Icons.Default.LocationOn, null) },
-            text = { Text(stringResource(R.string.screen_room_attachment_source_location)) },
-        )
+        if (state.canShareLocation) {
+            ListItem(
+                modifier = Modifier.clickable {
+                    state.eventSink(MessageComposerEvents.PickAttachmentSource.Location)
+                    onSendLocationClicked()
+                },
+                icon = { Icon(Icons.Default.LocationOn, null) },
+                text = { Text(stringResource(R.string.screen_room_attachment_source_location)) },
+            )
+        }
     }
 }
 
@@ -136,7 +138,9 @@ internal fun AttachmentSourcePickerMenu(
 @Composable
 internal fun AttachmentSourcePickerMenuPreview() = ElementPreview {
     AttachmentSourcePickerMenu(
-        eventSink = {},
+        state = aMessageComposerState(
+            canShareLocation = true,
+        ),
         onSendLocationClicked = {},
     )
 }
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 020236e890..934a67f2e4 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
@@ -74,6 +74,11 @@ class MessageComposerPresenter @Inject constructor(
             mutableStateOf(AttachmentsState.None)
         }
 
+        val canShareLocation = remember { mutableStateOf(false) }
+        LaunchedEffect(Unit) {
+            canShareLocation.value = featureFlagService.isFeatureEnabled(FeatureFlags.LocationSharing)
+        }
+
         val galleryMediaPicker = mediaPickerProvider.registerGalleryPicker { uri, mimeType ->
             handlePickedMedia(attachmentsState, uri, mimeType)
         }
@@ -140,23 +145,23 @@ class MessageComposerPresenter @Inject constructor(
                         )
                     )
                 }
-                MessageComposerEvents.AddAttachment -> localCoroutineScope.launchIfMediaPickerEnabled {
+                MessageComposerEvents.AddAttachment -> localCoroutineScope.launch {
                     showAttachmentSourcePicker = true
                 }
                 MessageComposerEvents.DismissAttachmentMenu -> showAttachmentSourcePicker = false
-                MessageComposerEvents.PickAttachmentSource.FromGallery -> localCoroutineScope.launchIfMediaPickerEnabled {
+                MessageComposerEvents.PickAttachmentSource.FromGallery -> localCoroutineScope.launch {
                     showAttachmentSourcePicker = false
                     galleryMediaPicker.launch()
                 }
-                MessageComposerEvents.PickAttachmentSource.FromFiles -> localCoroutineScope.launchIfMediaPickerEnabled {
+                MessageComposerEvents.PickAttachmentSource.FromFiles -> localCoroutineScope.launch {
                     showAttachmentSourcePicker = false
                     filesPicker.launch()
                 }
-                MessageComposerEvents.PickAttachmentSource.PhotoFromCamera -> localCoroutineScope.launchIfMediaPickerEnabled {
+                MessageComposerEvents.PickAttachmentSource.PhotoFromCamera -> localCoroutineScope.launch {
                     showAttachmentSourcePicker = false
                     cameraPhotoPicker.launch()
                 }
-                MessageComposerEvents.PickAttachmentSource.VideoFromCamera -> localCoroutineScope.launchIfMediaPickerEnabled {
+                MessageComposerEvents.PickAttachmentSource.VideoFromCamera -> localCoroutineScope.launch {
                     showAttachmentSourcePicker = false
                     cameraVideoPicker.launch()
                 }
@@ -173,17 +178,12 @@ class MessageComposerPresenter @Inject constructor(
             hasFocus = hasFocus.value,
             mode = messageComposerContext.composerMode,
             showAttachmentSourcePicker = showAttachmentSourcePicker,
+            canShareLocation = canShareLocation.value,
             attachmentsState = attachmentsState.value,
             eventSink = ::handleEvents
         )
     }
 
-    private fun CoroutineScope.launchIfMediaPickerEnabled(action: suspend () -> Unit) = launch {
-        if (featureFlagService.isFeatureEnabled(FeatureFlags.ShowMediaUploadingFlow)) {
-            action()
-        }
-    }
-
     private fun CoroutineScope.sendMessage(
         text: String,
         updateComposerMode: (newComposerMode: MessageComposerMode) -> Unit,
@@ -268,7 +268,8 @@ class MessageComposerPresenter @Inject constructor(
         mediaSender.sendMedia(uri, mimeType, compressIfPossible = false, progressCallback)
             .onSuccess {
                 attachmentState.value = AttachmentsState.None
-            }.onFailure {
+            }
+            .onFailure {
                 val snackbarMessage = SnackbarMessage(sendAttachmentError(it))
                 snackbarDispatcher.post(snackbarMessage)
                 attachmentState.value = AttachmentsState.None
diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/messagecomposer/MessageComposerState.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/messagecomposer/MessageComposerState.kt
index 28ec14ffeb..32faaf9d81 100644
--- a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/messagecomposer/MessageComposerState.kt
+++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/messagecomposer/MessageComposerState.kt
@@ -28,6 +28,7 @@ data class MessageComposerState(
     val hasFocus: Boolean,
     val mode: MessageComposerMode,
     val showAttachmentSourcePicker: Boolean,
+    val canShareLocation: Boolean,
     val attachmentsState: AttachmentsState,
     val eventSink: (MessageComposerEvents) -> Unit
 ) {
diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/messagecomposer/MessageComposerStateProvider.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/messagecomposer/MessageComposerStateProvider.kt
index 1934154824..a1fbb7ffa0 100644
--- a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/messagecomposer/MessageComposerStateProvider.kt
+++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/messagecomposer/MessageComposerStateProvider.kt
@@ -26,12 +26,21 @@ open class MessageComposerStateProvider : PreviewParameterProvider
                 val key = emojis[index % emojis.size]
-                add(AggregatedReaction(key = key, count = 1 + index, isHighlighted = isHighlighted))
+                add(anAggregatedReaction(
+                    key = key,
+                    count = index + 1,
+                    isHighlighted = isHighlighted
+                ))
             }
         }.toPersistentList()
     )
diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/TimelineView.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/TimelineView.kt
index d7820e707b..6e16a3b92d 100644
--- a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/TimelineView.kt
+++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/TimelineView.kt
@@ -81,6 +81,7 @@ fun TimelineView(
     onTimestampClicked: (TimelineItem.Event) -> Unit,
     onSwipeToReply: (TimelineItem.Event) -> Unit,
     onReactionClicked: (emoji: String, TimelineItem.Event) -> Unit,
+    onReactionLongClicked: (emoji: String, TimelineItem.Event) -> Unit,
     onMoreReactionsClicked: (TimelineItem.Event) -> Unit,
     modifier: Modifier = Modifier,
 ) {
@@ -94,6 +95,7 @@ fun TimelineView(
 
     val lazyListState = rememberLazyListState()
 
+    @Suppress("UNUSED_PARAMETER")
     fun inReplyToClicked(eventId: EventId) {
         // TODO implement this logic once we have support to 'jump to event X' in sliding sync
     }
@@ -120,6 +122,7 @@ fun TimelineView(
                     onUserDataClick = onUserDataClicked,
                     inReplyToClick = ::inReplyToClicked,
                     onReactionClick = onReactionClicked,
+                    onReactionLongClick = onReactionLongClicked,
                     onMoreReactionsClick = onMoreReactionsClicked,
                     onTimestampClicked = onTimestampClicked,
                     onSwipeToReply = onSwipeToReply,
@@ -137,6 +140,7 @@ fun TimelineView(
         }
 
         TimelineScrollHelper(
+            isTimelineEmpty = state.timelineItems.isEmpty(),
             lazyListState = lazyListState,
             hasNewItems = state.hasNewItems,
             onScrollFinishedAt = ::onScrollFinishedAt
@@ -154,6 +158,7 @@ fun TimelineItemRow(
     onLongClick: (TimelineItem.Event) -> Unit,
     inReplyToClick: (EventId) -> Unit,
     onReactionClick: (key: String, TimelineItem.Event) -> Unit,
+    onReactionLongClick: (key: String, TimelineItem.Event) -> Unit,
     onMoreReactionsClick: (TimelineItem.Event) -> Unit,
     onTimestampClicked: (TimelineItem.Event) -> Unit,
     onSwipeToReply: (TimelineItem.Event) -> Unit,
@@ -185,6 +190,7 @@ fun TimelineItemRow(
                     onUserDataClick = onUserDataClick,
                     inReplyToClick = inReplyToClick,
                     onReactionClick = onReactionClick,
+                    onReactionLongClick = onReactionLongClick,
                     onMoreReactionsClick = onMoreReactionsClick,
                     onTimestampClicked = onTimestampClicked,
                     onSwipeToReply = { onSwipeToReply(timelineItem) },
@@ -223,6 +229,7 @@ fun TimelineItemRow(
                                 onUserDataClick = onUserDataClick,
                                 onTimestampClicked = onTimestampClicked,
                                 onReactionClick = onReactionClick,
+                                onReactionLongClick = onReactionLongClick,
                                 onMoreReactionsClick = onMoreReactionsClick,
                                 onSwipeToReply = {},
                             )
@@ -236,6 +243,7 @@ fun TimelineItemRow(
 
 @Composable
 private fun BoxScope.TimelineScrollHelper(
+    isTimelineEmpty: Boolean,
     lazyListState: LazyListState,
     hasNewItems: Boolean,
     onScrollFinishedAt: (Int) -> Unit,
@@ -253,8 +261,8 @@ private fun BoxScope.TimelineScrollHelper(
         }
     }
 
-    LaunchedEffect(isScrollFinished) {
-        if (isScrollFinished) {
+    LaunchedEffect(isScrollFinished, isTimelineEmpty) {
+        if (isScrollFinished && !isTimelineEmpty) {
             // Notify the parent composable about the first visible item index when scrolling finishes
             onScrollFinishedAt(lazyListState.firstVisibleItemIndex)
         }
@@ -309,7 +317,7 @@ private fun JumpToBottomButton(
 
 @DayNightPreviews
 @Composable
-fun TimelineViewPreview(
+internal fun TimelineViewPreview(
     @PreviewParameter(TimelineItemEventContentProvider::class) content: TimelineItemEventContent
 ) = ElementPreview {
     val timelineItems = aTimelineItemList(content)
@@ -320,6 +328,7 @@ fun TimelineViewPreview(
         onUserDataClicked = {},
         onMessageLongClicked = {},
         onReactionClicked = { _, _ -> },
+        onReactionLongClicked = { _, _ -> },
         onMoreReactionsClicked = {},
         onSwipeToReply = {},
     )
diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/EmojiPicker.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/EmojiPicker.kt
index 182965a4e5..effd7f23f0 100644
--- a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/EmojiPicker.kt
+++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/EmojiPicker.kt
@@ -17,6 +17,7 @@
 package io.element.android.features.messages.impl.timeline.components
 
 import androidx.compose.foundation.ExperimentalFoundationApi
+import androidx.compose.foundation.background
 import androidx.compose.foundation.clickable
 import androidx.compose.foundation.interaction.MutableInteractionSource
 import androidx.compose.foundation.layout.Arrangement
@@ -31,6 +32,7 @@ import androidx.compose.foundation.lazy.grid.LazyVerticalGrid
 import androidx.compose.foundation.lazy.grid.items
 import androidx.compose.foundation.pager.HorizontalPager
 import androidx.compose.foundation.pager.rememberPagerState
+import androidx.compose.foundation.shape.CircleShape
 import androidx.compose.material.ripple.rememberRipple
 import androidx.compose.material3.Tab
 import androidx.compose.material3.TabRow
@@ -39,9 +41,9 @@ import androidx.compose.runtime.remember
 import androidx.compose.runtime.rememberCoroutineScope
 import androidx.compose.ui.Alignment
 import androidx.compose.ui.Modifier
+import androidx.compose.ui.graphics.Color
 import androidx.compose.ui.tooling.preview.Preview
 import androidx.compose.ui.unit.dp
-import androidx.compose.ui.unit.sp
 import com.vanniktech.emoji.Emoji
 import com.vanniktech.emoji.google.GoogleEmojiProvider
 import io.element.android.libraries.designsystem.preview.ElementPreviewDark
@@ -49,12 +51,15 @@ import io.element.android.libraries.designsystem.preview.ElementPreviewLight
 import io.element.android.libraries.designsystem.theme.components.Icon
 import io.element.android.libraries.designsystem.theme.components.Text
 import io.element.android.libraries.theme.ElementTheme
+import kotlinx.collections.immutable.ImmutableSet
+import kotlinx.collections.immutable.persistentSetOf
 import kotlinx.coroutines.launch
 
 @OptIn(ExperimentalFoundationApi::class)
 @Composable
 fun EmojiPicker(
     onEmojiSelected: (Emoji) -> Unit,
+    selectedEmojis: ImmutableSet,
     modifier: Modifier = Modifier,
 ) {
     val coroutineScope = rememberCoroutineScope()
@@ -62,7 +67,7 @@ fun EmojiPicker(
     val emojiProvider = remember { GoogleEmojiProvider() }
     val categories = remember { emojiProvider.categories }
     val pagerState = rememberPagerState()
-    Column (modifier) {
+    Column(modifier) {
         TabRow(
             selectedTabIndex = pagerState.currentPage,
         ) {
@@ -92,12 +97,19 @@ fun EmojiPicker(
                 modifier = Modifier.fillMaxSize(),
                 columns = GridCells.Adaptive(minSize = 40.dp),
                 contentPadding = PaddingValues(vertical = 10.dp, horizontal = 16.dp),
-                horizontalArrangement = Arrangement.SpaceEvenly,
+                horizontalArrangement = Arrangement.spacedBy(8.dp),
             ) {
                 items(category.emojis, key = { it.unicode }) { item ->
+                    val backgroundColor = if (selectedEmojis.contains(item.unicode)) {
+                        ElementTheme.colors.bgActionPrimaryRest
+                    } else {
+                        Color.Transparent
+                    }
+
                     Box(
                         modifier = Modifier
                             .size(40.dp)
+                            .background(backgroundColor, CircleShape)
                             .clickable(
                                 enabled = true,
                                 onClick = { onEmojiSelected(item) },
@@ -109,7 +121,8 @@ fun EmojiPicker(
                         Text(
                             text = item.unicode,
                             style = ElementTheme.typography.fontHeadingSmRegular,
-                        )                    }
+                        )
+                    }
                 }
             }
         }
@@ -132,6 +145,7 @@ internal fun EmojiPickerDarkPreview() {
 private fun ContentToPreview() {
     EmojiPicker(
         onEmojiSelected = {},
-        modifier = Modifier.fillMaxWidth()
+        modifier = Modifier.fillMaxWidth(),
+        selectedEmojis = persistentSetOf("😀", "😄", "😃")
     )
 }
diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/MessageEventBubble.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/MessageEventBubble.kt
index 932dce913c..446846db83 100644
--- a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/MessageEventBubble.kt
+++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/MessageEventBubble.kt
@@ -35,7 +35,6 @@ import androidx.compose.ui.graphics.Shape
 import androidx.compose.ui.tooling.preview.Preview
 import androidx.compose.ui.tooling.preview.PreviewParameter
 import androidx.compose.ui.unit.dp
-import androidx.compose.ui.unit.sp
 import io.element.android.features.messages.impl.timeline.model.TimelineItemGroupPosition
 import io.element.android.features.messages.impl.timeline.model.bubble.BubbleState
 import io.element.android.features.messages.impl.timeline.model.bubble.BubbleStateProvider
diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/MessageStateEventContainer.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/MessageStateEventContainer.kt
index 4bb66f0eac..69c73a68e1 100644
--- a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/MessageStateEventContainer.kt
+++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/MessageStateEventContainer.kt
@@ -33,7 +33,6 @@ import androidx.compose.ui.tooling.preview.Preview
 import androidx.compose.ui.unit.dp
 import io.element.android.libraries.designsystem.preview.ElementPreviewDark
 import io.element.android.libraries.designsystem.preview.ElementPreviewLight
-import io.element.android.libraries.theme.ElementTheme
 import io.element.android.libraries.designsystem.theme.components.Surface
 
 private val CORNER_RADIUS = 8.dp
diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/MessagesReactionButton.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/MessagesReactionButton.kt
index 8d2eb06f99..930adf36cd 100644
--- a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/MessagesReactionButton.kt
+++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/MessagesReactionButton.kt
@@ -17,9 +17,10 @@
 package io.element.android.features.messages.impl.timeline.components
 
 import androidx.compose.foundation.BorderStroke
+import androidx.compose.foundation.ExperimentalFoundationApi
 import androidx.compose.foundation.background
 import androidx.compose.foundation.border
-import androidx.compose.foundation.clickable
+import androidx.compose.foundation.combinedClickable
 import androidx.compose.foundation.layout.Row
 import androidx.compose.foundation.layout.Spacer
 import androidx.compose.foundation.layout.height
@@ -54,8 +55,10 @@ import io.element.android.libraries.designsystem.theme.components.Text
 import io.element.android.libraries.theme.ElementTheme
 
 @Composable
+@OptIn(ExperimentalFoundationApi::class)
 fun MessagesReactionButton(
     onClick: () -> Unit,
+    onLongClick: () -> Unit,
     content: MessagesReactionsButtonContent,
     modifier: Modifier = Modifier,
 ) {
@@ -82,7 +85,10 @@ fun MessagesReactionButton(
             .padding(vertical = 2.dp, horizontal = 2.dp)
             // Clip click indicator inside the outer border
             .clip(RoundedCornerShape(corner = CornerSize(12.dp)))
-            .clickable(onClick = onClick)
+            .combinedClickable(
+                onClick = onClick,
+                onLongClick = onLongClick
+            )
             // Inner border, to highlight when selected
             .border(BorderStroke(1.dp, borderColor), RoundedCornerShape(corner = CornerSize(12.dp)))
             .background(buttonColor, RoundedCornerShape(corner = CornerSize(12.dp)))
@@ -107,6 +113,7 @@ sealed class MessagesReactionsButtonContent {
 }
 
 private val reactionEmojiLineHeight = 20.sp
+private val addEmojiSize = 16.dp
 
 @Composable
 private fun TextContent(
@@ -117,6 +124,7 @@ private fun TextContent(
         .height(reactionEmojiLineHeight.toDp()),
     text = text,
     style = ElementTheme.typography.fontBodyMdRegular,
+    color = ElementTheme.materialColors.primary
 )
 
 @Composable
@@ -126,9 +134,10 @@ private fun IconContent(
 ) = Icon(
     imageVector = imageVector,
     contentDescription = stringResource(id = R.string.screen_room_timeline_add_reaction),
-    tint = MaterialTheme.colorScheme.secondary,
+    tint = ElementTheme.materialColors.secondary,
     modifier = modifier
-        .size(reactionEmojiLineHeight.toDp())
+        .size(addEmojiSize)
+
 )
 
 @Composable
@@ -161,7 +170,18 @@ private fun ReactionContent(
 internal fun MessagesReactionButtonPreview(@PreviewParameter(AggregatedReactionProvider::class) reaction: AggregatedReaction) = ElementPreview {
     MessagesReactionButton(
         content = MessagesReactionsButtonContent.Reaction(reaction),
-        onClick = {}
+        onClick = {},
+        onLongClick = {}
+    )
+}
+
+@DayNightPreviews
+@Composable
+internal fun MessagesAddReactionButtonPreview() = ElementPreview {
+    MessagesReactionButton(
+        content = MessagesReactionsButtonContent.Icon(Icons.Outlined.AddReaction),
+        onClick = {},
+        onLongClick = {}
     )
 }
 
@@ -169,13 +189,10 @@ internal fun MessagesReactionButtonPreview(@PreviewParameter(AggregatedReactionP
 @Composable
 internal fun MessagesReactionExtraButtonsPreview() = ElementPreview {
     Row {
-        MessagesReactionButton(
-            content = MessagesReactionsButtonContent.Icon(Icons.Outlined.AddReaction),
-            onClick = {}
-        )
         MessagesReactionButton(
             content = MessagesReactionsButtonContent.Text("12 more"),
-            onClick = {}
+            onClick = {},
+            onLongClick = {}
         )
         MessagesReactionButton(
             content = MessagesReactionsButtonContent.Reaction(
@@ -183,7 +200,8 @@ internal fun MessagesReactionExtraButtonsPreview() = ElementPreview {
                     key = "A very long reaction with many characters that should be truncated"
                 )
             ),
-            onClick = {}
+            onClick = {},
+            onLongClick = {}
         )
     }
 }
diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/TimelineItemEventRow.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/TimelineItemEventRow.kt
index fbb745c34e..90d3e6cd8c 100644
--- a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/TimelineItemEventRow.kt
+++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/TimelineItemEventRow.kt
@@ -59,7 +59,6 @@ import androidx.compose.ui.unit.dp
 import androidx.compose.ui.zIndex
 import androidx.constraintlayout.compose.ConstrainScope
 import androidx.constraintlayout.compose.ConstraintLayout
-import com.google.accompanist.flowlayout.FlowMainAxisAlignment
 import io.element.android.features.messages.impl.timeline.aTimelineItemEvent
 import io.element.android.features.messages.impl.timeline.aTimelineItemReactions
 import io.element.android.features.messages.impl.timeline.components.event.TimelineItemEventContentView
@@ -113,6 +112,7 @@ fun TimelineItemEventRow(
     inReplyToClick: (EventId) -> Unit,
     onTimestampClicked: (TimelineItem.Event) -> Unit,
     onReactionClick: (emoji: String, eventId: TimelineItem.Event) -> Unit,
+    onReactionLongClick: (emoji: String, eventId: TimelineItem.Event) -> Unit,
     onMoreReactionsClick: (eventId: TimelineItem.Event) -> Unit,
     onSwipeToReply: () -> Unit,
     modifier: Modifier = Modifier
@@ -170,6 +170,7 @@ fun TimelineItemEventRow(
                         inReplyToClicked = ::inReplyToClicked,
                         onUserDataClicked = ::onUserDataClicked,
                         onReactionClicked = { emoji -> onReactionClick(emoji, event) },
+                        onReactionLongClicked = { emoji -> onReactionLongClick(emoji, event) },
                         onMoreReactionsClicked = { onMoreReactionsClick(event) },
                     )
                 }
@@ -185,6 +186,7 @@ fun TimelineItemEventRow(
                 inReplyToClicked = ::inReplyToClicked,
                 onUserDataClicked = ::onUserDataClicked,
                 onReactionClicked = { emoji -> onReactionClick(emoji, event) },
+                onReactionLongClicked = { emoji -> onReactionLongClick(emoji, event) },
                 onMoreReactionsClicked = { onMoreReactionsClick(event) },
             )
         }
@@ -225,6 +227,7 @@ private fun TimelineItemEventRowContent(
     inReplyToClicked: () -> Unit,
     onUserDataClicked: () -> Unit,
     onReactionClicked: (emoji: String) -> Unit,
+    onReactionLongClicked: (emoji: String) -> Unit,
     onMoreReactionsClicked: (event: TimelineItem.Event) -> Unit,
     modifier: Modifier = Modifier,
 ) {
@@ -291,8 +294,9 @@ private fun TimelineItemEventRowContent(
         if (event.reactionsState.reactions.isNotEmpty()) {
             TimelineItemReactions(
                 reactionsState = event.reactionsState,
-                mainAxisAlignment = if (event.isMine) FlowMainAxisAlignment.End else FlowMainAxisAlignment.Start,
+                isOutgoing = event.isMine,
                 onReactionClicked = onReactionClicked,
+                onReactionLongClicked = onReactionLongClicked,
                 onMoreReactionsClicked = { onMoreReactionsClicked(event) },
                 modifier = Modifier
                     .constrainAs(reactions) {
@@ -480,7 +484,7 @@ private fun ReplyToContent(
     val paddings = if (attachmentThumbnailInfo != null) {
         PaddingValues(start = 4.dp, end = 12.dp, top = 4.dp, bottom = 4.dp)
     } else {
-        PaddingValues(start = 12.dp, end = 12.dp, top = 8.dp, bottom = 4.dp)
+        PaddingValues(horizontal = 12.dp, vertical = 4.dp)
     }
     Row(
         modifier
@@ -518,42 +522,46 @@ private fun ReplyToContent(
     }
 }
 
-private fun attachmentThumbnailInfoForInReplyTo(inReplyTo: InReplyTo.Ready) =
-    when (val type = inReplyTo.content.type) {
+private fun attachmentThumbnailInfoForInReplyTo(inReplyTo: InReplyTo.Ready): AttachmentThumbnailInfo? {
+    val messageContent = inReplyTo.content as? MessageContent ?: return null
+    return when (val type = messageContent.type) {
         is ImageMessageType -> AttachmentThumbnailInfo(
             thumbnailSource = type.info?.thumbnailSource,
-            textContent = inReplyTo.content.body,
+            textContent = messageContent.body,
             type = AttachmentThumbnailType.Image,
             blurHash = type.info?.blurhash,
         )
         is VideoMessageType -> AttachmentThumbnailInfo(
             thumbnailSource = type.info?.thumbnailSource,
-            textContent = inReplyTo.content.body,
+            textContent = messageContent.body,
             type = AttachmentThumbnailType.Video,
             blurHash = type.info?.blurhash,
         )
         is FileMessageType -> AttachmentThumbnailInfo(
             thumbnailSource = type.info?.thumbnailSource,
-            textContent = inReplyTo.content.body,
+            textContent = messageContent.body,
             type = AttachmentThumbnailType.File,
         )
         is LocationMessageType -> AttachmentThumbnailInfo(
-            textContent = inReplyTo.content.body,
+            textContent = messageContent.body,
             type = AttachmentThumbnailType.Location,
         )
         is AudioMessageType -> AttachmentThumbnailInfo(
-            textContent = inReplyTo.content.body,
+            textContent = messageContent.body,
             type = AttachmentThumbnailType.Audio,
         )
         else -> null
     }
+}
 
 @Composable
-private fun textForInReplyTo(inReplyTo: InReplyTo.Ready) =
-    when (inReplyTo.content.type) {
+private fun textForInReplyTo(inReplyTo: InReplyTo.Ready): String {
+    val messageContent = inReplyTo.content as? MessageContent ?: return ""
+    return when (messageContent.type) {
         is LocationMessageType -> stringResource(CommonStrings.common_shared_location)
-        else -> inReplyTo.content.body
+        else -> messageContent.body
     }
+}
 
 @Preview
 @Composable
@@ -585,6 +593,7 @@ private fun ContentToPreview() {
                 onUserDataClick = {},
                 inReplyToClick = {},
                 onReactionClick = { _, _ -> },
+                onReactionLongClick = { _, _ -> },
                 onMoreReactionsClick = {},
                 onTimestampClicked = {},
                 onSwipeToReply = {},
@@ -604,6 +613,7 @@ private fun ContentToPreview() {
                 onUserDataClick = {},
                 inReplyToClick = {},
                 onReactionClick = { _, _ -> },
+                onReactionLongClick = { _, _ -> },
                 onMoreReactionsClick = {},
                 onTimestampClicked = {},
                 onSwipeToReply = {},
@@ -650,6 +660,7 @@ private fun ContentToPreviewWithReply() {
                 onUserDataClick = {},
                 inReplyToClick = {},
                 onReactionClick = { _, _ -> },
+                onReactionLongClick = { _, _ -> },
                 onMoreReactionsClick = {},
                 onTimestampClicked = {},
                 onSwipeToReply = {},
@@ -670,6 +681,7 @@ private fun ContentToPreviewWithReply() {
                 onUserDataClick = {},
                 inReplyToClick = {},
                 onReactionClick = { _, _ -> },
+                onReactionLongClick = { _, _ -> },
                 onMoreReactionsClick = {},
                 onTimestampClicked = {},
                 onSwipeToReply = {},
@@ -726,6 +738,7 @@ private fun ContentTimestampToPreview(event: TimelineItem.Event) {
                     onUserDataClick = {},
                     inReplyToClick = {},
                     onReactionClick = { _, _ -> },
+                    onReactionLongClick = { _, _ -> },
                     onMoreReactionsClick = {},
                     onTimestampClicked = {},
                     onSwipeToReply = {},
@@ -765,6 +778,7 @@ private fun ContentWithManyReactionsToPreview() {
                 onUserDataClick = {},
                 inReplyToClick = {},
                 onReactionClick = { _, _ -> },
+                onReactionLongClick = { _, _ -> },
                 onMoreReactionsClick = {},
                 onSwipeToReply = {},
                 onTimestampClicked = {},
diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/TimelineItemReactionsLayout.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/TimelineItemReactionsLayout.kt
new file mode 100644
index 0000000000..01800f6348
--- /dev/null
+++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/TimelineItemReactionsLayout.kt
@@ -0,0 +1,217 @@
+/*
+ * Copyright (c) 2023 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
+ *
+ *     http://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.features.messages.impl.timeline.components
+
+import androidx.compose.material.icons.Icons
+import androidx.compose.material.icons.outlined.AddReaction
+import androidx.compose.runtime.Composable
+import androidx.compose.ui.Modifier
+import androidx.compose.ui.layout.MeasureResult
+import androidx.compose.ui.layout.Placeable
+import androidx.compose.ui.layout.SubcomposeLayout
+import androidx.compose.ui.res.stringResource
+import androidx.compose.ui.unit.Dp
+import androidx.compose.ui.unit.IntOffset
+import androidx.compose.ui.unit.dp
+import io.element.android.features.messages.impl.R
+import io.element.android.libraries.designsystem.preview.DayNightPreviews
+import io.element.android.libraries.designsystem.preview.ElementPreview
+
+/**
+ * A flow layout for reactions that will show a collapse/expand button when the layout wraps over a defined number of rows.
+ * It displays an add more button when there are greater than 0 reactions and always displays the reaction and add more button
+ * on the same row (moving them both to a new row if necessary).
+ * @param expandButton The expand button
+ * @param addMoreButton The add more button
+ * @param modifier The modifier to apply to this layout
+ * @param itemSpacing The horizontal spacing between items
+ * @param rowSpacing The vertical spacing between rows
+ * @param expanded Whether the layout should display in expanded or collapsed state
+ * @param rowsBeforeCollapsible The number of rows before the collapse/expand button is shown
+ * @param reactions The reaction buttons
+ */
+@Composable
+fun TimelineItemReactionsLayout(
+    expandButton: @Composable () -> Unit,
+    addMoreButton: @Composable () -> Unit,
+    modifier: Modifier = Modifier,
+    itemSpacing: Dp = 0.dp,
+    rowSpacing: Dp = 0.dp,
+    expanded: Boolean = false,
+    rowsBeforeCollapsible: Int? = 2,
+    reactions: @Composable () -> Unit,
+) {
+    SubcomposeLayout(modifier) { constraints ->
+        // Given the placeables and returns a structure representing
+        // how they should wrap on to multiple rows given the constraints max width.
+        fun calculateRows(placeables: List): List> {
+            val rows = mutableListOf>()
+            var currentRow = mutableListOf()
+            var rowX = 0
+
+            placeables.forEach { placeable ->
+                val horizontalSpacing = if (currentRow.isEmpty()) 0 else itemSpacing.toPx().toInt()
+                // If the current view does not fit on this row bump to the next
+                if (rowX + placeable.width > constraints.maxWidth) {
+                    rows.add(currentRow)
+                    currentRow = mutableListOf()
+                    rowX = 0
+                }
+                rowX += horizontalSpacing + placeable.width
+                currentRow.add(placeable)
+            }
+            // If there are items in the current row remember to append it to the returned value
+            if (currentRow.size > 0) {
+                rows.add(currentRow)
+            }
+            return rows
+        }
+
+        // Used to render the collapsed state, this takes the rows inputted and adds the extra button to the last row,
+        // removing only as many trailing reactions as needed to make space for it.
+        fun replaceTrailingItemsWithButtons(rowsIn: List>, expandButton: Placeable, addMoreButton: Placeable): List> {
+            val rows = rowsIn.toMutableList()
+            val lastRow = rows.last()
+            val buttonsWidth = expandButton.width + itemSpacing.toPx().toInt() + addMoreButton.width
+            var rowX = 0
+            lastRow.forEachIndexed { i, placeable ->
+                val horizontalSpacing = if (i == 0) 0 else itemSpacing.toPx().toInt()
+                rowX += placeable.width + horizontalSpacing
+                if (rowX > constraints.maxWidth - (buttonsWidth + horizontalSpacing)) {
+                    val lastRowWithButton = lastRow.take(i) + listOf(expandButton, addMoreButton)
+                    rows[rows.size - 1] = lastRowWithButton
+                    return rows
+                }
+            }
+            val lastRowWithButton = lastRow + listOf(expandButton, addMoreButton)
+            rows[rows.size - 1] = lastRowWithButton
+            return rows
+        }
+
+        // To prevent the add more and expand buttons from wrapping on to separate lines.
+        // If there is one item on the last line, it moves the expand button down.
+        fun ensureCollapseAndAddMoreButtonsAreOnTheSameRow(rowsIn: List>): List> {
+            val lastRow = rowsIn.last().toMutableList()
+            if (lastRow.size != 1) {
+                return rowsIn
+            }
+            val rows = rowsIn.toMutableList()
+            val secondLastRow = rows[rows.size - 2].toMutableList()
+            val expandButtonPlaceable = secondLastRow.removeLast()
+            lastRow.add(0, expandButtonPlaceable)
+            rows[rows.size - 2] = secondLastRow
+            rows[rows.size - 1] = lastRow
+            return rows
+        }
+
+        /// Given a list of rows place them in the layout.
+        fun layoutRows(rows: List>): MeasureResult {
+            var width = 0
+            var height = 0
+            val placeables = rows.mapIndexed { i, row ->
+                var rowX = 0
+                var rowHeight = 0
+                val verticalSpacing = if (i == 0) 0 else rowSpacing.toPx().toInt()
+                val rowWithPoints = row.mapIndexed { j, placeable ->
+                    val horizontalSpacing = if (j == 0) 0 else itemSpacing.toPx().toInt()
+                    val point = IntOffset(rowX + horizontalSpacing, height + verticalSpacing)
+                    rowX += placeable.width + horizontalSpacing
+                    rowHeight = maxOf(rowHeight, placeable.height)
+                    Pair(placeable, point)
+                }
+                height += rowHeight + verticalSpacing
+                width = maxOf(width, rowX)
+                rowWithPoints
+            }.flatten()
+
+            return layout(width = width, height = height) {
+                placeables.forEach {
+                    val (placeable, origin) = it
+                    placeable.placeRelative(origin.x, origin.y)
+                }
+            }
+        }
+
+        var reactionsPlaceables = subcompose(0, reactions).map { it.measure(constraints) }
+        if (reactionsPlaceables.isEmpty()) {
+            return@SubcomposeLayout layoutRows(listOf())
+        }
+        var expandPlaceable = subcompose(1, expandButton).first().measure(constraints)
+        // Enforce all reaction buttons have the same height
+        val maxHeight = (reactionsPlaceables + listOf(expandPlaceable)).maxOf { it.height }
+        val newConstrains = constraints.copy(minHeight = maxHeight)
+        reactionsPlaceables = subcompose(2, reactions).map { it.measure(newConstrains) }
+        expandPlaceable = subcompose(3, expandButton).first().measure(newConstrains)
+        val addMorePlaceable = subcompose(4, addMoreButton).first().measure(newConstrains)
+
+
+        // Calculate the layout of the rows with the reactions button and add more button
+        val reactionsAndAddMore = calculateRows(reactionsPlaceables + listOf(addMorePlaceable))
+        // If we have extended beyond the defined number of rows we are showing the expand/collapse ui
+        if (rowsBeforeCollapsible?.let { reactionsAndAddMore.size > it } == true) {
+            if (expanded) {
+                // Show all subviews with the add more button at the end
+                var reactionsAndButtons = calculateRows(reactionsPlaceables + listOf(expandPlaceable, addMorePlaceable))
+                reactionsAndButtons = ensureCollapseAndAddMoreButtonsAreOnTheSameRow(reactionsAndButtons)
+                layoutRows(reactionsAndButtons)
+            } else {
+                // Truncate to `rowsBeforeCollapsible` number of rows and replace the reactions at the end of the last row with the buttons
+                val collapsedRows = reactionsAndAddMore.take(rowsBeforeCollapsible)
+                val collapsedRowsWithButtons = replaceTrailingItemsWithButtons(collapsedRows, expandPlaceable, addMorePlaceable)
+                layoutRows(collapsedRowsWithButtons)
+            }
+        } else {
+            // Otherwise we are just showing all items without the expand button
+            layoutRows(reactionsAndAddMore)
+        }
+    }
+}
+
+@DayNightPreviews
+@Composable
+internal fun TimelineItemReactionsLayoutPreview() = ElementPreview {
+    TimelineItemReactionsLayout(
+        expanded = false,
+        expandButton = {
+            MessagesReactionButton(
+                content = MessagesReactionsButtonContent.Text(
+                    text = stringResource(id = R.string.screen_room_timeline_less_reactions)
+                ),
+                onClick = {},
+                onLongClick = {}
+            )
+        },
+        addMoreButton = {
+            MessagesReactionButton(
+                content = MessagesReactionsButtonContent.Icon(Icons.Outlined.AddReaction),
+                onClick = {},
+                onLongClick = {}
+            )
+        },
+        reactions = {
+            io.element.android.features.messages.impl.timeline.aTimelineItemReactions(count = 18).reactions.forEach {
+                MessagesReactionButton(
+                    content = MessagesReactionsButtonContent.Reaction(
+                        it
+                    ),
+                    onClick = {},
+                    onLongClick = {}
+                )
+            }
+        }
+    )
+}
diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/TimelineItemReactionsView.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/TimelineItemReactionsView.kt
index ca0a58da70..a5cdf4b6cc 100644
--- a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/TimelineItemReactionsView.kt
+++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/TimelineItemReactionsView.kt
@@ -19,18 +19,16 @@ package io.element.android.features.messages.impl.timeline.components
 import androidx.compose.material.icons.Icons
 import androidx.compose.material.icons.outlined.AddReaction
 import androidx.compose.runtime.Composable
-import androidx.compose.runtime.derivedStateOf
+import androidx.compose.runtime.CompositionLocalProvider
 import androidx.compose.runtime.getValue
 import androidx.compose.runtime.mutableStateOf
-import androidx.compose.runtime.remember
 import androidx.compose.runtime.saveable.rememberSaveable
 import androidx.compose.runtime.setValue
 import androidx.compose.ui.Modifier
-import androidx.compose.ui.res.pluralStringResource
+import androidx.compose.ui.platform.LocalLayoutDirection
 import androidx.compose.ui.res.stringResource
+import androidx.compose.ui.unit.LayoutDirection
 import androidx.compose.ui.unit.dp
-import com.google.accompanist.flowlayout.FlowMainAxisAlignment
-import com.google.accompanist.flowlayout.FlowRow
 import io.element.android.features.messages.impl.R
 import io.element.android.features.messages.impl.timeline.aTimelineItemReactions
 import io.element.android.features.messages.impl.timeline.model.AggregatedReaction
@@ -38,162 +36,132 @@ import io.element.android.features.messages.impl.timeline.model.TimelineItemReac
 import io.element.android.libraries.designsystem.preview.DayNightPreviews
 import io.element.android.libraries.designsystem.preview.ElementPreview
 import kotlinx.collections.immutable.ImmutableList
-import kotlinx.collections.immutable.toPersistentList
-
-/**
- * The maximum number of items that can be displayed before some items will be hidden
- *
- * TODO The threshold should be based on the number of rows, rather than items.
- *       Once items would spill onto a third row, they should be hidden.
- *       Note this could be particularly worthwhile to handle reactions that are
- *       longer than a single character (as annotation keys are free text).
- */
-private const val COLLAPSE_ITEMS_THRESHOLD = 8
 
 @Composable
 fun TimelineItemReactions(
     reactionsState: TimelineItemReactions,
-    mainAxisAlignment: FlowMainAxisAlignment,
+    isOutgoing: Boolean,
     onReactionClicked: (emoji: String) -> Unit,
+    onReactionLongClicked: (emoji: String) -> Unit,
     onMoreReactionsClicked: () -> Unit,
     modifier: Modifier = Modifier,
 ) {
     var expanded: Boolean by rememberSaveable { mutableStateOf(false) }
-
-    val reactions by remember(reactionsState, expanded) {
-        derivedStateOf {
-            val numToDisplay = if (expanded) {
-                reactionsState.reactions.count()
-            } else {
-                COLLAPSE_ITEMS_THRESHOLD
-            }
-            reactionsState.reactions.take(numToDisplay).toPersistentList()
-        }
-    }
-
-    val expandableState by remember {
-        derivedStateOf {
-            if (expanded) {
-                ExpandableState.Expanded
-            } else {
-                val hiddenItems = reactionsState.reactions.count() - reactions.count()
-                if (hiddenItems > 0) {
-                    ExpandableState.Collapsed(hidden = hiddenItems)
-                } else {
-                    ExpandableState.None
-                }
-            }
-        }
-    }
-
-    TimelineItemReactionsView(
-        modifier = modifier,
-        reactions = reactions,
-        expandableState = expandableState,
-        mainAxisAlignment = mainAxisAlignment,
-        onReactionClick = onReactionClicked,
-        onMoreReactionsClick = onMoreReactionsClicked,
-        onExpandClick = { expanded = true },
-        onCollapseClick = { expanded = false }
-    )
-}
-
-private sealed class ExpandableState {
-    object None: ExpandableState()
-    data class Collapsed(val hidden: Int): ExpandableState()
-    object Expanded : ExpandableState()
+        TimelineItemReactionsView(
+            modifier = modifier,
+            reactions = reactionsState.reactions,
+            expanded = expanded,
+            isOutgoing = isOutgoing,
+            onReactionClick = onReactionClicked,
+            onReactionLongClick = onReactionLongClicked,
+            onMoreReactionsClick = onMoreReactionsClicked,
+            onToggleExpandClick = { expanded = !expanded },
+        )
 }
 
 @Composable
 private fun TimelineItemReactionsView(
     reactions: ImmutableList,
-    expandableState: ExpandableState,
-    mainAxisAlignment: FlowMainAxisAlignment,
+    isOutgoing: Boolean,
+    expanded: Boolean,
     onReactionClick: (emoji: String) -> Unit,
+    onReactionLongClick: (emoji: String) -> Unit,
     onMoreReactionsClick: () -> Unit,
-    onExpandClick: () -> Unit,
-    onCollapseClick: () -> Unit,
+    onToggleExpandClick: () -> Unit,
     modifier: Modifier = Modifier
-) =
-    FlowRow(
-        modifier = modifier,
-        mainAxisSpacing = 4.dp,
-        crossAxisSpacing = 4.dp,
-        mainAxisAlignment = mainAxisAlignment,
-    ) {
-        reactions.forEach { reaction ->
-            MessagesReactionButton(
-                content = MessagesReactionsButtonContent.Reaction(reaction = reaction),
-                onClick = { onReactionClick(reaction.key) }
-            )
-        }
-        when (expandableState) {
-            ExpandableState.Expanded ->
+) {
+    // In LTR languages we want an incoming message's reactions to be LRT and outgoing to be RTL.
+    // For RTL languages it should be the opposite.
+    val currentLayout = LocalLayoutDirection.current
+    val reactionsLayoutDirection = if (!isOutgoing) currentLayout
+    else if (currentLayout == LayoutDirection.Ltr)
+        LayoutDirection.Rtl
+    else
+        LayoutDirection.Ltr
+
+    return CompositionLocalProvider(LocalLayoutDirection provides reactionsLayoutDirection) {
+        TimelineItemReactionsLayout(
+            modifier = modifier,
+            itemSpacing = 4.dp,
+            rowSpacing = 4.dp,
+            expanded = expanded,
+            expandButton = {
                 MessagesReactionButton(
                     content = MessagesReactionsButtonContent.Text(
-                        text = stringResource(id = R.string.screen_room_timeline_less_reactions)
+                        text = stringResource(id = if (expanded) R.string.screen_room_reactions_show_less else R.string.screen_room_reactions_show_more)
                     ),
-                    onClick = onCollapseClick,
+                    onClick = onToggleExpandClick,
+                    onLongClick = {}
                 )
-            is ExpandableState.Collapsed -> {
-                val hidden = expandableState.hidden
+            },
+            addMoreButton = {
                 MessagesReactionButton(
-                    content = MessagesReactionsButtonContent.Text(
-                        text = pluralStringResource(id = R.plurals.screen_room_timeline_more_reactions, hidden, hidden)
-                    ),
-                    onClick = onExpandClick,
+                    content = MessagesReactionsButtonContent.Icon(Icons.Outlined.AddReaction),
+                    onClick = onMoreReactionsClick,
+                    onLongClick = {}
                 )
+            },
+            reactions = {
+                reactions.forEach { reaction ->
+                    CompositionLocalProvider(LocalLayoutDirection provides currentLayout) {
+                        MessagesReactionButton(
+                            content = MessagesReactionsButtonContent.Reaction(reaction = reaction),
+                            onClick = { onReactionClick(reaction.key) },
+                            onLongClick = { onReactionLongClick(reaction.key) }
+                        )
+                    }
+                }
             }
-            ExpandableState.None -> {
-                // No expand or collapse action available
-            }
-        }
-        MessagesReactionButton(
-            content = MessagesReactionsButtonContent.Icon(Icons.Outlined.AddReaction),
-            onClick = onMoreReactionsClick
         )
     }
+}
 
 @DayNightPreviews
 @Composable
-fun TimelineItemReactionsViewPreview() = ElementPreview {
+internal fun TimelineItemReactionsViewPreview() = ElementPreview {
     ContentToPreview(
-        reactions = aTimelineItemReactions(count = 1).reactions,
-        expandableState = ExpandableState.None,
+        reactions = aTimelineItemReactions(count = 1).reactions
     )
 }
 
 @DayNightPreviews
 @Composable
-fun TimelineItemReactionsViewCollapsedPreview() = ElementPreview {
+internal fun TimelineItemReactionsViewFewPreview() = ElementPreview {
     ContentToPreview(
-        reactions = aTimelineItemReactions(count = 3).reactions,
-        expandableState = ExpandableState.Collapsed(hidden = 7),
+        reactions = aTimelineItemReactions(count = 3).reactions
     )
 }
 
 @DayNightPreviews
 @Composable
-fun TimelineItemReactionsViewExpandedPreview() = ElementPreview {
+internal fun TimelineItemReactionsViewIncomingPreview() = ElementPreview {
     ContentToPreview(
-        reactions = aTimelineItemReactions(count = 10).reactions,
-        expandableState = ExpandableState.Expanded,
+        reactions = aTimelineItemReactions(count = 18).reactions
+    )
+}
+
+@DayNightPreviews
+@Composable
+internal fun TimelineItemReactionsViewOutgoingPreview() = ElementPreview {
+    ContentToPreview(
+        reactions = aTimelineItemReactions(count = 18).reactions,
+        isOutgoing = true
     )
 }
 
 @Composable
 private fun ContentToPreview(
     reactions: ImmutableList,
-    expandableState: ExpandableState
+    isOutgoing: Boolean = false
 ) {
-    TimelineItemReactionsView(
-        reactions = reactions,
-        expandableState = expandableState,
-        mainAxisAlignment = FlowMainAxisAlignment.Center,
-        onReactionClick = {},
-        onMoreReactionsClick = {},
-        onExpandClick = {},
-        onCollapseClick = {}
+    TimelineItemReactions(
+        reactionsState = TimelineItemReactions(
+            reactions
+        ),
+        isOutgoing = isOutgoing,
+        onReactionClicked = {},
+        onReactionLongClicked = {},
+        onMoreReactionsClicked = {},
     )
 }
 
diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/customreaction/CustomReactionBottomSheet.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/customreaction/CustomReactionBottomSheet.kt
index 70c2a7dc10..d817ec0cd4 100644
--- a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/customreaction/CustomReactionBottomSheet.kt
+++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/customreaction/CustomReactionBottomSheet.kt
@@ -57,7 +57,8 @@ fun CustomReactionBottomSheet(
         ) {
             EmojiPicker(
                 onEmojiSelected = ::onEmojiSelectedDismiss,
-                modifier = Modifier.fillMaxSize()
+                modifier = Modifier.fillMaxSize(),
+                selectedEmojis = state.selectedEmoji,
             )
         }
     }
diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/customreaction/CustomReactionEvents.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/customreaction/CustomReactionEvents.kt
index b7c210553e..a0d69df372 100644
--- a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/customreaction/CustomReactionEvents.kt
+++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/customreaction/CustomReactionEvents.kt
@@ -16,8 +16,8 @@
 
 package io.element.android.features.messages.impl.timeline.components.customreaction
 
-import io.element.android.libraries.matrix.api.core.EventId
+import io.element.android.features.messages.impl.timeline.model.TimelineItem
 
 sealed interface CustomReactionEvents {
-    data class UpdateSelectedEvent(val eventId: EventId?) : CustomReactionEvents
+    data class UpdateSelectedEvent(val event: TimelineItem.Event?) : CustomReactionEvents
 }
diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/customreaction/CustomReactionPresenter.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/customreaction/CustomReactionPresenter.kt
index 0a23d42085..f094f2dbc6 100644
--- a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/customreaction/CustomReactionPresenter.kt
+++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/customreaction/CustomReactionPresenter.kt
@@ -21,22 +21,24 @@ import androidx.compose.runtime.getValue
 import androidx.compose.runtime.mutableStateOf
 import androidx.compose.runtime.remember
 import androidx.compose.runtime.setValue
+import io.element.android.features.messages.impl.timeline.model.TimelineItem
 import io.element.android.libraries.architecture.Presenter
-import io.element.android.libraries.matrix.api.core.EventId
+import kotlinx.collections.immutable.toImmutableSet
 import javax.inject.Inject
 
 class CustomReactionPresenter @Inject constructor() : Presenter {
 
     @Composable
     override fun present(): CustomReactionState {
-        var selectedEventId by remember { mutableStateOf(null) }
+        var selectedEvent by remember { mutableStateOf(null) }
 
         fun handleEvents(event: CustomReactionEvents) {
             when (event) {
-                is CustomReactionEvents.UpdateSelectedEvent -> selectedEventId = event.eventId
+                is CustomReactionEvents.UpdateSelectedEvent -> selectedEvent = event.event
             }
         }
 
-        return CustomReactionState(selectedEventId = selectedEventId, eventSink = ::handleEvents)
+        val selectedEmoji = selectedEvent?.reactionsState?.reactions?.mapNotNull { if(it.isHighlighted) it.key else null }.orEmpty().toImmutableSet()
+        return CustomReactionState(selectedEventId = selectedEvent?.eventId, selectedEmoji = selectedEmoji, eventSink = ::handleEvents)
     }
 }
diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/customreaction/CustomReactionState.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/customreaction/CustomReactionState.kt
index 6c0c7f3599..9de1642dff 100644
--- a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/customreaction/CustomReactionState.kt
+++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/customreaction/CustomReactionState.kt
@@ -17,8 +17,10 @@
 package io.element.android.features.messages.impl.timeline.components.customreaction
 
 import io.element.android.libraries.matrix.api.core.EventId
+import kotlinx.collections.immutable.ImmutableSet
 
 data class CustomReactionState(
     val selectedEventId: EventId?,
+    val selectedEmoji: ImmutableSet,
     val eventSink: (CustomReactionEvents) -> Unit,
 )
diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/event/ExtraPadding.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/event/ExtraPadding.kt
index d941b8a814..65101183d9 100644
--- a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/event/ExtraPadding.kt
+++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/event/ExtraPadding.kt
@@ -65,7 +65,7 @@ fun TimelineItem.Event.toExtraPadding(): ExtraPadding {
 fun ExtraPadding.getStr(fontSize: TextUnit): String {
     if (nbChars == 0) return ""
     val timestampFontSize = ElementTheme.typography.fontBodyXsRegular.fontSize // 11.sp
-    val nbOfSpaces = ((timestampFontSize.value / fontSize.value) * nbChars).toInt() + 1
+    val nbOfSpaces = (timestampFontSize.value / fontSize.value * nbChars).toInt() + 1
     // A space and some unbreakable spaces
     return " " + "\u00A0".repeat(nbOfSpaces)
 }
diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/event/TimelineItemContentView.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/event/TimelineItemContentView.kt
index 3df45eb760..d53e3f1e5b 100644
--- a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/event/TimelineItemContentView.kt
+++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/event/TimelineItemContentView.kt
@@ -25,6 +25,7 @@ import io.element.android.features.messages.impl.timeline.model.event.TimelineIt
 import io.element.android.features.messages.impl.timeline.model.event.TimelineItemFileContent
 import io.element.android.features.messages.impl.timeline.model.event.TimelineItemImageContent
 import io.element.android.features.messages.impl.timeline.model.event.TimelineItemLocationContent
+import io.element.android.features.messages.impl.timeline.model.event.TimelineItemPollContent
 import io.element.android.features.messages.impl.timeline.model.event.TimelineItemRedactedContent
 import io.element.android.features.messages.impl.timeline.model.event.TimelineItemStateContent
 import io.element.android.features.messages.impl.timeline.model.event.TimelineItemTextBasedContent
@@ -90,5 +91,10 @@ fun TimelineItemEventContentView(
             content = content,
             modifier = modifier
         )
+        is TimelineItemPollContent -> TimelineItemPollView(
+            content = content,
+            onAnswerSelected = {},
+            modifier = modifier,
+        )
     }
 }
diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/event/TimelineItemEncryptedView.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/event/TimelineItemEncryptedView.kt
index 9755377b39..cf481a0aec 100644
--- a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/event/TimelineItemEncryptedView.kt
+++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/event/TimelineItemEncryptedView.kt
@@ -30,7 +30,7 @@ import io.element.android.libraries.ui.strings.CommonStrings
 
 @Composable
 fun TimelineItemEncryptedView(
-    content: TimelineItemEncryptedContent,
+    @Suppress("UNUSED_PARAMETER") content: TimelineItemEncryptedContent,
     extraPadding: ExtraPadding,
     modifier: Modifier = Modifier
 ) {
diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/event/TimelineItemPollView.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/event/TimelineItemPollView.kt
new file mode 100644
index 0000000000..db3503be37
--- /dev/null
+++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/event/TimelineItemPollView.kt
@@ -0,0 +1,53 @@
+/*
+ * Copyright (c) 2023 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
+ *
+ *     http://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.features.messages.impl.timeline.components.event
+
+import androidx.compose.runtime.Composable
+import androidx.compose.ui.Modifier
+import androidx.compose.ui.tooling.preview.PreviewParameter
+import io.element.android.features.messages.impl.timeline.model.event.TimelineItemPollContent
+import io.element.android.features.messages.impl.timeline.model.event.TimelineItemPollContentProvider
+import io.element.android.features.poll.api.ActivePollContentView
+import io.element.android.libraries.designsystem.preview.DayNightPreviews
+import io.element.android.libraries.designsystem.preview.ElementPreview
+import io.element.android.libraries.matrix.api.poll.PollAnswer
+import kotlinx.collections.immutable.toImmutableList
+
+@Composable
+fun TimelineItemPollView(
+    content: TimelineItemPollContent,
+    onAnswerSelected: (PollAnswer) -> Unit,
+    modifier: Modifier = Modifier,
+) {
+    ActivePollContentView(
+        question = content.question,
+        answerItems = content.answerItems.toImmutableList(),
+        pollKind = content.pollKind,
+        onAnswerSelected = onAnswerSelected,
+        modifier = modifier,
+    )
+}
+
+@DayNightPreviews
+@Composable
+internal fun TimelineItemPollViewPreview(@PreviewParameter(TimelineItemPollContentProvider::class) content: TimelineItemPollContent) =
+    ElementPreview {
+        TimelineItemPollView(
+            content = content,
+            onAnswerSelected = {},
+        )
+    }
diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/event/TimelineItemRedactedView.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/event/TimelineItemRedactedView.kt
index 44917c7d5b..749151b55f 100644
--- a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/event/TimelineItemRedactedView.kt
+++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/event/TimelineItemRedactedView.kt
@@ -29,7 +29,7 @@ import io.element.android.libraries.ui.strings.CommonStrings
 
 @Composable
 fun TimelineItemRedactedView(
-    content: TimelineItemRedactedContent,
+    @Suppress("UNUSED_PARAMETER") content: TimelineItemRedactedContent,
     extraPadding: ExtraPadding,
     modifier: Modifier = Modifier
 ) {
diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/event/TimelineItemUnknownView.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/event/TimelineItemUnknownView.kt
index 852428cb92..f053c5a6a0 100644
--- a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/event/TimelineItemUnknownView.kt
+++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/event/TimelineItemUnknownView.kt
@@ -29,7 +29,7 @@ import io.element.android.libraries.ui.strings.CommonStrings
 
 @Composable
 fun TimelineItemUnknownView(
-    content: TimelineItemUnknownContent,
+    @Suppress("UNUSED_PARAMETER") content: TimelineItemUnknownContent,
     extraPadding: ExtraPadding,
     modifier: Modifier = Modifier
 ) {
diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/event/TimelineItemVideoView.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/event/TimelineItemVideoView.kt
index aeb2e7145e..8f8d767835 100644
--- a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/event/TimelineItemVideoView.kt
+++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/event/TimelineItemVideoView.kt
@@ -18,7 +18,6 @@ package io.element.android.features.messages.impl.timeline.components.event
 
 import androidx.compose.foundation.Image
 import androidx.compose.foundation.layout.Box
-import androidx.compose.foundation.layout.fillMaxSize
 import androidx.compose.material.icons.Icons
 import androidx.compose.material.icons.filled.PlayArrow
 import androidx.compose.runtime.Composable
diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/group/GroupHeaderView.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/group/GroupHeaderView.kt
index b2d5dbc7f6..ce853b84b5 100644
--- a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/group/GroupHeaderView.kt
+++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/group/GroupHeaderView.kt
@@ -35,7 +35,6 @@ import androidx.compose.ui.draw.clip
 import androidx.compose.ui.graphics.Color
 import androidx.compose.ui.tooling.preview.Preview
 import androidx.compose.ui.unit.dp
-import androidx.compose.ui.unit.sp
 import io.element.android.libraries.designsystem.preview.ElementPreviewDark
 import io.element.android.libraries.designsystem.preview.ElementPreviewLight
 import io.element.android.libraries.designsystem.theme.components.Icon
@@ -92,12 +91,12 @@ fun GroupHeaderView(
 
 @Preview
 @Composable
-fun GroupHeaderViewLightPreview() =
+internal fun GroupHeaderViewLightPreview() =
     ElementPreviewLight { ContentToPreview() }
 
 @Preview
 @Composable
-fun GroupHeaderViewDarkPreview() =
+internal fun GroupHeaderViewDarkPreview() =
     ElementPreviewDark { ContentToPreview() }
 
 @Composable
diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/html/HtmlDocument.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/html/HtmlDocument.kt
index cb0264cf5d..ecb81a4367 100644
--- a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/html/HtmlDocument.kt
+++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/html/HtmlDocument.kt
@@ -61,7 +61,7 @@ import org.jsoup.nodes.Element
 import org.jsoup.nodes.Node
 import org.jsoup.nodes.TextNode
 
-private const val chipId = "chip"
+private const val CHIP_ID = "chip"
 
 @Composable
 fun HtmlDocument(
@@ -351,7 +351,7 @@ private fun HtmlMxReply(
     Surface(
         modifier = modifier
             .padding(bottom = 4.dp)
-            .offset(x = -(8.dp)),
+            .offset(x = (-8).dp),
         color = MaterialTheme.colorScheme.background,
         shape = shape,
     ) {
@@ -544,17 +544,27 @@ private fun AnnotatedString.Builder.appendLink(link: Element) {
             pop()
         }
         is PermalinkData.RoomEmailInviteLink -> {
-            appendInlineContent(chipId, link.ownText())
+            safeAppendInlineContent(CHIP_ID, link.ownText())
         }
         is PermalinkData.RoomLink -> {
-            appendInlineContent(chipId, link.ownText())
+            safeAppendInlineContent(CHIP_ID, link.ownText())
         }
         is PermalinkData.UserLink -> {
-            appendInlineContent(chipId, link.ownText())
+            safeAppendInlineContent(CHIP_ID, link.ownText())
         }
     }
 }
 
+fun AnnotatedString.Builder.safeAppendInlineContent(chipId: String, ownText: String) {
+    if (ownText.isEmpty()) {
+        // alternateText cannot be empty and default parameter value is private,
+        // so just omit the second param here.
+        appendInlineContent(chipId)
+    } else {
+        appendInlineContent(chipId, ownText)
+    }
+}
+
 @Composable
 private fun HtmlText(
     text: AnnotatedString,
diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/reactionsummary/ReactionSummaryEvents.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/reactionsummary/ReactionSummaryEvents.kt
new file mode 100644
index 0000000000..fdf94f52ce
--- /dev/null
+++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/reactionsummary/ReactionSummaryEvents.kt
@@ -0,0 +1,25 @@
+/*
+ * Copyright (c) 2023 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
+ *
+ *     http://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.features.messages.impl.timeline.components.reactionsummary
+
+import io.element.android.features.messages.impl.timeline.model.AggregatedReaction
+import io.element.android.libraries.matrix.api.core.EventId
+
+sealed interface ReactionSummaryEvents {
+    object Clear : ReactionSummaryEvents
+    data class ShowReactionSummary(val eventId: EventId, val reactions: List, val selectedKey: String) : ReactionSummaryEvents
+}
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
new file mode 100644
index 0000000000..456ac5f548
--- /dev/null
+++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/reactionsummary/ReactionSummaryPresenter.kt
@@ -0,0 +1,87 @@
+/*
+ * Copyright (c) 2023 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
+ *
+ *     http://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.features.messages.impl.timeline.components.reactionsummary
+
+import androidx.compose.runtime.Composable
+import androidx.compose.runtime.LaunchedEffect
+import androidx.compose.runtime.MutableState
+import androidx.compose.runtime.collectAsState
+import androidx.compose.runtime.derivedStateOf
+import androidx.compose.runtime.getValue
+import androidx.compose.runtime.mutableStateOf
+import androidx.compose.runtime.remember
+import io.element.android.libraries.architecture.Presenter
+import io.element.android.libraries.matrix.api.room.MatrixRoom
+import io.element.android.libraries.matrix.api.room.RoomMember
+import io.element.android.libraries.matrix.api.room.roomMembers
+import io.element.android.libraries.matrix.api.user.MatrixUser
+import kotlinx.collections.immutable.ImmutableList
+import kotlinx.collections.immutable.toImmutableList
+import javax.inject.Inject
+
+class ReactionSummaryPresenter @Inject constructor(
+    private val room: MatrixRoom,
+) : Presenter {
+    @Composable
+    override fun present(): ReactionSummaryState {
+        LaunchedEffect(Unit) {
+            room.updateMembers()
+        }
+
+        val membersState by room.membersStateFlow.collectAsState()
+
+        val target: MutableState = remember {
+            mutableStateOf(null)
+        }
+        val targetWithAvatars = populateSenderAvatars(members = membersState.roomMembers().orEmpty().toImmutableList(), summary = target.value)
+
+        fun handleEvents(event: ReactionSummaryEvents) {
+            when (event) {
+                is ReactionSummaryEvents.ShowReactionSummary -> target.value = ReactionSummaryState.Summary(
+                    reactions = event.reactions,
+                    selectedKey = event.selectedKey,
+                    selectedEventId = event.eventId
+                )
+                ReactionSummaryEvents.Clear -> target.value = null
+            }
+        }
+        return ReactionSummaryState(
+            target = targetWithAvatars.value,
+            eventSink = ::handleEvents
+        )
+    }
+
+    @Composable
+    private fun populateSenderAvatars(members: ImmutableList, summary: ReactionSummaryState.Summary?) = remember(summary) {
+        derivedStateOf {
+            summary?.let { summary ->
+                summary.copy(reactions = summary.reactions.map { reaction ->
+                     reaction.copy(senders = reaction.senders.map { sender ->
+                         val member = members.firstOrNull { it.userId == sender.senderId }
+                         val user = MatrixUser(
+                             userId = sender.senderId,
+                             displayName = member?.displayName,
+                             avatarUrl = member?.avatarUrl
+                         )
+                         sender.copy(user = user)
+                     })
+                })
+            }
+        }
+    }
+
+}
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
new file mode 100644
index 0000000000..37e150320b
--- /dev/null
+++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/reactionsummary/ReactionSummaryState.kt
@@ -0,0 +1,32 @@
+/*
+ * Copyright (c) 2023 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
+ *
+ *     http://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.features.messages.impl.timeline.components.reactionsummary
+
+import io.element.android.features.messages.impl.timeline.model.AggregatedReaction
+import io.element.android.libraries.matrix.api.core.EventId
+
+data class ReactionSummaryState(
+    val target: Summary?,
+    val eventSink: (ReactionSummaryEvents) -> Unit
+){
+    data class Summary(
+        val reactions: List,
+        val selectedKey: String,
+        val selectedEventId: EventId
+    )
+}
+
diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/reactionsummary/ReactionSummaryStateProvider.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/reactionsummary/ReactionSummaryStateProvider.kt
new file mode 100644
index 0000000000..d6642922bb
--- /dev/null
+++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/reactionsummary/ReactionSummaryStateProvider.kt
@@ -0,0 +1,37 @@
+/*
+ * Copyright (c) 2023 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
+ *
+ *     http://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.features.messages.impl.timeline.components.reactionsummary
+
+import androidx.compose.ui.tooling.preview.PreviewParameterProvider
+import io.element.android.features.messages.impl.timeline.aTimelineItemReactions
+import io.element.android.libraries.matrix.api.core.EventId
+
+open class ReactionSummaryStateProvider : PreviewParameterProvider {
+    override val values = sequenceOf(anActionListState())
+}
+
+fun anActionListState(): ReactionSummaryState {
+    val reactions = aTimelineItemReactions(8, true).reactions
+    return ReactionSummaryState(
+        target = ReactionSummaryState.Summary(
+            reactions = reactions,
+            selectedKey = reactions[0].key,
+            selectedEventId = EventId("$1234"),
+        ),
+        eventSink = {}
+    )
+}
diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/reactionsummary/ReactionSummaryView.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/reactionsummary/ReactionSummaryView.kt
new file mode 100644
index 0000000000..1228c41a16
--- /dev/null
+++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/reactionsummary/ReactionSummaryView.kt
@@ -0,0 +1,274 @@
+/*
+ * Copyright (c) 2023 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
+ *
+ *     http://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.features.messages.impl.timeline.components.reactionsummary
+
+import androidx.compose.foundation.ExperimentalFoundationApi
+import androidx.compose.foundation.background
+import androidx.compose.foundation.clickable
+import androidx.compose.foundation.layout.Arrangement
+import androidx.compose.foundation.layout.Column
+import androidx.compose.foundation.layout.PaddingValues
+import androidx.compose.foundation.layout.Row
+import androidx.compose.foundation.layout.Spacer
+import androidx.compose.foundation.layout.fillMaxHeight
+import androidx.compose.foundation.layout.fillMaxWidth
+import androidx.compose.foundation.layout.heightIn
+import androidx.compose.foundation.layout.padding
+import androidx.compose.foundation.layout.width
+import androidx.compose.foundation.lazy.LazyColumn
+import androidx.compose.foundation.lazy.LazyRow
+import androidx.compose.foundation.lazy.items
+import androidx.compose.foundation.lazy.rememberLazyListState
+import androidx.compose.foundation.pager.HorizontalPager
+import androidx.compose.foundation.pager.rememberPagerState
+import androidx.compose.foundation.shape.CornerSize
+import androidx.compose.foundation.shape.RoundedCornerShape
+import androidx.compose.material3.ExperimentalMaterial3Api
+import androidx.compose.material3.MaterialTheme
+import androidx.compose.material3.rememberModalBottomSheetState
+import androidx.compose.runtime.Composable
+import androidx.compose.runtime.LaunchedEffect
+import androidx.compose.runtime.derivedStateOf
+import androidx.compose.runtime.getValue
+import androidx.compose.runtime.mutableStateOf
+import androidx.compose.runtime.remember
+import androidx.compose.runtime.rememberCoroutineScope
+import androidx.compose.runtime.saveable.rememberSaveable
+import androidx.compose.runtime.setValue
+import androidx.compose.ui.Alignment
+import androidx.compose.ui.Modifier
+import androidx.compose.ui.draw.clip
+import androidx.compose.ui.graphics.Color
+import androidx.compose.ui.text.style.TextOverflow
+import androidx.compose.ui.tooling.preview.PreviewParameter
+import androidx.compose.ui.unit.dp
+import androidx.compose.ui.unit.sp
+import io.element.android.features.messages.impl.timeline.model.AggregatedReaction
+import io.element.android.libraries.designsystem.components.avatar.Avatar
+import io.element.android.libraries.designsystem.components.avatar.AvatarData
+import io.element.android.libraries.designsystem.components.avatar.AvatarSize
+import io.element.android.libraries.designsystem.preview.DayNightPreviews
+import io.element.android.libraries.designsystem.preview.ElementPreview
+import io.element.android.libraries.designsystem.theme.components.ModalBottomSheet
+import io.element.android.libraries.designsystem.theme.components.Surface
+import io.element.android.libraries.designsystem.theme.components.Text
+import io.element.android.libraries.matrix.api.user.MatrixUser
+import io.element.android.libraries.matrix.ui.model.getAvatarData
+import io.element.android.libraries.theme.ElementTheme
+import kotlinx.coroutines.launch
+
+@OptIn(ExperimentalMaterial3Api::class)
+@Composable
+fun ReactionSummaryView(
+    state: ReactionSummaryState,
+    modifier: Modifier = Modifier,
+) {
+    val sheetState = rememberModalBottomSheetState()
+
+    fun onDismiss() {
+        state.eventSink(ReactionSummaryEvents.Clear)
+    }
+
+    if (state.target != null) {
+        ModalBottomSheet(
+            onDismissRequest = ::onDismiss,
+            sheetState = sheetState,
+            modifier = modifier
+        ) {
+            SheetContent(summary = state.target)
+        }
+    }
+}
+
+@OptIn(ExperimentalFoundationApi::class)
+@Composable
+private fun SheetContent(
+    summary: ReactionSummaryState.Summary,
+    modifier: Modifier = Modifier,
+) {
+    val animationScope = rememberCoroutineScope()
+    var selectedReactionKey: String by rememberSaveable { mutableStateOf(summary.selectedKey) }
+    val selectedReactionIndex: Int by remember {
+        derivedStateOf {
+            summary.reactions.indexOfFirst { it.key == selectedReactionKey }
+        }
+    }
+    val pagerState = rememberPagerState(initialPage = selectedReactionIndex)
+    val reactionListState = rememberLazyListState()
+
+    LaunchedEffect(pagerState.currentPage) {
+        selectedReactionKey = summary.reactions[pagerState.currentPage].key
+        val visibleInfo =  reactionListState.layoutInfo.visibleItemsInfo
+        if (selectedReactionIndex <= visibleInfo.first().index || selectedReactionIndex >= visibleInfo.last().index) {
+            reactionListState.animateScrollToItem(selectedReactionIndex)
+        }
+    }
+
+    Column(
+        modifier = modifier
+            .fillMaxWidth()
+            .fillMaxHeight()
+    ) {
+        LazyRow(state = reactionListState,
+            horizontalArrangement = Arrangement.spacedBy(8.dp),
+            contentPadding = PaddingValues(start = 12.dp, end = 12.dp, bottom = 12.dp)
+        ) {
+            items(summary.reactions) { reaction ->
+                AggregatedReactionButton(
+                    reaction = reaction,
+                    isHighlighted = selectedReactionKey == reaction.key,
+                    onClick = {
+                        selectedReactionKey = reaction.key
+                        animationScope.launch {
+                            pagerState.animateScrollToPage(selectedReactionIndex)
+                        }
+                    }
+                )
+            }
+        }
+        HorizontalPager(state = pagerState, pageCount = summary.reactions.size) { page ->
+            LazyColumn(modifier = Modifier.fillMaxHeight()) {
+                items(summary.reactions[page].senders) { sender ->
+
+                    val user = sender.user ?: MatrixUser(userId = sender.senderId)
+
+                    SenderRow(
+                        avatarData = user.getAvatarData(AvatarSize.UserListItem),
+                        name = user.displayName ?: user.userId.value,
+                        userId = user.userId.value,
+                        sentTime = sender.sentTime
+                    )
+                }
+            }
+        }
+    }
+}
+
+@Composable
+fun AggregatedReactionButton(
+    reaction: AggregatedReaction,
+    isHighlighted: Boolean,
+    onClick: () -> Unit,
+    modifier: Modifier = Modifier,
+) {
+
+    val buttonColor = if (isHighlighted) {
+        ElementTheme.colors.bgActionPrimaryRest
+    } else {
+        Color.Transparent
+    }
+
+    val textColor = if (isHighlighted) {
+        MaterialTheme.colorScheme.inversePrimary
+    } else {
+        MaterialTheme.colorScheme.primary
+    }
+
+    val roundedCornerShape = RoundedCornerShape(corner = CornerSize(percent = 50))
+    Surface(
+        modifier = modifier
+            .background(buttonColor, roundedCornerShape)
+            .clip(roundedCornerShape)
+            .clickable(onClick = onClick)
+            .padding(vertical = 8.dp, horizontal = 12.dp),
+        color = buttonColor
+    ) {
+        Row(
+            verticalAlignment = Alignment.CenterVertically,
+            modifier = Modifier,
+        ) {
+            Text(
+                text = reaction.displayKey,
+                style = ElementTheme.typography.fontBodyMdRegular.copy(
+                    fontSize = 20.sp,
+                    lineHeight = 25.sp
+                ),
+            )
+            if (reaction.count > 1) {
+                Spacer(modifier = Modifier.width(4.dp))
+                Text(
+                    text = reaction.count.toString(),
+                    color = textColor,
+                    style = ElementTheme.typography.fontBodyMdRegular.copy(
+                        fontSize = 20.sp,
+                        lineHeight = 25.sp
+                    )
+                )
+            }
+        }
+    }
+}
+
+@Composable
+fun SenderRow(
+    avatarData: AvatarData,
+    name: String,
+    userId: String,
+    sentTime: String,
+    modifier: Modifier = Modifier,
+) {
+    Row(
+        modifier = modifier
+            .fillMaxWidth()
+            .heightIn(min = 56.dp)
+            .padding(start = 16.dp, top = 4.dp, end = 16.dp, bottom = 4.dp),
+        verticalAlignment = Alignment.CenterVertically
+    ) {
+        Avatar(avatarData)
+        Column(
+            modifier = Modifier.padding(start = 12.dp),
+        ) {
+            Row(
+                modifier = Modifier.fillMaxWidth(),
+                verticalAlignment = Alignment.Bottom
+            ) {
+                Text(
+                    modifier = Modifier
+                        .padding(end = 4.dp)
+                        .weight(1f),
+                    text = name,
+                    maxLines = 1,
+                    overflow = TextOverflow.Ellipsis,
+                    color = MaterialTheme.colorScheme.primary,
+                    style = ElementTheme.typography.fontBodyMdRegular,
+                )
+                Text(
+                    text = sentTime,
+                    color = MaterialTheme.colorScheme.secondary,
+                    maxLines = 1,
+                    overflow = TextOverflow.Ellipsis,
+                    style = ElementTheme.typography.fontBodySmRegular,
+                )
+            }
+            Text(
+                text = userId,
+                color = MaterialTheme.colorScheme.secondary,
+                maxLines = 1,
+                overflow = TextOverflow.Ellipsis,
+                style = ElementTheme.typography.fontBodySmRegular,
+            )
+        }
+    }
+}
+
+@DayNightPreviews
+@Composable
+internal fun SheetContentPreview(
+    @PreviewParameter(ReactionSummaryStateProvider::class) state: ReactionSummaryState
+) = ElementPreview {
+    SheetContent(summary = state.target as ReactionSummaryState.Summary)
+}
diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/retrysendmenu/RetrySendMessageMenu.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/retrysendmenu/RetrySendMessageMenu.kt
index d344a5e995..cae55de241 100644
--- a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/retrysendmenu/RetrySendMessageMenu.kt
+++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/retrysendmenu/RetrySendMessageMenu.kt
@@ -31,7 +31,6 @@ import androidx.compose.runtime.Composable
 import androidx.compose.runtime.rememberCoroutineScope
 import androidx.compose.ui.Modifier
 import androidx.compose.ui.res.stringResource
-import androidx.compose.ui.text.font.FontWeight
 import androidx.compose.ui.tooling.preview.Preview
 import androidx.compose.ui.tooling.preview.PreviewParameter
 import androidx.compose.ui.unit.dp
@@ -165,6 +164,7 @@ internal fun RetrySendMessageMenuPreviewDark(@PreviewParameter(RetrySendMenuStat
     }
 }
 
+@Suppress("UNUSED_PARAMETER")
 @OptIn(ExperimentalMaterial3Api::class)
 @Composable
 private fun ContentToPreview(state: RetrySendMenuState) {
diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/virtual/TimelineEncryptedHistoryBannerView.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/virtual/TimelineEncryptedHistoryBannerView.kt
index 055e4bb876..65af6bdbf5 100644
--- a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/virtual/TimelineEncryptedHistoryBannerView.kt
+++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/virtual/TimelineEncryptedHistoryBannerView.kt
@@ -30,7 +30,6 @@ import androidx.compose.runtime.Composable
 import androidx.compose.ui.Modifier
 import androidx.compose.ui.draw.clip
 import androidx.compose.ui.res.stringResource
-import androidx.compose.ui.tooling.preview.Preview
 import androidx.compose.ui.unit.dp
 import io.element.android.features.messages.impl.R
 import io.element.android.libraries.designsystem.preview.DayNightPreviews
diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/virtual/TimelineItemDaySeparatorView.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/virtual/TimelineItemDaySeparatorView.kt
index c76d59806d..23e393ae8f 100644
--- a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/virtual/TimelineItemDaySeparatorView.kt
+++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/virtual/TimelineItemDaySeparatorView.kt
@@ -24,7 +24,6 @@ import androidx.compose.material3.MaterialTheme
 import androidx.compose.runtime.Composable
 import androidx.compose.ui.Alignment
 import androidx.compose.ui.Modifier
-import androidx.compose.ui.text.font.FontWeight
 import androidx.compose.ui.tooling.preview.Preview
 import androidx.compose.ui.tooling.preview.PreviewParameter
 import androidx.compose.ui.unit.dp
diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/diff/CacheInvalidator.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/diff/CacheInvalidator.kt
deleted file mode 100644
index 9aa3ab5e02..0000000000
--- a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/diff/CacheInvalidator.kt
+++ /dev/null
@@ -1,56 +0,0 @@
-/*
- * Copyright (c) 2023 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
- *
- *     http://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.features.messages.impl.timeline.diff
-
-import androidx.recyclerview.widget.ListUpdateCallback
-import io.element.android.features.messages.impl.timeline.model.TimelineItem
-import io.element.android.features.messages.impl.timeline.util.invalidateLast
-import timber.log.Timber
-
-internal class CacheInvalidator(private val itemStatesCache: MutableList) :
-    ListUpdateCallback {
-
-    override fun onChanged(position: Int, count: Int, payload: Any?) {
-        Timber.d("onChanged(position= $position, count= $count)")
-        (position until position + count).forEach {
-            // Invalidate cache
-            itemStatesCache[it] = null
-        }
-    }
-
-    override fun onMoved(fromPosition: Int, toPosition: Int) {
-        Timber.d("onMoved(fromPosition= $fromPosition, toPosition= $toPosition)")
-        val model = itemStatesCache.removeAt(fromPosition)
-        itemStatesCache.add(toPosition, model)
-    }
-
-    override fun onInserted(position: Int, count: Int) {
-        Timber.d("onInserted(position= $position, count= $count)")
-        itemStatesCache.invalidateLast()
-        repeat(count) {
-            itemStatesCache.add(position, null)
-        }
-    }
-
-    override fun onRemoved(position: Int, count: Int) {
-        Timber.d("onRemoved(position= $position, count= $count)")
-        itemStatesCache.invalidateLast()
-        repeat(count) {
-            itemStatesCache.removeAt(position)
-        }
-    }
-}
diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/diff/TimelineItemsCacheInvalidator.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/diff/TimelineItemsCacheInvalidator.kt
new file mode 100644
index 0000000000..a7a3bea00e
--- /dev/null
+++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/diff/TimelineItemsCacheInvalidator.kt
@@ -0,0 +1,63 @@
+/*
+ * Copyright (c) 2023 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
+ *
+ *     http://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.features.messages.impl.timeline.diff
+
+import io.element.android.features.messages.impl.timeline.model.TimelineItem
+import io.element.android.libraries.androidutils.diff.DefaultDiffCacheInvalidator
+import io.element.android.libraries.androidutils.diff.DiffCacheInvalidator
+import io.element.android.libraries.androidutils.diff.MutableDiffCache
+
+/**
+ * [DiffCacheInvalidator] implementation for [TimelineItem].
+ * It uses [DefaultDiffCacheInvalidator] and invalidate the cache around the updated item so that those items are computed again.
+ * This is needed because a timeline item is computed based on the previous and next items.
+ */
+internal class TimelineItemsCacheInvalidator : DiffCacheInvalidator {
+
+    private val delegate = DefaultDiffCacheInvalidator()
+
+    override fun onChanged(position: Int, count: Int, cache: MutableDiffCache) {
+        delegate.onChanged(position, count, cache)
+    }
+
+    override fun onMoved(fromPosition: Int, toPosition: Int, cache: MutableDiffCache) {
+        delegate.onMoved(fromPosition, toPosition, cache)
+    }
+
+    override fun onInserted(position: Int, count: Int, cache: MutableDiffCache) {
+        cache.invalidateAround(position)
+        delegate.onInserted(position, count, cache)
+    }
+
+    override fun onRemoved(position: Int, count: Int, cache: MutableDiffCache) {
+        cache.invalidateAround(position)
+        delegate.onRemoved(position, count, cache)
+    }
+}
+
+/**
+ * Invalidate the cache around the given position.
+ * It invalidates the previous and next items.
+ */
+private fun MutableDiffCache<*>.invalidateAround(position: Int) {
+    if (position > 0) {
+        set(position - 1, null)
+    }
+    if (position < indices().last) {
+        set(position + 1, null)
+    }
+}
diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/factories/TimelineItemsFactory.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/factories/TimelineItemsFactory.kt
index aa9786c945..d664d3f26c 100644
--- a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/factories/TimelineItemsFactory.kt
+++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/factories/TimelineItemsFactory.kt
@@ -19,13 +19,13 @@ package io.element.android.features.messages.impl.timeline.factories
 import androidx.compose.runtime.Composable
 import androidx.compose.runtime.State
 import androidx.compose.runtime.collectAsState
-import androidx.recyclerview.widget.DiffUtil
-import io.element.android.features.messages.impl.timeline.diff.CacheInvalidator
-import io.element.android.features.messages.impl.timeline.diff.MatrixTimelineItemsDiffCallback
+import io.element.android.features.messages.impl.timeline.diff.TimelineItemsCacheInvalidator
 import io.element.android.features.messages.impl.timeline.factories.event.TimelineItemEventFactory
 import io.element.android.features.messages.impl.timeline.factories.virtual.TimelineItemVirtualFactory
 import io.element.android.features.messages.impl.timeline.groups.TimelineItemGrouper
 import io.element.android.features.messages.impl.timeline.model.TimelineItem
+import io.element.android.libraries.androidutils.diff.DiffCacheUpdater
+import io.element.android.libraries.androidutils.diff.MutableListDiffCache
 import io.element.android.libraries.core.coroutine.CoroutineDispatchers
 import io.element.android.libraries.matrix.api.timeline.MatrixTimelineItem
 import kotlinx.collections.immutable.ImmutableList
@@ -35,9 +35,7 @@ import kotlinx.coroutines.flow.MutableStateFlow
 import kotlinx.coroutines.sync.Mutex
 import kotlinx.coroutines.sync.withLock
 import kotlinx.coroutines.withContext
-import timber.log.Timber
 import javax.inject.Inject
-import kotlin.system.measureTimeMillis
 
 class TimelineItemsFactory @Inject constructor(
     private val dispatchers: CoroutineDispatchers,
@@ -46,13 +44,20 @@ class TimelineItemsFactory @Inject constructor(
     private val timelineItemGrouper: TimelineItemGrouper,
 ) {
     private val timelineItems = MutableStateFlow(persistentListOf())
-    private val timelineItemsCache = arrayListOf()
-
-    // Items from rust sdk, used for diffing
-    private var matrixTimelineItems: List = emptyList()
 
     private val lock = Mutex()
-    private val cacheInvalidator = CacheInvalidator(timelineItemsCache)
+    private val diffCache = MutableListDiffCache()
+    private val diffCacheUpdater = DiffCacheUpdater(
+        diffCache = diffCache,
+        detectMoves = false,
+        cacheInvalidator = TimelineItemsCacheInvalidator()
+    ) { old, new ->
+        if (old is MatrixTimelineItem.Event && new is MatrixTimelineItem.Event) {
+            old.uniqueId == new.uniqueId
+        } else {
+            false
+        }
+    }
 
     @Composable
     fun collectItemsAsState(): State> {
@@ -63,15 +68,15 @@ class TimelineItemsFactory @Inject constructor(
         timelineItems: List,
     ) = withContext(dispatchers.computation) {
         lock.withLock {
-            calculateAndApplyDiff(timelineItems)
+            diffCacheUpdater.updateWith(timelineItems)
             buildAndEmitTimelineItemStates(timelineItems)
         }
     }
 
     private suspend fun buildAndEmitTimelineItemStates(timelineItems: List) {
         val newTimelineItemStates = ArrayList()
-        for (index in timelineItemsCache.indices.reversed()) {
-            val cacheItem = timelineItemsCache[index]
+        for (index in diffCache.indices().reversed()) {
+            val cacheItem = diffCache.get(index)
             if (cacheItem == null) {
                 buildAndCacheItem(timelineItems, index)?.also { timelineItemState ->
                     newTimelineItemStates.add(timelineItemState)
@@ -84,20 +89,6 @@ class TimelineItemsFactory @Inject constructor(
         this.timelineItems.emit(result)
     }
 
-    private fun calculateAndApplyDiff(newTimelineItems: List) {
-        val timeToDiff = measureTimeMillis {
-            val diffCallback =
-                MatrixTimelineItemsDiffCallback(
-                    oldList = matrixTimelineItems,
-                    newList = newTimelineItems
-                )
-            val diffResult = DiffUtil.calculateDiff(diffCallback, false)
-            matrixTimelineItems = newTimelineItems
-            diffResult.dispatchUpdatesTo(cacheInvalidator)
-        }
-        Timber.v("Time to apply diff on new list of ${newTimelineItems.size} items: $timeToDiff ms")
-    }
-
     private fun buildAndCacheItem(
         timelineItems: List,
         index: Int
@@ -108,7 +99,7 @@ class TimelineItemsFactory @Inject constructor(
                 is MatrixTimelineItem.Virtual -> virtualItemFactory.create(currentTimelineItem)
                 MatrixTimelineItem.Other -> null
             }
-        timelineItemsCache[index] = timelineItemState
+        diffCache[index] = timelineItemState
         return timelineItemState
     }
 }
diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/factories/event/TimelineItemContentFactory.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/factories/event/TimelineItemContentFactory.kt
index eb6d0e45c0..fad1ccc822 100644
--- a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/factories/event/TimelineItemContentFactory.kt
+++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/factories/event/TimelineItemContentFactory.kt
@@ -22,6 +22,8 @@ import io.element.android.libraries.matrix.api.timeline.item.event.EventTimeline
 import io.element.android.libraries.matrix.api.timeline.item.event.FailedToParseMessageLikeContent
 import io.element.android.libraries.matrix.api.timeline.item.event.FailedToParseStateContent
 import io.element.android.libraries.matrix.api.timeline.item.event.MessageContent
+import io.element.android.libraries.matrix.api.timeline.item.event.PollContent
+import io.element.android.libraries.matrix.api.timeline.item.event.PollEndContent
 import io.element.android.libraries.matrix.api.timeline.item.event.ProfileChangeContent
 import io.element.android.libraries.matrix.api.timeline.item.event.RedactedContent
 import io.element.android.libraries.matrix.api.timeline.item.event.RoomMembershipContent
@@ -35,6 +37,8 @@ class TimelineItemContentFactory @Inject constructor(
     private val messageFactory: TimelineItemContentMessageFactory,
     private val redactedMessageFactory: TimelineItemContentRedactedFactory,
     private val stickerFactory: TimelineItemContentStickerFactory,
+    private val pollFactory: TimelineItemContentPollFactory,
+    private val pollEndFactory: TimelineItemContentPollEndFactory,
     private val utdFactory: TimelineItemContentUTDFactory,
     private val roomMembershipFactory: TimelineItemContentRoomMembershipFactory,
     private val profileChangeFactory: TimelineItemContentProfileChangeFactory,
@@ -53,6 +57,8 @@ class TimelineItemContentFactory @Inject constructor(
             is RoomMembershipContent -> roomMembershipFactory.create(eventTimelineItem)
             is StateContent -> stateFactory.create(eventTimelineItem)
             is StickerContent -> stickerFactory.create(itemContent)
+            is PollContent -> pollFactory.create(itemContent)
+            is PollEndContent -> pollEndFactory.create(itemContent)
             is UnableToDecryptContent -> utdFactory.create(itemContent)
             is UnknownContent -> TimelineItemUnknownContent
         }
diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/factories/event/TimelineItemContentFailedToParseMessageFactory.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/factories/event/TimelineItemContentFailedToParseMessageFactory.kt
index 4dacb76523..e764cfa28f 100644
--- a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/factories/event/TimelineItemContentFailedToParseMessageFactory.kt
+++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/factories/event/TimelineItemContentFailedToParseMessageFactory.kt
@@ -23,7 +23,7 @@ import javax.inject.Inject
 
 class TimelineItemContentFailedToParseMessageFactory @Inject constructor() {
 
-    fun create(failedToParseMessageLike: FailedToParseMessageLikeContent): TimelineItemEventContent {
+    fun create(@Suppress("UNUSED_PARAMETER") failedToParseMessageLike: FailedToParseMessageLikeContent): TimelineItemEventContent {
         return TimelineItemUnknownContent
     }
 }
diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/factories/event/TimelineItemContentFailedToParseStateFactory.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/factories/event/TimelineItemContentFailedToParseStateFactory.kt
index 7e2bf90050..f7d3c10483 100644
--- a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/factories/event/TimelineItemContentFailedToParseStateFactory.kt
+++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/factories/event/TimelineItemContentFailedToParseStateFactory.kt
@@ -23,6 +23,7 @@ import javax.inject.Inject
 
 class TimelineItemContentFailedToParseStateFactory @Inject constructor() {
 
+    @Suppress("UNUSED_PARAMETER")
     fun create(failedToParseState: FailedToParseStateContent): TimelineItemEventContent {
         return TimelineItemUnknownContent
     }
diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/factories/event/TimelineItemContentPollEndFactory.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/factories/event/TimelineItemContentPollEndFactory.kt
new file mode 100644
index 0000000000..ff9eb837b6
--- /dev/null
+++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/factories/event/TimelineItemContentPollEndFactory.kt
@@ -0,0 +1,29 @@
+/*
+ * Copyright (c) 2023 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
+ *
+ *     http://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.features.messages.impl.timeline.factories.event
+
+import io.element.android.features.messages.impl.timeline.model.event.TimelineItemEventContent
+import io.element.android.features.messages.impl.timeline.model.event.TimelineItemUnknownContent
+import io.element.android.libraries.matrix.api.timeline.item.event.PollEndContent
+import javax.inject.Inject
+
+class TimelineItemContentPollEndFactory @Inject constructor() {
+
+    fun create(@Suppress("UNUSED_PARAMETER") content: PollEndContent): TimelineItemEventContent {
+        return TimelineItemUnknownContent
+    }
+}
diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/factories/event/TimelineItemContentPollFactory.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/factories/event/TimelineItemContentPollFactory.kt
new file mode 100644
index 0000000000..2ab69f10e4
--- /dev/null
+++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/factories/event/TimelineItemContentPollFactory.kt
@@ -0,0 +1,56 @@
+/*
+ * Copyright (c) 2023 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
+ *
+ *     http://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.features.messages.impl.timeline.factories.event
+
+import io.element.android.features.messages.impl.timeline.model.event.TimelineItemEventContent
+import io.element.android.features.messages.impl.timeline.model.event.TimelineItemPollContent
+import io.element.android.features.poll.api.PollAnswerItem
+import io.element.android.libraries.matrix.api.MatrixClient
+import io.element.android.libraries.matrix.api.poll.PollKind
+import io.element.android.libraries.matrix.api.timeline.item.event.PollContent
+import javax.inject.Inject
+
+class TimelineItemContentPollFactory @Inject constructor(
+    private val matrixClient: MatrixClient,
+) {
+
+    fun create(content: PollContent): TimelineItemEventContent {
+        // Todo Move this computation to the matrix rust sdk
+        val showResults = content.kind == PollKind.Disclosed && matrixClient.sessionId in content.votes.flatMap { it.value }
+        val pollVotesCount = content.votes.flatMap { it.value }.size
+        val userVotes = content.votes.filter { matrixClient.sessionId in it.value }.keys
+        val answerItems = content.answers.map { answer ->
+            val votesCount = content.votes[answer.id]?.size ?: 0
+            val progress = if (pollVotesCount > 0) votesCount.toFloat() / pollVotesCount.toFloat() else 0f
+            PollAnswerItem(
+                answer = answer,
+                isSelected = answer.id in userVotes,
+                isDisclosed = showResults,
+                votesCount = votesCount,
+                progress = progress,
+            )
+        }
+
+        return TimelineItemPollContent(
+            question = content.question,
+            answerItems = answerItems,
+            votes = content.votes,
+            pollKind = content.kind,
+            isDisclosed = showResults
+        )
+    }
+}
diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/factories/event/TimelineItemContentRedactedFactory.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/factories/event/TimelineItemContentRedactedFactory.kt
index dfbbd233c7..9419c7c31d 100644
--- a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/factories/event/TimelineItemContentRedactedFactory.kt
+++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/factories/event/TimelineItemContentRedactedFactory.kt
@@ -23,7 +23,7 @@ import javax.inject.Inject
 
 class TimelineItemContentRedactedFactory @Inject constructor() {
 
-    fun create(content: RedactedContent): TimelineItemEventContent {
+    fun create(@Suppress("UNUSED_PARAMETER") content: RedactedContent): TimelineItemEventContent {
         return TimelineItemRedactedContent
     }
 }
diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/factories/event/TimelineItemContentStickerFactory.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/factories/event/TimelineItemContentStickerFactory.kt
index b823791912..1607bb77c4 100644
--- a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/factories/event/TimelineItemContentStickerFactory.kt
+++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/factories/event/TimelineItemContentStickerFactory.kt
@@ -23,7 +23,7 @@ import javax.inject.Inject
 
 class TimelineItemContentStickerFactory @Inject constructor() {
 
-    fun create(content: StickerContent): TimelineItemEventContent {
+    fun create(@Suppress("UNUSED_PARAMETER") content: StickerContent): TimelineItemEventContent {
         return TimelineItemUnknownContent
     }
 }
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 6bc5df1e79..683b7515b9 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
@@ -18,6 +18,7 @@ package io.element.android.features.messages.impl.timeline.factories.event
 
 import io.element.android.features.messages.impl.timeline.groups.canBeDisplayedInBubbleBlock
 import io.element.android.features.messages.impl.timeline.model.AggregatedReaction
+import io.element.android.features.messages.impl.timeline.model.AggregatedReactionSender
 import io.element.android.features.messages.impl.timeline.model.TimelineItem
 import io.element.android.features.messages.impl.timeline.model.TimelineItemGroupPosition
 import io.element.android.features.messages.impl.timeline.model.TimelineItemReactions
@@ -90,14 +91,34 @@ class TimelineItemEventFactory @Inject constructor(
     }
 
     private fun MatrixTimelineItem.Event.computeReactionsState(): TimelineItemReactions {
-        val aggregatedReactions = event.reactions.map {
+        val timeFormatter = DateFormat.getTimeInstance(DateFormat.SHORT)
+        var aggregatedReactions = event.reactions.map { reaction ->
+            // Sort reactions within an aggregation by timestamp descending.
+            // This puts the most recent at the top, useful in cases like the
+            // reaction summary view or getting the most recent reaction.
             AggregatedReaction(
-                key = it.key,
-                count = it.count.toInt(),
-                isHighlighted = it.senderIds.contains(matrixClient.sessionId),
+                key = reaction.key,
+                currentUserId = matrixClient.sessionId,
+                senders = reaction.senders
+                    .sortedByDescending{ it.timestamp }
+                    .map {
+                        val date = Date(it.timestamp)
+                        AggregatedReactionSender(
+                            senderId = it.senderId,
+                            timestamp = date,
+                            sentTime = timeFormatter.format(date),
+                        )
+                    }
             )
         }
-        aggregatedReactions.sortedByDescending { it.count }
+        // Sort aggregated reactions by count and then timestamp ascending, using
+        // the most recent reaction in the aggregation(hence index 0).
+        // This appends new aggregations on the end of the reaction layout.
+        aggregatedReactions = aggregatedReactions
+            .sortedWith(
+                compareByDescending { it.count }
+                    .thenBy { it.senders[0].timestamp }
+            )
         return TimelineItemReactions(aggregatedReactions.toImmutableList())
     }
 
diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/groups/Groupability.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/groups/Groupability.kt
index 0b8baf692a..1d2dec09b7 100644
--- a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/groups/Groupability.kt
+++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/groups/Groupability.kt
@@ -22,6 +22,7 @@ import io.element.android.features.messages.impl.timeline.model.event.TimelineIt
 import io.element.android.features.messages.impl.timeline.model.event.TimelineItemFileContent
 import io.element.android.features.messages.impl.timeline.model.event.TimelineItemImageContent
 import io.element.android.features.messages.impl.timeline.model.event.TimelineItemLocationContent
+import io.element.android.features.messages.impl.timeline.model.event.TimelineItemPollContent
 import io.element.android.features.messages.impl.timeline.model.event.TimelineItemProfileChangeContent
 import io.element.android.features.messages.impl.timeline.model.event.TimelineItemRedactedContent
 import io.element.android.features.messages.impl.timeline.model.event.TimelineItemRoomMembershipContent
@@ -33,6 +34,8 @@ import io.element.android.libraries.matrix.api.timeline.MatrixTimelineItem
 import io.element.android.libraries.matrix.api.timeline.item.event.FailedToParseMessageLikeContent
 import io.element.android.libraries.matrix.api.timeline.item.event.FailedToParseStateContent
 import io.element.android.libraries.matrix.api.timeline.item.event.MessageContent
+import io.element.android.libraries.matrix.api.timeline.item.event.PollContent
+import io.element.android.libraries.matrix.api.timeline.item.event.PollEndContent
 import io.element.android.libraries.matrix.api.timeline.item.event.ProfileChangeContent
 import io.element.android.libraries.matrix.api.timeline.item.event.RedactedContent
 import io.element.android.libraries.matrix.api.timeline.item.event.RoomMembershipContent
@@ -55,6 +58,7 @@ internal fun TimelineItem.Event.canBeGrouped(): Boolean {
         is TimelineItemVideoContent,
         is TimelineItemAudioContent,
         is TimelineItemLocationContent,
+        is TimelineItemPollContent,
         TimelineItemRedactedContent,
         TimelineItemUnknownContent -> false
         is TimelineItemProfileChangeContent,
@@ -74,6 +78,8 @@ internal fun MatrixTimelineItem.Event.canBeDisplayedInBubbleBlock(): Boolean {
         is MessageContent,
         RedactedContent,
         is StickerContent,
+        is PollContent,
+        is PollEndContent,
         is UnableToDecryptContent -> true
         is FailedToParseStateContent,
         is ProfileChangeContent,
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 ba13896c06..59c52ed8cf 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
@@ -17,6 +17,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
 
 /**
  * Length at which we ellipsize a reaction key for display
@@ -27,16 +28,15 @@ import io.element.android.libraries.core.extensions.ellipsize
 private const val MAX_DISPLAY_CHARS = 16
 
 /**
+ * @property currentUserId the ID of the currently logged in user
  * @property key the full reaction key (e.g. "👍", "YES!")
- * @property count the number of users who reacted with this key
- * @property isHighlighted true if the reaction has (also) been sent by the current user.
+ * @property senders the list of users who sent the reactions
  */
 data class AggregatedReaction(
+    val currentUserId: UserId,
     val key: String,
-    val count: Int,
-    val isHighlighted: Boolean = false
+    val senders: List
 ) {
-
     /**
      * The key to be displayed on screen.
      *
@@ -45,4 +45,18 @@ data class AggregatedReaction(
     val displayKey: String by lazy {
         key.ellipsize(MAX_DISPLAY_CHARS)
     }
+
+    /**
+     * The number of users who reacted with this key.
+     */
+    val count: Int by lazy {
+        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 }
+    }
 }
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 148f565911..dcd6bb105c 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
@@ -17,6 +17,9 @@
 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 java.text.DateFormat
+import java.util.Date
 
 open class AggregatedReactionProvider : PreviewParameterProvider {
     override val values: Sequence
@@ -29,11 +32,27 @@ open class AggregatedReactionProvider : PreviewParameterProvider
+            val timeFormatter = DateFormat.getTimeInstance(DateFormat.SHORT)
+            val date = Date(1_689_061_264L)
+            add(
+                AggregatedReactionSender(
+                    senderId = if (isHighlighted && index == 0) userId else UserId("@user$index:server.org"),
+                    timestamp = date,
+                    sentTime = timeFormatter.format(date),
+                )
+            )
+        }
+    }
+    return AggregatedReaction(
+        currentUserId = userId,
+        key = key,
+        senders = senders
+    )
+}
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
new file mode 100644
index 0000000000..276ee0b266
--- /dev/null
+++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/model/AggregatedReactionSender.kt
@@ -0,0 +1,28 @@
+/*
+ * Copyright (c) 2023 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
+ *
+ *     http://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.features.messages.impl.timeline.model
+
+import io.element.android.libraries.matrix.api.core.UserId
+import io.element.android.libraries.matrix.api.user.MatrixUser
+import java.util.Date
+
+data class AggregatedReactionSender(
+    val senderId: UserId,
+    val timestamp: Date,
+    val sentTime: String,
+    val user: MatrixUser? = null
+)
diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/model/event/TimelineItemEventContent.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/model/event/TimelineItemEventContent.kt
index 0ff67e481f..02837bd6b4 100644
--- a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/model/event/TimelineItemEventContent.kt
+++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/model/event/TimelineItemEventContent.kt
@@ -33,3 +33,21 @@ fun TimelineItemEventContent.canBeCopied(): Boolean =
         is TimelineItemRedactedContent -> true
         else -> false
     }
+
+/**
+ * Return true if user can react (i.e. send a reaction) on the event content.
+ */
+fun TimelineItemEventContent.canReact(): Boolean =
+    when (this) {
+        is TimelineItemTextBasedContent,
+        is TimelineItemAudioContent,
+        is TimelineItemEncryptedContent,
+        is TimelineItemFileContent,
+        is TimelineItemImageContent,
+        is TimelineItemLocationContent,
+        is TimelineItemPollContent,
+        is TimelineItemVideoContent -> true
+        is TimelineItemStateContent,
+        is TimelineItemRedactedContent,
+        TimelineItemUnknownContent -> false
+    }
diff --git a/app/src/main/kotlin/io/element/android/x/initializer/TimberInitializer.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/model/event/TimelineItemPollContent.kt
similarity index 52%
rename from app/src/main/kotlin/io/element/android/x/initializer/TimberInitializer.kt
rename to features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/model/event/TimelineItemPollContent.kt
index 5a641d75c6..b8a2fa8bca 100644
--- a/app/src/main/kotlin/io/element/android/x/initializer/TimberInitializer.kt
+++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/model/event/TimelineItemPollContent.kt
@@ -14,22 +14,18 @@
  * limitations under the License.
  */
 
-package io.element.android.x.initializer
+package io.element.android.features.messages.impl.timeline.model.event
 
-import android.content.Context
-import androidx.startup.Initializer
-import io.element.android.features.rageshake.impl.logs.VectorFileLogger
-import io.element.android.x.BuildConfig
-import timber.log.Timber
+import io.element.android.features.poll.api.PollAnswerItem
+import io.element.android.libraries.matrix.api.core.UserId
+import io.element.android.libraries.matrix.api.poll.PollKind
 
-class TimberInitializer : Initializer {
-
-    override fun create(context: Context) {
-        if (BuildConfig.DEBUG) {
-            Timber.plant(Timber.DebugTree())
-        }
-        Timber.plant(VectorFileLogger(context))
-    }
-
-    override fun dependencies(): List>> = emptyList()
+data class TimelineItemPollContent(
+    val question: String,
+    val answerItems: List,
+    val votes: Map>,
+    val pollKind: PollKind,
+    val isDisclosed: Boolean,
+) : TimelineItemEventContent {
+    override val type: String = "TimelineItemPollContent"
 }
diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/model/event/TimelineItemPollContentProvider.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/model/event/TimelineItemPollContentProvider.kt
new file mode 100644
index 0000000000..665d507ead
--- /dev/null
+++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/model/event/TimelineItemPollContentProvider.kt
@@ -0,0 +1,39 @@
+/*
+ * Copyright (c) 2023 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
+ *
+ *     http://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.features.messages.impl.timeline.model.event
+
+import androidx.compose.ui.tooling.preview.PreviewParameterProvider
+import io.element.android.features.poll.api.aPollAnswerItemList
+import io.element.android.libraries.matrix.api.poll.PollKind
+
+open class TimelineItemPollContentProvider : PreviewParameterProvider {
+    override val values: Sequence
+        get() = sequenceOf(
+            aTimelineItemPollContent(),
+            aTimelineItemPollContent().copy(isDisclosed = true),
+        )
+}
+
+fun aTimelineItemPollContent(): TimelineItemPollContent {
+    return TimelineItemPollContent(
+        pollKind = PollKind.Disclosed,
+        isDisclosed = false,
+        question = "What type of food should we have at the party?",
+        answerItems = aPollAnswerItemList(),
+        votes = emptyMap(),
+    )
+}
diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/utils/messagesummary/MessageSummaryFormatterImpl.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/utils/messagesummary/MessageSummaryFormatterImpl.kt
index 42c50bbd9d..2b35eeda37 100644
--- a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/utils/messagesummary/MessageSummaryFormatterImpl.kt
+++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/utils/messagesummary/MessageSummaryFormatterImpl.kt
@@ -24,6 +24,7 @@ import io.element.android.features.messages.impl.timeline.model.event.TimelineIt
 import io.element.android.features.messages.impl.timeline.model.event.TimelineItemFileContent
 import io.element.android.features.messages.impl.timeline.model.event.TimelineItemImageContent
 import io.element.android.features.messages.impl.timeline.model.event.TimelineItemLocationContent
+import io.element.android.features.messages.impl.timeline.model.event.TimelineItemPollContent
 import io.element.android.features.messages.impl.timeline.model.event.TimelineItemProfileChangeContent
 import io.element.android.features.messages.impl.timeline.model.event.TimelineItemRedactedContent
 import io.element.android.features.messages.impl.timeline.model.event.TimelineItemStateContent
@@ -47,6 +48,7 @@ class MessageSummaryFormatterImpl @Inject constructor(
             is TimelineItemLocationContent -> context.getString(CommonStrings.common_shared_location)
             is TimelineItemEncryptedContent -> context.getString(CommonStrings.common_unable_to_decrypt)
             is TimelineItemRedactedContent -> context.getString(CommonStrings.common_message_removed)
+            is TimelineItemPollContent, // Todo Polls: handle summary
             is TimelineItemUnknownContent -> context.getString(CommonStrings.common_unsupported_event)
             is TimelineItemImageContent -> context.getString(CommonStrings.common_image)
             is TimelineItemVideoContent -> context.getString(CommonStrings.common_video)
diff --git a/features/messages/impl/src/main/res/values-de/translations.xml b/features/messages/impl/src/main/res/values-de/translations.xml
index 1486e35726..84c903844e 100644
--- a/features/messages/impl/src/main/res/values-de/translations.xml
+++ b/features/messages/impl/src/main/res/values-de/translations.xml
@@ -20,6 +20,6 @@
   "Mehr anzeigen"
   "Erneut senden"
   "Ihre Nachricht konnte nicht gesendet werden"
-  "Fehler bei der Verarbeitung von Medien zum Hochladen, bitte versuchen Sie es erneut."
+  "Fehler bei der Verarbeitung von Medien zum Hochladen, bitte versuche es erneut."
   "Entfernen"
 
diff --git a/features/messages/impl/src/main/res/values-fr/translations.xml b/features/messages/impl/src/main/res/values-fr/translations.xml
index 03dcaffac7..5f9f0223aa 100644
--- a/features/messages/impl/src/main/res/values-fr/translations.xml
+++ b/features/messages/impl/src/main/res/values-fr/translations.xml
@@ -5,7 +5,7 @@
     "%1$d changements dans la conversation"
   
   
-    
+    "%1$d de plus"
     "%1$d de plus"
   
   "Appareil photo"
@@ -19,6 +19,16 @@
   "Vous êtes seul dans ce chat"
   "Message copié"
   "Vous n‘avez pas le droit de poster dans ce salon"
+  "Autoriser les paramètres personnalisés"
+  "Activer cette option remplacera votre paramètre par défaut"
+  "Me notifier dans ce chat pour"
+  "paramètres généraux"
+  "Paramètre par défaut"
+  "Une erreur s’est produite lors du chargement des paramètres de notification."
+  "Impossible de restaurer le mode par défaut, veuillez réessayer."
+  "Impossible de régler le mode, veuillez réessayer."
+  "Tous les messages"
+  "Mentions et mots-clés uniquement"
   "Afficher moins"
   "Afficher plus"
   "Renvoyer"
diff --git a/features/messages/impl/src/main/res/values-ru/translations.xml b/features/messages/impl/src/main/res/values-ru/translations.xml
new file mode 100644
index 0000000000..7870cbc331
--- /dev/null
+++ b/features/messages/impl/src/main/res/values-ru/translations.xml
@@ -0,0 +1,39 @@
+
+
+  
+    "%1$d изменение в комнате"
+    "%1$d изменения в комнате"
+    "%1$d изменений в комнате"
+  
+  "Камера"
+  "Сделать фото"
+  "Записать видео"
+  "Вложение"
+  "Фото и Видео библиотека"
+  "Местоположение"
+  "В настоящее время история сообщений недоступна в этой комнате"
+  "Не удалось получить данные о пользователе"
+  "Хотите пригласить их снова?"
+  "Вы одни в этой комнате"
+  "Сообщение скопировано"
+  "У вас нет разрешения публиковать сообщения в этой комнате"
+  "Разрешить пользовательские настройки"
+  "Включение этого параметра отменяет настройки по умолчанию"
+  "Уведомить меня в этом чате"
+  "Вы можете изменить его в своем %1$s."
+  "Основные Настройки"
+  "Настройка по умолчанию"
+  "Произошла ошибка при загрузке настроек уведомлений."
+  "Не удалось восстановить режим по умолчанию, попробуйте еще раз."
+  "Не удалось настроить режим, попробуйте еще раз."
+  "Все сообщения"
+  "Только упоминания и ключевые слова"
+  "Показать меньше"
+  "Показать больше"
+  "Отправить снова"
+  "Не удалось отправить ваше сообщение"
+  "Добавить эмодзи"
+  "Показать меньше"
+  "Не удалось обработать медиафайл для загрузки, попробуйте еще раз."
+  "Удалить"
+
diff --git a/features/messages/impl/src/main/res/values-sk/translations.xml b/features/messages/impl/src/main/res/values-sk/translations.xml
index 39b7e974be..07e62e9a4d 100644
--- a/features/messages/impl/src/main/res/values-sk/translations.xml
+++ b/features/messages/impl/src/main/res/values-sk/translations.xml
@@ -6,7 +6,7 @@
     "%1$d zmien miestnosti"
   
   
-    
+    "%1$d ďalší"
     "%1$d ďalšie"
     "%1$d ďalších"
   
@@ -22,6 +22,17 @@
   "V tomto rozhovore ste sami"
   "Správa skopírovaná"
   "Nemáte povolenie uverejňovať príspevky v tejto miestnosti"
+  "Povoliť vlastné nastavenie"
+  "Zapnutím tohto nastavenia sa prepíše vaše predvolené nastavenie"
+  "Upozorniť ma v tejto konverzácii na"
+  "Môžete to zmeniť vo svojich %1$s."
+  "všeobecných nastaveniach"
+  "Predvolené nastavenie"
+  "Pri načítavaní nastavení oznámení došlo k chybe."
+  "Nepodarilo sa obnoviť predvolený režim, skúste to prosím znova."
+  "Nepodarilo sa nastaviť režim, skúste to prosím znova."
+  "Všetky správy"
+  "Iba zmienky a kľúčové slová"
   "Zobraziť menej"
   "Zobraziť viac"
   "Odoslať znova"
diff --git a/features/messages/impl/src/main/res/values-zh-rTW/translations.xml b/features/messages/impl/src/main/res/values-zh-rTW/translations.xml
new file mode 100644
index 0000000000..d7344e54ca
--- /dev/null
+++ b/features/messages/impl/src/main/res/values-zh-rTW/translations.xml
@@ -0,0 +1,26 @@
+
+
+  
+    "%1$d 個聊天室變更"
+  
+  
+    "還有 %1$d 個"
+  
+  "照相機"
+  "拍照"
+  "錄影"
+  "附件"
+  "位置"
+  "此聊天室只有您一個人"
+  "訊息已複製"
+  "您沒有權限在此聊天室傳送訊息"
+  "全域設定"
+  "預設"
+  "無法重設為預設模式,請再試一次。"
+  "無法設定模式,請再試一次。"
+  "所有訊息"
+  "只限提及與關鍵字"
+  "重傳"
+  "無法傳送您的訊息"
+  "移除"
+
diff --git a/features/messages/impl/src/main/res/values/localazy.xml b/features/messages/impl/src/main/res/values/localazy.xml
index 6303589aa2..c88beff81a 100644
--- a/features/messages/impl/src/main/res/values/localazy.xml
+++ b/features/messages/impl/src/main/res/values/localazy.xml
@@ -13,6 +13,7 @@
   "Attachment"
   "Photo & Video Library"
   "Location"
+  "Poll"
   "Message history is currently unavailable in this room"
   "Could not retrieve user details"
   "Would you like to invite them back?"
diff --git a/features/messages/impl/src/test/kotlin/io/element/android/features/messages/MessagesPresenterTest.kt b/features/messages/impl/src/test/kotlin/io/element/android/features/messages/MessagesPresenterTest.kt
index 8e68da1d12..5fcd06a980 100644
--- a/features/messages/impl/src/test/kotlin/io/element/android/features/messages/MessagesPresenterTest.kt
+++ b/features/messages/impl/src/test/kotlin/io/element/android/features/messages/MessagesPresenterTest.kt
@@ -17,10 +17,9 @@
 package io.element.android.features.messages
 
 import android.net.Uri
-import app.cash.molecule.RecompositionClock
+import app.cash.molecule.RecompositionMode
 import app.cash.molecule.moleculeFlow
 import app.cash.turbine.test
-import com.google.common.collect.Iterables.skip
 import com.google.common.truth.Truth.assertThat
 import io.element.android.features.analytics.test.FakeAnalyticsService
 import io.element.android.features.messages.fixtures.aMessageEvent
@@ -36,6 +35,7 @@ import io.element.android.features.messages.impl.messagecomposer.MessageComposer
 import io.element.android.features.messages.impl.messagecomposer.MessageComposerPresenter
 import io.element.android.features.messages.impl.timeline.TimelinePresenter
 import io.element.android.features.messages.impl.timeline.components.customreaction.CustomReactionPresenter
+import io.element.android.features.messages.impl.timeline.components.reactionsummary.ReactionSummaryPresenter
 import io.element.android.features.messages.impl.timeline.components.retrysendmenu.RetrySendMenuPresenter
 import io.element.android.features.messages.impl.timeline.model.event.TimelineItemFileContent
 import io.element.android.features.messages.impl.timeline.model.event.TimelineItemImageContent
@@ -45,10 +45,11 @@ import io.element.android.features.messages.media.FakeLocalMediaFactory
 import io.element.android.features.messages.utils.messagesummary.FakeMessageSummaryFormatter
 import io.element.android.features.networkmonitor.test.FakeNetworkMonitor
 import io.element.android.libraries.androidutils.clipboard.FakeClipboardHelper
+import io.element.android.libraries.architecture.Async
 import io.element.android.libraries.core.coroutine.CoroutineDispatchers
-import io.element.android.libraries.core.meta.BuildMeta
-import io.element.android.libraries.core.meta.BuildType
 import io.element.android.libraries.core.mimetype.MimeTypes
+import io.element.android.libraries.designsystem.components.avatar.AvatarData
+import io.element.android.libraries.designsystem.components.avatar.AvatarSize
 import io.element.android.libraries.designsystem.utils.SnackbarDispatcher
 import io.element.android.libraries.featureflag.test.FakeFeatureFlagService
 import io.element.android.libraries.matrix.api.media.MediaSource
@@ -68,6 +69,8 @@ import io.element.android.libraries.mediapickers.test.FakePickerProvider
 import io.element.android.libraries.mediaupload.api.MediaSender
 import io.element.android.libraries.mediaupload.test.FakeMediaPreProcessor
 import io.element.android.libraries.textcomposer.MessageComposerMode
+import io.element.android.tests.testutils.consumeItemsUntilPredicate
+import io.element.android.tests.testutils.consumeItemsUntilTimeout
 import io.element.android.tests.testutils.testCoroutineDispatchers
 import io.mockk.mockk
 import kotlinx.coroutines.test.TestScope
@@ -81,12 +84,19 @@ class MessagesPresenterTest {
     @Test
     fun `present - initial state`() = runTest {
         val presenter = createMessagePresenter()
-        moleculeFlow(RecompositionClock.Immediate) {
+        moleculeFlow(RecompositionMode.Immediate) {
             presenter.present()
         }.test {
-
-            val initialState = awaitItem()
+            val initialState = consumeItemsUntilTimeout().last()
             assertThat(initialState.roomId).isEqualTo(A_ROOM_ID)
+            assertThat(initialState.roomName).isEqualTo(Async.Success(""))
+            assertThat(initialState.roomAvatar).isEqualTo(Async.Success(AvatarData(id = A_ROOM_ID.value, name = "", size = AvatarSize.TimelineRoom)))
+            assertThat(initialState.userHasPermissionToSendMessage).isTrue()
+            assertThat(initialState.userHasPermissionToRedact).isFalse()
+            assertThat(initialState.hasNetworkConnection).isTrue()
+            assertThat(initialState.snackbarMessage).isNull()
+            assertThat(initialState.inviteProgress).isEqualTo(Async.Uninitialized)
+            assertThat(initialState.showReinvitePrompt).isFalse()
         }
     }
 
@@ -95,14 +105,13 @@ class MessagesPresenterTest {
         val coroutineDispatchers = testCoroutineDispatchers(useUnconfinedTestDispatcher = true)
         val room = FakeMatrixRoom()
         val presenter = createMessagePresenter(matrixRoom = room, coroutineDispatchers = coroutineDispatchers)
-        moleculeFlow(RecompositionClock.Immediate) {
+        moleculeFlow(RecompositionMode.Immediate) {
             presenter.present()
         }.test {
-
+            skipItems(1)
             val initialState = awaitItem()
             initialState.eventSink.invoke(MessagesEvents.ToggleReaction("👍", AN_EVENT_ID))
             assertThat(room.myReactions.count()).isEqualTo(1)
-
             // No crashes when sending a reaction failed
             room.givenToggleReactionResult(Result.failure(IllegalStateException("Failed to send reaction")))
             initialState.eventSink.invoke(MessagesEvents.ToggleReaction("👍", AN_EVENT_ID))
@@ -116,10 +125,10 @@ class MessagesPresenterTest {
         val coroutineDispatchers = testCoroutineDispatchers(useUnconfinedTestDispatcher = true)
         val room = FakeMatrixRoom()
         val presenter = createMessagePresenter(matrixRoom = room, coroutineDispatchers = coroutineDispatchers)
-        moleculeFlow(RecompositionClock.Immediate) {
+        moleculeFlow(RecompositionMode.Immediate) {
             presenter.present()
         }.test {
-
+            skipItems(1)
             val initialState = awaitItem()
             initialState.eventSink.invoke(MessagesEvents.ToggleReaction("👍", AN_EVENT_ID))
             assertThat(room.myReactions.count()).isEqualTo(1)
@@ -133,10 +142,9 @@ class MessagesPresenterTest {
     fun `present - handle action forward`() = runTest {
         val navigator = FakeMessagesNavigator()
         val presenter = createMessagePresenter(navigator = navigator)
-        moleculeFlow(RecompositionClock.Immediate) {
+        moleculeFlow(RecompositionMode.Immediate) {
             presenter.present()
         }.test {
-
             val initialState = awaitItem()
             initialState.eventSink.invoke(MessagesEvents.HandleAction(TimelineItemAction.Forward, aMessageEvent()))
             assertThat(awaitItem().actionListState.target).isEqualTo(ActionListState.Target.None)
@@ -149,10 +157,10 @@ class MessagesPresenterTest {
         val clipboardHelper = FakeClipboardHelper()
         val event = aMessageEvent()
         val presenter = createMessagePresenter(clipboardHelper = clipboardHelper)
-        moleculeFlow(RecompositionClock.Immediate) {
+        moleculeFlow(RecompositionMode.Immediate) {
             presenter.present()
         }.test {
-
+            skipItems(1)
             val initialState = awaitItem()
             initialState.eventSink.invoke(MessagesEvents.HandleAction(TimelineItemAction.Copy, event))
             assertThat(awaitItem().actionListState.target).isEqualTo(ActionListState.Target.None)
@@ -163,13 +171,12 @@ class MessagesPresenterTest {
     @Test
     fun `present - handle action reply`() = runTest {
         val presenter = createMessagePresenter()
-        moleculeFlow(RecompositionClock.Immediate) {
+        moleculeFlow(RecompositionMode.Immediate) {
             presenter.present()
         }.test {
-
+            skipItems(1)
             val initialState = awaitItem()
             initialState.eventSink.invoke(MessagesEvents.HandleAction(TimelineItemAction.Reply, aMessageEvent()))
-            
             val finalState = awaitItem()
             assertThat(finalState.composerState.mode).isInstanceOf(MessageComposerMode.Reply::class.java)
             assertThat(awaitItem().actionListState.target).isEqualTo(ActionListState.Target.None)
@@ -179,10 +186,9 @@ class MessagesPresenterTest {
     @Test
     fun `present - handle action reply to an event with no id does nothing`() = runTest {
         val presenter = createMessagePresenter()
-        moleculeFlow(RecompositionClock.Immediate) {
+        moleculeFlow(RecompositionMode.Immediate) {
             presenter.present()
         }.test {
-
             val initialState = awaitItem()
             initialState.eventSink.invoke(MessagesEvents.HandleAction(TimelineItemAction.Reply, aMessageEvent(eventId = null)))
             assertThat(awaitItem().actionListState.target).isEqualTo(ActionListState.Target.None)
@@ -194,10 +200,10 @@ class MessagesPresenterTest {
     @Test
     fun `present - handle action reply to an image media message`() = runTest {
         val presenter = createMessagePresenter()
-        moleculeFlow(RecompositionClock.Immediate) {
+        moleculeFlow(RecompositionMode.Immediate) {
             presenter.present()
         }.test {
-
+            skipItems(1)
             val initialState = awaitItem()
             val mediaMessage = aMessageEvent(
                 content = TimelineItemImageContent(
@@ -214,7 +220,6 @@ class MessagesPresenterTest {
                 )
             )
             initialState.eventSink.invoke(MessagesEvents.HandleAction(TimelineItemAction.Reply, mediaMessage))
-            
             val finalState = awaitItem()
             assertThat(finalState.composerState.mode).isInstanceOf(MessageComposerMode.Reply::class.java)
             val replyMode = finalState.composerState.mode as MessageComposerMode.Reply
@@ -226,10 +231,10 @@ class MessagesPresenterTest {
     @Test
     fun `present - handle action reply to a video media message`() = runTest {
         val presenter = createMessagePresenter()
-        moleculeFlow(RecompositionClock.Immediate) {
+        moleculeFlow(RecompositionMode.Immediate) {
             presenter.present()
         }.test {
-
+            skipItems(1)
             val initialState = awaitItem()
             val mediaMessage = aMessageEvent(
                 content = TimelineItemVideoContent(
@@ -247,7 +252,6 @@ class MessagesPresenterTest {
                 )
             )
             initialState.eventSink.invoke(MessagesEvents.HandleAction(TimelineItemAction.Reply, mediaMessage))
-            
             val finalState = awaitItem()
             assertThat(finalState.composerState.mode).isInstanceOf(MessageComposerMode.Reply::class.java)
             val replyMode = finalState.composerState.mode as MessageComposerMode.Reply
@@ -259,10 +263,10 @@ class MessagesPresenterTest {
     @Test
     fun `present - handle action reply to a file media message`() = runTest {
         val presenter = createMessagePresenter()
-        moleculeFlow(RecompositionClock.Immediate) {
+        moleculeFlow(RecompositionMode.Immediate) {
             presenter.present()
         }.test {
-
+            skipItems(1)
             val initialState = awaitItem()
             val mediaMessage = aMessageEvent(
                 content = TimelineItemFileContent(
@@ -275,7 +279,6 @@ class MessagesPresenterTest {
                 )
             )
             initialState.eventSink.invoke(MessagesEvents.HandleAction(TimelineItemAction.Reply, mediaMessage))
-            
             val finalState = awaitItem()
             assertThat(finalState.composerState.mode).isInstanceOf(MessageComposerMode.Reply::class.java)
             val replyMode = finalState.composerState.mode as MessageComposerMode.Reply
@@ -287,13 +290,12 @@ class MessagesPresenterTest {
     @Test
     fun `present - handle action edit`() = runTest {
         val presenter = createMessagePresenter()
-        moleculeFlow(RecompositionClock.Immediate) {
+        moleculeFlow(RecompositionMode.Immediate) {
             presenter.present()
         }.test {
-
+            skipItems(1)
             val initialState = awaitItem()
             initialState.eventSink.invoke(MessagesEvents.HandleAction(TimelineItemAction.Edit, aMessageEvent()))
-            
             val finalState = awaitItem()
             assertThat(finalState.composerState.mode).isInstanceOf(MessageComposerMode.Edit::class.java)
             assertThat(awaitItem().actionListState.target).isEqualTo(ActionListState.Target.None)
@@ -305,10 +307,10 @@ class MessagesPresenterTest {
         val coroutineDispatchers = testCoroutineDispatchers(useUnconfinedTestDispatcher = true)
         val matrixRoom = FakeMatrixRoom()
         val presenter = createMessagePresenter(matrixRoom = matrixRoom, coroutineDispatchers = coroutineDispatchers)
-        moleculeFlow(RecompositionClock.Immediate) {
+        moleculeFlow(RecompositionMode.Immediate) {
             presenter.present()
         }.test {
-
+            skipItems(1)
             val initialState = awaitItem()
             initialState.eventSink.invoke(MessagesEvents.HandleAction(TimelineItemAction.Redact, aMessageEvent()))
             assertThat(matrixRoom.redactEventEventIdParam).isEqualTo(AN_EVENT_ID)
@@ -320,10 +322,9 @@ class MessagesPresenterTest {
     fun `present - handle action report content`() = runTest {
         val navigator = FakeMessagesNavigator()
         val presenter = createMessagePresenter(navigator = navigator)
-        moleculeFlow(RecompositionClock.Immediate) {
+        moleculeFlow(RecompositionMode.Immediate) {
             presenter.present()
         }.test {
-
             val initialState = awaitItem()
             initialState.eventSink.invoke(MessagesEvents.HandleAction(TimelineItemAction.ReportContent, aMessageEvent()))
             assertThat(awaitItem().actionListState.target).isEqualTo(ActionListState.Target.None)
@@ -334,13 +335,13 @@ class MessagesPresenterTest {
     @Test
     fun `present - handle dismiss action`() = runTest {
         val presenter = createMessagePresenter()
-        moleculeFlow(RecompositionClock.Immediate) {
+        moleculeFlow(RecompositionMode.Immediate) {
             presenter.present()
         }.test {
-
             val initialState = awaitItem()
             initialState.eventSink.invoke(MessagesEvents.Dismiss)
             assertThat(awaitItem().actionListState.target).isEqualTo(ActionListState.Target.None)
+
         }
     }
 
@@ -348,10 +349,9 @@ class MessagesPresenterTest {
     fun `present - handle action show developer info`() = runTest {
         val navigator = FakeMessagesNavigator()
         val presenter = createMessagePresenter(navigator = navigator)
-        moleculeFlow(RecompositionClock.Immediate) {
+        moleculeFlow(RecompositionMode.Immediate) {
             presenter.present()
         }.test {
-
             val initialState = awaitItem()
             initialState.eventSink.invoke(MessagesEvents.HandleAction(TimelineItemAction.Developer, aMessageEvent()))
             assertThat(awaitItem().actionListState.target).isEqualTo(ActionListState.Target.None)
@@ -363,23 +363,24 @@ class MessagesPresenterTest {
     fun `present - shows prompt to reinvite users in DM`() = runTest {
         val room = FakeMatrixRoom(sessionId = A_SESSION_ID, isDirect = true, activeMemberCount = 1L)
         val presenter = createMessagePresenter(matrixRoom = room)
-        moleculeFlow(RecompositionClock.Immediate) {
+        moleculeFlow(RecompositionMode.Immediate) {
             presenter.present()
         }.test {
-
+            skipItems(1)
             val initialState = awaitItem()
-
             // Initially the composer doesn't have focus, so we don't show the alert
             assertThat(initialState.showReinvitePrompt).isFalse()
-
             // When the input field is focused we show the alert
             initialState.composerState.eventSink(MessageComposerEvents.FocusChanged(true))
-            val focusedState = awaitItem()
+            val focusedState = consumeItemsUntilPredicate { state ->
+                state.showReinvitePrompt
+            }.last()
             assertThat(focusedState.showReinvitePrompt).isTrue()
-
             // If it's dismissed then we stop showing the alert
             initialState.eventSink(MessagesEvents.InviteDialogDismissed(InviteDialogAction.Cancel))
-            val dismissedState = awaitItem()
+            val dismissedState = consumeItemsUntilPredicate { state ->
+                !state.showReinvitePrompt
+            }.last()
             assertThat(dismissedState.showReinvitePrompt).isFalse()
         }
     }
@@ -388,13 +389,12 @@ class MessagesPresenterTest {
     fun `present - doesn't show reinvite prompt in non-direct room`() = runTest {
         val room = FakeMatrixRoom(sessionId = A_SESSION_ID, isDirect = false, activeMemberCount = 1L)
         val presenter = createMessagePresenter(matrixRoom = room)
-        moleculeFlow(RecompositionClock.Immediate) {
+        moleculeFlow(RecompositionMode.Immediate) {
             presenter.present()
         }.test {
-            
+            skipItems(1)
             val initialState = awaitItem()
             assertThat(initialState.showReinvitePrompt).isFalse()
-
             initialState.composerState.eventSink(MessageComposerEvents.FocusChanged(true))
             val focusedState = awaitItem()
             assertThat(focusedState.showReinvitePrompt).isFalse()
@@ -405,13 +405,12 @@ class MessagesPresenterTest {
     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 presenter = createMessagePresenter(matrixRoom = room)
-        moleculeFlow(RecompositionClock.Immediate) {
+        moleculeFlow(RecompositionMode.Immediate) {
             presenter.present()
         }.test {
-            
+            skipItems(1)
             val initialState = awaitItem()
             assertThat(initialState.showReinvitePrompt).isFalse()
-
             initialState.composerState.eventSink(MessageComposerEvents.FocusChanged(true))
             val focusedState = awaitItem()
             assertThat(focusedState.showReinvitePrompt).isFalse()
@@ -430,17 +429,14 @@ class MessagesPresenterTest {
             )
         )
         val presenter = createMessagePresenter(matrixRoom = room)
-        moleculeFlow(RecompositionClock.Immediate) {
+        moleculeFlow(RecompositionMode.Immediate) {
             presenter.present()
         }.test {
-            val initialState = awaitItem()
-            skipItems(1)
+            val initialState = consumeItemsUntilTimeout().last()
             initialState.eventSink(MessagesEvents.InviteDialogDismissed(InviteDialogAction.Invite))
-            
             skipItems(1)
             val loadingState = awaitItem()
             assertThat(loadingState.inviteProgress.isLoading()).isTrue()
-
             val newState = awaitItem()
             assertThat(newState.inviteProgress.isSuccess()).isTrue()
             assertThat(room.invitedUserId).isEqualTo(A_SESSION_ID_2)
@@ -460,17 +456,14 @@ class MessagesPresenterTest {
             )
         )
         val presenter = createMessagePresenter(matrixRoom = room)
-        moleculeFlow(RecompositionClock.Immediate) {
+        moleculeFlow(RecompositionMode.Immediate) {
             presenter.present()
         }.test {
-            val initialState = awaitItem()
-            skipItems(1)
+            val initialState = consumeItemsUntilTimeout().last()
             initialState.eventSink(MessagesEvents.InviteDialogDismissed(InviteDialogAction.Invite))
-            
             skipItems(1)
             val loadingState = awaitItem()
             assertThat(loadingState.inviteProgress.isLoading()).isTrue()
-
             val newState = awaitItem()
             assertThat(newState.inviteProgress.isSuccess()).isTrue()
             assertThat(room.invitedUserId).isEqualTo(A_SESSION_ID_2)
@@ -482,17 +475,14 @@ class MessagesPresenterTest {
         val room = FakeMatrixRoom(sessionId = A_SESSION_ID)
         room.givenRoomMembersState(MatrixRoomMembersState.Unknown)
         val presenter = createMessagePresenter(matrixRoom = room)
-        moleculeFlow(RecompositionClock.Immediate) {
+        moleculeFlow(RecompositionMode.Immediate) {
             presenter.present()
         }.test {
-            val initialState = awaitItem()
-            skipItems(1)
+            val initialState = consumeItemsUntilTimeout().last()
             initialState.eventSink(MessagesEvents.InviteDialogDismissed(InviteDialogAction.Invite))
-            
             skipItems(1)
             val loadingState = awaitItem()
             assertThat(loadingState.inviteProgress.isLoading()).isTrue()
-
             val newState = awaitItem()
             assertThat(newState.inviteProgress.isFailure()).isTrue()
         }
@@ -511,18 +501,19 @@ class MessagesPresenterTest {
         )
         room.givenInviteUserResult(Result.failure(Throwable("Oops!")))
         val presenter = createMessagePresenter(matrixRoom = room)
-        moleculeFlow(RecompositionClock.Immediate) {
+        moleculeFlow(RecompositionMode.Immediate) {
             presenter.present()
         }.test {
-            val initialState = awaitItem()
-            skipItems(1)
+            val initialState = consumeItemsUntilTimeout().last()
             initialState.eventSink(MessagesEvents.InviteDialogDismissed(InviteDialogAction.Invite))
-            skipItems(1)
-            val loadingState = awaitItem()
+            val loadingState = consumeItemsUntilPredicate { state ->
+                state.inviteProgress.isLoading()
+            }.last()
             assertThat(loadingState.inviteProgress.isLoading()).isTrue()
-
-            val newState = awaitItem()
-            assertThat(newState.inviteProgress.isFailure()).isTrue()
+            val failureState = consumeItemsUntilPredicate { state ->
+                state.inviteProgress.isFailure()
+            }.last()
+            assertThat(failureState.inviteProgress.isFailure()).isTrue()
         }
     }
 
@@ -531,10 +522,10 @@ class MessagesPresenterTest {
         val matrixRoom = FakeMatrixRoom()
         matrixRoom.givenCanSendEventResult(MessageEventType.ROOM_MESSAGE, Result.success(true))
         val presenter = createMessagePresenter(matrixRoom = matrixRoom)
-        moleculeFlow(RecompositionClock.Immediate) {
+        moleculeFlow(RecompositionMode.Immediate) {
             presenter.present()
         }.test {
-            
+            skipItems(1)
             assertThat(awaitItem().userHasPermissionToSendMessage).isTrue()
         }
     }
@@ -544,13 +535,27 @@ class MessagesPresenterTest {
         val matrixRoom = FakeMatrixRoom()
         matrixRoom.givenCanSendEventResult(MessageEventType.ROOM_MESSAGE, Result.success(false))
         val presenter = createMessagePresenter(matrixRoom = matrixRoom)
-        moleculeFlow(RecompositionClock.Immediate) {
+        moleculeFlow(RecompositionMode.Immediate) {
             presenter.present()
         }.test {
             // Default value
             assertThat(awaitItem().userHasPermissionToSendMessage).isTrue()
             skipItems(1)
             assertThat(awaitItem().userHasPermissionToSendMessage).isFalse()
+            cancelAndIgnoreRemainingEvents()
+        }
+    }
+
+    @Test
+    fun `present - permission to redact`() = runTest {
+        val matrixRoom = FakeMatrixRoom(canRedact = true)
+        val presenter = createMessagePresenter(matrixRoom = matrixRoom)
+        moleculeFlow(RecompositionMode.Immediate) {
+            presenter.present()
+        }.test {
+            val initialState = consumeItemsUntilPredicate { it.userHasPermissionToRedact }.last()
+            assertThat(initialState.userHasPermissionToRedact).isTrue()
+            cancelAndIgnoreRemainingEvents()
         }
     }
 
@@ -580,6 +585,7 @@ class MessagesPresenterTest {
         val buildMeta = aBuildMeta()
         val actionListPresenter = ActionListPresenter(buildMeta = buildMeta)
         val customReactionPresenter = CustomReactionPresenter()
+        val reactionSummaryPresenter = ReactionSummaryPresenter(room = matrixRoom)
         val retrySendMenuPresenter = RetrySendMenuPresenter(room = matrixRoom)
         return MessagesPresenter(
             room = matrixRoom,
@@ -587,6 +593,7 @@ class MessagesPresenterTest {
             timelinePresenter = timelinePresenter,
             actionListPresenter = actionListPresenter,
             customReactionPresenter = customReactionPresenter,
+            reactionSummaryPresenter = reactionSummaryPresenter,
             retrySendMenuPresenter = retrySendMenuPresenter,
             networkMonitor = FakeNetworkMonitor(),
             snackbarDispatcher = SnackbarDispatcher(),
diff --git a/features/messages/impl/src/test/kotlin/io/element/android/features/messages/actionlist/ActionListPresenterTest.kt b/features/messages/impl/src/test/kotlin/io/element/android/features/messages/actionlist/ActionListPresenterTest.kt
index 0aafa68100..afef9f6730 100644
--- a/features/messages/impl/src/test/kotlin/io/element/android/features/messages/actionlist/ActionListPresenterTest.kt
+++ b/features/messages/impl/src/test/kotlin/io/element/android/features/messages/actionlist/ActionListPresenterTest.kt
@@ -16,7 +16,7 @@
 
 package io.element.android.features.messages.actionlist
 
-import app.cash.molecule.RecompositionClock
+import app.cash.molecule.RecompositionMode
 import app.cash.molecule.moleculeFlow
 import app.cash.turbine.test
 import com.google.common.truth.Truth.assertThat
@@ -30,7 +30,6 @@ import io.element.android.features.messages.impl.timeline.model.event.TimelineIt
 import io.element.android.features.messages.impl.timeline.model.event.TimelineItemTextContent
 import io.element.android.features.messages.impl.timeline.model.event.aTimelineItemImageContent
 import io.element.android.features.messages.impl.timeline.model.event.aTimelineItemStateEventContent
-import io.element.android.libraries.matrix.api.timeline.item.event.LocalEventSendState
 import io.element.android.libraries.matrix.test.A_MESSAGE
 import io.element.android.libraries.matrix.test.core.aBuildMeta
 import kotlinx.collections.immutable.persistentListOf
@@ -41,7 +40,7 @@ class ActionListPresenterTest {
     @Test
     fun `present - initial state`() = runTest {
         val presenter = anActionListPresenter(isBuildDebuggable = true)
-        moleculeFlow(RecompositionClock.Immediate) {
+        moleculeFlow(RecompositionMode.Immediate) {
             presenter.present()
         }.test {
             val initialState = awaitItem()
@@ -52,12 +51,12 @@ class ActionListPresenterTest {
     @Test
     fun `present - compute for message from me redacted`() = runTest {
         val presenter = anActionListPresenter(isBuildDebuggable = true)
-        moleculeFlow(RecompositionClock.Immediate) {
+        moleculeFlow(RecompositionMode.Immediate) {
             presenter.present()
         }.test {
             val initialState = awaitItem()
             val messageEvent = aMessageEvent(isMine = true, content = TimelineItemRedactedContent)
-            initialState.eventSink.invoke(ActionListEvents.ComputeForMessage(messageEvent))
+            initialState.eventSink.invoke(ActionListEvents.ComputeForMessage(messageEvent, false))
             // val loadingState = awaitItem()
             // assertThat(loadingState.target).isEqualTo(ActionListState.Target.Loading(messageEvent))
             val successState = awaitItem()
@@ -77,12 +76,12 @@ class ActionListPresenterTest {
     @Test
     fun `present - compute for message from others redacted`() = runTest {
         val presenter = anActionListPresenter(isBuildDebuggable = true)
-        moleculeFlow(RecompositionClock.Immediate) {
+        moleculeFlow(RecompositionMode.Immediate) {
             presenter.present()
         }.test {
             val initialState = awaitItem()
             val messageEvent = aMessageEvent(isMine = false, content = TimelineItemRedactedContent)
-            initialState.eventSink.invoke(ActionListEvents.ComputeForMessage(messageEvent))
+            initialState.eventSink.invoke(ActionListEvents.ComputeForMessage(messageEvent, false))
             // val loadingState = awaitItem()
             // assertThat(loadingState.target).isEqualTo(ActionListState.Target.Loading(messageEvent))
             val successState = awaitItem()
@@ -102,7 +101,7 @@ class ActionListPresenterTest {
     @Test
     fun `present - compute for others message`() = runTest {
         val presenter = anActionListPresenter(isBuildDebuggable = true)
-        moleculeFlow(RecompositionClock.Immediate) {
+        moleculeFlow(RecompositionMode.Immediate) {
             presenter.present()
         }.test {
             val initialState = awaitItem()
@@ -110,7 +109,7 @@ class ActionListPresenterTest {
                 isMine = false,
                 content = TimelineItemTextContent(body = A_MESSAGE, htmlDocument = null, isEdited = false)
             )
-            initialState.eventSink.invoke(ActionListEvents.ComputeForMessage(messageEvent))
+            initialState.eventSink.invoke(ActionListEvents.ComputeForMessage(messageEvent, false))
             // val loadingState = awaitItem()
             // assertThat(loadingState.target).isEqualTo(ActionListState.Target.Loading(messageEvent))
             val successState = awaitItem()
@@ -131,10 +130,41 @@ class ActionListPresenterTest {
         }
     }
 
+    @Test
+    fun `present - compute for others message and can redact`() = runTest {
+        val presenter = anActionListPresenter(isBuildDebuggable = true)
+        moleculeFlow(RecompositionMode.Immediate) {
+            presenter.present()
+        }.test {
+            val initialState = awaitItem()
+            val messageEvent = aMessageEvent(
+                isMine = false,
+                content = TimelineItemTextContent(body = A_MESSAGE, htmlDocument = null, isEdited = false)
+            )
+            initialState.eventSink.invoke(ActionListEvents.ComputeForMessage(messageEvent, true))
+            val successState = awaitItem()
+            assertThat(successState.target).isEqualTo(
+                ActionListState.Target.Success(
+                    messageEvent,
+                    persistentListOf(
+                        TimelineItemAction.Reply,
+                        TimelineItemAction.Forward,
+                        TimelineItemAction.Copy,
+                        TimelineItemAction.Developer,
+                        TimelineItemAction.ReportContent,
+                        TimelineItemAction.Redact,
+                    )
+                )
+            )
+            initialState.eventSink.invoke(ActionListEvents.Clear)
+            assertThat(awaitItem().target).isEqualTo(ActionListState.Target.None)
+        }
+    }
+
     @Test
     fun `present - compute for my message`() = runTest {
         val presenter = anActionListPresenter(isBuildDebuggable = true)
-        moleculeFlow(RecompositionClock.Immediate) {
+        moleculeFlow(RecompositionMode.Immediate) {
             presenter.present()
         }.test {
             val initialState = awaitItem()
@@ -142,7 +172,7 @@ class ActionListPresenterTest {
                 isMine = true,
                 content = TimelineItemTextContent(body = A_MESSAGE, htmlDocument = null, isEdited = false)
             )
-            initialState.eventSink.invoke(ActionListEvents.ComputeForMessage(messageEvent))
+            initialState.eventSink.invoke(ActionListEvents.ComputeForMessage(messageEvent, false))
             // val loadingState = awaitItem()
             // assertThat(loadingState.target).isEqualTo(ActionListState.Target.Loading(messageEvent))
             val successState = awaitItem()
@@ -167,7 +197,7 @@ class ActionListPresenterTest {
     @Test
     fun `present - compute for a media item`() = runTest {
         val presenter = anActionListPresenter(isBuildDebuggable = true)
-        moleculeFlow(RecompositionClock.Immediate) {
+        moleculeFlow(RecompositionMode.Immediate) {
             presenter.present()
         }.test {
             val initialState = awaitItem()
@@ -175,7 +205,7 @@ class ActionListPresenterTest {
                 isMine = true,
                 content = aTimelineItemImageContent(),
             )
-            initialState.eventSink.invoke(ActionListEvents.ComputeForMessage(messageEvent))
+            initialState.eventSink.invoke(ActionListEvents.ComputeForMessage(messageEvent, false))
             // val loadingState = awaitItem()
             // assertThat(loadingState.target).isEqualTo(ActionListState.Target.Loading(messageEvent))
             val successState = awaitItem()
@@ -198,7 +228,7 @@ class ActionListPresenterTest {
     @Test
     fun `present - compute for a state item in debug build`() = runTest {
         val presenter = anActionListPresenter(isBuildDebuggable = true)
-        moleculeFlow(RecompositionClock.Immediate) {
+        moleculeFlow(RecompositionMode.Immediate) {
             presenter.present()
         }.test {
             val initialState = awaitItem()
@@ -206,7 +236,7 @@ class ActionListPresenterTest {
                 isMine = true,
                 content = aTimelineItemStateEventContent(),
             )
-            initialState.eventSink.invoke(ActionListEvents.ComputeForMessage(stateEvent))
+            initialState.eventSink.invoke(ActionListEvents.ComputeForMessage(stateEvent, false))
             // val loadingState = awaitItem()
             // assertThat(loadingState.target).isEqualTo(ActionListState.Target.Loading(messageEvent))
             val successState = awaitItem()
@@ -227,7 +257,7 @@ class ActionListPresenterTest {
     @Test
     fun `present - compute for a state item in non-debuggable build`() = runTest {
         val presenter = anActionListPresenter(isBuildDebuggable = false)
-        moleculeFlow(RecompositionClock.Immediate) {
+        moleculeFlow(RecompositionMode.Immediate) {
             presenter.present()
         }.test {
             val initialState = awaitItem()
@@ -235,7 +265,7 @@ class ActionListPresenterTest {
                 isMine = true,
                 content = aTimelineItemStateEventContent(),
             )
-            initialState.eventSink.invoke(ActionListEvents.ComputeForMessage(stateEvent))
+            initialState.eventSink.invoke(ActionListEvents.ComputeForMessage(stateEvent, false))
             // val loadingState = awaitItem()
             // assertThat(loadingState.target).isEqualTo(ActionListState.Target.Loading(messageEvent))
             val successState = awaitItem()
@@ -255,7 +285,7 @@ class ActionListPresenterTest {
     @Test
     fun `present - compute message in non-debuggable build`() = runTest {
         val presenter = anActionListPresenter(isBuildDebuggable = false)
-        moleculeFlow(RecompositionClock.Immediate) {
+        moleculeFlow(RecompositionMode.Immediate) {
             presenter.present()
         }.test {
             val initialState = awaitItem()
@@ -263,7 +293,7 @@ class ActionListPresenterTest {
                 isMine = true,
                 content = TimelineItemTextContent(body = A_MESSAGE, htmlDocument = null, isEdited = false)
             )
-            initialState.eventSink.invoke(ActionListEvents.ComputeForMessage(messageEvent))
+            initialState.eventSink.invoke(ActionListEvents.ComputeForMessage(messageEvent, false))
             // val loadingState = awaitItem()
             // assertThat(loadingState.target).isEqualTo(ActionListState.Target.Loading(messageEvent))
             val successState = awaitItem()
@@ -287,7 +317,7 @@ class ActionListPresenterTest {
     @Test
     fun `present - compute message with no actions`() = runTest {
         val presenter = anActionListPresenter(isBuildDebuggable = false)
-        moleculeFlow(RecompositionClock.Immediate) {
+        moleculeFlow(RecompositionMode.Immediate) {
             presenter.present()
         }.test {
             val initialState = awaitItem()
@@ -300,10 +330,10 @@ class ActionListPresenterTest {
                 content = TimelineItemRedactedContent,
             )
 
-            initialState.eventSink.invoke(ActionListEvents.ComputeForMessage(messageEvent))
+            initialState.eventSink.invoke(ActionListEvents.ComputeForMessage(messageEvent, false))
             assertThat(awaitItem().target).isInstanceOf(ActionListState.Target.Success::class.java)
 
-            initialState.eventSink.invoke(ActionListEvents.ComputeForMessage(redactedEvent))
+            initialState.eventSink.invoke(ActionListEvents.ComputeForMessage(redactedEvent, false))
             awaitItem().run {
                 assertThat(target).isEqualTo(ActionListState.Target.None)
                 assertThat(displayEmojiReactions).isFalse()
@@ -314,7 +344,7 @@ class ActionListPresenterTest {
     @Test
     fun `present - compute not sent message`() = runTest {
         val presenter = anActionListPresenter(isBuildDebuggable = false)
-        moleculeFlow(RecompositionClock.Immediate) {
+        moleculeFlow(RecompositionMode.Immediate) {
             presenter.present()
         }.test {
             val initialState = awaitItem()
@@ -324,7 +354,7 @@ class ActionListPresenterTest {
                 content = TimelineItemTextContent(body = A_MESSAGE, htmlDocument = null, isEdited = false),
             )
 
-            initialState.eventSink.invoke(ActionListEvents.ComputeForMessage(messageEvent))
+            initialState.eventSink.invoke(ActionListEvents.ComputeForMessage(messageEvent, false))
             val successState = awaitItem()
             assertThat(successState.target).isEqualTo(
                 ActionListState.Target.Success(
diff --git a/features/messages/impl/src/test/kotlin/io/element/android/features/messages/attachments/AttachmentsPreviewPresenterTest.kt b/features/messages/impl/src/test/kotlin/io/element/android/features/messages/attachments/AttachmentsPreviewPresenterTest.kt
index db202569ee..fb8b3b1948 100644
--- a/features/messages/impl/src/test/kotlin/io/element/android/features/messages/attachments/AttachmentsPreviewPresenterTest.kt
+++ b/features/messages/impl/src/test/kotlin/io/element/android/features/messages/attachments/AttachmentsPreviewPresenterTest.kt
@@ -19,7 +19,7 @@
 package io.element.android.features.messages.attachments
 
 import android.net.Uri
-import app.cash.molecule.RecompositionClock
+import app.cash.molecule.RecompositionMode
 import app.cash.molecule.moleculeFlow
 import app.cash.turbine.test
 import com.google.common.truth.Truth.assertThat
@@ -55,7 +55,7 @@ class AttachmentsPreviewPresenterTest {
             )
         )
         val presenter = anAttachmentsPreviewPresenter(room = room)
-        moleculeFlow(RecompositionClock.Immediate) {
+        moleculeFlow(RecompositionMode.Immediate) {
             presenter.present()
         }.test {
             val initialState = awaitItem()
@@ -77,7 +77,7 @@ class AttachmentsPreviewPresenterTest {
         val failure = MediaPreProcessor.Failure(null)
         room.givenSendMediaResult(Result.failure(failure))
         val presenter = anAttachmentsPreviewPresenter(room = room)
-        moleculeFlow(RecompositionClock.Immediate) {
+        moleculeFlow(RecompositionMode.Immediate) {
             presenter.present()
         }.test {
             val initialState = awaitItem()
@@ -86,7 +86,7 @@ class AttachmentsPreviewPresenterTest {
             val loadingState = awaitItem()
             assertThat(loadingState.sendActionState).isEqualTo(SendActionState.Sending.Processing)
             val failureState = awaitItem()
-            assertThat(failureState.sendActionState).isEqualTo((SendActionState.Failure(failure)))
+            assertThat(failureState.sendActionState).isEqualTo(SendActionState.Failure(failure))
             assertThat(room.sendMediaCount).isEqualTo(0)
             failureState.eventSink(AttachmentsPreviewEvents.ClearSendState)
             val clearedState = awaitItem()
diff --git a/features/messages/impl/src/test/kotlin/io/element/android/features/messages/fixtures/media.kt b/features/messages/impl/src/test/kotlin/io/element/android/features/messages/fixtures/media.kt
index 1357c05913..00701c0a75 100644
--- a/features/messages/impl/src/test/kotlin/io/element/android/features/messages/fixtures/media.kt
+++ b/features/messages/impl/src/test/kotlin/io/element/android/features/messages/fixtures/media.kt
@@ -21,7 +21,6 @@ import io.element.android.features.messages.impl.attachments.Attachment
 import io.element.android.features.messages.impl.media.local.LocalMedia
 import io.element.android.features.messages.impl.media.local.MediaInfo
 import io.element.android.features.messages.impl.media.local.anImageInfo
-import io.element.android.libraries.core.mimetype.MimeTypes
 
 fun aLocalMedia(
     uri: Uri,
diff --git a/features/messages/impl/src/test/kotlin/io/element/android/features/messages/fixtures/timelineItemsFactory.kt b/features/messages/impl/src/test/kotlin/io/element/android/features/messages/fixtures/timelineItemsFactory.kt
index 638c5e0556..3b1a38e16f 100644
--- a/features/messages/impl/src/test/kotlin/io/element/android/features/messages/fixtures/timelineItemsFactory.kt
+++ b/features/messages/impl/src/test/kotlin/io/element/android/features/messages/fixtures/timelineItemsFactory.kt
@@ -21,6 +21,8 @@ import io.element.android.features.messages.impl.timeline.factories.event.Timeli
 import io.element.android.features.messages.impl.timeline.factories.event.TimelineItemContentFailedToParseMessageFactory
 import io.element.android.features.messages.impl.timeline.factories.event.TimelineItemContentFailedToParseStateFactory
 import io.element.android.features.messages.impl.timeline.factories.event.TimelineItemContentMessageFactory
+import io.element.android.features.messages.impl.timeline.factories.event.TimelineItemContentPollEndFactory
+import io.element.android.features.messages.impl.timeline.factories.event.TimelineItemContentPollFactory
 import io.element.android.features.messages.impl.timeline.factories.event.TimelineItemContentProfileChangeFactory
 import io.element.android.features.messages.impl.timeline.factories.event.TimelineItemContentRedactedFactory
 import io.element.android.features.messages.impl.timeline.factories.event.TimelineItemContentRoomMembershipFactory
@@ -42,6 +44,7 @@ import kotlinx.coroutines.test.TestScope
 
 internal fun TestScope.aTimelineItemsFactory(): TimelineItemsFactory {
     val timelineEventFormatter = aTimelineEventFormatter()
+    val matrixClient = FakeMatrixClient()
     return TimelineItemsFactory(
         dispatchers = testCoroutineDispatchers(),
         eventItemFactory = TimelineItemEventFactory(
@@ -49,6 +52,8 @@ internal fun TestScope.aTimelineItemsFactory(): TimelineItemsFactory {
                 messageFactory = TimelineItemContentMessageFactory(FakeFileSizeFormatter(), FileExtensionExtractorWithoutValidation()),
                 redactedMessageFactory = TimelineItemContentRedactedFactory(),
                 stickerFactory = TimelineItemContentStickerFactory(),
+                pollFactory = TimelineItemContentPollFactory(matrixClient),
+                pollEndFactory = TimelineItemContentPollEndFactory(),
                 utdFactory = TimelineItemContentUTDFactory(),
                 roomMembershipFactory = TimelineItemContentRoomMembershipFactory(timelineEventFormatter),
                 profileChangeFactory = TimelineItemContentProfileChangeFactory(timelineEventFormatter),
@@ -56,7 +61,7 @@ internal fun TestScope.aTimelineItemsFactory(): TimelineItemsFactory {
                 failedToParseMessageFactory = TimelineItemContentFailedToParseMessageFactory(),
                 failedToParseStateFactory = TimelineItemContentFailedToParseStateFactory()
             ),
-            matrixClient = FakeMatrixClient(),
+            matrixClient = matrixClient,
         ),
         virtualItemFactory = TimelineItemVirtualFactory(
             daySeparatorFactory = TimelineItemDaySeparatorFactory(
diff --git a/features/messages/impl/src/test/kotlin/io/element/android/features/messages/forward/ForwardMessagesPresenterTests.kt b/features/messages/impl/src/test/kotlin/io/element/android/features/messages/forward/ForwardMessagesPresenterTests.kt
index 502305ab1d..983b251df7 100644
--- a/features/messages/impl/src/test/kotlin/io/element/android/features/messages/forward/ForwardMessagesPresenterTests.kt
+++ b/features/messages/impl/src/test/kotlin/io/element/android/features/messages/forward/ForwardMessagesPresenterTests.kt
@@ -16,7 +16,7 @@
 
 package io.element.android.features.messages.forward
 
-import app.cash.molecule.RecompositionClock
+import app.cash.molecule.RecompositionMode
 import app.cash.molecule.moleculeFlow
 import app.cash.turbine.test
 import com.google.common.truth.Truth.assertThat
@@ -24,12 +24,12 @@ import io.element.android.features.messages.impl.forward.ForwardMessagesEvents
 import io.element.android.features.messages.impl.forward.ForwardMessagesPresenter
 import io.element.android.libraries.designsystem.theme.components.SearchBarResultState
 import io.element.android.libraries.matrix.api.core.EventId
-import io.element.android.libraries.matrix.api.room.RoomSummary
+import io.element.android.libraries.matrix.api.roomlist.RoomSummary
 import io.element.android.libraries.matrix.test.AN_EVENT_ID
 import io.element.android.libraries.matrix.test.FakeMatrixClient
 import io.element.android.libraries.matrix.test.room.FakeMatrixRoom
-import io.element.android.libraries.matrix.test.room.FakeRoomSummaryDataSource
 import io.element.android.libraries.matrix.test.room.aRoomSummaryDetail
+import io.element.android.libraries.matrix.test.roomlist.FakeRoomListService
 import kotlinx.collections.immutable.persistentListOf
 import kotlinx.coroutines.CoroutineScope
 import kotlinx.coroutines.test.runTest
@@ -40,7 +40,7 @@ class ForwardMessagesPresenterTests {
     @Test
     fun `present - initial state`() = runTest {
         val presenter = aPresenter()
-        moleculeFlow(RecompositionClock.Immediate) {
+        moleculeFlow(RecompositionMode.Immediate) {
             presenter.present()
         }.test {
             val initialState = awaitItem()
@@ -60,7 +60,7 @@ class ForwardMessagesPresenterTests {
     @Test
     fun `present - toggle search active`() = runTest {
         val presenter = aPresenter()
-        moleculeFlow(RecompositionClock.Immediate) {
+        moleculeFlow(RecompositionMode.Immediate) {
             presenter.present()
         }.test {
             val initialState = awaitItem()
@@ -76,12 +76,12 @@ class ForwardMessagesPresenterTests {
 
     @Test
     fun `present - update query`() = runTest {
-        val roomSummaryDataSource = FakeRoomSummaryDataSource().apply {
+        val roomListService = FakeRoomListService().apply {
             postAllRooms(listOf(RoomSummary.Filled(aRoomSummaryDetail())))
         }
-        val client = FakeMatrixClient(roomSummaryDataSource = roomSummaryDataSource)
+        val client = FakeMatrixClient(roomListService = roomListService)
         val presenter = aPresenter(client = client)
-        moleculeFlow(RecompositionClock.Immediate) {
+        moleculeFlow(RecompositionMode.Immediate) {
             presenter.present()
         }.test {
             val initialState = awaitItem()
@@ -96,7 +96,7 @@ class ForwardMessagesPresenterTests {
     @Test
     fun `present - select a room and forward successful`() = runTest {
         val presenter = aPresenter()
-        moleculeFlow(RecompositionClock.Immediate) {
+        moleculeFlow(RecompositionMode.Immediate) {
             presenter.present()
         }.test {
             val initialState = awaitItem()
@@ -123,7 +123,7 @@ class ForwardMessagesPresenterTests {
     fun `present - select a room and forward failed, then clear`() = runTest {
         val room = FakeMatrixRoom()
         val presenter = aPresenter(fakeMatrixRoom = room)
-        moleculeFlow(RecompositionClock.Immediate) {
+        moleculeFlow(RecompositionMode.Immediate) {
             presenter.present()
         }.test {
             val initialState = awaitItem()
@@ -151,7 +151,7 @@ class ForwardMessagesPresenterTests {
     @Test
     fun `present - select and remove a room`() = runTest {
         val presenter = aPresenter()
-        moleculeFlow(RecompositionClock.Immediate) {
+        moleculeFlow(RecompositionMode.Immediate) {
             presenter.present()
         }.test {
             val initialState = awaitItem()
@@ -166,11 +166,10 @@ class ForwardMessagesPresenterTests {
         }
     }
 
-        private fun CoroutineScope.aPresenter(
+    private fun CoroutineScope.aPresenter(
         eventId: EventId = AN_EVENT_ID,
         fakeMatrixRoom: FakeMatrixRoom = FakeMatrixRoom(),
         coroutineScope: CoroutineScope = this,
         client: FakeMatrixClient = FakeMatrixClient(),
     ) = ForwardMessagesPresenter(eventId.value, fakeMatrixRoom, coroutineScope, client)
-
 }
diff --git a/features/messages/impl/src/test/kotlin/io/element/android/features/messages/media/viewer/MediaViewerPresenterTest.kt b/features/messages/impl/src/test/kotlin/io/element/android/features/messages/media/viewer/MediaViewerPresenterTest.kt
index 2b66d2cf9b..3c31fa49d3 100644
--- a/features/messages/impl/src/test/kotlin/io/element/android/features/messages/media/viewer/MediaViewerPresenterTest.kt
+++ b/features/messages/impl/src/test/kotlin/io/element/android/features/messages/media/viewer/MediaViewerPresenterTest.kt
@@ -19,7 +19,7 @@
 package io.element.android.features.messages.media.viewer
 
 import android.net.Uri
-import app.cash.molecule.RecompositionClock
+import app.cash.molecule.RecompositionMode
 import app.cash.molecule.moleculeFlow
 import app.cash.turbine.test
 import com.google.common.truth.Truth.assertThat
@@ -50,7 +50,7 @@ class MediaViewerPresenterTest {
         val mediaLoader = FakeMediaLoader()
         val mediaActions = FakeLocalMediaActions()
         val presenter = aMediaViewerPresenter(mediaLoader, mediaActions)
-        moleculeFlow(RecompositionClock.Immediate) {
+        moleculeFlow(RecompositionMode.Immediate) {
             presenter.present()
         }.test {
             var state = awaitItem()
@@ -71,7 +71,7 @@ class MediaViewerPresenterTest {
         val mediaActions = FakeLocalMediaActions()
         val snackbarDispatcher = SnackbarDispatcher()
         val presenter = aMediaViewerPresenter(mediaLoader, mediaActions, snackbarDispatcher)
-        moleculeFlow(RecompositionClock.Immediate) {
+        moleculeFlow(RecompositionMode.Immediate) {
             presenter.present()
         }.test {
             var state = awaitItem()
@@ -117,7 +117,7 @@ class MediaViewerPresenterTest {
         val mediaLoader = FakeMediaLoader()
         val mediaActions = FakeLocalMediaActions()
         val presenter = aMediaViewerPresenter(mediaLoader, mediaActions)
-        moleculeFlow(RecompositionClock.Immediate) {
+        moleculeFlow(RecompositionMode.Immediate) {
             presenter.present()
         }.test {
             mediaLoader.shouldFail = true
diff --git a/features/messages/impl/src/test/kotlin/io/element/android/features/messages/report/ReportMessagePresenterTests.kt b/features/messages/impl/src/test/kotlin/io/element/android/features/messages/report/ReportMessagePresenterTests.kt
index 090dd36dbe..e6b0dee0c9 100644
--- a/features/messages/impl/src/test/kotlin/io/element/android/features/messages/report/ReportMessagePresenterTests.kt
+++ b/features/messages/impl/src/test/kotlin/io/element/android/features/messages/report/ReportMessagePresenterTests.kt
@@ -16,7 +16,7 @@
 
 package io.element.android.features.messages.report
 
-import app.cash.molecule.RecompositionClock
+import app.cash.molecule.RecompositionMode
 import app.cash.molecule.moleculeFlow
 import app.cash.turbine.test
 import com.google.common.truth.Truth.assertThat
@@ -36,7 +36,7 @@ class ReportMessagePresenterTests {
     @Test
     fun `presenter - initial state`() = runTest {
         val presenter = aPresenter()
-        moleculeFlow(RecompositionClock.Immediate) {
+        moleculeFlow(RecompositionMode.Immediate) {
             presenter.present()
         }.test {
             val initialState = awaitItem()
@@ -49,7 +49,7 @@ class ReportMessagePresenterTests {
     @Test
     fun `presenter - update reason`() = runTest {
         val presenter = aPresenter()
-        moleculeFlow(RecompositionClock.Immediate) {
+        moleculeFlow(RecompositionMode.Immediate) {
             presenter.present()
         }.test {
             val initialState = awaitItem()
@@ -63,7 +63,7 @@ class ReportMessagePresenterTests {
     @Test
     fun `presenter - toggle block user`() = runTest {
         val presenter = aPresenter()
-        moleculeFlow(RecompositionClock.Immediate) {
+        moleculeFlow(RecompositionMode.Immediate) {
             presenter.present()
         }.test {
             val initialState = awaitItem()
@@ -81,7 +81,7 @@ class ReportMessagePresenterTests {
     fun `presenter - handle successful report and block user`() = runTest {
         val room = FakeMatrixRoom()
         val presenter = aPresenter(matrixRoom = room)
-        moleculeFlow(RecompositionClock.Immediate) {
+        moleculeFlow(RecompositionMode.Immediate) {
             presenter.present()
         }.test {
             val initialState = awaitItem()
@@ -98,7 +98,7 @@ class ReportMessagePresenterTests {
     fun `presenter - handle successful report`() = runTest {
         val room = FakeMatrixRoom()
         val presenter = aPresenter(matrixRoom = room)
-        moleculeFlow(RecompositionClock.Immediate) {
+        moleculeFlow(RecompositionMode.Immediate) {
             presenter.present()
         }.test {
             val initialState = awaitItem()
@@ -115,7 +115,7 @@ class ReportMessagePresenterTests {
             givenReportContentResult(Result.failure(Exception("Failed to report content")))
         }
         val presenter = aPresenter(matrixRoom = room)
-        moleculeFlow(RecompositionClock.Immediate) {
+        moleculeFlow(RecompositionMode.Immediate) {
             presenter.present()
         }.test {
             val initialState = awaitItem()
diff --git a/features/messages/impl/src/test/kotlin/io/element/android/features/messages/textcomposer/MessageComposerPresenterTest.kt b/features/messages/impl/src/test/kotlin/io/element/android/features/messages/textcomposer/MessageComposerPresenterTest.kt
index d3fda7b881..5c75c963e5 100644
--- a/features/messages/impl/src/test/kotlin/io/element/android/features/messages/textcomposer/MessageComposerPresenterTest.kt
+++ b/features/messages/impl/src/test/kotlin/io/element/android/features/messages/textcomposer/MessageComposerPresenterTest.kt
@@ -19,7 +19,7 @@
 package io.element.android.features.messages.textcomposer
 
 import android.net.Uri
-import app.cash.molecule.RecompositionClock
+import app.cash.molecule.RecompositionMode
 import app.cash.molecule.moleculeFlow
 import app.cash.turbine.ReceiveTurbine
 import app.cash.turbine.test
@@ -68,7 +68,7 @@ class MessageComposerPresenterTest {
         givenResult(mockk()) // Uri is not available in JVM, so the only way to have a non-null Uri is using Mockk
     }
     private val featureFlagService = FakeFeatureFlagService(
-        mapOf(FeatureFlags.ShowMediaUploadingFlow.key to true)
+        mapOf(FeatureFlags.LocationSharing.key to true)
     )
     private val mediaPreProcessor = FakeMediaPreProcessor()
     private val snackbarDispatcher = SnackbarDispatcher()
@@ -78,14 +78,16 @@ class MessageComposerPresenterTest {
     @Test
     fun `present - initial state`() = runTest {
         val presenter = createPresenter(this)
-        moleculeFlow(RecompositionClock.Immediate) {
+        moleculeFlow(RecompositionMode.Immediate) {
             presenter.present()
         }.test {
+            skipItems(1)
             val initialState = awaitItem()
             assertThat(initialState.isFullScreen).isFalse()
             assertThat(initialState.text).isEqualTo("")
             assertThat(initialState.mode).isEqualTo(MessageComposerMode.Normal(""))
             assertThat(initialState.showAttachmentSourcePicker).isFalse()
+            assertThat(initialState.canShareLocation).isTrue()
             assertThat(initialState.attachmentsState).isEqualTo(AttachmentsState.None)
             assertThat(initialState.isSendButtonVisible).isFalse()
         }
@@ -94,9 +96,10 @@ class MessageComposerPresenterTest {
     @Test
     fun `present - toggle fullscreen`() = runTest {
         val presenter = createPresenter(this)
-        moleculeFlow(RecompositionClock.Immediate) {
+        moleculeFlow(RecompositionMode.Immediate) {
             presenter.present()
         }.test {
+            skipItems(1)
             val initialState = awaitItem()
             initialState.eventSink.invoke(MessageComposerEvents.ToggleFullScreenState)
             val fullscreenState = awaitItem()
@@ -110,9 +113,10 @@ class MessageComposerPresenterTest {
     @Test
     fun `present - change message`() = runTest {
         val presenter = createPresenter(this)
-        moleculeFlow(RecompositionClock.Immediate) {
+        moleculeFlow(RecompositionMode.Immediate) {
             presenter.present()
         }.test {
+            skipItems(1)
             val initialState = awaitItem()
             initialState.eventSink.invoke(MessageComposerEvents.UpdateText(A_MESSAGE))
             val withMessageState = awaitItem()
@@ -128,9 +132,10 @@ class MessageComposerPresenterTest {
     @Test
     fun `present - change mode to edit`() = runTest {
         val presenter = createPresenter(this)
-        moleculeFlow(RecompositionClock.Immediate) {
+        moleculeFlow(RecompositionMode.Immediate) {
             presenter.present()
         }.test {
+            skipItems(1)
             var state = awaitItem()
             val mode = anEditMode()
             state.eventSink.invoke(MessageComposerEvents.SetMode(mode))
@@ -146,9 +151,10 @@ class MessageComposerPresenterTest {
     @Test
     fun `present - change mode to reply`() = runTest {
         val presenter = createPresenter(this)
-        moleculeFlow(RecompositionClock.Immediate) {
+        moleculeFlow(RecompositionMode.Immediate) {
             presenter.present()
         }.test {
+            skipItems(1)
             var state = awaitItem()
             val mode = aReplyMode()
             state.eventSink.invoke(MessageComposerEvents.SetMode(mode))
@@ -163,9 +169,10 @@ class MessageComposerPresenterTest {
     @Test
     fun `present - change mode to quote`() = runTest {
         val presenter = createPresenter(this)
-        moleculeFlow(RecompositionClock.Immediate) {
+        moleculeFlow(RecompositionMode.Immediate) {
             presenter.present()
         }.test {
+            skipItems(1)
             var state = awaitItem()
             val mode = aQuoteMode()
             state.eventSink.invoke(MessageComposerEvents.SetMode(mode))
@@ -180,9 +187,10 @@ class MessageComposerPresenterTest {
     @Test
     fun `present - send message`() = runTest {
         val presenter = createPresenter(this)
-        moleculeFlow(RecompositionClock.Immediate) {
+        moleculeFlow(RecompositionMode.Immediate) {
             presenter.present()
         }.test {
+            skipItems(1)
             val initialState = awaitItem()
             initialState.eventSink.invoke(MessageComposerEvents.UpdateText(A_MESSAGE))
             val withMessageState = awaitItem()
@@ -202,9 +210,10 @@ class MessageComposerPresenterTest {
             this,
             fakeMatrixRoom,
         )
-        moleculeFlow(RecompositionClock.Immediate) {
+        moleculeFlow(RecompositionMode.Immediate) {
             presenter.present()
         }.test {
+            skipItems(1)
             val initialState = awaitItem()
             assertThat(initialState.text).isEqualTo("")
             val mode = anEditMode()
@@ -233,9 +242,10 @@ class MessageComposerPresenterTest {
             this,
             fakeMatrixRoom,
         )
-        moleculeFlow(RecompositionClock.Immediate) {
+        moleculeFlow(RecompositionMode.Immediate) {
             presenter.present()
         }.test {
+            skipItems(1)
             val initialState = awaitItem()
             assertThat(initialState.text).isEqualTo("")
             val mode = anEditMode(eventId = null, transactionId = A_TRANSACTION_ID)
@@ -264,9 +274,10 @@ class MessageComposerPresenterTest {
             this,
             fakeMatrixRoom,
         )
-        moleculeFlow(RecompositionClock.Immediate) {
+        moleculeFlow(RecompositionMode.Immediate) {
             presenter.present()
         }.test {
+            skipItems(1)
             val initialState = awaitItem()
             assertThat(initialState.text).isEqualTo("")
             val mode = aReplyMode()
@@ -291,9 +302,10 @@ class MessageComposerPresenterTest {
     @Test
     fun `present - Open attachments menu`() = runTest {
         val presenter = createPresenter(this)
-        moleculeFlow(RecompositionClock.Immediate) {
+        moleculeFlow(RecompositionMode.Immediate) {
             presenter.present()
         }.test {
+            skipItems(1)
             val initialState = awaitItem()
             assertThat(initialState.showAttachmentSourcePicker).isEqualTo(false)
             initialState.eventSink(MessageComposerEvents.AddAttachment)
@@ -304,9 +316,10 @@ class MessageComposerPresenterTest {
     @Test
     fun `present - Dismiss attachments menu`() = runTest {
         val presenter = createPresenter(this)
-        moleculeFlow(RecompositionClock.Immediate) {
+        moleculeFlow(RecompositionMode.Immediate) {
             presenter.present()
         }.test {
+            skipItems(1)
             val initialState = awaitItem()
             initialState.eventSink(MessageComposerEvents.AddAttachment)
             skipItems(1)
@@ -338,9 +351,10 @@ class MessageComposerPresenterTest {
                 )
             )
         )
-        moleculeFlow(RecompositionClock.Immediate) {
+        moleculeFlow(RecompositionMode.Immediate) {
             presenter.present()
         }.test {
+            skipItems(1)
             val initialState = awaitItem()
             initialState.eventSink(MessageComposerEvents.PickAttachmentSource.FromGallery)
             val previewingState = awaitItem()
@@ -372,9 +386,10 @@ class MessageComposerPresenterTest {
                 )
             )
         )
-        moleculeFlow(RecompositionClock.Immediate) {
+        moleculeFlow(RecompositionMode.Immediate) {
             presenter.present()
         }.test {
+            skipItems(1)
             val initialState = awaitItem()
             initialState.eventSink(MessageComposerEvents.PickAttachmentSource.FromGallery)
             val previewingState = awaitItem()
@@ -390,9 +405,10 @@ class MessageComposerPresenterTest {
             givenResult(null) // Simulate a user canceling the flow
             givenMimeType(MimeTypes.Images)
         }
-        moleculeFlow(RecompositionClock.Immediate) {
+        moleculeFlow(RecompositionMode.Immediate) {
             presenter.present()
         }.test {
+            skipItems(1)
             val initialState = awaitItem()
             initialState.eventSink(MessageComposerEvents.PickAttachmentSource.FromGallery)
             // No crashes here, otherwise it fails
@@ -410,9 +426,10 @@ class MessageComposerPresenterTest {
             )
         )
         val presenter = createPresenter(this, room = room)
-        moleculeFlow(RecompositionClock.Immediate) {
+        moleculeFlow(RecompositionMode.Immediate) {
             presenter.present()
         }.test {
+            skipItems(1)
             val initialState = awaitItem()
             initialState.eventSink(MessageComposerEvents.PickAttachmentSource.FromFiles)
             val sendingState = awaitItem()
@@ -431,9 +448,10 @@ class MessageComposerPresenterTest {
     fun `present - Take photo`() = runTest {
         val room = FakeMatrixRoom()
         val presenter = createPresenter(this, room = room)
-        moleculeFlow(RecompositionClock.Immediate) {
+        moleculeFlow(RecompositionMode.Immediate) {
             presenter.present()
         }.test {
+            skipItems(1)
             val initialState = awaitItem()
             initialState.eventSink(MessageComposerEvents.PickAttachmentSource.PhotoFromCamera)
             val previewingState = awaitItem()
@@ -447,9 +465,10 @@ class MessageComposerPresenterTest {
     fun `present - Record video`() = runTest {
         val room = FakeMatrixRoom()
         val presenter = createPresenter(this, room = room)
-        moleculeFlow(RecompositionClock.Immediate) {
+        moleculeFlow(RecompositionMode.Immediate) {
             presenter.present()
         }.test {
+            skipItems(1)
             val initialState = awaitItem()
             initialState.eventSink(MessageComposerEvents.PickAttachmentSource.VideoFromCamera)
             val previewingState = awaitItem()
@@ -464,9 +483,10 @@ class MessageComposerPresenterTest {
             givenSendMediaResult(Result.failure(Exception()))
         }
         val presenter = createPresenter(this, room = room)
-        moleculeFlow(RecompositionClock.Immediate) {
+        moleculeFlow(RecompositionMode.Immediate) {
             presenter.present()
         }.test {
+            skipItems(1)
             val initialState = awaitItem()
             initialState.eventSink(MessageComposerEvents.PickAttachmentSource.FromFiles)
             val sendingState = awaitItem()
diff --git a/features/messages/impl/src/test/kotlin/io/element/android/features/messages/timeline/TimelinePresenterTest.kt b/features/messages/impl/src/test/kotlin/io/element/android/features/messages/timeline/TimelinePresenterTest.kt
index c1d414c633..b4bb14f672 100644
--- a/features/messages/impl/src/test/kotlin/io/element/android/features/messages/timeline/TimelinePresenterTest.kt
+++ b/features/messages/impl/src/test/kotlin/io/element/android/features/messages/timeline/TimelinePresenterTest.kt
@@ -16,7 +16,7 @@
 
 package io.element.android.features.messages.timeline
 
-import app.cash.molecule.RecompositionClock
+import app.cash.molecule.RecompositionMode
 import app.cash.molecule.moleculeFlow
 import app.cash.turbine.test
 import com.google.common.truth.Truth.assertThat
@@ -24,8 +24,12 @@ import io.element.android.features.messages.fixtures.aTimelineItemsFactory
 import io.element.android.features.messages.impl.timeline.TimelineEvents
 import io.element.android.features.messages.impl.timeline.TimelinePresenter
 import io.element.android.features.messages.impl.timeline.factories.TimelineItemsFactory
+import io.element.android.features.messages.impl.timeline.model.TimelineItem
+import io.element.android.libraries.matrix.ui.components.aMatrixUserList
 import io.element.android.libraries.matrix.api.timeline.MatrixTimeline
 import io.element.android.libraries.matrix.api.timeline.MatrixTimelineItem
+import io.element.android.libraries.matrix.api.timeline.item.event.EventReaction
+import io.element.android.libraries.matrix.api.timeline.item.event.ReactionSender
 import io.element.android.libraries.matrix.api.timeline.item.virtual.VirtualTimelineItem
 import io.element.android.libraries.matrix.test.AN_EVENT_ID
 import io.element.android.libraries.matrix.test.room.FakeMatrixRoom
@@ -37,12 +41,13 @@ import io.element.android.tests.testutils.testCoroutineDispatchers
 import kotlinx.coroutines.test.TestScope
 import kotlinx.coroutines.test.runTest
 import org.junit.Test
+import java.util.Date
 
 class TimelinePresenterTest {
     @Test
     fun `present - initial state`() = runTest {
         val presenter = createTimelinePresenter()
-        moleculeFlow(RecompositionClock.Immediate) {
+        moleculeFlow(RecompositionMode.Immediate) {
             presenter.present()
         }.test {
             val initialState = awaitItem()
@@ -55,7 +60,7 @@ class TimelinePresenterTest {
     @Test
     fun `present - load more`() = runTest {
         val presenter = createTimelinePresenter()
-        moleculeFlow(RecompositionClock.Immediate) {
+        moleculeFlow(RecompositionMode.Immediate) {
             presenter.present()
         }.test {
             val initialState = awaitItem()
@@ -74,7 +79,7 @@ class TimelinePresenterTest {
     @Test
     fun `present - set highlighted event`() = runTest {
         val presenter = createTimelinePresenter()
-        moleculeFlow(RecompositionClock.Immediate) {
+        moleculeFlow(RecompositionMode.Immediate) {
             presenter.present()
         }.test {
             val initialState = awaitItem()
@@ -97,7 +102,7 @@ class TimelinePresenterTest {
             )
         )
         val presenter = createTimelinePresenter(timeline)
-        moleculeFlow(RecompositionClock.Immediate) {
+        moleculeFlow(RecompositionMode.Immediate) {
             presenter.present()
         }.test {
             assertThat(timeline.sendReadReceiptCount).isEqualTo(0)
@@ -114,14 +119,14 @@ class TimelinePresenterTest {
     }
 
     @Test
-    fun `present - on scroll finished will not send read receipt no event is before the index`() = runTest {
+    fun `present - on scroll finished will not send read receipt if no event is before the index`() = runTest {
         val timeline = FakeMatrixTimeline(
             initialTimelineItems = listOf(
                 MatrixTimelineItem.Event(0, anEventTimelineItem())
             )
         )
         val presenter = createTimelinePresenter(timeline)
-        moleculeFlow(RecompositionClock.Immediate) {
+        moleculeFlow(RecompositionMode.Immediate) {
             presenter.present()
         }.test {
             assertThat(timeline.sendReadReceiptCount).isEqualTo(0)
@@ -145,7 +150,7 @@ class TimelinePresenterTest {
             )
         )
         val presenter = createTimelinePresenter(timeline)
-        moleculeFlow(RecompositionClock.Immediate) {
+        moleculeFlow(RecompositionMode.Immediate) {
             presenter.present()
         }.test {
             assertThat(timeline.sendReadReceiptCount).isEqualTo(0)
@@ -165,7 +170,7 @@ class TimelinePresenterTest {
     fun `present - covers hasNewItems scenarios`() = runTest {
         val timeline = FakeMatrixTimeline()
         val presenter = createTimelinePresenter(timeline)
-        moleculeFlow(RecompositionClock.Immediate) {
+        moleculeFlow(RecompositionMode.Immediate) {
             presenter.present()
         }.test {
             val initialState = awaitItem()
@@ -188,6 +193,61 @@ class TimelinePresenterTest {
         }
     }
 
+    @Test
+    fun `present - reaction ordering`() = runTest {
+        val timeline = FakeMatrixTimeline()
+        val presenter = createTimelinePresenter(timeline)
+        moleculeFlow(RecompositionMode.Immediate) {
+            presenter.present()
+        }.test {
+            val initialState = awaitItem()
+            assertThat(initialState.hasNewItems).isFalse()
+            assertThat(initialState.timelineItems.size).isEqualTo(0)
+            val now = Date().time
+            val minuteInMilis = 60 * 1000
+            // Use index as a convenient value for timestamp
+            val (alice, bob, charlie) = aMatrixUserList().take(3).mapIndexed { i, user ->
+                ReactionSender(senderId = user.userId, timestamp = now + i * minuteInMilis)
+            }
+            val oneReaction = listOf(
+                EventReaction(
+                    key = "❤️",
+                    senders = listOf(alice, charlie)
+                ),
+                EventReaction(
+                key = "👍",
+                senders = listOf(alice, bob)
+                ),
+                EventReaction(
+                    key = "🐶",
+                    senders = listOf(charlie)
+                ),
+            )
+            timeline.updateTimelineItems {
+                listOf(MatrixTimelineItem.Event(0, anEventTimelineItem(reactions = oneReaction)))
+            }
+            skipItems(1)
+            val item = awaitItem().timelineItems.first()
+            assertThat(item).isInstanceOf(TimelineItem.Event::class.java)
+            val event = item as TimelineItem.Event
+            val reactions = event.reactionsState.reactions
+            assertThat(reactions.size).isEqualTo(3)
+
+            // Aggregated reactions are sorted by count first and then timestamp ascending(new ones tagged on the end)
+            assertThat(reactions[0].count).isEqualTo(2)
+            assertThat(reactions[0].key).isEqualTo("👍")
+            assertThat(reactions[0].senders[0].senderId).isEqualTo(bob.senderId)
+
+            assertThat(reactions[1].count).isEqualTo(2)
+            assertThat(reactions[1].key).isEqualTo("❤️")
+            assertThat(reactions[1].senders[0].senderId).isEqualTo(charlie.senderId)
+
+            assertThat(reactions[2].count).isEqualTo(1)
+            assertThat(reactions[2].key).isEqualTo("🐶")
+            assertThat(reactions[2].senders[0].senderId).isEqualTo(charlie.senderId)
+        }
+    }
+
     private fun TestScope.createTimelinePresenter(
         timeline: MatrixTimeline = FakeMatrixTimeline(),
         timelineItemsFactory: TimelineItemsFactory = aTimelineItemsFactory()
diff --git a/features/messages/impl/src/test/kotlin/io/element/android/features/messages/timeline/components/customreaction/CustomReactionPresenterTests.kt b/features/messages/impl/src/test/kotlin/io/element/android/features/messages/timeline/components/customreaction/CustomReactionPresenterTests.kt
index 237cb81d38..84628cedae 100644
--- a/features/messages/impl/src/test/kotlin/io/element/android/features/messages/timeline/components/customreaction/CustomReactionPresenterTests.kt
+++ b/features/messages/impl/src/test/kotlin/io/element/android/features/messages/timeline/components/customreaction/CustomReactionPresenterTests.kt
@@ -16,10 +16,12 @@
 
 package io.element.android.features.messages.timeline.components.customreaction
 
-import app.cash.molecule.RecompositionClock
+import app.cash.molecule.RecompositionMode
 import app.cash.molecule.moleculeFlow
 import app.cash.turbine.test
 import com.google.common.truth.Truth.assertThat
+import io.element.android.features.messages.impl.timeline.aTimelineItemEvent
+import io.element.android.features.messages.impl.timeline.aTimelineItemReactions
 import io.element.android.features.messages.impl.timeline.components.customreaction.CustomReactionEvents
 import io.element.android.features.messages.impl.timeline.components.customreaction.CustomReactionPresenter
 import io.element.android.libraries.matrix.test.AN_EVENT_ID
@@ -32,17 +34,33 @@ class CustomReactionPresenterTests {
 
     @Test
     fun `present - handle selecting and de-selecting an event`() = runTest {
-        moleculeFlow(RecompositionClock.Immediate) {
+        moleculeFlow(RecompositionMode.Immediate) {
             presenter.present()
         }.test {
             val initialState = awaitItem()
             assertThat(initialState.selectedEventId).isNull()
 
-            initialState.eventSink(CustomReactionEvents.UpdateSelectedEvent(AN_EVENT_ID))
+            initialState.eventSink(CustomReactionEvents.UpdateSelectedEvent(aTimelineItemEvent(eventId = AN_EVENT_ID)))
             assertThat(awaitItem().selectedEventId).isEqualTo(AN_EVENT_ID)
 
             initialState.eventSink(CustomReactionEvents.UpdateSelectedEvent(null))
             assertThat(awaitItem().selectedEventId).isNull()
         }
     }
+
+    @Test
+    fun `present - handle selected emojis`() = runTest {
+        moleculeFlow(RecompositionMode.Immediate) {
+            presenter.present()
+        }.test {
+            val initialState = awaitItem()
+            assertThat(initialState.selectedEventId).isNull()
+            val reactions = aTimelineItemReactions(count = 1, isHighlighted = true)
+            val key = reactions.reactions.first().key
+            initialState.eventSink(CustomReactionEvents.UpdateSelectedEvent(aTimelineItemEvent(eventId = AN_EVENT_ID, timelineItemReactions = reactions)))
+            val stateWithSelectedEmojis = awaitItem()
+            assertThat(stateWithSelectedEmojis.selectedEventId).isEqualTo(AN_EVENT_ID)
+            assertThat(stateWithSelectedEmojis.selectedEmoji).contains(key)
+        }
+    }
 }
diff --git a/features/messages/impl/src/test/kotlin/io/element/android/features/messages/timeline/components/reactionsummary/ReactionSummaryPresenterTests.kt b/features/messages/impl/src/test/kotlin/io/element/android/features/messages/timeline/components/reactionsummary/ReactionSummaryPresenterTests.kt
new file mode 100644
index 0000000000..0170878cb5
--- /dev/null
+++ b/features/messages/impl/src/test/kotlin/io/element/android/features/messages/timeline/components/reactionsummary/ReactionSummaryPresenterTests.kt
@@ -0,0 +1,80 @@
+/*
+ * Copyright (c) 2023 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
+ *
+ *     http://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.features.messages.timeline.components.reactionsummary
+
+import app.cash.molecule.RecompositionMode
+import app.cash.molecule.moleculeFlow
+import app.cash.turbine.test
+import com.google.common.truth.Truth.assertThat
+import io.element.android.features.messages.impl.timeline.components.reactionsummary.ReactionSummaryEvents
+import io.element.android.features.messages.impl.timeline.components.reactionsummary.ReactionSummaryPresenter
+import io.element.android.features.messages.impl.timeline.model.anAggregatedReaction
+import io.element.android.libraries.matrix.api.room.MatrixRoomMembersState
+import io.element.android.libraries.matrix.test.AN_AVATAR_URL
+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.A_USER_NAME
+import io.element.android.libraries.matrix.test.room.FakeMatrixRoom
+import io.element.android.libraries.matrix.test.room.aRoomMember
+import kotlinx.coroutines.test.runTest
+import org.junit.Test
+
+class ReactionSummaryPresenterTests {
+    private val aggregatedReaction = anAggregatedReaction(userId = A_USER_ID, key = "👍", isHighlighted = true)
+    private val roomMember = aRoomMember(userId = A_USER_ID,  avatarUrl = AN_AVATAR_URL, displayName = A_USER_NAME)
+    private val summaryEvent = ReactionSummaryEvents.ShowReactionSummary(AN_EVENT_ID, listOf(aggregatedReaction), aggregatedReaction.key)
+    private val room = FakeMatrixRoom().apply {
+        givenRoomMembersState(MatrixRoomMembersState.Ready(listOf(roomMember)))
+    }
+    private val presenter = ReactionSummaryPresenter(room)
+
+    @Test
+    fun `present - handle showing and hiding the reaction summary`() = runTest {
+        moleculeFlow(RecompositionMode.Immediate) {
+            presenter.present()
+        }.test {
+            val initialState = awaitItem()
+            assertThat(initialState.target).isEqualTo(null)
+
+            initialState.eventSink(summaryEvent)
+            assertThat(awaitItem().target).isNotNull()
+
+            initialState.eventSink(ReactionSummaryEvents.Clear)
+            assertThat(awaitItem().target).isNull()
+        }
+    }
+
+    @Test
+    fun `present - handle reaction summary content and avatars populated`() = runTest {
+        moleculeFlow(RecompositionMode.Immediate) {
+            presenter.present()
+        }.test {
+            val initialState = awaitItem()
+            assertThat(initialState.target).isEqualTo(null)
+
+            initialState.eventSink(summaryEvent)
+            val reactions = awaitItem().target?.reactions
+            assertThat(reactions?.count()).isEqualTo(1)
+            assertThat(reactions?.first()?.key).isEqualTo("👍")
+            assertThat(reactions?.first()?.senders?.first()?.senderId).isEqualTo(A_USER_ID)
+            assertThat(reactions?.first()?.senders?.first()?.user?.userId).isEqualTo(A_USER_ID)
+            assertThat(reactions?.first()?.senders?.first()?.user?.avatarUrl).isEqualTo(AN_AVATAR_URL)
+            assertThat(reactions?.first()?.senders?.first()?.user?.displayName).isEqualTo(A_USER_NAME)
+        }
+    }
+
+}
diff --git a/features/messages/impl/src/test/kotlin/io/element/android/features/messages/timeline/components/retrysendmenu/RetrySendMenuPresenterTests.kt b/features/messages/impl/src/test/kotlin/io/element/android/features/messages/timeline/components/retrysendmenu/RetrySendMenuPresenterTests.kt
index 1e467b82af..4f4f0a0ee4 100644
--- a/features/messages/impl/src/test/kotlin/io/element/android/features/messages/timeline/components/retrysendmenu/RetrySendMenuPresenterTests.kt
+++ b/features/messages/impl/src/test/kotlin/io/element/android/features/messages/timeline/components/retrysendmenu/RetrySendMenuPresenterTests.kt
@@ -16,7 +16,7 @@
 
 package io.element.android.features.messages.timeline.components.retrysendmenu
 
-import app.cash.molecule.RecompositionClock
+import app.cash.molecule.RecompositionMode
 import app.cash.molecule.moleculeFlow
 import app.cash.turbine.test
 import com.google.common.truth.Truth.assertThat
@@ -35,7 +35,7 @@ class RetrySendMenuPresenterTests {
 
     @Test
     fun `present - handle event selected`() = runTest {
-        moleculeFlow(RecompositionClock.Immediate) {
+        moleculeFlow(RecompositionMode.Immediate) {
             presenter.present()
         }.test {
             val initialState = awaitItem()
@@ -48,7 +48,7 @@ class RetrySendMenuPresenterTests {
 
     @Test
     fun `present - handle dismiss`() = runTest {
-        moleculeFlow(RecompositionClock.Immediate) {
+        moleculeFlow(RecompositionMode.Immediate) {
             presenter.present()
         }.test {
             val initialState = awaitItem()
@@ -63,7 +63,7 @@ class RetrySendMenuPresenterTests {
 
     @Test
     fun `present - handle resend with transactionId`() = runTest {
-        moleculeFlow(RecompositionClock.Immediate) {
+        moleculeFlow(RecompositionMode.Immediate) {
             presenter.present()
         }.test {
             val initialState = awaitItem()
@@ -79,7 +79,7 @@ class RetrySendMenuPresenterTests {
 
     @Test
     fun `present - handle resend without transactionId`() = runTest {
-        moleculeFlow(RecompositionClock.Immediate) {
+        moleculeFlow(RecompositionMode.Immediate) {
             presenter.present()
         }.test {
             val initialState = awaitItem()
@@ -96,7 +96,7 @@ class RetrySendMenuPresenterTests {
     @Test
     fun `present - handle resend with error`() = runTest {
         room.givenRetrySendMessageResult(Result.failure(IllegalStateException("An error")))
-        moleculeFlow(RecompositionClock.Immediate) {
+        moleculeFlow(RecompositionMode.Immediate) {
             presenter.present()
         }.test {
             val initialState = awaitItem()
@@ -112,7 +112,7 @@ class RetrySendMenuPresenterTests {
 
     @Test
     fun `present - handle remove failed message with transactionId`() = runTest {
-        moleculeFlow(RecompositionClock.Immediate) {
+        moleculeFlow(RecompositionMode.Immediate) {
             presenter.present()
         }.test {
             val initialState = awaitItem()
@@ -128,7 +128,7 @@ class RetrySendMenuPresenterTests {
 
     @Test
     fun `present - handle remove failed message without transactionId`() = runTest {
-        moleculeFlow(RecompositionClock.Immediate) {
+        moleculeFlow(RecompositionMode.Immediate) {
             presenter.present()
         }.test {
             val initialState = awaitItem()
@@ -145,7 +145,7 @@ class RetrySendMenuPresenterTests {
     @Test
     fun `present - handle remove failed message with error`() = runTest {
         room.givenRetrySendMessageResult(Result.failure(IllegalStateException("An error")))
-        moleculeFlow(RecompositionClock.Immediate) {
+        moleculeFlow(RecompositionMode.Immediate) {
             presenter.present()
         }.test {
             val initialState = awaitItem()
diff --git a/features/messages/impl/src/test/kotlin/io/element/android/features/messages/timeline/model/AggregatedReactionTest.kt b/features/messages/impl/src/test/kotlin/io/element/android/features/messages/timeline/model/AggregatedReactionTest.kt
index 0e1ccbd003..ce107f76aa 100644
--- a/features/messages/impl/src/test/kotlin/io/element/android/features/messages/timeline/model/AggregatedReactionTest.kt
+++ b/features/messages/impl/src/test/kotlin/io/element/android/features/messages/timeline/model/AggregatedReactionTest.kt
@@ -16,19 +16,30 @@
 
 package io.element.android.features.messages.timeline.model
 
-import io.element.android.features.messages.impl.timeline.model.AggregatedReaction
+import io.element.android.features.messages.impl.timeline.model.anAggregatedReaction
 import org.junit.Assert.assertEquals
 import org.junit.Test
 
 class AggregatedReactionTest {
     @Test
     fun `reaction display key is shortened`() {
-        val reaction = AggregatedReaction(
-                key = "1234567890123456790",
-                count = 1,
-                isHighlighted = false
+        val reaction = anAggregatedReaction(
+            key = "1234567890123456790",
+            count = 1
         )
 
         assertEquals("1234567890123456…", reaction.displayKey)
     }
+
+    @Test
+    fun `reaction count and isHighlighted are computed correctly`() {
+        val reaction = anAggregatedReaction(
+            key = "1234567890123456790",
+            count = 3,
+            isHighlighted = true
+        )
+
+        assertEquals(3, reaction.count)
+        assertEquals(true, reaction.isHighlighted)
+    }
 }
diff --git a/features/networkmonitor/api/src/main/kotlin/io/element/android/features/networkmonitor/api/ui/ConnectivityIndicatorView.kt b/features/networkmonitor/api/src/main/kotlin/io/element/android/features/networkmonitor/api/ui/ConnectivityIndicatorView.kt
index 7d01d668c9..855bf067dd 100644
--- a/features/networkmonitor/api/src/main/kotlin/io/element/android/features/networkmonitor/api/ui/ConnectivityIndicatorView.kt
+++ b/features/networkmonitor/api/src/main/kotlin/io/element/android/features/networkmonitor/api/ui/ConnectivityIndicatorView.kt
@@ -42,11 +42,12 @@ import androidx.compose.ui.Alignment
 import androidx.compose.ui.Modifier
 import androidx.compose.ui.graphics.ColorFilter
 import androidx.compose.ui.res.stringResource
-import androidx.compose.ui.text.font.FontWeight
 import androidx.compose.ui.tooling.preview.Preview
 import androidx.compose.ui.unit.dp
+import androidx.compose.ui.unit.sp
 import io.element.android.libraries.designsystem.preview.ElementPreviewDark
 import io.element.android.libraries.designsystem.preview.ElementPreviewLight
+import io.element.android.libraries.designsystem.text.toDp
 import io.element.android.libraries.theme.ElementTheme
 import io.element.android.libraries.ui.strings.CommonStrings
 
@@ -86,14 +87,14 @@ private fun Indicator(modifier: Modifier = Modifier) {
             .statusBarsPadding()
             .padding(vertical = 6.dp),
         horizontalArrangement = Arrangement.Center,
-        verticalAlignment = Alignment.Bottom,
+        verticalAlignment = Alignment.CenterVertically,
     ) {
         val tint = MaterialTheme.colorScheme.primary
         Image(
             imageVector = Icons.Outlined.WifiOff,
             contentDescription = null,
             colorFilter = ColorFilter.tint(tint),
-            modifier = Modifier.size(16.dp),
+            modifier = Modifier.size(16.sp.toDp()),
         )
         Spacer(modifier = Modifier.width(8.dp))
         Text(
diff --git a/features/onboarding/impl/build.gradle.kts b/features/onboarding/impl/build.gradle.kts
index 0952835d46..0f97a0ffeb 100644
--- a/features/onboarding/impl/build.gradle.kts
+++ b/features/onboarding/impl/build.gradle.kts
@@ -48,6 +48,4 @@ dependencies {
     testImplementation(libs.test.truth)
     testImplementation(libs.test.turbine)
     testImplementation(projects.libraries.matrix.test)
-
-    androidTestImplementation(libs.test.junitext)
 }
diff --git a/features/onboarding/impl/src/main/kotlin/io/element/android/features/onboarding/impl/OnBoardingView.kt b/features/onboarding/impl/src/main/kotlin/io/element/android/features/onboarding/impl/OnBoardingView.kt
index 0651d9cc2e..1adfe6bd93 100644
--- a/features/onboarding/impl/src/main/kotlin/io/element/android/features/onboarding/impl/OnBoardingView.kt
+++ b/features/onboarding/impl/src/main/kotlin/io/element/android/features/onboarding/impl/OnBoardingView.kt
@@ -23,10 +23,8 @@ import androidx.compose.foundation.layout.fillMaxSize
 import androidx.compose.foundation.layout.fillMaxWidth
 import androidx.compose.foundation.layout.height
 import androidx.compose.foundation.layout.padding
-import androidx.compose.foundation.layout.width
 import androidx.compose.material.icons.Icons
 import androidx.compose.material.icons.filled.QrCode
-import androidx.compose.material3.MaterialTheme
 import androidx.compose.runtime.Composable
 import androidx.compose.ui.Alignment.Companion.CenterHorizontally
 import androidx.compose.ui.BiasAlignment
@@ -42,9 +40,8 @@ import io.element.android.libraries.designsystem.atomic.molecules.ButtonColumnMo
 import io.element.android.libraries.designsystem.atomic.pages.OnBoardingPage
 import io.element.android.libraries.designsystem.preview.DayNightPreviews
 import io.element.android.libraries.designsystem.preview.ElementPreview
-import io.element.android.libraries.designsystem.theme.aliasButtonText
 import io.element.android.libraries.designsystem.theme.components.Button
-import io.element.android.libraries.designsystem.theme.components.Icon
+import io.element.android.libraries.designsystem.theme.components.IconSource
 import io.element.android.libraries.designsystem.theme.components.OutlinedButton
 import io.element.android.libraries.designsystem.theme.components.Text
 import io.element.android.libraries.testtags.TestTags
@@ -144,46 +141,27 @@ private fun OnBoardingButtons(
         }
         if (state.canLoginWithQrCode) {
             Button(
+                text = stringResource(id = R.string.screen_onboarding_sign_in_with_qr_code),
+                leadingIcon = IconSource.Vector(Icons.Default.QrCode),
                 onClick = onSignInWithQrCode,
-                enabled = true,
-                modifier = Modifier
-                    .fillMaxWidth()
-            ) {
-                Icon(
-                    imageVector = Icons.Default.QrCode, contentDescription = null,
-                    tint = MaterialTheme.colorScheme.onPrimary
-                )
-                Spacer(Modifier.width(14.dp))
-                Text(
-                    text = stringResource(id = R.string.screen_onboarding_sign_in_with_qr_code),
-                    style = ElementTheme.typography.aliasButtonText,
-                )
-            }
+                modifier = Modifier.fillMaxWidth()
+            )
         }
         Button(
+            text = stringResource(id = signInButtonStringRes),
             onClick = onSignIn,
-            enabled = true,
             modifier = Modifier
                 .fillMaxWidth()
                 .testTag(TestTags.onBoardingSignIn)
-        ) {
-            Text(
-                text = stringResource(id = signInButtonStringRes),
-                style = ElementTheme.typography.aliasButtonText,
-            )
-        }
+        )
         if (state.canCreateAccount) {
             OutlinedButton(
+                text = stringResource(id = R.string.screen_onboarding_sign_up),
                 onClick = onCreateAccount,
                 enabled = true,
                 modifier = Modifier
                     .fillMaxWidth()
-            ) {
-                Text(
-                    text = stringResource(id = R.string.screen_onboarding_sign_up),
-                    style = ElementTheme.typography.aliasButtonText,
-                )
-            }
+            )
         }
         Spacer(modifier = Modifier.height(16.dp))
     }
diff --git a/features/onboarding/impl/src/main/res/values-de/translations.xml b/features/onboarding/impl/src/main/res/values-de/translations.xml
index e36fa31a2b..82e20c3509 100644
--- a/features/onboarding/impl/src/main/res/values-de/translations.xml
+++ b/features/onboarding/impl/src/main/res/values-de/translations.xml
@@ -4,7 +4,7 @@
   "Mit QR-Code anmelden"
   "Konto erstellen"
   "Sicher kommunizieren und zusammenarbeiten"
-  "Willkommen beim schnellsten Element jemals. Optimiert für Geschwindigkeit und Einfachheit."
+  "Willkommen beim schnellsten Element aller Zeiten. Optimiert für Geschwindigkeit und Einfachheit."
   "Willkommen zur %1$s. Verbessert, für Geschwindigkeit und Einfachheit."
   "Sei in deinem Element"
 
diff --git a/features/onboarding/impl/src/main/res/values-ru/translations.xml b/features/onboarding/impl/src/main/res/values-ru/translations.xml
new file mode 100644
index 0000000000..5c8c12c2b0
--- /dev/null
+++ b/features/onboarding/impl/src/main/res/values-ru/translations.xml
@@ -0,0 +1,10 @@
+
+
+  "Вход в систему вручную"
+  "Войти с помощью QR-кода"
+  "Создать учетную запись"
+  "Безопасное общение и совместная работа"
+  "Добро пожаловать в самый быстрый Element. Преимущество в скорости и простоте."
+  "Добро пожаловать в %1$s. Supercharged — это скорость и простота."
+  "Будь в своей стихии"
+
diff --git a/features/onboarding/impl/src/main/res/values-zh-rTW/translations.xml b/features/onboarding/impl/src/main/res/values-zh-rTW/translations.xml
new file mode 100644
index 0000000000..5150b50c9a
--- /dev/null
+++ b/features/onboarding/impl/src/main/res/values-zh-rTW/translations.xml
@@ -0,0 +1,8 @@
+
+
+  "手動登入"
+  "使用 QR code 登入"
+  "建立帳號"
+  "歡迎使用有史以來最快的 Element。速度超快,操作簡便。"
+  "得心應手"
+
diff --git a/features/onboarding/impl/src/test/kotlin/io/element/android/features/onboarding/impl/OnBoardingPresenterTest.kt b/features/onboarding/impl/src/test/kotlin/io/element/android/features/onboarding/impl/OnBoardingPresenterTest.kt
index f415cd795f..d336e5b466 100644
--- a/features/onboarding/impl/src/test/kotlin/io/element/android/features/onboarding/impl/OnBoardingPresenterTest.kt
+++ b/features/onboarding/impl/src/test/kotlin/io/element/android/features/onboarding/impl/OnBoardingPresenterTest.kt
@@ -16,7 +16,7 @@
 
 package io.element.android.features.onboarding.impl
 
-import app.cash.molecule.RecompositionClock
+import app.cash.molecule.RecompositionMode
 import app.cash.molecule.moleculeFlow
 import app.cash.turbine.test
 import com.google.common.truth.Truth.assertThat
@@ -27,7 +27,7 @@ class OnBoardingPresenterTest {
     @Test
     fun `present - initial state`() = runTest {
         val presenter = OnBoardingPresenter()
-        moleculeFlow(RecompositionClock.Immediate) {
+        moleculeFlow(RecompositionMode.Immediate) {
             presenter.present()
         }.test {
             val initialState = awaitItem()
diff --git a/features/poll/api/build.gradle.kts b/features/poll/api/build.gradle.kts
new file mode 100644
index 0000000000..be198ba740
--- /dev/null
+++ b/features/poll/api/build.gradle.kts
@@ -0,0 +1,35 @@
+/*
+ * Copyright (c) 2023 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
+ *
+ *     http://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.
+ */
+
+plugins {
+    id("io.element.android-compose-library")
+    alias(libs.plugins.ksp)
+}
+
+android {
+    namespace = "io.element.android.features.poll.api"
+}
+
+dependencies {
+    implementation(projects.libraries.architecture)
+    implementation(projects.libraries.designsystem)
+    implementation(projects.libraries.uiStrings)
+    implementation(libs.androidx.constraintlayout)
+    implementation(libs.androidx.constraintlayout.compose)
+    implementation(projects.libraries.matrix.api)
+
+    ksp(libs.showkase.processor)
+}
diff --git a/features/poll/api/src/main/kotlin/io/element/android/features/poll/api/ActivePollContentView.kt b/features/poll/api/src/main/kotlin/io/element/android/features/poll/api/ActivePollContentView.kt
new file mode 100644
index 0000000000..587c3306b1
--- /dev/null
+++ b/features/poll/api/src/main/kotlin/io/element/android/features/poll/api/ActivePollContentView.kt
@@ -0,0 +1,118 @@
+/*
+ * Copyright (c) 2023 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
+ *
+ *     http://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.features.poll.api
+
+import androidx.compose.foundation.layout.Arrangement
+import androidx.compose.foundation.layout.Column
+import androidx.compose.foundation.layout.Row
+import androidx.compose.foundation.layout.fillMaxWidth
+import androidx.compose.foundation.layout.padding
+import androidx.compose.foundation.selection.selectableGroup
+import androidx.compose.material.icons.Icons
+import androidx.compose.material.icons.filled.BarChart
+import androidx.compose.runtime.Composable
+import androidx.compose.ui.Alignment
+import androidx.compose.ui.Modifier
+import androidx.compose.ui.res.stringResource
+import androidx.compose.ui.unit.dp
+import io.element.android.libraries.designsystem.preview.DayNightPreviews
+import io.element.android.libraries.designsystem.preview.ElementPreview
+import io.element.android.libraries.designsystem.theme.components.Icon
+import io.element.android.libraries.designsystem.theme.components.Text
+import io.element.android.libraries.matrix.api.poll.PollAnswer
+import io.element.android.libraries.matrix.api.poll.PollKind
+import io.element.android.libraries.theme.ElementTheme
+import io.element.android.libraries.ui.strings.CommonStrings
+import kotlinx.collections.immutable.ImmutableList
+
+@Composable
+fun ActivePollContentView(
+    question: String,
+    answerItems: ImmutableList,
+    pollKind: PollKind,
+    onAnswerSelected: (PollAnswer) -> Unit,
+    modifier: Modifier = Modifier,
+) {
+    val showResults = answerItems.any { it.isSelected }
+    Column(
+        modifier = modifier
+            .selectableGroup()
+            .fillMaxWidth(),
+        verticalArrangement = Arrangement.spacedBy(16.dp),
+    ) {
+        Row(
+            horizontalArrangement = Arrangement.spacedBy(4.dp),
+        ) {
+            Icon(imageVector = Icons.Default.BarChart, contentDescription = null)
+            Text(
+                text = question,
+                style = ElementTheme.typography.fontBodyLgMedium
+            )
+        }
+
+        answerItems.forEach { answerItem ->
+            PollAnswerView(
+                answerItem = answerItem,
+                onClick = { onAnswerSelected(answerItem.answer) }
+            )
+        }
+
+        val votesCount = answerItems.sumOf { it.votesCount }
+        when {
+            pollKind == PollKind.Undisclosed -> {
+                Text(
+                    modifier = Modifier
+                        .align(Alignment.Start)
+                        .padding(start = 32.dp),
+                    style = ElementTheme.typography.fontBodyXsRegular,
+                    color = ElementTheme.colors.textSecondary,
+                    text = stringResource(CommonStrings.common_poll_undisclosed_text),
+                )
+            }
+            showResults -> {
+                Text(
+                    modifier = Modifier.align(Alignment.End),
+                    style = ElementTheme.typography.fontBodyXsRegular,
+                    color = ElementTheme.colors.textSecondary,
+                    text = stringResource(CommonStrings.common_poll_total_votes, votesCount),
+                )
+            }
+        }
+    }
+}
+
+@DayNightPreviews
+@Composable
+internal fun ActivePollContentNoResultsPreview() = ElementPreview {
+    ActivePollContentView(
+        question = "What type of food should we have at the party?",
+        answerItems = aPollAnswerItemList(isDisclosed = false),
+        pollKind = PollKind.Undisclosed,
+        onAnswerSelected = { },
+    )
+}
+
+@DayNightPreviews
+@Composable
+internal fun ActivePollContentWithResultsPreview() = ElementPreview {
+    ActivePollContentView(
+        question = "What type of food should we have at the party?",
+        answerItems = aPollAnswerItemList(),
+        pollKind = PollKind.Disclosed,
+        onAnswerSelected = { },
+    )
+}
diff --git a/features/poll/api/src/main/kotlin/io/element/android/features/poll/api/PollAnswerItem.kt b/features/poll/api/src/main/kotlin/io/element/android/features/poll/api/PollAnswerItem.kt
new file mode 100644
index 0000000000..24db33ad1f
--- /dev/null
+++ b/features/poll/api/src/main/kotlin/io/element/android/features/poll/api/PollAnswerItem.kt
@@ -0,0 +1,36 @@
+/*
+ * Copyright (c) 2023 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
+ *
+ *     http://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.features.poll.api
+
+import io.element.android.libraries.matrix.api.poll.PollAnswer
+
+/**
+ * UI model for a [PollAnswer].
+ *
+ * @property answer the poll answer.
+ * @property isSelected whether the user has selected this answer.
+ * @property isDisclosed whether the votes for this answer should be disclosed.
+ * @property votesCount the number of votes for this answer.
+ * @property progress the percentage of votes for this answer.
+ */
+data class PollAnswerItem(
+    val answer: PollAnswer,
+    val isSelected: Boolean,
+    val isDisclosed: Boolean,
+    val votesCount: Int,
+    val progress: Float,
+)
diff --git a/features/poll/api/src/main/kotlin/io/element/android/features/poll/api/PollAnswerView.kt b/features/poll/api/src/main/kotlin/io/element/android/features/poll/api/PollAnswerView.kt
new file mode 100644
index 0000000000..26fa6fbb71
--- /dev/null
+++ b/features/poll/api/src/main/kotlin/io/element/android/features/poll/api/PollAnswerView.kt
@@ -0,0 +1,125 @@
+/*
+ * Copyright (c) 2023 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
+ *
+ *     http://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.features.poll.api
+
+import androidx.compose.foundation.layout.fillMaxWidth
+import androidx.compose.foundation.layout.wrapContentHeight
+import androidx.compose.foundation.selection.selectable
+import androidx.compose.runtime.Composable
+import androidx.compose.ui.Modifier
+import androidx.compose.ui.graphics.StrokeCap
+import androidx.compose.ui.res.pluralStringResource
+import androidx.compose.ui.semantics.Role
+import androidx.compose.ui.unit.dp
+import androidx.constraintlayout.compose.ConstraintLayout
+import androidx.constraintlayout.compose.Dimension
+import androidx.constraintlayout.compose.Visibility
+import io.element.android.libraries.designsystem.preview.DayNightPreviews
+import io.element.android.libraries.designsystem.preview.ElementPreview
+import io.element.android.libraries.designsystem.theme.components.LinearProgressIndicator
+import io.element.android.libraries.designsystem.theme.components.RadioButton
+import io.element.android.libraries.designsystem.theme.components.Text
+import io.element.android.libraries.theme.ElementTheme
+import io.element.android.libraries.ui.strings.CommonPlurals
+
+@Suppress("DestructuringDeclarationWithTooManyEntries") // This is necessary to declare the constraints ids
+@Composable
+fun PollAnswerView(
+    answerItem: PollAnswerItem,
+    onClick: () -> Unit,
+    modifier: Modifier = Modifier,
+) {
+    ConstraintLayout(
+        modifier
+            .wrapContentHeight()
+            .fillMaxWidth()
+            .selectable(
+                selected = answerItem.isSelected,
+                onClick = onClick,
+                role = Role.RadioButton,
+            )
+    ) {
+        val (radioButton, answerText, votesText, progressBar) = createRefs()
+        RadioButton(
+            modifier = Modifier.constrainAs(radioButton) {
+                top.linkTo(answerText.top)
+                bottom.linkTo(answerText.bottom)
+                start.linkTo(parent.start)
+                end.linkTo(answerText.start)
+            },
+            selected = answerItem.isSelected,
+            onClick = null // null recommended for accessibility with screenreaders
+        )
+        Text(
+            modifier = Modifier.constrainAs(answerText) {
+                width = Dimension.fillToConstraints
+                top.linkTo(parent.top)
+                start.linkTo(radioButton.end, margin = 8.dp)
+                end.linkTo(votesText.start)
+                bottom.linkTo(progressBar.top)
+            },
+            text = answerItem.answer.text,
+        )
+        Text(
+            modifier = Modifier.constrainAs(votesText) {
+                start.linkTo(answerText.end)
+                end.linkTo(parent.end)
+                bottom.linkTo(answerText.bottom)
+                visibility = if (answerItem.isDisclosed) Visibility.Visible else Visibility.Gone
+            },
+            text = pluralStringResource(
+                id = CommonPlurals.common_poll_votes_count,
+                count = answerItem.votesCount,
+                answerItem.votesCount
+            ),
+            style = ElementTheme.typography.fontBodySmRegular,
+            color = ElementTheme.colors.textSecondary,
+        )
+        LinearProgressIndicator(
+            progress = answerItem.progress,
+            modifier = Modifier
+                .constrainAs(progressBar) {
+                    start.linkTo(answerText.start)
+                    end.linkTo(votesText.end)
+                    top.linkTo(answerText.bottom, margin = 10.dp)
+                    bottom.linkTo(parent.bottom)
+                    width = Dimension.fillToConstraints
+                    visibility = if (answerItem.isDisclosed) Visibility.Visible else Visibility.Gone
+
+                },
+            strokeCap = StrokeCap.Round,
+        )
+    }
+}
+
+@DayNightPreviews
+@Composable
+internal fun PollAnswerViewNoResultsPreview() = ElementPreview {
+    PollAnswerView(
+        answerItem = aPollAnswerItem(),
+        onClick = { },
+    )
+}
+
+@DayNightPreviews
+@Composable
+internal fun PollAnswerViewWithResultPreview() = ElementPreview {
+    PollAnswerView(
+        answerItem = aPollAnswerItem(isDisclosed = true),
+        onClick = { }
+    )
+}
diff --git a/features/poll/api/src/main/kotlin/io/element/android/features/poll/api/PollAnswerViewProvider.kt b/features/poll/api/src/main/kotlin/io/element/android/features/poll/api/PollAnswerViewProvider.kt
new file mode 100644
index 0000000000..062d09fd88
--- /dev/null
+++ b/features/poll/api/src/main/kotlin/io/element/android/features/poll/api/PollAnswerViewProvider.kt
@@ -0,0 +1,60 @@
+/*
+ * Copyright (c) 2023 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
+ *
+ *     http://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.features.poll.api
+
+import io.element.android.libraries.matrix.api.poll.PollAnswer
+import kotlinx.collections.immutable.persistentListOf
+
+fun aPollAnswerItemList(isDisclosed: Boolean = true) = persistentListOf(
+    aPollAnswerItem(
+        answer = PollAnswer("option_1", "Italian \uD83C\uDDEE\uD83C\uDDF9"),
+        isDisclosed = isDisclosed,
+        votesCount = 5,
+        progress = 0.5f
+    ),
+    aPollAnswerItem(
+        answer = PollAnswer("option_2", "Chinese \uD83C\uDDE8\uD83C\uDDF3"),
+        isDisclosed = isDisclosed,
+        votesCount = 0,
+        progress = 0f
+    ),
+    aPollAnswerItem(
+        answer = PollAnswer("option_3", "Brazilian \uD83C\uDDE7\uD83C\uDDF7"),
+        isDisclosed = isDisclosed,
+        isSelected = true,
+        votesCount = 1,
+        progress = 0.1f
+    ),
+    aPollAnswerItem(isDisclosed = isDisclosed),
+)
+
+fun aPollAnswerItem(
+    answer: PollAnswer = PollAnswer(
+        "option_4",
+        "French \uD83C\uDDEB\uD83C\uDDF7 But make it a very very very long option then this should just keep expanding"
+    ),
+    isSelected: Boolean = false,
+    isDisclosed: Boolean = true,
+    votesCount: Int = 4,
+    progress: Float = 0.4f,
+) = PollAnswerItem(
+    answer = answer,
+    isSelected = isSelected,
+    isDisclosed = isDisclosed,
+    votesCount = votesCount,
+    progress = progress
+)
diff --git a/features/poll/api/src/main/kotlin/io/element/android/features/poll/api/PollEntryPoint.kt b/features/poll/api/src/main/kotlin/io/element/android/features/poll/api/PollEntryPoint.kt
new file mode 100644
index 0000000000..d8f2aed846
--- /dev/null
+++ b/features/poll/api/src/main/kotlin/io/element/android/features/poll/api/PollEntryPoint.kt
@@ -0,0 +1,37 @@
+/*
+ * Copyright (c) 2023 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
+ *
+ *     http://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.features.poll.api
+
+import com.bumble.appyx.core.modality.BuildContext
+import com.bumble.appyx.core.node.Node
+import com.bumble.appyx.core.plugin.Plugin
+import io.element.android.libraries.architecture.FeatureEntryPoint
+
+interface PollEntryPoint : FeatureEntryPoint {
+
+    fun nodeBuilder(parentNode: Node, buildContext: BuildContext): NodeBuilder
+
+    interface NodeBuilder {
+        fun callback(callback: Callback): NodeBuilder
+        fun build(): Node
+    }
+
+    interface Callback : Plugin {
+        // Add your callbacks
+    }
+}
+
diff --git a/features/poll/impl/build.gradle.kts b/features/poll/impl/build.gradle.kts
new file mode 100644
index 0000000000..626a7d0f2c
--- /dev/null
+++ b/features/poll/impl/build.gradle.kts
@@ -0,0 +1,52 @@
+/*
+ * Copyright (c) 2023 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
+ *
+ *     http://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.
+ */
+
+// TODO: Remove once https://youtrack.jetbrains.com/issue/KTIJ-19369 is fixed
+@Suppress("DSL_SCOPE_VIOLATION")
+plugins {
+    id("io.element.android-compose-library")
+    alias(libs.plugins.anvil)
+    alias(libs.plugins.ksp)
+    id("kotlin-parcelize")
+}
+
+android {
+    namespace = "io.element.android.features.poll.impl"
+}
+
+anvil {
+    generateDaggerFactories.set(true)
+}
+
+dependencies {
+    implementation(projects.anvilannotations)
+    anvil(projects.anvilcodegen)
+    api(projects.features.poll.api)
+    implementation(projects.libraries.core)
+    implementation(projects.libraries.architecture)
+    implementation(projects.libraries.matrix.api)
+    implementation(projects.libraries.matrixui)
+    implementation(projects.libraries.designsystem)
+
+    testImplementation(libs.test.junit)
+    testImplementation(libs.coroutines.test)
+    testImplementation(libs.molecule.runtime)
+    testImplementation(libs.test.truth)
+    testImplementation(libs.test.turbine)
+    testImplementation(projects.libraries.matrix.test)
+
+    ksp(libs.showkase.processor)
+}
diff --git a/features/poll/impl/src/main/kotlin/io/element/android/features/poll/impl/DefaultPollEntryPoint.kt b/features/poll/impl/src/main/kotlin/io/element/android/features/poll/impl/DefaultPollEntryPoint.kt
new file mode 100644
index 0000000000..052c1bcd5f
--- /dev/null
+++ b/features/poll/impl/src/main/kotlin/io/element/android/features/poll/impl/DefaultPollEntryPoint.kt
@@ -0,0 +1,46 @@
+/*
+ * Copyright (c) 2023 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
+ *
+ *     http://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.features.poll.impl
+
+import com.bumble.appyx.core.modality.BuildContext
+import com.bumble.appyx.core.node.Node
+import com.bumble.appyx.core.plugin.Plugin
+import com.squareup.anvil.annotations.ContributesBinding
+import io.element.android.features.poll.api.PollEntryPoint
+import io.element.android.libraries.architecture.createNode
+import io.element.android.libraries.di.AppScope
+import javax.inject.Inject
+
+@ContributesBinding(AppScope::class)
+class DefaultPollEntryPoint @Inject constructor() : PollEntryPoint {
+
+    override fun nodeBuilder(parentNode: Node, buildContext: BuildContext): PollEntryPoint.NodeBuilder {
+        val plugins = ArrayList()
+
+        return object : PollEntryPoint.NodeBuilder {
+
+            override fun callback(callback: PollEntryPoint.Callback): PollEntryPoint.NodeBuilder {
+                plugins += callback
+                return this
+            }
+
+            override fun build(): Node {
+                return parentNode.createNode(buildContext, plugins)
+            }
+        }
+    }
+}
diff --git a/features/poll/impl/src/main/kotlin/io/element/android/features/poll/impl/PollFlowNode.kt b/features/poll/impl/src/main/kotlin/io/element/android/features/poll/impl/PollFlowNode.kt
new file mode 100644
index 0000000000..9dfeebc692
--- /dev/null
+++ b/features/poll/impl/src/main/kotlin/io/element/android/features/poll/impl/PollFlowNode.kt
@@ -0,0 +1,70 @@
+/*
+ * Copyright (c) 2023 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
+ *
+ *     http://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.features.poll.impl
+
+import android.os.Parcelable
+import androidx.compose.runtime.Composable
+import androidx.compose.ui.Modifier
+import com.bumble.appyx.core.composable.Children
+import com.bumble.appyx.core.modality.BuildContext
+import com.bumble.appyx.core.node.Node
+import com.bumble.appyx.core.plugin.Plugin
+import com.bumble.appyx.navmodel.backstack.BackStack
+import dagger.assisted.Assisted
+import dagger.assisted.AssistedInject
+import io.element.android.anvilannotations.ContributesNode
+import io.element.android.libraries.architecture.BackstackNode
+import io.element.android.libraries.architecture.animation.rememberDefaultTransitionHandler
+import io.element.android.libraries.architecture.createNode
+import io.element.android.libraries.di.SessionScope
+import kotlinx.parcelize.Parcelize
+
+@ContributesNode(SessionScope::class)
+class PollFlowNode @AssistedInject constructor(
+    @Assisted buildContext: BuildContext,
+    @Assisted plugins: List,
+) : BackstackNode(
+    backstack = BackStack(
+        initialElement = NavTarget.Root,
+        savedStateMap = buildContext.savedStateMap,
+    ),
+    buildContext = buildContext,
+    plugins = plugins,
+) {
+
+    sealed interface NavTarget : Parcelable {
+        @Parcelize
+        object Root : NavTarget
+    }
+
+    override fun resolve(navTarget: NavTarget, buildContext: BuildContext): Node {
+        return when (navTarget) {
+            NavTarget.Root -> {
+                createNode(buildContext)
+            }
+        }
+    }
+
+    @Composable
+    override fun View(modifier: Modifier) {
+        Children(
+            navModel = backstack,
+            modifier = modifier,
+            transitionHandler = rememberDefaultTransitionHandler(),
+        )
+    }
+}
diff --git a/features/preferences/impl/build.gradle.kts b/features/preferences/impl/build.gradle.kts
index f183f7f1fa..4ffca9d239 100644
--- a/features/preferences/impl/build.gradle.kts
+++ b/features/preferences/impl/build.gradle.kts
@@ -47,6 +47,7 @@ dependencies {
     implementation(projects.features.ftue.api)
     implementation(projects.libraries.matrixui)
     implementation(projects.features.logout.api)
+    implementation(projects.services.analytics.api)
     implementation(projects.services.toolbox.api)
     implementation(libs.datetime)
     implementation(libs.accompanist.placeholder)
@@ -68,6 +69,4 @@ dependencies {
     testImplementation(projects.features.analytics.test)
     testImplementation(projects.features.analytics.impl)
     testImplementation(projects.tests.testutils)
-
-    androidTestImplementation(libs.test.junitext)
 }
diff --git a/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/about/AboutView.kt b/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/about/AboutView.kt
index b7c2663b72..81075969c6 100644
--- a/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/about/AboutView.kt
+++ b/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/about/AboutView.kt
@@ -50,12 +50,12 @@ fun AboutView(
 
 @Preview
 @Composable
-fun AboutViewLightPreview(@PreviewParameter(AboutStateProvider::class) state: AboutState) =
+internal fun AboutViewLightPreview(@PreviewParameter(AboutStateProvider::class) state: AboutState) =
     ElementPreviewLight { ContentToPreview(state) }
 
 @Preview
 @Composable
-fun AboutViewDarkPreview(@PreviewParameter(AboutStateProvider::class) state: AboutState) =
+internal fun AboutViewDarkPreview(@PreviewParameter(AboutStateProvider::class) state: AboutState) =
     ElementPreviewDark { ContentToPreview(state) }
 
 @Composable
diff --git a/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/about/ElementLegal.kt b/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/about/ElementLegal.kt
index 81af611716..e09e0df8f8 100644
--- a/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/about/ElementLegal.kt
+++ b/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/about/ElementLegal.kt
@@ -19,17 +19,17 @@ package io.element.android.features.preferences.impl.about
 import androidx.annotation.StringRes
 import io.element.android.libraries.ui.strings.CommonStrings
 
-private const val CopyrightUrl = "https://element.io/copyright"
-private const val UsePolicyUrl = "https://element.io/acceptable-use-policy-terms"
-private const val PrivacyUrl = "https://element.io/privacy"
+private const val COPYRIGHT_URL = "https://element.io/copyright"
+private const val USE_POLICY_URL = "https://element.io/acceptable-use-policy-terms"
+private const val PRIVACY_URL = "https://element.io/privacy"
 
 sealed class ElementLegal(
     @StringRes val titleRes: Int,
     val url: String,
 ) {
-    object Copyright : ElementLegal(CommonStrings.common_copyright, CopyrightUrl)
-    object AcceptableUsePolicy : ElementLegal(CommonStrings.common_acceptable_use_policy, UsePolicyUrl)
-    object PrivacyPolicy : ElementLegal(CommonStrings.common_privacy_policy, PrivacyUrl)
+    object Copyright : ElementLegal(CommonStrings.common_copyright, COPYRIGHT_URL)
+    object AcceptableUsePolicy : ElementLegal(CommonStrings.common_acceptable_use_policy, USE_POLICY_URL)
+    object PrivacyPolicy : ElementLegal(CommonStrings.common_privacy_policy, PRIVACY_URL)
 }
 
 fun getAllLegals(): List {
diff --git a/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/analytics/AnalyticsSettingsView.kt b/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/analytics/AnalyticsSettingsView.kt
index 165406c6f5..3ee7365122 100644
--- a/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/analytics/AnalyticsSettingsView.kt
+++ b/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/analytics/AnalyticsSettingsView.kt
@@ -46,12 +46,12 @@ fun AnalyticsSettingsView(
 
 @Preview
 @Composable
-fun AnalyticsSettingsViewLightPreview(@PreviewParameter(AnalyticsSettingsStateProvider::class) state: AnalyticsSettingsState) =
+internal fun AnalyticsSettingsViewLightPreview(@PreviewParameter(AnalyticsSettingsStateProvider::class) state: AnalyticsSettingsState) =
     ElementPreviewLight { ContentToPreview(state) }
 
 @Preview
 @Composable
-fun AnalyticsSettingsViewDarkPreview(@PreviewParameter(AnalyticsSettingsStateProvider::class) state: AnalyticsSettingsState) =
+internal fun AnalyticsSettingsViewDarkPreview(@PreviewParameter(AnalyticsSettingsStateProvider::class) state: AnalyticsSettingsState) =
     ElementPreviewDark { ContentToPreview(state) }
 
 @Composable
diff --git a/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/developer/DeveloperSettingsView.kt b/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/developer/DeveloperSettingsView.kt
index 1ead19154d..23ea4faf86 100644
--- a/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/developer/DeveloperSettingsView.kt
+++ b/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/developer/DeveloperSettingsView.kt
@@ -56,6 +56,12 @@ fun DeveloperSettingsView(
         RageshakePreferencesView(
             state = state.rageshakeState,
         )
+        PreferenceCategory(title = "Crash", showDivider = false) {
+            PreferenceText(
+                title = "Crash the app 💥",
+                onClick = { error("This crash is a test.") }
+            )
+        }
         val cache = state.cacheSize
         PreferenceCategory(title = "Cache", showDivider = false) {
             PreferenceText(
@@ -90,12 +96,12 @@ fun FeatureListContent(
 
 @Preview
 @Composable
-fun DeveloperSettingsViewLightPreview(@PreviewParameter(DeveloperSettingsStateProvider::class) state: DeveloperSettingsState) =
+internal fun DeveloperSettingsViewLightPreview(@PreviewParameter(DeveloperSettingsStateProvider::class) state: DeveloperSettingsState) =
     ElementPreviewLight { ContentToPreview(state) }
 
 @Preview
 @Composable
-fun DeveloperSettingsViewDarkPreview(@PreviewParameter(DeveloperSettingsStateProvider::class) state: DeveloperSettingsState) =
+internal fun DeveloperSettingsViewDarkPreview(@PreviewParameter(DeveloperSettingsStateProvider::class) state: DeveloperSettingsState) =
     ElementPreviewDark { ContentToPreview(state) }
 
 @Composable
diff --git a/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/root/PreferencesRootPresenter.kt b/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/root/PreferencesRootPresenter.kt
index 66ff62ee2b..0cd2e7f7db 100644
--- a/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/root/PreferencesRootPresenter.kt
+++ b/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/root/PreferencesRootPresenter.kt
@@ -35,6 +35,7 @@ import io.element.android.libraries.matrix.api.user.MatrixUser
 import io.element.android.libraries.matrix.api.user.getCurrentUser
 import io.element.android.libraries.matrix.api.verification.SessionVerificationService
 import io.element.android.libraries.matrix.api.verification.SessionVerifiedStatus
+import io.element.android.services.analytics.api.AnalyticsService
 import kotlinx.coroutines.CoroutineScope
 import kotlinx.coroutines.launch
 import javax.inject.Inject
@@ -43,6 +44,7 @@ class PreferencesRootPresenter @Inject constructor(
     private val logoutPresenter: LogoutPreferencePresenter,
     private val matrixClient: MatrixClient,
     private val sessionVerificationService: SessionVerificationService,
+    private val analyticsService: AnalyticsService,
     private val buildType: BuildType,
     private val versionFormatter: VersionFormatter,
     private val snackbarDispatcher: SnackbarDispatcher,
@@ -58,6 +60,7 @@ class PreferencesRootPresenter @Inject constructor(
         }
 
         val snackbarMessage by snackbarDispatcher.collectSnackbarMessageAsState()
+        val hasAnalyticsProviders = remember { analyticsService.getAvailableAnalyticsProviders().isNotEmpty() }
 
         // Session verification status (unknown, not verified, verified)
         val sessionVerifiedStatus by sessionVerificationService.sessionVerifiedStatus.collectAsState()
@@ -72,6 +75,7 @@ class PreferencesRootPresenter @Inject constructor(
             myUser = matrixUser.value,
             version = versionFormatter.get(),
             showCompleteVerification = sessionIsNotVerified,
+            showAnalyticsSettings = hasAnalyticsProviders,
             showDeveloperSettings = showDeveloperSettings,
             snackbarMessage = snackbarMessage,
         )
diff --git a/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/root/PreferencesRootState.kt b/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/root/PreferencesRootState.kt
index 2b0963c53c..540c470815 100644
--- a/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/root/PreferencesRootState.kt
+++ b/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/root/PreferencesRootState.kt
@@ -25,6 +25,7 @@ data class PreferencesRootState(
     val myUser: MatrixUser?,
     val version: String,
     val showCompleteVerification: Boolean,
+    val showAnalyticsSettings: Boolean,
     val showDeveloperSettings: Boolean,
     val snackbarMessage: SnackbarMessage?,
 )
diff --git a/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/root/PreferencesRootStateProvider.kt b/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/root/PreferencesRootStateProvider.kt
index 9dbd54ffff..e8c148267f 100644
--- a/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/root/PreferencesRootStateProvider.kt
+++ b/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/root/PreferencesRootStateProvider.kt
@@ -25,6 +25,7 @@ fun aPreferencesRootState() = PreferencesRootState(
     myUser = null,
     version = "Version 1.1 (1)",
     showCompleteVerification = true,
+    showAnalyticsSettings = true,
     showDeveloperSettings = true,
     snackbarMessage = SnackbarMessage(CommonStrings.common_verification_complete),
 )
diff --git a/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/root/PreferencesRootView.kt b/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/root/PreferencesRootView.kt
index 01d790f8b9..556d940664 100644
--- a/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/root/PreferencesRootView.kt
+++ b/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/root/PreferencesRootView.kt
@@ -24,8 +24,6 @@ import androidx.compose.material.icons.outlined.DeveloperMode
 import androidx.compose.material.icons.outlined.Help
 import androidx.compose.material.icons.outlined.InsertChart
 import androidx.compose.material.icons.outlined.VerifiedUser
-import androidx.compose.material3.Snackbar
-import androidx.compose.material3.SnackbarHost
 import androidx.compose.runtime.Composable
 import androidx.compose.ui.Modifier
 import androidx.compose.ui.res.stringResource
@@ -41,6 +39,7 @@ import io.element.android.libraries.designsystem.preview.ElementPreviewLight
 import io.element.android.libraries.designsystem.preview.LargeHeightPreview
 import io.element.android.libraries.designsystem.theme.components.Divider
 import io.element.android.libraries.designsystem.theme.components.Text
+import io.element.android.libraries.designsystem.utils.SnackbarHost
 import io.element.android.libraries.designsystem.utils.rememberSnackbarHostState
 import io.element.android.libraries.matrix.api.user.MatrixUser
 import io.element.android.libraries.matrix.ui.components.MatrixUserProvider
@@ -65,13 +64,7 @@ fun PreferencesRootView(
         modifier = modifier,
         onBackPressed = onBackPressed,
         title = stringResource(id = CommonStrings.common_settings),
-        snackbarHost = {
-            SnackbarHost(snackbarHostState) { data ->
-                Snackbar(
-                    snackbarData = data,
-                )
-            }
-        }
+        snackbarHost = { SnackbarHost(snackbarHostState) }
     ) {
         UserPreferences(state.myUser)
         if (state.showCompleteVerification) {
@@ -82,11 +75,13 @@ fun PreferencesRootView(
             )
             Divider()
         }
-        PreferenceText(
-            title = stringResource(id = CommonStrings.common_analytics),
-            icon = Icons.Outlined.InsertChart,
-            onClick = onOpenAnalytics,
-        )
+        if (state.showAnalyticsSettings) {
+            PreferenceText(
+                title = stringResource(id = CommonStrings.common_analytics),
+                icon = Icons.Outlined.InsertChart,
+                onClick = onOpenAnalytics,
+            )
+        }
         PreferenceText(
             title = stringResource(id = CommonStrings.action_report_bug),
             icon = Icons.Outlined.BugReport,
@@ -127,12 +122,12 @@ fun DeveloperPreferencesView(onOpenDeveloperSettings: () -> Unit) {
 
 @LargeHeightPreview
 @Composable
-fun PreferencesRootViewLightPreview(@PreviewParameter(MatrixUserProvider::class) matrixUser: MatrixUser) =
+internal fun PreferencesRootViewLightPreview(@PreviewParameter(MatrixUserProvider::class) matrixUser: MatrixUser) =
     ElementPreviewLight { ContentToPreview(matrixUser) }
 
 @LargeHeightPreview
 @Composable
-fun PreferencesRootViewDarkPreview(@PreviewParameter(MatrixUserProvider::class) matrixUser: MatrixUser) =
+internal fun PreferencesRootViewDarkPreview(@PreviewParameter(MatrixUserProvider::class) matrixUser: MatrixUser) =
     ElementPreviewDark { ContentToPreview(matrixUser) }
 
 @Composable
diff --git a/features/preferences/impl/src/test/kotlin/io/element/android/features/preferences/impl/about/AboutPresenterTest.kt b/features/preferences/impl/src/test/kotlin/io/element/android/features/preferences/impl/about/AboutPresenterTest.kt
index 97fa158d09..4b025c10ad 100644
--- a/features/preferences/impl/src/test/kotlin/io/element/android/features/preferences/impl/about/AboutPresenterTest.kt
+++ b/features/preferences/impl/src/test/kotlin/io/element/android/features/preferences/impl/about/AboutPresenterTest.kt
@@ -16,7 +16,7 @@
 
 package io.element.android.features.preferences.impl.about
 
-import app.cash.molecule.RecompositionClock
+import app.cash.molecule.RecompositionMode
 import app.cash.molecule.moleculeFlow
 import app.cash.turbine.test
 import com.google.common.truth.Truth.assertThat
@@ -27,7 +27,7 @@ class AboutPresenterTest {
     @Test
     fun `present - initial state`() = runTest {
         val presenter = AboutPresenter()
-        moleculeFlow(RecompositionClock.Immediate) {
+        moleculeFlow(RecompositionMode.Immediate) {
             presenter.present()
         }.test {
             val initialState = awaitItem()
diff --git a/features/preferences/impl/src/test/kotlin/io/element/android/features/preferences/impl/analytics/AnalyticsAnalyticsSettingsPresenterTest.kt b/features/preferences/impl/src/test/kotlin/io/element/android/features/preferences/impl/analytics/AnalyticsAnalyticsSettingsPresenterTest.kt
index 5382ad0b37..29cc25e5be 100644
--- a/features/preferences/impl/src/test/kotlin/io/element/android/features/preferences/impl/analytics/AnalyticsAnalyticsSettingsPresenterTest.kt
+++ b/features/preferences/impl/src/test/kotlin/io/element/android/features/preferences/impl/analytics/AnalyticsAnalyticsSettingsPresenterTest.kt
@@ -16,7 +16,7 @@
 
 package io.element.android.features.preferences.impl.analytics
 
-import app.cash.molecule.RecompositionClock
+import app.cash.molecule.RecompositionMode
 import app.cash.molecule.moleculeFlow
 import app.cash.turbine.test
 import com.google.common.truth.Truth.assertThat
@@ -33,7 +33,7 @@ class AnalyticsAnalyticsSettingsPresenterTest {
         val presenter = AnalyticsSettingsPresenter(
             analyticsPresenter,
         )
-        moleculeFlow(RecompositionClock.Immediate) {
+        moleculeFlow(RecompositionMode.Immediate) {
             presenter.present()
         }.test {
             val initialState = awaitItem()
diff --git a/features/preferences/impl/src/test/kotlin/io/element/android/features/preferences/impl/developer/DeveloperSettingsPresenterTest.kt b/features/preferences/impl/src/test/kotlin/io/element/android/features/preferences/impl/developer/DeveloperSettingsPresenterTest.kt
index 87a556621c..9b1bda3631 100644
--- a/features/preferences/impl/src/test/kotlin/io/element/android/features/preferences/impl/developer/DeveloperSettingsPresenterTest.kt
+++ b/features/preferences/impl/src/test/kotlin/io/element/android/features/preferences/impl/developer/DeveloperSettingsPresenterTest.kt
@@ -16,7 +16,7 @@
 
 package io.element.android.features.preferences.impl.developer
 
-import app.cash.molecule.RecompositionClock
+import app.cash.molecule.RecompositionMode
 import app.cash.molecule.moleculeFlow
 import app.cash.turbine.test
 import com.google.common.truth.Truth.assertThat
@@ -41,7 +41,7 @@ class DeveloperSettingsPresenterTest {
             FakeClearCacheUseCase(),
             rageshakePresenter
         )
-        moleculeFlow(RecompositionClock.Immediate) {
+        moleculeFlow(RecompositionMode.Immediate) {
             presenter.present()
         }.test {
             val initialState = awaitItem()
@@ -65,7 +65,7 @@ class DeveloperSettingsPresenterTest {
             FakeClearCacheUseCase(),
             rageshakePresenter,
         )
-        moleculeFlow(RecompositionClock.Immediate) {
+        moleculeFlow(RecompositionMode.Immediate) {
             presenter.present()
         }.test {
             skipItems(1)
@@ -84,7 +84,7 @@ class DeveloperSettingsPresenterTest {
             FakeClearCacheUseCase(),
             rageshakePresenter,
         )
-        moleculeFlow(RecompositionClock.Immediate) {
+        moleculeFlow(RecompositionMode.Immediate) {
             presenter.present()
         }.test {
             skipItems(1)
@@ -109,7 +109,7 @@ class DeveloperSettingsPresenterTest {
             clearCacheUseCase,
             rageshakePresenter,
         )
-        moleculeFlow(RecompositionClock.Immediate) {
+        moleculeFlow(RecompositionMode.Immediate) {
             presenter.present()
         }.test {
             skipItems(1)
diff --git a/features/preferences/impl/src/test/kotlin/io/element/android/features/preferences/impl/root/PreferencesRootPresenterTest.kt b/features/preferences/impl/src/test/kotlin/io/element/android/features/preferences/impl/root/PreferencesRootPresenterTest.kt
index f3cf23599f..580426fcfa 100644
--- a/features/preferences/impl/src/test/kotlin/io/element/android/features/preferences/impl/root/PreferencesRootPresenterTest.kt
+++ b/features/preferences/impl/src/test/kotlin/io/element/android/features/preferences/impl/root/PreferencesRootPresenterTest.kt
@@ -16,10 +16,11 @@
 
 package io.element.android.features.preferences.impl.root
 
-import app.cash.molecule.RecompositionClock
+import app.cash.molecule.RecompositionMode
 import app.cash.molecule.moleculeFlow
 import app.cash.turbine.test
 import com.google.common.truth.Truth.assertThat
+import io.element.android.features.analytics.test.FakeAnalyticsService
 import io.element.android.features.logout.impl.DefaultLogoutPreferencePresenter
 import io.element.android.libraries.architecture.Async
 import io.element.android.libraries.core.meta.BuildType
@@ -41,11 +42,12 @@ class PreferencesRootPresenterTest {
             logoutPresenter,
             matrixClient,
             FakeSessionVerificationService(),
+            FakeAnalyticsService(),
             BuildType.DEBUG,
             FakeVersionFormatter(),
             SnackbarDispatcher(),
         )
-        moleculeFlow(RecompositionClock.Immediate) {
+        moleculeFlow(RecompositionMode.Immediate) {
             presenter.present()
         }.test {
             val initialState = awaitItem()
@@ -61,6 +63,7 @@ class PreferencesRootPresenterTest {
                 )
             )
             assertThat(loadedState.showDeveloperSettings).isEqualTo(true)
+            assertThat(loadedState.showAnalyticsSettings).isEqualTo(false)
         }
     }
 }
diff --git a/features/rageshake/api/src/main/kotlin/io/element/android/features/rageshake/api/detection/RageshakeDetectionState.kt b/features/rageshake/api/src/main/kotlin/io/element/android/features/rageshake/api/detection/RageshakeDetectionState.kt
index 5d6df8bac9..04f38597ed 100644
--- a/features/rageshake/api/src/main/kotlin/io/element/android/features/rageshake/api/detection/RageshakeDetectionState.kt
+++ b/features/rageshake/api/src/main/kotlin/io/element/android/features/rageshake/api/detection/RageshakeDetectionState.kt
@@ -17,7 +17,6 @@
 package io.element.android.features.rageshake.api.detection
 
 import androidx.compose.runtime.Immutable
-import androidx.compose.runtime.Stable
 import io.element.android.features.rageshake.api.preferences.RageshakePreferencesState
 
 @Immutable
diff --git a/features/rageshake/api/src/main/kotlin/io/element/android/features/rageshake/api/preferences/RageshakePreferencesView.kt b/features/rageshake/api/src/main/kotlin/io/element/android/features/rageshake/api/preferences/RageshakePreferencesView.kt
index 73e04fb5d4..3cc2a8211a 100644
--- a/features/rageshake/api/src/main/kotlin/io/element/android/features/rageshake/api/preferences/RageshakePreferencesView.kt
+++ b/features/rageshake/api/src/main/kotlin/io/element/android/features/rageshake/api/preferences/RageshakePreferencesView.kt
@@ -68,12 +68,12 @@ fun RageshakePreferencesView(
 
 @Preview
 @Composable
-fun RageshakePreferencesViewLightPreview(@PreviewParameter(RageshakePreferencesStateProvider::class) state: RageshakePreferencesState) =
+internal fun RageshakePreferencesViewLightPreview(@PreviewParameter(RageshakePreferencesStateProvider::class) state: RageshakePreferencesState) =
     ElementPreviewLight { ContentToPreview(state) }
 
 @Preview
 @Composable
-fun RageshakePreferencesViewDarkPreview(@PreviewParameter(RageshakePreferencesStateProvider::class) state: RageshakePreferencesState) =
+internal fun RageshakePreferencesViewDarkPreview(@PreviewParameter(RageshakePreferencesStateProvider::class) state: RageshakePreferencesState) =
     ElementPreviewDark { ContentToPreview(state) }
 
 @Composable
diff --git a/features/rageshake/api/src/main/kotlin/io/element/android/features/rageshake/api/reporter/BugReporter.kt b/features/rageshake/api/src/main/kotlin/io/element/android/features/rageshake/api/reporter/BugReporter.kt
index 0af13dcdda..99849ef1d4 100644
--- a/features/rageshake/api/src/main/kotlin/io/element/android/features/rageshake/api/reporter/BugReporter.kt
+++ b/features/rageshake/api/src/main/kotlin/io/element/android/features/rageshake/api/reporter/BugReporter.kt
@@ -16,6 +16,8 @@
 
 package io.element.android.features.rageshake.api.reporter
 
+import java.io.File
+
 interface BugReporter {
     /**
      * Send a bug report.
@@ -43,4 +45,14 @@ interface BugReporter {
         customFields: Map? = null,
         listener: BugReporterListener?
     )
+
+    /**
+     * Clean the log files if needed to avoid wasting disk space.
+     */
+    fun cleanLogDirectoryIfNeeded()
+
+    /**
+     * Provide the log directory.
+     */
+    fun logDirectory(): File
 }
diff --git a/features/rageshake/api/src/main/res/values-ru/translations.xml b/features/rageshake/api/src/main/res/values-ru/translations.xml
new file mode 100644
index 0000000000..6cb17a3401
--- /dev/null
+++ b/features/rageshake/api/src/main/res/values-ru/translations.xml
@@ -0,0 +1,5 @@
+
+
+  "При последнем использовании %1$s произошел сбой. Хотите поделиться отчетом о сбое?"
+  "Кажется, вы трясли телефон. Хотите открыть экран отчета об ошибке?"
+
diff --git a/features/rageshake/impl/build.gradle.kts b/features/rageshake/impl/build.gradle.kts
index 137a3bd070..464d521689 100644
--- a/features/rageshake/impl/build.gradle.kts
+++ b/features/rageshake/impl/build.gradle.kts
@@ -32,6 +32,7 @@ anvil {
 dependencies {
     implementation(projects.anvilannotations)
     anvil(projects.anvilcodegen)
+    implementation(projects.services.toolbox.api)
     implementation(projects.libraries.androidutils)
     implementation(projects.libraries.core)
     implementation(projects.libraries.network)
@@ -56,6 +57,4 @@ dependencies {
     testImplementation(libs.test.mockk)
     testImplementation(projects.libraries.matrix.test)
     testImplementation(projects.features.rageshake.test)
-
-    androidTestImplementation(libs.test.junitext)
 }
diff --git a/features/rageshake/impl/src/main/kotlin/io/element/android/features/rageshake/impl/bugreport/BugReportView.kt b/features/rageshake/impl/src/main/kotlin/io/element/android/features/rageshake/impl/bugreport/BugReportView.kt
index 74f3a13d13..32d45b29ff 100644
--- a/features/rageshake/impl/src/main/kotlin/io/element/android/features/rageshake/impl/bugreport/BugReportView.kt
+++ b/features/rageshake/impl/src/main/kotlin/io/element/android/features/rageshake/impl/bugreport/BugReportView.kt
@@ -31,6 +31,7 @@ import androidx.compose.ui.Modifier
 import androidx.compose.ui.platform.LocalContext
 import androidx.compose.ui.res.stringResource
 import androidx.compose.ui.text.input.ImeAction
+import androidx.compose.ui.text.input.KeyboardCapitalization
 import androidx.compose.ui.text.input.KeyboardType
 import androidx.compose.ui.tooling.preview.Preview
 import androidx.compose.ui.tooling.preview.PreviewParameter
@@ -47,8 +48,8 @@ import io.element.android.libraries.designsystem.components.preferences.Preferen
 import io.element.android.libraries.designsystem.preview.ElementPreviewDark
 import io.element.android.libraries.designsystem.preview.ElementPreviewLight
 import io.element.android.libraries.designsystem.preview.debugPlaceholderBackground
-import io.element.android.libraries.designsystem.theme.components.Button
 import io.element.android.libraries.designsystem.theme.components.CircularProgressIndicator
+import io.element.android.libraries.designsystem.theme.components.Button
 import io.element.android.libraries.designsystem.theme.components.OutlinedTextField
 import io.element.android.libraries.designsystem.theme.components.Text
 import io.element.android.libraries.designsystem.utils.LogCompositions
@@ -97,6 +98,7 @@ fun BugReportView(
                         eventSink(BugReportEvents.SetDescription(it))
                     },
                     keyboardOptions = KeyboardOptions(
+                        capitalization = KeyboardCapitalization.Sentences,
                         keyboardType = KeyboardType.Text,
                         imeAction = ImeAction.Next
                     ),
@@ -147,14 +149,13 @@ fun BugReportView(
             // Submit
             PreferenceRow {
                 Button(
+                    text = stringResource(id = CommonStrings.action_send),
                     onClick = { eventSink(BugReportEvents.SendBugReport) },
                     enabled = state.submitEnabled,
                     modifier = Modifier
                         .fillMaxWidth()
                         .padding(top = 24.dp, bottom = 16.dp)
-                ) {
-                    Text(text = stringResource(id = CommonStrings.action_send))
-                }
+                )
             }
         }
 
@@ -176,11 +177,11 @@ fun BugReportView(
 
 @Preview
 @Composable
-fun BugReportViewLightPreview(@PreviewParameter(BugReportStateProvider::class) state: BugReportState) = ElementPreviewLight { ContentToPreview(state) }
+internal fun BugReportViewLightPreview(@PreviewParameter(BugReportStateProvider::class) state: BugReportState) = ElementPreviewLight { ContentToPreview(state) }
 
 @Preview
 @Composable
-fun BugReportViewDarkPreview(@PreviewParameter(BugReportStateProvider::class) state: BugReportState) = ElementPreviewDark { ContentToPreview(state) }
+internal fun BugReportViewDarkPreview(@PreviewParameter(BugReportStateProvider::class) state: BugReportState) = ElementPreviewDark { ContentToPreview(state) }
 
 @Composable
 private fun ContentToPreview(state: BugReportState) {
diff --git a/features/rageshake/impl/src/main/kotlin/io/element/android/features/rageshake/impl/crash/VectorUncaughtExceptionHandler.kt b/features/rageshake/impl/src/main/kotlin/io/element/android/features/rageshake/impl/crash/VectorUncaughtExceptionHandler.kt
index a5e7edf405..b71c8af372 100644
--- a/features/rageshake/impl/src/main/kotlin/io/element/android/features/rageshake/impl/crash/VectorUncaughtExceptionHandler.kt
+++ b/features/rageshake/impl/src/main/kotlin/io/element/android/features/rageshake/impl/crash/VectorUncaughtExceptionHandler.kt
@@ -62,9 +62,9 @@ class VectorUncaughtExceptionHandler(
                 totalSize = info.totalMemory()
                 usedSize = totalSize - freeSize
             }
-            append("usedSize   " + usedSize / 1048576L + " MB\n")
-            append("freeSize   " + freeSize / 1048576L + " MB\n")
-            append("totalSize   " + totalSize / 1048576L + " MB\n")
+            append("usedSize   " + usedSize / 1_048_576L + " MB\n")
+            append("freeSize   " + freeSize / 1_048_576L + " MB\n")
+            append("totalSize   " + totalSize / 1_048_576L + " MB\n")
             append("Thread: ")
             append(thread.name)
             append(", Exception: ")
diff --git a/features/rageshake/impl/src/main/kotlin/io/element/android/features/rageshake/impl/logs/VectorFileLogger.kt b/features/rageshake/impl/src/main/kotlin/io/element/android/features/rageshake/impl/logs/VectorFileLogger.kt
index eea6c1dbbf..6b5d7c9096 100644
--- a/features/rageshake/impl/src/main/kotlin/io/element/android/features/rageshake/impl/logs/VectorFileLogger.kt
+++ b/features/rageshake/impl/src/main/kotlin/io/element/android/features/rageshake/impl/logs/VectorFileLogger.kt
@@ -48,7 +48,7 @@ class VectorFileLogger(
         }
 
         private const val SIZE_20MB = 20 * 1024 * 1024
-        private const val SIZE_50MB = 50 * 1024 * 1024
+        // private const val SIZE_50MB = 50 * 1024 * 1024
     }
 
     /*
diff --git a/features/rageshake/impl/src/main/kotlin/io/element/android/features/rageshake/impl/reporter/DefaultBugReporter.kt b/features/rageshake/impl/src/main/kotlin/io/element/android/features/rageshake/impl/reporter/DefaultBugReporter.kt
index 5695596650..a8491b5a74 100755
--- a/features/rageshake/impl/src/main/kotlin/io/element/android/features/rageshake/impl/reporter/DefaultBugReporter.kt
+++ b/features/rageshake/impl/src/main/kotlin/io/element/android/features/rageshake/impl/reporter/DefaultBugReporter.kt
@@ -18,6 +18,7 @@ package io.element.android.features.rageshake.impl.reporter
 
 import android.content.Context
 import android.os.Build
+import android.text.format.DateUtils.DAY_IN_MILLIS
 import androidx.core.net.toFile
 import androidx.core.net.toUri
 import com.squareup.anvil.annotations.ContributesBinding
@@ -27,10 +28,10 @@ import io.element.android.features.rageshake.api.reporter.BugReporterListener
 import io.element.android.features.rageshake.api.reporter.ReportType
 import io.element.android.features.rageshake.api.screenshot.ScreenshotHolder
 import io.element.android.features.rageshake.impl.R
-import io.element.android.features.rageshake.impl.logs.VectorFileLogger
 import io.element.android.libraries.androidutils.file.compressFile
 import io.element.android.libraries.androidutils.file.safeDelete
 import io.element.android.libraries.core.coroutine.CoroutineDispatchers
+import io.element.android.libraries.core.data.tryOrNull
 import io.element.android.libraries.core.extensions.toOnOff
 import io.element.android.libraries.core.meta.BuildMeta
 import io.element.android.libraries.core.mimetype.MimeTypes
@@ -38,7 +39,10 @@ import io.element.android.libraries.di.AppScope
 import io.element.android.libraries.di.ApplicationContext
 import io.element.android.libraries.network.useragent.UserAgentProvider
 import io.element.android.libraries.sessionstorage.api.SessionStore
+import io.element.android.services.toolbox.api.systemclock.SystemClock
+import kotlinx.coroutines.CoroutineScope
 import kotlinx.coroutines.flow.first
+import kotlinx.coroutines.launch
 import kotlinx.coroutines.withContext
 import okhttp3.Call
 import okhttp3.MediaType.Companion.toMediaTypeOrNull
@@ -65,6 +69,8 @@ class DefaultBugReporter @Inject constructor(
     @ApplicationContext private val context: Context,
     private val screenshotHolder: ScreenshotHolder,
     private val crashDataStore: CrashDataStore,
+    private val coroutineScope: CoroutineScope,
+    private val systemClock: SystemClock,
     private val coroutineDispatchers: CoroutineDispatchers,
     private val okHttpClient: Provider,
     private val userAgentProvider: UserAgentProvider,
@@ -87,7 +93,8 @@ class DefaultBugReporter @Inject constructor(
         // filenames
         private const val LOG_CAT_ERROR_FILENAME = "logcatError.log"
         private const val LOG_CAT_FILENAME = "logcat.log"
-        private const val KEY_REQUESTS_FILENAME = "keyRequests.log"
+        private const val LOG_DIRECTORY_NAME = "logs"
+        // private const val KEY_REQUESTS_FILENAME = "keyRequests.log"
 
         private const val BUFFER_SIZE = 1024 * 1024 * 50
     }
@@ -103,7 +110,7 @@ class DefaultBugReporter @Inject constructor(
             .adapter(Types.newParameterizedType(Map::class.java, String::class.java, Any::class.java))
      */
 
-    private val LOGCAT_CMD_ERROR = arrayOf(
+    private val logcatCommandError = arrayOf(
         "logcat", // /< Run 'logcat' command
         "-d", // /< Dump the log rather than continue outputting it
         "-v", // formatting
@@ -114,7 +121,7 @@ class DefaultBugReporter @Inject constructor(
             "*:S" // /< Everything else silent, so don't pick it..
     )
 
-    private val LOGCAT_CMD_DEBUG = arrayOf("logcat", "-d", "-v", "threadtime", "*:*")
+    private val logcatCommandDebug = arrayOf("logcat", "-d", "-v", "threadtime", "*:*")
 
     /**
      * Send a bug report.
@@ -158,9 +165,8 @@ class DefaultBugReporter @Inject constructor(
 
             val gzippedFiles = ArrayList()
 
-            val vectorFileLogger = VectorFileLogger.getFromTimber()
-            if (withDevicesLogs && vectorFileLogger != null) {
-                val files = vectorFileLogger.getLogFiles()
+            if (withDevicesLogs) {
+                val files = getLogFiles()
                 files.mapNotNullTo(gzippedFiles) { f ->
                     if (!mIsCancelled) {
                         compressFile(f)
@@ -168,6 +174,7 @@ class DefaultBugReporter @Inject constructor(
                         null
                     }
                 }
+                files.deleteAllExceptMostRecent()
             }
 
             if (!mIsCancelled && (withCrashLogs || withDevicesLogs)) {
@@ -458,6 +465,54 @@ class DefaultBugReporter @Inject constructor(
         )
     }
 
+    override fun logDirectory(): File {
+        return File(context.cacheDir, LOG_DIRECTORY_NAME)
+    }
+
+    override fun cleanLogDirectoryIfNeeded() {
+        coroutineScope.launch(coroutineDispatchers.io) {
+            // delete the log files older than 1 day, except the most recent one
+            deleteOldLogFiles(systemClock.epochMillis() - DAY_IN_MILLIS)
+        }
+    }
+
+    /**
+     * @return the files on the log directory.
+     */
+    private fun getLogFiles(): List {
+        return tryOrNull(
+            onError = { Timber.e(it, "## getLogFiles() failed") }
+        ) {
+            val logDirectory = logDirectory()
+            logDirectory.listFiles()?.toList()
+        }.orEmpty()
+    }
+
+    /**
+     * Delete the log files older than the given time except the most recent one.
+     * @param time the time in ms
+     */
+    private fun deleteOldLogFiles(time: Long) {
+        val logFiles = getLogFiles()
+        val oldLogFiles = logFiles.filter { it.lastModified() < time }
+        oldLogFiles.deleteAllExceptMostRecent()
+    }
+
+    /**
+     * Delete all the log files except the most recent one.
+     *
+     */
+    private fun List.deleteAllExceptMostRecent() {
+        if (size > 1) {
+            val mostRecentFile = maxByOrNull { it.lastModified() }
+            forEach { file ->
+                if (file != mostRecentFile) {
+                    file.safeDelete()
+                }
+            }
+        }
+    }
+
     // ==============================================================================================================
     // Logcat management
     // ==============================================================================================================
@@ -485,6 +540,10 @@ class DefaultBugReporter @Inject constructor(
             Timber.e(error, "## saveLogCat() : fail to write logcat OOM")
         } catch (e: Exception) {
             Timber.e(e, "## saveLogCat() : fail to write logcat")
+        } finally {
+            if (logCatErrFile.exists()) {
+                logCatErrFile.safeDelete()
+            }
         }
 
         return null
@@ -500,7 +559,7 @@ class DefaultBugReporter @Inject constructor(
         val logcatProc: Process
 
         try {
-            logcatProc = Runtime.getRuntime().exec(if (isErrorLogCat) LOGCAT_CMD_ERROR else LOGCAT_CMD_DEBUG)
+            logcatProc = Runtime.getRuntime().exec(if (isErrorLogCat) logcatCommandError else logcatCommandDebug)
         } catch (e1: IOException) {
             return
         }
diff --git a/features/rageshake/impl/src/main/res/values-de/translations.xml b/features/rageshake/impl/src/main/res/values-de/translations.xml
index a24318545d..b316d8b45e 100644
--- a/features/rageshake/impl/src/main/res/values-de/translations.xml
+++ b/features/rageshake/impl/src/main/res/values-de/translations.xml
@@ -1,14 +1,14 @@
 
 
   "Bildschirmfoto anhängen"
-  "Sie können mich kontaktieren, wenn Sie weitere Fragen haben"
+  "Ihr könnt mich kontaktieren, wenn ihr weitere Fragen habt"
   "Kontaktiere mich"
   "Bildschirmfoto bearbeiten"
   "Beschreibe bitte den Fehler. Was hast du gemacht? Was hätte passieren sollen? Was ist passiert? Bitte beschreibe alles mit so vielen Details wie möglich."
   "Beschreibe den Fehler…"
-  "Wenn möglich, verfassen Sie die Beschreibung bitte auf Englisch."
+  "Wenn möglich, verfasse die Beschreibung bitte auf Englisch."
   "Absturzprotokolle senden"
-  "Senden Sie Protokolle, um zu helfen"
+  "Logs zulassen"
   "Bildschirmfoto senden"
   "Um zu überprüfen, ob alles wie vorgesehen funktioniert, werden Protokolle mit deiner Nachricht gesendet. Diese werden privat sein. Um nur Ihre Nachricht zu senden, schalte diese Einstellung aus."
   "%1$s ist bei der letzten Verwendung abgestürzt. Möchtest du uns einen Absturzbericht senden?"
diff --git a/features/rageshake/impl/src/main/res/values-fr/translations.xml b/features/rageshake/impl/src/main/res/values-fr/translations.xml
index bf6ad2d215..53b95af6be 100644
--- a/features/rageshake/impl/src/main/res/values-fr/translations.xml
+++ b/features/rageshake/impl/src/main/res/values-fr/translations.xml
@@ -1,7 +1,7 @@
 
 
   "Joindre une capture d\'écran"
-  "Vous pouvez me contacter si vous avez des questions complémentaires"
+  "Vous pouvez me contacter si vous avez des questions complémentaires."
   "Me contacter"
   "Modifier la capture d\'écran"
   "S\'il vous plait, veuillez décrire le bogue. Qu\'avez-vous fait ? À quoi vous attendiez-vous ? Que s\'est-il réellement passé. Veuillez ajouter le plus de détails possible."
diff --git a/features/rageshake/impl/src/main/res/values-ru/translations.xml b/features/rageshake/impl/src/main/res/values-ru/translations.xml
new file mode 100644
index 0000000000..8f05a3148d
--- /dev/null
+++ b/features/rageshake/impl/src/main/res/values-ru/translations.xml
@@ -0,0 +1,15 @@
+
+
+  "Приложить снимок экрана"
+  "Вы можете связаться со мной, если у Вас возникнут какие-либо дополнительные вопросы."
+  "Связаться со мной"
+  "Редактировать снимок экрана"
+  "Пожалуйста, опишите ошибку. Что вы сделали? Что вы ожидали, что произойдет? Что произошло на самом деле. Пожалуйста, опишите все как можно подробнее."
+  "Опишите ошибку…"
+  "Если возможно, пожалуйста, напишите описание на английском языке."
+  "Отправка журналов сбоев"
+  "Разрешить ведение журналов"
+  "Отправить снимок экрана"
+  "Чтобы убедиться, что все работает правильно, в сообщение будут включены журналы. Чтобы отправить сообщение без журналов, отключите эту настройку."
+  "При последнем использовании %1$s произошел сбой. Хотите поделиться отчетом о сбое?"
+
diff --git a/features/rageshake/impl/src/main/res/values-sk/translations.xml b/features/rageshake/impl/src/main/res/values-sk/translations.xml
index cb530d1712..51222367a6 100644
--- a/features/rageshake/impl/src/main/res/values-sk/translations.xml
+++ b/features/rageshake/impl/src/main/res/values-sk/translations.xml
@@ -1,7 +1,7 @@
 
 
   "Priložiť snímku obrazovky"
-  "V prípade ďalších otázok ma môžete kontaktovať"
+  "V prípade ďalších otázok ma môžete kontaktovať."
   "Kontaktujte ma"
   "Upraviť snímku obrazovky"
   "Popíšte prosím chybu. Čo ste urobili? Čo ste očakávali, že sa stane? Čo sa skutočne stalo. Prosím, uveďte čo najviac podrobností."
diff --git a/features/rageshake/impl/src/main/res/values-zh-rTW/translations.xml b/features/rageshake/impl/src/main/res/values-zh-rTW/translations.xml
new file mode 100644
index 0000000000..6e9eaabed3
--- /dev/null
+++ b/features/rageshake/impl/src/main/res/values-zh-rTW/translations.xml
@@ -0,0 +1,7 @@
+
+
+  "附上螢幕截圖"
+  "聯絡我"
+  "編輯螢幕截圖"
+  "傳送螢幕截圖"
+
diff --git a/features/rageshake/impl/src/test/kotlin/io/element/android/features/rageshake/impl/bugreport/BugReportPresenterTest.kt b/features/rageshake/impl/src/test/kotlin/io/element/android/features/rageshake/impl/bugreport/BugReportPresenterTest.kt
index 9b868a637d..c0418783dd 100644
--- a/features/rageshake/impl/src/test/kotlin/io/element/android/features/rageshake/impl/bugreport/BugReportPresenterTest.kt
+++ b/features/rageshake/impl/src/test/kotlin/io/element/android/features/rageshake/impl/bugreport/BugReportPresenterTest.kt
@@ -16,7 +16,7 @@
 
 package io.element.android.features.rageshake.impl.bugreport
 
-import app.cash.molecule.RecompositionClock
+import app.cash.molecule.RecompositionMode
 import app.cash.molecule.moleculeFlow
 import app.cash.turbine.test
 import com.google.common.truth.Truth.assertThat
@@ -41,7 +41,7 @@ class BugReportPresenterTest {
             FakeScreenshotHolder(),
             this,
         )
-        moleculeFlow(RecompositionClock.Immediate) {
+        moleculeFlow(RecompositionMode.Immediate) {
             presenter.present()
         }.test {
             val initialState = awaitItem()
@@ -62,7 +62,7 @@ class BugReportPresenterTest {
             FakeScreenshotHolder(),
             this,
         )
-        moleculeFlow(RecompositionClock.Immediate) {
+        moleculeFlow(RecompositionMode.Immediate) {
             presenter.present()
         }.test {
             val initialState = awaitItem()
@@ -81,7 +81,7 @@ class BugReportPresenterTest {
             FakeScreenshotHolder(),
             this,
         )
-        moleculeFlow(RecompositionClock.Immediate) {
+        moleculeFlow(RecompositionMode.Immediate) {
             presenter.present()
         }.test {
             val initialState = awaitItem()
@@ -100,7 +100,7 @@ class BugReportPresenterTest {
             FakeScreenshotHolder(),
             this,
         )
-        moleculeFlow(RecompositionClock.Immediate) {
+        moleculeFlow(RecompositionMode.Immediate) {
             presenter.present()
         }.test {
             val initialState = awaitItem()
@@ -120,7 +120,7 @@ class BugReportPresenterTest {
             FakeScreenshotHolder(),
             this,
         )
-        moleculeFlow(RecompositionClock.Immediate) {
+        moleculeFlow(RecompositionMode.Immediate) {
             presenter.present()
         }.test {
             val initialState = awaitItem()
@@ -139,7 +139,7 @@ class BugReportPresenterTest {
             FakeScreenshotHolder(screenshotUri = A_SCREENSHOT_URI),
             this,
         )
-        moleculeFlow(RecompositionClock.Immediate) {
+        moleculeFlow(RecompositionMode.Immediate) {
             presenter.present()
         }.test {
             skipItems(1)
@@ -161,7 +161,7 @@ class BugReportPresenterTest {
             FakeScreenshotHolder(screenshotUri = A_SCREENSHOT_URI),
             this,
         )
-        moleculeFlow(RecompositionClock.Immediate) {
+        moleculeFlow(RecompositionMode.Immediate) {
             presenter.present()
         }.test {
             val initialState = awaitItem()
@@ -186,7 +186,7 @@ class BugReportPresenterTest {
             FakeScreenshotHolder(screenshotUri = A_SCREENSHOT_URI),
             this,
         )
-        moleculeFlow(RecompositionClock.Immediate) {
+        moleculeFlow(RecompositionMode.Immediate) {
             presenter.present()
         }.test {
             val initialState = awaitItem()
@@ -215,7 +215,7 @@ class BugReportPresenterTest {
             FakeScreenshotHolder(screenshotUri = A_SCREENSHOT_URI),
             this,
         )
-        moleculeFlow(RecompositionClock.Immediate) {
+        moleculeFlow(RecompositionMode.Immediate) {
             presenter.present()
         }.test {
             val initialState = awaitItem()
diff --git a/features/rageshake/impl/src/test/kotlin/io/element/android/features/rageshake/impl/bugreport/FakeBugReporter.kt b/features/rageshake/impl/src/test/kotlin/io/element/android/features/rageshake/impl/bugreport/FakeBugReporter.kt
index ac8940a1ac..82edaf563d 100644
--- a/features/rageshake/impl/src/test/kotlin/io/element/android/features/rageshake/impl/bugreport/FakeBugReporter.kt
+++ b/features/rageshake/impl/src/test/kotlin/io/element/android/features/rageshake/impl/bugreport/FakeBugReporter.kt
@@ -21,6 +21,7 @@ import io.element.android.features.rageshake.api.reporter.BugReporterListener
 import io.element.android.features.rageshake.api.reporter.ReportType
 import io.element.android.libraries.matrix.test.A_FAILURE_REASON
 import kotlinx.coroutines.delay
+import java.io.File
 
 class FakeBugReporter(val mode: FakeBugReporterMode = FakeBugReporterMode.Success) : BugReporter {
     override suspend fun sendBugReport(
@@ -55,6 +56,14 @@ class FakeBugReporter(val mode: FakeBugReporterMode = FakeBugReporterMode.Succes
         delay(100)
         listener?.onUploadSucceed(null)
     }
+
+    override fun cleanLogDirectoryIfNeeded() {
+        // No op
+    }
+
+    override fun logDirectory(): File {
+        return File("fake")
+    }
 }
 
 enum class FakeBugReporterMode {
diff --git a/features/rageshake/impl/src/test/kotlin/io/element/android/features/rageshake/impl/crash/ui/CrashDetectionPresenterTest.kt b/features/rageshake/impl/src/test/kotlin/io/element/android/features/rageshake/impl/crash/ui/CrashDetectionPresenterTest.kt
index 2d9834607f..b8b8c4b6d0 100644
--- a/features/rageshake/impl/src/test/kotlin/io/element/android/features/rageshake/impl/crash/ui/CrashDetectionPresenterTest.kt
+++ b/features/rageshake/impl/src/test/kotlin/io/element/android/features/rageshake/impl/crash/ui/CrashDetectionPresenterTest.kt
@@ -16,7 +16,7 @@
 
 package io.element.android.features.rageshake.impl.crash.ui
 
-import app.cash.molecule.RecompositionClock
+import app.cash.molecule.RecompositionMode
 import app.cash.molecule.moleculeFlow
 import app.cash.turbine.test
 import com.google.common.truth.Truth.assertThat
@@ -33,7 +33,7 @@ class CrashDetectionPresenterTest {
         val presenter = DefaultCrashDetectionPresenter(
             FakeCrashDataStore()
         )
-        moleculeFlow(RecompositionClock.Immediate) {
+        moleculeFlow(RecompositionMode.Immediate) {
             presenter.present()
         }.test {
             val initialState = awaitItem()
@@ -46,7 +46,7 @@ class CrashDetectionPresenterTest {
         val presenter = DefaultCrashDetectionPresenter(
             FakeCrashDataStore(appHasCrashed = true)
         )
-        moleculeFlow(RecompositionClock.Immediate) {
+        moleculeFlow(RecompositionMode.Immediate) {
             presenter.present()
         }.test {
             skipItems(1)
@@ -61,7 +61,7 @@ class CrashDetectionPresenterTest {
         val presenter = DefaultCrashDetectionPresenter(
             FakeCrashDataStore(appHasCrashed = true)
         )
-        moleculeFlow(RecompositionClock.Immediate) {
+        moleculeFlow(RecompositionMode.Immediate) {
             presenter.present()
         }.test {
             skipItems(1)
@@ -77,7 +77,7 @@ class CrashDetectionPresenterTest {
         val presenter = DefaultCrashDetectionPresenter(
             FakeCrashDataStore(appHasCrashed = true, crashData = A_CRASH_DATA)
         )
-        moleculeFlow(RecompositionClock.Immediate) {
+        moleculeFlow(RecompositionMode.Immediate) {
             presenter.present()
         }.test {
             skipItems(1)
diff --git a/features/rageshake/impl/src/test/kotlin/io/element/android/features/rageshake/impl/detection/RageshakeDetectionPresenterTest.kt b/features/rageshake/impl/src/test/kotlin/io/element/android/features/rageshake/impl/detection/RageshakeDetectionPresenterTest.kt
index eb49eb450e..02a0fc0794 100644
--- a/features/rageshake/impl/src/test/kotlin/io/element/android/features/rageshake/impl/detection/RageshakeDetectionPresenterTest.kt
+++ b/features/rageshake/impl/src/test/kotlin/io/element/android/features/rageshake/impl/detection/RageshakeDetectionPresenterTest.kt
@@ -17,7 +17,7 @@
 package io.element.android.features.rageshake.impl.detection
 
 import android.graphics.Bitmap
-import app.cash.molecule.RecompositionClock
+import app.cash.molecule.RecompositionMode
 import app.cash.molecule.moleculeFlow
 import app.cash.turbine.test
 import com.google.common.truth.Truth.assertThat
@@ -59,7 +59,7 @@ class RageshakeDetectionPresenterTest {
                 rageshakeDataStore = rageshakeDataStore,
             )
         )
-        moleculeFlow(RecompositionClock.Immediate) {
+        moleculeFlow(RecompositionMode.Immediate) {
             presenter.present()
         }.test {
             skipItems(1)
@@ -83,7 +83,7 @@ class RageshakeDetectionPresenterTest {
                 rageshakeDataStore = rageshakeDataStore,
             )
         )
-        moleculeFlow(RecompositionClock.Immediate) {
+        moleculeFlow(RecompositionMode.Immediate) {
             presenter.present()
         }.test {
             skipItems(1)
@@ -108,7 +108,7 @@ class RageshakeDetectionPresenterTest {
                 rageshakeDataStore = rageshakeDataStore,
             )
         )
-        moleculeFlow(RecompositionClock.Immediate) {
+        moleculeFlow(RecompositionMode.Immediate) {
             presenter.present()
         }.test {
             skipItems(1)
@@ -142,7 +142,7 @@ class RageshakeDetectionPresenterTest {
                 rageshakeDataStore = rageshakeDataStore,
             )
         )
-        moleculeFlow(RecompositionClock.Immediate) {
+        moleculeFlow(RecompositionMode.Immediate) {
             presenter.present()
         }.test {
             skipItems(1)
@@ -176,7 +176,7 @@ class RageshakeDetectionPresenterTest {
                 rageshakeDataStore = rageshakeDataStore,
             )
         )
-        moleculeFlow(RecompositionClock.Immediate) {
+        moleculeFlow(RecompositionMode.Immediate) {
             presenter.present()
         }.test {
             skipItems(1)
diff --git a/features/rageshake/impl/src/test/kotlin/io/element/android/features/rageshake/impl/preferences/RageshakePreferencesPresenterTest.kt b/features/rageshake/impl/src/test/kotlin/io/element/android/features/rageshake/impl/preferences/RageshakePreferencesPresenterTest.kt
index b01ce22645..56759c360c 100644
--- a/features/rageshake/impl/src/test/kotlin/io/element/android/features/rageshake/impl/preferences/RageshakePreferencesPresenterTest.kt
+++ b/features/rageshake/impl/src/test/kotlin/io/element/android/features/rageshake/impl/preferences/RageshakePreferencesPresenterTest.kt
@@ -16,7 +16,7 @@
 
 package io.element.android.features.rageshake.impl.preferences
 
-import app.cash.molecule.RecompositionClock
+import app.cash.molecule.RecompositionMode
 import app.cash.molecule.moleculeFlow
 import app.cash.turbine.test
 import com.google.common.truth.Truth.assertThat
@@ -34,7 +34,7 @@ class RageshakePreferencesPresenterTest {
             FakeRageShake(isAvailableValue = true),
             FakeRageshakeDataStore(isEnabled = true)
         )
-        moleculeFlow(RecompositionClock.Immediate) {
+        moleculeFlow(RecompositionMode.Immediate) {
             presenter.present()
         }.test {
             skipItems(1)
@@ -50,7 +50,7 @@ class RageshakePreferencesPresenterTest {
             FakeRageShake(isAvailableValue = false),
             FakeRageshakeDataStore(isEnabled = true)
         )
-        moleculeFlow(RecompositionClock.Immediate) {
+        moleculeFlow(RecompositionMode.Immediate) {
             presenter.present()
         }.test {
             skipItems(1)
@@ -66,7 +66,7 @@ class RageshakePreferencesPresenterTest {
             FakeRageShake(isAvailableValue = true),
             FakeRageshakeDataStore(isEnabled = true)
         )
-        moleculeFlow(RecompositionClock.Immediate) {
+        moleculeFlow(RecompositionMode.Immediate) {
             presenter.present()
         }.test {
             skipItems(1)
@@ -85,7 +85,7 @@ class RageshakePreferencesPresenterTest {
             FakeRageShake(isAvailableValue = true),
             FakeRageshakeDataStore(isEnabled = true)
         )
-        moleculeFlow(RecompositionClock.Immediate) {
+        moleculeFlow(RecompositionMode.Immediate) {
             presenter.present()
         }.test {
             skipItems(1)
diff --git a/features/roomdetails/impl/src/main/kotlin/io/element/android/features/roomdetails/impl/RoomDetailsView.kt b/features/roomdetails/impl/src/main/kotlin/io/element/android/features/roomdetails/impl/RoomDetailsView.kt
index 9aa8ea41c3..51754ca6de 100644
--- a/features/roomdetails/impl/src/main/kotlin/io/element/android/features/roomdetails/impl/RoomDetailsView.kt
+++ b/features/roomdetails/impl/src/main/kotlin/io/element/android/features/roomdetails/impl/RoomDetailsView.kt
@@ -17,18 +17,15 @@
 package io.element.android.features.roomdetails.impl
 
 import androidx.compose.foundation.layout.Arrangement
-import androidx.compose.foundation.layout.Box
 import androidx.compose.foundation.layout.Column
 import androidx.compose.foundation.layout.ExperimentalLayoutApi
 import androidx.compose.foundation.layout.Row
 import androidx.compose.foundation.layout.Spacer
 import androidx.compose.foundation.layout.consumeWindowInsets
-import androidx.compose.foundation.layout.fillMaxSize
 import androidx.compose.foundation.layout.fillMaxWidth
 import androidx.compose.foundation.layout.height
 import androidx.compose.foundation.layout.padding
 import androidx.compose.foundation.layout.size
-import androidx.compose.foundation.layout.widthIn
 import androidx.compose.foundation.rememberScrollState
 import androidx.compose.foundation.verticalScroll
 import androidx.compose.material.icons.Icons
@@ -50,6 +47,7 @@ import androidx.compose.ui.Modifier
 import androidx.compose.ui.graphics.vector.ImageVector
 import androidx.compose.ui.res.stringResource
 import androidx.compose.ui.res.vectorResource
+import androidx.compose.ui.text.style.TextAlign
 import androidx.compose.ui.tooling.preview.PreviewParameter
 import androidx.compose.ui.unit.dp
 import io.element.android.features.leaveroom.api.LeaveRoomView
@@ -69,7 +67,6 @@ import io.element.android.libraries.designsystem.preview.ElementPreviewLight
 import io.element.android.libraries.designsystem.preview.LargeHeightPreview
 import io.element.android.libraries.designsystem.theme.components.DropdownMenu
 import io.element.android.libraries.designsystem.theme.components.DropdownMenuItem
-import io.element.android.libraries.designsystem.theme.components.DropdownMenuItemText
 import io.element.android.libraries.designsystem.theme.components.Icon
 import io.element.android.libraries.designsystem.theme.components.IconButton
 import io.element.android.libraries.designsystem.theme.components.Scaffold
@@ -197,7 +194,7 @@ internal fun RoomDetailsTopBar(
                     onDismissRequest = { showMenu = false },
                 ) {
                     DropdownMenuItem(
-                        text = { DropdownMenuItemText(stringResource(id = CommonStrings.action_edit)) },
+                        text = { Text(stringResource(id = CommonStrings.action_edit)) },
                         onClick = {
                             // Explicitly close the menu before handling the action, as otherwise it stays open during the
                             // transition and renders really badly.
@@ -226,18 +223,30 @@ internal fun RoomHeaderSection(
     roomAlias: String?,
     modifier: Modifier = Modifier
 ) {
-    Column(modifier.fillMaxWidth(), horizontalAlignment = Alignment.CenterHorizontally) {
-        Box(modifier = Modifier.size(70.dp)) {
-            Avatar(
-                avatarData = AvatarData(roomId, roomName, avatarUrl, AvatarSize.RoomHeader),
-                modifier = Modifier.fillMaxSize()
-            )
-        }
+    Column(
+        modifier = modifier
+            .fillMaxWidth()
+            .padding(horizontal = 16.dp),
+        horizontalAlignment = Alignment.CenterHorizontally,
+    ) {
+        Avatar(
+            avatarData = AvatarData(roomId, roomName, avatarUrl, AvatarSize.RoomHeader),
+            modifier = Modifier.size(70.dp)
+        )
         Spacer(modifier = Modifier.height(24.dp))
-        Text(roomName, style = ElementTheme.typography.fontHeadingLgBold)
+        Text(
+            text = roomName,
+            style = ElementTheme.typography.fontHeadingLgBold,
+            textAlign = TextAlign.Center,
+        )
         if (roomAlias != null) {
             Spacer(modifier = Modifier.height(6.dp))
-            Text(roomAlias, style = ElementTheme.typography.fontBodyLgRegular, color = MaterialTheme.colorScheme.secondary)
+            Text(
+                text = roomAlias,
+                style = ElementTheme.typography.fontBodyLgRegular,
+                color = MaterialTheme.colorScheme.secondary,
+                textAlign = TextAlign.Center,
+            )
         }
         Spacer(Modifier.height(32.dp))
     }
@@ -322,12 +331,12 @@ internal fun OtherActionsSection(onLeaveRoom: () -> Unit, modifier: Modifier = M
 
 @LargeHeightPreview
 @Composable
-fun RoomDetailsLightPreview(@PreviewParameter(RoomDetailsStateProvider::class) state: RoomDetailsState) =
+internal fun RoomDetailsLightPreview(@PreviewParameter(RoomDetailsStateProvider::class) state: RoomDetailsState) =
     ElementPreviewLight { ContentToPreview(state) }
 
 @LargeHeightPreview
 @Composable
-fun RoomDetailsDarkPreview(@PreviewParameter(RoomDetailsStateProvider::class) state: RoomDetailsState) =
+internal fun RoomDetailsDarkPreview(@PreviewParameter(RoomDetailsStateProvider::class) state: RoomDetailsState) =
     ElementPreviewDark { ContentToPreview(state) }
 
 @Composable
diff --git a/features/roomdetails/impl/src/main/kotlin/io/element/android/features/roomdetails/impl/edit/RoomDetailsEditView.kt b/features/roomdetails/impl/src/main/kotlin/io/element/android/features/roomdetails/impl/edit/RoomDetailsEditView.kt
index 029f5ac5df..cd0cbf878e 100644
--- a/features/roomdetails/impl/src/main/kotlin/io/element/android/features/roomdetails/impl/edit/RoomDetailsEditView.kt
+++ b/features/roomdetails/impl/src/main/kotlin/io/element/android/features/roomdetails/impl/edit/RoomDetailsEditView.kt
@@ -34,6 +34,7 @@ import androidx.compose.foundation.layout.padding
 import androidx.compose.foundation.layout.size
 import androidx.compose.foundation.rememberScrollState
 import androidx.compose.foundation.shape.CircleShape
+import androidx.compose.foundation.text.KeyboardOptions
 import androidx.compose.foundation.verticalScroll
 import androidx.compose.material.ExperimentalMaterialApi
 import androidx.compose.material.ModalBottomSheetValue
@@ -52,6 +53,7 @@ import androidx.compose.ui.focus.FocusManager
 import androidx.compose.ui.input.pointer.pointerInput
 import androidx.compose.ui.platform.LocalFocusManager
 import androidx.compose.ui.res.stringResource
+import androidx.compose.ui.text.input.KeyboardCapitalization
 import androidx.compose.ui.tooling.preview.Preview
 import androidx.compose.ui.tooling.preview.PreviewParameter
 import androidx.compose.ui.unit.dp
@@ -66,7 +68,6 @@ import io.element.android.libraries.designsystem.components.button.BackButton
 import io.element.android.libraries.designsystem.components.dialogs.ErrorDialog
 import io.element.android.libraries.designsystem.preview.ElementPreviewDark
 import io.element.android.libraries.designsystem.preview.ElementPreviewLight
-import io.element.android.libraries.designsystem.theme.aliasButtonText
 import io.element.android.libraries.designsystem.theme.aliasScreenTitle
 import io.element.android.libraries.designsystem.theme.components.Icon
 import io.element.android.libraries.designsystem.theme.components.Scaffold
@@ -113,17 +114,13 @@ fun RoomDetailsEditView(
                 navigationIcon = { BackButton(onClick = onBackPressed) },
                 actions = {
                     TextButton(
+                        text = stringResource(CommonStrings.action_save),
                         enabled = state.saveButtonEnabled,
                         onClick = {
                             focusManager.clearFocus()
                             state.eventSink(RoomDetailsEditEvents.Save)
                         },
-                    ) {
-                        Text(
-                            text = stringResource(CommonStrings.action_save),
-                            style = ElementTheme.typography.aliasButtonText,
-                        )
-                    }
+                    )
                 }
             )
         },
@@ -164,6 +161,9 @@ fun RoomDetailsEditView(
                     placeholder = stringResource(CommonStrings.common_topic_placeholder),
                     maxLines = 10,
                     onValueChange = { state.eventSink(RoomDetailsEditEvents.UpdateRoomTopic(it)) },
+                    keyboardOptions = KeyboardOptions(
+                        capitalization = KeyboardCapitalization.Sentences,
+                    ),
                 )
             } else {
                 LabelledReadOnlyField(
@@ -287,12 +287,12 @@ private fun Modifier.clearFocusOnTap(focusManager: FocusManager): Modifier =
 
 @Preview
 @Composable
-fun RoomDetailsEditViewLightPreview(@PreviewParameter(RoomDetailsEditStateProvider::class) state: RoomDetailsEditState) =
+internal fun RoomDetailsEditViewLightPreview(@PreviewParameter(RoomDetailsEditStateProvider::class) state: RoomDetailsEditState) =
     ElementPreviewLight { ContentToPreview(state) }
 
 @Preview
 @Composable
-fun RoomDetailsEditViewDarkPreview(@PreviewParameter(RoomDetailsEditStateProvider::class) state: RoomDetailsEditState) =
+internal fun RoomDetailsEditViewDarkPreview(@PreviewParameter(RoomDetailsEditStateProvider::class) state: RoomDetailsEditState) =
     ElementPreviewDark { ContentToPreview(state) }
 
 @Composable
diff --git a/features/roomdetails/impl/src/main/kotlin/io/element/android/features/roomdetails/impl/invite/RoomInviteMembersPresenter.kt b/features/roomdetails/impl/src/main/kotlin/io/element/android/features/roomdetails/impl/invite/RoomInviteMembersPresenter.kt
index 00cb04b118..cc0886c3af 100644
--- a/features/roomdetails/impl/src/main/kotlin/io/element/android/features/roomdetails/impl/invite/RoomInviteMembersPresenter.kt
+++ b/features/roomdetails/impl/src/main/kotlin/io/element/android/features/roomdetails/impl/invite/RoomInviteMembersPresenter.kt
@@ -93,7 +93,7 @@ class RoomInviteMembersPresenter @Inject constructor(
         value = if (value.contains(user)) {
             value.filterNot { it == user }
         } else {
-            (value + user)
+            value + user
         }.toImmutableList()
     }
 
diff --git a/features/roomdetails/impl/src/main/kotlin/io/element/android/features/roomdetails/impl/invite/RoomInviteMembersView.kt b/features/roomdetails/impl/src/main/kotlin/io/element/android/features/roomdetails/impl/invite/RoomInviteMembersView.kt
index 555f04af20..8f01569f01 100644
--- a/features/roomdetails/impl/src/main/kotlin/io/element/android/features/roomdetails/impl/invite/RoomInviteMembersView.kt
+++ b/features/roomdetails/impl/src/main/kotlin/io/element/android/features/roomdetails/impl/invite/RoomInviteMembersView.kt
@@ -128,10 +128,8 @@ fun RoomInviteMembersTopBar(
         navigationIcon = { BackButton(onClick = onBackPressed) },
         actions = {
             TextButton(
+                text = stringResource(CommonStrings.action_send),
                 onClick = onSendPressed,
-                content = {
-                    Text(stringResource(CommonStrings.action_send))
-                },
                 enabled = canSend,
             )
         }
@@ -220,12 +218,12 @@ private fun RoomInviteMembersSearchBar(
 
 @Preview
 @Composable
-fun RoomInviteMembersLightPreview(@PreviewParameter(RoomInviteMembersStateProvider::class) state: RoomInviteMembersState) =
+internal fun RoomInviteMembersLightPreview(@PreviewParameter(RoomInviteMembersStateProvider::class) state: RoomInviteMembersState) =
     ElementPreviewLight { ContentToPreview(state) }
 
 @Preview
 @Composable
-fun RoomInviteMembersDarkPreview(@PreviewParameter(RoomInviteMembersStateProvider::class) state: RoomInviteMembersState) =
+internal fun RoomInviteMembersDarkPreview(@PreviewParameter(RoomInviteMembersStateProvider::class) state: RoomInviteMembersState) =
     ElementPreviewDark { ContentToPreview(state) }
 
 @Composable
diff --git a/features/roomdetails/impl/src/main/kotlin/io/element/android/features/roomdetails/impl/members/RoomMemberListPresenter.kt b/features/roomdetails/impl/src/main/kotlin/io/element/android/features/roomdetails/impl/members/RoomMemberListPresenter.kt
index 0787563aed..49ae479d40 100644
--- a/features/roomdetails/impl/src/main/kotlin/io/element/android/features/roomdetails/impl/members/RoomMemberListPresenter.kt
+++ b/features/roomdetails/impl/src/main/kotlin/io/element/android/features/roomdetails/impl/members/RoomMemberListPresenter.kt
@@ -18,7 +18,6 @@ package io.element.android.features.roomdetails.impl.members
 
 import androidx.compose.runtime.Composable
 import androidx.compose.runtime.LaunchedEffect
-import androidx.compose.runtime.State
 import androidx.compose.runtime.collectAsState
 import androidx.compose.runtime.getValue
 import androidx.compose.runtime.mutableStateOf
@@ -31,7 +30,6 @@ import io.element.android.libraries.architecture.Presenter
 import io.element.android.libraries.core.coroutine.CoroutineDispatchers
 import io.element.android.libraries.designsystem.theme.components.SearchBarResultState
 import io.element.android.libraries.matrix.api.room.MatrixRoom
-import io.element.android.libraries.matrix.api.room.MatrixRoomMembersState
 import io.element.android.libraries.matrix.api.room.RoomMembershipState
 import io.element.android.libraries.matrix.api.room.powerlevels.canInvite
 import kotlinx.collections.immutable.toImmutableList
@@ -101,6 +99,5 @@ class RoomMemberListPresenter @Inject constructor(
             },
         )
     }
-
 }
 
diff --git a/features/roomdetails/impl/src/main/kotlin/io/element/android/features/roomdetails/impl/members/RoomMemberListView.kt b/features/roomdetails/impl/src/main/kotlin/io/element/android/features/roomdetails/impl/members/RoomMemberListView.kt
index 3bfde66c06..b0bac12d4e 100644
--- a/features/roomdetails/impl/src/main/kotlin/io/element/android/features/roomdetails/impl/members/RoomMemberListView.kt
+++ b/features/roomdetails/impl/src/main/kotlin/io/element/android/features/roomdetails/impl/members/RoomMemberListView.kt
@@ -45,7 +45,6 @@ import io.element.android.libraries.designsystem.components.avatar.AvatarSize
 import io.element.android.libraries.designsystem.components.button.BackButton
 import io.element.android.libraries.designsystem.preview.ElementPreviewDark
 import io.element.android.libraries.designsystem.preview.ElementPreviewLight
-import io.element.android.libraries.designsystem.theme.aliasButtonText
 import io.element.android.libraries.designsystem.theme.aliasScreenTitle
 import io.element.android.libraries.designsystem.theme.components.CircularProgressIndicator
 import io.element.android.libraries.designsystem.theme.components.Scaffold
@@ -212,14 +211,9 @@ private fun RoomMemberListTopBar(
         actions = {
             if (canInvite) {
                 TextButton(
-                    modifier = Modifier.padding(horizontal = 8.dp),
+                    text = stringResource(CommonStrings.action_invite),
                     onClick = onInvitePressed,
-                ) {
-                    Text(
-                        text = stringResource(CommonStrings.action_invite),
-                        style = ElementTheme.typography.aliasButtonText,
-                    )
-                }
+                )
             }
         }
     )
@@ -257,12 +251,12 @@ private fun RoomMemberSearchBar(
 
 @Preview
 @Composable
-fun RoomMemberListLightPreview(@PreviewParameter(RoomMemberListStateProvider::class) state: RoomMemberListState) =
+internal fun RoomMemberListLightPreview(@PreviewParameter(RoomMemberListStateProvider::class) state: RoomMemberListState) =
     ElementPreviewLight { ContentToPreview(state) }
 
 @Preview
 @Composable
-fun RoomMemberListDarkPreview(@PreviewParameter(RoomMemberListStateProvider::class) state: RoomMemberListState) =
+internal fun RoomMemberListDarkPreview(@PreviewParameter(RoomMemberListStateProvider::class) state: RoomMemberListState) =
     ElementPreviewDark { ContentToPreview(state) }
 
 @Composable
diff --git a/features/roomdetails/impl/src/main/kotlin/io/element/android/features/roomdetails/impl/members/details/RoomMemberDetailsView.kt b/features/roomdetails/impl/src/main/kotlin/io/element/android/features/roomdetails/impl/members/details/RoomMemberDetailsView.kt
index 72b9d4c20c..84dd9319cf 100644
--- a/features/roomdetails/impl/src/main/kotlin/io/element/android/features/roomdetails/impl/members/details/RoomMemberDetailsView.kt
+++ b/features/roomdetails/impl/src/main/kotlin/io/element/android/features/roomdetails/impl/members/details/RoomMemberDetailsView.kt
@@ -39,6 +39,7 @@ import androidx.compose.runtime.Composable
 import androidx.compose.ui.Alignment
 import androidx.compose.ui.Modifier
 import androidx.compose.ui.res.stringResource
+import androidx.compose.ui.text.style.TextAlign
 import androidx.compose.ui.tooling.preview.PreviewParameter
 import androidx.compose.ui.unit.dp
 import io.element.android.features.roomdetails.impl.blockuser.BlockUserDialogs
@@ -118,10 +119,16 @@ internal fun RoomMemberHeaderSection(
         }
         Spacer(modifier = Modifier.height(24.dp))
         if (userName != null) {
-            Text(userName, style = ElementTheme.typography.fontHeadingLgBold)
+            Text(text = userName, style = ElementTheme.typography.fontHeadingLgBold)
             Spacer(modifier = Modifier.height(6.dp))
         }
-        Text(userId, style = ElementTheme.typography.fontBodyLgRegular, color = MaterialTheme.colorScheme.secondary)
+        Text(
+            text = userId,
+            style = ElementTheme.typography.fontBodyLgRegular,
+            color = MaterialTheme.colorScheme.secondary,
+            modifier = Modifier.fillMaxWidth().padding(horizontal = 16.dp),
+            textAlign = TextAlign.Center,
+        )
         Spacer(Modifier.height(40.dp))
     }
 }
@@ -146,12 +153,12 @@ internal fun SendMessageSection(onSendMessage: () -> Unit, modifier: Modifier =
 
 @LargeHeightPreview
 @Composable
-fun RoomMemberDetailsViewLightPreview(@PreviewParameter(RoomMemberDetailsStateProvider::class) state: RoomMemberDetailsState) =
+internal fun RoomMemberDetailsViewLightPreview(@PreviewParameter(RoomMemberDetailsStateProvider::class) state: RoomMemberDetailsState) =
     ElementPreviewLight { ContentToPreview(state) }
 
 @LargeHeightPreview
 @Composable
-fun RoomMemberDetailsViewDarkPreview(@PreviewParameter(RoomMemberDetailsStateProvider::class) state: RoomMemberDetailsState) =
+internal fun RoomMemberDetailsViewDarkPreview(@PreviewParameter(RoomMemberDetailsStateProvider::class) state: RoomMemberDetailsState) =
     ElementPreviewDark { ContentToPreview(state) }
 
 @Composable
diff --git a/features/roomdetails/impl/src/main/res/values-fr/translations.xml b/features/roomdetails/impl/src/main/res/values-fr/translations.xml
index ee34445805..2696cc99ea 100644
--- a/features/roomdetails/impl/src/main/res/values-fr/translations.xml
+++ b/features/roomdetails/impl/src/main/res/values-fr/translations.xml
@@ -1,7 +1,7 @@
 
 
   
-    "1 membre"
+    "%1$d membre"
     "%1$d membres"
   
   "Définir un sujet"
@@ -12,17 +12,22 @@
   "Impossible de mettre à jour le salon"
   "Les messages sont sécurisés par des cadenas numériques. Seuls vous et les destinataires possédez les clés uniques pour les déverrouiller."
   "Chiffrement des messages activé"
+  "Une erreur s’est produite lors du chargement des paramètres de notification."
+  "Impossible de désactiver les notifications de cette salle, veuillez réessayer."
+  "Impossible de réactiver les notifications de cette salle, veuillez réessayer."
   "Inviter des personnes"
+  "Personnalisé"
+  "Par défaut"
   "Notifications"
   "Nom du salon"
   "Partager le salon"
   "Mise à jour du salon…"
   "En attente"
   "Bloquer"
-  "Les utilisateurs bloqués ne pourront pas vous envoyer de messages et tous leurs messages seront masqués. Vous pouvez annuler cette action à tout moment."
+  "Les utilisateurs bloqués ne pourront pas vous envoyer de messages et tous leurs messages seront masqués. Vous pouvez les débloquer à tout moment."
   "Bloquer l\'utilisateur"
   "Débloquer"
-  "Lorsque vous débloquez l\'utilisateur, vous pourrez à nouveau voir tous leur messages."
+  "Vous pourrez à nouveau voir tous leurs messages."
   "Débloquer l\'utilisateur"
   "Quitter le salon"
   "Personnes"
diff --git a/features/roomdetails/impl/src/main/res/values-ru/translations.xml b/features/roomdetails/impl/src/main/res/values-ru/translations.xml
new file mode 100644
index 0000000000..4d2664ab30
--- /dev/null
+++ b/features/roomdetails/impl/src/main/res/values-ru/translations.xml
@@ -0,0 +1,38 @@
+
+
+  
+    "%1$d пользователь"
+    "%1$d пользователя"
+    "%1$d пользователей"
+  
+  "Добавить тему"
+  "Уже зарегистрирован"
+  "Уже приглашены"
+  "Редактировать комнату"
+  "Произошла неизвестная ошибка, и информацию нельзя было изменить."
+  "Не удалось обновить комнату"
+  "Сообщения зашифрованы. Только у вас и у получателей есть уникальные ключи для их разблокировки."
+  "Шифрование сообщений включено"
+  "При загрузке настроек уведомлений произошла ошибка."
+  "Не удалось отключить звук в этой комнате, попробуйте еще раз."
+  "Не удалось включить звук в эту комнату, попробуйте еще раз."
+  "Пригласить участника"
+  "Пользовательский"
+  "По умолчанию"
+  "Уведомления"
+  "Название комнаты"
+  "Поделиться комнатой"
+  "Обновление комнаты…"
+  "В ожидании"
+  "Участники комнаты"
+  "Заблокировать"
+  "Заблокированные пользователи не смогут отправлять вам сообщения, а все их сообщения будут скрыты. Вы можете разблокировать их в любое время."
+  "Заблокировать пользователя"
+  "Разблокировать"
+  "Вы снова сможете увидеть все сообщения."
+  "Разблокировать пользователя"
+  "Покинуть комнату"
+  "Пользователи"
+  "Безопасность"
+  "Тема"
+
diff --git a/features/roomdetails/impl/src/main/res/values-zh-rTW/translations.xml b/features/roomdetails/impl/src/main/res/values-zh-rTW/translations.xml
new file mode 100644
index 0000000000..cbac73f938
--- /dev/null
+++ b/features/roomdetails/impl/src/main/res/values-zh-rTW/translations.xml
@@ -0,0 +1,27 @@
+
+
+  
+    "%1$d 位夥伴"
+  
+  "新增主題"
+  "已是成員"
+  "已邀請"
+  "編輯聊天室"
+  "訊息已加密"
+  "邀請夥伴"
+  "自訂"
+  "預設"
+  "通知"
+  "聊天室名稱"
+  "分享聊天室"
+  "正在更新聊天室…"
+  "待定"
+  "聊天室成員"
+  "封鎖"
+  "封鎖使用者"
+  "解除封鎖"
+  "解除封鎖使用者"
+  "離開聊天室"
+  "夥伴"
+  "主題"
+
diff --git a/features/roomdetails/impl/src/main/res/values/localazy.xml b/features/roomdetails/impl/src/main/res/values/localazy.xml
index 158ba386b4..b1f67dab1e 100644
--- a/features/roomdetails/impl/src/main/res/values/localazy.xml
+++ b/features/roomdetails/impl/src/main/res/values/localazy.xml
@@ -1,7 +1,7 @@
 
 
   
-    "1 person"
+    "%1$d person"
     "%1$d people"
   
   "Add topic"
diff --git a/features/roomdetails/impl/src/test/kotlin/io/element/android/features/roomdetails/RoomDetailsPresenterTests.kt b/features/roomdetails/impl/src/test/kotlin/io/element/android/features/roomdetails/RoomDetailsPresenterTests.kt
index ccd1476c3a..08d6a58535 100644
--- a/features/roomdetails/impl/src/test/kotlin/io/element/android/features/roomdetails/RoomDetailsPresenterTests.kt
+++ b/features/roomdetails/impl/src/test/kotlin/io/element/android/features/roomdetails/RoomDetailsPresenterTests.kt
@@ -16,7 +16,7 @@
 
 package io.element.android.features.roomdetails
 
-import app.cash.molecule.RecompositionClock
+import app.cash.molecule.RecompositionMode
 import app.cash.molecule.moleculeFlow
 import app.cash.turbine.test
 import com.google.common.truth.Truth.assertThat
@@ -60,7 +60,7 @@ class RoomDetailsPresenterTests {
     fun `present - initial state is created from room info`() = runTest {
         val room = aMatrixRoom()
         val presenter = aRoomDetailsPresenter(room)
-        moleculeFlow(RecompositionClock.Immediate) {
+        moleculeFlow(RecompositionMode.Immediate) {
             presenter.present()
         }.test {
             val initialState = awaitItem()
@@ -79,7 +79,7 @@ class RoomDetailsPresenterTests {
     fun `present - initial state with no room name`() = runTest {
         val room = aMatrixRoom(name = null)
         val presenter = aRoomDetailsPresenter(room)
-        moleculeFlow(RecompositionClock.Immediate) {
+        moleculeFlow(RecompositionMode.Immediate) {
             presenter.present()
         }.test {
             val initialState = awaitItem()
@@ -101,7 +101,7 @@ class RoomDetailsPresenterTests {
             givenRoomMembersState(MatrixRoomMembersState.Ready(roomMembers))
         }
         val presenter = aRoomDetailsPresenter(room)
-        moleculeFlow(RecompositionClock.Immediate) {
+        moleculeFlow(RecompositionMode.Immediate) {
             presenter.present()
         }.test {
             val initialState = awaitItem()
@@ -117,7 +117,7 @@ class RoomDetailsPresenterTests {
             givenCanInviteResult(Result.success(true))
         }
         val presenter = aRoomDetailsPresenter(room)
-        moleculeFlow(RecompositionClock.Immediate) {
+        moleculeFlow(RecompositionMode.Immediate) {
             presenter.present()
         }.test {
             // Initially false
@@ -135,7 +135,7 @@ class RoomDetailsPresenterTests {
             givenCanInviteResult(Result.success(false))
         }
         val presenter = aRoomDetailsPresenter(room)
-        moleculeFlow(RecompositionClock.Immediate) {
+        moleculeFlow(RecompositionMode.Immediate) {
             presenter.present()
         }.test {
             assertThat(awaitItem().canInvite).isFalse()
@@ -148,7 +148,7 @@ class RoomDetailsPresenterTests {
             givenCanInviteResult(Result.failure(Throwable("Whoops")))
         }
         val presenter = aRoomDetailsPresenter(room)
-        moleculeFlow(RecompositionClock.Immediate) {
+        moleculeFlow(RecompositionMode.Immediate) {
             presenter.present()
         }.test {
             assertThat(awaitItem().canInvite).isFalse()
@@ -164,7 +164,7 @@ class RoomDetailsPresenterTests {
             givenCanInviteResult(Result.success(false))
         }
         val presenter = aRoomDetailsPresenter(room)
-        moleculeFlow(RecompositionClock.Immediate) {
+        moleculeFlow(RecompositionMode.Immediate) {
             presenter.present()
         }.test {
             // Initially false
@@ -193,7 +193,7 @@ class RoomDetailsPresenterTests {
             givenCanInviteResult(Result.success(false))
         }
         val presenter = aRoomDetailsPresenter(room)
-        moleculeFlow(RecompositionClock.Immediate) {
+        moleculeFlow(RecompositionMode.Immediate) {
             presenter.present()
         }.test {
             // Initially false
@@ -222,7 +222,7 @@ class RoomDetailsPresenterTests {
             givenCanSendStateResult(StateEventType.ROOM_TOPIC, Result.success(true))
         }
         val presenter = aRoomDetailsPresenter(room)
-        moleculeFlow(RecompositionClock.Immediate) {
+        moleculeFlow(RecompositionMode.Immediate) {
             presenter.present()
         }.test {
             skipItems(1)
@@ -243,7 +243,7 @@ class RoomDetailsPresenterTests {
             givenCanInviteResult(Result.success(false))
         }
         val presenter = aRoomDetailsPresenter(room)
-        moleculeFlow(RecompositionClock.Immediate) {
+        moleculeFlow(RecompositionMode.Immediate) {
             presenter.present()
         }.test {
             // Initially false
@@ -264,7 +264,7 @@ class RoomDetailsPresenterTests {
             givenCanInviteResult(Result.success(false))
         }
         val presenter = aRoomDetailsPresenter(room)
-        moleculeFlow(RecompositionClock.Immediate) {
+        moleculeFlow(RecompositionMode.Immediate) {
             presenter.present()
         }.test {
             // Initially false, and no further events
@@ -280,7 +280,7 @@ class RoomDetailsPresenterTests {
         }
 
         val presenter = aRoomDetailsPresenter(room)
-        moleculeFlow(RecompositionClock.Immediate) {
+        moleculeFlow(RecompositionMode.Immediate) {
             presenter.present()
         }.test {
             // The initial state is "hidden" and no further state changes happen
@@ -296,7 +296,7 @@ class RoomDetailsPresenterTests {
         }
 
         val presenter = aRoomDetailsPresenter(room)
-        moleculeFlow(RecompositionClock.Immediate) {
+        moleculeFlow(RecompositionMode.Immediate) {
             presenter.present()
         }.test {
             // Ignore the initial state
@@ -314,7 +314,7 @@ class RoomDetailsPresenterTests {
         val leaveRoomPresenter = LeaveRoomPresenterFake()
         val room = aMatrixRoom()
         val presenter = aRoomDetailsPresenter(room, leaveRoomPresenter)
-        moleculeFlow(RecompositionClock.Immediate) {
+        moleculeFlow(RecompositionMode.Immediate) {
             presenter.present()
         }.test {
             awaitItem().eventSink(RoomDetailsEvent.LeaveRoom)
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 20d253f3fb..e43703e235 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
@@ -17,7 +17,7 @@
 package io.element.android.features.roomdetails.edit
 
 import android.net.Uri
-import app.cash.molecule.RecompositionClock
+import app.cash.molecule.RecompositionMode
 import app.cash.molecule.moleculeFlow
 import app.cash.turbine.test
 import com.google.common.truth.Truth.assertThat
@@ -82,7 +82,7 @@ class RoomDetailsEditPresenterTest {
         val room = aMatrixRoom(avatarUrl = AN_AVATAR_URL)
         val presenter = aRoomDetailsEditPresenter(room)
 
-        moleculeFlow(RecompositionClock.Immediate) {
+        moleculeFlow(RecompositionMode.Immediate) {
             presenter.present()
         }.test {
             val initialState = awaitItem()
@@ -109,7 +109,7 @@ class RoomDetailsEditPresenterTest {
         }
         val presenter = aRoomDetailsEditPresenter(room)
 
-        moleculeFlow(RecompositionClock.Immediate) {
+        moleculeFlow(RecompositionMode.Immediate) {
             presenter.present()
         }.test {
             // Initially false
@@ -135,7 +135,7 @@ class RoomDetailsEditPresenterTest {
         }
         val presenter = aRoomDetailsEditPresenter(room)
 
-        moleculeFlow(RecompositionClock.Immediate) {
+        moleculeFlow(RecompositionMode.Immediate) {
             presenter.present()
         }.test {
             // Initially false
@@ -161,7 +161,7 @@ class RoomDetailsEditPresenterTest {
         }
         val presenter = aRoomDetailsEditPresenter(room)
 
-        moleculeFlow(RecompositionClock.Immediate) {
+        moleculeFlow(RecompositionMode.Immediate) {
             presenter.present()
         }.test {
             // Initially false
@@ -183,7 +183,7 @@ class RoomDetailsEditPresenterTest {
         val room = aMatrixRoom(topic = "My topic", name = "Name", avatarUrl = AN_AVATAR_URL)
         val presenter = aRoomDetailsEditPresenter(room)
 
-        moleculeFlow(RecompositionClock.Immediate) {
+        moleculeFlow(RecompositionMode.Immediate) {
             presenter.present()
         }.test {
             val initialState = awaitItem()
@@ -229,7 +229,7 @@ class RoomDetailsEditPresenterTest {
 
         val presenter = aRoomDetailsEditPresenter(room)
 
-        moleculeFlow(RecompositionClock.Immediate) {
+        moleculeFlow(RecompositionMode.Immediate) {
             presenter.present()
         }.test {
             val initialState = awaitItem()
@@ -250,7 +250,7 @@ class RoomDetailsEditPresenterTest {
 
         val presenter = aRoomDetailsEditPresenter(room)
 
-        moleculeFlow(RecompositionClock.Immediate) {
+        moleculeFlow(RecompositionMode.Immediate) {
             presenter.present()
         }.test {
             val initialState = awaitItem()
@@ -271,7 +271,7 @@ class RoomDetailsEditPresenterTest {
 
         val presenter = aRoomDetailsEditPresenter(room)
 
-        moleculeFlow(RecompositionClock.Immediate) {
+        moleculeFlow(RecompositionMode.Immediate) {
             presenter.present()
         }.test {
             val initialState = awaitItem()
@@ -323,7 +323,7 @@ class RoomDetailsEditPresenterTest {
 
         val presenter = aRoomDetailsEditPresenter(room)
 
-        moleculeFlow(RecompositionClock.Immediate) {
+        moleculeFlow(RecompositionMode.Immediate) {
             presenter.present()
         }.test {
             val initialState = awaitItem()
@@ -373,7 +373,7 @@ class RoomDetailsEditPresenterTest {
 
         val presenter = aRoomDetailsEditPresenter(room)
 
-        moleculeFlow(RecompositionClock.Immediate) {
+        moleculeFlow(RecompositionMode.Immediate) {
             presenter.present()
         }.test {
             val initialState = awaitItem()
@@ -398,7 +398,7 @@ class RoomDetailsEditPresenterTest {
 
         val presenter = aRoomDetailsEditPresenter(room)
 
-        moleculeFlow(RecompositionClock.Immediate) {
+        moleculeFlow(RecompositionMode.Immediate) {
             presenter.present()
         }.test {
             val initialState = awaitItem()
@@ -422,7 +422,7 @@ class RoomDetailsEditPresenterTest {
 
         val presenter = aRoomDetailsEditPresenter(room)
 
-        moleculeFlow(RecompositionClock.Immediate) {
+        moleculeFlow(RecompositionMode.Immediate) {
             presenter.present()
         }.test {
             val initialState = awaitItem()
@@ -445,7 +445,7 @@ class RoomDetailsEditPresenterTest {
 
         val presenter = aRoomDetailsEditPresenter(room)
 
-        moleculeFlow(RecompositionClock.Immediate) {
+        moleculeFlow(RecompositionMode.Immediate) {
             presenter.present()
         }.test {
             val initialState = awaitItem()
@@ -470,7 +470,7 @@ class RoomDetailsEditPresenterTest {
 
         val presenter = aRoomDetailsEditPresenter(room)
 
-        moleculeFlow(RecompositionClock.Immediate) {
+        moleculeFlow(RecompositionMode.Immediate) {
             presenter.present()
         }.test {
             val initialState = awaitItem()
@@ -495,7 +495,7 @@ class RoomDetailsEditPresenterTest {
 
         val presenter = aRoomDetailsEditPresenter(room)
 
-        moleculeFlow(RecompositionClock.Immediate) {
+        moleculeFlow(RecompositionMode.Immediate) {
             presenter.present()
         }.test {
             val initialState = awaitItem()
@@ -561,7 +561,7 @@ class RoomDetailsEditPresenterTest {
 
         val presenter = aRoomDetailsEditPresenter(room)
 
-        moleculeFlow(RecompositionClock.Immediate) {
+        moleculeFlow(RecompositionMode.Immediate) {
             presenter.present()
         }.test {
             val initialState = awaitItem()
@@ -580,7 +580,7 @@ class RoomDetailsEditPresenterTest {
     private suspend fun saveAndAssertFailure(room: MatrixRoom, event: RoomDetailsEditEvents) {
         val presenter = aRoomDetailsEditPresenter(room)
 
-        moleculeFlow(RecompositionClock.Immediate) {
+        moleculeFlow(RecompositionMode.Immediate) {
             presenter.present()
         }.test {
             val initialState = awaitItem()
diff --git a/features/roomdetails/impl/src/test/kotlin/io/element/android/features/roomdetails/impl/invite/RoomInviteMembersPresenterTest.kt b/features/roomdetails/impl/src/test/kotlin/io/element/android/features/roomdetails/impl/invite/RoomInviteMembersPresenterTest.kt
index 8600cefeac..ede7342882 100644
--- a/features/roomdetails/impl/src/test/kotlin/io/element/android/features/roomdetails/impl/invite/RoomInviteMembersPresenterTest.kt
+++ b/features/roomdetails/impl/src/test/kotlin/io/element/android/features/roomdetails/impl/invite/RoomInviteMembersPresenterTest.kt
@@ -16,7 +16,7 @@
 
 package io.element.android.features.roomdetails.impl.invite
 
-import app.cash.molecule.RecompositionClock
+import app.cash.molecule.RecompositionMode
 import app.cash.molecule.moleculeFlow
 import app.cash.turbine.test
 import com.google.common.truth.Truth.assertThat
@@ -52,7 +52,7 @@ internal class RoomInviteMembersPresenterTest {
             coroutineDispatchers = testCoroutineDispatchers()
         )
 
-        moleculeFlow(RecompositionClock.Immediate) {
+        moleculeFlow(RecompositionMode.Immediate) {
             presenter.present()
         }.test {
             val initialState = awaitItem()
@@ -74,7 +74,7 @@ internal class RoomInviteMembersPresenterTest {
             coroutineDispatchers = testCoroutineDispatchers()
         )
 
-        moleculeFlow(RecompositionClock.Immediate) {
+        moleculeFlow(RecompositionMode.Immediate) {
             presenter.present()
         }.test {
             val initialState = awaitItem()
@@ -95,7 +95,7 @@ internal class RoomInviteMembersPresenterTest {
             roomMemberListDataSource = createDataSource(FakeMatrixRoom()),
             coroutineDispatchers = testCoroutineDispatchers(useUnconfinedTestDispatcher = true)
         )
-        moleculeFlow(RecompositionClock.Immediate) {
+        moleculeFlow(RecompositionMode.Immediate) {
             presenter.present()
         }.test {
             val initialState = awaitItem()
@@ -121,7 +121,7 @@ internal class RoomInviteMembersPresenterTest {
             roomMemberListDataSource = createDataSource(FakeMatrixRoom()),
             coroutineDispatchers = testCoroutineDispatchers(useUnconfinedTestDispatcher = true)
         )
-        moleculeFlow(RecompositionClock.Immediate) {
+        moleculeFlow(RecompositionMode.Immediate) {
             presenter.present()
         }.test {
             val initialState = awaitItem()
@@ -173,7 +173,7 @@ internal class RoomInviteMembersPresenterTest {
             ),
             coroutineDispatchers = coroutineDispatchers
         )
-        moleculeFlow(RecompositionClock.Immediate) {
+        moleculeFlow(RecompositionMode.Immediate) {
             presenter.present()
         }.test {
             val initialState = awaitItem()
@@ -232,7 +232,7 @@ internal class RoomInviteMembersPresenterTest {
             coroutineDispatchers = testCoroutineDispatchers(useUnconfinedTestDispatcher = true)
         )
 
-        moleculeFlow(RecompositionClock.Immediate) {
+        moleculeFlow(RecompositionMode.Immediate) {
             presenter.present()
         }.test {
             val initialState = awaitItem()
@@ -270,7 +270,7 @@ internal class RoomInviteMembersPresenterTest {
             coroutineDispatchers = testCoroutineDispatchers()
         )
 
-        moleculeFlow(RecompositionClock.Immediate) {
+        moleculeFlow(RecompositionMode.Immediate) {
             presenter.present()
         }.test {
             val initialState = awaitItem()
@@ -298,7 +298,7 @@ internal class RoomInviteMembersPresenterTest {
             roomMemberListDataSource = createDataSource(FakeMatrixRoom()),
             coroutineDispatchers = testCoroutineDispatchers(useUnconfinedTestDispatcher = true)
         )
-        moleculeFlow(RecompositionClock.Immediate) {
+        moleculeFlow(RecompositionMode.Immediate) {
             presenter.present()
         }.test {
             val initialState = awaitItem()
@@ -339,7 +339,7 @@ internal class RoomInviteMembersPresenterTest {
             roomMemberListDataSource = createDataSource(FakeMatrixRoom()),
             coroutineDispatchers = testCoroutineDispatchers(useUnconfinedTestDispatcher = true)
         )
-        moleculeFlow(RecompositionClock.Immediate) {
+        moleculeFlow(RecompositionMode.Immediate) {
             presenter.present()
         }.test {
             val initialState = awaitItem()
diff --git a/features/roomdetails/impl/src/test/kotlin/io/element/android/features/roomdetails/members/RoomMemberListPresenterTests.kt b/features/roomdetails/impl/src/test/kotlin/io/element/android/features/roomdetails/members/RoomMemberListPresenterTests.kt
index c3a79481e6..9de035d017 100644
--- a/features/roomdetails/impl/src/test/kotlin/io/element/android/features/roomdetails/members/RoomMemberListPresenterTests.kt
+++ b/features/roomdetails/impl/src/test/kotlin/io/element/android/features/roomdetails/members/RoomMemberListPresenterTests.kt
@@ -16,7 +16,7 @@
 
 package io.element.android.features.roomdetails.members
 
-import app.cash.molecule.RecompositionClock
+import app.cash.molecule.RecompositionMode
 import app.cash.molecule.moleculeFlow
 import app.cash.turbine.test
 import com.google.common.truth.Truth
@@ -44,7 +44,7 @@ class RoomMemberListPresenterTests {
     @Test
     fun `search is done automatically on start, but is async`() = runTest {
         val presenter = createPresenter()
-        moleculeFlow(RecompositionClock.Immediate) {
+        moleculeFlow(RecompositionMode.Immediate) {
             presenter.present()
         }.test {
             val initialState = awaitItem()
@@ -52,7 +52,6 @@ class RoomMemberListPresenterTests {
             Truth.assertThat(initialState.searchQuery).isEmpty()
             Truth.assertThat(initialState.searchResults).isInstanceOf(SearchBarResultState.NotSearching::class.java)
             Truth.assertThat(initialState.isSearchActive).isFalse()
-
             val loadedState = awaitItem()
             Truth.assertThat(loadedState.roomMembers).isInstanceOf(Async.Success::class.java)
             Truth.assertThat((loadedState.roomMembers as Async.Success).data.invited).isEqualTo(listOf(aVictor(), aWalter()))
@@ -63,32 +62,30 @@ class RoomMemberListPresenterTests {
     @Test
     fun `open search`() = runTest {
         val presenter = createPresenter()
-        moleculeFlow(RecompositionClock.Immediate) {
+        moleculeFlow(RecompositionMode.Immediate) {
             presenter.present()
         }.test {
-            val initialState = awaitItem()
+            skipItems(1)
             val loadedState = awaitItem()
-
             loadedState.eventSink(RoomMemberListEvents.OnSearchActiveChanged(true))
-
             val searchActiveState = awaitItem()
-            Truth.assertThat((searchActiveState.isSearchActive)).isTrue()
+            Truth.assertThat(searchActiveState.isSearchActive).isTrue()
         }
     }
 
     @Test
     fun `search for something which is not found`() = runTest {
         val presenter = createPresenter()
-        moleculeFlow(RecompositionClock.Immediate) {
+        moleculeFlow(RecompositionMode.Immediate) {
             presenter.present()
         }.test {
-            val initialState = awaitItem()
+            skipItems(1)
             val loadedState = awaitItem()
             loadedState.eventSink(RoomMemberListEvents.OnSearchActiveChanged(true))
             val searchActiveState = awaitItem()
-            loadedState.eventSink(RoomMemberListEvents.UpdateSearchQuery("something"))
+            searchActiveState.eventSink(RoomMemberListEvents.UpdateSearchQuery("something"))
             val searchQueryUpdatedState = awaitItem()
-            Truth.assertThat((searchQueryUpdatedState.searchQuery)).isEqualTo("something")
+            Truth.assertThat(searchQueryUpdatedState.searchQuery).isEqualTo("something")
             val searchSearchResultDelivered = awaitItem()
             Truth.assertThat(searchSearchResultDelivered.searchResults).isInstanceOf(SearchBarResultState.NoResults::class.java)
         }
@@ -97,21 +94,20 @@ class RoomMemberListPresenterTests {
     @Test
     fun `search for something which is found`() = runTest {
         val presenter = createPresenter()
-        moleculeFlow(RecompositionClock.Immediate) {
+        moleculeFlow(RecompositionMode.Immediate) {
             presenter.present()
         }.test {
-            val initialState = awaitItem()
+            skipItems(1)
             val loadedState = awaitItem()
             loadedState.eventSink(RoomMemberListEvents.OnSearchActiveChanged(true))
             val searchActiveState = awaitItem()
-            loadedState.eventSink(RoomMemberListEvents.UpdateSearchQuery("Alice"))
+            searchActiveState.eventSink(RoomMemberListEvents.UpdateSearchQuery("Alice"))
             val searchQueryUpdatedState = awaitItem()
-            Truth.assertThat((searchQueryUpdatedState.searchQuery)).isEqualTo("Alice")
+            Truth.assertThat(searchQueryUpdatedState.searchQuery).isEqualTo("Alice")
             val searchSearchResultDelivered = awaitItem()
-            Truth.assertThat((searchSearchResultDelivered.searchResults)).isInstanceOf(SearchBarResultState.Results::class.java)
+            Truth.assertThat(searchSearchResultDelivered.searchResults).isInstanceOf(SearchBarResultState.Results::class.java)
             Truth.assertThat((searchSearchResultDelivered.searchResults as SearchBarResultState.Results).results.joined.first().displayName)
                 .isEqualTo("Alice")
-
         }
     }
 
@@ -122,7 +118,7 @@ class RoomMemberListPresenterTests {
                 givenCanInviteResult(Result.success(true))
             }
         )
-        moleculeFlow(RecompositionClock.Immediate) {
+        moleculeFlow(RecompositionMode.Immediate) {
             presenter.present()
         }.test {
             skipItems(1)
@@ -138,7 +134,7 @@ class RoomMemberListPresenterTests {
                 givenCanInviteResult(Result.success(false))
             }
         )
-        moleculeFlow(RecompositionClock.Immediate) {
+        moleculeFlow(RecompositionMode.Immediate) {
             presenter.present()
         }.test {
             skipItems(1)
@@ -154,7 +150,7 @@ class RoomMemberListPresenterTests {
                 givenCanInviteResult(Result.failure(Throwable("Eek")))
             }
         )
-        moleculeFlow(RecompositionClock.Immediate) {
+        moleculeFlow(RecompositionMode.Immediate) {
             presenter.present()
         }.test {
             skipItems(1)
diff --git a/features/roomdetails/impl/src/test/kotlin/io/element/android/features/roomdetails/members/details/RoomMemberDetailsPresenterTests.kt b/features/roomdetails/impl/src/test/kotlin/io/element/android/features/roomdetails/members/details/RoomMemberDetailsPresenterTests.kt
index 94b940bb17..71df3ad633 100644
--- a/features/roomdetails/impl/src/test/kotlin/io/element/android/features/roomdetails/members/details/RoomMemberDetailsPresenterTests.kt
+++ b/features/roomdetails/impl/src/test/kotlin/io/element/android/features/roomdetails/members/details/RoomMemberDetailsPresenterTests.kt
@@ -16,7 +16,7 @@
 
 package io.element.android.features.roomdetails.members.details
 
-import app.cash.molecule.RecompositionClock
+import app.cash.molecule.RecompositionMode
 import app.cash.molecule.moleculeFlow
 import app.cash.turbine.test
 import com.google.common.truth.Truth
@@ -45,7 +45,7 @@ class RoomMemberDetailsPresenterTests {
             givenRoomMembersState(MatrixRoomMembersState.Ready(listOf(roomMember)))
         }
         val presenter = RoomMemberDetailsPresenter(FakeMatrixClient(), room, roomMember.userId)
-        moleculeFlow(RecompositionClock.Immediate) {
+        moleculeFlow(RecompositionMode.Immediate) {
             presenter.present()
         }.test {
             val initialState = awaitItem()
@@ -69,7 +69,7 @@ class RoomMemberDetailsPresenterTests {
             givenRoomMembersState(MatrixRoomMembersState.Ready(listOf(roomMember)))
         }
         val presenter = RoomMemberDetailsPresenter(FakeMatrixClient(), room, roomMember.userId)
-        moleculeFlow(RecompositionClock.Immediate) {
+        moleculeFlow(RecompositionMode.Immediate) {
             presenter.present()
         }.test {
             val initialState = awaitItem()
@@ -89,7 +89,7 @@ class RoomMemberDetailsPresenterTests {
             givenRoomMembersState(MatrixRoomMembersState.Ready(listOf(roomMember)))
         }
         val presenter = RoomMemberDetailsPresenter(FakeMatrixClient(), room, roomMember.userId)
-        moleculeFlow(RecompositionClock.Immediate) {
+        moleculeFlow(RecompositionMode.Immediate) {
             presenter.present()
         }.test {
             val initialState = awaitItem()
@@ -105,7 +105,7 @@ class RoomMemberDetailsPresenterTests {
         val room = aMatrixRoom()
         val roomMember = aRoomMember()
         val presenter = RoomMemberDetailsPresenter(FakeMatrixClient(), room, roomMember.userId)
-        moleculeFlow(RecompositionClock.Immediate) {
+        moleculeFlow(RecompositionMode.Immediate) {
             presenter.present()
         }.test {
             val initialState = awaitItem()
@@ -126,7 +126,7 @@ class RoomMemberDetailsPresenterTests {
         val room = aMatrixRoom()
         val roomMember = aRoomMember()
         val presenter = RoomMemberDetailsPresenter(FakeMatrixClient(), room, roomMember.userId)
-        moleculeFlow(RecompositionClock.Immediate) {
+        moleculeFlow(RecompositionMode.Immediate) {
             presenter.present()
         }.test {
             val initialState = awaitItem()
@@ -147,7 +147,7 @@ class RoomMemberDetailsPresenterTests {
         val matrixClient = FakeMatrixClient()
         matrixClient.givenIgnoreUserResult(Result.failure(A_THROWABLE))
         val presenter = RoomMemberDetailsPresenter(matrixClient, room, roomMember.userId)
-        moleculeFlow(RecompositionClock.Immediate) {
+        moleculeFlow(RecompositionMode.Immediate) {
             presenter.present()
         }.test {
             val initialState = awaitItem()
@@ -166,7 +166,7 @@ class RoomMemberDetailsPresenterTests {
         val room = aMatrixRoom()
         val roomMember = aRoomMember()
         val presenter = RoomMemberDetailsPresenter(FakeMatrixClient(), room, roomMember.userId)
-        moleculeFlow(RecompositionClock.Immediate) {
+        moleculeFlow(RecompositionMode.Immediate) {
             presenter.present()
         }.test {
             val initialState = awaitItem()
diff --git a/features/roomlist/impl/build.gradle.kts b/features/roomlist/impl/build.gradle.kts
index 302e54fe09..f5a08ba860 100644
--- a/features/roomlist/impl/build.gradle.kts
+++ b/features/roomlist/impl/build.gradle.kts
@@ -71,6 +71,4 @@ dependencies {
     testImplementation(projects.features.networkmonitor.test)
     testImplementation(projects.tests.testutils)
     testImplementation(projects.features.leaveroom.fake)
-
-    androidTestImplementation(libs.test.junitext)
 }
diff --git a/features/roomlist/impl/src/main/kotlin/io/element/android/features/roomlist/impl/RoomListContextMenu.kt b/features/roomlist/impl/src/main/kotlin/io/element/android/features/roomlist/impl/RoomListContextMenu.kt
index 740c14aa8d..700235f3e2 100644
--- a/features/roomlist/impl/src/main/kotlin/io/element/android/features/roomlist/impl/RoomListContextMenu.kt
+++ b/features/roomlist/impl/src/main/kotlin/io/element/android/features/roomlist/impl/RoomListContextMenu.kt
@@ -30,7 +30,6 @@ import androidx.compose.material3.MaterialTheme
 import androidx.compose.runtime.Composable
 import androidx.compose.ui.Modifier
 import androidx.compose.ui.res.stringResource
-import androidx.compose.ui.text.font.FontWeight
 import androidx.compose.ui.tooling.preview.Preview
 import androidx.compose.ui.unit.dp
 import io.element.android.libraries.designsystem.VectorIcons
diff --git a/features/roomlist/impl/src/main/kotlin/io/element/android/features/roomlist/impl/RoomListPresenter.kt b/features/roomlist/impl/src/main/kotlin/io/element/android/features/roomlist/impl/RoomListPresenter.kt
index 21f946b3fd..dbef9c799b 100644
--- a/features/roomlist/impl/src/main/kotlin/io/element/android/features/roomlist/impl/RoomListPresenter.kt
+++ b/features/roomlist/impl/src/main/kotlin/io/element/android/features/roomlist/impl/RoomListPresenter.kt
@@ -44,7 +44,7 @@ import kotlinx.coroutines.CoroutineScope
 import kotlinx.coroutines.launch
 import javax.inject.Inject
 
-private const val extendedRangeSize = 40
+private const val EXTENDED_RANGE_SIZE = 40
 
 class RoomListPresenter @Inject constructor(
     private val client: MatrixClient,
@@ -130,11 +130,11 @@ class RoomListPresenter @Inject constructor(
 
     private fun updateVisibleRange(range: IntRange) {
         if (range.isEmpty()) return
-        val midExtendedRangeSize = extendedRangeSize / 2
+        val midExtendedRangeSize = EXTENDED_RANGE_SIZE / 2
         val extendedRangeStart = (range.first - midExtendedRangeSize).coerceAtLeast(0)
         // Safe to give bigger size than room list
         val extendedRangeEnd = range.last + midExtendedRangeSize
         val extendedRange = IntRange(extendedRangeStart, extendedRangeEnd)
-        client.roomSummaryDataSource.updateAllRoomsVisibleRange(extendedRange)
+        client.roomListService.updateAllRoomsVisibleRange(extendedRange)
     }
 }
diff --git a/features/roomlist/impl/src/main/kotlin/io/element/android/features/roomlist/impl/RoomListView.kt b/features/roomlist/impl/src/main/kotlin/io/element/android/features/roomlist/impl/RoomListView.kt
index 657648df42..02a72306dc 100644
--- a/features/roomlist/impl/src/main/kotlin/io/element/android/features/roomlist/impl/RoomListView.kt
+++ b/features/roomlist/impl/src/main/kotlin/io/element/android/features/roomlist/impl/RoomListView.kt
@@ -28,8 +28,6 @@ import androidx.compose.foundation.lazy.itemsIndexed
 import androidx.compose.foundation.lazy.rememberLazyListState
 import androidx.compose.material3.ExperimentalMaterial3Api
 import androidx.compose.material3.MaterialTheme
-import androidx.compose.material3.Snackbar
-import androidx.compose.material3.SnackbarHost
 import androidx.compose.material3.TopAppBarDefaults
 import androidx.compose.material3.rememberTopAppBarState
 import androidx.compose.runtime.Composable
@@ -59,6 +57,7 @@ import io.element.android.libraries.designsystem.theme.components.FloatingAction
 import io.element.android.libraries.designsystem.theme.components.Icon
 import io.element.android.libraries.designsystem.theme.components.Scaffold
 import io.element.android.libraries.designsystem.utils.LogCompositions
+import io.element.android.libraries.designsystem.utils.SnackbarHost
 import io.element.android.libraries.designsystem.utils.rememberSnackbarHostState
 import io.element.android.libraries.matrix.api.core.RoomId
 import io.element.android.libraries.designsystem.R as DrawableR
@@ -227,13 +226,7 @@ fun RoomListContent(
                 )
             }
         },
-        snackbarHost = {
-            SnackbarHost(snackbarHostState) { data ->
-                Snackbar(
-                    snackbarData = data,
-                )
-            }
-        },
+        snackbarHost = { SnackbarHost(snackbarHostState) },
     )
 }
 
diff --git a/features/roomlist/impl/src/main/kotlin/io/element/android/features/roomlist/impl/components/RequestVerificationHeader.kt b/features/roomlist/impl/src/main/kotlin/io/element/android/features/roomlist/impl/components/RequestVerificationHeader.kt
index 16eea28f20..9d6b54366a 100644
--- a/features/roomlist/impl/src/main/kotlin/io/element/android/features/roomlist/impl/components/RequestVerificationHeader.kt
+++ b/features/roomlist/impl/src/main/kotlin/io/element/android/features/roomlist/impl/components/RequestVerificationHeader.kt
@@ -19,7 +19,6 @@ package io.element.android.features.roomlist.impl.components
 import androidx.compose.foundation.clickable
 import androidx.compose.foundation.layout.Box
 import androidx.compose.foundation.layout.Column
-import androidx.compose.foundation.layout.PaddingValues
 import androidx.compose.foundation.layout.Row
 import androidx.compose.foundation.layout.Spacer
 import androidx.compose.foundation.layout.fillMaxWidth
@@ -37,7 +36,7 @@ import androidx.compose.ui.unit.dp
 import io.element.android.features.roomlist.impl.R
 import io.element.android.libraries.designsystem.preview.ElementPreviewDark
 import io.element.android.libraries.designsystem.preview.ElementPreviewLight
-import io.element.android.libraries.designsystem.theme.aliasButtonText
+import io.element.android.libraries.designsystem.theme.components.ButtonSize
 import io.element.android.libraries.designsystem.theme.components.Button
 import io.element.android.libraries.designsystem.theme.components.Icon
 import io.element.android.libraries.designsystem.theme.components.Surface
@@ -83,15 +82,11 @@ internal fun RequestVerificationHeader(
                 )
                 Spacer(modifier = Modifier.height(12.dp))
                 Button(
+                    text = stringResource(CommonStrings.action_continue),
+                    size = ButtonSize.Medium,
                     modifier = Modifier.fillMaxWidth(),
-                    contentPadding = PaddingValues(horizontal = 20.dp, vertical = 7.dp),
                     onClick = onVerifyClicked,
-                ) {
-                    Text(
-                        stringResource(CommonStrings.action_continue),
-                        style = ElementTheme.typography.aliasButtonText
-                    )
-                }
+                )
             }
         }
     }
diff --git a/features/roomlist/impl/src/main/kotlin/io/element/android/features/roomlist/impl/components/RoomListTopBar.kt b/features/roomlist/impl/src/main/kotlin/io/element/android/features/roomlist/impl/components/RoomListTopBar.kt
index db0ea8c11d..001c048e4e 100644
--- a/features/roomlist/impl/src/main/kotlin/io/element/android/features/roomlist/impl/components/RoomListTopBar.kt
+++ b/features/roomlist/impl/src/main/kotlin/io/element/android/features/roomlist/impl/components/RoomListTopBar.kt
@@ -43,10 +43,11 @@ import io.element.android.libraries.designsystem.components.avatar.Avatar
 import io.element.android.libraries.designsystem.components.avatar.AvatarSize
 import io.element.android.libraries.designsystem.preview.ElementPreviewDark
 import io.element.android.libraries.designsystem.preview.ElementPreviewLight
+import io.element.android.libraries.designsystem.text.applyScaleDown
+import io.element.android.libraries.designsystem.text.toSp
 import io.element.android.libraries.designsystem.theme.aliasScreenTitle
 import io.element.android.libraries.designsystem.theme.components.DropdownMenu
 import io.element.android.libraries.designsystem.theme.components.DropdownMenuItem
-import io.element.android.libraries.designsystem.theme.components.DropdownMenuItemText
 import io.element.android.libraries.designsystem.theme.components.Icon
 import io.element.android.libraries.designsystem.theme.components.IconButton
 import io.element.android.libraries.designsystem.theme.components.MediumTopAppBar
@@ -114,7 +115,11 @@ private fun DefaultRoomListTopBar(
             val fontStyle = if (scrollBehavior.state.collapsedFraction > 0.5)
                 ElementTheme.typography.aliasScreenTitle
             else
-                ElementTheme.typography.fontHeadingLgBold
+                ElementTheme.typography.fontHeadingLgBold.copy(
+                    // Due to a limitation of MediumTopAppBar, and to avoid the text to be truncated,
+                    // ensure that the font size will never be bigger than 28.dp.
+                    fontSize = 28.dp.applyScaleDown().toSp()
+                )
             Text(
                 style = fontStyle,
                 text = stringResource(id = R.string.screen_roomlist_main_space_title)
@@ -163,7 +168,7 @@ private fun DefaultRoomListTopBar(
                         showMenu = false
                         onMenuActionClicked(RoomListMenuAction.InviteFriends)
                     },
-                    text = { DropdownMenuItemText(stringResource(id = CommonStrings.action_invite)) },
+                    text = { Text(stringResource(id = CommonStrings.action_invite)) },
                     leadingIcon = {
                         Icon(
                             Icons.Outlined.Share,
@@ -177,7 +182,7 @@ private fun DefaultRoomListTopBar(
                         showMenu = false
                         onMenuActionClicked(RoomListMenuAction.ReportBug)
                     },
-                    text = { DropdownMenuItemText(stringResource(id = CommonStrings.common_report_a_bug)) },
+                    text = { Text(stringResource(id = CommonStrings.common_report_a_bug)) },
                     leadingIcon = {
                         Icon(
                             Icons.Outlined.BugReport,
diff --git a/features/roomlist/impl/src/main/kotlin/io/element/android/features/roomlist/impl/components/RoomSummaryRow.kt b/features/roomlist/impl/src/main/kotlin/io/element/android/features/roomlist/impl/components/RoomSummaryRow.kt
index b32f169e6b..aab174c6a4 100644
--- a/features/roomlist/impl/src/main/kotlin/io/element/android/features/roomlist/impl/components/RoomSummaryRow.kt
+++ b/features/roomlist/impl/src/main/kotlin/io/element/android/features/roomlist/impl/components/RoomSummaryRow.kt
@@ -155,7 +155,7 @@ private fun RowScope.NameAndTimestampRow(room: RoomListRoomSummary) {
 @Composable
 private fun RowScope.LastMessageAndIndicatorRow(room: RoomListRoomSummary) {
     // Last Message
-    val attributedLastMessage = (room.lastMessage as? AnnotatedString)
+    val attributedLastMessage = room.lastMessage as? AnnotatedString
         ?: AnnotatedString(room.lastMessage.orEmpty().toString())
     Text(
         modifier = Modifier
@@ -186,10 +186,10 @@ class PercentRectangleSizeShape(private val percent: Float) : Shape {
         val halfPercent = percent / 2f
         val path = Path().apply {
             val rect = Rect(
-                0f,
-                size.height * halfPercent,
-                size.width,
-                size.height - (size.height * halfPercent)
+                left = 0f,
+                top = size.height * halfPercent,
+                right = size.width,
+                bottom = size.height * (1 - halfPercent)
             )
             addRect(rect)
             close()
diff --git a/features/roomlist/impl/src/main/kotlin/io/element/android/features/roomlist/impl/datasource/DefaultInviteStateDataSource.kt b/features/roomlist/impl/src/main/kotlin/io/element/android/features/roomlist/impl/datasource/DefaultInviteStateDataSource.kt
index 3a89014799..e05efd3ddd 100644
--- a/features/roomlist/impl/src/main/kotlin/io/element/android/features/roomlist/impl/datasource/DefaultInviteStateDataSource.kt
+++ b/features/roomlist/impl/src/main/kotlin/io/element/android/features/roomlist/impl/datasource/DefaultInviteStateDataSource.kt
@@ -30,7 +30,7 @@ import io.element.android.libraries.core.coroutine.CoroutineDispatchers
 import io.element.android.libraries.di.SessionScope
 import io.element.android.libraries.matrix.api.MatrixClient
 import io.element.android.libraries.matrix.api.core.RoomId
-import io.element.android.libraries.matrix.api.room.RoomSummary
+import io.element.android.libraries.matrix.api.roomlist.RoomSummary
 import kotlinx.coroutines.withContext
 import javax.inject.Inject
 
@@ -44,8 +44,9 @@ class DefaultInviteStateDataSource @Inject constructor(
     @Composable
     override fun inviteState(): InvitesState {
         val invites by client
-            .roomSummaryDataSource
-            .inviteRooms()
+            .roomListService
+            .invites()
+            .summaries
             .collectAsState()
 
         val seenInvites by seenInvitesStore
diff --git a/features/roomlist/impl/src/main/kotlin/io/element/android/features/roomlist/impl/datasource/RoomListDataSource.kt b/features/roomlist/impl/src/main/kotlin/io/element/android/features/roomlist/impl/datasource/RoomListDataSource.kt
index 8602f15910..e44bcd6b6b 100644
--- a/features/roomlist/impl/src/main/kotlin/io/element/android/features/roomlist/impl/datasource/RoomListDataSource.kt
+++ b/features/roomlist/impl/src/main/kotlin/io/element/android/features/roomlist/impl/datasource/RoomListDataSource.kt
@@ -18,6 +18,8 @@ package io.element.android.features.roomlist.impl.datasource
 
 import io.element.android.features.roomlist.impl.model.RoomListRoomSummary
 import io.element.android.features.roomlist.impl.model.RoomListRoomSummaryPlaceholders
+import io.element.android.libraries.androidutils.diff.DiffCacheUpdater
+import io.element.android.libraries.androidutils.diff.MutableListDiffCache
 import io.element.android.libraries.core.coroutine.CoroutineDispatchers
 import io.element.android.libraries.core.extensions.orEmpty
 import io.element.android.libraries.dateformatter.api.LastMessageTimestampFormatter
@@ -25,8 +27,8 @@ import io.element.android.libraries.designsystem.components.avatar.AvatarData
 import io.element.android.libraries.designsystem.components.avatar.AvatarSize
 import io.element.android.libraries.eventformatter.api.RoomLastMessageFormatter
 import io.element.android.libraries.matrix.api.core.RoomId
-import io.element.android.libraries.matrix.api.room.RoomSummary
-import io.element.android.libraries.matrix.api.room.RoomSummaryDataSource
+import io.element.android.libraries.matrix.api.roomlist.RoomListService
+import io.element.android.libraries.matrix.api.roomlist.RoomSummary
 import kotlinx.collections.immutable.ImmutableList
 import kotlinx.collections.immutable.persistentListOf
 import kotlinx.collections.immutable.toImmutableList
@@ -36,11 +38,13 @@ import kotlinx.coroutines.flow.StateFlow
 import kotlinx.coroutines.flow.combine
 import kotlinx.coroutines.flow.launchIn
 import kotlinx.coroutines.flow.onEach
+import kotlinx.coroutines.sync.Mutex
+import kotlinx.coroutines.sync.withLock
 import kotlinx.coroutines.withContext
 import javax.inject.Inject
 
 class RoomListDataSource @Inject constructor(
-    private val roomSummaryDataSource: RoomSummaryDataSource,
+    private val roomListService: RoomListService,
     private val lastMessageTimestampFormatter: LastMessageTimestampFormatter,
     private val roomLastMessageFormatter: RoomLastMessageFormatter,
     private val coroutineDispatchers: CoroutineDispatchers,
@@ -50,15 +54,18 @@ class RoomListDataSource @Inject constructor(
     private val _allRooms = MutableStateFlow>(persistentListOf())
     private val _filteredRooms = MutableStateFlow>(persistentListOf())
 
+    private val lock = Mutex()
+    private val diffCache = MutableListDiffCache()
+    private val diffCacheUpdater = DiffCacheUpdater(diffCache = diffCache, detectMoves = true) { old, new ->
+        old?.identifier() == new?.identifier()
+    }
+
     fun launchIn(coroutineScope: CoroutineScope) {
-        roomSummaryDataSource
+        roomListService
             .allRooms()
+            .summaries
             .onEach { roomSummaries ->
-                _allRooms.value = if (roomSummaries.isEmpty()) {
-                    RoomListRoomSummaryPlaceholders.createFakeList(16)
-                } else {
-                    mapRoomSummaries(roomSummaries)
-                }.toImmutableList()
+                replaceWith(roomSummaries)
             }
             .launchIn(coroutineScope)
 
@@ -73,7 +80,8 @@ class RoomListDataSource @Inject constructor(
         }
             .onEach {
                 _filteredRooms.value = it
-            }.launchIn(coroutineScope)
+            }
+            .launchIn(coroutineScope)
     }
 
     fun updateFilter(filterValue: String) {
@@ -84,33 +92,63 @@ class RoomListDataSource @Inject constructor(
     val allRooms: StateFlow> = _allRooms
     val filteredRooms: StateFlow> = _filteredRooms
 
-    private suspend fun mapRoomSummaries(
-        roomSummaries: List
-    ): List = withContext(coroutineDispatchers.computation) {
-        roomSummaries.map { roomSummary ->
-            when (roomSummary) {
-                is RoomSummary.Empty -> RoomListRoomSummaryPlaceholders.create(roomSummary.identifier)
-                is RoomSummary.Filled -> {
-                    val avatarData = AvatarData(
-                        id = roomSummary.identifier(),
-                        name = roomSummary.details.name,
-                        url = roomSummary.details.avatarURLString,
-                        size = AvatarSize.RoomListItem,
-                    )
-                    val roomIdentifier = roomSummary.identifier()
-                    RoomListRoomSummary(
-                        id = roomSummary.identifier(),
-                        roomId = RoomId(roomIdentifier),
-                        name = roomSummary.details.name,
-                        hasUnread = roomSummary.details.unreadNotificationCount > 0,
-                        timestamp = lastMessageTimestampFormatter.format(roomSummary.details.lastMessageTimestamp),
-                        lastMessage = roomSummary.details.lastMessage?.let { message ->
-                            roomLastMessageFormatter.format(message.event, roomSummary.details.isDirect)
-                        }.orEmpty(),
-                        avatarData = avatarData,
-                    )
-                }
-            }
+    private suspend fun replaceWith(roomSummaries: List) = withContext(coroutineDispatchers.computation) {
+        lock.withLock {
+            diffCacheUpdater.updateWith(roomSummaries)
+            buildAndEmitAllRooms(roomSummaries)
         }
     }
+
+    private suspend fun buildAndEmitAllRooms(roomSummaries: List) {
+        if (diffCache.isEmpty()) {
+            _allRooms.emit(
+                RoomListRoomSummaryPlaceholders.createFakeList(16).toImmutableList()
+            )
+        } else {
+            val roomListRoomSummaries = ArrayList()
+            for (index in diffCache.indices()) {
+                val cacheItem = diffCache.get(index)
+                if (cacheItem == null) {
+                    buildAndCacheItem(roomSummaries, index)?.also { timelineItemState ->
+                        roomListRoomSummaries.add(timelineItemState)
+                    }
+                } else {
+                    roomListRoomSummaries.add(cacheItem)
+                }
+            }
+            _allRooms.emit(roomListRoomSummaries.toImmutableList())
+        }
+    }
+
+    private fun buildAndCacheItem(
+        roomSummaries: List,
+        index: Int
+    ): RoomListRoomSummary? {
+        val roomListRoomSummary = when (val roomSummary = roomSummaries.getOrNull(index)) {
+            is RoomSummary.Empty -> RoomListRoomSummaryPlaceholders.create(roomSummary.identifier)
+            is RoomSummary.Filled -> {
+                val avatarData = AvatarData(
+                    id = roomSummary.identifier(),
+                    name = roomSummary.details.name,
+                    url = roomSummary.details.avatarURLString,
+                    size = AvatarSize.RoomListItem,
+                )
+                val roomIdentifier = roomSummary.identifier()
+                RoomListRoomSummary(
+                    id = roomSummary.identifier(),
+                    roomId = RoomId(roomIdentifier),
+                    name = roomSummary.details.name,
+                    hasUnread = roomSummary.details.unreadNotificationCount > 0,
+                    timestamp = lastMessageTimestampFormatter.format(roomSummary.details.lastMessageTimestamp),
+                    lastMessage = roomSummary.details.lastMessage?.let { message ->
+                        roomLastMessageFormatter.format(message.event, roomSummary.details.isDirect)
+                    }.orEmpty(),
+                    avatarData = avatarData,
+                )
+            }
+            null -> null
+        }
+        diffCache[index] = roomListRoomSummary
+        return roomListRoomSummary
+    }
 }
diff --git a/features/roomlist/impl/src/main/res/values-ru/translations.xml b/features/roomlist/impl/src/main/res/values-ru/translations.xml
new file mode 100644
index 0000000000..fcd91c56e3
--- /dev/null
+++ b/features/roomlist/impl/src/main/res/values-ru/translations.xml
@@ -0,0 +1,9 @@
+
+
+  "Создайте новую беседу или комнату"
+  "Начните переписку с отправки сообщения."
+  "Пока нет доступных чатов."
+  "Все чаты"
+  "Похоже, вы используете новое устройство. Чтобы получить доступ к зашифрованным сообщениям в дальнейшем, проверьте их на другом устройстве."
+  "Подтвердите, что это вы"
+
diff --git a/features/roomlist/impl/src/main/res/values-sk/translations.xml b/features/roomlist/impl/src/main/res/values-sk/translations.xml
index 250822f4c9..0a1879a484 100644
--- a/features/roomlist/impl/src/main/res/values-sk/translations.xml
+++ b/features/roomlist/impl/src/main/res/values-sk/translations.xml
@@ -1,6 +1,8 @@
 
 
   "Vytvorte novú konverzáciu alebo miestnosť"
+  "Začnite tým, že niekomu pošlete správu."
+  "Zatiaľ žiadne konverzácie."
   "Všetky konverzácie"
   "Vyzerá to tak, že používate nové zariadenie. Overte svoj prístup k zašifrovaným správam pomocou vášho druhého zariadenia."
   "Overte, že ste to vy"
diff --git a/features/roomlist/impl/src/main/res/values-zh-rTW/translations.xml b/features/roomlist/impl/src/main/res/values-zh-rTW/translations.xml
new file mode 100644
index 0000000000..b4d22c5b26
--- /dev/null
+++ b/features/roomlist/impl/src/main/res/values-zh-rTW/translations.xml
@@ -0,0 +1,4 @@
+
+
+  "建立新的對話或聊天室"
+
diff --git a/features/roomlist/impl/src/main/res/values/localazy.xml b/features/roomlist/impl/src/main/res/values/localazy.xml
index 3a1c3cbad6..d63f96d07c 100644
--- a/features/roomlist/impl/src/main/res/values/localazy.xml
+++ b/features/roomlist/impl/src/main/res/values/localazy.xml
@@ -1,6 +1,8 @@
 
 
   "Create a new conversation or room"
+  "Get started by messaging someone."
+  "No chats yet."
   "All Chats"
   "Looks like you’re using a new device. Verify with another device to access your encrypted messages moving forwards."
   "Verify it’s you"
diff --git a/features/roomlist/impl/src/test/kotlin/io/element/android/features/roomlist/impl/RoomListPresenterTests.kt b/features/roomlist/impl/src/test/kotlin/io/element/android/features/roomlist/impl/RoomListPresenterTests.kt
index 0ead16da45..eaa3801e12 100644
--- a/features/roomlist/impl/src/test/kotlin/io/element/android/features/roomlist/impl/RoomListPresenterTests.kt
+++ b/features/roomlist/impl/src/test/kotlin/io/element/android/features/roomlist/impl/RoomListPresenterTests.kt
@@ -16,7 +16,7 @@
 
 package io.element.android.features.roomlist.impl
 
-import app.cash.molecule.RecompositionClock
+import app.cash.molecule.RecompositionMode
 import app.cash.molecule.moleculeFlow
 import app.cash.turbine.test
 import com.google.common.truth.Truth
@@ -47,9 +47,10 @@ import io.element.android.libraries.matrix.test.A_ROOM_NAME
 import io.element.android.libraries.matrix.test.A_USER_ID
 import io.element.android.libraries.matrix.test.A_USER_NAME
 import io.element.android.libraries.matrix.test.FakeMatrixClient
-import io.element.android.libraries.matrix.test.room.FakeRoomSummaryDataSource
 import io.element.android.libraries.matrix.test.room.aRoomSummaryFilled
+import io.element.android.libraries.matrix.test.roomlist.FakeRoomListService
 import io.element.android.libraries.matrix.test.verification.FakeSessionVerificationService
+import io.element.android.tests.testutils.consumeItemsUntilPredicate
 import io.element.android.tests.testutils.testCoroutineDispatchers
 import kotlinx.coroutines.flow.MutableStateFlow
 import kotlinx.coroutines.test.TestScope
@@ -61,7 +62,7 @@ class RoomListPresenterTests {
     @Test
     fun `present - should start with no user and then load user with success`() = runTest {
         val presenter = createRoomListPresenter()
-        moleculeFlow(RecompositionClock.Immediate) {
+        moleculeFlow(RecompositionMode.Immediate) {
             presenter.present()
         }.test {
             val initialState = awaitItem()
@@ -81,7 +82,7 @@ class RoomListPresenterTests {
             userAvatarURLString = Result.failure(AN_EXCEPTION),
         )
         val presenter = createRoomListPresenter(matrixClient)
-        moleculeFlow(RecompositionClock.Immediate) {
+        moleculeFlow(RecompositionMode.Immediate) {
             presenter.present()
         }.test {
             val initialState = awaitItem()
@@ -94,7 +95,7 @@ class RoomListPresenterTests {
     @Test
     fun `present - should filter room with success`() = runTest {
         val presenter = createRoomListPresenter()
-        moleculeFlow(RecompositionClock.Immediate) {
+        moleculeFlow(RecompositionMode.Immediate) {
             presenter.present()
         }.test {
             skipItems(1)
@@ -110,21 +111,20 @@ class RoomListPresenterTests {
 
     @Test
     fun `present - load 1 room with success`() = runTest {
-        val roomSummaryDataSource = FakeRoomSummaryDataSource()
+        val roomListService = FakeRoomListService()
         val matrixClient = FakeMatrixClient(
-            roomSummaryDataSource = roomSummaryDataSource
+            roomListService = roomListService
         )
         val presenter = createRoomListPresenter(matrixClient)
-        moleculeFlow(RecompositionClock.Immediate) {
+        moleculeFlow(RecompositionMode.Immediate) {
             presenter.present()
         }.test {
-            skipItems(1)
-            val initialState = awaitItem()
+            val initialState = consumeItemsUntilPredicate { state -> state.roomList.size == 16 }.last()
             // Room list is loaded with 16 placeholders
             Truth.assertThat(initialState.roomList.size).isEqualTo(16)
             Truth.assertThat(initialState.roomList.all { it.isPlaceholder }).isTrue()
-            roomSummaryDataSource.postAllRooms(listOf(aRoomSummaryFilled()))
-            val withRoomState = awaitItem()
+            roomListService.postAllRooms(listOf(aRoomSummaryFilled()))
+            val withRoomState = consumeItemsUntilPredicate { state -> state.roomList.size == 1 }.last()
             Truth.assertThat(withRoomState.roomList.size).isEqualTo(1)
             Truth.assertThat(withRoomState.roomList.first())
                 .isEqualTo(aRoomListRoomSummary)
@@ -133,68 +133,66 @@ class RoomListPresenterTests {
 
     @Test
     fun `present - load 1 room with success and filter rooms`() = runTest {
-        val roomSummaryDataSource = FakeRoomSummaryDataSource()
+        val roomListService = FakeRoomListService()
         val matrixClient = FakeMatrixClient(
-            roomSummaryDataSource = roomSummaryDataSource
+            roomListService = roomListService
         )
         val presenter = createRoomListPresenter(matrixClient)
-        moleculeFlow(RecompositionClock.Immediate) {
+        moleculeFlow(RecompositionMode.Immediate) {
             presenter.present()
         }.test {
-            roomSummaryDataSource.postAllRooms(listOf(aRoomSummaryFilled()))
-            skipItems(1)
-            val loadedState = awaitItem()
+            roomListService.postAllRooms(listOf(aRoomSummaryFilled()))
+            val loadedState = consumeItemsUntilPredicate { state -> state.roomList.size == 1 }.last()
             // Test filtering with result
             loadedState.eventSink.invoke(RoomListEvents.UpdateFilter(A_ROOM_NAME.substring(0, 3)))
-            skipItems(1) // Filter update
-            val withNotFilteredRoomState = awaitItem()
-            Truth.assertThat(withNotFilteredRoomState.filter).isEqualTo(A_ROOM_NAME.substring(0, 3))
-            Truth.assertThat(withNotFilteredRoomState.filteredRoomList.size).isEqualTo(1)
-            Truth.assertThat(withNotFilteredRoomState.filteredRoomList.first())
+            val withFilteredRoomState = consumeItemsUntilPredicate { state -> state.filteredRoomList.size == 1 }.last()
+            Truth.assertThat(withFilteredRoomState.filter).isEqualTo(A_ROOM_NAME.substring(0, 3))
+            Truth.assertThat(withFilteredRoomState.filteredRoomList.size).isEqualTo(1)
+            Truth.assertThat(withFilteredRoomState.filteredRoomList.first())
                 .isEqualTo(aRoomListRoomSummary)
             // Test filtering without result
-            withNotFilteredRoomState.eventSink.invoke(RoomListEvents.UpdateFilter("tada"))
-            skipItems(1) // Filter update
-            Truth.assertThat(awaitItem().filter).isEqualTo("tada")
-            Truth.assertThat(awaitItem().filteredRoomList).isEmpty()
+            withFilteredRoomState.eventSink.invoke(RoomListEvents.UpdateFilter("tada"))
+            val withNotFilteredRoomState = consumeItemsUntilPredicate { state -> state.filteredRoomList.size == 0 }.last()
+            Truth.assertThat(withNotFilteredRoomState.filter).isEqualTo("tada")
+            Truth.assertThat(withNotFilteredRoomState.filteredRoomList).isEmpty()
         }
     }
 
     @Test
     fun `present - update visible range`() = runTest {
-        val roomSummaryDataSource = FakeRoomSummaryDataSource()
+        val roomListService = FakeRoomListService()
         val matrixClient = FakeMatrixClient(
-            roomSummaryDataSource = roomSummaryDataSource
+            roomListService = roomListService
         )
         val presenter = createRoomListPresenter(matrixClient)
-        moleculeFlow(RecompositionClock.Immediate) {
+        moleculeFlow(RecompositionMode.Immediate) {
             presenter.present()
         }.test {
-            roomSummaryDataSource.postAllRooms(listOf(aRoomSummaryFilled()))
+            roomListService.postAllRooms(listOf(aRoomSummaryFilled()))
             val loadedState = awaitItem()
             // check initial value
-            Truth.assertThat(roomSummaryDataSource.latestSlidingSyncRange).isNull()
+            Truth.assertThat(roomListService.latestSlidingSyncRange).isNull()
             // Test empty range
             loadedState.eventSink.invoke(RoomListEvents.UpdateVisibleRange(IntRange(1, 0)))
-            Truth.assertThat(roomSummaryDataSource.latestSlidingSyncRange).isNull()
+            Truth.assertThat(roomListService.latestSlidingSyncRange).isNull()
             // Update visible range and check that range is transmitted to the SDK after computation
             loadedState.eventSink.invoke(RoomListEvents.UpdateVisibleRange(IntRange(0, 0)))
-            Truth.assertThat(roomSummaryDataSource.latestSlidingSyncRange)
+            Truth.assertThat(roomListService.latestSlidingSyncRange)
                 .isEqualTo(IntRange(0, 20))
             loadedState.eventSink.invoke(RoomListEvents.UpdateVisibleRange(IntRange(0, 1)))
-            Truth.assertThat(roomSummaryDataSource.latestSlidingSyncRange)
+            Truth.assertThat(roomListService.latestSlidingSyncRange)
                 .isEqualTo(IntRange(0, 21))
             loadedState.eventSink.invoke(RoomListEvents.UpdateVisibleRange(IntRange(19, 29)))
-            Truth.assertThat(roomSummaryDataSource.latestSlidingSyncRange)
+            Truth.assertThat(roomListService.latestSlidingSyncRange)
                 .isEqualTo(IntRange(0, 49))
             loadedState.eventSink.invoke(RoomListEvents.UpdateVisibleRange(IntRange(49, 59)))
-            Truth.assertThat(roomSummaryDataSource.latestSlidingSyncRange)
+            Truth.assertThat(roomListService.latestSlidingSyncRange)
                 .isEqualTo(IntRange(29, 79))
             loadedState.eventSink.invoke(RoomListEvents.UpdateVisibleRange(IntRange(149, 159)))
-            Truth.assertThat(roomSummaryDataSource.latestSlidingSyncRange)
+            Truth.assertThat(roomListService.latestSlidingSyncRange)
                 .isEqualTo(IntRange(129, 179))
             loadedState.eventSink.invoke(RoomListEvents.UpdateVisibleRange(IntRange(149, 259)))
-            Truth.assertThat(roomSummaryDataSource.latestSlidingSyncRange)
+            Truth.assertThat(roomListService.latestSlidingSyncRange)
                 .isEqualTo(IntRange(129, 279))
             cancelAndIgnoreRemainingEvents()
         }
@@ -202,9 +200,9 @@ class RoomListPresenterTests {
 
     @Test
     fun `present - handle DismissRequestVerificationPrompt`() = runTest {
-        val roomSummaryDataSource = FakeRoomSummaryDataSource()
+        val roomListService = FakeRoomListService()
         val matrixClient = FakeMatrixClient(
-            roomSummaryDataSource = roomSummaryDataSource
+            roomListService = roomListService
         )
         val presenter = createRoomListPresenter(
             client = matrixClient,
@@ -213,7 +211,7 @@ class RoomListPresenterTests {
                 givenVerifiedStatus(SessionVerifiedStatus.NotVerified)
             },
         )
-        moleculeFlow(RecompositionClock.Immediate) {
+        moleculeFlow(RecompositionMode.Immediate) {
             presenter.present()
         }.test {
             val eventSink = awaitItem().eventSink
@@ -229,7 +227,7 @@ class RoomListPresenterTests {
         val inviteStateFlow = MutableStateFlow(InvitesState.NoInvites)
         val inviteStateDataSource = FakeInviteDataSource(inviteStateFlow)
         val presenter = createRoomListPresenter(inviteStateDataSource = inviteStateDataSource)
-        moleculeFlow(RecompositionClock.Immediate) {
+        moleculeFlow(RecompositionMode.Immediate) {
             presenter.present()
         }.test {
             skipItems(1)
@@ -249,7 +247,7 @@ class RoomListPresenterTests {
     @Test
     fun `present - show context menu`() = runTest {
         val presenter = createRoomListPresenter()
-        moleculeFlow(RecompositionClock.Immediate) {
+        moleculeFlow(RecompositionMode.Immediate) {
             presenter.present()
         }.test {
             skipItems(1)
@@ -267,7 +265,7 @@ class RoomListPresenterTests {
     @Test
     fun `present - hide context menu`() = runTest {
         val presenter = createRoomListPresenter()
-        moleculeFlow(RecompositionClock.Immediate) {
+        moleculeFlow(RecompositionMode.Immediate) {
             presenter.present()
         }.test {
             skipItems(1)
@@ -290,7 +288,7 @@ class RoomListPresenterTests {
     fun `present - leave room calls into leave room presenter`() = runTest {
         val leaveRoomPresenter = LeaveRoomPresenterFake()
         val presenter = createRoomListPresenter(leaveRoomPresenter = leaveRoomPresenter)
-        moleculeFlow(RecompositionClock.Immediate) {
+        moleculeFlow(RecompositionMode.Immediate) {
             presenter.present()
         }.test {
             val initialState = awaitItem()
@@ -319,7 +317,7 @@ class RoomListPresenterTests {
         inviteStateDataSource = inviteStateDataSource,
         leaveRoomPresenter = leaveRoomPresenter,
         roomListDataSource = RoomListDataSource(
-            client.roomSummaryDataSource,
+            client.roomListService,
             lastMessageTimestampFormatter,
             roomLastMessageFormatter,
             coroutineDispatchers = testCoroutineDispatchers()
diff --git a/features/roomlist/impl/src/test/kotlin/io/element/android/features/roomlist/impl/datasource/DefaultInviteStateDataSourceTest.kt b/features/roomlist/impl/src/test/kotlin/io/element/android/features/roomlist/impl/datasource/DefaultInviteStateDataSourceTest.kt
index b67a6c6b43..ce7bf685a8 100644
--- a/features/roomlist/impl/src/test/kotlin/io/element/android/features/roomlist/impl/datasource/DefaultInviteStateDataSourceTest.kt
+++ b/features/roomlist/impl/src/test/kotlin/io/element/android/features/roomlist/impl/datasource/DefaultInviteStateDataSourceTest.kt
@@ -16,7 +16,7 @@
 
 package io.element.android.features.roomlist.impl.datasource
 
-import app.cash.molecule.RecompositionClock
+import app.cash.molecule.RecompositionMode
 import app.cash.molecule.moleculeFlow
 import app.cash.turbine.test
 import com.google.common.truth.Truth
@@ -25,8 +25,8 @@ import io.element.android.features.roomlist.impl.InvitesState
 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.FakeMatrixClient
-import io.element.android.libraries.matrix.test.room.FakeRoomSummaryDataSource
 import io.element.android.libraries.matrix.test.room.aRoomSummaryFilled
+import io.element.android.libraries.matrix.test.roomlist.FakeRoomListService
 import io.element.android.tests.testutils.testCoroutineDispatchers
 import kotlinx.coroutines.test.runTest
 import org.junit.Test
@@ -35,12 +35,12 @@ internal class DefaultInviteStateDataSourceTest {
 
     @Test
     fun `emits NoInvites state if invites list is empty`() = runTest {
-        val roomSummaryDataSource = FakeRoomSummaryDataSource()
-        val client = FakeMatrixClient(roomSummaryDataSource = roomSummaryDataSource)
+        val roomListService = FakeRoomListService()
+        val client = FakeMatrixClient(roomListService = roomListService)
         val seenStore = FakeSeenInvitesStore()
         val dataSource = DefaultInviteStateDataSource(client, seenStore, testCoroutineDispatchers())
 
-        moleculeFlow(RecompositionClock.Immediate) {
+        moleculeFlow(RecompositionMode.Immediate) {
             dataSource.inviteState()
         }.test {
             Truth.assertThat(awaitItem()).isEqualTo(InvitesState.NoInvites)
@@ -49,13 +49,13 @@ internal class DefaultInviteStateDataSourceTest {
 
     @Test
     fun `emits NewInvites state if unseen invite exists`() = runTest {
-        val roomSummaryDataSource = FakeRoomSummaryDataSource()
-        roomSummaryDataSource.postInviteRooms(listOf(aRoomSummaryFilled(roomId = A_ROOM_ID)))
-        val client = FakeMatrixClient(roomSummaryDataSource = roomSummaryDataSource)
+        val roomListService = FakeRoomListService()
+        roomListService.postInviteRooms(listOf(aRoomSummaryFilled(roomId = A_ROOM_ID)))
+        val client = FakeMatrixClient(roomListService = roomListService)
         val seenStore = FakeSeenInvitesStore()
         val dataSource = DefaultInviteStateDataSource(client, seenStore, testCoroutineDispatchers())
 
-        moleculeFlow(RecompositionClock.Immediate) {
+        moleculeFlow(RecompositionMode.Immediate) {
             dataSource.inviteState()
         }.test {
             skipItems(1)
@@ -65,14 +65,14 @@ internal class DefaultInviteStateDataSourceTest {
 
     @Test
     fun `emits NewInvites state if multiple invites exist and at least one is unseen`() = runTest {
-        val roomSummaryDataSource = FakeRoomSummaryDataSource()
-        roomSummaryDataSource.postInviteRooms(listOf(aRoomSummaryFilled(roomId = A_ROOM_ID), aRoomSummaryFilled(roomId = A_ROOM_ID_2)))
-        val client = FakeMatrixClient(roomSummaryDataSource = roomSummaryDataSource)
+        val roomListService = FakeRoomListService()
+        roomListService.postInviteRooms(listOf(aRoomSummaryFilled(roomId = A_ROOM_ID), aRoomSummaryFilled(roomId = A_ROOM_ID_2)))
+        val client = FakeMatrixClient(roomListService = roomListService)
         val seenStore = FakeSeenInvitesStore()
         seenStore.publishRoomIds(setOf(A_ROOM_ID))
         val dataSource = DefaultInviteStateDataSource(client, seenStore, testCoroutineDispatchers(useUnconfinedTestDispatcher = true))
 
-        moleculeFlow(RecompositionClock.Immediate) {
+        moleculeFlow(RecompositionMode.Immediate) {
             dataSource.inviteState()
         }.test {
             skipItems(1)
@@ -82,14 +82,14 @@ internal class DefaultInviteStateDataSourceTest {
 
     @Test
     fun `emits SeenInvites state if invite exists in seen store`() = runTest {
-        val roomSummaryDataSource = FakeRoomSummaryDataSource()
-        roomSummaryDataSource.postInviteRooms(listOf(aRoomSummaryFilled(roomId = A_ROOM_ID)))
-        val client = FakeMatrixClient(roomSummaryDataSource = roomSummaryDataSource)
+        val roomListService = FakeRoomListService()
+        roomListService.postInviteRooms(listOf(aRoomSummaryFilled(roomId = A_ROOM_ID)))
+        val client = FakeMatrixClient(roomListService = roomListService)
         val seenStore = FakeSeenInvitesStore()
         seenStore.publishRoomIds(setOf(A_ROOM_ID))
         val dataSource = DefaultInviteStateDataSource(client, seenStore, testCoroutineDispatchers(useUnconfinedTestDispatcher = true))
 
-        moleculeFlow(RecompositionClock.Immediate) {
+        moleculeFlow(RecompositionMode.Immediate) {
             dataSource.inviteState()
         }.test {
             skipItems(1)
@@ -100,19 +100,19 @@ internal class DefaultInviteStateDataSourceTest {
 
     @Test
     fun `emits new state in response to upstream events`() = runTest {
-        val roomSummaryDataSource = FakeRoomSummaryDataSource()
-        val client = FakeMatrixClient(roomSummaryDataSource = roomSummaryDataSource)
+        val roomListService = FakeRoomListService()
+        val client = FakeMatrixClient(roomListService = roomListService)
         val seenStore = FakeSeenInvitesStore()
         val dataSource = DefaultInviteStateDataSource(client, seenStore, testCoroutineDispatchers())
 
-        moleculeFlow(RecompositionClock.Immediate) {
+        moleculeFlow(RecompositionMode.Immediate) {
             dataSource.inviteState()
         }.test {
             // Initially there are no invites
             Truth.assertThat(awaitItem()).isEqualTo(InvitesState.NoInvites)
 
             // When a single invite is received, state should be NewInvites
-            roomSummaryDataSource.postInviteRooms(listOf(aRoomSummaryFilled(roomId = A_ROOM_ID)))
+            roomListService.postInviteRooms(listOf(aRoomSummaryFilled(roomId = A_ROOM_ID)))
             skipItems(1)
             Truth.assertThat(awaitItem()).isEqualTo(InvitesState.NewInvites)
 
@@ -122,12 +122,12 @@ internal class DefaultInviteStateDataSourceTest {
             Truth.assertThat(awaitItem()).isEqualTo(InvitesState.SeenInvites)
 
             // Another new invite resets it to NewInvites
-            roomSummaryDataSource.postInviteRooms(listOf(aRoomSummaryFilled(roomId = A_ROOM_ID), aRoomSummaryFilled(roomId = A_ROOM_ID_2)))
+            roomListService.postInviteRooms(listOf(aRoomSummaryFilled(roomId = A_ROOM_ID), aRoomSummaryFilled(roomId = A_ROOM_ID_2)))
             skipItems(1)
             Truth.assertThat(awaitItem()).isEqualTo(InvitesState.NewInvites)
 
             // All of the invites going away reverts to NoInvites
-            roomSummaryDataSource.postInviteRooms(emptyList())
+            roomListService.postInviteRooms(emptyList())
             skipItems(1)
             Truth.assertThat(awaitItem()).isEqualTo(InvitesState.NoInvites)
         }
diff --git a/features/verifysession/impl/src/main/kotlin/io/element/android/features/verifysession/impl/VerifySelfSessionView.kt b/features/verifysession/impl/src/main/kotlin/io/element/android/features/verifysession/impl/VerifySelfSessionView.kt
index 77984a3bb2..0ffd518669 100644
--- a/features/verifysession/impl/src/main/kotlin/io/element/android/features/verifysession/impl/VerifySelfSessionView.kt
+++ b/features/verifysession/impl/src/main/kotlin/io/element/android/features/verifysession/impl/VerifySelfSessionView.kt
@@ -27,7 +27,6 @@ import androidx.compose.foundation.layout.height
 import androidx.compose.foundation.layout.padding
 import androidx.compose.foundation.layout.widthIn
 import androidx.compose.material3.MaterialTheme
-import androidx.compose.material3.TextButton
 import androidx.compose.runtime.Composable
 import androidx.compose.runtime.derivedStateOf
 import androidx.compose.runtime.getValue
@@ -44,15 +43,16 @@ import io.element.android.libraries.architecture.Async
 import io.element.android.libraries.designsystem.atomic.molecules.ButtonColumnMolecule
 import io.element.android.libraries.designsystem.atomic.molecules.IconTitleSubtitleMolecule
 import io.element.android.libraries.designsystem.atomic.pages.HeaderFooterPage
-import io.element.android.libraries.designsystem.components.button.ButtonWithProgress
 import io.element.android.libraries.designsystem.preview.ElementPreviewDark
 import io.element.android.libraries.designsystem.preview.ElementPreviewLight
-import io.element.android.libraries.designsystem.theme.aliasButtonText
+import io.element.android.libraries.designsystem.theme.components.Button
 import io.element.android.libraries.designsystem.theme.components.CircularProgressIndicator
 import io.element.android.libraries.designsystem.theme.components.Text
+import io.element.android.libraries.designsystem.theme.components.TextButton
 import io.element.android.libraries.matrix.api.verification.VerificationEmoji
 import io.element.android.libraries.theme.ElementTheme
 import io.element.android.libraries.ui.strings.CommonStrings
+import kotlinx.coroutines.sync.Mutex
 import io.element.android.features.verifysession.impl.VerifySelfSessionState.VerificationStep as FlowStep
 
 @Composable
@@ -75,6 +75,7 @@ fun VerifySelfSessionView(
     val buttonsVisible by remember(verificationFlowStep) {
         derivedStateOf { verificationFlowStep != FlowStep.AwaitingOtherDeviceResponse && verificationFlowStep != FlowStep.Completed }
     }
+    Mutex()
     HeaderFooterPage(
         modifier = modifier,
         header = {
@@ -219,35 +220,33 @@ internal fun BottomMenu(screenState: VerifySelfSessionState, goBack: () -> Unit)
     ButtonColumnMolecule(
         modifier = Modifier.padding(bottom = 20.dp)
     ) {
-        ButtonWithProgress(
-            text = positiveButtonTitle?.let { stringResource(it) },
-            showProgress = isVerifying,
-            modifier = Modifier.fillMaxWidth(),
-            onClick = { positiveButtonEvent?.let { eventSink(it) } }
-        )
+        if (positiveButtonTitle != null) {
+            Button(
+                text = stringResource(positiveButtonTitle),
+                showProgress = isVerifying,
+                modifier = Modifier.fillMaxWidth(),
+                onClick = { positiveButtonEvent?.let { eventSink(it) } }
+            )
+        }
         if (negativeButtonTitle != null) {
             TextButton(
+                text = stringResource(negativeButtonTitle),
                 modifier = Modifier.fillMaxWidth(),
                 onClick = negativeButtonCallback,
                 enabled = negativeButtonEnabled,
-            ) {
-                Text(
-                    text = stringResource(negativeButtonTitle),
-                    style = ElementTheme.typography.aliasButtonText,
-                )
-            }
+            )
         }
     }
 }
 
 @Preview
 @Composable
-fun VerifySelfSessionViewLightPreview(@PreviewParameter(VerifySelfSessionStateProvider::class) state: VerifySelfSessionState) =
+internal fun VerifySelfSessionViewLightPreview(@PreviewParameter(VerifySelfSessionStateProvider::class) state: VerifySelfSessionState) =
     ElementPreviewLight { ContentToPreview(state) }
 
 @Preview
 @Composable
-fun VerifySelfSessionViewDarkPreview(@PreviewParameter(VerifySelfSessionStateProvider::class) state: VerifySelfSessionState) =
+internal fun VerifySelfSessionViewDarkPreview(@PreviewParameter(VerifySelfSessionStateProvider::class) state: VerifySelfSessionState) =
     ElementPreviewDark { ContentToPreview(state) }
 
 @Composable
diff --git a/features/verifysession/impl/src/main/res/values-ru/translations.xml b/features/verifysession/impl/src/main/res/values-ru/translations.xml
new file mode 100644
index 0000000000..552204fd7a
--- /dev/null
+++ b/features/verifysession/impl/src/main/res/values-ru/translations.xml
@@ -0,0 +1,19 @@
+
+
+  "Кажется, что-то не так. Время ожидания запроса истекло, либо запрос был отклонен."
+  "Убедитесь, что приведенные ниже смайлики совпадают со смайликами, показанными во время другого сеанса."
+  "Сравните смайлики"
+  "Ваш новый сеанс подтвержден. У него есть доступ к вашим зашифрованным сообщениям, и другие пользователи увидят его как доверенное."
+  "Чтобы получить доступ к зашифрованной истории сообщений, докажите, что это вы."
+  "Открыть существующий сеанс"
+  "Повторить проверку"
+  "Я готов"
+  "Ожидание соответствия"
+  "Сравните уникальные смайлики, убедившись, что они расположены в том же порядке."
+  "Они не совпадают"
+  "Они совпадают"
+  "Для продолжения работы примите запрос на запуск процесса проверки в другом сеансе."
+  "Ожидание принятия запроса"
+  "Проверка отменена"
+  "Начать"
+
diff --git a/features/verifysession/impl/src/main/res/values-zh-rTW/translations.xml b/features/verifysession/impl/src/main/res/values-zh-rTW/translations.xml
new file mode 100644
index 0000000000..fc59911a93
--- /dev/null
+++ b/features/verifysession/impl/src/main/res/values-zh-rTW/translations.xml
@@ -0,0 +1,9 @@
+
+
+  "我準備好了"
+  "等待比對"
+  "不相符"
+  "相符"
+  "驗證已取消"
+  "開始"
+
diff --git a/features/verifysession/impl/src/test/kotlin/io/element/android/features/verifysession/impl/VerifySelfSessionPresenterTests.kt b/features/verifysession/impl/src/test/kotlin/io/element/android/features/verifysession/impl/VerifySelfSessionPresenterTests.kt
index 0b58c125de..82664f0e03 100644
--- a/features/verifysession/impl/src/test/kotlin/io/element/android/features/verifysession/impl/VerifySelfSessionPresenterTests.kt
+++ b/features/verifysession/impl/src/test/kotlin/io/element/android/features/verifysession/impl/VerifySelfSessionPresenterTests.kt
@@ -16,7 +16,7 @@
 
 package io.element.android.features.verifysession.impl
 
-import app.cash.molecule.RecompositionClock
+import app.cash.molecule.RecompositionMode
 import app.cash.molecule.moleculeFlow
 import app.cash.turbine.ReceiveTurbine
 import app.cash.turbine.test
@@ -36,7 +36,7 @@ class VerifySelfSessionPresenterTests {
     @Test
     fun `present - Initial state is received`() = runTest {
         val presenter = createPresenter()
-        moleculeFlow(RecompositionClock.Immediate) {
+        moleculeFlow(RecompositionMode.Immediate) {
             presenter.present()
         }.test {
             assertThat(awaitItem().verificationFlowStep).isEqualTo(VerificationStep.Initial)
@@ -47,7 +47,7 @@ class VerifySelfSessionPresenterTests {
     fun `present - Handles requestVerification`() = runTest {
         val service = FakeSessionVerificationService()
         val presenter = createPresenter(service)
-        moleculeFlow(RecompositionClock.Immediate) {
+        moleculeFlow(RecompositionMode.Immediate) {
             presenter.present()
         }.test {
             requestVerificationAndAwaitVerifyingState(service)
@@ -58,7 +58,7 @@ class VerifySelfSessionPresenterTests {
     fun `present - Handles startSasVerification`() = runTest {
         val service = FakeSessionVerificationService()
         val presenter = createPresenter(service)
-        moleculeFlow(RecompositionClock.Immediate) {
+        moleculeFlow(RecompositionMode.Immediate) {
             presenter.present()
         }.test {
             val initialState = awaitItem()
@@ -77,7 +77,7 @@ class VerifySelfSessionPresenterTests {
     @Test
     fun `present - Cancelation on initial state does nothing`() = runTest {
         val presenter = createPresenter()
-        moleculeFlow(RecompositionClock.Immediate) {
+        moleculeFlow(RecompositionMode.Immediate) {
             presenter.present()
         }.test {
             val initialState = awaitItem()
@@ -92,7 +92,7 @@ class VerifySelfSessionPresenterTests {
     fun `present - A fail in the flow cancels it`() = runTest {
         val service = FakeSessionVerificationService()
         val presenter = createPresenter(service)
-        moleculeFlow(RecompositionClock.Immediate) {
+        moleculeFlow(RecompositionMode.Immediate) {
             presenter.present()
         }.test {
             val state = requestVerificationAndAwaitVerifyingState(service)
@@ -109,7 +109,7 @@ class VerifySelfSessionPresenterTests {
     fun `present - Canceling the flow once it's verifying cancels it`() = runTest {
         val service = FakeSessionVerificationService()
         val presenter = createPresenter(service)
-        moleculeFlow(RecompositionClock.Immediate) {
+        moleculeFlow(RecompositionMode.Immediate) {
             presenter.present()
         }.test {
             val state = requestVerificationAndAwaitVerifyingState(service)
@@ -123,7 +123,7 @@ class VerifySelfSessionPresenterTests {
     fun `present - When verifying, if we receive another challenge we ignore it`() = runTest {
         val service = FakeSessionVerificationService()
         val presenter = createPresenter(service)
-        moleculeFlow(RecompositionClock.Immediate) {
+        moleculeFlow(RecompositionMode.Immediate) {
             presenter.present()
         }.test {
             requestVerificationAndAwaitVerifyingState(service)
@@ -136,7 +136,7 @@ class VerifySelfSessionPresenterTests {
     fun `present - Restart after cancelation returns to requesting verification`() = runTest {
         val service = FakeSessionVerificationService()
         val presenter = createPresenter(service)
-        moleculeFlow(RecompositionClock.Immediate) {
+        moleculeFlow(RecompositionMode.Immediate) {
             presenter.present()
         }.test {
             val state = requestVerificationAndAwaitVerifyingState(service)
@@ -158,7 +158,7 @@ class VerifySelfSessionPresenterTests {
             givenEmojiList(emojis)
         }
         val presenter = createPresenter(service)
-        moleculeFlow(RecompositionClock.Immediate) {
+        moleculeFlow(RecompositionMode.Immediate) {
             presenter.present()
         }.test {
             val state = requestVerificationAndAwaitVerifyingState(service)
@@ -172,7 +172,7 @@ class VerifySelfSessionPresenterTests {
     fun `present - When verification is declined, the flow is canceled`() = runTest {
         val service = FakeSessionVerificationService()
         val presenter = createPresenter(service)
-        moleculeFlow(RecompositionClock.Immediate) {
+        moleculeFlow(RecompositionMode.Immediate) {
             presenter.present()
         }.test {
             val state = requestVerificationAndAwaitVerifyingState(service)
diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml
index f0759ee705..ca23a17afd 100644
--- a/gradle/libs.versions.toml
+++ b/gradle/libs.versions.toml
@@ -6,7 +6,7 @@
 android_gradle_plugin = "8.0.2"
 kotlin = "1.8.22"
 ksp = "1.8.22-1.0.11"
-molecule = "0.11.0"
+molecule = "1.2.0"
 
 # AndroidX
 material = "1.9.0"
@@ -14,11 +14,11 @@ core = "1.10.1"
 datastore = "1.0.0"
 constraintlayout = "2.1.4"
 constraintlayout_compose = "1.0.1"
-recyclerview = "1.3.0"
+recyclerview = "1.3.1"
 lifecycle = "2.6.1"
 activity = "1.7.2"
 startup = "1.1.1"
-media3 = "1.1.0"
+media3 = "1.1.1"
 browser = "1.5.0"
 
 # Compose
@@ -45,11 +45,11 @@ dependencycheck = "8.3.1"
 dependencyanalysis = "1.20.0"
 stem = "2.3.0"
 sqldelight = "1.5.5"
-telephoto = "0.4.0"
+telephoto = "0.5.0"
 
 # DI
 dagger = "2.47"
-anvil = "2.4.6"
+anvil = "2.4.7-1-8"
 
 # Auto service
 autoservice = "1.1.1"
@@ -65,7 +65,7 @@ android_gradle_plugin = { module = "com.android.tools.build:gradle", version.ref
 android_desugar = "com.android.tools:desugar_jdk_libs:2.0.3"
 kotlin_gradle_plugin = { module = "org.jetbrains.kotlin:kotlin-gradle-plugin", version.ref = "kotlin" }
 # https://firebase.google.com/docs/android/setup#available-libraries
-google_firebase_bom = "com.google.firebase:firebase-bom:32.2.0"
+google_firebase_bom = "com.google.firebase:firebase-bom:32.2.2"
 
 # AndroidX
 androidx_material = { module = "com.google.android.material:material", version.ref = "material" }
@@ -123,7 +123,7 @@ test_junit = "junit:junit:4.13.2"
 test_runner = "androidx.test:runner:1.5.2"
 test_uiautomator = "androidx.test.uiautomator:uiautomator:2.2.0"
 test_junitext = "androidx.test.ext:junit:1.1.5"
-test_mockk = "io.mockk:mockk:1.13.5"
+test_mockk = "io.mockk:mockk:1.13.7"
 test_barista = "com.adevinta.android:barista:4.3.0"
 test_hamcrest = "org.hamcrest:hamcrest:2.2"
 test_orchestrator = "androidx.test:orchestrator:1.4.2"
@@ -145,7 +145,7 @@ jsoup = { module = "org.jsoup:jsoup", version.ref = "jsoup" }
 appyx_core = { module = "com.bumble.appyx:core", version.ref = "appyx" }
 molecule-runtime = { module = "app.cash.molecule:molecule-runtime", version.ref = "molecule" }
 timber = "com.jakewharton.timber:timber:5.0.1"
-matrix_sdk = "org.matrix.rustcomponents:sdk-android:0.1.34"
+matrix_sdk = "org.matrix.rustcomponents:sdk-android:0.1.42"
 sqldelight-driver-android = { module = "com.squareup.sqldelight:android-driver", version.ref = "sqldelight" }
 sqldelight-driver-jvm = { module = "com.squareup.sqldelight:sqlite-driver", version.ref = "sqldelight" }
 sqldelight-coroutines = { module = "com.squareup.sqldelight:coroutines-extensions", version.ref = "sqldelight" }
@@ -156,14 +156,14 @@ otaliastudios_transcoder = "com.otaliastudios:transcoder:0.10.5"
 vanniktech_blurhash = "com.vanniktech:blurhash:0.1.0"
 vanniktech_emoji = "com.vanniktech:emoji-google:0.16.0"
 telephoto_zoomableimage = { module = "me.saket.telephoto:zoomable-image-coil", version.ref = "telephoto" }
-statemachine = "com.freeletics.flowredux:compose:1.1.0"
+statemachine = "com.freeletics.flowredux:compose:1.2.0"
 maplibre = "org.maplibre.gl:android-sdk:10.2.0"
 maplibre_ktx = "org.maplibre.gl:android-sdk-ktx-v7:2.0.0"
 maplibre_annotation = "org.maplibre.gl:android-plugin-annotation-v9:2.0.0"
 
 # Analytics
 posthog = "com.posthog.android:posthog:2.0.3"
-sentry_android = "io.sentry:sentry-android:6.26.0"
+sentry = "io.sentry:sentry-android:6.28.0"
 matrix_analytics_events = "com.github.matrix-org:matrix-analytics-events:42b2faa417c1e95f430bf8f6e379adba25ad5ef8"
 
 # Di
@@ -196,7 +196,7 @@ kapt = { id = "org.jetbrains.kotlin.kapt", version.ref = "kotlin" }
 ksp = { id = "com.google.devtools.ksp", version.ref = "ksp" }
 anvil = { id = "com.squareup.anvil", version.ref = "anvil" }
 detekt = { id = "io.gitlab.arturbosch.detekt", version.ref = "detekt" }
-ktlint = "org.jlleitschuh.gradle.ktlint:11.5.0"
+ktlint = "org.jlleitschuh.gradle.ktlint:11.5.1"
 dependencygraph = { id = "com.savvasdalkitsis.module-dependency-graph", version.ref = "dependencygraph" }
 dependencycheck = { id = "org.owasp.dependencycheck", version.ref = "dependencycheck" }
 dependencyanalysis = { id = "com.autonomousapps.dependency-analysis", version.ref = "dependencyanalysis" }
diff --git a/libraries/androidutils/build.gradle.kts b/libraries/androidutils/build.gradle.kts
index 92e3c46126..57e4ca3569 100644
--- a/libraries/androidutils/build.gradle.kts
+++ b/libraries/androidutils/build.gradle.kts
@@ -37,6 +37,7 @@ dependencies {
     implementation(libs.timber)
     implementation(libs.androidx.corektx)
     implementation(libs.androidx.activity.activity)
+    implementation(libs.androidx.recyclerview)
     implementation(libs.androidx.exifinterface)
     implementation(libs.androidx.security.crypto)
     implementation(libs.androidx.browser)
diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/diff/MatrixTimelineItemsDiffCallback.kt b/libraries/androidutils/src/main/kotlin/io/element/android/libraries/androidutils/diff/DefaultDiffCallback.kt
similarity index 70%
rename from features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/diff/MatrixTimelineItemsDiffCallback.kt
rename to libraries/androidutils/src/main/kotlin/io/element/android/libraries/androidutils/diff/DefaultDiffCallback.kt
index 4a78447bd7..219441d5e6 100644
--- a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/diff/MatrixTimelineItemsDiffCallback.kt
+++ b/libraries/androidutils/src/main/kotlin/io/element/android/libraries/androidutils/diff/DefaultDiffCallback.kt
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2022 New Vector Ltd
+ * Copyright (c) 2023 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.
@@ -14,14 +14,17 @@
  * limitations under the License.
  */
 
-package io.element.android.features.messages.impl.timeline.diff
+package io.element.android.libraries.androidutils.diff
 
 import androidx.recyclerview.widget.DiffUtil
-import io.element.android.libraries.matrix.api.timeline.MatrixTimelineItem
 
-internal class MatrixTimelineItemsDiffCallback(
-    private val oldList: List,
-    private val newList: List
+/**
+ *  Default implementation of [DiffUtil.Callback] that uses [areItemsTheSame] to compare items.
+ */
+internal class DefaultDiffCallback(
+    private val oldList: List,
+    private val newList: List,
+    private val areItemsTheSame: (oldItem: T?, newItem: T?) -> Boolean,
 ) : DiffUtil.Callback() {
 
     override fun getOldListSize(): Int {
@@ -35,11 +38,7 @@ internal class MatrixTimelineItemsDiffCallback(
     override fun areItemsTheSame(oldItemPosition: Int, newItemPosition: Int): Boolean {
         val oldItem = oldList.getOrNull(oldItemPosition)
         val newItem = newList.getOrNull(newItemPosition)
-        return if (oldItem is MatrixTimelineItem.Event && newItem is MatrixTimelineItem.Event) {
-            oldItem.uniqueId == newItem.uniqueId
-        } else {
-            false
-        }
+        return areItemsTheSame(oldItem, newItem)
     }
 
     override fun areContentsTheSame(oldItemPosition: Int, newItemPosition: Int): Boolean {
diff --git a/libraries/androidutils/src/main/kotlin/io/element/android/libraries/androidutils/diff/DiffCache.kt b/libraries/androidutils/src/main/kotlin/io/element/android/libraries/androidutils/diff/DiffCache.kt
new file mode 100644
index 0000000000..3d1161e2e0
--- /dev/null
+++ b/libraries/androidutils/src/main/kotlin/io/element/android/libraries/androidutils/diff/DiffCache.kt
@@ -0,0 +1,67 @@
+/*
+ * Copyright (c) 2023 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
+ *
+ *     http://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.androidutils.diff
+
+/**
+ * A cache that can be used to store some data that can be invalidated when a diff is applied.
+ * The cache is invalidated by the [DiffCacheInvalidator].
+ */
+interface DiffCache {
+    fun get(index: Int): E?
+    fun indices(): IntRange
+    fun isEmpty(): Boolean
+}
+
+/**
+ * A [DiffCache] that can be mutated by adding, removing or updating elements.
+ */
+interface MutableDiffCache : DiffCache {
+    fun removeAt(index: Int): E?
+    fun add(index: Int, element: E?)
+    operator fun set(index: Int, element: E?)
+}
+
+/**
+ * A [MutableDiffCache] backed by a [MutableList].
+ *
+ */
+class MutableListDiffCache(private val mutableList: MutableList = ArrayList()) : MutableDiffCache {
+
+    override fun removeAt(index: Int): E? {
+        return mutableList.removeAt(index)
+    }
+
+    override fun get(index: Int): E? {
+        return mutableList.getOrNull(index)
+    }
+
+    override fun indices(): IntRange {
+        return mutableList.indices
+    }
+
+    override fun isEmpty(): Boolean {
+        return mutableList.isEmpty()
+    }
+
+    override operator fun set(index: Int, element: E?) {
+        mutableList[index] = element
+    }
+
+    override fun add(index: Int, element: E?) {
+        mutableList.add(index, element)
+    }
+}
diff --git a/libraries/androidutils/src/main/kotlin/io/element/android/libraries/androidutils/diff/DiffCacheInvalidator.kt b/libraries/androidutils/src/main/kotlin/io/element/android/libraries/androidutils/diff/DiffCacheInvalidator.kt
new file mode 100644
index 0000000000..4ebdc3224f
--- /dev/null
+++ b/libraries/androidutils/src/main/kotlin/io/element/android/libraries/androidutils/diff/DiffCacheInvalidator.kt
@@ -0,0 +1,63 @@
+/*
+ * Copyright (c) 2023 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
+ *
+ *     http://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.androidutils.diff
+
+/**
+ * [DiffCacheInvalidator] is used to invalidate the cache when the list is updated.
+ * It is used by [DiffCacheUpdater].
+ * Check the default implementation [DefaultDiffCacheInvalidator].
+ */
+interface DiffCacheInvalidator {
+    fun onChanged(position: Int, count: Int, cache: MutableDiffCache)
+
+    fun onMoved(fromPosition: Int, toPosition: Int, cache: MutableDiffCache)
+
+    fun onInserted(position: Int, count: Int, cache: MutableDiffCache)
+
+    fun onRemoved(position: Int, count: Int, cache: MutableDiffCache)
+}
+
+/**
+ * Default implementation of [DiffCacheInvalidator].
+ * It invalidates the cache by setting values to null.
+ */
+class DefaultDiffCacheInvalidator : DiffCacheInvalidator {
+
+    override fun onChanged(position: Int, count: Int, cache: MutableDiffCache) {
+        for (i in position until position + count) {
+            // Invalidate cache
+            cache[i] = null
+        }
+    }
+
+    override fun onMoved(fromPosition: Int, toPosition: Int, cache: MutableDiffCache) {
+        val model = cache.removeAt(fromPosition)
+        cache.add(toPosition, model)
+    }
+
+    override fun onInserted(position: Int, count: Int, cache: MutableDiffCache) {
+        repeat(count) {
+            cache.add(position, null)
+        }
+    }
+
+    override fun onRemoved(position: Int, count: Int, cache: MutableDiffCache) {
+        repeat(count) {
+            cache.removeAt(position)
+        }
+    }
+}
diff --git a/libraries/androidutils/src/main/kotlin/io/element/android/libraries/androidutils/diff/DiffCacheUpdater.kt b/libraries/androidutils/src/main/kotlin/io/element/android/libraries/androidutils/diff/DiffCacheUpdater.kt
new file mode 100644
index 0000000000..500edcb135
--- /dev/null
+++ b/libraries/androidutils/src/main/kotlin/io/element/android/libraries/androidutils/diff/DiffCacheUpdater.kt
@@ -0,0 +1,70 @@
+/*
+ * Copyright (c) 2023 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
+ *
+ *     http://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.androidutils.diff
+
+import androidx.recyclerview.widget.DiffUtil
+import androidx.recyclerview.widget.ListUpdateCallback
+import timber.log.Timber
+import kotlin.system.measureTimeMillis
+
+/**
+ * Class in charge of updating a [MutableDiffCache] according to the cache invalidation rules provided by the [DiffCacheInvalidator].
+ * @param ListItem the type of the items in the list
+ * @param CachedItem the type of the items in the cache
+ * @param diffCache the cache to update
+ * @param detectMoves true if DiffUtil should try to detect moved items, false otherwise
+ * @param cacheInvalidator the invalidator to use to update the cache
+ * @param areItemsTheSame the function to use to compare items
+ */
+class DiffCacheUpdater(
+    private val diffCache: MutableDiffCache,
+    private val detectMoves: Boolean = false,
+    private val cacheInvalidator: DiffCacheInvalidator = DefaultDiffCacheInvalidator(),
+    private val areItemsTheSame: (oldItem: ListItem?, newItem: ListItem?) -> Boolean,
+) {
+
+    private val lock = Object()
+    private var prevOriginalList: List = emptyList()
+
+    private val listUpdateCallback = object : ListUpdateCallback {
+        override fun onInserted(position: Int, count: Int) {
+            cacheInvalidator.onInserted(position, count, diffCache)
+        }
+
+        override fun onRemoved(position: Int, count: Int) {
+            cacheInvalidator.onRemoved(position, count, diffCache)
+        }
+
+        override fun onMoved(fromPosition: Int, toPosition: Int) {
+            cacheInvalidator.onMoved(fromPosition, toPosition, diffCache)
+        }
+
+        override fun onChanged(position: Int, count: Int, payload: Any?) {
+            cacheInvalidator.onChanged(position, count, diffCache)
+        }
+    }
+
+    fun updateWith(newOriginalList: List) = synchronized(lock) {
+        val timeToDiff = measureTimeMillis {
+            val diffCallback = DefaultDiffCallback(prevOriginalList, newOriginalList, areItemsTheSame)
+            val diffResult = DiffUtil.calculateDiff(diffCallback, detectMoves)
+            prevOriginalList = newOriginalList
+            diffResult.dispatchUpdatesTo(listUpdateCallback)
+        }
+        Timber.v("Time to apply diff on new list of ${newOriginalList.size} items: $timeToDiff ms")
+    }
+}
diff --git a/libraries/androidutils/src/main/kotlin/io/element/android/libraries/androidutils/system/SystemUtils.kt b/libraries/androidutils/src/main/kotlin/io/element/android/libraries/androidutils/system/SystemUtils.kt
index 65a5dc9e0d..a9a17dcceb 100644
--- a/libraries/androidutils/src/main/kotlin/io/element/android/libraries/androidutils/system/SystemUtils.kt
+++ b/libraries/androidutils/src/main/kotlin/io/element/android/libraries/androidutils/system/SystemUtils.kt
@@ -59,7 +59,7 @@ fun Context.isAnimationEnabled(): Boolean {
 }
 
 @ChecksSdkIntAtLeast(api = Build.VERSION_CODES.O)
-fun supportNotificationChannels() = (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O)
+fun supportNotificationChannels() = Build.VERSION.SDK_INT >= Build.VERSION_CODES.O
 
 /**
  * Return the application label of the provided package. If not found, the package is returned.
@@ -183,7 +183,7 @@ fun Context.startInstallFromSourceIntent(
     noActivityFoundMessage: String = getString(R.string.error_no_compatible_app_found),
 ) {
     val intent = Intent(Settings.ACTION_MANAGE_UNKNOWN_APP_SOURCES)
-        .setData(Uri.parse(String.format("package:%s", packageName)))
+        .setData(Uri.parse("package:$packageName"))
     try {
         activityResultLauncher.launch(intent)
     } catch (activityNotFoundException: ActivityNotFoundException) {
diff --git a/libraries/androidutils/src/main/res/values-ru/translations.xml b/libraries/androidutils/src/main/res/values-ru/translations.xml
new file mode 100644
index 0000000000..bb236dc893
--- /dev/null
+++ b/libraries/androidutils/src/main/res/values-ru/translations.xml
@@ -0,0 +1,4 @@
+
+
+  "Не найдено совместимое приложение для обработки этого действия."
+
diff --git a/libraries/androidutils/src/main/res/values/integers.xml b/libraries/androidutils/src/main/res/values/integers.xml
index ecbfa4cdda..2f9e641bdf 100644
--- a/libraries/androidutils/src/main/res/values/integers.xml
+++ b/libraries/androidutils/src/main/res/values/integers.xml
@@ -15,9 +15,9 @@
   ~ limitations under the License.
   -->
 
-
+
 
-    1
-    0
+    1
+    0
 
 
diff --git a/libraries/architecture/src/main/kotlin/io/element/android/libraries/architecture/NodeInputs.kt b/libraries/architecture/src/main/kotlin/io/element/android/libraries/architecture/NodeInputs.kt
index b96d9e166b..534c9d741b 100644
--- a/libraries/architecture/src/main/kotlin/io/element/android/libraries/architecture/NodeInputs.kt
+++ b/libraries/architecture/src/main/kotlin/io/element/android/libraries/architecture/NodeInputs.kt
@@ -23,5 +23,5 @@ import com.bumble.appyx.core.plugin.plugins
 interface NodeInputs : Plugin
 
 inline fun  Node.inputs(): I {
-    return plugins().firstOrNull() ?: throw RuntimeException("Make sure to actually pass NodeInputs plugin to your node")
+    return requireNotNull(plugins().firstOrNull()) { "Make sure to actually pass NodeInputs plugin to your node" }
 }
diff --git a/libraries/core/src/main/kotlin/io/element/android/libraries/core/data/Try.kt b/libraries/core/src/main/kotlin/io/element/android/libraries/core/data/Try.kt
index b91d249547..fe801e71f7 100644
--- a/libraries/core/src/main/kotlin/io/element/android/libraries/core/data/Try.kt
+++ b/libraries/core/src/main/kotlin/io/element/android/libraries/core/data/Try.kt
@@ -16,11 +16,11 @@
 
 package io.element.android.libraries.core.data
 
-inline fun  tryOrNull(noinline onError: ((Throwable) -> Unit)? = null, operation: () -> A): A? {
+inline fun  tryOrNull(onError: ((Throwable) -> Unit) = { }, operation: () -> A): A? {
     return try {
         operation()
     } catch (any: Throwable) {
-        onError?.invoke(any)
+        onError.invoke(any)
         null
     }
 }
diff --git a/libraries/core/src/main/kotlin/io/element/android/libraries/core/extensions/BasicExtensions.kt b/libraries/core/src/main/kotlin/io/element/android/libraries/core/extensions/BasicExtensions.kt
index db07432df0..343f5ce351 100644
--- a/libraries/core/src/main/kotlin/io/element/android/libraries/core/extensions/BasicExtensions.kt
+++ b/libraries/core/src/main/kotlin/io/element/android/libraries/core/extensions/BasicExtensions.kt
@@ -72,7 +72,3 @@ fun String.ellipsize(length: Int): String {
 
     return "${this.take(length)}…"
 }
-
-inline fun  Any?.takeAs(): R? {
-    return takeIf { it is R } as R?
-}
diff --git a/libraries/dateformatter/impl/src/test/kotlin/io/element/android/libraries/dateformatter/impl/DefaultLastMessageTimestampFormatterTest.kt b/libraries/dateformatter/impl/src/test/kotlin/io/element/android/libraries/dateformatter/impl/DefaultLastMessageTimestampFormatterTest.kt
index 483e27af71..5aefcdcd7b 100644
--- a/libraries/dateformatter/impl/src/test/kotlin/io/element/android/libraries/dateformatter/impl/DefaultLastMessageTimestampFormatterTest.kt
+++ b/libraries/dateformatter/impl/src/test/kotlin/io/element/android/libraries/dateformatter/impl/DefaultLastMessageTimestampFormatterTest.kt
@@ -101,7 +101,7 @@ class DefaultLastMessageTimestampFormatterTest {
      * Create DefaultLastMessageFormatter and set current time to the provided date.
      */
     private fun createFormatter(@Suppress("SameParameterValue") currentDate: String): LastMessageTimestampFormatter {
-        val clock = FakeClock().also { it.givenInstant(Instant.parse(currentDate)) }
+        val clock = FakeClock().apply { givenInstant(Instant.parse(currentDate)) }
         val localDateTimeProvider = LocalDateTimeProvider(clock, TimeZone.UTC)
         val dateFormatters = DateFormatters(Locale.US, clock, TimeZone.UTC)
         return DefaultLastMessageTimestampFormatter(localDateTimeProvider, dateFormatters)
diff --git a/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/VectorIcons.kt b/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/VectorIcons.kt
index 0e33567129..47b951baa2 100644
--- a/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/VectorIcons.kt
+++ b/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/VectorIcons.kt
@@ -25,4 +25,6 @@ object VectorIcons {
     val DoorOpen = R.drawable.ic_door_open_24
     val DeveloperMode = R.drawable.ic_developer_mode
     val ReportContent = R.drawable.ic_report_content
+    val Groups = R.drawable.ic_groups
+    val Share = R.drawable.ic_share
 }
diff --git a/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/atomic/atoms/ElementLogoAtom.kt b/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/atomic/atoms/ElementLogoAtom.kt
index 94e50d5953..8f96ed6b6e 100644
--- a/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/atomic/atoms/ElementLogoAtom.kt
+++ b/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/atomic/atoms/ElementLogoAtom.kt
@@ -138,7 +138,7 @@ fun Modifier.shapeShadow(
                 val paint = Paint()
                 val frameworkPaint = paint.asFrameworkPaint()
                 if (blurRadius != 0.dp) {
-                    frameworkPaint.maskFilter = (BlurMaskFilter(blurRadius.toPx(), BlurMaskFilter.Blur.NORMAL))
+                    frameworkPaint.maskFilter = BlurMaskFilter(blurRadius.toPx(), BlurMaskFilter.Blur.NORMAL)
                 }
                 frameworkPaint.color = color.toArgb()
 
diff --git a/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/atomic/atoms/InfoListItemMolecule.kt b/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/atomic/atoms/InfoListItemMolecule.kt
index 6b20c96880..2af9e77b99 100644
--- a/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/atomic/atoms/InfoListItemMolecule.kt
+++ b/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/atomic/atoms/InfoListItemMolecule.kt
@@ -70,7 +70,7 @@ fun InfoListItemMolecule(
 
 @DayNightPreviews
 @Composable
-fun InfoListItemMoleculePreview() {
+internal fun InfoListItemMoleculePreview() {
     ElementPreview {
         val color = if (isSystemInDarkTheme()) Color.DarkGray else Color.LightGray
         Column(
diff --git a/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/atomic/molecules/ButtonColumnMolecule.kt b/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/atomic/molecules/ButtonColumnMolecule.kt
index a8ad97a950..9fc688f227 100644
--- a/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/atomic/molecules/ButtonColumnMolecule.kt
+++ b/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/atomic/molecules/ButtonColumnMolecule.kt
@@ -28,7 +28,7 @@ import androidx.compose.ui.unit.dp
 import io.element.android.libraries.designsystem.preview.ElementPreviewDark
 import io.element.android.libraries.designsystem.preview.ElementPreviewLight
 import io.element.android.libraries.designsystem.theme.components.Button
-import io.element.android.libraries.designsystem.theme.components.Text
+import io.element.android.libraries.designsystem.theme.components.OutlinedButton
 import io.element.android.libraries.designsystem.theme.components.TextButton
 
 @Composable
@@ -59,11 +59,8 @@ internal fun ButtonColumnMoleculeDarkPreview() =
 @Composable
 private fun ContentToPreview() {
     ButtonColumnMolecule {
-        Button(onClick = {}, modifier = Modifier.fillMaxWidth()) {
-            Text(text = "Button")
-        }
-        TextButton(onClick = {}, modifier = Modifier.fillMaxWidth()) {
-            Text(text = "TextButton")
-        }
+        Button(text = "Button", onClick = {}, modifier = Modifier.fillMaxWidth())
+        OutlinedButton(text = "OutlinedButton", onClick = {}, modifier = Modifier.fillMaxWidth())
+        TextButton(text = "TextButton", onClick = {}, modifier = Modifier.fillMaxWidth())
     }
 }
diff --git a/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/atomic/molecules/ButtonRowMolecule.kt b/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/atomic/molecules/ButtonRowMolecule.kt
index b8b5a2146f..7c03a2106e 100644
--- a/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/atomic/molecules/ButtonRowMolecule.kt
+++ b/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/atomic/molecules/ButtonRowMolecule.kt
@@ -25,7 +25,6 @@ import androidx.compose.ui.Modifier
 import androidx.compose.ui.tooling.preview.Preview
 import io.element.android.libraries.designsystem.preview.ElementPreviewDark
 import io.element.android.libraries.designsystem.preview.ElementPreviewLight
-import io.element.android.libraries.designsystem.theme.components.Text
 import io.element.android.libraries.designsystem.theme.components.TextButton
 
 @Composable
@@ -54,11 +53,7 @@ internal fun ButtonRowMoleculeDarkPreview() =
 @Composable
 private fun ContentToPreview() {
     ButtonRowMolecule {
-        TextButton(onClick = { }) {
-            Text("Button 1")
-        }
-        TextButton(onClick = { }) {
-            Text("Button 2")
-        }
+        TextButton(text = "Button 1", onClick = {})
+        TextButton(text = "Button 2", onClick = {})
     }
 }
diff --git a/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/atomic/molecules/IconTitlePlaceholdersRowMolecule.kt b/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/atomic/molecules/IconTitlePlaceholdersRowMolecule.kt
new file mode 100644
index 0000000000..1a10aa2886
--- /dev/null
+++ b/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/atomic/molecules/IconTitlePlaceholdersRowMolecule.kt
@@ -0,0 +1,70 @@
+/*
+ * Copyright (c) 2023 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
+ *
+ *     http://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.designsystem.atomic.molecules
+
+import androidx.compose.foundation.background
+import androidx.compose.foundation.layout.Arrangement
+import androidx.compose.foundation.layout.Box
+import androidx.compose.foundation.layout.Row
+import androidx.compose.foundation.layout.Spacer
+import androidx.compose.foundation.layout.size
+import androidx.compose.foundation.layout.width
+import androidx.compose.foundation.shape.CircleShape
+import androidx.compose.runtime.Composable
+import androidx.compose.ui.Alignment
+import androidx.compose.ui.Modifier
+import androidx.compose.ui.unit.Dp
+import androidx.compose.ui.unit.dp
+import io.element.android.libraries.designsystem.atomic.atoms.PlaceholderAtom
+import io.element.android.libraries.designsystem.components.avatar.AvatarSize
+import io.element.android.libraries.designsystem.preview.DayNightPreviews
+import io.element.android.libraries.designsystem.preview.ElementPreview
+import io.element.android.libraries.designsystem.theme.placeholderBackground
+import io.element.android.libraries.theme.ElementTheme
+
+@Composable
+fun IconTitlePlaceholdersRowMolecule(
+    iconSize: Dp,
+    modifier: Modifier = Modifier,
+    horizontalArrangement: Arrangement.Horizontal = Arrangement.Start,
+    verticalAlignment: Alignment.Vertical = Alignment.CenterVertically,
+) {
+    Row(
+        modifier = modifier,
+        horizontalArrangement = horizontalArrangement,
+        verticalAlignment = verticalAlignment,
+    ) {
+        Box(
+            modifier = Modifier
+                .size(iconSize)
+                .align(Alignment.CenterVertically)
+                .background(color = ElementTheme.colors.placeholderBackground, shape = CircleShape)
+        )
+        Spacer(modifier = Modifier.width(8.dp))
+        PlaceholderAtom(width = 20.dp, height = 7.dp)
+        Spacer(modifier = Modifier.width(7.dp))
+        PlaceholderAtom(width = 45.dp, height = 7.dp)
+    }
+}
+
+@DayNightPreviews
+@Composable
+internal fun IconTitlePlaceholdersRowMoleculePreview() = ElementPreview {
+    IconTitlePlaceholdersRowMolecule(
+        iconSize = AvatarSize.TimelineRoom.dp,
+    )
+}
diff --git a/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/components/LabelledTextField.kt b/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/components/LabelledTextField.kt
index cc1d92ccd8..4856d54bff 100644
--- a/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/components/LabelledTextField.kt
+++ b/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/components/LabelledTextField.kt
@@ -20,6 +20,7 @@ import androidx.compose.foundation.layout.Arrangement
 import androidx.compose.foundation.layout.Column
 import androidx.compose.foundation.layout.fillMaxWidth
 import androidx.compose.foundation.layout.padding
+import androidx.compose.foundation.text.KeyboardOptions
 import androidx.compose.material3.MaterialTheme
 import androidx.compose.runtime.Composable
 import androidx.compose.ui.Modifier
@@ -39,6 +40,7 @@ fun LabelledTextField(
     placeholder: String? = null,
     singleLine: Boolean = false,
     maxLines: Int = if (singleLine) 1 else Int.MAX_VALUE,
+    keyboardOptions: KeyboardOptions = KeyboardOptions.Default,
     onValueChange: (String) -> Unit = {},
 ) {
     Column(
@@ -59,17 +61,18 @@ fun LabelledTextField(
             onValueChange = onValueChange,
             singleLine = singleLine,
             maxLines = maxLines,
+            keyboardOptions = keyboardOptions,
         )
     }
 }
 
 @Preview
 @Composable
-fun LabelledTextFieldLightPreview() = ElementPreviewLight { ContentToPreview() }
+internal fun LabelledTextFieldLightPreview() = ElementPreviewLight { ContentToPreview() }
 
 @Preview
 @Composable
-fun LabelledTextFieldDarkPreview() = ElementPreviewDark { ContentToPreview() }
+internal fun LabelledTextFieldDarkPreview() = ElementPreviewDark { ContentToPreview() }
 
 @Composable
 private fun ContentToPreview() {
diff --git a/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/components/PinIcon.kt b/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/components/PinIcon.kt
index c6af3e1cdf..93a0c5d436 100644
--- a/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/components/PinIcon.kt
+++ b/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/components/PinIcon.kt
@@ -51,6 +51,6 @@ fun PinIcon(
 
 @DayNightPreviews
 @Composable
-fun PinIconPreview() = ElementPreview {
+internal fun PinIconPreview() = ElementPreview {
     PinIcon()
 }
diff --git a/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/components/ProgressDialog.kt b/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/components/ProgressDialog.kt
index a5ad996ea7..20589c89ee 100644
--- a/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/components/ProgressDialog.kt
+++ b/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/components/ProgressDialog.kt
@@ -35,7 +35,7 @@ import androidx.compose.ui.tooling.preview.Preview
 import androidx.compose.ui.unit.dp
 import androidx.compose.ui.window.Dialog
 import androidx.compose.ui.window.DialogProperties
-import io.element.android.libraries.designsystem.components.dialogs.DialogPreview
+import io.element.android.libraries.designsystem.theme.components.DialogPreview
 import io.element.android.libraries.designsystem.preview.ElementThemedPreview
 import io.element.android.libraries.designsystem.preview.PreviewGroup
 import io.element.android.libraries.designsystem.theme.components.CircularProgressIndicator
@@ -129,9 +129,10 @@ private fun ProgressDialogContent(
                     modifier = Modifier.fillMaxWidth(),
                     contentAlignment = Alignment.BottomEnd
                 ) {
-                    TextButton(onClick = onCancelClicked) {
-                        Text(stringResource(id = CommonStrings.action_cancel))
-                    }
+                    TextButton(
+                        text = stringResource(id = CommonStrings.action_cancel),
+                        onClick = onCancelClicked,
+                    )
                 }
             }
         }
diff --git a/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/components/async/AsyncFailure.kt b/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/components/async/AsyncFailure.kt
index b5aa9b85d3..d30b78ca7f 100644
--- a/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/components/async/AsyncFailure.kt
+++ b/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/components/async/AsyncFailure.kt
@@ -48,9 +48,10 @@ fun AsyncFailure(
         Text(text = throwable.message ?: stringResource(id = CommonStrings.error_unknown))
         if (onRetry != null) {
             Spacer(modifier = Modifier.height(24.dp))
-            Button(onClick = onRetry) {
-                Text(text = stringResource(id = CommonStrings.action_retry))
-            }
+            Button(
+                text = stringResource(id = CommonStrings.action_retry),
+                onClick = onRetry
+            )
         }
     }
 }
diff --git a/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/components/avatar/Avatar.kt b/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/components/avatar/Avatar.kt
index b28e52a5ff..1c763a81c3 100644
--- a/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/components/avatar/Avatar.kt
+++ b/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/components/avatar/Avatar.kt
@@ -102,7 +102,7 @@ private fun InitialsAvatar(
 
 @Preview(group = PreviewGroup.Avatars)
 @Composable
-fun AvatarPreview(@PreviewParameter(AvatarDataProvider::class) avatarData: AvatarData) =
+internal fun AvatarPreview(@PreviewParameter(AvatarDataProvider::class) avatarData: AvatarData) =
     ElementThemedPreview {
         Row(
             verticalAlignment = Alignment.CenterVertically,
diff --git a/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/components/avatar/AvatarDataProvider.kt b/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/components/avatar/AvatarDataProvider.kt
index 1727fffd1c..14c7ad3eff 100644
--- a/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/components/avatar/AvatarDataProvider.kt
+++ b/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/components/avatar/AvatarDataProvider.kt
@@ -20,19 +20,16 @@ import androidx.compose.ui.tooling.preview.PreviewParameterProvider
 
 open class AvatarDataProvider : PreviewParameterProvider {
     override val values: Sequence
-        get() {
-            AvatarSize.values()
-                .also { it.sortBy { item -> item.name } }
-                .asSequence()
-            return AvatarSize.values().asSequence().map {
+        get() = AvatarSize.values()
+            .asSequence()
+            .map {
                 sequenceOf(
                     anAvatarData(size = it),
                     anAvatarData(size = it).copy(name = null),
                     anAvatarData(size = it).copy(url = "aUrl"),
                 )
             }
-                .flatten()
-        }
+            .flatten()
 }
 
 fun anAvatarData(
diff --git a/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/components/button/ButtonVisuals.kt b/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/components/button/ButtonVisuals.kt
new file mode 100644
index 0000000000..24f3989f66
--- /dev/null
+++ b/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/components/button/ButtonVisuals.kt
@@ -0,0 +1,53 @@
+/*
+ * Copyright (c) 2023 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
+ *
+ *     http://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.designsystem.components.button
+
+import androidx.compose.material3.Icon
+import androidx.compose.runtime.Composable
+import io.element.android.libraries.designsystem.theme.components.Button
+import io.element.android.libraries.designsystem.theme.components.IconButton
+import io.element.android.libraries.designsystem.theme.components.IconSource
+import io.element.android.libraries.designsystem.theme.components.TextButton
+
+/**
+ * A sealed class that represents the different visual styles that a button can have.
+ */
+sealed interface ButtonVisuals {
+
+    val action: () -> Unit
+
+    /**
+     * Creates a [Button] composable based on the visual state.
+     */
+    @Composable
+    fun Composable()
+
+    data class Text(val text: String, override val action: () -> Unit) : ButtonVisuals {
+        @Composable
+        override fun Composable() {
+            TextButton(text = text, onClick = action)
+        }
+    }
+    data class Icon(val iconSource: IconSource, override val action: () -> Unit) : ButtonVisuals {
+        @Composable
+        override fun Composable() {
+            IconButton(onClick = action) {
+                Icon(iconSource.getPainter(), iconSource.contentDescription)
+            }
+        }
+    }
+}
diff --git a/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/components/button/ButtonWithProgress.kt b/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/components/button/ButtonWithProgress.kt
deleted file mode 100644
index 06702de253..0000000000
--- a/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/components/button/ButtonWithProgress.kt
+++ /dev/null
@@ -1,107 +0,0 @@
-/*
- * Copyright (c) 2023 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
- *
- *     http://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.designsystem.components.button
-
-import androidx.compose.foundation.BorderStroke
-import androidx.compose.foundation.interaction.MutableInteractionSource
-import androidx.compose.foundation.layout.PaddingValues
-import androidx.compose.foundation.layout.Spacer
-import androidx.compose.foundation.layout.size
-import androidx.compose.foundation.layout.width
-import androidx.compose.foundation.progressSemantics
-import androidx.compose.material3.ButtonColors
-import androidx.compose.material3.ButtonElevation
-import androidx.compose.material3.MaterialTheme
-import androidx.compose.runtime.Composable
-import androidx.compose.runtime.remember
-import androidx.compose.ui.Modifier
-import androidx.compose.ui.graphics.Shape
-import androidx.compose.ui.tooling.preview.Preview
-import androidx.compose.ui.unit.dp
-import io.element.android.libraries.designsystem.preview.ElementThemedPreview
-import io.element.android.libraries.designsystem.preview.PreviewGroup
-import io.element.android.libraries.designsystem.theme.aliasButtonText
-import io.element.android.libraries.designsystem.theme.components.Button
-import io.element.android.libraries.designsystem.theme.components.CircularProgressIndicator
-import io.element.android.libraries.designsystem.theme.components.ElementButtonDefaults
-import io.element.android.libraries.designsystem.theme.components.Text
-import io.element.android.libraries.theme.ElementTheme
-
-/**
- * A component that will display a button with an indeterminate circular progressbar.
- * When [showProgress] is true:
- *  - A circular progressbar is displayed.
- *  - [text] is replaced by [progressText], if defined.
- *  - [onClick] gets disabled.
- */
-@Composable
-fun ButtonWithProgress(
-    text: String?,
-    onClick: () -> Unit,
-    modifier: Modifier = Modifier,
-    showProgress: Boolean = false,
-    progressText: String? = text,
-    enabled: Boolean = true,
-    shape: Shape = ElementButtonDefaults.shape,
-    colors: ButtonColors = ElementButtonDefaults.buttonColors(),
-    elevation: ButtonElevation? = ElementButtonDefaults.buttonElevation(),
-    border: BorderStroke? = null,
-    contentPadding: PaddingValues = ElementButtonDefaults.ContentPadding,
-    interactionSource: MutableInteractionSource = remember { MutableInteractionSource() },
-) {
-    Button(
-        onClick = {
-            if (!showProgress) {
-                onClick()
-            }
-        },
-        modifier = modifier,
-        enabled = enabled,
-        shape = shape,
-        colors = colors,
-        elevation = elevation,
-        border = border,
-        contentPadding = contentPadding,
-        interactionSource = interactionSource,
-    ) {
-        if (showProgress) {
-            CircularProgressIndicator(
-                modifier = Modifier
-                    .progressSemantics()
-                    .size(18.dp),
-                color = MaterialTheme.colorScheme.onPrimary,
-                strokeWidth = 2.dp,
-            )
-            if (progressText != null) {
-                Spacer(Modifier.width(10.dp))
-                Text(progressText, style = ElementTheme.typography.aliasButtonText)
-            }
-        } else if (text != null) {
-            Text(text, style = ElementTheme.typography.aliasButtonText)
-        }
-    }
-}
-
-@Preview(group = PreviewGroup.Buttons)
-@Composable
-internal fun ButtonWithProgressPreview() = ElementThemedPreview {
-    ButtonWithProgress(
-        text = "Button with progress",
-        onClick = {},
-        showProgress = true,
-    )
-}
diff --git a/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/components/dialogs/ConfirmationDialog.kt b/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/components/dialogs/ConfirmationDialog.kt
index b11c9f878d..0c2fca84d5 100644
--- a/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/components/dialogs/ConfirmationDialog.kt
+++ b/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/components/dialogs/ConfirmationDialog.kt
@@ -17,20 +17,15 @@
 package io.element.android.libraries.designsystem.components.dialogs
 
 import androidx.compose.material3.AlertDialog
-import androidx.compose.material3.AlertDialogDefaults
 import androidx.compose.material3.ExperimentalMaterial3Api
-import androidx.compose.material3.MaterialTheme
 import androidx.compose.runtime.Composable
 import androidx.compose.ui.Modifier
-import androidx.compose.ui.graphics.Color
-import androidx.compose.ui.graphics.Shape
 import androidx.compose.ui.res.stringResource
 import androidx.compose.ui.tooling.preview.Preview
-import androidx.compose.ui.tooling.preview.PreviewParameter
-import androidx.compose.ui.unit.Dp
 import io.element.android.libraries.designsystem.preview.ElementThemedPreview
 import io.element.android.libraries.designsystem.preview.PreviewGroup
-import io.element.android.libraries.designsystem.utils.BooleanProvider
+import io.element.android.libraries.designsystem.theme.components.DialogPreview
+import io.element.android.libraries.designsystem.theme.components.SimpleAlertDialogContent
 import io.element.android.libraries.ui.strings.CommonStrings
 
 @OptIn(ExperimentalMaterial3Api::class)
@@ -44,16 +39,8 @@ fun ConfirmationDialog(
     submitText: String = stringResource(id = CommonStrings.action_ok),
     cancelText: String = stringResource(id = CommonStrings.action_cancel),
     thirdButtonText: String? = null,
-    emphasizeSubmitButton: Boolean = false,
     onCancelClicked: () -> Unit = onDismiss,
     onThirdButtonClicked: () -> Unit = {},
-    shape: Shape = AlertDialogDefaults.shape,
-    containerColor: Color = AlertDialogDefaults.containerColor,
-    iconContentColor: Color = AlertDialogDefaults.iconContentColor,
-    // According to the design team, `primary` should be used here instead of the default `onSurface`
-    titleContentColor: Color = MaterialTheme.colorScheme.primary,
-    textContentColor: Color = AlertDialogDefaults.textContentColor,
-    tonalElevation: Dp = AlertDialogDefaults.TonalElevation,
 ) {
     AlertDialog(modifier = modifier, onDismissRequest = onDismiss) {
         ConfirmationDialogContent(
@@ -65,13 +52,6 @@ fun ConfirmationDialog(
             onSubmitClicked = onSubmitClicked,
             onCancelClicked = onCancelClicked,
             onThirdButtonClicked = onThirdButtonClicked,
-            shape = shape,
-            containerColor = containerColor,
-            iconContentColor = iconContentColor,
-            titleContentColor = titleContentColor,
-            textContentColor = textContentColor,
-            tonalElevation = tonalElevation,
-            emphasizeSubmitButton = emphasizeSubmitButton,
         )
     }
 }
@@ -87,13 +67,6 @@ private fun ConfirmationDialogContent(
     title: String? = null,
     thirdButtonText: String? = null,
     onThirdButtonClicked: () -> Unit = {},
-    emphasizeSubmitButton: Boolean = false,
-    shape: Shape = AlertDialogDefaults.shape,
-    containerColor: Color = AlertDialogDefaults.containerColor,
-    iconContentColor: Color = AlertDialogDefaults.iconContentColor,
-    titleContentColor: Color = AlertDialogDefaults.titleContentColor,
-    textContentColor: Color = AlertDialogDefaults.textContentColor,
-    tonalElevation: Dp = AlertDialogDefaults.TonalElevation,
     icon: @Composable (() -> Unit)? = null,
 ) {
     SimpleAlertDialogContent(
@@ -106,21 +79,14 @@ private fun ConfirmationDialogContent(
         onCancelClicked = onCancelClicked,
         thirdButtonText = thirdButtonText,
         onThirdButtonClicked = onThirdButtonClicked,
-        emphasizeSubmitButton = emphasizeSubmitButton,
-        shape = shape,
-        containerColor = containerColor,
-        iconContentColor = iconContentColor,
-        titleContentColor = titleContentColor,
-        textContentColor = textContentColor,
-        tonalElevation = tonalElevation,
         icon = icon,
     )
 }
 
 @Preview(group = PreviewGroup.Dialogs)
 @Composable
-internal fun ConfirmationDialogPreview(@PreviewParameter(BooleanProvider::class) emphasizeSubmitButton: Boolean) =
-    ElementThemedPreview {
+internal fun ConfirmationDialogPreview() =
+    ElementThemedPreview(showBackground = false) {
         DialogPreview {
             ConfirmationDialogContent(
                 content = "Content",
@@ -130,7 +96,7 @@ internal fun ConfirmationDialogPreview(@PreviewParameter(BooleanProvider::class)
                 thirdButtonText = "Disable",
                 onSubmitClicked = {},
                 onCancelClicked = {},
-                emphasizeSubmitButton = emphasizeSubmitButton,
+                onThirdButtonClicked = {},
             )
         }
     }
diff --git a/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/components/dialogs/ErrorDialog.kt b/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/components/dialogs/ErrorDialog.kt
index d69281b6e9..fb5c511bf4 100644
--- a/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/components/dialogs/ErrorDialog.kt
+++ b/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/components/dialogs/ErrorDialog.kt
@@ -17,17 +17,15 @@
 package io.element.android.libraries.designsystem.components.dialogs
 
 import androidx.compose.material3.AlertDialog
-import androidx.compose.material3.AlertDialogDefaults
 import androidx.compose.material3.ExperimentalMaterial3Api
 import androidx.compose.runtime.Composable
 import androidx.compose.ui.Modifier
-import androidx.compose.ui.graphics.Color
-import androidx.compose.ui.graphics.Shape
 import androidx.compose.ui.res.stringResource
 import androidx.compose.ui.tooling.preview.Preview
-import androidx.compose.ui.unit.Dp
 import io.element.android.libraries.designsystem.preview.ElementThemedPreview
 import io.element.android.libraries.designsystem.preview.PreviewGroup
+import io.element.android.libraries.designsystem.theme.components.DialogPreview
+import io.element.android.libraries.designsystem.theme.components.SimpleAlertDialogContent
 import io.element.android.libraries.ui.strings.CommonStrings
 
 @OptIn(ExperimentalMaterial3Api::class)
@@ -38,12 +36,6 @@ fun ErrorDialog(
     title: String = ErrorDialogDefaults.title,
     submitText: String = ErrorDialogDefaults.submitText,
     onDismiss: () -> Unit = {},
-    shape: Shape = AlertDialogDefaults.shape,
-    containerColor: Color = AlertDialogDefaults.containerColor,
-    iconContentColor: Color = AlertDialogDefaults.iconContentColor,
-    titleContentColor: Color = AlertDialogDefaults.titleContentColor,
-    textContentColor: Color = AlertDialogDefaults.textContentColor,
-    tonalElevation: Dp = AlertDialogDefaults.TonalElevation,
 ) {
     AlertDialog(modifier = modifier, onDismissRequest = onDismiss) {
         ErrorDialogContent(
@@ -51,12 +43,6 @@ fun ErrorDialog(
             content = content,
             submitText = submitText,
             onSubmitText = onDismiss,
-            shape = shape,
-            containerColor = containerColor,
-            iconContentColor = iconContentColor,
-            titleContentColor = titleContentColor,
-            textContentColor = textContentColor,
-            tonalElevation = tonalElevation,
         )
     }
 }
@@ -68,12 +54,6 @@ private fun ErrorDialogContent(
     title: String = ErrorDialogDefaults.title,
     submitText: String = ErrorDialogDefaults.submitText,
     onSubmitText: () -> Unit = {},
-    shape: Shape = AlertDialogDefaults.shape,
-    containerColor: Color = AlertDialogDefaults.containerColor,
-    iconContentColor: Color = AlertDialogDefaults.iconContentColor,
-    titleContentColor: Color = AlertDialogDefaults.titleContentColor,
-    textContentColor: Color = AlertDialogDefaults.textContentColor,
-    tonalElevation: Dp = AlertDialogDefaults.TonalElevation,
 ) {
     SimpleAlertDialogContent(
         modifier = modifier,
@@ -81,12 +61,6 @@ private fun ErrorDialogContent(
         content = content,
         cancelText = submitText,
         onCancelClicked = onSubmitText,
-        shape = shape,
-        containerColor = containerColor,
-        iconContentColor = iconContentColor,
-        titleContentColor = titleContentColor,
-        textContentColor = textContentColor,
-        tonalElevation = tonalElevation,
     )
 }
 
@@ -98,7 +72,7 @@ object ErrorDialogDefaults {
 @Preview(group = PreviewGroup.Dialogs)
 @Composable
 internal fun ErrorDialogPreview() {
-    ElementThemedPreview {
+    ElementThemedPreview(showBackground = false) {
         DialogPreview {
             ErrorDialogContent(
                 content = "Content",
diff --git a/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/components/dialogs/RetryDialog.kt b/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/components/dialogs/RetryDialog.kt
index 5e22779085..85447b940b 100644
--- a/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/components/dialogs/RetryDialog.kt
+++ b/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/components/dialogs/RetryDialog.kt
@@ -17,21 +17,18 @@
 package io.element.android.libraries.designsystem.components.dialogs
 
 import androidx.compose.material3.AlertDialog
-import androidx.compose.material3.AlertDialogDefaults
-import androidx.compose.material3.TextButton
+import androidx.compose.material3.ExperimentalMaterial3Api
 import androidx.compose.runtime.Composable
 import androidx.compose.ui.Modifier
-import androidx.compose.ui.graphics.Color
-import androidx.compose.ui.graphics.Shape
 import androidx.compose.ui.res.stringResource
 import androidx.compose.ui.tooling.preview.Preview
-import androidx.compose.ui.unit.Dp
 import io.element.android.libraries.designsystem.preview.ElementThemedPreview
 import io.element.android.libraries.designsystem.preview.PreviewGroup
-import io.element.android.libraries.designsystem.theme.components.Text
-import io.element.android.libraries.theme.ElementTheme
+import io.element.android.libraries.designsystem.theme.components.DialogPreview
+import io.element.android.libraries.designsystem.theme.components.SimpleAlertDialogContent
 import io.element.android.libraries.ui.strings.CommonStrings
 
+@OptIn(ExperimentalMaterial3Api::class)
 @Composable
 fun RetryDialog(
     content: String,
@@ -41,51 +38,17 @@ fun RetryDialog(
     dismissText: String = RetryDialogDefaults.dismissText,
     onRetry: () -> Unit = {},
     onDismiss: () -> Unit = {},
-    shape: Shape = AlertDialogDefaults.shape,
-    containerColor: Color = AlertDialogDefaults.containerColor,
-    iconContentColor: Color = AlertDialogDefaults.iconContentColor,
-    titleContentColor: Color = AlertDialogDefaults.titleContentColor,
-    textContentColor: Color = AlertDialogDefaults.textContentColor,
-    tonalElevation: Dp = AlertDialogDefaults.TonalElevation,
 ) {
-    AlertDialog(
-        modifier = modifier,
-        onDismissRequest = onDismiss,
-        title = {
-            Text(
-                text = title,
-                style = ElementTheme.typography.fontHeadingSmRegular,
-            )
-        },
-        text = {
-            Text(
-                text = content,
-                style = ElementTheme.typography.fontBodyMdRegular,
-            )
-        },
-        confirmButton = {
-            TextButton(onClick = onRetry) {
-                Text(
-                    text = retryText,
-                    style = ElementTheme.typography.fontBodyMdRegular,
-                )
-            }
-        },
-        dismissButton = {
-            TextButton(onClick = onDismiss) {
-                Text(
-                    text = dismissText,
-                    style = ElementTheme.typography.fontBodyMdRegular,
-                )
-            }
-        },
-        shape = shape,
-        containerColor = containerColor,
-        iconContentColor = iconContentColor,
-        titleContentColor = titleContentColor,
-        textContentColor = textContentColor,
-        tonalElevation = tonalElevation,
-    )
+    AlertDialog(modifier = modifier, onDismissRequest = onDismiss) {
+        RetryDialogContent(
+            title = title,
+            content = content,
+            retryText = retryText,
+            dismissText = dismissText,
+            onRetry = onRetry,
+            onDismiss = onDismiss,
+        )
+    }
 }
 
 @Composable
@@ -97,12 +60,6 @@ private fun RetryDialogContent(
     dismissText: String = RetryDialogDefaults.dismissText,
     onRetry: () -> Unit = {},
     onDismiss: () -> Unit = {},
-    shape: Shape = AlertDialogDefaults.shape,
-    containerColor: Color = AlertDialogDefaults.containerColor,
-    iconContentColor: Color = AlertDialogDefaults.iconContentColor,
-    titleContentColor: Color = AlertDialogDefaults.titleContentColor,
-    textContentColor: Color = AlertDialogDefaults.textContentColor,
-    tonalElevation: Dp = AlertDialogDefaults.TonalElevation,
 ) {
     SimpleAlertDialogContent(
         modifier = modifier,
@@ -112,12 +69,6 @@ private fun RetryDialogContent(
         onSubmitClicked = onRetry,
         cancelText = dismissText,
         onCancelClicked = onDismiss,
-        shape = shape,
-        containerColor = containerColor,
-        iconContentColor = iconContentColor,
-        titleContentColor = titleContentColor,
-        textContentColor = textContentColor,
-        tonalElevation = tonalElevation,
     )
 }
 
@@ -129,13 +80,12 @@ object RetryDialogDefaults {
 
 @Preview(group = PreviewGroup.Dialogs)
 @Composable
-internal fun RetryDialogPreview() = ElementThemedPreview { ContentToPreview() }
-
-@Composable
-private fun ContentToPreview() {
-    DialogPreview {
-        RetryDialogContent(
-            content = "Content",
-        )
+internal fun RetryDialogPreview() {
+    ElementThemedPreview(showBackground = false) {
+        DialogPreview {
+            RetryDialogContent(
+                content = "Content",
+            )
+        }
     }
 }
diff --git a/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/components/preferences/PreferenceSwitch.kt b/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/components/preferences/PreferenceSwitch.kt
index bbd3583688..b9a8d267f5 100644
--- a/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/components/preferences/PreferenceSwitch.kt
+++ b/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/components/preferences/PreferenceSwitch.kt
@@ -27,7 +27,6 @@ import androidx.compose.foundation.layout.padding
 import androidx.compose.foundation.layout.width
 import androidx.compose.material.icons.Icons
 import androidx.compose.material.icons.filled.Announcement
-import androidx.compose.material3.Switch
 import androidx.compose.runtime.Composable
 import androidx.compose.ui.Alignment
 import androidx.compose.ui.Modifier
@@ -37,6 +36,7 @@ import androidx.compose.ui.unit.dp
 import io.element.android.libraries.designsystem.components.preferences.components.PreferenceIcon
 import io.element.android.libraries.designsystem.preview.ElementThemedPreview
 import io.element.android.libraries.designsystem.preview.PreviewGroup
+import io.element.android.libraries.designsystem.theme.components.Switch
 import io.element.android.libraries.designsystem.theme.components.Text
 import io.element.android.libraries.designsystem.toEnabledColor
 import io.element.android.libraries.designsystem.toSecondaryEnabledColor
diff --git a/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/preview/DayNightPreviews.kt b/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/preview/DayNightPreviews.kt
index 201d6f7151..b91e6a1024 100644
--- a/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/preview/DayNightPreviews.kt
+++ b/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/preview/DayNightPreviews.kt
@@ -42,6 +42,13 @@ const val DAY_MODE_NAME = "D"
  *
  * NB: Content should be wrapped into [ElementPreview] to apply proper theming.
  */
-@Preview(name = DAY_MODE_NAME)
-@Preview(name = NIGHT_MODE_NAME, uiMode = Configuration.UI_MODE_NIGHT_YES)
+@Preview(
+    name = DAY_MODE_NAME,
+    fontScale = 1f,
+)
+@Preview(
+    name = NIGHT_MODE_NAME,
+    uiMode = Configuration.UI_MODE_NIGHT_YES,
+    fontScale = 1f,
+)
 annotation class DayNightPreviews
diff --git a/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/preview/PreviewGroup.kt b/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/preview/PreviewGroup.kt
index aaff9a49f9..b704d0a26e 100644
--- a/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/preview/PreviewGroup.kt
+++ b/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/preview/PreviewGroup.kt
@@ -30,6 +30,7 @@ object PreviewGroup {
     const val Preferences = "Preferences"
     const val Progress = "Progress Indicators"
     const val Search = "Search views"
+    const val Snackbars = "Snackbars"
     const val Sliders = "Sliders"
     const val Text = "Text"
     const val TextFields = "TextFields"
diff --git a/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/preview/SheetState.kt b/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/preview/SheetState.kt
new file mode 100644
index 0000000000..a83bc5708c
--- /dev/null
+++ b/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/preview/SheetState.kt
@@ -0,0 +1,27 @@
+/*
+ * Copyright (c) 2023 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
+ *
+ *     http://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.designsystem.preview
+
+import androidx.compose.material3.ExperimentalMaterial3Api
+import androidx.compose.material3.SheetState
+import androidx.compose.material3.SheetValue
+
+@OptIn(ExperimentalMaterial3Api::class)
+val sheetStateForPreview = SheetState(
+    skipPartiallyExpanded = true,
+    initialValue = SheetValue.Expanded,
+)
diff --git a/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/preview/WithFontScale.kt b/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/preview/WithFontScale.kt
new file mode 100644
index 0000000000..6d3ecfc82b
--- /dev/null
+++ b/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/preview/WithFontScale.kt
@@ -0,0 +1,38 @@
+/*
+ * Copyright (c) 2023 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
+ *
+ *     http://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.designsystem.preview
+
+import androidx.compose.runtime.Composable
+import androidx.compose.runtime.CompositionLocalProvider
+import androidx.compose.ui.platform.LocalDensity
+import androidx.compose.ui.unit.Density
+
+/**
+ * Showkase does not take into account the `fontScale` parameter of the Preview annotation, so alter the
+ * LocalDensity in the CompositionLocalProvider.
+ */
+@Composable
+fun WithFontScale(fontScale: Float, content: @Composable () -> Unit) {
+    CompositionLocalProvider(
+        LocalDensity provides Density(
+            density = LocalDensity.current.density,
+            fontScale = fontScale
+        )
+    ) {
+        content()
+    }
+}
diff --git a/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/ruler/WithRulers.kt b/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/ruler/WithRulers.kt
index a5fc895e5d..58c9a44709 100644
--- a/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/ruler/WithRulers.kt
+++ b/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/ruler/WithRulers.kt
@@ -24,8 +24,8 @@ import androidx.compose.ui.unit.Dp
 import androidx.compose.ui.unit.dp
 import io.element.android.libraries.designsystem.preview.ElementPreviewDark
 import io.element.android.libraries.designsystem.preview.ElementPreviewLight
+import io.element.android.libraries.designsystem.theme.components.ButtonSize
 import io.element.android.libraries.designsystem.theme.components.OutlinedButton
-import io.element.android.libraries.designsystem.theme.components.Text
 
 /**
  * Debug tool to add a vertical and a horizontal ruler on top of the content.
@@ -76,8 +76,10 @@ internal fun WithRulerDarkPreview() =
 @Composable
 private fun ContentToPreview() {
     WithRulers(xRulersOffset = 20.dp, yRulersOffset = 15.dp) {
-        OutlinedButton(onClick = {}) {
-            Text(text = "A Button with rulers on it!")
-        }
+        OutlinedButton(
+            text = "A Button with rulers on it!",
+            size = ButtonSize.Medium,
+            onClick = {},
+        )
     }
 }
diff --git a/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/text/DpScale.kt b/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/text/DpScale.kt
new file mode 100644
index 0000000000..c6408b662e
--- /dev/null
+++ b/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/text/DpScale.kt
@@ -0,0 +1,126 @@
+/*
+ * Copyright (c) 2023 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
+ *
+ *     http://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.designsystem.text
+
+import androidx.compose.foundation.layout.Arrangement
+import androidx.compose.foundation.layout.Column
+import androidx.compose.foundation.layout.padding
+import androidx.compose.runtime.Composable
+import androidx.compose.ui.Modifier
+import androidx.compose.ui.platform.LocalDensity
+import androidx.compose.ui.tooling.preview.Preview
+import androidx.compose.ui.unit.Dp
+import androidx.compose.ui.unit.dp
+import io.element.android.libraries.designsystem.preview.ElementPreviewLight
+import io.element.android.libraries.designsystem.preview.WithFontScale
+import io.element.android.libraries.designsystem.theme.components.Text
+import io.element.android.libraries.theme.ElementTheme
+
+/**
+ * Return the maximum value between the receiver value and the value with fontScale applied.
+ * So if fontScale is >= 1f, the same value is returned, and if fontScale is < 1f, so returned value
+ * will be smaller.
+ */
+@Composable
+fun Dp.applyScaleDown(): Dp = with(LocalDensity.current) {
+    return this@applyScaleDown * fontScale.coerceAtMost(1f)
+}
+
+/**
+ * Return the minimum value between the receiver value and the value with fontScale applied.
+ * So if fontScale is <= 1f, the same value is returned, and if fontScale is > 1f, so returned value
+ * will be bigger.
+ */
+@Composable
+fun Dp.applyScaleUp(): Dp = with(LocalDensity.current) {
+    return this@applyScaleUp * fontScale.coerceAtLeast(1f)
+}
+
+@Preview
+@Composable
+internal fun DpScalePreview_0_75f() = WithFontScale(0.75f) {
+    ElementPreviewLight {
+        val fontSizeInDp = 16.dp
+        Column(
+            modifier = Modifier.padding(4.dp),
+            verticalArrangement = Arrangement.spacedBy(6.dp)
+        ) {
+            Text(
+                text = "Text with size of 16.sp",
+                style = ElementTheme.typography.fontBodyLgRegular.copy(fontSize = fontSizeInDp.toSp())
+            )
+            Text(
+                text = "Text with the same size (applyScaleUp)",
+                style = ElementTheme.typography.fontBodyLgRegular.copy(fontSize = fontSizeInDp.applyScaleUp().toSp())
+            )
+            Text(
+                text = "Text with a smaller size (applyScaleDown)",
+                style = ElementTheme.typography.fontBodyLgRegular.copy(fontSize = fontSizeInDp.applyScaleDown().toSp())
+            )
+        }
+    }
+}
+
+@Preview
+@Composable
+internal fun DpScalePreview_1_0f() = WithFontScale(1f) {
+    ElementPreviewLight {
+        val fontSizeInDp = 16.dp
+        Column(
+            modifier = Modifier.padding(4.dp),
+            verticalArrangement = Arrangement.spacedBy(6.dp)
+        ) {
+            Text(
+                text = "Text with size of 16.sp",
+                style = ElementTheme.typography.fontBodyLgRegular.copy(fontSize = fontSizeInDp.toSp())
+            )
+            Text(
+                text = "Text with the same size (applyScaleUp)",
+                style = ElementTheme.typography.fontBodyLgRegular.copy(fontSize = fontSizeInDp.applyScaleUp().toSp())
+            )
+            Text(
+                text = "Text with the same size (applyScaleDown)",
+                style = ElementTheme.typography.fontBodyLgRegular.copy(fontSize = fontSizeInDp.applyScaleDown().toSp())
+            )
+        }
+    }
+}
+
+@Preview
+@Composable
+internal fun DpScalePreview_1_5f() = WithFontScale(1.5f) {
+    ElementPreviewLight {
+        val fontSizeInDp = 16.dp
+        Column(
+            modifier = Modifier.padding(4.dp),
+            verticalArrangement = Arrangement.spacedBy(6.dp)
+        ) {
+            Text(
+                text = "Text with size of 16.sp",
+                style = ElementTheme.typography.fontBodyLgRegular.copy(fontSize = fontSizeInDp.toSp())
+            )
+            Text(
+                text = "Text with a bigger size (applyScaleUp)",
+                style = ElementTheme.typography.fontBodyLgRegular.copy(fontSize = fontSizeInDp.applyScaleUp().toSp())
+            )
+            Text(
+                text = "Text with the same size (applyScaleDown)",
+                style = ElementTheme.typography.fontBodyLgRegular.copy(fontSize = fontSizeInDp.applyScaleDown().toSp())
+            )
+        }
+    }
+}
diff --git a/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/components/dialogs/AlertDialogContent.kt b/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/theme/components/AlertDialogContent.kt
similarity index 64%
rename from libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/components/dialogs/AlertDialogContent.kt
rename to libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/theme/components/AlertDialogContent.kt
index c1e8b0c055..a3c7274c45 100644
--- a/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/components/dialogs/AlertDialogContent.kt
+++ b/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/theme/components/AlertDialogContent.kt
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-package io.element.android.libraries.designsystem.components.dialogs
+package io.element.android.libraries.designsystem.theme.components
 
 import androidx.compose.foundation.layout.Arrangement
 import androidx.compose.foundation.layout.Box
@@ -22,26 +22,32 @@ import androidx.compose.foundation.layout.Column
 import androidx.compose.foundation.layout.PaddingValues
 import androidx.compose.foundation.layout.padding
 import androidx.compose.foundation.layout.sizeIn
-import androidx.compose.material3.AlertDialogDefaults
+import androidx.compose.foundation.shape.RoundedCornerShape
+import androidx.compose.material.icons.Icons
+import androidx.compose.material.icons.filled.Notifications
 import androidx.compose.material3.LocalContentColor
 import androidx.compose.material3.MaterialTheme
 import androidx.compose.material3.ProvideTextStyle
 import androidx.compose.material3.Surface
-import androidx.compose.material3.TextButton
 import androidx.compose.runtime.Composable
 import androidx.compose.runtime.CompositionLocalProvider
+import androidx.compose.runtime.ReadOnlyComposable
 import androidx.compose.ui.Alignment
 import androidx.compose.ui.Modifier
 import androidx.compose.ui.graphics.Color
 import androidx.compose.ui.graphics.Shape
 import androidx.compose.ui.layout.Layout
 import androidx.compose.ui.layout.Placeable
+import androidx.compose.ui.tooling.preview.Preview
 import androidx.compose.ui.unit.Dp
 import androidx.compose.ui.unit.dp
-import io.element.android.libraries.designsystem.theme.components.Text
+import io.element.android.libraries.designsystem.preview.ElementThemedPreview
+import io.element.android.libraries.designsystem.preview.PreviewGroup
 import io.element.android.libraries.theme.ElementTheme
 import kotlin.math.max
 
+// Figma designs: https://www.figma.com/file/G1xy0HDZKJf5TCRFmKb5d5/Compound-Android-Components?type=design&node-id=911%3A343492&mode=design&t=jeyd1bXKOOx8y10r-1
+
 @Composable
 internal fun SimpleAlertDialogContent(
     content: String,
@@ -53,13 +59,6 @@ internal fun SimpleAlertDialogContent(
     onSubmitClicked: () -> Unit = {},
     thirdButtonText: String? = null,
     onThirdButtonClicked: () -> Unit = {},
-    emphasizeSubmitButton: Boolean = false,
-    shape: Shape = AlertDialogDefaults.shape,
-    containerColor: Color = AlertDialogDefaults.containerColor,
-    iconContentColor: Color = AlertDialogDefaults.iconContentColor,
-    titleContentColor: Color = AlertDialogDefaults.titleContentColor,
-    textContentColor: Color = AlertDialogDefaults.textContentColor,
-    tonalElevation: Dp = AlertDialogDefaults.TonalElevation,
     icon: @Composable (() -> Unit)? = null,
 ) {
     AlertDialogContent(
@@ -71,54 +70,47 @@ internal fun SimpleAlertDialogContent(
                 if (thirdButtonText != null) {
                     // If there is a 3rd item it should be at the end of the dialog
                     // Having this 3rd action is discouraged, see https://m3.material.io/components/dialogs/guidelines#e13b68f5-e367-4275-ad6f-c552ee8e358f
-                    TextButton(onClick = onThirdButtonClicked) {
-                        Text(
-                            text = thirdButtonText,
-                            style = ElementTheme.typography.fontBodyMdRegular,
-                        )
-                    }
-                }
-                TextButton(onClick = onCancelClicked) {
-                    Text(
-                        text = cancelText,
-                        style = ElementTheme.typography.fontBodyMdRegular,
+                    TextButton(
+                        text = thirdButtonText,
+                        size = ButtonSize.Medium,
+                        onClick = onThirdButtonClicked,
                     )
                 }
+                TextButton(
+                    text = cancelText,
+                    size = ButtonSize.Medium,
+                    onClick = onCancelClicked,
+                )
                 if (submitText != null) {
-                    TextButton(onClick = onSubmitClicked) {
-                        Text(
-                            text = submitText,
-                            style = if (emphasizeSubmitButton) {
-                                ElementTheme.typography.fontBodyMdMedium
-                            } else {
-                                ElementTheme.typography.fontBodyMdRegular
-                            }
-                        )
-                    }
+                    Button(
+                        text = submitText,
+                        size = ButtonSize.Medium,
+                        onClick = onSubmitClicked,
+                    )
                 }
             }
         },
         modifier = modifier,
-        title = {
-            if (title != null) {
+        title = title?.let { titleText ->
+            @Composable {
                 Text(
-                    text = title,
-                    style = ElementTheme.typography.fontHeadingSmRegular,
+                    text = titleText,
+                    style = ElementTheme.typography.fontHeadingSmMedium,
                 )
             }
         },
         text = {
             Text(
                 text = content,
-                style = ElementTheme.typography.fontBodyMdRegular,
+                style = ElementTheme.materialTypography.bodyMedium,
             )
         },
-        shape = shape,
-        containerColor = containerColor,
-        iconContentColor = iconContentColor,
-        titleContentColor = titleContentColor,
-        textContentColor = textContentColor,
-        tonalElevation = tonalElevation,
+        shape = DialogContentDefaults.shape,
+        containerColor = DialogContentDefaults.containerColor,
+        iconContentColor = DialogContentDefaults.iconContentColor,
+        titleContentColor = DialogContentDefaults.titleContentColor,
+        textContentColor = DialogContentDefaults.textContentColor,
+        tonalElevation = 0.dp,
         icon = icon,
         // Note that a button content color is provided here from the dialog's token, but in
         // most cases, TextButtons should be used for dismiss and confirm buttons.
@@ -128,6 +120,9 @@ internal fun SimpleAlertDialogContent(
     )
 }
 
+/**
+ * Copy of M3's `AlertDialogContent` so we can use it for previews.
+ */
 @Composable
 internal fun AlertDialogContent(
     buttons: @Composable () -> Unit,
@@ -150,13 +145,13 @@ internal fun AlertDialogContent(
         tonalElevation = tonalElevation,
     ) {
         Column(
-            modifier = Modifier.padding(DialogPadding)
+            modifier = Modifier.padding(DialogContentDefaults.externalPadding)
         ) {
             icon?.let {
                 CompositionLocalProvider(LocalContentColor provides iconContentColor) {
                     Box(
                         Modifier
-                            .padding(IconPadding)
+                            .padding(DialogContentDefaults.iconPadding)
                             .align(Alignment.CenterHorizontally)
                     ) {
                         icon()
@@ -170,7 +165,7 @@ internal fun AlertDialogContent(
                         Box(
                             // Align the title to the center when an icon is present.
                             Modifier
-                                .padding(TitlePadding)
+                                .padding(DialogContentDefaults.titlePadding)
                                 .align(
                                     if (icon == null) {
                                         Alignment.Start
@@ -192,7 +187,7 @@ internal fun AlertDialogContent(
                         Box(
                             Modifier
                                 .weight(weight = 1f, fill = false)
-                                .padding(TextPadding)
+                                .padding(DialogContentDefaults.textPadding)
                                 .align(Alignment.Start)
                         ) {
                             text()
@@ -216,7 +211,7 @@ internal fun AlertDialogContent(
  * customization.
  */
 @Composable
-internal fun AlertDialogFlowRow(
+private fun AlertDialogFlowRow(
     mainAxisSpacing: Dp,
     crossAxisSpacing: Dp,
     content: @Composable () -> Unit
@@ -243,7 +238,8 @@ internal fun AlertDialogFlowRow(
             if (sequences.isNotEmpty()) {
                 crossAxisSpace += crossAxisSpacing.roundToPx()
             }
-            sequences += currentSequence.toList()
+            // Ensures that confirming actions appear above dismissive actions.
+            sequences.add(0, currentSequence.toList())
             crossAxisSizes += currentCrossAxisSize
             crossAxisPositions += crossAxisSpace
 
@@ -287,12 +283,11 @@ internal fun AlertDialogFlowRow(
                     placeables[j].width +
                         if (j < placeables.lastIndex) mainAxisSpacing.roundToPx() else 0
                 }
-                val arrangement = Arrangement.Bottom
-                // TODO(soboleva): rtl support
-                // Handle vertical direction
+                val arrangement = Arrangement.End
                 val mainAxisPositions = IntArray(childrenMainAxisSizes.size) { 0 }
                 with(arrangement) {
-                    arrange(mainAxisLayoutSize, childrenMainAxisSizes, mainAxisPositions)
+                    arrange(mainAxisLayoutSize, childrenMainAxisSizes,
+                        layoutDirection, mainAxisPositions)
                 }
                 placeables.forEachIndexed { j, placeable ->
                     placeable.place(
@@ -317,14 +312,87 @@ internal fun DialogPreview(content: @Composable () -> Unit) {
     }
 }
 
-// Paddings for each of the dialog's parts.
-private val DialogPadding = PaddingValues(all = 24.dp)
-private val IconPadding = PaddingValues(bottom = 16.dp)
-private val TitlePadding = PaddingValues(bottom = 16.dp)
-private val TextPadding = PaddingValues(bottom = 24.dp)
+internal object DialogContentDefaults {
+    val shape = RoundedCornerShape(12.dp)
+    val externalPadding = PaddingValues(all = 24.dp)
+    val titlePadding = PaddingValues(bottom = 16.dp)
+    val iconPadding = PaddingValues(bottom = 8.dp)
+    val textPadding = PaddingValues(bottom = 16.dp)
 
+    val containerColor: Color
+        @Composable
+        @ReadOnlyComposable
+        get()= ElementTheme.colors.bgCanvasDefault
+
+    val textContentColor: Color
+        @Composable
+        @ReadOnlyComposable
+        get()= ElementTheme.materialColors.onSurfaceVariant
+
+    val titleContentColor: Color
+        @Composable
+        @ReadOnlyComposable
+        get()= ElementTheme.materialColors.onSurface
+
+    val iconContentColor: Color
+        @Composable
+        @ReadOnlyComposable
+        get()= ElementTheme.materialColors.primary
+}
+
+// Paddings for each of the dialog's parts. Taken from M3 source code.
 internal val ButtonsMainAxisSpacing = 8.dp
 internal val ButtonsCrossAxisSpacing = 12.dp
 
 internal val DialogMinWidth = 280.dp
 internal val DialogMaxWidth = 560.dp
+
+@Preview(group = PreviewGroup.Dialogs, name = "Dialog with title, icon and ok button")
+@Composable
+@Suppress("MaxLineLength")
+internal fun DialogWithTitleIconAndOkButtonPreview() {
+    ElementThemedPreview(showBackground = false) {
+        DialogPreview {
+            SimpleAlertDialogContent(
+                icon = {
+                    Icon(imageVector = Icons.Default.Notifications, contentDescription = null)
+                },
+                title = "Dialog Title",
+                content = "A dialog is a type of modal window that appears in front of app content to provide critical information, or prompt for a decision to be made. Learn more",
+                cancelText = "OK",
+                onCancelClicked = {},
+            )
+        }
+    }
+}
+
+@Preview(group = PreviewGroup.Dialogs, name = "Dialog with title and ok button")
+@Composable
+@Suppress("MaxLineLength")
+internal fun DialogWithTitleAndOkButtonPreview() {
+    ElementThemedPreview(showBackground = false) {
+        DialogPreview {
+            SimpleAlertDialogContent(
+                title = "Dialog Title",
+                content = "A dialog is a type of modal window that appears in front of app content to provide critical information, or prompt for a decision to be made. Learn more",
+                cancelText = "OK",
+                onCancelClicked = {},
+            )
+        }
+    }
+}
+
+@Preview(group = PreviewGroup.Dialogs, name = "Dialog with only message and ok button")
+@Composable
+@Suppress("MaxLineLength")
+internal fun DialogWithOnlyMessageAndOkButtonPreview() {
+    ElementThemedPreview(showBackground = false) {
+        DialogPreview {
+            SimpleAlertDialogContent(
+                content = "A dialog is a type of modal window that appears in front of app content to provide critical information, or prompt for a decision to be made. Learn more",
+                cancelText = "OK",
+                onCancelClicked = {},
+            )
+        }
+    }
+}
diff --git a/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/theme/components/Button.kt b/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/theme/components/Button.kt
index 64c79a3906..8c5d96c400 100644
--- a/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/theme/components/Button.kt
+++ b/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/theme/components/Button.kt
@@ -18,68 +18,367 @@ package io.element.android.libraries.designsystem.theme.components
 
 import androidx.compose.foundation.BorderStroke
 import androidx.compose.foundation.interaction.MutableInteractionSource
+import androidx.compose.foundation.layout.Arrangement
 import androidx.compose.foundation.layout.Column
+import androidx.compose.foundation.layout.IntrinsicSize
 import androidx.compose.foundation.layout.PaddingValues
-import androidx.compose.foundation.layout.RowScope
+import androidx.compose.foundation.layout.Row
+import androidx.compose.foundation.layout.fillMaxWidth
+import androidx.compose.foundation.layout.heightIn
+import androidx.compose.foundation.layout.padding
+import androidx.compose.foundation.layout.size
+import androidx.compose.foundation.layout.width
+import androidx.compose.foundation.progressSemantics
+import androidx.compose.foundation.shape.RoundedCornerShape
+import androidx.compose.material.icons.Icons
+import androidx.compose.material.icons.outlined.Share
 import androidx.compose.material3.ButtonColors
 import androidx.compose.material3.ButtonDefaults
-import androidx.compose.material3.ButtonElevation
+import androidx.compose.material3.LocalContentColor
+import androidx.compose.material3.MaterialTheme
 import androidx.compose.runtime.Composable
 import androidx.compose.runtime.remember
+import androidx.compose.ui.Alignment
 import androidx.compose.ui.Modifier
-import androidx.compose.ui.graphics.Shape
+import androidx.compose.ui.graphics.Color
+import androidx.compose.ui.graphics.RectangleShape
+import androidx.compose.ui.graphics.isSpecified
+import androidx.compose.ui.graphics.painter.Painter
+import androidx.compose.ui.graphics.vector.ImageVector
+import androidx.compose.ui.graphics.vector.rememberVectorPainter
+import androidx.compose.ui.res.painterResource
+import androidx.compose.ui.text.style.TextOverflow
 import androidx.compose.ui.tooling.preview.Preview
 import androidx.compose.ui.unit.dp
 import io.element.android.libraries.designsystem.preview.ElementThemedPreview
 import io.element.android.libraries.designsystem.preview.PreviewGroup
+import io.element.android.libraries.theme.ElementTheme
+
+// Designs: https://www.figma.com/file/G1xy0HDZKJf5TCRFmKb5d5/Compound-Android-Components?type=design&mode=design&t=U03tOFZz5FSLVUMa-1
 
 @Composable
 fun Button(
+    text: String,
     onClick: () -> Unit,
     modifier: Modifier = Modifier,
     enabled: Boolean = true,
-    shape: Shape = ElementButtonDefaults.shape,
-    colors: ButtonColors = ElementButtonDefaults.buttonColors(),
-    elevation: ButtonElevation? = ElementButtonDefaults.buttonElevation(),
-    border: BorderStroke? = null,
-    contentPadding: PaddingValues = ElementButtonDefaults.ContentPadding,
-    interactionSource: MutableInteractionSource = remember { MutableInteractionSource() },
-    content: @Composable RowScope.() -> Unit
+    size: ButtonSize = ButtonSize.Large,
+    showProgress: Boolean = false,
+    leadingIcon: IconSource? = null,
+) = ButtonInternal(
+    text = text,
+    onClick = onClick,
+    style = ButtonStyle.Filled,
+    modifier = modifier,
+    enabled = enabled,
+    size = size,
+    showProgress = showProgress,
+    leadingIcon = leadingIcon
+)
+
+@Composable
+fun OutlinedButton(
+    text: String,
+    onClick: () -> Unit,
+    modifier: Modifier = Modifier,
+    enabled: Boolean = true,
+    size: ButtonSize = ButtonSize.Large,
+    showProgress: Boolean = false,
+    leadingIcon: IconSource? = null,
+) = ButtonInternal(
+    text = text,
+    onClick = onClick,
+    style = ButtonStyle.Outlined,
+    modifier = modifier,
+    enabled = enabled,
+    size = size,
+    showProgress = showProgress,
+    leadingIcon = leadingIcon
+)
+
+@Composable
+fun TextButton(
+    text: String,
+    onClick: () -> Unit,
+    modifier: Modifier = Modifier,
+    enabled: Boolean = true,
+    size: ButtonSize = ButtonSize.Large,
+    showProgress: Boolean = false,
+    leadingIcon: IconSource? = null,
+) = ButtonInternal(
+    text = text,
+    onClick = onClick,
+    style = ButtonStyle.Text,
+    modifier = modifier,
+    enabled = enabled,
+    size = size,
+    showProgress = showProgress,
+    leadingIcon = leadingIcon
+)
+
+@Composable
+internal fun ButtonInternal(
+    text: String,
+    onClick: () -> Unit,
+    style: ButtonStyle,
+    modifier: Modifier = Modifier,
+    colors: ButtonColors = style.getColors(),
+    enabled: Boolean = true,
+    size: ButtonSize = ButtonSize.Large,
+    showProgress: Boolean = false,
+    leadingIcon: IconSource? = null,
 ) {
+    val minHeight = when (size) {
+        ButtonSize.Medium -> 40.dp
+        ButtonSize.Large -> 48.dp
+    }
+
+    val contentPadding = when (size) {
+        ButtonSize.Medium -> {
+            when (style) {
+                ButtonStyle.Text -> PaddingValues(horizontal = 12.dp, vertical = 10.dp)
+                else -> PaddingValues(horizontal = 16.dp, vertical = 10.dp)
+            }
+        }
+        ButtonSize.Large -> {
+            when (style) {
+                ButtonStyle.Text -> PaddingValues(horizontal = 16.dp, vertical = 13.dp)
+                else -> PaddingValues(horizontal = 24.dp, vertical = 13.dp)
+            }
+        }
+    }
+
+    val shape = when (style) {
+        ButtonStyle.Filled, ButtonStyle.Outlined -> RoundedCornerShape(percent = 50)
+        ButtonStyle.Text -> RectangleShape
+    }
+
+    val border = when (style) {
+        ButtonStyle.Filled, ButtonStyle.Text -> null
+        ButtonStyle.Outlined -> BorderStroke(
+            width = 1.dp,
+            color = ElementTheme.colors.borderInteractiveSecondary
+        )
+    }
+
+    val textStyle = when (size) {
+        ButtonSize.Medium -> MaterialTheme.typography.labelLarge
+        ButtonSize.Large -> ElementTheme.typography.fontBodyLgMedium
+    }
+
+    val internalPadding = when {
+        style == ButtonStyle.Text -> if (leadingIcon != null) PaddingValues(start = 8.dp) else PaddingValues(0.dp)
+        else -> PaddingValues(horizontal = 8.dp)
+    }
+
     androidx.compose.material3.Button(
-        onClick = onClick,
-        modifier = modifier,
+        onClick = {
+            if (!showProgress) {
+                onClick()
+            }
+        },
+        modifier = modifier.heightIn(min = minHeight),
         enabled = enabled,
         shape = shape,
         colors = colors,
-        elevation = elevation,
+        elevation = null,
         border = border,
         contentPadding = contentPadding,
-        interactionSource = interactionSource,
-        content = content,
-    )
+        interactionSource = remember { MutableInteractionSource() },
+    ) {
+        when {
+            showProgress -> {
+                CircularProgressIndicator(
+                    modifier = Modifier
+                        .progressSemantics()
+                        .size(20.dp),
+                    color = LocalContentColor.current,
+                    strokeWidth = 2.dp,
+                )
+            }
+            leadingIcon != null -> {
+                androidx.compose.material.Icon(
+                    painter = leadingIcon.getPainter(),
+                    contentDescription = null,
+                    tint = LocalContentColor.current,
+                    modifier = Modifier.size(20.dp),
+                )
+            }
+            else -> Unit
+        }
+        Text(
+            text = text,
+            style = textStyle,
+            maxLines = 1,
+            overflow = TextOverflow.Ellipsis,
+            modifier = Modifier.padding(internalPadding),
+        )
+    }
 }
 
-object ElementButtonDefaults {
-    val ContentPadding = PaddingValues(horizontal = 24.dp, vertical = 14.dp)
-    val shape: Shape @Composable get() = ButtonDefaults.shape
-    @Composable
-    fun buttonElevation(): ButtonElevation = ButtonDefaults.buttonElevation()
+sealed interface IconSource {
+    val contentDescription: String?
+
+    data class Resource(val id: Int, override val contentDescription: String? = null) : IconSource
+    data class Vector(val vector: ImageVector, override val contentDescription: String? = null) : IconSource
 
     @Composable
-    fun buttonColors(): ButtonColors = ButtonDefaults.buttonColors()
+    fun getPainter(): Painter = when (this) {
+        is Resource -> painterResource(id)
+        is Vector -> rememberVectorPainter(image = vector)
+    }
+}
 
+enum class ButtonSize {
+    Medium, Large
+}
+
+internal enum class ButtonStyle {
+    Filled, Outlined, Text;
+
+    @Composable
+    fun getColors(): ButtonColors = when (this) {
+        Filled -> ButtonDefaults.buttonColors(
+            containerColor = ElementTheme.materialColors.primary,
+            contentColor = ElementTheme.materialColors.onPrimary,
+            disabledContainerColor = ElementTheme.colors.bgActionPrimaryDisabled,
+            disabledContentColor = ElementTheme.colors.textOnSolidPrimary
+        )
+        Outlined -> ButtonDefaults.buttonColors(
+            containerColor = Color.Transparent,
+            contentColor = ElementTheme.materialColors.primary,
+            disabledContainerColor = Color.Transparent,
+            disabledContentColor = ElementTheme.colors.textDisabled,
+        )
+        Text -> ButtonDefaults.buttonColors(
+            containerColor = Color.Transparent,
+            contentColor = if (LocalContentColor.current.isSpecified) LocalContentColor.current else ElementTheme.materialColors.primary,
+            disabledContainerColor = Color.Transparent,
+            disabledContentColor = ElementTheme.colors.textDisabled,
+        )
+    }
 }
 
 @Preview(group = PreviewGroup.Buttons)
 @Composable
-internal fun ButtonPreview() = ElementThemedPreview {
-    Column {
-        Button(onClick = {}, enabled = true) {
-            Text(text = "Click me! - Enabled")
-        }
-        Button(onClick = {}, enabled = false) {
-            Text(text = "Click me! - Disabled")
+internal fun FilledButtonMediumPreview() {
+    ButtonCombinationPreview(
+        style = ButtonStyle.Filled,
+        size = ButtonSize.Medium,
+    )
+}
+
+@Preview(group = PreviewGroup.Buttons)
+@Composable
+internal fun FilledButtonLargePreview() {
+    ButtonCombinationPreview(
+        style = ButtonStyle.Filled,
+        size = ButtonSize.Large,
+    )
+}
+
+@Preview(group = PreviewGroup.Buttons)
+@Composable
+internal fun OutlinedButtonMediumPreview() {
+    ButtonCombinationPreview(
+        style = ButtonStyle.Outlined,
+        size = ButtonSize.Medium,
+    )
+}
+
+@Preview(group = PreviewGroup.Buttons)
+@Composable
+internal fun OutlinedButtonLargePreview() {
+    ButtonCombinationPreview(
+        style = ButtonStyle.Outlined,
+        size = ButtonSize.Large,
+    )
+}
+
+@Preview(group = PreviewGroup.Buttons)
+@Composable
+internal fun TextButtonMediumPreview() {
+    ButtonCombinationPreview(
+        style = ButtonStyle.Text,
+        size = ButtonSize.Medium,
+    )
+}
+
+@Preview(group = PreviewGroup.Buttons)
+@Composable
+internal fun TextButtonLargePreview() {
+    ButtonCombinationPreview(
+        style = ButtonStyle.Text,
+        size = ButtonSize.Large,
+    )
+}
+
+@Composable
+private fun ButtonCombinationPreview(
+    style: ButtonStyle,
+    size: ButtonSize,
+    modifier: Modifier = Modifier,
+) {
+    ElementThemedPreview {
+        Column(
+            verticalArrangement = Arrangement.spacedBy(8.dp),
+            modifier = Modifier
+                .padding(16.dp)
+                .width(IntrinsicSize.Max),
+        ) {
+            // Normal
+            ButtonRowPreview(
+                modifier = Modifier.then(modifier),
+                style = style,
+                size = size,
+            )
+
+            // With icon
+            ButtonRowPreview(
+                modifier = Modifier.then(modifier),
+                leadingIcon = IconSource.Vector(Icons.Outlined.Share),
+                style = style,
+                size = size,
+            )
+
+            // With progress
+            ButtonRowPreview(
+                modifier = Modifier.then(modifier),
+                showProgress = true,
+                style = style,
+                size = size,
+            )
         }
     }
 }
+
+@Composable
+private fun ButtonRowPreview(
+    style: ButtonStyle,
+    size: ButtonSize,
+    modifier: Modifier = Modifier,
+    leadingIcon: IconSource? = null,
+    showProgress: Boolean = false,
+) {
+    Row(modifier = Modifier.fillMaxWidth(), horizontalArrangement = Arrangement.spacedBy(8.dp, Alignment.CenterHorizontally)) {
+        ButtonInternal(
+            text = "A button",
+            showProgress = showProgress,
+            onClick = {},
+            style = style,
+            size = size,
+            leadingIcon = leadingIcon,
+            modifier = Modifier.then(modifier),
+        )
+        ButtonInternal(
+            text = "A button",
+            showProgress = showProgress,
+            enabled = false,
+            onClick = {},
+            style = style,
+            size = size,
+            leadingIcon = leadingIcon,
+            modifier = Modifier.then(modifier),
+        )
+    }
+}
diff --git a/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/theme/components/Checkbox.kt b/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/theme/components/Checkbox.kt
index b754b3d420..31c6cc3647 100644
--- a/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/theme/components/Checkbox.kt
+++ b/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/theme/components/Checkbox.kt
@@ -17,15 +17,25 @@
 package io.element.android.libraries.designsystem.theme.components
 
 import androidx.compose.foundation.interaction.MutableInteractionSource
+import androidx.compose.foundation.layout.Arrangement
 import androidx.compose.foundation.layout.Column
+import androidx.compose.foundation.layout.Row
 import androidx.compose.material3.CheckboxColors
 import androidx.compose.material3.CheckboxDefaults
 import androidx.compose.runtime.Composable
+import androidx.compose.runtime.getValue
+import androidx.compose.runtime.mutableStateOf
 import androidx.compose.runtime.remember
+import androidx.compose.runtime.setValue
 import androidx.compose.ui.Modifier
+import androidx.compose.ui.state.ToggleableState
 import androidx.compose.ui.tooling.preview.Preview
+import androidx.compose.ui.unit.dp
 import io.element.android.libraries.designsystem.preview.ElementThemedPreview
 import io.element.android.libraries.designsystem.preview.PreviewGroup
+import io.element.android.libraries.theme.ElementTheme
+
+// Designs in https://www.figma.com/file/G1xy0HDZKJf5TCRFmKb5d5/Compound-Android-Components?type=design&mode=design&t=qb99xBP5mwwCtGkN-1
 
 @Composable
 fun Checkbox(
@@ -33,12 +43,20 @@ fun Checkbox(
     onCheckedChange: ((Boolean) -> Unit)?,
     modifier: Modifier = Modifier,
     enabled: Boolean = true,
-    colors: CheckboxColors = CheckboxDefaults.colors(),
+    hasError: Boolean = false,
+    indeterminate: Boolean = false,
+    colors: CheckboxColors = if (hasError) compoundErrorCheckBoxColors() else compoundCheckBoxColors(),
     interactionSource: MutableInteractionSource = remember { MutableInteractionSource() }
 ) {
-    androidx.compose.material3.Checkbox(
-        checked = checked,
-        onCheckedChange = onCheckedChange,
+    var indeterminateState by remember { mutableStateOf(indeterminate) }
+    androidx.compose.material3.TriStateCheckbox(
+        state = if (!checked && indeterminateState) ToggleableState.Indeterminate else ToggleableState(checked),
+        onClick = onCheckedChange?.let {
+            {
+                indeterminateState = false
+                onCheckedChange(!checked)
+            }
+        },
         modifier = modifier,
         enabled = enabled,
         colors = colors,
@@ -46,6 +64,30 @@ fun Checkbox(
     )
 }
 
+@Composable
+private fun compoundCheckBoxColors(): CheckboxColors {
+    return CheckboxDefaults.colors(
+        checkedColor = ElementTheme.materialColors.primary,
+        uncheckedColor = ElementTheme.colors.borderInteractivePrimary,
+        checkmarkColor = ElementTheme.materialColors.onPrimary,
+        disabledUncheckedColor = ElementTheme.colors.borderDisabled,
+        disabledCheckedColor = ElementTheme.colors.iconDisabled,
+        disabledIndeterminateColor = ElementTheme.colors.iconDisabled,
+    )
+}
+
+@Composable
+private fun compoundErrorCheckBoxColors(): CheckboxColors {
+    return CheckboxDefaults.colors(
+        checkedColor = ElementTheme.materialColors.error,
+        uncheckedColor = ElementTheme.materialColors.error,
+        checkmarkColor = ElementTheme.materialColors.onPrimary,
+        disabledUncheckedColor = ElementTheme.colors.borderDisabled,
+        disabledCheckedColor = ElementTheme.colors.iconDisabled,
+        disabledIndeterminateColor = ElementTheme.colors.iconDisabled,
+    )
+}
+
 @Preview(group = PreviewGroup.Toggles)
 @Composable
 internal fun CheckboxesPreview() = ElementThemedPreview(vertical = false) { ContentToPreview() }
@@ -53,9 +95,33 @@ internal fun CheckboxesPreview() = ElementThemedPreview(vertical = false) { Cont
 @Composable
 private fun ContentToPreview() {
     Column {
-        Checkbox(onCheckedChange = {}, enabled = true, checked = true)
-        Checkbox(onCheckedChange = {}, enabled = true, checked = false)
-        Checkbox(onCheckedChange = {}, enabled = false, checked = true)
-        Checkbox(onCheckedChange = {}, enabled = false, checked = false)
+        // Unchecked
+        Row(horizontalArrangement = Arrangement.spacedBy(6.dp)) {
+            Checkbox(onCheckedChange = {}, enabled = true, checked = false)
+            Checkbox(onCheckedChange = {}, enabled = false, checked = false)
+        }
+        // Checked
+        Row(horizontalArrangement = Arrangement.spacedBy(6.dp)) {
+            Checkbox(onCheckedChange = {}, enabled = true, checked = true)
+            Checkbox(onCheckedChange = {}, enabled = false, checked = true)
+        }
+        // Indeterminate
+        Row(horizontalArrangement = Arrangement.spacedBy(6.dp)) {
+            Checkbox(onCheckedChange = {}, enabled = true, checked = false, indeterminate = true)
+            Checkbox(onCheckedChange = {}, enabled = false, checked = false, indeterminate = true)
+        }
+        // Error
+        Row(horizontalArrangement = Arrangement.spacedBy(6.dp)) {
+            Checkbox(hasError = true, onCheckedChange = {}, checked = false)
+            Checkbox(hasError = true, onCheckedChange = {}, enabled = false, checked = false)
+        }
+        Row(horizontalArrangement = Arrangement.spacedBy(6.dp)) {
+            Checkbox(hasError = true, onCheckedChange = {}, enabled = true, checked = true)
+            Checkbox(hasError = true, onCheckedChange = {}, enabled = false, checked = true)
+        }
+        Row(horizontalArrangement = Arrangement.spacedBy(6.dp)) {
+            Checkbox(onCheckedChange = {}, enabled = true, checked = false, indeterminate = true, hasError = true)
+            Checkbox(onCheckedChange = {}, enabled = false, checked = false, indeterminate = true, hasError = true)
+        }
     }
 }
diff --git a/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/theme/components/DropdownMenu.kt b/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/theme/components/DropdownMenu.kt
index 175c0fb402..c0160bb7f8 100644
--- a/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/theme/components/DropdownMenu.kt
+++ b/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/theme/components/DropdownMenu.kt
@@ -26,7 +26,7 @@ import androidx.compose.ui.unit.dp
 import androidx.compose.ui.window.PopupProperties
 import io.element.android.libraries.theme.ElementTheme
 
-private val minMenuWidth = 200.dp
+// Figma designs: https://www.figma.com/file/G1xy0HDZKJf5TCRFmKb5d5/Compound-Android-Components?type=design&node-id=1032%3A44063&mode=design&t=rsNegTbEVLYAXL76-1
 
 @Composable
 fun DropdownMenu(
@@ -38,19 +38,17 @@ fun DropdownMenu(
     properties: PopupProperties = PopupProperties(focusable = true),
     content: @Composable ColumnScope.() -> Unit
 ) {
-    val bgColor = if (ElementTheme.isLightTheme) {
-        ElementTheme.materialColors.background
-    } else {
-        ElementTheme.colors.bgSubtlePrimary
-    }
+    // Note: the internal shape corner radius should be 8dp, but there is a 4p value hardcoded in the internal Surface component
     androidx.compose.material3.DropdownMenu(
         expanded = expanded,
         onDismissRequest = onDismissRequest,
         modifier = modifier
-            .background(color = bgColor)
+            .background(color = ElementTheme.colors.bgCanvasDefault)
             .widthIn(min = minMenuWidth),
         offset = offset,
         properties = properties,
         content = content
     )
 }
+
+private val minMenuWidth = 200.dp
diff --git a/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/theme/components/DropdownMenuItem.kt b/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/theme/components/DropdownMenuItem.kt
index b8c18f99c6..f8e0fc2b78 100644
--- a/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/theme/components/DropdownMenuItem.kt
+++ b/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/theme/components/DropdownMenuItem.kt
@@ -17,20 +17,26 @@
 package io.element.android.libraries.designsystem.theme.components
 
 import androidx.compose.foundation.interaction.MutableInteractionSource
+import androidx.compose.foundation.layout.Column
 import androidx.compose.foundation.layout.PaddingValues
 import androidx.compose.material.icons.Icons
+import androidx.compose.material.icons.filled.ArrowRight
 import androidx.compose.material.icons.filled.BugReport
-import androidx.compose.material.icons.filled.Share
+import androidx.compose.material3.LocalTextStyle
+import androidx.compose.material3.MaterialTheme
 import androidx.compose.material3.MenuDefaults
-import androidx.compose.material3.MenuItemColors
 import androidx.compose.runtime.Composable
+import androidx.compose.runtime.CompositionLocalProvider
 import androidx.compose.runtime.remember
 import androidx.compose.ui.Modifier
 import androidx.compose.ui.tooling.preview.Preview
+import androidx.compose.ui.unit.dp
 import io.element.android.libraries.designsystem.preview.ElementThemedPreview
 import io.element.android.libraries.designsystem.preview.PreviewGroup
 import io.element.android.libraries.theme.ElementTheme
 
+// Figma designs: https://www.figma.com/file/G1xy0HDZKJf5TCRFmKb5d5/Compound-Android-Components?type=design&node-id=1032%3A44063&mode=design&t=rsNegTbEVLYAXL76-1
+
 @Composable
 fun DropdownMenuItem(
     text: @Composable () -> Unit,
@@ -39,34 +45,37 @@ fun DropdownMenuItem(
     leadingIcon: @Composable (() -> Unit)? = null,
     trailingIcon: @Composable (() -> Unit)? = null,
     enabled: Boolean = true,
-    colors: MenuItemColors = MenuDefaults.itemColors(),
-    contentPadding: PaddingValues = MenuDefaults.DropdownMenuItemContentPadding,
     interactionSource: MutableInteractionSource = remember { MutableInteractionSource() },
 ) {
     androidx.compose.material3.DropdownMenuItem(
-        text = text,
+        text = {
+            CompositionLocalProvider(LocalTextStyle provides MaterialTheme.typography.bodyLarge) {
+                text()
+            }
+        },
         onClick = onClick,
         modifier = modifier,
         leadingIcon = leadingIcon,
         trailingIcon = trailingIcon,
         enabled = enabled,
-        colors = colors,
-        contentPadding = contentPadding,
+        colors = DropDownMenuItemDefaults.colors(),
+        contentPadding = DropDownMenuItemDefaults.contentPadding,
         interactionSource = interactionSource
     )
 }
 
-@Composable
-fun DropdownMenuItemText(
-    text: String,
-    modifier: Modifier = Modifier,
-) {
-    Text(
-        text = text,
-        color = ElementTheme.materialColors.primary,
-        style = ElementTheme.typography.fontBodyLgRegular,
-        modifier = modifier,
+internal object DropDownMenuItemDefaults {
+    @Composable
+    fun colors() = MenuDefaults.itemColors(
+        textColor = ElementTheme.colors.textPrimary,
+        leadingIconColor = ElementTheme.colors.iconPrimary,
+        trailingIconColor = ElementTheme.colors.iconSecondary,
+        disabledTextColor = ElementTheme.colors.textDisabled,
+        disabledLeadingIconColor = ElementTheme.colors.iconDisabled,
+        disabledTrailingIconColor = ElementTheme.colors.iconDisabled,
     )
+
+    val contentPadding = PaddingValues(all = 12.dp)
 }
 
 @Preview(group = PreviewGroup.Menus)
@@ -75,10 +84,36 @@ internal fun DropdownMenuItemPreview() = ElementThemedPreview { ContentToPreview
 
 @Composable
 private fun ContentToPreview() {
-    DropdownMenuItem(
-        text = { DropdownMenuItemText(text = "Item") },
-        onClick = {},
-        leadingIcon = { Icon(Icons.Default.BugReport, contentDescription = null) },
-        trailingIcon = { Icon(Icons.Default.Share, contentDescription = null) },
-    )
+    Column {
+        DropdownMenuItem(
+            text = { Text(text = "Item") },
+            onClick = {},
+            trailingIcon = { Icon(Icons.Default.ArrowRight, contentDescription = null) },
+        )
+        Divider()
+        DropdownMenuItem(
+            text = { Text(text = "Item") },
+            onClick = {},
+            leadingIcon = { Icon(Icons.Default.BugReport, contentDescription = null) },
+        )
+        DropdownMenuItem(
+            text = { Text(text = "Item") },
+            onClick = {},
+            leadingIcon = { Icon(Icons.Default.BugReport, contentDescription = null) },
+            trailingIcon = { Icon(Icons.Default.ArrowRight, contentDescription = null) },
+        )
+        DropdownMenuItem(
+            text = { Text(text = "Item") },
+            onClick = {},
+            enabled = false,
+            leadingIcon = { Icon(Icons.Default.BugReport, contentDescription = null) },
+            trailingIcon = { Icon(Icons.Default.ArrowRight, contentDescription = null) },
+        )
+        Divider()
+        DropdownMenuItem(
+            text = { Text(text = "Multiline\nItem") },
+            onClick = {},
+            trailingIcon = { Icon(Icons.Default.ArrowRight, contentDescription = null) },
+        )
+    }
 }
diff --git a/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/theme/components/IconButton.kt b/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/theme/components/IconButton.kt
index 14cc6b62ce..7063ab1eb1 100644
--- a/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/theme/components/IconButton.kt
+++ b/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/theme/components/IconButton.kt
@@ -17,16 +17,22 @@
 package io.element.android.libraries.designsystem.theme.components
 
 import androidx.compose.foundation.interaction.MutableInteractionSource
+import androidx.compose.foundation.layout.Column
 import androidx.compose.foundation.layout.Row
 import androidx.compose.material.icons.Icons
 import androidx.compose.material.icons.filled.Close
 import androidx.compose.material3.IconButtonDefaults
+import androidx.compose.material3.LocalContentColor
 import androidx.compose.runtime.Composable
+import androidx.compose.runtime.CompositionLocalProvider
 import androidx.compose.runtime.remember
 import androidx.compose.ui.Modifier
 import androidx.compose.ui.tooling.preview.Preview
 import io.element.android.libraries.designsystem.preview.ElementThemedPreview
 import io.element.android.libraries.designsystem.preview.PreviewGroup
+import io.element.android.libraries.theme.ElementTheme
+
+// Figma designs: https://www.figma.com/file/G1xy0HDZKJf5TCRFmKb5d5/Compound-Android-Components?type=design&node-id=1182%3A48861&mode=design&t=Shlcvznm1oUyqGC2-1
 
 @Composable
 fun IconButton(
@@ -36,11 +42,15 @@ fun IconButton(
     interactionSource: MutableInteractionSource = remember { MutableInteractionSource() },
     content: @Composable () -> Unit
 ) {
+    val colors = IconButtonDefaults.iconButtonColors(
+        contentColor = LocalContentColor.current,
+        disabledContentColor = ElementTheme.colors.iconDisabled,
+    )
     androidx.compose.material3.IconButton(
         onClick = onClick,
         modifier = modifier,
         enabled = enabled,
-        colors = IconButtonDefaults.iconButtonColors(),
+        colors = colors,
         interactionSource = interactionSource,
         content = content,
     )
@@ -53,12 +63,26 @@ internal fun IconButtonPreview() =
 
 @Composable
 private fun ContentToPreview() {
-    Row {
-        IconButton(onClick = {}) {
-            Icon(imageVector = Icons.Filled.Close, contentDescription = "")
+    Column {
+        CompositionLocalProvider(LocalContentColor provides ElementTheme.colors.iconPrimary) {
+            Row {
+                IconButton(onClick = {}) {
+                    Icon(imageVector = Icons.Filled.Close, contentDescription = "")
+                }
+                IconButton(enabled = false, onClick = {}) {
+                    Icon(imageVector = Icons.Filled.Close, contentDescription = "")
+                }
+            }
         }
-        IconButton(enabled = false, onClick = {}) {
-            Icon(imageVector = Icons.Filled.Close, contentDescription = "")
+        CompositionLocalProvider(LocalContentColor provides ElementTheme.colors.iconSecondary) {
+            Row {
+                IconButton(onClick = {}) {
+                    Icon(imageVector = Icons.Filled.Close, contentDescription = "")
+                }
+                IconButton(enabled = false, onClick = {}) {
+                    Icon(imageVector = Icons.Filled.Close, contentDescription = "")
+                }
+            }
         }
     }
 }
diff --git a/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/theme/components/LinearProgressIndicator.kt b/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/theme/components/LinearProgressIndicator.kt
new file mode 100644
index 0000000000..54985eaa51
--- /dev/null
+++ b/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/theme/components/LinearProgressIndicator.kt
@@ -0,0 +1,90 @@
+/*
+ * Copyright (c) 2023 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
+ *
+ *     http://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.designsystem.theme.components
+
+import androidx.compose.foundation.layout.Arrangement
+import androidx.compose.foundation.layout.Column
+import androidx.compose.material3.ProgressIndicatorDefaults
+import androidx.compose.runtime.Composable
+import androidx.compose.ui.Modifier
+import androidx.compose.ui.graphics.Color
+import androidx.compose.ui.graphics.StrokeCap
+import androidx.compose.ui.platform.LocalInspectionMode
+import androidx.compose.ui.tooling.preview.Preview
+import androidx.compose.ui.unit.dp
+import io.element.android.libraries.designsystem.preview.ElementThemedPreview
+import io.element.android.libraries.designsystem.preview.PreviewGroup
+
+@Composable
+fun LinearProgressIndicator(
+    progress: Float,
+    modifier: Modifier = Modifier,
+    color: Color = ProgressIndicatorDefaults.linearColor,
+    trackColor: Color = ProgressIndicatorDefaults.linearTrackColor,
+    strokeCap: StrokeCap = ProgressIndicatorDefaults.LinearStrokeCap,
+) {
+    androidx.compose.material3.LinearProgressIndicator(
+        modifier = modifier,
+        progress = progress,
+        color = color,
+        trackColor = trackColor,
+        strokeCap = strokeCap,
+    )
+}
+
+@Composable
+fun LinearProgressIndicator(
+    modifier: Modifier = Modifier,
+    color: Color = ProgressIndicatorDefaults.linearColor,
+    trackColor: Color = ProgressIndicatorDefaults.linearTrackColor,
+    strokeCap: StrokeCap = ProgressIndicatorDefaults.LinearStrokeCap,
+) {
+    if (LocalInspectionMode.current) {
+        // Use a determinate progress indicator to improve the preview rendering
+        androidx.compose.material3.LinearProgressIndicator(
+            modifier = modifier,
+            progress = 0.75F,
+            color = color,
+            trackColor = trackColor,
+            strokeCap = strokeCap,
+        )
+    } else {
+        androidx.compose.material3.LinearProgressIndicator(
+            modifier = modifier,
+            color = color,
+            trackColor = trackColor,
+            strokeCap = strokeCap,
+        )
+    }
+}
+
+@Preview(group = PreviewGroup.Progress)
+@Composable
+internal fun LinearProgressIndicatorPreview() = ElementThemedPreview(vertical = false) { ContentToPreview() }
+
+@Composable
+private fun ContentToPreview() {
+    Column(verticalArrangement = Arrangement.spacedBy(4.dp)) {
+        // Indeterminate progress
+        LinearProgressIndicator(
+        )
+        // Fixed progress
+        LinearProgressIndicator(
+            progress = 0.90F
+        )
+    }
+}
diff --git a/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/theme/components/MediumTopAppBar.kt b/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/theme/components/MediumTopAppBar.kt
index d3cd2fee07..d868f49965 100644
--- a/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/theme/components/MediumTopAppBar.kt
+++ b/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/theme/components/MediumTopAppBar.kt
@@ -18,15 +18,21 @@ package io.element.android.libraries.designsystem.theme.components
 
 import androidx.compose.foundation.layout.RowScope
 import androidx.compose.foundation.layout.WindowInsets
+import androidx.compose.material.icons.Icons
+import androidx.compose.material.icons.filled.Share
 import androidx.compose.material3.ExperimentalMaterial3Api
+import androidx.compose.material3.LocalContentColor
 import androidx.compose.material3.TopAppBarColors
 import androidx.compose.material3.TopAppBarDefaults
 import androidx.compose.material3.TopAppBarScrollBehavior
 import androidx.compose.runtime.Composable
+import androidx.compose.runtime.CompositionLocalProvider
 import androidx.compose.ui.Modifier
 import androidx.compose.ui.tooling.preview.Preview
+import io.element.android.libraries.designsystem.components.button.BackButton
 import io.element.android.libraries.designsystem.preview.ElementThemedPreview
 import io.element.android.libraries.designsystem.preview.PreviewGroup
+import io.element.android.libraries.theme.ElementTheme
 
 @OptIn(ExperimentalMaterial3Api::class)
 @Composable
@@ -43,7 +49,11 @@ fun MediumTopAppBar(
         title = title,
         modifier = modifier,
         navigationIcon = navigationIcon,
-        actions = actions,
+        actions = {
+            CompositionLocalProvider(LocalContentColor provides ElementTheme.colors.textActionPrimary) {
+                actions()
+            }
+        },
         windowInsets = windowInsets,
         colors = colors,
         scrollBehavior = scrollBehavior,
@@ -58,5 +68,14 @@ internal fun MediumTopAppBarPreview() =
 @OptIn(ExperimentalMaterial3Api::class)
 @Composable
 private fun ContentToPreview() {
-    MediumTopAppBar(title = { Text(text = "Title") })
+    MediumTopAppBar(
+        title = { Text(text = "Title") },
+        navigationIcon = { BackButton(onClick = {}) },
+        actions = {
+            TextButton(text = "Action", onClick = {})
+            IconButton(onClick = {}) {
+                Icon(imageVector = Icons.Default.Share, contentDescription = null)
+            }
+        }
+    )
 }
diff --git a/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/theme/components/ModalBottomSheet.kt b/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/theme/components/ModalBottomSheet.kt
index a31e4188c6..57b0612ad7 100644
--- a/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/theme/components/ModalBottomSheet.kt
+++ b/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/theme/components/ModalBottomSheet.kt
@@ -25,7 +25,6 @@ import androidx.compose.foundation.layout.padding
 import androidx.compose.material3.BottomSheetDefaults
 import androidx.compose.material3.ExperimentalMaterial3Api
 import androidx.compose.material3.SheetState
-import androidx.compose.material3.SheetValue
 import androidx.compose.material3.contentColorFor
 import androidx.compose.material3.rememberModalBottomSheetState
 import androidx.compose.runtime.Composable
@@ -38,6 +37,7 @@ import androidx.compose.ui.unit.dp
 import io.element.android.libraries.designsystem.preview.ElementPreviewDark
 import io.element.android.libraries.designsystem.preview.ElementPreviewLight
 import io.element.android.libraries.designsystem.preview.PreviewGroup
+import io.element.android.libraries.designsystem.preview.sheetStateForPreview
 import io.element.android.libraries.theme.ElementTheme
 import kotlinx.coroutines.CoroutineScope
 import kotlinx.coroutines.launch
@@ -100,10 +100,7 @@ private fun ContentToPreview() {
     ) {
         ModalBottomSheet(
             onDismissRequest = {},
-            sheetState = SheetState(
-                skipPartiallyExpanded = true,
-                initialValue = SheetValue.Expanded,
-            ),
+            sheetState = sheetStateForPreview,
         ) {
             Text(
                 text = "Sheet Content",
diff --git a/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/theme/components/OutlinedButton.kt b/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/theme/components/OutlinedButton.kt
deleted file mode 100644
index fa7ee261f6..0000000000
--- a/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/theme/components/OutlinedButton.kt
+++ /dev/null
@@ -1,91 +0,0 @@
-/*
- * Copyright (c) 2023 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
- *
- *     http://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.designsystem.theme.components
-
-import androidx.compose.foundation.BorderStroke
-import androidx.compose.foundation.interaction.MutableInteractionSource
-import androidx.compose.foundation.layout.Arrangement
-import androidx.compose.foundation.layout.Column
-import androidx.compose.foundation.layout.PaddingValues
-import androidx.compose.foundation.layout.RowScope
-import androidx.compose.material3.ButtonColors
-import androidx.compose.material3.ButtonDefaults
-import androidx.compose.material3.ButtonElevation
-import androidx.compose.runtime.Composable
-import androidx.compose.runtime.remember
-import androidx.compose.ui.Modifier
-import androidx.compose.ui.graphics.Shape
-import androidx.compose.ui.tooling.preview.Preview
-import androidx.compose.ui.unit.dp
-import io.element.android.libraries.designsystem.preview.ElementThemedPreview
-import io.element.android.libraries.designsystem.preview.PreviewGroup
-
-@Composable
-fun OutlinedButton(
-    onClick: () -> Unit,
-    modifier: Modifier = Modifier,
-    enabled: Boolean = true,
-    shape: Shape = ElementOutlinedButtonDefaults.shape,
-    colors: ButtonColors = ElementOutlinedButtonDefaults.buttonColors(),
-    elevation: ButtonElevation? = ElementOutlinedButtonDefaults.buttonElevation(),
-    border: BorderStroke? = ElementOutlinedButtonDefaults.border,
-    contentPadding: PaddingValues = ElementOutlinedButtonDefaults.ContentPadding,
-    interactionSource: MutableInteractionSource = remember { MutableInteractionSource() },
-    content: @Composable RowScope.() -> Unit
-) {
-    androidx.compose.material3.Button(
-        onClick = onClick,
-        modifier = modifier,
-        enabled = enabled,
-        shape = shape,
-        colors = colors,
-        elevation = elevation,
-        border = border,
-        contentPadding = contentPadding,
-        interactionSource = interactionSource,
-        content = content,
-    )
-}
-
-object ElementOutlinedButtonDefaults {
-    val ContentPadding = PaddingValues(horizontal = 24.dp, vertical = 14.dp)
-    val shape: Shape @Composable get() = ButtonDefaults.outlinedShape
-    val border: BorderStroke @Composable get() = ButtonDefaults.outlinedButtonBorder
-    @Composable
-    fun buttonElevation(): ButtonElevation = ButtonDefaults.buttonElevation()
-
-    @Composable
-    fun buttonColors(): ButtonColors = ButtonDefaults.outlinedButtonColors()
-
-
-}
-
-@Preview(group = PreviewGroup.Buttons)
-@Composable
-internal fun OutlinedButtonsPreview() = ElementThemedPreview { ContentToPreview() }
-
-@Composable
-private fun ContentToPreview() {
-    Column(verticalArrangement = Arrangement.spacedBy(8.dp)) {
-        OutlinedButton(onClick = {}, enabled = true) {
-            Text(text = "Click me! - Enabled")
-        }
-        OutlinedButton(onClick = {}, enabled = false) {
-            Text(text = "Click me! - Disabled")
-        }
-    }
-}
diff --git a/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/theme/components/RadioButton.kt b/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/theme/components/RadioButton.kt
index 6b0c1b377e..a8b186a6b2 100644
--- a/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/theme/components/RadioButton.kt
+++ b/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/theme/components/RadioButton.kt
@@ -17,15 +17,21 @@
 package io.element.android.libraries.designsystem.theme.components
 
 import androidx.compose.foundation.interaction.MutableInteractionSource
+import androidx.compose.foundation.layout.Arrangement
 import androidx.compose.foundation.layout.Column
+import androidx.compose.foundation.layout.Row
 import androidx.compose.material3.RadioButtonColors
 import androidx.compose.material3.RadioButtonDefaults
 import androidx.compose.runtime.Composable
 import androidx.compose.runtime.remember
 import androidx.compose.ui.Modifier
 import androidx.compose.ui.tooling.preview.Preview
+import androidx.compose.ui.unit.dp
 import io.element.android.libraries.designsystem.preview.ElementThemedPreview
 import io.element.android.libraries.designsystem.preview.PreviewGroup
+import io.element.android.libraries.theme.ElementTheme
+
+// Designs in https://www.figma.com/file/G1xy0HDZKJf5TCRFmKb5d5/Compound-Android-Components?type=design&node-id=425%3A24202&mode=design&t=qb99xBP5mwwCtGkN-1
 
 @Composable
 fun RadioButton(
@@ -33,7 +39,7 @@ fun RadioButton(
     onClick: (() -> Unit)?,
     modifier: Modifier = Modifier,
     enabled: Boolean = true,
-    colors: RadioButtonColors = RadioButtonDefaults.colors(),
+    colors: RadioButtonColors = compoundRadioButtonColors(),
     interactionSource: MutableInteractionSource = remember { MutableInteractionSource() }
 ) {
     androidx.compose.material3.RadioButton(
@@ -46,6 +52,15 @@ fun RadioButton(
     )
 }
 
+@Composable
+internal fun compoundRadioButtonColors(): RadioButtonColors {
+    return RadioButtonDefaults.colors(
+        unselectedColor = ElementTheme.colors.borderInteractivePrimary,
+        disabledUnselectedColor = ElementTheme.colors.borderDisabled,
+        disabledSelectedColor = ElementTheme.colors.iconDisabled,
+    )
+}
+
 @Preview(group = PreviewGroup.Toggles)
 @Composable
 internal fun RadioButtonPreview() = ElementThemedPreview(vertical = false) { ContentToPreview() }
@@ -53,9 +68,13 @@ internal fun RadioButtonPreview() = ElementThemedPreview(vertical = false) { Con
 @Composable
 private fun ContentToPreview() {
     Column {
-        RadioButton(selected = false, onClick = {})
-        RadioButton(selected = true, onClick = {})
-        RadioButton(selected = false, enabled = false, onClick = {})
-        RadioButton(selected = true, enabled = false, onClick = {})
+        Row(horizontalArrangement = Arrangement.spacedBy(6.dp)) {
+            RadioButton(selected = false, onClick = {})
+            RadioButton(selected = false, enabled = false, onClick = {})
+        }
+        Row(horizontalArrangement = Arrangement.spacedBy(6.dp)) {
+            RadioButton(selected = true, onClick = {})
+            RadioButton(selected = true, enabled = false, onClick = {})
+        }
     }
 }
diff --git a/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/theme/components/Snackbar.kt b/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/theme/components/Snackbar.kt
new file mode 100644
index 0000000000..d2969fc3e9
--- /dev/null
+++ b/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/theme/components/Snackbar.kt
@@ -0,0 +1,147 @@
+/*
+ * Copyright (c) 2023 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
+ *
+ *     http://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.designsystem.theme.components
+
+import androidx.compose.foundation.shape.RoundedCornerShape
+import androidx.compose.material.icons.Icons
+import androidx.compose.material.icons.filled.Close
+import androidx.compose.material3.SnackbarDefaults
+import androidx.compose.runtime.Composable
+import androidx.compose.ui.Modifier
+import androidx.compose.ui.graphics.Color
+import androidx.compose.ui.graphics.Shape
+import androidx.compose.ui.tooling.preview.Preview
+import androidx.compose.ui.unit.dp
+import io.element.android.libraries.designsystem.components.button.ButtonVisuals
+import io.element.android.libraries.designsystem.preview.ElementThemedPreview
+import io.element.android.libraries.designsystem.preview.PreviewGroup
+import io.element.android.libraries.theme.ElementTheme
+import io.element.android.libraries.theme.SnackBarLabelColorDark
+import io.element.android.libraries.theme.SnackBarLabelColorLight
+
+@Composable
+fun Snackbar(
+    message: String,
+    modifier: Modifier = Modifier,
+    action: ButtonVisuals? = null,
+    dismissAction: ButtonVisuals? = null,
+    actionOnNewLine: Boolean = false,
+    shape: Shape = RoundedCornerShape(8.dp),
+    containerColor: Color = SnackbarDefaults.color,
+    contentColor: Color = ElementTheme.materialColors.inverseOnSurface,
+    actionContentColor: Color = actionContentColor(),
+    dismissActionContentColor: Color = SnackbarDefaults.dismissActionContentColor,
+) {
+    Snackbar(
+        modifier = modifier,
+        action = action?.let { @Composable { it.Composable() } },
+        dismissAction = dismissAction?.let { @Composable { it.Composable() } },
+        actionOnNewLine = actionOnNewLine,
+        shape = shape,
+        containerColor = containerColor,
+        contentColor = contentColor,
+        actionContentColor = actionContentColor,
+        dismissActionContentColor = dismissActionContentColor,
+        content = { Text(text = message) },
+    )
+}
+
+@Composable
+fun Snackbar(
+    modifier: Modifier = Modifier,
+    action: @Composable (() -> Unit)? = null,
+    dismissAction: @Composable (() -> Unit)? = null,
+    actionOnNewLine: Boolean = false,
+    shape: Shape = RoundedCornerShape(8.dp),
+    containerColor: Color = SnackbarDefaults.color,
+    contentColor: Color = ElementTheme.materialColors.inverseOnSurface,
+    actionContentColor: Color = actionContentColor(),
+    dismissActionContentColor: Color = SnackbarDefaults.dismissActionContentColor,
+    content: @Composable () -> Unit
+) {
+    androidx.compose.material3.Snackbar(
+        modifier = modifier,
+        action = action,
+        dismissAction = dismissAction,
+        actionOnNewLine = actionOnNewLine,
+        shape = shape,
+        containerColor = containerColor,
+        contentColor = contentColor,
+        actionContentColor = actionContentColor,
+        dismissActionContentColor = dismissActionContentColor,
+        content = content,
+    )
+}
+
+// TODO this color is temporary, an `inverse` version should be added to the semantic colors instead
+@Composable
+private fun actionContentColor(): Color {
+    return if (ElementTheme.isLightTheme) {
+        SnackBarLabelColorLight
+    } else {
+        SnackBarLabelColorDark
+    }
+}
+
+@Preview(name = "Snackbar", group = PreviewGroup.Snackbars)
+@Composable
+internal fun SnackbarPreview() {
+    ElementThemedPreview {
+        Snackbar(message = "Snackbar supporting text")
+    }
+}
+
+@Preview(name = "Snackbar with action", group = PreviewGroup.Snackbars)
+@Composable
+internal fun SnackbarWithActionPreview() {
+    ElementThemedPreview {
+        Snackbar(message = "Snackbar supporting text", action = ButtonVisuals.Text("Action", {}))
+    }
+}
+
+@Preview(name = "Snackbar with action and close button", group = PreviewGroup.Snackbars)
+@Composable
+internal fun SnackbarWithActionAndCloseButtonPreview() {
+    ElementThemedPreview {
+        Snackbar(
+            message = "Snackbar supporting text",
+            action = ButtonVisuals.Text("Action", {}),
+            dismissAction = ButtonVisuals.Icon(IconSource.Vector(Icons.Default.Close), {})
+        )
+    }
+}
+
+@Preview(name = "Snackbar with action on new line", group = PreviewGroup.Snackbars)
+@Composable
+internal fun SnackbarWithActionOnNewLinePreview() {
+    ElementThemedPreview {
+        Snackbar(message = "Snackbar supporting text", action = ButtonVisuals.Text("Action", {}), actionOnNewLine = true)
+    }
+}
+
+@Preview(name = "Snackbar with action and close button on new line", group = PreviewGroup.Snackbars)
+@Composable
+internal fun SnackbarWithActionOnNewLineAndCloseButtonPreview() {
+    ElementThemedPreview {
+        Snackbar(
+            message = "Snackbar supporting text",
+            action = ButtonVisuals.Text("Action", {}),
+            dismissAction = ButtonVisuals.Icon(IconSource.Vector(Icons.Default.Close), {}),
+            actionOnNewLine = true
+        )
+    }
+}
diff --git a/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/theme/components/Switch.kt b/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/theme/components/Switch.kt
new file mode 100644
index 0000000000..ab4c9dee05
--- /dev/null
+++ b/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/theme/components/Switch.kt
@@ -0,0 +1,89 @@
+/*
+ * Copyright (c) 2023 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
+ *
+ *     http://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.designsystem.theme.components
+
+import androidx.compose.foundation.interaction.MutableInteractionSource
+import androidx.compose.foundation.layout.Arrangement
+import androidx.compose.foundation.layout.Column
+import androidx.compose.foundation.layout.Row
+import androidx.compose.foundation.layout.padding
+import androidx.compose.material3.SwitchColors
+import androidx.compose.material3.SwitchDefaults
+import androidx.compose.runtime.Composable
+import androidx.compose.runtime.getValue
+import androidx.compose.runtime.mutableStateOf
+import androidx.compose.runtime.remember
+import androidx.compose.runtime.setValue
+import androidx.compose.ui.Modifier
+import androidx.compose.ui.graphics.Color
+import androidx.compose.ui.tooling.preview.Preview
+import androidx.compose.ui.unit.dp
+import io.element.android.libraries.designsystem.preview.ElementThemedPreview
+import io.element.android.libraries.designsystem.preview.PreviewGroup
+import io.element.android.libraries.theme.ElementTheme
+import androidx.compose.material3.Switch as Material3Switch
+
+// Designs in https://www.figma.com/file/G1xy0HDZKJf5TCRFmKb5d5/Compound-Android-Components?type=design&node-id=425%3A24203&mode=design&t=qb99xBP5mwwCtGkN-1
+
+@Composable
+fun Switch(
+    checked: Boolean,
+    onCheckedChange: ((Boolean) -> Unit)?,
+    modifier: Modifier = Modifier,
+    enabled: Boolean = true,
+    colors: SwitchColors = compoundSwitchColors(),
+    interactionSource: MutableInteractionSource = remember { MutableInteractionSource() },
+    thumbContent: (@Composable () -> Unit)? = null,
+) {
+    Material3Switch(
+        checked = checked,
+        onCheckedChange = onCheckedChange,
+        modifier = modifier,
+        enabled = enabled,
+        colors = colors,
+        interactionSource = interactionSource,
+        thumbContent = thumbContent
+    )
+}
+
+@Composable
+internal fun compoundSwitchColors() = SwitchDefaults.colors(
+    uncheckedThumbColor = ElementTheme.colors.bgActionPrimaryRest,
+    uncheckedTrackColor = Color.Transparent,
+    disabledUncheckedBorderColor = ElementTheme.colors.borderDisabled,
+    disabledUncheckedThumbColor = ElementTheme.colors.iconDisabled,
+    disabledCheckedTrackColor = ElementTheme.colors.iconDisabled,
+    disabledCheckedBorderColor = ElementTheme.colors.iconDisabled,
+)
+
+@Preview(group = PreviewGroup.Toggles)
+@Composable
+internal fun SwitchPreview() {
+    var checked by remember { mutableStateOf(false) }
+    ElementThemedPreview {
+        Column(modifier = Modifier.padding(10.dp), verticalArrangement = Arrangement.spacedBy(6.dp)) {
+            Row(horizontalArrangement = Arrangement.spacedBy(6.dp)) {
+                Switch(checked = checked, onCheckedChange = { checked = !checked })
+                Switch(enabled = false, checked = checked, onCheckedChange = { checked = !checked })
+            }
+            Row(horizontalArrangement = Arrangement.spacedBy(6.dp)) {
+                Switch(checked = !checked, onCheckedChange = { checked = !checked })
+                Switch(enabled = false, checked = !checked, onCheckedChange = { checked = !checked })
+            }
+        }
+    }
+}
diff --git a/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/theme/components/TextButton.kt b/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/theme/components/TextButton.kt
deleted file mode 100644
index 3b4b50a5e7..0000000000
--- a/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/theme/components/TextButton.kt
+++ /dev/null
@@ -1,76 +0,0 @@
-/*
- * Copyright (c) 2023 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
- *
- *     http://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.designsystem.theme.components
-
-import androidx.compose.foundation.BorderStroke
-import androidx.compose.foundation.interaction.MutableInteractionSource
-import androidx.compose.foundation.layout.Column
-import androidx.compose.foundation.layout.PaddingValues
-import androidx.compose.foundation.layout.RowScope
-import androidx.compose.material3.ButtonColors
-import androidx.compose.material3.ButtonDefaults
-import androidx.compose.material3.ButtonElevation
-import androidx.compose.runtime.Composable
-import androidx.compose.runtime.remember
-import androidx.compose.ui.Modifier
-import androidx.compose.ui.graphics.Shape
-import androidx.compose.ui.tooling.preview.Preview
-import io.element.android.libraries.designsystem.preview.ElementThemedPreview
-import io.element.android.libraries.designsystem.preview.PreviewGroup
-
-@Composable
-fun TextButton(
-    onClick: () -> Unit,
-    modifier: Modifier = Modifier,
-    enabled: Boolean = true,
-    shape: Shape = ButtonDefaults.textShape,
-    colors: ButtonColors = ButtonDefaults.textButtonColors(),
-    elevation: ButtonElevation? = null,
-    border: BorderStroke? = null,
-    contentPadding: PaddingValues = ButtonDefaults.TextButtonContentPadding,
-    interactionSource: MutableInteractionSource = remember { MutableInteractionSource() },
-    content: @Composable RowScope.() -> Unit
-) {
-    androidx.compose.material3.TextButton(
-        onClick = onClick,
-        modifier = modifier,
-        enabled = enabled,
-        shape = shape,
-        colors = colors,
-        elevation = elevation,
-        border = border,
-        contentPadding = contentPadding,
-        interactionSource = interactionSource,
-        content = content,
-    )
-}
-
-@Preview(group = PreviewGroup.Buttons)
-@Composable
-internal fun TextButtonPreview() = ElementThemedPreview { ContentToPreview() }
-
-@Composable
-private fun ContentToPreview() {
-    Column {
-        TextButton(onClick = {}, enabled = true) {
-            Text(text = "Click me! - Enabled")
-        }
-        TextButton(onClick = {}, enabled = false) {
-            Text(text = "Click me! - Disabled")
-        }
-    }
-}
diff --git a/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/theme/components/TopAppBar.kt b/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/theme/components/TopAppBar.kt
index 23848ef76d..93d11e8c9a 100644
--- a/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/theme/components/TopAppBar.kt
+++ b/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/theme/components/TopAppBar.kt
@@ -18,15 +18,21 @@ package io.element.android.libraries.designsystem.theme.components
 
 import androidx.compose.foundation.layout.RowScope
 import androidx.compose.foundation.layout.WindowInsets
+import androidx.compose.material.icons.Icons
+import androidx.compose.material.icons.filled.Share
 import androidx.compose.material3.ExperimentalMaterial3Api
+import androidx.compose.material3.LocalContentColor
 import androidx.compose.material3.TopAppBarColors
 import androidx.compose.material3.TopAppBarDefaults
 import androidx.compose.material3.TopAppBarScrollBehavior
 import androidx.compose.runtime.Composable
+import androidx.compose.runtime.CompositionLocalProvider
 import androidx.compose.ui.Modifier
 import androidx.compose.ui.tooling.preview.Preview
+import io.element.android.libraries.designsystem.components.button.BackButton
 import io.element.android.libraries.designsystem.preview.ElementThemedPreview
 import io.element.android.libraries.designsystem.preview.PreviewGroup
+import io.element.android.libraries.theme.ElementTheme
 
 @OptIn(ExperimentalMaterial3Api::class)
 @Composable
@@ -43,7 +49,11 @@ fun TopAppBar(
         title = title,
         modifier = modifier,
         navigationIcon = navigationIcon,
-        actions = actions,
+        actions = {
+            CompositionLocalProvider(LocalContentColor provides ElementTheme.colors.textActionPrimary) {
+                actions()
+            }
+        },
         windowInsets = windowInsets,
         colors = colors,
         scrollBehavior = scrollBehavior,
@@ -58,5 +68,14 @@ internal fun TopAppBarPreview() =
 @OptIn(ExperimentalMaterial3Api::class)
 @Composable
 private fun ContentToPreview() {
-    TopAppBar(title = { Text(text = "Title") })
+    TopAppBar(
+        title = { Text(text = "Title") },
+        navigationIcon = { BackButton(onClick = {}) },
+        actions = {
+            TextButton(text = "Action", onClick = {})
+            IconButton(onClick = {}) {
+                Icon(imageVector = Icons.Default.Share, contentDescription = null)
+            }
+        }
+    )
 }
diff --git a/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/theme/components/previews/DatePickerPreview.kt b/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/theme/components/previews/DatePickerPreview.kt
index a422c5e729..45b5eb39be 100644
--- a/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/theme/components/previews/DatePickerPreview.kt
+++ b/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/theme/components/previews/DatePickerPreview.kt
@@ -23,7 +23,7 @@ import androidx.compose.material3.MaterialTheme
 import androidx.compose.material3.rememberDatePickerState
 import androidx.compose.runtime.Composable
 import androidx.compose.ui.tooling.preview.Preview
-import io.element.android.libraries.designsystem.components.dialogs.AlertDialogContent
+import io.element.android.libraries.designsystem.theme.components.AlertDialogContent
 import io.element.android.libraries.designsystem.preview.ElementPreviewDark
 import io.element.android.libraries.designsystem.preview.ElementPreviewLight
 import io.element.android.libraries.designsystem.preview.PreviewGroup
@@ -44,7 +44,7 @@ internal fun DatePickerPreviewDark() {
 @Composable
 private fun ContentToPreview() {
     val state = rememberDatePickerState(
-        initialSelectedDateMillis = 1672578000000L,
+        initialSelectedDateMillis = 1_672_578_000_000L,
     )
     AlertDialogContent(
         buttons = { /*TODO*/ },
diff --git a/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/theme/components/previews/MenuPreview.kt b/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/theme/components/previews/MenuPreview.kt
index f1c2cd444d..2ca04f1008 100644
--- a/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/theme/components/previews/MenuPreview.kt
+++ b/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/theme/components/previews/MenuPreview.kt
@@ -30,7 +30,6 @@ import io.element.android.libraries.designsystem.preview.PreviewGroup
 import io.element.android.libraries.designsystem.theme.components.Button
 import io.element.android.libraries.designsystem.theme.components.DropdownMenu
 import io.element.android.libraries.designsystem.theme.components.DropdownMenuItem
-import io.element.android.libraries.designsystem.theme.components.DropdownMenuItemText
 import io.element.android.libraries.designsystem.theme.components.Icon
 import io.element.android.libraries.designsystem.theme.components.Text
 
@@ -39,9 +38,7 @@ import io.element.android.libraries.designsystem.theme.components.Text
 internal fun MenuPreview() {
     ElementThemedPreview {
         var isExpanded by remember { mutableStateOf(false) }
-        Button(onClick = { isExpanded = !isExpanded }) {
-            Text("Toggle")
-        }
+        Button(text = "Toggle", onClick = { isExpanded = !isExpanded })
         DropdownMenu(expanded = isExpanded, onDismissRequest = { isExpanded = false }) {
             for (i in 0..5) {
                 val leadingIcon: @Composable (() -> Unit)? = if (i in 2..3) {
@@ -60,7 +57,7 @@ internal fun MenuPreview() {
                     null
                 }
                 DropdownMenuItem(
-                    text = { DropdownMenuItemText(text = "Item $i") },
+                    text = { Text(text = "Item $i") },
                     onClick = { isExpanded = false },
                     leadingIcon = leadingIcon,
                     trailingIcon = trailingIcon,
diff --git a/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/theme/components/previews/SwitchPreview.kt b/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/theme/components/previews/SwitchPreview.kt
deleted file mode 100644
index 11491a0a1c..0000000000
--- a/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/theme/components/previews/SwitchPreview.kt
+++ /dev/null
@@ -1,51 +0,0 @@
-/*
- * Copyright (c) 2023 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
- *
- *     http://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.designsystem.theme.components.previews
-
-import androidx.compose.foundation.layout.Arrangement
-import androidx.compose.foundation.layout.Row
-import androidx.compose.material.icons.Icons
-import androidx.compose.material.icons.outlined.Check
-import androidx.compose.material3.Switch
-import androidx.compose.runtime.Composable
-import androidx.compose.runtime.getValue
-import androidx.compose.runtime.mutableStateOf
-import androidx.compose.runtime.remember
-import androidx.compose.runtime.setValue
-import androidx.compose.ui.tooling.preview.Preview
-import androidx.compose.ui.unit.dp
-import io.element.android.libraries.designsystem.preview.ElementThemedPreview
-import io.element.android.libraries.designsystem.preview.PreviewGroup
-import io.element.android.libraries.designsystem.theme.components.Icon
-
-@Preview(group = PreviewGroup.Toggles)
-@Composable
-internal fun SwitchPreview() {
-    ElementThemedPreview {
-        Row(horizontalArrangement = Arrangement.spacedBy(8.dp)) {
-            var checked by remember { mutableStateOf(false) }
-            Switch(checked = checked, onCheckedChange = { checked = !checked })
-            Switch(checked = checked, onCheckedChange = { checked = !checked }, thumbContent = {
-                Icon(imageVector = Icons.Outlined.Check, contentDescription = null)
-            })
-            Switch(checked = checked, enabled = false, onCheckedChange = { checked = !checked })
-            Switch(checked = checked, enabled = false, onCheckedChange = { checked = !checked }, thumbContent = {
-                Icon(imageVector = Icons.Outlined.Check, contentDescription = null)
-            })
-        }
-    }
-}
diff --git a/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/theme/components/previews/TimePickerPreview.kt b/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/theme/components/previews/TimePickerPreview.kt
index 79f0fffbee..7aae42ed0e 100644
--- a/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/theme/components/previews/TimePickerPreview.kt
+++ b/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/theme/components/previews/TimePickerPreview.kt
@@ -24,7 +24,7 @@ import androidx.compose.material3.TimePickerLayoutType
 import androidx.compose.material3.rememberTimePickerState
 import androidx.compose.runtime.Composable
 import androidx.compose.ui.tooling.preview.Preview
-import io.element.android.libraries.designsystem.components.dialogs.AlertDialogContent
+import io.element.android.libraries.designsystem.theme.components.AlertDialogContent
 import io.element.android.libraries.designsystem.preview.ElementPreviewDark
 import io.element.android.libraries.designsystem.preview.ElementPreviewLight
 import io.element.android.libraries.designsystem.preview.ElementThemedPreview
diff --git a/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/utils/LogCompositions.kt b/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/utils/LogCompositions.kt
index f6edd1a8fb..2618a5de82 100644
--- a/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/utils/LogCompositions.kt
+++ b/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/utils/LogCompositions.kt
@@ -28,10 +28,12 @@ import timber.log.Timber
 @Composable
 fun LogCompositions(tag: String, msg: String) {
     if (BuildConfig.DEBUG) {
-        val ref = remember { Ref(0) }
+        val ref = remember { Ref() }
         SideEffect { ref.value++ }
-        Timber.d(tag, "Compositions: $msg ${ref.value}")
+        Timber.tag(tag).d("Compositions: $msg ${ref.value}")
     }
 }
 
-class Ref(var value: Int)
+private class Ref {
+    var value: Int = 0
+}
diff --git a/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/utils/Snackbar.kt b/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/utils/Snackbar.kt
index f4e44779d1..4513a90914 100644
--- a/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/utils/Snackbar.kt
+++ b/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/utils/Snackbar.kt
@@ -17,6 +17,8 @@
 package io.element.android.libraries.designsystem.utils
 
 import androidx.annotation.StringRes
+import androidx.compose.material.icons.Icons
+import androidx.compose.material.icons.filled.Close
 import androidx.compose.material3.SnackbarDuration
 import androidx.compose.material3.SnackbarHostState
 import androidx.compose.runtime.Composable
@@ -25,7 +27,11 @@ import androidx.compose.runtime.State
 import androidx.compose.runtime.collectAsState
 import androidx.compose.runtime.compositionLocalOf
 import androidx.compose.runtime.remember
+import androidx.compose.ui.Modifier
 import androidx.compose.ui.res.stringResource
+import io.element.android.libraries.designsystem.components.button.ButtonVisuals
+import io.element.android.libraries.designsystem.theme.components.IconSource
+import io.element.android.libraries.designsystem.theme.components.Snackbar
 import kotlinx.coroutines.flow.Flow
 import kotlinx.coroutines.flow.MutableStateFlow
 import kotlinx.coroutines.flow.asStateFlow
@@ -65,6 +71,19 @@ fun SnackbarDispatcher.collectSnackbarMessageAsState(): State
     return snackbarMessage.collectAsState(initial = null)
 }
 
+@Composable
+fun SnackbarHost(hostState: SnackbarHostState, modifier: Modifier = Modifier) {
+    androidx.compose.material3.SnackbarHost(hostState, modifier) { data ->
+        Snackbar(
+            message = data.visuals.message,
+            action = data.visuals.actionLabel?.let { ButtonVisuals.Text(it, data::performAction) },
+            dismissAction = if (data.visuals.withDismissAction) {
+                ButtonVisuals.Icon(IconSource.Vector(Icons.Default.Close), data::dismiss)
+            } else null,
+        )
+    }
+}
+
 @Composable
 fun rememberSnackbarHostState(snackbarMessage: SnackbarMessage?): SnackbarHostState {
     val snackbarHostState = remember { SnackbarHostState() }
diff --git a/libraries/designsystem/src/main/res/drawable/ic_baseline_reply_24.xml b/libraries/designsystem/src/main/res/drawable/ic_baseline_reply_24.xml
deleted file mode 100644
index 96a220a5cd..0000000000
--- a/libraries/designsystem/src/main/res/drawable/ic_baseline_reply_24.xml
+++ /dev/null
@@ -1,27 +0,0 @@
-
-
-
-    
-
diff --git a/libraries/designsystem/src/main/res/drawable/ic_content_arrow_forward.xml b/libraries/designsystem/src/main/res/drawable/ic_content_arrow_forward.xml
deleted file mode 100644
index 739053947d..0000000000
--- a/libraries/designsystem/src/main/res/drawable/ic_content_arrow_forward.xml
+++ /dev/null
@@ -1,27 +0,0 @@
-
-
-
-    
-
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 f1af61c8e7..0736cf61ce 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
@@ -37,6 +37,8 @@ import io.element.android.libraries.matrix.api.timeline.item.event.LocationMessa
 import io.element.android.libraries.matrix.api.timeline.item.event.MessageContent
 import io.element.android.libraries.matrix.api.timeline.item.event.MessageType
 import io.element.android.libraries.matrix.api.timeline.item.event.NoticeMessageType
+import io.element.android.libraries.matrix.api.timeline.item.event.PollContent
+import io.element.android.libraries.matrix.api.timeline.item.event.PollEndContent
 import io.element.android.libraries.matrix.api.timeline.item.event.ProfileChangeContent
 import io.element.android.libraries.matrix.api.timeline.item.event.ProfileTimelineDetails
 import io.element.android.libraries.matrix.api.timeline.item.event.RedactedContent
@@ -94,6 +96,7 @@ class DefaultRoomLastMessageFormatter @Inject constructor(
             is StateContent -> {
                 stateContentFormatter.format(content, senderDisplayName, isOutgoing, RenderingMode.RoomList)
             }
+            is PollContent, is PollEndContent, // TODO Polls: handle last message
             is FailedToParseMessageLikeContent, is FailedToParseStateContent, is UnknownContent -> {
                 prefixIfNeeded(sp.getString(CommonStrings.common_unsupported_event), senderDisplayName, isDmRoom)
             }
diff --git a/libraries/eventformatter/impl/src/main/kotlin/io/element/android/libraries/eventformatter/impl/DefaultTimelineEventFormatter.kt b/libraries/eventformatter/impl/src/main/kotlin/io/element/android/libraries/eventformatter/impl/DefaultTimelineEventFormatter.kt
index 8f89233a31..42d8aae083 100644
--- a/libraries/eventformatter/impl/src/main/kotlin/io/element/android/libraries/eventformatter/impl/DefaultTimelineEventFormatter.kt
+++ b/libraries/eventformatter/impl/src/main/kotlin/io/element/android/libraries/eventformatter/impl/DefaultTimelineEventFormatter.kt
@@ -26,6 +26,8 @@ import io.element.android.libraries.matrix.api.timeline.item.event.EventTimeline
 import io.element.android.libraries.matrix.api.timeline.item.event.FailedToParseMessageLikeContent
 import io.element.android.libraries.matrix.api.timeline.item.event.FailedToParseStateContent
 import io.element.android.libraries.matrix.api.timeline.item.event.MessageContent
+import io.element.android.libraries.matrix.api.timeline.item.event.PollContent
+import io.element.android.libraries.matrix.api.timeline.item.event.PollEndContent
 import io.element.android.libraries.matrix.api.timeline.item.event.ProfileChangeContent
 import io.element.android.libraries.matrix.api.timeline.item.event.ProfileTimelineDetails
 import io.element.android.libraries.matrix.api.timeline.item.event.RedactedContent
@@ -63,6 +65,8 @@ class DefaultTimelineEventFormatter @Inject constructor(
             }
             RedactedContent,
             is StickerContent,
+            is PollContent,
+            is PollEndContent,
             is UnableToDecryptContent,
             is MessageContent,
             is FailedToParseMessageLikeContent,
diff --git a/libraries/eventformatter/impl/src/main/res/values-ru/translations.xml b/libraries/eventformatter/impl/src/main/res/values-ru/translations.xml
new file mode 100644
index 0000000000..4c1defbb68
--- /dev/null
+++ b/libraries/eventformatter/impl/src/main/res/values-ru/translations.xml
@@ -0,0 +1,57 @@
+
+
+  "(аватар тоже был изменен)"
+  "%1$s сменили свой аватар"
+  "Вы сменили аватар"
+  "%1$s изменил свое отображаемое имя с %2$s на %3$s"
+  "Вы изменили свое отображаемое имя с %1$s на %2$s"
+  "%1$s удалил свое отображаемое имя (оно было %2$s)"
+  "Вы удалили свое отображаемое имя (оно было %1$s)"
+  "%1$s установили свое отображаемое имя на %2$s"
+  "Вы установили отображаемое имя на %1$s"
+  "%1$s изменил аватар комнаты"
+  "Вы изменили аватар комнаты"
+  "%1$s удалил аватар комнаты"
+  "Вы удалили аватар комнаты"
+  "%1$s заблокирован %2$s"
+  "Вы заблокировали %1$s"
+  "%1$s создал комнату"
+  "Вы создали комнату"
+  "%1$s пригласил %2$s"
+  "%1$s принял приглашение"
+  "Вы приняли приглашение"
+  "Вы пригласили %1$s"
+  "Пользователь %1$s пригласил вас"
+  "%1$s присоединился к комнате"
+  "Вы вошли в комнату"
+  "%1$s запросил присоединение"
+  "%1$s разрешил %2$s присоединиться"
+  "%1$s разрешил вам присоединиться"
+  "Вы запросили присоединение"
+  "%1$s отклонил запрос %2$s на присоединение"
+  "Вы отклонили запрос %1$s на присоединение"
+  "%1$s отклонил ваш запрос на присоединение"
+  "%1$s больше не заинтересован в присоединении"
+  "Вы отменили запрос на присоединение"
+  "%1$s покинул комнату"
+  "Вы вышли из комнаты"
+  "%1$s изменил название комнаты на: %2$s"
+  "Вы изменили название комнаты на: %1$s"
+  "%1$s удалил название комнаты"
+  "Вы удалили название комнаты"
+  "%1$s отклонил приглашение"
+  "Вы отклонили приглашение"
+  "%1$s удалил %2$s"
+  "Вы удалили %1$s"
+  "%1$s отправила приглашение %2$s присоединиться к комнате"
+  "Вы отправили приглашение присоединиться к комнате %1$s"
+  "%1$s отозвал приглашение %2$s присоединиться к комнате"
+  "Вы отозвали приглашение %1$s присоединиться к комнате"
+  "%1$s изменил тему на: %2$s"
+  "Вы изменили тему на: %1$s"
+  "%1$s удалил тему комнаты"
+  "Вы удалили тему комнаты"
+  "%1$s разблокирован %2$s"
+  "Вы разблокировали %1$s"
+  "%1$s внес неизвестное изменение в составе"
+
diff --git a/libraries/eventformatter/impl/src/main/res/values-zh-rTW/translations.xml b/libraries/eventformatter/impl/src/main/res/values-zh-rTW/translations.xml
new file mode 100644
index 0000000000..45ab0acee1
--- /dev/null
+++ b/libraries/eventformatter/impl/src/main/res/values-zh-rTW/translations.xml
@@ -0,0 +1,37 @@
+
+
+  "%1$s將他的顯示名稱從%2$s變更為%3$s"
+  "您將您的顯示名稱從%1$s1變更為%2$s"
+  "%1$s的顯示名稱已被本人移除(原為%2$s)"
+  "您的顯示名稱已被您移除(原為%1$s)"
+  "%1$s將他的顯示名稱設為%2$s"
+  "您將您的顯示名稱設為%1$s"
+  "%1$s建立此聊天室"
+  "您建立此聊天室"
+  "%1$s邀請%2$s"
+  "%1$s接受邀請"
+  "您接受邀請"
+  "您邀請%1$s"
+  "%1$s邀請您"
+  "%1$s加入聊天室"
+  "您加入聊天室"
+  "%1$s請求加入"
+  "您請求加入"
+  "%1$s拒絕%2$s的加入請求"
+  "您拒絕%1$s的加入請求"
+  "%1$s拒絕您的加入請求"
+  "%1$s離開聊天室"
+  "您離開聊天室"
+  "%1$s將聊天室名稱變更為%2$s"
+  "您將聊天室名稱變更為%1$s"
+  "聊天室名稱已被%1$s移除"
+  "聊天室名稱已被您移除"
+  "%2$s已被%1$s移除"
+  "%1$s已被您移除"
+  "%1$s邀請%2$s加入聊天室"
+  "您邀請%1$s加入聊天室"
+  "%1$s將主題變更為%2$s"
+  "您將主題變更為%1$s"
+  "聊天室主題已被%1$s移除"
+  "聊天室主題已被您移除"
+
diff --git a/libraries/featureflag/api/src/main/kotlin/io/element/android/libraries/featureflag/api/FeatureFlags.kt b/libraries/featureflag/api/src/main/kotlin/io/element/android/libraries/featureflag/api/FeatureFlags.kt
index 920be09389..4c1bfed33a 100644
--- a/libraries/featureflag/api/src/main/kotlin/io/element/android/libraries/featureflag/api/FeatureFlags.kt
+++ b/libraries/featureflag/api/src/main/kotlin/io/element/android/libraries/featureflag/api/FeatureFlags.kt
@@ -22,16 +22,8 @@ enum class FeatureFlags(
     override val description: String? = null,
     override val defaultValue: Boolean = true
 ) : Feature {
-    CollapseRoomStateEvents(
-        key = "feature.collapseroomstateevents",
-        title = "Collapse room state events",
-    ),
-    ShowStartChatFlow(
-        key = "feature.showstartchatflow",
-        title = "Show start chat flow",
-    ),
-    ShowMediaUploadingFlow(
-        key = "feature.showmediauploadingflow",
-        title = "Show media uploading flow",
+    LocationSharing(
+        key = "feature.locationsharing",
+        title = "Allow user to share location",
     )
 }
diff --git a/libraries/featureflag/impl/src/main/kotlin/io/element/android/libraries/featureflag/impl/BuildtimeFeatureFlagProvider.kt b/libraries/featureflag/impl/src/main/kotlin/io/element/android/libraries/featureflag/impl/BuildtimeFeatureFlagProvider.kt
index ae498e67df..d226885495 100644
--- a/libraries/featureflag/impl/src/main/kotlin/io/element/android/libraries/featureflag/impl/BuildtimeFeatureFlagProvider.kt
+++ b/libraries/featureflag/impl/src/main/kotlin/io/element/android/libraries/featureflag/impl/BuildtimeFeatureFlagProvider.kt
@@ -29,9 +29,7 @@ class BuildtimeFeatureFlagProvider @Inject constructor() :
     override suspend fun isFeatureEnabled(feature: Feature): Boolean {
         return if (feature is FeatureFlags) {
             when (feature) {
-                FeatureFlags.CollapseRoomStateEvents -> false
-                FeatureFlags.ShowStartChatFlow -> false
-                FeatureFlags.ShowMediaUploadingFlow -> false
+                FeatureFlags.LocationSharing -> true
             }
         } else {
             false
diff --git a/libraries/featureflag/impl/src/test/kotlin/io/element/android/libraries/featureflag/impl/DefaultFeatureFlagServiceTest.kt b/libraries/featureflag/impl/src/test/kotlin/io/element/android/libraries/featureflag/impl/DefaultFeatureFlagServiceTest.kt
index 5f7f01423a..ea9b03acdf 100644
--- a/libraries/featureflag/impl/src/test/kotlin/io/element/android/libraries/featureflag/impl/DefaultFeatureFlagServiceTest.kt
+++ b/libraries/featureflag/impl/src/test/kotlin/io/element/android/libraries/featureflag/impl/DefaultFeatureFlagServiceTest.kt
@@ -26,14 +26,14 @@ class DefaultFeatureFlagServiceTest {
     @Test
     fun `given service without provider when feature is checked then it returns the default value`() = runTest {
         val featureFlagService = DefaultFeatureFlagService(emptySet())
-        val isFeatureEnabled = featureFlagService.isFeatureEnabled(FeatureFlags.ShowStartChatFlow)
-        assertThat(isFeatureEnabled).isEqualTo(FeatureFlags.ShowStartChatFlow.defaultValue)
+        val isFeatureEnabled = featureFlagService.isFeatureEnabled(FeatureFlags.LocationSharing)
+        assertThat(isFeatureEnabled).isEqualTo(FeatureFlags.LocationSharing.defaultValue)
     }
 
     @Test
     fun `given service without provider when set enabled feature is called then it returns false`() = runTest {
         val featureFlagService = DefaultFeatureFlagService(emptySet())
-        val result = featureFlagService.setFeatureEnabled(FeatureFlags.ShowStartChatFlow, true)
+        val result = featureFlagService.setFeatureEnabled(FeatureFlags.LocationSharing, true)
         assertThat(result).isEqualTo(false)
     }
 
@@ -41,7 +41,7 @@ class DefaultFeatureFlagServiceTest {
     fun `given service with a runtime provider when set enabled feature is called then it returns true`() = runTest {
         val featureFlagProvider = FakeRuntimeFeatureFlagProvider(0)
         val featureFlagService = DefaultFeatureFlagService(setOf(featureFlagProvider))
-        val result = featureFlagService.setFeatureEnabled(FeatureFlags.ShowStartChatFlow, true)
+        val result = featureFlagService.setFeatureEnabled(FeatureFlags.LocationSharing, true)
         assertThat(result).isEqualTo(true)
     }
 
@@ -49,10 +49,10 @@ class DefaultFeatureFlagServiceTest {
     fun `given service with a runtime provider and feature enabled when feature is checked then it returns the correct value`() = runTest {
         val featureFlagProvider = FakeRuntimeFeatureFlagProvider(0)
         val featureFlagService = DefaultFeatureFlagService(setOf(featureFlagProvider))
-        featureFlagService.setFeatureEnabled(FeatureFlags.ShowStartChatFlow, true)
-        assertThat(featureFlagService.isFeatureEnabled(FeatureFlags.ShowStartChatFlow)).isEqualTo(true)
-        featureFlagService.setFeatureEnabled(FeatureFlags.ShowStartChatFlow, false)
-        assertThat(featureFlagService.isFeatureEnabled(FeatureFlags.ShowStartChatFlow)).isEqualTo(false)
+        featureFlagService.setFeatureEnabled(FeatureFlags.LocationSharing, true)
+        assertThat(featureFlagService.isFeatureEnabled(FeatureFlags.LocationSharing)).isEqualTo(true)
+        featureFlagService.setFeatureEnabled(FeatureFlags.LocationSharing, false)
+        assertThat(featureFlagService.isFeatureEnabled(FeatureFlags.LocationSharing)).isEqualTo(false)
     }
 
     @Test
@@ -60,8 +60,8 @@ class DefaultFeatureFlagServiceTest {
         val lowPriorityfeatureFlagProvider = FakeRuntimeFeatureFlagProvider(LOW_PRIORITY)
         val highPriorityfeatureFlagProvider = FakeRuntimeFeatureFlagProvider(HIGH_PRIORITY)
         val featureFlagService = DefaultFeatureFlagService(setOf(lowPriorityfeatureFlagProvider, highPriorityfeatureFlagProvider))
-        lowPriorityfeatureFlagProvider.setFeatureEnabled(FeatureFlags.ShowStartChatFlow, false)
-        highPriorityfeatureFlagProvider.setFeatureEnabled(FeatureFlags.ShowStartChatFlow, true)
-        assertThat(featureFlagService.isFeatureEnabled(FeatureFlags.ShowStartChatFlow)).isEqualTo(true)
+        lowPriorityfeatureFlagProvider.setFeatureEnabled(FeatureFlags.LocationSharing, false)
+        highPriorityfeatureFlagProvider.setFeatureEnabled(FeatureFlags.LocationSharing, true)
+        assertThat(featureFlagService.isFeatureEnabled(FeatureFlags.LocationSharing)).isEqualTo(true)
     }
 }
diff --git a/libraries/maplibre-compose/src/main/kotlin/io/element/android/libraries/maplibre/compose/MapLocationSettings.kt b/libraries/maplibre-compose/src/main/kotlin/io/element/android/libraries/maplibre/compose/MapLocationSettings.kt
index 4b7b7005f2..69e0e9b1d4 100644
--- a/libraries/maplibre-compose/src/main/kotlin/io/element/android/libraries/maplibre/compose/MapLocationSettings.kt
+++ b/libraries/maplibre-compose/src/main/kotlin/io/element/android/libraries/maplibre/compose/MapLocationSettings.kt
@@ -18,6 +18,8 @@
 
 package io.element.android.libraries.maplibre.compose
 
+import androidx.compose.ui.graphics.Color
+
 internal val DefaultMapLocationSettings = MapLocationSettings()
 
 /**
@@ -28,4 +30,11 @@ internal val DefaultMapLocationSettings = MapLocationSettings()
  */
 public data class MapLocationSettings(
     public val locationEnabled: Boolean = false,
+    public val backgroundTintColor: Color = Color.Unspecified,
+    public val foregroundTintColor: Color = Color.Unspecified,
+    public val backgroundStaleTintColor: Color = Color.Unspecified,
+    public val foregroundStaleTintColor: Color = Color.Unspecified,
+    public val accuracyColor: Color = Color.Unspecified,
+    public val pulseEnabled: Boolean = false,
+    public val pulseColor: Color = Color.Unspecified
 )
diff --git a/libraries/maplibre-compose/src/main/kotlin/io/element/android/libraries/maplibre/compose/MapUpdater.kt b/libraries/maplibre-compose/src/main/kotlin/io/element/android/libraries/maplibre/compose/MapUpdater.kt
index d7d5f9ca11..e4e3565f22 100644
--- a/libraries/maplibre-compose/src/main/kotlin/io/element/android/libraries/maplibre/compose/MapUpdater.kt
+++ b/libraries/maplibre-compose/src/main/kotlin/io/element/android/libraries/maplibre/compose/MapUpdater.kt
@@ -39,6 +39,7 @@ internal class MapPropertiesNode(
     style: Style,
     context: Context,
     cameraPositionState: CameraPositionState,
+    locationSettings: MapLocationSettings,
 ) : MapNode {
 
     init {
@@ -46,7 +47,13 @@ internal class MapPropertiesNode(
             LocationComponentActivationOptions.Builder(context, style)
                 .locationComponentOptions(
                     LocationComponentOptions.builder(context)
-                        .pulseEnabled(true)
+                        .backgroundTintColor(locationSettings.backgroundTintColor.toArgb())
+                        .foregroundTintColor(locationSettings.foregroundTintColor.toArgb())
+                        .backgroundStaleTintColor(locationSettings.backgroundStaleTintColor.toArgb())
+                        .foregroundStaleTintColor(locationSettings.foregroundStaleTintColor.toArgb())
+                        .accuracyColor(locationSettings.accuracyColor.toArgb())
+                        .pulseEnabled(locationSettings.pulseEnabled)
+                        .pulseColor(locationSettings.pulseColor.toArgb())
                         .build()
                 )
                 .locationEngineRequest(
@@ -116,9 +123,9 @@ internal class MapPropertiesNode(
 @Composable
 internal inline fun MapUpdater(
     cameraPositionState: CameraPositionState,
-    mapLocationSettings: MapLocationSettings,
-    mapUiSettings: MapUiSettings,
-    mapSymbolManagerSettings: MapSymbolManagerSettings,
+    locationSettings: MapLocationSettings,
+    uiSettings: MapUiSettings,
+    symbolManagerSettings: MapSymbolManagerSettings,
 ) {
     val mapApplier = currentComposer.applier as MapApplier
     val map = mapApplier.map
@@ -132,21 +139,22 @@ internal inline fun MapUpdater(
                 style = style,
                 context = context,
                 cameraPositionState = cameraPositionState,
+                locationSettings = locationSettings,
             )
         },
         update = {
-            set(mapLocationSettings.locationEnabled) { map.locationComponent.isLocationComponentEnabled = it }
+            set(locationSettings.locationEnabled) { map.locationComponent.isLocationComponentEnabled = it }
 
-            set(mapUiSettings.compassEnabled) { map.uiSettings.isCompassEnabled = it }
-            set(mapUiSettings.rotationGesturesEnabled) { map.uiSettings.isRotateGesturesEnabled = it }
-            set(mapUiSettings.scrollGesturesEnabled) { map.uiSettings.isScrollGesturesEnabled = it }
-            set(mapUiSettings.tiltGesturesEnabled) { map.uiSettings.isTiltGesturesEnabled = it }
-            set(mapUiSettings.zoomGesturesEnabled) { map.uiSettings.isZoomGesturesEnabled = it }
-            set(mapUiSettings.logoGravity) { map.uiSettings.logoGravity = it }
-            set(mapUiSettings.attributionGravity) { map.uiSettings.attributionGravity = it }
-            set(mapUiSettings.attributionTintColor) { map.uiSettings.setAttributionTintColor(it.toArgb()) }
+            set(uiSettings.compassEnabled) { map.uiSettings.isCompassEnabled = it }
+            set(uiSettings.rotationGesturesEnabled) { map.uiSettings.isRotateGesturesEnabled = it }
+            set(uiSettings.scrollGesturesEnabled) { map.uiSettings.isScrollGesturesEnabled = it }
+            set(uiSettings.tiltGesturesEnabled) { map.uiSettings.isTiltGesturesEnabled = it }
+            set(uiSettings.zoomGesturesEnabled) { map.uiSettings.isZoomGesturesEnabled = it }
+            set(uiSettings.logoGravity) { map.uiSettings.logoGravity = it }
+            set(uiSettings.attributionGravity) { map.uiSettings.attributionGravity = it }
+            set(uiSettings.attributionTintColor) { map.uiSettings.setAttributionTintColor(it.toArgb()) }
 
-            set(mapSymbolManagerSettings.iconAllowOverlap) { symbolManager.iconAllowOverlap = it }
+            set(symbolManagerSettings.iconAllowOverlap) { symbolManager.iconAllowOverlap = it }
 
             update(cameraPositionState) { this.cameraPositionState = it }
         }
diff --git a/libraries/maplibre-compose/src/main/kotlin/io/element/android/libraries/maplibre/compose/MapboxMap.kt b/libraries/maplibre-compose/src/main/kotlin/io/element/android/libraries/maplibre/compose/MapboxMap.kt
index 3c3cf3e44f..5af79e7524 100644
--- a/libraries/maplibre-compose/src/main/kotlin/io/element/android/libraries/maplibre/compose/MapboxMap.kt
+++ b/libraries/maplibre-compose/src/main/kotlin/io/element/android/libraries/maplibre/compose/MapboxMap.kt
@@ -124,9 +124,9 @@ public fun MapboxMap(
             ) {
                 MapUpdater(
                     cameraPositionState = currentCameraPositionState,
-                    mapUiSettings = currentUiSettings,
-                    mapLocationSettings = currentMapLocationSettings,
-                    mapSymbolManagerSettings = currentSymbolManagerSettings,
+                    uiSettings = currentUiSettings,
+                    locationSettings = currentMapLocationSettings,
+                    symbolManagerSettings = currentSymbolManagerSettings,
                 )
                 CompositionLocalProvider(
                     LocalCameraPositionState provides cameraPositionState,
@@ -236,7 +236,7 @@ private fun MapView.lifecycleObserver(previousState: MutableState {
                 //handled in onDispose
             }
-            else -> throw IllegalStateException()
+            Lifecycle.Event.ON_ANY -> error("ON_ANY should never be used")
         }
         previousState.value = event
     }
diff --git a/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/MatrixClient.kt b/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/MatrixClient.kt
index 747de5f554..67c0625a91 100644
--- a/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/MatrixClient.kt
+++ b/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/MatrixClient.kt
@@ -26,7 +26,7 @@ import io.element.android.libraries.matrix.api.notification.NotificationService
 import io.element.android.libraries.matrix.api.pusher.PushersService
 import io.element.android.libraries.matrix.api.room.MatrixRoom
 import io.element.android.libraries.matrix.api.room.RoomMembershipObserver
-import io.element.android.libraries.matrix.api.room.RoomSummaryDataSource
+import io.element.android.libraries.matrix.api.roomlist.RoomListService
 import io.element.android.libraries.matrix.api.sync.SyncService
 import io.element.android.libraries.matrix.api.user.MatrixSearchUserResults
 import io.element.android.libraries.matrix.api.user.MatrixUser
@@ -35,7 +35,7 @@ import java.io.Closeable
 
 interface MatrixClient : Closeable {
     val sessionId: SessionId
-    val roomSummaryDataSource: RoomSummaryDataSource
+    val roomListService: RoomListService
     val mediaLoader: MatrixMediaLoader
     suspend fun getRoom(roomId: RoomId): MatrixRoom?
     suspend fun findDM(userId: UserId): MatrixRoom?
diff --git a/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/auth/AuthenticationException.kt b/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/auth/AuthenticationException.kt
index e670e02f11..48712b7ddf 100644
--- a/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/auth/AuthenticationException.kt
+++ b/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/auth/AuthenticationException.kt
@@ -22,5 +22,6 @@ sealed class AuthenticationException(message: String) : Exception(message) {
     class SlidingSyncNotAvailable(message: String) : AuthenticationException(message)
     class SessionMissing(message: String) : AuthenticationException(message)
     class Generic(message: String) : AuthenticationException(message)
-    class OidcError(type: String, message: String) : AuthenticationException(message)
+    // TODO Oidc
+    // class OidcError(type: String, message: String) : AuthenticationException(message)
 }
diff --git a/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/core/MatrixPatterns.kt b/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/core/MatrixPatterns.kt
index bc0f0c04bc..a668448752 100644
--- a/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/core/MatrixPatterns.kt
+++ b/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/core/MatrixPatterns.kt
@@ -30,7 +30,8 @@ object MatrixPatterns {
 
     // regex pattern to find matrix user ids in a string.
     // See https://matrix.org/docs/spec/appendices#historical-user-ids
-    private const val MATRIX_USER_IDENTIFIER_REGEX = "@[A-Z0-9\\x21-\\x39\\x3B-\\x7F]+$DOMAIN_REGEX"
+    // Sadly, we need to relax the regex pattern a bit as there already exist some ids that don't match the spec.
+    private const val MATRIX_USER_IDENTIFIER_REGEX = "^@.*?$DOMAIN_REGEX$"
     val PATTERN_CONTAIN_MATRIX_USER_IDENTIFIER = MATRIX_USER_IDENTIFIER_REGEX.toRegex(RegexOption.IGNORE_CASE)
 
     // regex pattern to find room ids in a string.
@@ -42,7 +43,8 @@ object MatrixPatterns {
     private val PATTERN_CONTAIN_MATRIX_ALIAS = MATRIX_ROOM_ALIAS_REGEX.toRegex(RegexOption.IGNORE_CASE)
 
     // regex pattern to find message ids in a string.
-    private const val MATRIX_EVENT_IDENTIFIER_REGEX = "\\$[A-Z0-9]+$DOMAIN_REGEX"
+    // Sadly, we need to relax the regex pattern a bit as there already exist some ids that don't match the spec.
+    private const val MATRIX_EVENT_IDENTIFIER_REGEX = "^\\$.+$DOMAIN_REGEX$"
     private val PATTERN_CONTAIN_MATRIX_EVENT_IDENTIFIER = MATRIX_EVENT_IDENTIFIER_REGEX.toRegex(RegexOption.IGNORE_CASE)
 
     // regex pattern to find message ids in a string.
diff --git a/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/notification/NotificationData.kt b/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/notification/NotificationData.kt
index 4ded947d56..639509a15a 100644
--- a/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/notification/NotificationData.kt
+++ b/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/notification/NotificationData.kt
@@ -23,7 +23,6 @@ import io.element.android.libraries.matrix.api.room.RoomMembershipState
 import io.element.android.libraries.matrix.api.timeline.item.event.MessageType
 
 data class NotificationData(
-    val senderId: UserId,
     val eventId: EventId,
     val roomId: RoomId,
     val senderAvatarUrl: String?,
@@ -33,14 +32,10 @@ data class NotificationData(
     val isDirect: Boolean,
     val isEncrypted: Boolean,
     val isNoisy: Boolean,
-    val event: NotificationEvent,
-)
-
-data class NotificationEvent(
     val timestamp: Long,
     val content: NotificationContent,
     // For images for instance
-    val contentUrl: String?
+    val contentUrl: String?,
 )
 
 sealed interface NotificationContent {
@@ -61,6 +56,7 @@ sealed interface NotificationContent {
         ) : MessageLike
         object RoomEncrypted : MessageLike
         data class RoomMessage(
+            val senderId: UserId,
             val messageType: MessageType
         ) : MessageLike
         object RoomRedaction : MessageLike
diff --git a/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/notification/NotificationService.kt b/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/notification/NotificationService.kt
index 2046252930..972873ab38 100644
--- a/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/notification/NotificationService.kt
+++ b/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/notification/NotificationService.kt
@@ -21,5 +21,5 @@ import io.element.android.libraries.matrix.api.core.RoomId
 import io.element.android.libraries.matrix.api.core.SessionId
 
 interface NotificationService {
-    fun getNotification(userId: SessionId, roomId: RoomId, eventId: EventId, filterByPushRules: Boolean): Result
+    suspend fun getNotification(userId: SessionId, roomId: RoomId, eventId: EventId): Result
 }
diff --git a/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/permalink/PermalinkBuilder.kt b/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/permalink/PermalinkBuilder.kt
index 6a15bfb514..31e28a40db 100644
--- a/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/permalink/PermalinkBuilder.kt
+++ b/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/permalink/PermalinkBuilder.kt
@@ -25,7 +25,6 @@ object PermalinkBuilder {
 
     private const val ROOM_PATH = "room/"
     private const val USER_PATH = "user/"
-    private const val GROUP_PATH = "group/"
 
     private val permalinkBaseUrl get() = (MatrixConfiguration.clientPermalinkBaseUrl ?: MatrixConfiguration.matrixToPermalinkBaseUrl).also {
         var baseUrl = it
diff --git a/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/permalink/PermalinkParser.kt b/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/permalink/PermalinkParser.kt
index fc900e4bbb..ba9cdc1e80 100644
--- a/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/permalink/PermalinkParser.kt
+++ b/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/permalink/PermalinkParser.kt
@@ -95,9 +95,9 @@ object PermalinkParser {
         return if (signUrl.isNullOrEmpty().not() && email.isNullOrEmpty().not()) {
             try {
                 val signValidUri = Uri.parse(signUrl)
-                val identityServerHost = signValidUri.authority ?: throw IllegalArgumentException()
-                val token = signValidUri.getQueryParameter("token") ?: throw IllegalArgumentException()
-                val privateKey = signValidUri.getQueryParameter("private_key") ?: throw IllegalArgumentException()
+                val identityServerHost = signValidUri.authority ?: throw IllegalArgumentException("missing `authority`")
+                val token = signValidUri.getQueryParameter("token") ?: throw IllegalArgumentException("missing `token`")
+                val privateKey = signValidUri.getQueryParameter("private_key") ?: throw IllegalArgumentException("missing `private_key`")
                 PermalinkData.RoomEmailInviteLink(
                     roomId = identifier,
                     email = email!!,
@@ -137,7 +137,8 @@ object PermalinkParser {
             .parameterList
             .filter {
                 it.mParameter == "via"
-            }.map {
+            }
+            .map {
                 URLDecoder.decode(it.mValue, "UTF-8")
             }
     }
diff --git a/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/poll/PollAnswer.kt b/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/poll/PollAnswer.kt
new file mode 100644
index 0000000000..2d4abaafb5
--- /dev/null
+++ b/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/poll/PollAnswer.kt
@@ -0,0 +1,22 @@
+/*
+ * Copyright (c) 2023 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
+ *
+ *     http://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.api.poll
+
+data class PollAnswer(
+    val id: String,
+    val text: String
+)
diff --git a/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/poll/PollKind.kt b/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/poll/PollKind.kt
new file mode 100644
index 0000000000..85bb7c0256
--- /dev/null
+++ b/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/poll/PollKind.kt
@@ -0,0 +1,24 @@
+/*
+ * Copyright (c) 2023 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
+ *
+ *     http://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.api.poll
+
+enum class PollKind {
+    /** Voters should see results as soon as they have voted. */
+    Disclosed,
+
+    /** Results should be only revealed when the poll is ended. */
+    Undisclosed
+}
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 be0ff447b3..f8b9e6c2c3 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
@@ -63,7 +63,11 @@ interface MatrixRoom : Closeable {
 
     val timeline: MatrixTimeline
 
-    fun open(): Result
+    fun destroy()
+
+    fun subscribeToSync()
+
+    fun unsubscribeFromSync()
 
     suspend fun userDisplayName(userId: UserId): Result
 
@@ -101,6 +105,8 @@ interface MatrixRoom : Closeable {
 
     suspend fun canUserInvite(userId: UserId): Result
 
+    suspend fun canUserRedact(userId: UserId): Result
+
     suspend fun canUserSendState(userId: UserId, type: StateEventType): Result
 
     suspend fun canUserSendMessage(userId: UserId, type: MessageEventType): Result
@@ -133,6 +139,8 @@ interface MatrixRoom : Closeable {
         zoomLevel: Int? = null,
         assetType: AssetType? = null,
     ): Result
+
+    override fun close() = destroy()
 }
 
 
diff --git a/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/room/powerlevels/MatrixRoomPowerLevels.kt b/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/room/powerlevels/MatrixRoomPowerLevels.kt
index 852401bffc..e0ba452efe 100644
--- a/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/room/powerlevels/MatrixRoomPowerLevels.kt
+++ b/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/room/powerlevels/MatrixRoomPowerLevels.kt
@@ -34,3 +34,9 @@ suspend fun MatrixRoom.canSendState(type: StateEventType): Result = can
  * Shortcut for calling [MatrixRoom.canUserSendMessage] with our own user.
  */
 suspend fun MatrixRoom.canSendMessage(type: MessageEventType): Result = canUserSendMessage(sessionId, type)
+
+/**
+ * Shortcut for calling [MatrixRoom.canUserRedact] with our own user.
+ */
+suspend fun MatrixRoom.canRedact(): Result = canUserRedact(sessionId)
+
diff --git a/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/room/RoomSummaryDataSource.kt b/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/roomlist/RoomList.kt
similarity index 65%
rename from libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/room/RoomSummaryDataSource.kt
rename to libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/roomlist/RoomList.kt
index d677d56ed9..8714bc2c5c 100644
--- a/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/room/RoomSummaryDataSource.kt
+++ b/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/roomlist/RoomList.kt
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-package io.element.android.libraries.matrix.api.room
+package io.element.android.libraries.matrix.api.roomlist
 
 import kotlinx.coroutines.TimeoutCancellationException
 import kotlinx.coroutines.flow.StateFlow
@@ -23,25 +23,34 @@ import kotlinx.coroutines.withTimeout
 import timber.log.Timber
 import kotlin.time.Duration
 
-interface RoomSummaryDataSource {
-
+/**
+ * Holds some flows related to a specific set of rooms.
+ * Can be retrieved from [RoomListService] methods.
+ */
+interface RoomList {
     sealed class LoadingState {
         object NotLoaded : LoadingState()
         data class Loaded(val numberOfRooms: Int) : LoadingState()
     }
 
-    fun updateAllRoomsVisibleRange(range: IntRange)
-    fun allRoomsLoadingState(): StateFlow
-    fun allRooms(): StateFlow>
-    fun inviteRooms(): StateFlow>
+    /**
+     * The list of room summaries as a flow.
+     */
+    val summaries: StateFlow>
+
+    /**
+     * The loading state of the room list as a flow.
+     * This is useful to know if a specific set of rooms is loaded or not.
+     */
+    val loadingState: StateFlow
 }
 
-suspend fun RoomSummaryDataSource.awaitAllRoomsAreLoaded(timeout: Duration = Duration.INFINITE) {
+suspend fun RoomList.awaitLoaded(timeout: Duration = Duration.INFINITE) {
     try {
         Timber.d("awaitAllRoomsAreLoaded: wait")
         withTimeout(timeout) {
-            allRoomsLoadingState().firstOrNull {
-                it is RoomSummaryDataSource.LoadingState.Loaded
+            loadingState.firstOrNull {
+                it is RoomList.LoadingState.Loaded
             }
         }
     } catch (timeoutException: TimeoutCancellationException) {
diff --git a/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/roomlist/RoomListService.kt b/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/roomlist/RoomListService.kt
new file mode 100644
index 0000000000..99381d0e74
--- /dev/null
+++ b/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/roomlist/RoomListService.kt
@@ -0,0 +1,56 @@
+/*
+ * Copyright (c) 2023 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
+ *
+ *     http://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.api.roomlist
+
+import kotlinx.coroutines.flow.StateFlow
+
+/**
+ * Entry point for the room list api.
+ * This service will provide different sets of rooms (all, invites, etc.).
+ * It requires the SyncService to be started to receive updates.
+ */
+interface RoomListService {
+
+    sealed class State {
+        object Idle : State()
+        object Running : State()
+        object Error : State()
+        object Terminated : State()
+    }
+
+    /**
+     * returns a [RoomList] object of all rooms we want to display.
+     * This will exclude some rooms like the invites, or spaces.
+     */
+    fun allRooms(): RoomList
+
+    /**
+     * returns a [RoomList] object of all invites.
+     */
+    fun invites(): RoomList
+
+    /**
+     * Will set the visible range of all rooms.
+     * This is useful to load more data when the user scrolls down.
+     */
+    fun updateAllRoomsVisibleRange(range: IntRange)
+
+    /**
+     * The state of the service as a flow.
+     */
+    val state: StateFlow
+}
diff --git a/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/room/RoomSummary.kt b/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/roomlist/RoomSummary.kt
similarity index 92%
rename from libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/room/RoomSummary.kt
rename to libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/roomlist/RoomSummary.kt
index 7dedd86b63..87cf2139d6 100644
--- a/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/room/RoomSummary.kt
+++ b/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/roomlist/RoomSummary.kt
@@ -14,9 +14,10 @@
  * limitations under the License.
  */
 
-package io.element.android.libraries.matrix.api.room
+package io.element.android.libraries.matrix.api.roomlist
 
 import io.element.android.libraries.matrix.api.core.RoomId
+import io.element.android.libraries.matrix.api.room.RoomMember
 import io.element.android.libraries.matrix.api.room.message.RoomMessage
 
 sealed interface RoomSummary {
diff --git a/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/sync/SyncService.kt b/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/sync/SyncService.kt
index 5271ec9bc0..994b35edc4 100644
--- a/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/sync/SyncService.kt
+++ b/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/sync/SyncService.kt
@@ -27,7 +27,7 @@ interface SyncService {
     /**
      * Tries to stop the sync. If service is not syncing it has no effect.
      */
-    fun stopSync(): Result
+    suspend fun stopSync(): Result
 
     /**
      * Flow of [SyncState]. Will be updated as soon as the current [SyncState] changes.
diff --git a/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/timeline/item/event/EventContent.kt b/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/timeline/item/event/EventContent.kt
index 203fb30794..82c322668c 100644
--- a/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/timeline/item/event/EventContent.kt
+++ b/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/timeline/item/event/EventContent.kt
@@ -23,6 +23,8 @@ import io.element.android.libraries.matrix.api.media.FileInfo
 import io.element.android.libraries.matrix.api.media.ImageInfo
 import io.element.android.libraries.matrix.api.media.MediaSource
 import io.element.android.libraries.matrix.api.media.VideoInfo
+import io.element.android.libraries.matrix.api.poll.PollAnswer
+import io.element.android.libraries.matrix.api.poll.PollKind
 
 sealed interface EventContent
 
@@ -44,7 +46,7 @@ sealed interface InReplyTo {
     /** The event details are available. */
     data class Ready(
         val eventId: EventId,
-        val content: MessageContent,
+        val content: EventContent,
         val senderId: UserId,
         val senderDisplayName: String?,
         val senderAvatarUrl: String?,
@@ -69,6 +71,19 @@ data class StickerContent(
     val url: String
 ) : EventContent
 
+data class PollContent(
+    val question: String,
+    val kind: PollKind,
+    val maxSelections: ULong,
+    val answers: List,
+    val votes: Map>,
+    val endTime: ULong?
+) : EventContent
+
+data class PollEndContent(
+    val startEventId: String
+) : EventContent
+
 data class UnableToDecryptContent(
     val data: Data
 ) : EventContent {
diff --git a/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/timeline/item/event/EventReaction.kt b/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/timeline/item/event/EventReaction.kt
index 8bea4b5330..a2e68d17d2 100644
--- a/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/timeline/item/event/EventReaction.kt
+++ b/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/timeline/item/event/EventReaction.kt
@@ -16,10 +16,7 @@
 
 package io.element.android.libraries.matrix.api.timeline.item.event
 
-import io.element.android.libraries.matrix.api.core.UserId
-
 data class EventReaction(
     val key: String,
-    val count: Long,
-    val senderIds: List
+    val senders: List
 )
diff --git a/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/timeline/item/event/ReactionSender.kt b/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/timeline/item/event/ReactionSender.kt
new file mode 100644
index 0000000000..60398cffd5
--- /dev/null
+++ b/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/timeline/item/event/ReactionSender.kt
@@ -0,0 +1,31 @@
+/*
+ * Copyright (c) 2023 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
+ *
+ *     http://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.api.timeline.item.event
+
+import io.element.android.libraries.matrix.api.core.UserId
+
+/**
+ * The sender of a reaction.
+ *
+ * @property senderId the ID of the user who sent the reaction
+ * @property timestamp the timestamp the reaction was received on the origin homeserver
+ */
+data class ReactionSender(
+    val senderId: UserId,
+    val timestamp: Long
+)
+
diff --git a/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/tracing/TracingConfiguration.kt b/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/tracing/TracingConfiguration.kt
index 8bcd602b9f..6381cc7ed8 100644
--- a/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/tracing/TracingConfiguration.kt
+++ b/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/tracing/TracingConfiguration.kt
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2022 New Vector Ltd
+ * Copyright (c) 2023 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.
@@ -17,64 +17,7 @@
 package io.element.android.libraries.matrix.api.tracing
 
 data class TracingConfiguration(
-    val overrides: Map = emptyMap()
-) {
-
-    // Order should matters
-    private val targets: MutableMap = mutableMapOf(
-        Target.Common to LogLevel.Warn,
-        Target.Hyper to LogLevel.Warn,
-        Target.Sled to LogLevel.Warn,
-        Target.MatrixSdk.Root to LogLevel.Warn,
-        Target.MatrixSdk.Sled to LogLevel.Warn,
-        Target.MatrixSdk.Crypto to LogLevel.Debug,
-        Target.MatrixSdk.HttpClient to LogLevel.Debug,
-        Target.MatrixSdk.SlidingSync to LogLevel.Trace,
-        Target.MatrixSdk.BaseSlidingSync to LogLevel.Trace,
-    )
-
-    val filter: String
-        get() {
-            overrides.forEach { (target, logLevel) ->
-                targets[target] = logLevel
-            }
-            return targets.map {
-                if (it.key.filter.isEmpty()) {
-                    it.value.filter
-                } else {
-                    "${it.key.filter}=${it.value.filter}"
-                }
-            }.joinToString(separator = ",")
-        }
-}
-
-sealed class Target(open val filter: String) {
-    object Common : Target("")
-    object Hyper : Target("hyper")
-    object Sled : Target("sled")
-    sealed class MatrixSdk(override val filter: String) : Target(filter) {
-        object Root : MatrixSdk("matrix_sdk")
-        object Sled : MatrixSdk("matrix_sdk_sled")
-        object Crypto: MatrixSdk("matrix_sdk_crypto")
-        object FFI : MatrixSdk("matrix_sdk_ffi")
-        object HttpClient : MatrixSdk("matrix_sdk::http_client")
-        object UniffiAPI : MatrixSdk("matrix_sdk_ffi::uniffi_api")
-        object SlidingSync : MatrixSdk("matrix_sdk::sliding_sync")
-        object BaseSlidingSync : MatrixSdk("matrix_sdk_base::sliding_sync")
-    }
-}
-
-sealed class LogLevel(val filter: String) {
-    object Warn : LogLevel("warn")
-    object Trace : LogLevel("trace")
-    object Info : LogLevel("info")
-    object Debug : LogLevel("debug")
-    object Error : LogLevel("error")
-}
-
-object TracingConfigurations {
-    val release = TracingConfiguration(overrides = mapOf(Target.Common to LogLevel.Info))
-    val debug = TracingConfiguration(overrides = mapOf(Target.Common to LogLevel.Info))
-
-    fun custom(overrides: Map) = TracingConfiguration(overrides)
-}
+    val filterConfiguration: TracingFilterConfiguration,
+    val writesToLogcat: Boolean,
+    val writesToFilesConfiguration: WriteToFilesConfiguration,
+)
diff --git a/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/tracing/TracingFilterConfiguration.kt b/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/tracing/TracingFilterConfiguration.kt
new file mode 100644
index 0000000000..21c6954c2a
--- /dev/null
+++ b/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/tracing/TracingFilterConfiguration.kt
@@ -0,0 +1,93 @@
+/*
+ * Copyright (c) 2022 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
+ *
+ *     http://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.api.tracing
+
+data class TracingFilterConfiguration(
+    val overrides: Map = emptyMap(),
+) {
+
+    // Order should matters
+    private val targetsToLogLevel: MutableMap = mutableMapOf(
+        Target.COMMON to LogLevel.Info,
+        Target.HYPER to LogLevel.Warn,
+        Target.MATRIX_SDK_CRYPTO to LogLevel.Debug,
+        Target.MATRIX_SDK_HTTP_CLIENT to LogLevel.Debug,
+        Target.MATRIX_SDK_SLIDING_SYNC to LogLevel.Trace,
+        Target.MATRIX_SDK_BASE_SLIDING_SYNC to LogLevel.Trace,
+        Target.MATRIX_SDK_UI_TIMELINE to LogLevel.Info,
+    )
+
+    val filter: String
+        get() {
+            overrides.forEach { (target, logLevel) ->
+                targetsToLogLevel[target] = logLevel
+            }
+            return targetsToLogLevel.map {
+                if (it.key.filter.isEmpty()) {
+                    it.value.filter
+                } else {
+                    "${it.key.filter}=${it.value.filter}"
+                }
+            }.joinToString(separator = ",")
+        }
+}
+
+enum class Target(open val filter: String) {
+    COMMON(""),
+    ELEMENT("elementx"),
+    HYPER("hyper"),
+    MATRIX_SDK_FFI("matrix_sdk_ffi"),
+    MATRIX_SDK_UNIFFI_API("matrix_sdk_ffi::uniffi_api"),
+    MATRIX_SDK_CRYPTO("matrix_sdk_crypto"),
+    MATRIX_SDK_HTTP_CLIENT("matrix_sdk::http_client"),
+    MATRIX_SDK_SLIDING_SYNC("matrix_sdk::sliding_sync"),
+    MATRIX_SDK_BASE_SLIDING_SYNC("matrix_sdk_base::sliding_sync"),
+    MATRIX_SDK_UI_TIMELINE("matrix_sdk_ui::timeline"),
+}
+
+sealed class LogLevel(val filter: String) {
+    object Warn : LogLevel("warn")
+    object Trace : LogLevel("trace")
+    object Info : LogLevel("info")
+    object Debug : LogLevel("debug")
+    object Error : LogLevel("error")
+}
+
+object TracingFilterConfigurations {
+    val release = TracingFilterConfiguration(
+        overrides = mapOf(
+            Target.COMMON to LogLevel.Info,
+            Target.ELEMENT to LogLevel.Debug
+        ),
+    )
+    val debug = TracingFilterConfiguration(
+        overrides = mapOf(
+            Target.COMMON to LogLevel.Info,
+            Target.ELEMENT to LogLevel.Trace
+        )
+    )
+
+    /**
+     *  Use this method to create a custom configuration where all targets will have the same log level.
+     */
+    fun custom(logLevel: LogLevel) = TracingFilterConfiguration(overrides = Target.values().associateWith { logLevel })
+
+    /**
+     * Use this method to override the log level of specific targets.
+     */
+    fun custom(overrides: Map) = TracingFilterConfiguration(overrides)
+}
diff --git a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/tracing/TracingConfiguration.kt b/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/tracing/TracingService.kt
similarity index 60%
rename from libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/tracing/TracingConfiguration.kt
rename to libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/tracing/TracingService.kt
index f32b18c9f2..4a74f83b20 100644
--- a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/tracing/TracingConfiguration.kt
+++ b/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/tracing/TracingService.kt
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2022 New Vector Ltd
+ * Copyright (c) 2023 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.
@@ -14,13 +14,11 @@
  * limitations under the License.
  */
 
-package io.element.android.libraries.matrix.impl.tracing
+package io.element.android.libraries.matrix.api.tracing
 
-import io.element.android.libraries.matrix.api.tracing.TracingConfiguration
 import timber.log.Timber
 
-fun setupTracing(tracingConfiguration: TracingConfiguration) {
-    val filter = tracingConfiguration.filter
-    Timber.v("Tracing config filter = $filter")
-    org.matrix.rustcomponents.sdk.setupTracing(filter)
+interface TracingService {
+    fun setupTracing(tracingConfiguration: TracingConfiguration)
+    fun createTimberTree(): Timber.Tree
 }
diff --git a/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/tracing/WriteToFilesConfiguration.kt b/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/tracing/WriteToFilesConfiguration.kt
new file mode 100644
index 0000000000..cafa375a6a
--- /dev/null
+++ b/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/tracing/WriteToFilesConfiguration.kt
@@ -0,0 +1,22 @@
+/*
+ * Copyright (c) 2023 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
+ *
+ *     http://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.api.tracing
+
+sealed class WriteToFilesConfiguration {
+    object Disabled : WriteToFilesConfiguration()
+    data class Enabled(val directory: String, val filenamePrefix: String) : WriteToFilesConfiguration()
+}
diff --git a/libraries/matrix/impl/build.gradle.kts b/libraries/matrix/impl/build.gradle.kts
index 7786a3ee3f..016833def6 100644
--- a/libraries/matrix/impl/build.gradle.kts
+++ b/libraries/matrix/impl/build.gradle.kts
@@ -29,7 +29,7 @@ anvil {
 }
 
 dependencies {
-    // api(projects.libraries.rustsdk)
+    // implementation(projects.libraries.rustsdk)
     implementation(libs.matrix.sdk)
     implementation(projects.libraries.di)
     implementation(projects.libraries.androidutils)
@@ -45,4 +45,5 @@ dependencies {
     testImplementation(libs.test.junit)
     testImplementation(libs.test.truth)
     testImplementation(projects.libraries.matrix.test)
+    testImplementation(libs.coroutines.test)
 }
diff --git a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/RustMatrixClient.kt b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/RustMatrixClient.kt
index 640e0772a9..8f5cfa496b 100644
--- a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/RustMatrixClient.kt
+++ b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/RustMatrixClient.kt
@@ -32,8 +32,8 @@ import io.element.android.libraries.matrix.api.notification.NotificationService
 import io.element.android.libraries.matrix.api.pusher.PushersService
 import io.element.android.libraries.matrix.api.room.MatrixRoom
 import io.element.android.libraries.matrix.api.room.RoomMembershipObserver
-import io.element.android.libraries.matrix.api.room.RoomSummaryDataSource
-import io.element.android.libraries.matrix.api.room.awaitAllRoomsAreLoaded
+import io.element.android.libraries.matrix.api.roomlist.RoomListService
+import io.element.android.libraries.matrix.api.roomlist.awaitLoaded
 import io.element.android.libraries.matrix.api.sync.SyncService
 import io.element.android.libraries.matrix.api.sync.SyncState
 import io.element.android.libraries.matrix.api.user.MatrixSearchUserResults
@@ -45,9 +45,8 @@ import io.element.android.libraries.matrix.impl.notification.RustNotificationSer
 import io.element.android.libraries.matrix.impl.pushers.RustPushersService
 import io.element.android.libraries.matrix.impl.room.RoomContentForwarder
 import io.element.android.libraries.matrix.impl.room.RustMatrixRoom
-import io.element.android.libraries.matrix.impl.room.RustRoomSummaryDataSource
-import io.element.android.libraries.matrix.impl.room.roomOrNull
-import io.element.android.libraries.matrix.impl.room.stateFlow
+import io.element.android.libraries.matrix.impl.roomlist.RustRoomListService
+import io.element.android.libraries.matrix.impl.roomlist.roomOrNull
 import io.element.android.libraries.matrix.impl.sync.RustSyncService
 import io.element.android.libraries.matrix.impl.usersearch.UserProfileMapper
 import io.element.android.libraries.matrix.impl.usersearch.UserSearchResultMapper
@@ -90,20 +89,20 @@ class RustMatrixClient constructor(
 ) : MatrixClient {
 
     override val sessionId: UserId = UserId(client.userId())
-    private val roomListService = syncService.roomListService()
+    private val innerRoomListService = syncService.roomListService()
     private val sessionDispatcher = dispatchers.io.limitedParallelism(64)
     private val sessionCoroutineScope = appCoroutineScope.childScope(dispatchers.main, "Session-${sessionId}")
     private val verificationService = RustSessionVerificationService()
-    private val rustSyncService = RustSyncService(syncService, roomListService.stateFlow(), sessionCoroutineScope)
+    private val rustSyncService = RustSyncService(syncService, sessionCoroutineScope)
     private val pushersService = RustPushersService(
         client = client,
         dispatchers = dispatchers,
     )
     private val notificationClient = client.notificationClient().use { builder ->
-        builder.finish()
+        builder.filterByPushRules().finish()
     }
 
-    private val notificationService = RustNotificationService(notificationClient)
+    private val notificationService = RustNotificationService(sessionId, notificationClient, dispatchers, clock)
 
     private val isLoggingOut = AtomicBoolean(false)
 
@@ -122,15 +121,15 @@ class RustMatrixClient constructor(
         }
     }
 
-    private val rustRoomSummaryDataSource: RustRoomSummaryDataSource =
-        RustRoomSummaryDataSource(
-            roomListService = roomListService,
+    private val rustRoomListService: RoomListService =
+        RustRoomListService(
+            innerRoomListService = innerRoomListService,
             sessionCoroutineScope = sessionCoroutineScope,
             dispatcher = sessionDispatcher,
         )
 
-    override val roomSummaryDataSource: RoomSummaryDataSource
-        get() = rustRoomSummaryDataSource
+    override val roomListService: RoomListService
+        get() = rustRoomListService
 
     private val rustMediaLoader = RustMediaLoader(baseCacheDirectory, dispatchers, client)
     override val mediaLoader: MatrixMediaLoader
@@ -138,7 +137,7 @@ class RustMatrixClient constructor(
 
     private val roomMembershipObserver = RoomMembershipObserver()
 
-    private val roomContentForwarder = RoomContentForwarder(roomListService)
+    private val roomContentForwarder = RoomContentForwarder(innerRoomListService)
 
     init {
         client.setDelegate(clientDelegate)
@@ -147,35 +146,36 @@ class RustMatrixClient constructor(
                 if (syncState == SyncState.Running) {
                     onSlidingSyncUpdate()
                 }
-            }.launchIn(sessionCoroutineScope)
+            }
+            .launchIn(sessionCoroutineScope)
     }
 
-    override suspend fun getRoom(roomId: RoomId): MatrixRoom? {
+    override suspend fun getRoom(roomId: RoomId): MatrixRoom? = withContext(sessionDispatcher) {
         // Check if already in memory...
         var cachedPairOfRoom = pairOfRoom(roomId)
         if (cachedPairOfRoom == null) {
             //... otherwise, lets wait for the SS to load all rooms and check again.
-            roomSummaryDataSource.awaitAllRoomsAreLoaded()
+            roomListService.allRooms().awaitLoaded()
             cachedPairOfRoom = pairOfRoom(roomId)
         }
-        if (cachedPairOfRoom == null) return null
-        val (roomListItem, fullRoom) = cachedPairOfRoom
-        return RustMatrixRoom(
-            sessionId = sessionId,
-            roomListItem = roomListItem,
-            innerRoom = fullRoom,
-            sessionCoroutineScope = sessionCoroutineScope,
-            coroutineDispatchers = dispatchers,
-            systemClock = clock,
-            roomContentForwarder = roomContentForwarder,
-            sessionData = sessionStore.getSession(sessionId.value)!!,
-        )
+        cachedPairOfRoom?.let { (roomListItem, fullRoom) ->
+            RustMatrixRoom(
+                sessionId = sessionId,
+                roomListItem = roomListItem,
+                innerRoom = fullRoom,
+                sessionCoroutineScope = sessionCoroutineScope,
+                coroutineDispatchers = dispatchers,
+                systemClock = clock,
+                roomContentForwarder = roomContentForwarder,
+                sessionData = sessionStore.getSession(sessionId.value)!!,
+            )
+        }
     }
 
-    private suspend fun pairOfRoom(roomId: RoomId): Pair? = withContext(sessionDispatcher) {
-        val cachedRoomListItem = roomListService.roomOrNull(roomId.value)
+    private fun pairOfRoom(roomId: RoomId): Pair? {
+        val cachedRoomListItem = innerRoomListService.roomOrNull(roomId.value)
         val fullRoom = cachedRoomListItem?.fullRoom()
-        if (cachedRoomListItem == null || fullRoom == null) {
+        return if (cachedRoomListItem == null || fullRoom == null) {
             Timber.d("No room cached for $roomId")
             null
         } else {
@@ -224,10 +224,11 @@ class RustMatrixClient constructor(
 
             // Wait to receive the room back from the sync
             withTimeout(30_000L) {
-                roomSummaryDataSource.allRooms()
+                roomListService.allRooms().summaries
                     .filter { roomSummaries ->
                         roomSummaries.map { it.identifier() }.contains(roomId.value)
-                    }.first()
+                    }
+                    .first()
             }
             roomId
         }
@@ -271,7 +272,7 @@ class RustMatrixClient constructor(
         client.setDelegate(null)
         verificationService.destroy()
         syncService.destroy()
-        roomListService.destroy()
+        innerRoomListService.destroy()
         notificationClient.destroy()
         client.destroy()
     }
diff --git a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/RustMatrixClientFactory.kt b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/RustMatrixClientFactory.kt
new file mode 100644
index 0000000000..931133c266
--- /dev/null
+++ b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/RustMatrixClientFactory.kt
@@ -0,0 +1,78 @@
+/*
+ * Copyright (c) 2023 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
+ *
+ *     http://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
+
+import android.content.Context
+import io.element.android.libraries.core.coroutine.CoroutineDispatchers
+import io.element.android.libraries.di.ApplicationContext
+import io.element.android.libraries.network.useragent.UserAgentProvider
+import io.element.android.libraries.sessionstorage.api.SessionData
+import io.element.android.libraries.sessionstorage.api.SessionStore
+import io.element.android.services.toolbox.api.systemclock.SystemClock
+import kotlinx.coroutines.CoroutineScope
+import kotlinx.coroutines.withContext
+import org.matrix.rustcomponents.sdk.ClientBuilder
+import org.matrix.rustcomponents.sdk.Session
+import org.matrix.rustcomponents.sdk.use
+import java.io.File
+import javax.inject.Inject
+
+class RustMatrixClientFactory @Inject constructor(
+    @ApplicationContext private val context: Context,
+    private val baseDirectory: File,
+    private val appCoroutineScope: CoroutineScope,
+    private val coroutineDispatchers: CoroutineDispatchers,
+    private val sessionStore: SessionStore,
+    private val userAgentProvider: UserAgentProvider,
+    private val clock: SystemClock,
+) {
+
+    suspend fun create(sessionData: SessionData): RustMatrixClient = withContext(coroutineDispatchers.io) {
+        val client = ClientBuilder()
+            .basePath(baseDirectory.absolutePath)
+            .homeserverUrl(sessionData.homeserverUrl)
+            .username(sessionData.userId)
+            .userAgent(userAgentProvider.provide())
+            // FIXME Quick and dirty fix for stopping version requests on startup https://github.com/matrix-org/matrix-rust-sdk/pull/1376
+            .serverVersions(listOf("v1.0", "v1.1", "v1.2", "v1.3", "v1.4", "v1.5"))
+            .use { it.build() }
+
+        client.restoreSession(sessionData.toSession())
+
+        val syncService = client.syncService().finish()
+
+        RustMatrixClient(
+            client = client,
+            syncService = syncService,
+            sessionStore = sessionStore,
+            appCoroutineScope = appCoroutineScope,
+            dispatchers = coroutineDispatchers,
+            baseDirectory = baseDirectory,
+            baseCacheDirectory = context.cacheDir,
+            clock = clock,
+        )
+    }
+}
+
+private fun SessionData.toSession() = Session(
+    accessToken = accessToken,
+    refreshToken = refreshToken,
+    userId = userId,
+    deviceId = deviceId,
+    homeserverUrl = homeserverUrl,
+    slidingSyncProxy = slidingSyncProxy,
+)
diff --git a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/auth/OidcConfig.kt b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/auth/OidcConfig.kt
index 1ba5063df9..b5115ffad4 100644
--- a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/auth/OidcConfig.kt
+++ b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/auth/OidcConfig.kt
@@ -16,8 +16,8 @@
 
 package io.element.android.libraries.matrix.impl.auth
 
-import io.element.android.libraries.matrix.api.auth.OidcConfig
 // TODO Oidc
+// import io.element.android.libraries.matrix.api.auth.OidcConfig
 // import org.matrix.rustcomponents.sdk.OidcClientMetadata
 
 /*
diff --git a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/auth/RustMatrixAuthenticationService.kt b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/auth/RustMatrixAuthenticationService.kt
index 0bc299d020..ba06891013 100644
--- a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/auth/RustMatrixAuthenticationService.kt
+++ b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/auth/RustMatrixAuthenticationService.kt
@@ -16,33 +16,27 @@
 
 package io.element.android.libraries.matrix.impl.auth
 
-import android.content.Context
+// TODO Oidc
+// import org.matrix.rustcomponents.sdk.OidcAuthenticationUrl
 import com.squareup.anvil.annotations.ContributesBinding
 import io.element.android.libraries.core.coroutine.CoroutineDispatchers
 import io.element.android.libraries.core.extensions.mapFailure
 import io.element.android.libraries.di.AppScope
-import io.element.android.libraries.di.ApplicationContext
 import io.element.android.libraries.di.SingleIn
 import io.element.android.libraries.matrix.api.MatrixClient
 import io.element.android.libraries.matrix.api.auth.MatrixAuthenticationService
 import io.element.android.libraries.matrix.api.auth.MatrixHomeServerDetails
 import io.element.android.libraries.matrix.api.auth.OidcDetails
 import io.element.android.libraries.matrix.api.core.SessionId
-import io.element.android.libraries.matrix.impl.RustMatrixClient
+import io.element.android.libraries.matrix.impl.RustMatrixClientFactory
 import io.element.android.libraries.matrix.impl.exception.mapClientException
 import io.element.android.libraries.network.useragent.UserAgentProvider
 import io.element.android.libraries.sessionstorage.api.SessionData
 import io.element.android.libraries.sessionstorage.api.SessionStore
-import io.element.android.services.toolbox.api.systemclock.SystemClock
-import kotlinx.coroutines.CoroutineScope
 import kotlinx.coroutines.flow.Flow
 import kotlinx.coroutines.flow.MutableStateFlow
 import kotlinx.coroutines.flow.StateFlow
 import kotlinx.coroutines.withContext
-import org.matrix.rustcomponents.sdk.Client
-import org.matrix.rustcomponents.sdk.ClientBuilder
-// TODO Oidc
-// import org.matrix.rustcomponents.sdk.OidcAuthenticationUrl
 import org.matrix.rustcomponents.sdk.Session
 import org.matrix.rustcomponents.sdk.use
 import java.io.File
@@ -53,13 +47,11 @@ import org.matrix.rustcomponents.sdk.AuthenticationService as RustAuthentication
 @ContributesBinding(AppScope::class)
 @SingleIn(AppScope::class)
 class RustMatrixAuthenticationService @Inject constructor(
-    @ApplicationContext private val context: Context,
-    private val baseDirectory: File,
-    private val appCoroutineScope: CoroutineScope,
+    baseDirectory: File,
     private val coroutineDispatchers: CoroutineDispatchers,
     private val sessionStore: SessionStore,
-    private val clock: SystemClock,
-    private val userAgentProvider: UserAgentProvider,
+    userAgentProvider: UserAgentProvider,
+    private val rustMatrixClientFactory: RustMatrixClientFactory,
 ) : MatrixAuthenticationService {
 
     private val authService: RustAuthenticationService = RustAuthenticationService(
@@ -84,16 +76,9 @@ class RustMatrixAuthenticationService @Inject constructor(
         runCatching {
             val sessionData = sessionStore.getSession(sessionId.value)
             if (sessionData != null) {
-                val client = ClientBuilder()
-                    .basePath(baseDirectory.absolutePath)
-                    .homeserverUrl(sessionData.homeserverUrl)
-                    .username(sessionData.userId)
-                    .userAgent(userAgentProvider.provide())
-                    .use { it.build() }
-                client.restoreSession(sessionData.toSession())
-                createMatrixClient(client)
+                rustMatrixClientFactory.create(sessionData)
             } else {
-                throw IllegalStateException("No session to restore with id $sessionId")
+                error("No session to restore with id $sessionId")
             }
         }.mapFailure { failure ->
             failure.mapClientException()
@@ -181,30 +166,8 @@ class RustMatrixAuthenticationService @Inject constructor(
          */
     }
 
-    private suspend fun createMatrixClient(client: Client): MatrixClient {
-        val syncService = client.syncService().finish()
-        return RustMatrixClient(
-            client = client,
-            syncService = syncService,
-            sessionStore = sessionStore,
-            appCoroutineScope = appCoroutineScope,
-            dispatchers = coroutineDispatchers,
-            baseDirectory = baseDirectory,
-            baseCacheDirectory = context.cacheDir,
-            clock = clock,
-        )
-    }
 }
 
-private fun SessionData.toSession() = Session(
-    accessToken = accessToken,
-    refreshToken = refreshToken,
-    userId = userId,
-    deviceId = deviceId,
-    homeserverUrl = homeserverUrl,
-    slidingSyncProxy = slidingSyncProxy,
-)
-
 private fun Session.toSessionData() = SessionData(
     userId = userId,
     deviceId = deviceId,
diff --git a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/di/SessionMatrixModule.kt b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/di/SessionMatrixModule.kt
index bf260be6ec..dba1dbd0a3 100644
--- a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/di/SessionMatrixModule.kt
+++ b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/di/SessionMatrixModule.kt
@@ -23,7 +23,7 @@ import io.element.android.libraries.di.SessionScope
 import io.element.android.libraries.matrix.api.MatrixClient
 import io.element.android.libraries.matrix.api.media.MatrixMediaLoader
 import io.element.android.libraries.matrix.api.room.RoomMembershipObserver
-import io.element.android.libraries.matrix.api.room.RoomSummaryDataSource
+import io.element.android.libraries.matrix.api.roomlist.RoomListService
 import io.element.android.libraries.matrix.api.verification.SessionVerificationService
 
 @Module
@@ -40,8 +40,8 @@ object SessionMatrixModule {
     }
 
     @Provides
-    fun provideRoomSummaryDataSource(matrixClient: MatrixClient): RoomSummaryDataSource {
-        return matrixClient.roomSummaryDataSource
+    fun providesRoomListService(matrixClient: MatrixClient): RoomListService {
+        return matrixClient.roomListService
     }
 
     @Provides
diff --git a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/media/ImageInfo.kt b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/media/ImageInfo.kt
index b66cec96fd..99b806ed4a 100644
--- a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/media/ImageInfo.kt
+++ b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/media/ImageInfo.kt
@@ -17,7 +17,6 @@
 package io.element.android.libraries.matrix.impl.media
 
 import io.element.android.libraries.matrix.api.media.ImageInfo
-import org.matrix.rustcomponents.sdk.MediaSource
 import org.matrix.rustcomponents.sdk.ImageInfo as RustImageInfo
 
 fun RustImageInfo.map(): ImageInfo = ImageInfo(
diff --git a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/notification/NotificationMapper.kt b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/notification/NotificationMapper.kt
index 07acb7fec5..0d9f794173 100644
--- a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/notification/NotificationMapper.kt
+++ b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/notification/NotificationMapper.kt
@@ -19,19 +19,29 @@ package io.element.android.libraries.matrix.impl.notification
 import io.element.android.libraries.core.bool.orFalse
 import io.element.android.libraries.matrix.api.core.EventId
 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.core.SessionId
+import io.element.android.libraries.matrix.api.notification.NotificationContent
 import io.element.android.libraries.matrix.api.notification.NotificationData
+import io.element.android.libraries.matrix.api.room.RoomMembershipState
+import io.element.android.services.toolbox.api.systemclock.SystemClock
+import org.matrix.rustcomponents.sdk.NotificationEvent
 import org.matrix.rustcomponents.sdk.NotificationItem
 import org.matrix.rustcomponents.sdk.use
 
-class NotificationMapper {
-    private val timelineEventMapper = TimelineEventMapper()
+class NotificationMapper(
+    sessionId: SessionId,
+    private val clock: SystemClock,
+) {
+    private val notificationContentMapper = NotificationContentMapper(sessionId)
 
-    fun map(roomId: RoomId, notificationItem: NotificationItem): NotificationData {
+    fun map(
+        eventId: EventId,
+        roomId: RoomId,
+        notificationItem: NotificationItem
+    ): NotificationData {
         return notificationItem.use { item ->
             NotificationData(
-                senderId = UserId(item.event.senderId()),
-                eventId = EventId(item.event.eventId()),
+                eventId = eventId,
                 roomId = roomId,
                 senderAvatarUrl = item.senderInfo.avatarUrl,
                 senderDisplayName = item.senderInfo.displayName,
@@ -39,9 +49,28 @@ class NotificationMapper {
                 roomDisplayName = item.roomInfo.displayName,
                 isDirect = item.roomInfo.isDirect,
                 isEncrypted = item.roomInfo.isEncrypted.orFalse(),
-                isNoisy = item.isNoisy,
-                event = item.event.use { event -> timelineEventMapper.map(event) }
+                isNoisy = item.isNoisy.orFalse(),
+                timestamp = item.timestamp() ?: clock.epochMillis(),
+                content = item.event.use { notificationContentMapper.map(it) },
+                contentUrl = null,
             )
         }
     }
 }
+
+class NotificationContentMapper(private val sessionId: SessionId) {
+    private val timelineEventToNotificationContentMapper = TimelineEventToNotificationContentMapper()
+
+    fun map(notificationEvent: NotificationEvent): NotificationContent =
+        when (notificationEvent) {
+            is NotificationEvent.Timeline -> timelineEventToNotificationContentMapper.map(notificationEvent.event)
+            is NotificationEvent.Invite -> NotificationContent.StateEvent.RoomMemberContent(
+                userId = sessionId.value,
+                membershipState = RoomMembershipState.INVITE,
+            )
+        }
+}
+
+private fun NotificationItem.timestamp(): Long? {
+    return (this.event as? NotificationEvent.Timeline)?.event?.timestamp()?.toLong()
+}
diff --git a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/notification/RustNotificationService.kt b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/notification/RustNotificationService.kt
index 92c996049e..0f3aebd049 100644
--- a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/notification/RustNotificationService.kt
+++ b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/notification/RustNotificationService.kt
@@ -16,29 +16,34 @@
 
 package io.element.android.libraries.matrix.impl.notification
 
+import io.element.android.libraries.core.coroutine.CoroutineDispatchers
 import io.element.android.libraries.matrix.api.core.EventId
 import io.element.android.libraries.matrix.api.core.RoomId
 import io.element.android.libraries.matrix.api.core.SessionId
 import io.element.android.libraries.matrix.api.notification.NotificationData
 import io.element.android.libraries.matrix.api.notification.NotificationService
+import io.element.android.services.toolbox.api.systemclock.SystemClock
+import kotlinx.coroutines.withContext
 import org.matrix.rustcomponents.sdk.NotificationClient
 import org.matrix.rustcomponents.sdk.use
 
 class RustNotificationService(
+    sessionId: SessionId,
     private val notificationClient: NotificationClient,
+    private val dispatchers: CoroutineDispatchers,
+    clock: SystemClock,
 ) : NotificationService {
-    private val notificationMapper: NotificationMapper = NotificationMapper()
+    private val notificationMapper: NotificationMapper = NotificationMapper(sessionId, clock)
 
-    override fun getNotification(
+    override suspend fun getNotification(
         userId: SessionId,
         roomId: RoomId,
         eventId: EventId,
-        filterByPushRules: Boolean,
-    ): Result {
-        return runCatching {
+    ): Result = withContext(dispatchers.io) {
+        runCatching {
             val item = notificationClient.getNotification(roomId.value, eventId.value)
             item?.use {
-                notificationMapper.map(roomId, it)
+                notificationMapper.map(eventId, roomId, it)
             }
         }
     }
diff --git a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/notification/TimelineEventMapper.kt b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/notification/TimelineEventToNotificationContentMapper.kt
similarity index 85%
rename from libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/notification/TimelineEventMapper.kt
rename to libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/notification/TimelineEventToNotificationContentMapper.kt
index f7d4a00188..e30e57113d 100644
--- a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/notification/TimelineEventMapper.kt
+++ b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/notification/TimelineEventToNotificationContentMapper.kt
@@ -16,8 +16,8 @@
 
 package io.element.android.libraries.matrix.impl.notification
 
+import io.element.android.libraries.matrix.api.core.UserId
 import io.element.android.libraries.matrix.api.notification.NotificationContent
-import io.element.android.libraries.matrix.api.notification.NotificationEvent
 import io.element.android.libraries.matrix.impl.room.RoomMemberMapper
 import io.element.android.libraries.matrix.impl.timeline.item.event.EventMessageMapper
 import org.matrix.rustcomponents.sdk.MessageLikeEventContent
@@ -27,22 +27,20 @@ import org.matrix.rustcomponents.sdk.TimelineEventType
 import org.matrix.rustcomponents.sdk.use
 import javax.inject.Inject
 
-class TimelineEventMapper @Inject constructor() {
+class TimelineEventToNotificationContentMapper @Inject constructor() {
 
-    fun map(timelineEvent: TimelineEvent): NotificationEvent {
+    fun map(timelineEvent: TimelineEvent): NotificationContent {
         return timelineEvent.use {
-            NotificationEvent(
-                timestamp = it.timestamp().toLong(),
-                content = it.eventType().toContent(),
-                contentUrl = null // TODO it.eventType().toContentUrl(),
-            )
+            timelineEvent.eventType().use { eventType ->
+                eventType.toContent(senderId = UserId(timelineEvent.senderId()))
+            }
         }
     }
 }
 
-private fun TimelineEventType.toContent(): NotificationContent {
+private fun TimelineEventType.toContent(senderId: UserId): NotificationContent {
     return when (this) {
-        is TimelineEventType.MessageLike -> content.toContent()
+        is TimelineEventType.MessageLike -> content.toContent(senderId)
         is TimelineEventType.State -> content.toContent()
     }
 }
@@ -75,9 +73,9 @@ private fun StateEventContent.toContent(): NotificationContent.StateEvent {
     }
 }
 
-private fun MessageLikeEventContent.toContent(): NotificationContent.MessageLike {
+private fun MessageLikeEventContent.toContent(senderId: UserId): NotificationContent.MessageLike {
     return use {
-        when (it) {
+        when (this) {
             MessageLikeEventContent.CallAnswer -> NotificationContent.MessageLike.CallAnswer
             MessageLikeEventContent.CallCandidates -> NotificationContent.MessageLike.CallCandidates
             MessageLikeEventContent.CallHangup -> NotificationContent.MessageLike.CallHangup
@@ -89,10 +87,10 @@ private fun MessageLikeEventContent.toContent(): NotificationContent.MessageLike
             MessageLikeEventContent.KeyVerificationMac -> NotificationContent.MessageLike.KeyVerificationMac
             MessageLikeEventContent.KeyVerificationReady -> NotificationContent.MessageLike.KeyVerificationReady
             MessageLikeEventContent.KeyVerificationStart -> NotificationContent.MessageLike.KeyVerificationStart
-            is MessageLikeEventContent.ReactionContent -> NotificationContent.MessageLike.ReactionContent(it.relatedEventId)
+            is MessageLikeEventContent.ReactionContent -> NotificationContent.MessageLike.ReactionContent(relatedEventId)
             MessageLikeEventContent.RoomEncrypted -> NotificationContent.MessageLike.RoomEncrypted
             is MessageLikeEventContent.RoomMessage -> {
-                NotificationContent.MessageLike.RoomMessage(EventMessageMapper().mapMessageType(it.messageType))
+                NotificationContent.MessageLike.RoomMessage(senderId, EventMessageMapper().mapMessageType(messageType))
             }
             MessageLikeEventContent.RoomRedaction -> NotificationContent.MessageLike.RoomRedaction
             MessageLikeEventContent.Sticker -> NotificationContent.MessageLike.Sticker
diff --git a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/poll/PollAnswer.kt b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/poll/PollAnswer.kt
new file mode 100644
index 0000000000..c3098bdcb0
--- /dev/null
+++ b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/poll/PollAnswer.kt
@@ -0,0 +1,25 @@
+/*
+ * Copyright (c) 2023 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
+ *
+ *     http://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.poll
+
+import io.element.android.libraries.matrix.api.poll.PollAnswer
+import org.matrix.rustcomponents.sdk.PollAnswer as RustPollAnswer
+
+fun RustPollAnswer.map(): PollAnswer = PollAnswer(
+    id = id,
+    text = text,
+)
diff --git a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/poll/PollKind.kt b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/poll/PollKind.kt
new file mode 100644
index 0000000000..bde49464ad
--- /dev/null
+++ b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/poll/PollKind.kt
@@ -0,0 +1,25 @@
+/*
+ * Copyright (c) 2023 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
+ *
+ *     http://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.poll
+
+import io.element.android.libraries.matrix.api.poll.PollKind
+import org.matrix.rustcomponents.sdk.PollKind as RustPollKind
+
+fun RustPollKind.map(): PollKind = when (this) {
+    RustPollKind.DISCLOSED -> PollKind.Disclosed
+    RustPollKind.UNDISCLOSED -> PollKind.Undisclosed
+}
diff --git a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/room/RoomContentForwarder.kt b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/room/RoomContentForwarder.kt
index 4e2d63d091..8ee0361ace 100644
--- a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/room/RoomContentForwarder.kt
+++ b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/room/RoomContentForwarder.kt
@@ -20,6 +20,7 @@ import io.element.android.libraries.core.coroutine.parallelMap
 import io.element.android.libraries.matrix.api.core.EventId
 import io.element.android.libraries.matrix.api.core.RoomId
 import io.element.android.libraries.matrix.api.room.ForwardEventException
+import io.element.android.libraries.matrix.impl.roomlist.roomOrNull
 import kotlinx.coroutines.CancellationException
 import kotlinx.coroutines.withTimeout
 import org.matrix.rustcomponents.sdk.Room
@@ -80,6 +81,6 @@ class RoomContentForwarder(
     }
 
     private object NoOpTimelineListener : TimelineListener {
-        override fun onUpdate(diff: TimelineDiff) = Unit
+        override fun onUpdate(diff: List) = Unit
     }
 }
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 16434aa3c8..dc74a273f4 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
@@ -18,6 +18,7 @@ package io.element.android.libraries.matrix.impl.room
 
 import io.element.android.libraries.core.coroutine.CoroutineDispatchers
 import io.element.android.libraries.core.coroutine.childScope
+import io.element.android.libraries.core.coroutine.parallelMap
 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
@@ -40,9 +41,6 @@ import io.element.android.libraries.matrix.impl.core.toProgressWatcher
 import io.element.android.libraries.matrix.impl.media.map
 import io.element.android.libraries.matrix.impl.room.location.toInner
 import io.element.android.libraries.matrix.impl.timeline.RustMatrixTimeline
-import io.element.android.libraries.matrix.impl.timeline.backPaginationStatusFlow
-import io.element.android.libraries.matrix.impl.timeline.eventOrigin
-import io.element.android.libraries.matrix.impl.timeline.timelineDiffFlow
 import io.element.android.libraries.sessionstorage.api.SessionData
 import io.element.android.services.toolbox.api.systemclock.SystemClock
 import kotlinx.coroutines.CoroutineScope
@@ -51,11 +49,7 @@ import kotlinx.coroutines.cancel
 import kotlinx.coroutines.flow.MutableStateFlow
 import kotlinx.coroutines.flow.StateFlow
 import kotlinx.coroutines.flow.asStateFlow
-import kotlinx.coroutines.flow.launchIn
-import kotlinx.coroutines.flow.onEach
-import kotlinx.coroutines.launch
 import kotlinx.coroutines.withContext
-import org.matrix.rustcomponents.sdk.EventItemOrigin
 import org.matrix.rustcomponents.sdk.RequiredState
 import org.matrix.rustcomponents.sdk.Room
 import org.matrix.rustcomponents.sdk.RoomListItem
@@ -88,7 +82,6 @@ class RustMatrixRoom(
 
     private val roomCoroutineScope = sessionCoroutineScope.childScope(coroutineDispatchers.main, "RoomScope-$roomId")
     private val _membersStateFlow = MutableStateFlow(MatrixRoomMembersState.Unknown)
-    private val isInit = MutableStateFlow(false)
     private val _syncUpdateFlow = MutableStateFlow(0L)
     private val _timeline by lazy {
         RustMatrixTimeline(
@@ -97,6 +90,7 @@ class RustMatrixRoom(
             roomCoroutineScope = roomCoroutineScope,
             dispatcher = roomDispatcher,
             lastLoginTimestamp = sessionData.loginTimestamp,
+            onNewSyncedEvent = { _syncUpdateFlow.value = systemClock.epochMillis() }
         )
     }
 
@@ -106,8 +100,7 @@ class RustMatrixRoom(
 
     override val timeline: MatrixTimeline = _timeline
 
-    override fun open(): Result {
-        if (isInit.value) return Result.failure(IllegalStateException("Listener already registered"))
+    override fun subscribeToSync() {
         val settings = RoomSubscription(
             requiredState = listOf(
                 RequiredState(key = EventType.STATE_ROOM_CANONICAL_ALIAS, value = ""),
@@ -118,35 +111,16 @@ class RustMatrixRoom(
             timelineLimit = null
         )
         roomListItem.subscribe(settings)
-        roomCoroutineScope.launch(roomDispatcher) {
-            innerRoom.timelineDiffFlow { initialList ->
-                _timeline.postItems(initialList)
-            }.onEach { diff ->
-                if (diff.eventOrigin() == EventItemOrigin.SYNC) {
-                    _syncUpdateFlow.value = systemClock.epochMillis()
-                }
-                _timeline.postDiff(diff)
-            }.launchIn(this)
-
-            innerRoom.backPaginationStatusFlow()
-                .onEach {
-                    _timeline.postPaginationStatus(it)
-                }.launchIn(this)
-
-            fetchMembers()
-        }
-        isInit.value = true
-        return Result.success(Unit)
     }
 
-    override fun close() {
-        if (isInit.value) {
-            isInit.value = false
-            roomCoroutineScope.cancel()
-            roomListItem.unsubscribe()
-            innerRoom.destroy()
-            roomListItem.destroy()
-        }
+    override fun unsubscribeFromSync() {
+        roomListItem.unsubscribe()
+    }
+
+    override fun destroy() {
+        roomCoroutineScope.cancel()
+        innerRoom.destroy()
+        roomListItem.destroy()
     }
 
     override val name: String?
@@ -166,7 +140,7 @@ class RustMatrixRoom(
 
     override val avatarUrl: String?
         get() {
-            return innerRoom.avatarUrl()
+            return roomListItem.avatarUrl() ?: innerRoom.avatarUrl()
         }
 
     override val isEncrypted: Boolean
@@ -195,7 +169,7 @@ class RustMatrixRoom(
         val currentMembers = currentState.roomMembers()
         _membersStateFlow.value = MatrixRoomMembersState.Pending(prevRoomMembers = currentMembers)
         runCatching {
-            innerRoom.members().map(RoomMemberMapper::map)
+            innerRoom.members().parallelMap(RoomMemberMapper::map)
         }.map {
             _membersStateFlow.value = MatrixRoomMembersState.Ready(it)
         }.onFailure {
@@ -276,6 +250,12 @@ class RustMatrixRoom(
         }
     }
 
+    override suspend fun canUserRedact(userId: UserId): Result {
+        return runCatching {
+            innerRoom.canUserRedact(userId.value)
+        }
+    }
+
     override suspend fun canUserSendState(userId: UserId, type: StateEventType): Result {
         return runCatching {
             innerRoom.canUserSendState(userId.value, type.map())
@@ -363,12 +343,6 @@ class RustMatrixRoom(
         }
     }
 
-    private suspend fun fetchMembers() = withContext(roomDispatcher) {
-        runCatching {
-            innerRoom.fetchMembers()
-        }
-    }
-
     override suspend fun reportContent(eventId: EventId, reason: String, blockUserId: UserId?): Result = withContext(roomDispatcher) {
         runCatching {
             innerRoom.reportContent(eventId = eventId.value, score = null, reason = reason)
@@ -396,13 +370,15 @@ class RustMatrixRoom(
             )
         }
     }
-}
 
-//TODO handle cancellation, need refactoring of how we are catching errors
-private suspend fun sendAttachment(handle: () -> SendAttachmentJoinHandle): Result {
-    return runCatching {
-        handle().use {
-            it.join()
+    //TODO handle cancellation, need refactoring of how we are catching errors
+    private suspend fun sendAttachment(handle: () -> SendAttachmentJoinHandle): Result {
+        return runCatching {
+            handle().use {
+                it.join()
+            }
         }
     }
 }
+
+
diff --git a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/room/RustRoomSummaryDataSource.kt b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/room/RustRoomSummaryDataSource.kt
deleted file mode 100644
index efdbcf34ad..0000000000
--- a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/room/RustRoomSummaryDataSource.kt
+++ /dev/null
@@ -1,122 +0,0 @@
-/*
- * Copyright (c) 2023 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
- *
- *     http://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.room
-
-import io.element.android.libraries.matrix.api.room.RoomSummary
-import io.element.android.libraries.matrix.api.room.RoomSummaryDataSource
-import kotlinx.coroutines.CoroutineDispatcher
-import kotlinx.coroutines.CoroutineScope
-import kotlinx.coroutines.flow.Flow
-import kotlinx.coroutines.flow.MutableStateFlow
-import kotlinx.coroutines.flow.StateFlow
-import kotlinx.coroutines.flow.first
-import kotlinx.coroutines.flow.launchIn
-import kotlinx.coroutines.flow.map
-import kotlinx.coroutines.flow.onEach
-import kotlinx.coroutines.launch
-import org.matrix.rustcomponents.sdk.RoomList
-import org.matrix.rustcomponents.sdk.RoomListEntriesUpdate
-import org.matrix.rustcomponents.sdk.RoomListException
-import org.matrix.rustcomponents.sdk.RoomListInput
-import org.matrix.rustcomponents.sdk.RoomListLoadingState
-import org.matrix.rustcomponents.sdk.RoomListRange
-import org.matrix.rustcomponents.sdk.RoomListService
-import org.matrix.rustcomponents.sdk.RoomListServiceState
-import timber.log.Timber
-
-internal class RustRoomSummaryDataSource(
-    private val roomListService: RoomListService,
-    private val sessionCoroutineScope: CoroutineScope,
-    dispatcher: CoroutineDispatcher,
-    roomSummaryDetailsFactory: RoomSummaryDetailsFactory = RoomSummaryDetailsFactory(),
-) : RoomSummaryDataSource {
-
-    private val allRooms = MutableStateFlow>(emptyList())
-    private val inviteRooms = MutableStateFlow>(emptyList())
-
-    private val allRoomsLoadingState: MutableStateFlow = MutableStateFlow(RoomSummaryDataSource.LoadingState.NotLoaded)
-    private val allRoomsListProcessor = RoomSummaryListProcessor(allRooms, roomListService, roomSummaryDetailsFactory, shouldFetchFullRoom = false)
-    private val inviteRoomsListProcessor = RoomSummaryListProcessor(inviteRooms, roomListService, roomSummaryDetailsFactory, shouldFetchFullRoom = true)
-
-    init {
-        sessionCoroutineScope.launch(dispatcher) {
-            val allRooms = roomListService.allRooms()
-            allRooms
-                .observeEntriesWithProcessor(allRoomsListProcessor)
-                .launchIn(this)
-
-            allRooms
-                .loadingStateFlow()
-                .map { it.toRoomSummaryDataSourceLoadingState() }
-                .onEach {
-                    allRoomsLoadingState.value = it
-                }.launchIn(this)
-
-            launch {
-                // Wait until running, as invites is only available after that
-                roomListService.stateFlow().first {
-                    it == RoomListServiceState.RUNNING
-                }
-                roomListService.invites()
-                    .observeEntriesWithProcessor(inviteRoomsListProcessor)
-                    .launchIn(this)
-            }
-        }
-    }
-
-    override fun allRooms(): StateFlow> {
-        return allRooms
-    }
-
-    override fun inviteRooms(): StateFlow> {
-        return inviteRooms
-    }
-
-    override fun allRoomsLoadingState(): StateFlow {
-        return allRoomsLoadingState
-    }
-
-    override fun updateAllRoomsVisibleRange(range: IntRange) {
-        Timber.v("setVisibleRange=$range")
-        sessionCoroutineScope.launch {
-            try {
-                val ranges = listOf(RoomListRange(range.first.toUInt(), range.last.toUInt()))
-                roomListService.applyInput(
-                    RoomListInput.Viewport(ranges)
-                )
-            } catch (exception: RoomListException) {
-                Timber.e(exception, "Failed updating visible range")
-            }
-        }
-    }
-}
-
-private fun RoomListLoadingState.toRoomSummaryDataSourceLoadingState(): RoomSummaryDataSource.LoadingState {
-    return when (this) {
-        is RoomListLoadingState.Loaded -> RoomSummaryDataSource.LoadingState.Loaded(maximumNumberOfRooms?.toInt() ?: 0)
-        is RoomListLoadingState.NotLoaded -> RoomSummaryDataSource.LoadingState.NotLoaded
-    }
-}
-
-private fun RoomList.observeEntriesWithProcessor(processor: RoomSummaryListProcessor): Flow {
-    return entriesFlow { roomListEntries ->
-        processor.postEntries(roomListEntries)
-    }.onEach { update ->
-        processor.postUpdate(update)
-    }
-}
-
diff --git a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/room/RoomListExtensions.kt b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/roomlist/RoomListExtensions.kt
similarity index 76%
rename from libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/room/RoomListExtensions.kt
rename to libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/roomlist/RoomListExtensions.kt
index 84c4eeaefb..8d96990a9e 100644
--- a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/room/RoomListExtensions.kt
+++ b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/roomlist/RoomListExtensions.kt
@@ -14,18 +14,19 @@
  * limitations under the License.
  */
 
-package io.element.android.libraries.matrix.impl.room
+package io.element.android.libraries.matrix.impl.roomlist
 
+import io.element.android.libraries.core.data.tryOrNull
 import io.element.android.libraries.matrix.impl.util.mxCallbackFlow
 import kotlinx.coroutines.channels.Channel
 import kotlinx.coroutines.channels.trySendBlocking
 import kotlinx.coroutines.flow.Flow
 import kotlinx.coroutines.flow.buffer
+import kotlinx.coroutines.flow.catch
 import org.matrix.rustcomponents.sdk.RoomList
 import org.matrix.rustcomponents.sdk.RoomListEntriesListener
 import org.matrix.rustcomponents.sdk.RoomListEntriesUpdate
 import org.matrix.rustcomponents.sdk.RoomListEntry
-import org.matrix.rustcomponents.sdk.RoomListException
 import org.matrix.rustcomponents.sdk.RoomListItem
 import org.matrix.rustcomponents.sdk.RoomListLoadingState
 import org.matrix.rustcomponents.sdk.RoomListLoadingStateListener
@@ -42,31 +43,34 @@ fun RoomList.loadingStateFlow(): Flow =
             }
         }
         val result = loadingState(listener)
-        send(result.state)
+        try {
+            send(result.state)
+        } catch (exception: Exception) {
+            Timber.d("loadingStateFlow() initialState failed.")
+        }
         result.stateStream
+    }.catch {
+        Timber.d(it, "loadingStateFlow() failed")
     }.buffer(Channel.UNLIMITED)
 
-fun RoomList.entriesFlow(onInitialList: suspend (List) -> Unit): Flow =
+fun RoomList.entriesFlow(onInitialList: suspend (List) -> Unit): Flow> =
     mxCallbackFlow {
         val listener = object : RoomListEntriesListener {
-            override fun onUpdate(roomEntriesUpdate: RoomListEntriesUpdate) {
+            override fun onUpdate(roomEntriesUpdate: List) {
                 trySendBlocking(roomEntriesUpdate)
             }
         }
         val result = entries(listener)
-        onInitialList(result.entries)
+        try {
+            onInitialList(result.entries)
+        } catch (exception: Exception) {
+            Timber.d("entriesFlow() onInitialList failed.")
+        }
         result.entriesStream
+    }.catch {
+        Timber.d(it, "entriesFlow() failed")
     }.buffer(Channel.UNLIMITED)
 
-fun RoomListService.roomOrNull(roomId: String): RoomListItem? {
-    return try {
-        room(roomId)
-    } catch (exception: RoomListException) {
-        Timber.d(exception, "Failed finding room with id=$roomId.")
-        return null
-    }
-}
-
 fun RoomListService.stateFlow(): Flow =
     mxCallbackFlow {
         val listener = object : RoomListServiceStateListener {
@@ -74,5 +78,16 @@ fun RoomListService.stateFlow(): Flow =
                 trySendBlocking(state)
             }
         }
-        state(listener)
+        tryOrNull {
+            state(listener)
+        }
     }.buffer(Channel.UNLIMITED)
+
+fun RoomListService.roomOrNull(roomId: String): RoomListItem? {
+    return try {
+        room(roomId)
+    } catch (exception: Exception) {
+        Timber.d(exception, "Failed finding room with id=$roomId.")
+        return null
+    }
+}
diff --git a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/room/RoomSummaryDetailsFactory.kt b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/roomlist/RoomSummaryDetailsFactory.kt
similarity index 89%
rename from libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/room/RoomSummaryDetailsFactory.kt
rename to libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/roomlist/RoomSummaryDetailsFactory.kt
index 7dd7bf4581..b57eb892e0 100644
--- a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/room/RoomSummaryDetailsFactory.kt
+++ b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/roomlist/RoomSummaryDetailsFactory.kt
@@ -14,10 +14,11 @@
  * limitations under the License.
  */
 
-package io.element.android.libraries.matrix.impl.room
+package io.element.android.libraries.matrix.impl.roomlist
 
 import io.element.android.libraries.matrix.api.core.RoomId
-import io.element.android.libraries.matrix.api.room.RoomSummaryDetails
+import io.element.android.libraries.matrix.api.roomlist.RoomSummaryDetails
+import io.element.android.libraries.matrix.impl.room.RoomMemberMapper
 import io.element.android.libraries.matrix.impl.room.message.RoomMessageFactory
 import org.matrix.rustcomponents.sdk.Room
 import org.matrix.rustcomponents.sdk.RoomListItem
diff --git a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/room/RoomSummaryListProcessor.kt b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/roomlist/RoomSummaryListProcessor.kt
similarity index 93%
rename from libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/room/RoomSummaryListProcessor.kt
rename to libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/roomlist/RoomSummaryListProcessor.kt
index a8ab4cb807..9a67ff1f30 100644
--- a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/room/RoomSummaryListProcessor.kt
+++ b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/roomlist/RoomSummaryListProcessor.kt
@@ -14,10 +14,10 @@
  * limitations under the License.
  */
 
-package io.element.android.libraries.matrix.impl.room
+package io.element.android.libraries.matrix.impl.roomlist
 
 import io.element.android.libraries.core.coroutine.parallelMap
-import io.element.android.libraries.matrix.api.room.RoomSummary
+import io.element.android.libraries.matrix.api.roomlist.RoomSummary
 import kotlinx.coroutines.CompletableDeferred
 import kotlinx.coroutines.flow.MutableStateFlow
 import kotlinx.coroutines.sync.Mutex
@@ -50,12 +50,14 @@ class RoomSummaryListProcessor(
         initLatch.complete(Unit)
     }
 
-    suspend fun postUpdate(update: RoomListEntriesUpdate) {
+    suspend fun postUpdate(updates: List) {
         // Makes sure to process first entries before update.
         initLatch.await()
         updateRoomSummaries {
-            Timber.v("Update rooms from postUpdate ($update) on ${Thread.currentThread()}")
-            applyUpdate(update)
+            Timber.v("Update rooms from postUpdates (with ${updates.size} items) on ${Thread.currentThread()}")
+            updates.forEach { update ->
+                applyUpdate(update)
+            }
         }
     }
 
diff --git a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/roomlist/RustRoomList.kt b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/roomlist/RustRoomList.kt
new file mode 100644
index 0000000000..481b38dd9b
--- /dev/null
+++ b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/roomlist/RustRoomList.kt
@@ -0,0 +1,29 @@
+/*
+ * Copyright (c) 2023 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
+ *
+ *     http://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.roomlist
+
+import io.element.android.libraries.matrix.api.roomlist.RoomList
+import io.element.android.libraries.matrix.api.roomlist.RoomSummary
+import kotlinx.coroutines.flow.StateFlow
+
+/**
+ * Simple implementation of [RoomList] where state flows are provided through constructor.
+ */
+class RustRoomList(
+    override val summaries: StateFlow>,
+    override val loadingState: StateFlow
+) : RoomList
diff --git a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/roomlist/RustRoomListService.kt b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/roomlist/RustRoomListService.kt
new file mode 100644
index 0000000000..bf66bade3b
--- /dev/null
+++ b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/roomlist/RustRoomListService.kt
@@ -0,0 +1,151 @@
+/*
+ * Copyright (c) 2023 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
+ *
+ *     http://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.roomlist
+
+import io.element.android.libraries.matrix.api.roomlist.RoomList
+import io.element.android.libraries.matrix.api.roomlist.RoomListService
+import io.element.android.libraries.matrix.api.roomlist.RoomSummary
+import kotlinx.coroutines.CoroutineDispatcher
+import kotlinx.coroutines.CoroutineScope
+import kotlinx.coroutines.flow.Flow
+import kotlinx.coroutines.flow.MutableStateFlow
+import kotlinx.coroutines.flow.SharingStarted
+import kotlinx.coroutines.flow.StateFlow
+import kotlinx.coroutines.flow.distinctUntilChanged
+import kotlinx.coroutines.flow.first
+import kotlinx.coroutines.flow.launchIn
+import kotlinx.coroutines.flow.map
+import kotlinx.coroutines.flow.onEach
+import kotlinx.coroutines.flow.stateIn
+import kotlinx.coroutines.launch
+import org.matrix.rustcomponents.sdk.RoomListEntriesUpdate
+import org.matrix.rustcomponents.sdk.RoomListException
+import org.matrix.rustcomponents.sdk.RoomListInput
+import org.matrix.rustcomponents.sdk.RoomListLoadingState
+import org.matrix.rustcomponents.sdk.RoomListRange
+import org.matrix.rustcomponents.sdk.RoomListServiceState
+import timber.log.Timber
+import org.matrix.rustcomponents.sdk.RoomListService as InnerRustRoomListService
+
+class RustRoomListService(
+    private val innerRoomListService: InnerRustRoomListService,
+    private val sessionCoroutineScope: CoroutineScope,
+    dispatcher: CoroutineDispatcher,
+    roomSummaryDetailsFactory: RoomSummaryDetailsFactory = RoomSummaryDetailsFactory(),
+) : RoomListService {
+
+    private val allRooms = MutableStateFlow>(emptyList())
+    private val inviteRooms = MutableStateFlow>(emptyList())
+
+    private val allRoomsLoadingState: MutableStateFlow = MutableStateFlow(RoomList.LoadingState.NotLoaded)
+    private val allRoomsListProcessor = RoomSummaryListProcessor(allRooms, innerRoomListService, roomSummaryDetailsFactory, shouldFetchFullRoom = false)
+    private val invitesLoadingState: MutableStateFlow = MutableStateFlow(RoomList.LoadingState.NotLoaded)
+    private val inviteRoomsListProcessor = RoomSummaryListProcessor(inviteRooms, innerRoomListService, roomSummaryDetailsFactory, shouldFetchFullRoom = true)
+
+    init {
+        sessionCoroutineScope.launch(dispatcher) {
+            val allRooms = innerRoomListService.allRooms()
+            allRooms
+                .observeEntriesWithProcessor(allRoomsListProcessor)
+                .launchIn(this)
+            allRooms
+                .observeLoadingState(allRoomsLoadingState)
+                .launchIn(this)
+
+
+            launch {
+                // Wait until running, as invites is only available after that
+                innerRoomListService.stateFlow().first {
+                    it == RoomListServiceState.RUNNING
+                }
+                val invites = innerRoomListService.invites()
+                invites
+                    .observeEntriesWithProcessor(inviteRoomsListProcessor)
+                    .launchIn(this)
+                invites
+                    .observeLoadingState(invitesLoadingState)
+                    .launchIn(this)
+
+            }
+        }
+    }
+
+    override fun allRooms(): RoomList {
+        return RustRoomList(allRooms, allRoomsLoadingState)
+    }
+
+    override fun invites(): RoomList {
+        return RustRoomList(inviteRooms, invitesLoadingState)
+    }
+
+    override fun updateAllRoomsVisibleRange(range: IntRange) {
+        Timber.v("setVisibleRange=$range")
+        sessionCoroutineScope.launch {
+            try {
+                val ranges = listOf(RoomListRange(range.first.toUInt(), range.last.toUInt()))
+                innerRoomListService.applyInput(
+                    RoomListInput.Viewport(ranges)
+                )
+            } catch (exception: RoomListException) {
+                Timber.e(exception, "Failed updating visible range")
+            }
+        }
+    }
+
+    override val state: StateFlow =
+        innerRoomListService.stateFlow()
+            .map { it.toRoomListState() }
+            .onEach { state ->
+                Timber.d("RoomList state=$state")
+            }
+            .distinctUntilChanged()
+            .stateIn(sessionCoroutineScope, SharingStarted.Eagerly, RoomListService.State.Idle)
+}
+
+private fun RoomListLoadingState.toLoadingState(): RoomList.LoadingState {
+    return when (this) {
+        is RoomListLoadingState.Loaded -> RoomList.LoadingState.Loaded(maximumNumberOfRooms?.toInt() ?: 0)
+        RoomListLoadingState.NotLoaded -> RoomList.LoadingState.NotLoaded
+    }
+}
+
+private fun RoomListServiceState.toRoomListState(): RoomListService.State {
+    return when (this) {
+        RoomListServiceState.INIT,
+        RoomListServiceState.SETTING_UP -> RoomListService.State.Idle
+        RoomListServiceState.RUNNING -> RoomListService.State.Running
+        RoomListServiceState.ERROR -> RoomListService.State.Error
+        RoomListServiceState.TERMINATED -> RoomListService.State.Terminated
+    }
+}
+
+private fun org.matrix.rustcomponents.sdk.RoomList.observeEntriesWithProcessor(processor: RoomSummaryListProcessor): Flow> {
+    return entriesFlow { roomListEntries ->
+        processor.postEntries(roomListEntries)
+    }.onEach { update ->
+        processor.postUpdate(update)
+    }
+}
+
+private fun org.matrix.rustcomponents.sdk.RoomList.observeLoadingState(stateFlow: MutableStateFlow): Flow {
+    return loadingStateFlow()
+        .map { it.toLoadingState() }
+        .onEach {
+            stateFlow.value = it
+        }
+}
+
diff --git a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/sync/AppStateMapper.kt b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/sync/AppStateMapper.kt
index 51228231f9..ae90f9fc44 100644
--- a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/sync/AppStateMapper.kt
+++ b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/sync/AppStateMapper.kt
@@ -17,19 +17,8 @@
 package io.element.android.libraries.matrix.impl.sync
 
 import io.element.android.libraries.matrix.api.sync.SyncState
-import org.matrix.rustcomponents.sdk.RoomListServiceState
 import org.matrix.rustcomponents.sdk.SyncServiceState
 
-internal fun RoomListServiceState.toSyncState(): SyncState {
-    return when (this) {
-        RoomListServiceState.INIT,
-        RoomListServiceState.SETTING_UP -> SyncState.Idle
-        RoomListServiceState.RUNNING -> SyncState.Running
-        RoomListServiceState.ERROR -> SyncState.Error
-        RoomListServiceState.TERMINATED -> SyncState.Terminated
-    }
-}
-
 internal fun SyncServiceState.toSyncState(): SyncState {
     return when (this) {
         SyncServiceState.IDLE -> SyncState.Idle
diff --git a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/sync/RustSyncService.kt b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/sync/RustSyncService.kt
index ca40ca400c..932da42afb 100644
--- a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/sync/RustSyncService.kt
+++ b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/sync/RustSyncService.kt
@@ -19,38 +19,40 @@ package io.element.android.libraries.matrix.impl.sync
 import io.element.android.libraries.matrix.api.sync.SyncService
 import io.element.android.libraries.matrix.api.sync.SyncState
 import kotlinx.coroutines.CoroutineScope
-import kotlinx.coroutines.flow.Flow
 import kotlinx.coroutines.flow.SharingStarted
 import kotlinx.coroutines.flow.StateFlow
 import kotlinx.coroutines.flow.distinctUntilChanged
 import kotlinx.coroutines.flow.map
 import kotlinx.coroutines.flow.onEach
 import kotlinx.coroutines.flow.stateIn
-import org.matrix.rustcomponents.sdk.RoomListServiceState
 import org.matrix.rustcomponents.sdk.SyncServiceInterface
+import org.matrix.rustcomponents.sdk.SyncServiceState
 import timber.log.Timber
 
 class RustSyncService(
     private val innerSyncService: SyncServiceInterface,
-    roomListStateFlow: Flow,
     sessionCoroutineScope: CoroutineScope
 ) : SyncService {
 
     override suspend fun startSync() = runCatching {
-        Timber.v("Start sync")
+        Timber.i("Start sync")
         innerSyncService.start()
+    }.onFailure {
+        Timber.d("Start sync failed: $it")
     }
 
-    override fun stopSync() = runCatching {
-        Timber.v("Stop sync")
-        innerSyncService.pause()
+    override suspend fun stopSync() = runCatching {
+        Timber.i("Stop sync")
+        innerSyncService.stop()
+    }.onFailure {
+        Timber.d("Stop sync failed: $it")
     }
 
     override val syncState: StateFlow =
-        roomListStateFlow
-            .map(RoomListServiceState::toSyncState)
+        innerSyncService.stateFlow()
+            .map(SyncServiceState::toSyncState)
             .onEach { state ->
-                Timber.v("Sync state=$state")
+                Timber.i("Sync state=$state")
             }
             .distinctUntilChanged()
             .stateIn(sessionCoroutineScope, SharingStarted.Eagerly, SyncState.Idle)
diff --git a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/sync/SyncServiceExtension.kt b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/sync/SyncServiceExtension.kt
index 36dabb71f3..c9e38ec7d4 100644
--- a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/sync/SyncServiceExtension.kt
+++ b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/sync/SyncServiceExtension.kt
@@ -16,21 +16,24 @@
 
 package io.element.android.libraries.matrix.impl.sync
 
+import io.element.android.libraries.core.data.tryOrNull
 import io.element.android.libraries.matrix.impl.util.mxCallbackFlow
 import kotlinx.coroutines.channels.Channel
 import kotlinx.coroutines.channels.trySendBlocking
 import kotlinx.coroutines.flow.Flow
 import kotlinx.coroutines.flow.buffer
-import org.matrix.rustcomponents.sdk.SyncService
+import org.matrix.rustcomponents.sdk.SyncServiceInterface
 import org.matrix.rustcomponents.sdk.SyncServiceState
 import org.matrix.rustcomponents.sdk.SyncServiceStateObserver
 
-fun SyncService.stateFlow(): Flow =
+fun SyncServiceInterface.stateFlow(): Flow =
     mxCallbackFlow {
         val listener = object : SyncServiceStateObserver {
             override fun onUpdate(state: SyncServiceState) {
                 trySendBlocking(state)
             }
         }
-        state(listener)
+        tryOrNull {
+            state(listener)
+        }
     }.buffer(Channel.UNLIMITED)
diff --git a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/timeline/MatrixTimelineDiffProcessor.kt b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/timeline/MatrixTimelineDiffProcessor.kt
index b14d459697..fd880e7fe3 100644
--- a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/timeline/MatrixTimelineDiffProcessor.kt
+++ b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/timeline/MatrixTimelineDiffProcessor.kt
@@ -23,6 +23,7 @@ import kotlinx.coroutines.sync.withLock
 import org.matrix.rustcomponents.sdk.TimelineChange
 import org.matrix.rustcomponents.sdk.TimelineDiff
 import org.matrix.rustcomponents.sdk.TimelineItem
+import timber.log.Timber
 
 internal class MatrixTimelineDiffProcessor(
     private val timelineItems: MutableStateFlow>,
@@ -33,14 +34,18 @@ internal class MatrixTimelineDiffProcessor(
 
     suspend fun postItems(items: List) {
         updateTimelineItems {
+            Timber.v("Update timeline items from postItems (with ${items.size} items) on ${Thread.currentThread()}")
             val mappedItems = items.map { it.asMatrixTimelineItem() }
             addAll(0, mappedItems)
         }
     }
 
-    suspend fun postDiff(diff: TimelineDiff) {
+    suspend fun postDiffs(diffs: List) {
         updateTimelineItems {
-            applyDiff(diff)
+            Timber.v("Update timeline items from postDiffs (with ${diffs.size} items) on ${Thread.currentThread()}")
+            diffs.forEach { diff ->
+                applyDiff(diff)
+            }
         }
     }
 
diff --git a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/timeline/RoomTimelineExtensions.kt b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/timeline/RoomTimelineExtensions.kt
index d6febb32dc..bddd2bc872 100644
--- a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/timeline/RoomTimelineExtensions.kt
+++ b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/timeline/RoomTimelineExtensions.kt
@@ -16,28 +16,47 @@
 
 package io.element.android.libraries.matrix.impl.timeline
 
+import io.element.android.libraries.core.data.tryOrNull
+import io.element.android.libraries.matrix.impl.util.cancelAndDestroy
+import io.element.android.libraries.matrix.impl.util.destroyAll
 import io.element.android.libraries.matrix.impl.util.mxCallbackFlow
 import kotlinx.coroutines.channels.Channel
+import kotlinx.coroutines.channels.awaitClose
 import kotlinx.coroutines.channels.trySendBlocking
 import kotlinx.coroutines.flow.Flow
 import kotlinx.coroutines.flow.buffer
+import kotlinx.coroutines.flow.callbackFlow
+import kotlinx.coroutines.flow.catch
 import org.matrix.rustcomponents.sdk.BackPaginationStatus
 import org.matrix.rustcomponents.sdk.BackPaginationStatusListener
 import org.matrix.rustcomponents.sdk.Room
 import org.matrix.rustcomponents.sdk.TimelineDiff
 import org.matrix.rustcomponents.sdk.TimelineItem
 import org.matrix.rustcomponents.sdk.TimelineListener
+import timber.log.Timber
 
-internal fun Room.timelineDiffFlow(onInitialList: suspend (List) -> Unit): Flow =
-    mxCallbackFlow {
+internal fun Room.timelineDiffFlow(onInitialList: suspend (List) -> Unit): Flow> =
+    callbackFlow {
         val listener = object : TimelineListener {
-            override fun onUpdate(diff: TimelineDiff) {
+            override fun onUpdate(diff: List) {
                 trySendBlocking(diff)
             }
         }
+        val roomId = id()
+        Timber.d("Open timelineDiffFlow for room $roomId")
         val result = addTimelineListener(listener)
-        onInitialList(result.items)
-        result.itemsStream
+        try {
+            onInitialList(result.items)
+        } catch (exception: Exception) {
+            Timber.d(exception, "Catch failure in timelineDiffFlow of room $roomId")
+        }
+        awaitClose {
+            Timber.d("Close timelineDiffFlow for room $roomId")
+            result.itemsStream.cancelAndDestroy()
+            result.items.destroyAll()
+        }
+    }.catch {
+        Timber.d(it, "timelineDiffFlow() failed")
     }.buffer(Channel.UNLIMITED)
 
 internal fun Room.backPaginationStatusFlow(): Flow =
@@ -47,5 +66,7 @@ internal fun Room.backPaginationStatusFlow(): Flow =
                 trySendBlocking(status)
             }
         }
-        subscribeToBackPaginationStatus(listener)
+        tryOrNull {
+            subscribeToBackPaginationStatus(listener)
+        }
     }.buffer(Channel.UNLIMITED)
diff --git a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/timeline/RustMatrixTimeline.kt b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/timeline/RustMatrixTimeline.kt
index e213fb623c..aa8427608d 100644
--- a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/timeline/RustMatrixTimeline.kt
+++ b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/timeline/RustMatrixTimeline.kt
@@ -26,28 +26,33 @@ import io.element.android.libraries.matrix.impl.timeline.item.event.EventMessage
 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
-import kotlinx.coroutines.CompletableDeferred
 import io.element.android.libraries.matrix.impl.timeline.postprocessor.TimelineEncryptedHistoryPostProcessor
+import io.element.android.libraries.matrix.impl.util.TaskHandleBag
+import kotlinx.coroutines.CompletableDeferred
 import kotlinx.coroutines.CoroutineDispatcher
 import kotlinx.coroutines.CoroutineScope
 import kotlinx.coroutines.ExperimentalCoroutinesApi
-import kotlinx.coroutines.FlowPreview
+import kotlinx.coroutines.coroutineScope
+import kotlinx.coroutines.ensureActive
 import kotlinx.coroutines.flow.Flow
 import kotlinx.coroutines.flow.MutableStateFlow
 import kotlinx.coroutines.flow.StateFlow
 import kotlinx.coroutines.flow.asStateFlow
 import kotlinx.coroutines.flow.getAndUpdate
+import kotlinx.coroutines.flow.launchIn
 import kotlinx.coroutines.flow.mapLatest
-import kotlinx.coroutines.flow.sample
+import kotlinx.coroutines.flow.onEach
+import kotlinx.coroutines.launch
 import kotlinx.coroutines.withContext
 import org.matrix.rustcomponents.sdk.BackPaginationStatus
+import org.matrix.rustcomponents.sdk.EventItemOrigin
 import org.matrix.rustcomponents.sdk.PaginationOptions
 import org.matrix.rustcomponents.sdk.Room
 import org.matrix.rustcomponents.sdk.TimelineDiff
 import org.matrix.rustcomponents.sdk.TimelineItem
 import timber.log.Timber
-import java.util.concurrent.atomic.AtomicBoolean
 import java.util.Date
+import java.util.concurrent.atomic.AtomicBoolean
 
 private const val INITIAL_MAX_SIZE = 50
 
@@ -57,6 +62,7 @@ class RustMatrixTimeline(
     private val innerRoom: Room,
     private val dispatcher: CoroutineDispatcher,
     private val lastLoginTimestamp: Date?,
+    private val onNewSyncedEvent: () -> Unit,
 ) : MatrixTimeline {
 
     private val initLatch = CompletableDeferred()
@@ -73,6 +79,7 @@ class RustMatrixTimeline(
         lastLoginTimestamp = lastLoginTimestamp,
         isRoomEncrypted = matrixRoom.isEncrypted,
         paginationStateFlow = _paginationState,
+        dispatcher = dispatcher,
     )
 
     private val timelineItemFactory = MatrixTimelineItemMapper(
@@ -93,27 +100,60 @@ class RustMatrixTimeline(
 
     override val paginationState: StateFlow = _paginationState.asStateFlow()
 
-    @OptIn(FlowPreview::class, ExperimentalCoroutinesApi::class)
-    override val timelineItems: Flow> = _timelineItems.sample(50)
-        .mapLatest { items ->
-            encryptedHistoryPostProcessor.process(items)
-        }
+    init {
+        Timber.d("Initialize timeline for room ${matrixRoom.roomId}")
 
-    internal suspend fun postItems(items: List) {
+        val taskHandleBag = TaskHandleBag()
+        roomCoroutineScope.launch(dispatcher) {
+            innerRoom.timelineDiffFlow { initialList ->
+                postItems(initialList)
+            }.onEach { diffs ->
+                if (diffs.any { diff -> diff.eventOrigin() == EventItemOrigin.SYNC }) {
+                    onNewSyncedEvent()
+                }
+                postDiffs(diffs)
+            }.launchIn(this)
+
+            innerRoom.backPaginationStatusFlow()
+                .onEach {
+                    postPaginationStatus(it)
+                }
+                .launchIn(this)
+
+            taskHandleBag += fetchMembers().getOrNull()
+        }.invokeOnCompletion {
+            taskHandleBag.dispose()
+        }
+    }
+
+    private suspend fun fetchMembers() = withContext(dispatcher) {
+        initLatch.await()
+        runCatching {
+            innerRoom.fetchMembers()
+        }
+    }
+
+    @OptIn(ExperimentalCoroutinesApi::class)
+    override val timelineItems: Flow> = _timelineItems.mapLatest { items ->
+        encryptedHistoryPostProcessor.process(items)
+    }
+
+    private suspend fun postItems(items: List) = coroutineScope {
         // Split the initial items in multiple list as there is no pagination in the cached data, so we can post timelineItems asap.
         items.chunked(INITIAL_MAX_SIZE).reversed().forEach {
+            ensureActive()
             timelineDiffProcessor.postItems(it)
         }
         isInit.set(true)
         initLatch.complete(Unit)
     }
 
-    internal suspend fun postDiff(timelineDiff: TimelineDiff) {
+    private suspend fun postDiffs(diffs: List) {
         initLatch.await()
-        timelineDiffProcessor.postDiff(timelineDiff)
+        timelineDiffProcessor.postDiffs(diffs)
     }
 
-    internal fun postPaginationStatus(status: BackPaginationStatus) {
+    private fun postPaginationStatus(status: BackPaginationStatus) {
         _paginationState.getAndUpdate { currentPaginationState ->
             if (hasEncryptionHistoryBanner()) {
                 return@getAndUpdate currentPaginationState.copy(
diff --git a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/timeline/item/event/EventMessageMapper.kt b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/timeline/item/event/EventMessageMapper.kt
index 9f4df1f6b3..330a06da62 100644
--- a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/timeline/item/event/EventMessageMapper.kt
+++ b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/timeline/item/event/EventMessageMapper.kt
@@ -42,16 +42,18 @@ import org.matrix.rustcomponents.sdk.MessageType as RustMessageType
 
 class EventMessageMapper {
 
+    private val timelineEventContentMapper by lazy { TimelineEventContentMapper() }
+
     fun map(message: Message): MessageContent = message.use {
         val type = it.msgtype().use(this::mapMessageType)
         val inReplyToId = it.inReplyTo()?.eventId?.let(::EventId)
-        val inReplyToEvent: InReplyTo? = (it.inReplyTo()?.event)?.use { details ->
+        val inReplyToEvent: InReplyTo? = it.inReplyTo()?.event?.use { details ->
             when (details) {
                 is RepliedToEventDetails.Ready -> {
                     val senderProfile = details.senderProfile as? ProfileDetails.Ready
                     InReplyTo.Ready(
                         eventId = inReplyToId!!,
-                        content = map(details.message),
+                        content = timelineEventContentMapper.map(details.content),
                         senderId = UserId(details.sender),
                         senderDisplayName = senderProfile?.displayName,
                         senderAvatarUrl = senderProfile?.avatarUrl,
diff --git a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/timeline/item/event/EventTimelineItemMapper.kt b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/timeline/item/event/EventTimelineItemMapper.kt
index 359b9ecdef..21e7d51638 100644
--- a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/timeline/item/event/EventTimelineItemMapper.kt
+++ b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/timeline/item/event/EventTimelineItemMapper.kt
@@ -25,6 +25,7 @@ import io.element.android.libraries.matrix.api.timeline.item.event.EventReaction
 import io.element.android.libraries.matrix.api.timeline.item.event.EventTimelineItem
 import io.element.android.libraries.matrix.api.timeline.item.event.LocalEventSendState
 import io.element.android.libraries.matrix.api.timeline.item.event.ProfileTimelineDetails
+import io.element.android.libraries.matrix.api.timeline.item.event.ReactionSender
 import org.matrix.rustcomponents.sdk.Reaction
 import org.matrix.rustcomponents.sdk.EventItemOrigin as RustEventItemOrigin
 import org.matrix.rustcomponents.sdk.EventSendState as RustEventSendState
@@ -81,8 +82,12 @@ private fun List?.map(): List {
     return this?.map {
         EventReaction(
             key = it.key,
-            count = it.count.toLong(),
-            senderIds = it.senders.map { sender -> UserId(sender.senderId) }
+            senders = it.senders.map { sender ->
+                ReactionSender(
+                    senderId = UserId(sender.senderId),
+                    timestamp = sender.timestamp.toLong()
+                )
+            }
         )
     } ?: emptyList()
 }
diff --git a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/timeline/item/event/TimelineEventContentMapper.kt b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/timeline/item/event/TimelineEventContentMapper.kt
index 33727c15d4..7ee1d1490d 100644
--- a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/timeline/item/event/TimelineEventContentMapper.kt
+++ b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/timeline/item/event/TimelineEventContentMapper.kt
@@ -22,6 +22,8 @@ import io.element.android.libraries.matrix.api.timeline.item.event.FailedToParse
 import io.element.android.libraries.matrix.api.timeline.item.event.FailedToParseStateContent
 import io.element.android.libraries.matrix.api.timeline.item.event.MembershipChange
 import io.element.android.libraries.matrix.api.timeline.item.event.OtherState
+import io.element.android.libraries.matrix.api.timeline.item.event.PollContent
+import io.element.android.libraries.matrix.api.timeline.item.event.PollEndContent
 import io.element.android.libraries.matrix.api.timeline.item.event.ProfileChangeContent
 import io.element.android.libraries.matrix.api.timeline.item.event.RedactedContent
 import io.element.android.libraries.matrix.api.timeline.item.event.RoomMembershipContent
@@ -30,6 +32,7 @@ import io.element.android.libraries.matrix.api.timeline.item.event.StickerConten
 import io.element.android.libraries.matrix.api.timeline.item.event.UnableToDecryptContent
 import io.element.android.libraries.matrix.api.timeline.item.event.UnknownContent
 import io.element.android.libraries.matrix.impl.media.map
+import io.element.android.libraries.matrix.impl.poll.map
 import org.matrix.rustcomponents.sdk.TimelineItemContent
 import org.matrix.rustcomponents.sdk.TimelineItemContentKind
 import org.matrix.rustcomponents.sdk.EncryptedMessage as RustEncryptedMessage
@@ -91,11 +94,27 @@ class TimelineEventContentMapper(private val eventMessageMapper: EventMessageMap
                     url = kind.url,
                 )
             }
+            is TimelineItemContentKind.Poll -> {
+                PollContent(
+                    question = kind.question,
+                    kind = kind.kind.map(),
+                    maxSelections = kind.maxSelections,
+                    answers = kind.answers.map { answer -> answer.map() },
+                    votes = kind.votes.mapValues { vote ->
+                        vote.value.map { userId -> UserId(userId) }
+                    },
+                    endTime = kind.endTime,
+                )
+            }
+            is TimelineItemContentKind.PollEnd -> {
+                PollEndContent(startEventId = kind.startEventId)
+            }
             is TimelineItemContentKind.UnableToDecrypt -> {
                 UnableToDecryptContent(
                     data = kind.msg.map()
                 )
             }
+            else -> UnknownContent
         }
     }
 }
diff --git a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/timeline/postprocessor/TimelineEncryptedHistoryPostProcessor.kt b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/timeline/postprocessor/TimelineEncryptedHistoryPostProcessor.kt
index ca5c7342f8..b273bef21b 100644
--- a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/timeline/postprocessor/TimelineEncryptedHistoryPostProcessor.kt
+++ b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/timeline/postprocessor/TimelineEncryptedHistoryPostProcessor.kt
@@ -19,19 +19,23 @@ package io.element.android.libraries.matrix.impl.timeline.postprocessor
 import io.element.android.libraries.matrix.api.timeline.MatrixTimeline
 import io.element.android.libraries.matrix.api.timeline.MatrixTimelineItem
 import io.element.android.libraries.matrix.api.timeline.item.virtual.VirtualTimelineItem
+import kotlinx.coroutines.CoroutineDispatcher
 import kotlinx.coroutines.flow.MutableStateFlow
 import kotlinx.coroutines.flow.getAndUpdate
+import kotlinx.coroutines.withContext
+import timber.log.Timber
 import java.util.Date
-import java.util.UUID
 
 class TimelineEncryptedHistoryPostProcessor(
+    private val dispatcher: CoroutineDispatcher,
     private val lastLoginTimestamp: Date?,
     private val isRoomEncrypted: Boolean,
     private val paginationStateFlow: MutableStateFlow,
 ) {
 
-    fun process(items: List): List {
-        if (!isRoomEncrypted || lastLoginTimestamp == null) return items
+    suspend fun process(items: List): List = withContext(dispatcher) {
+        Timber.d("Process on Thread=${Thread.currentThread()}")
+        if (!isRoomEncrypted || lastLoginTimestamp == null) return@withContext items
 
         val filteredItems = replaceWithEncryptionHistoryBannerIfNeeded(items)
         // Disable back pagination
@@ -44,7 +48,7 @@ class TimelineEncryptedHistoryPostProcessor(
                 )
             }
         }
-        return filteredItems
+        filteredItems
     }
 
     private fun replaceWithEncryptionHistoryBannerIfNeeded(list: List): List {
@@ -70,5 +74,4 @@ class TimelineEncryptedHistoryPostProcessor(
         val timestamp = (item as? MatrixTimelineItem.Event)?.event?.timestamp ?: return false
         return timestamp <= lastLoginTimestamp!!.time
     }
-
 }
diff --git a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/tracing/LogEventLocation.kt b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/tracing/LogEventLocation.kt
new file mode 100644
index 0000000000..712735649c
--- /dev/null
+++ b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/tracing/LogEventLocation.kt
@@ -0,0 +1,40 @@
+/*
+ * Copyright (c) 2023 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
+ *
+ *     http://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.tracing
+
+/**
+ * This class is used to provide file, line, column information to the Rust SDK [org.matrix.rustcomponents.sdk.logEvent] method.
+ * The data is extracted from a [StackTraceElement] instance.
+ */
+data class LogEventLocation(
+    val file: String,
+    val line: UInt?,
+) {
+
+    companion object {
+        /**
+         * Create a [LogEventLocation] from a [StackTraceElement].
+         */
+        fun from(stackTraceElement: StackTraceElement): LogEventLocation {
+            return LogEventLocation(
+                file = stackTraceElement.fileName ?: "",
+                line = stackTraceElement.lineNumber.takeIf { it >= 0 }?.toUInt()
+            )
+        }
+    }
+}
+
diff --git a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/tracing/RustTracingService.kt b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/tracing/RustTracingService.kt
new file mode 100644
index 0000000000..c211f48c05
--- /dev/null
+++ b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/tracing/RustTracingService.kt
@@ -0,0 +1,52 @@
+/*
+ * Copyright (c) 2023 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
+ *
+ *     http://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.tracing
+
+import com.squareup.anvil.annotations.ContributesBinding
+import io.element.android.libraries.core.meta.BuildMeta
+import io.element.android.libraries.di.AppScope
+import io.element.android.libraries.matrix.api.tracing.TracingConfiguration
+import io.element.android.libraries.matrix.api.tracing.TracingService
+import io.element.android.libraries.matrix.api.tracing.WriteToFilesConfiguration
+import org.matrix.rustcomponents.sdk.TracingFileConfiguration
+import timber.log.Timber
+import javax.inject.Inject
+
+@ContributesBinding(AppScope::class)
+class RustTracingService @Inject constructor(private val buildMeta: BuildMeta) : TracingService {
+
+    override fun setupTracing(tracingConfiguration: TracingConfiguration) {
+        val filter = tracingConfiguration.filterConfiguration
+        val rustTracingConfiguration = org.matrix.rustcomponents.sdk.TracingConfiguration(
+            filter = tracingConfiguration.filterConfiguration.filter,
+            writeToStdoutOrSystem = tracingConfiguration.writesToLogcat,
+            writeToFiles = when (val writeToFilesConfiguration = tracingConfiguration.writesToFilesConfiguration) {
+                is WriteToFilesConfiguration.Disabled -> null
+                is WriteToFilesConfiguration.Enabled -> TracingFileConfiguration(
+                    path = writeToFilesConfiguration.directory,
+                    filePrefix = writeToFilesConfiguration.filenamePrefix,
+                )
+            },
+        )
+        org.matrix.rustcomponents.sdk.setupTracing(rustTracingConfiguration)
+        Timber.v("Tracing config filter = $filter")
+    }
+
+    override fun createTimberTree(): Timber.Tree {
+        return RustTracingTree(retrieveFromStackTrace = buildMeta.isDebuggable)
+    }
+}
diff --git a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/tracing/RustTracingTree.kt b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/tracing/RustTracingTree.kt
new file mode 100644
index 0000000000..275994081d
--- /dev/null
+++ b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/tracing/RustTracingTree.kt
@@ -0,0 +1,78 @@
+/*
+ * Copyright (c) 2023 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
+ *
+ *     http://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.tracing
+
+import android.util.Log
+import io.element.android.libraries.matrix.api.tracing.Target
+import org.matrix.rustcomponents.sdk.LogLevel
+import org.matrix.rustcomponents.sdk.logEvent
+import timber.log.Timber
+
+/**
+ * List of fully qualified class names to ignore when looking for the first stack trace element.
+ */
+private val fqcnIgnore = listOf(
+    Timber::class.java.name,
+    Timber.Forest::class.java.name,
+    Timber.Tree::class.java.name,
+    RustTracingTree::class.java.name,
+)
+
+/**
+ * A Timber tree that passes logs to the Rust SDK.
+ */
+internal class RustTracingTree(private val retrieveFromStackTrace: Boolean) : Timber.Tree() {
+
+    override fun log(priority: Int, tag: String?, message: String, t: Throwable?) {
+        val location = if (retrieveFromStackTrace) {
+            getLogEventLocationFromStackTrace()
+        } else {
+            LogEventLocation("", null)
+        }
+        val logLevel = priority.toLogLevel()
+        logEvent(
+            file = location.file,
+            line = location.line,
+            level = logLevel,
+            target = Target.ELEMENT.filter,
+            message = message,
+        )
+    }
+
+    /**
+     * Extract the [LogEventLocation] from the stack trace.
+     */
+    private fun getLogEventLocationFromStackTrace(): LogEventLocation {
+        return Throwable(null, null).stackTrace
+            .first { it.className !in fqcnIgnore }
+            .let(LogEventLocation::from)
+    }
+}
+
+/**
+ * Convert a log priority to a Rust SDK log level.
+ */
+private fun Int.toLogLevel(): LogLevel {
+    return when (this) {
+        Log.VERBOSE -> LogLevel.TRACE
+        Log.DEBUG -> LogLevel.DEBUG
+        Log.INFO -> LogLevel.INFO
+        Log.WARN -> LogLevel.WARN
+        Log.ERROR -> LogLevel.ERROR
+        else -> LogLevel.DEBUG
+    }
+}
diff --git a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/util/CallbackFlow.kt b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/util/CallbackFlow.kt
index a347973e89..fbf393e587 100644
--- a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/util/CallbackFlow.kt
+++ b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/util/CallbackFlow.kt
@@ -21,11 +21,10 @@ import kotlinx.coroutines.channels.awaitClose
 import kotlinx.coroutines.flow.callbackFlow
 import org.matrix.rustcomponents.sdk.TaskHandle
 
-internal fun  mxCallbackFlow(block: suspend ProducerScope.() -> TaskHandle) =
+internal fun  mxCallbackFlow(block: suspend ProducerScope.() -> TaskHandle?) =
     callbackFlow {
-        val token: TaskHandle = block(this)
+        val taskHandle: TaskHandle? = block(this)
         awaitClose {
-            token.cancel()
-            token.destroy()
+            taskHandle?.cancelAndDestroy()
         }
     }
diff --git a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/util/Disposables.kt b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/util/Disposables.kt
new file mode 100644
index 0000000000..ac92a2e026
--- /dev/null
+++ b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/util/Disposables.kt
@@ -0,0 +1,24 @@
+/*
+ * Copyright (c) 2023 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
+ *
+ *     http://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 org.matrix.rustcomponents.sdk.Disposable
+
+/**
+ * Call destroy on all elements of the iterable.
+ */
+internal fun Iterable.destroyAll() = forEach { it.destroy() }
diff --git a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/util/TaskHandleBag.kt b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/util/TaskHandle.kt
similarity index 73%
rename from libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/util/TaskHandleBag.kt
rename to libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/util/TaskHandle.kt
index 9a21645351..5842ba1546 100644
--- a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/util/TaskHandleBag.kt
+++ b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/util/TaskHandle.kt
@@ -19,18 +19,22 @@ package io.element.android.libraries.matrix.impl.util
 import org.matrix.rustcomponents.sdk.TaskHandle
 import java.util.concurrent.CopyOnWriteArraySet
 
-class TaskHandleBag(private val tokens: MutableSet = CopyOnWriteArraySet()) : Set by tokens {
+fun TaskHandle.cancelAndDestroy() {
+    cancel()
+    destroy()
+}
+
+class TaskHandleBag(private val taskHandles: MutableSet = CopyOnWriteArraySet()) : Set by taskHandles {
 
     operator fun plusAssign(taskHandle: TaskHandle?) {
         if (taskHandle == null) return
-        tokens += taskHandle
+        taskHandles += taskHandle
     }
 
     fun dispose() {
-        tokens.forEach {
-            it.cancel()
-            it.destroy()
+        taskHandles.forEach {
+            it.cancelAndDestroy()
         }
-        tokens.clear()
+        taskHandles.clear()
     }
 }
diff --git a/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/timeline/postprocessor/TimelineEncryptedHistoryPostProcessorTest.kt b/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/timeline/postprocessor/TimelineEncryptedHistoryPostProcessorTest.kt
index 91f0bc1883..63920cd6ce 100644
--- a/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/timeline/postprocessor/TimelineEncryptedHistoryPostProcessorTest.kt
+++ b/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/timeline/postprocessor/TimelineEncryptedHistoryPostProcessorTest.kt
@@ -22,15 +22,18 @@ import io.element.android.libraries.matrix.api.timeline.MatrixTimelineItem
 import io.element.android.libraries.matrix.api.timeline.item.virtual.VirtualTimelineItem
 import io.element.android.libraries.matrix.test.room.anEventTimelineItem
 import kotlinx.coroutines.flow.MutableStateFlow
+import kotlinx.coroutines.test.StandardTestDispatcher
+import kotlinx.coroutines.test.TestScope
+import kotlinx.coroutines.test.runTest
 import org.junit.Test
 import java.util.Date
 
 class TimelineEncryptedHistoryPostProcessorTest {
 
-    private val defaultLastLoginTimestamp = Date(1689061264L)
+    private val defaultLastLoginTimestamp = Date(1_689_061_264L)
 
     @Test
-    fun `given an unencrypted room, nothing is done`() {
+    fun `given an unencrypted room, nothing is done`() = runTest {
         val processor = createPostProcessor(isRoomEncrypted = false)
         val items = listOf(
             MatrixTimelineItem.Event(0L, anEventTimelineItem())
@@ -39,7 +42,7 @@ class TimelineEncryptedHistoryPostProcessorTest {
     }
 
     @Test
-    fun `given a null lastLoginTimestamp, nothing is done`() {
+    fun `given a null lastLoginTimestamp, nothing is done`() = runTest {
         val processor = createPostProcessor(lastLoginTimestamp = null)
         val items = listOf(
             MatrixTimelineItem.Event(0L, anEventTimelineItem())
@@ -48,14 +51,14 @@ class TimelineEncryptedHistoryPostProcessorTest {
     }
 
     @Test
-    fun `given an empty list, nothing is done`() {
+    fun `given an empty list, nothing is done`() = runTest {
         val processor = createPostProcessor()
         val items = emptyList()
         assertThat(processor.process(items)).isSameInstanceAs(items)
     }
 
     @Test
-    fun `given a list with no items before lastLoginTimestamp, nothing is done`() {
+    fun `given a list with no items before lastLoginTimestamp, nothing is done`() = runTest {
         val processor = createPostProcessor()
         val items = listOf(
             MatrixTimelineItem.Event(0L, anEventTimelineItem(timestamp = defaultLastLoginTimestamp.time + 1))
@@ -64,7 +67,7 @@ class TimelineEncryptedHistoryPostProcessorTest {
     }
 
     @Test
-    fun `given a list with an item with equal timestamp as lastLoginTimestamp, it's replaced`() {
+    fun `given a list with an item with equal timestamp as lastLoginTimestamp, it's replaced`() = runTest {
         val processor = createPostProcessor()
         val items = listOf(
             MatrixTimelineItem.Event(0L, anEventTimelineItem(timestamp = defaultLastLoginTimestamp.time))
@@ -74,7 +77,7 @@ class TimelineEncryptedHistoryPostProcessorTest {
     }
 
     @Test
-    fun `given a list with an item with a lower timestamp than lastLoginTimestamp, it's replaced`() {
+    fun `given a list with an item with a lower timestamp than lastLoginTimestamp, it's replaced`() = runTest {
         val processor = createPostProcessor()
         val items = listOf(
             MatrixTimelineItem.Event(0L, anEventTimelineItem(timestamp = defaultLastLoginTimestamp.time - 1))
@@ -85,7 +88,7 @@ class TimelineEncryptedHistoryPostProcessorTest {
     }
 
     @Test
-    fun `given a list with several with lower or equal timestamps than lastLoginTimestamp, they're replaced and the user can't back paginate`() {
+    fun `given a list with several with lower or equal timestamps than lastLoginTimestamp, they're replaced and the user can't back paginate`() = runTest {
         val paginationStateFlow = MutableStateFlow(MatrixTimeline.PaginationState(hasMoreToLoadBackwards = true, isBackPaginating = false))
         val processor = createPostProcessor(paginationStateFlow = paginationStateFlow)
         val items = listOf(
@@ -102,7 +105,7 @@ class TimelineEncryptedHistoryPostProcessorTest {
         assertThat(paginationStateFlow.value).isEqualTo(MatrixTimeline.PaginationState(hasMoreToLoadBackwards = false, isBackPaginating = false))
     }
 
-    private fun createPostProcessor(
+    private fun TestScope.createPostProcessor(
         lastLoginTimestamp: Date? = defaultLastLoginTimestamp,
         isRoomEncrypted: Boolean = true,
         paginationStateFlow: MutableStateFlow =
@@ -111,5 +114,6 @@ class TimelineEncryptedHistoryPostProcessorTest {
         lastLoginTimestamp = lastLoginTimestamp,
         isRoomEncrypted = isRoomEncrypted,
         paginationStateFlow = paginationStateFlow,
+        dispatcher = StandardTestDispatcher(testScheduler)
     )
 }
diff --git a/libraries/matrix/test/src/main/kotlin/io/element/android/libraries/matrix/test/FakeMatrixClient.kt b/libraries/matrix/test/src/main/kotlin/io/element/android/libraries/matrix/test/FakeMatrixClient.kt
index 1a654ac8d4..1229836e30 100644
--- a/libraries/matrix/test/src/main/kotlin/io/element/android/libraries/matrix/test/FakeMatrixClient.kt
+++ b/libraries/matrix/test/src/main/kotlin/io/element/android/libraries/matrix/test/FakeMatrixClient.kt
@@ -27,7 +27,7 @@ import io.element.android.libraries.matrix.api.notification.NotificationService
 import io.element.android.libraries.matrix.api.pusher.PushersService
 import io.element.android.libraries.matrix.api.room.MatrixRoom
 import io.element.android.libraries.matrix.api.room.RoomMembershipObserver
-import io.element.android.libraries.matrix.api.room.RoomSummaryDataSource
+import io.element.android.libraries.matrix.api.roomlist.RoomListService
 import io.element.android.libraries.matrix.api.user.MatrixSearchUserResults
 import io.element.android.libraries.matrix.api.user.MatrixUser
 import io.element.android.libraries.matrix.api.verification.SessionVerificationService
@@ -35,7 +35,7 @@ import io.element.android.libraries.matrix.test.media.FakeMediaLoader
 import io.element.android.libraries.matrix.test.notification.FakeNotificationService
 import io.element.android.libraries.matrix.test.pushers.FakePushersService
 import io.element.android.libraries.matrix.test.room.FakeMatrixRoom
-import io.element.android.libraries.matrix.test.room.FakeRoomSummaryDataSource
+import io.element.android.libraries.matrix.test.roomlist.FakeRoomListService
 import io.element.android.libraries.matrix.test.sync.FakeSyncService
 import io.element.android.libraries.matrix.test.verification.FakeSessionVerificationService
 import io.element.android.tests.testutils.simulateLongTask
@@ -45,7 +45,7 @@ class FakeMatrixClient(
     override val sessionId: SessionId = A_SESSION_ID,
     private val userDisplayName: Result = Result.success(A_USER_NAME),
     private val userAvatarURLString: Result = Result.success(AN_AVATAR_URL),
-    override val roomSummaryDataSource: RoomSummaryDataSource = FakeRoomSummaryDataSource(),
+    override val roomListService: RoomListService = FakeRoomListService(),
     override val mediaLoader: MatrixMediaLoader = FakeMediaLoader(),
     private val sessionVerificationService: FakeSessionVerificationService = FakeSessionVerificationService(),
     private val pushersService: FakePushersService = FakePushersService(),
diff --git a/libraries/matrix/test/src/main/kotlin/io/element/android/libraries/matrix/test/TestData.kt b/libraries/matrix/test/src/main/kotlin/io/element/android/libraries/matrix/test/TestData.kt
index 3da47a8563..677774afe4 100644
--- a/libraries/matrix/test/src/main/kotlin/io/element/android/libraries/matrix/test/TestData.kt
+++ b/libraries/matrix/test/src/main/kotlin/io/element/android/libraries/matrix/test/TestData.kt
@@ -24,7 +24,6 @@ import io.element.android.libraries.matrix.api.core.SpaceId
 import io.element.android.libraries.matrix.api.core.ThreadId
 import io.element.android.libraries.matrix.api.core.TransactionId
 import io.element.android.libraries.matrix.api.core.UserId
-import java.util.UUID
 
 const val A_USER_NAME = "alice"
 const val A_PASSWORD = "password"
diff --git a/libraries/matrix/test/src/main/kotlin/io/element/android/libraries/matrix/test/notification/FakeNotificationService.kt b/libraries/matrix/test/src/main/kotlin/io/element/android/libraries/matrix/test/notification/FakeNotificationService.kt
index 9eb5a20ba4..7cb92d35c5 100644
--- a/libraries/matrix/test/src/main/kotlin/io/element/android/libraries/matrix/test/notification/FakeNotificationService.kt
+++ b/libraries/matrix/test/src/main/kotlin/io/element/android/libraries/matrix/test/notification/FakeNotificationService.kt
@@ -23,7 +23,7 @@ import io.element.android.libraries.matrix.api.notification.NotificationData
 import io.element.android.libraries.matrix.api.notification.NotificationService
 
 class FakeNotificationService : NotificationService {
-    override fun getNotification(userId: SessionId, roomId: RoomId, eventId: EventId, filterByPushRules: Boolean): Result {
+    override suspend fun getNotification(userId: SessionId, roomId: RoomId, eventId: EventId): Result {
         return Result.success(null)
     }
 }
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 7fe7de5b9f..ee735ae81b 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,6 +56,7 @@ class FakeMatrixRoom(
     override val joinedMemberCount: Long = 123L,
     override val activeMemberCount: Long = 234L,
     private val matrixTimeline: MatrixTimeline = FakeMatrixTimeline(),
+    canRedact: Boolean = false,
 ) : MatrixRoom {
 
     private var ignoreResult: Result = Result.success(Unit)
@@ -66,6 +67,7 @@ class FakeMatrixRoom(
     private var joinRoomResult = Result.success(Unit)
     private var inviteUserResult = Result.success(Unit)
     private var canInviteResult = Result.success(true)
+    private var canRedactResult = Result.success(canRedact)
     private val canSendStateResults = mutableMapOf>()
     private val canSendEventResults = mutableMapOf>()
     private var sendMediaResult = Result.success(Unit)
@@ -100,7 +102,6 @@ class FakeMatrixRoom(
     private val _sentLocations = mutableListOf()
     val sentLocations: List = _sentLocations
 
-
     var invitedUserId: UserId? = null
         private set
 
@@ -128,9 +129,11 @@ class FakeMatrixRoom(
 
     override val timeline: MatrixTimeline = matrixTimeline
 
-    override fun open(): Result {
-        return Result.success(Unit)
-    }
+    override fun subscribeToSync() = Unit
+
+    override fun unsubscribeFromSync() = Unit
+
+    override fun destroy() = Unit
 
     override suspend fun userDisplayName(userId: UserId): Result = simulateLongTask {
         userDisplayNameResult
@@ -206,6 +209,10 @@ class FakeMatrixRoom(
         return canInviteResult
     }
 
+    override suspend fun canUserRedact(userId: UserId): Result {
+        return canRedactResult
+    }
+
     override suspend fun canUserSendState(userId: UserId, type: StateEventType): Result {
         return canSendStateResults[type] ?: Result.failure(IllegalStateException("No fake answer"))
     }
@@ -283,8 +290,6 @@ class FakeMatrixRoom(
         return sendLocationResult
     }
 
-    override fun close() = Unit
-
     fun givenLeaveRoomError(throwable: Throwable?) {
         this.leaveRoomError = throwable
     }
diff --git a/libraries/matrix/test/src/main/kotlin/io/element/android/libraries/matrix/test/room/RoomSummaryFixture.kt b/libraries/matrix/test/src/main/kotlin/io/element/android/libraries/matrix/test/room/RoomSummaryFixture.kt
index 4df815c54c..59bac7ad40 100644
--- a/libraries/matrix/test/src/main/kotlin/io/element/android/libraries/matrix/test/room/RoomSummaryFixture.kt
+++ b/libraries/matrix/test/src/main/kotlin/io/element/android/libraries/matrix/test/room/RoomSummaryFixture.kt
@@ -20,8 +20,8 @@ import io.element.android.libraries.matrix.api.core.EventId
 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.core.UserId
-import io.element.android.libraries.matrix.api.room.RoomSummary
-import io.element.android.libraries.matrix.api.room.RoomSummaryDetails
+import io.element.android.libraries.matrix.api.roomlist.RoomSummary
+import io.element.android.libraries.matrix.api.roomlist.RoomSummaryDetails
 import io.element.android.libraries.matrix.api.room.message.RoomMessage
 import io.element.android.libraries.matrix.api.timeline.item.TimelineItemDebugInfo
 import io.element.android.libraries.matrix.api.timeline.item.event.EventContent
diff --git a/libraries/matrix/test/src/main/kotlin/io/element/android/libraries/matrix/test/room/FakeRoomSummaryDataSource.kt b/libraries/matrix/test/src/main/kotlin/io/element/android/libraries/matrix/test/roomlist/FakeRoomListService.kt
similarity index 51%
rename from libraries/matrix/test/src/main/kotlin/io/element/android/libraries/matrix/test/room/FakeRoomSummaryDataSource.kt
rename to libraries/matrix/test/src/main/kotlin/io/element/android/libraries/matrix/test/roomlist/FakeRoomListService.kt
index cae36e14c8..fa2e347e3b 100644
--- a/libraries/matrix/test/src/main/kotlin/io/element/android/libraries/matrix/test/room/FakeRoomSummaryDataSource.kt
+++ b/libraries/matrix/test/src/main/kotlin/io/element/android/libraries/matrix/test/roomlist/FakeRoomListService.kt
@@ -14,18 +14,21 @@
  * limitations under the License.
  */
 
-package io.element.android.libraries.matrix.test.room
+package io.element.android.libraries.matrix.test.roomlist
 
-import io.element.android.libraries.matrix.api.room.RoomSummary
-import io.element.android.libraries.matrix.api.room.RoomSummaryDataSource
+import io.element.android.libraries.matrix.api.roomlist.RoomList
+import io.element.android.libraries.matrix.api.roomlist.RoomListService
+import io.element.android.libraries.matrix.api.roomlist.RoomSummary
 import kotlinx.coroutines.flow.MutableStateFlow
 import kotlinx.coroutines.flow.StateFlow
 
-class FakeRoomSummaryDataSource : RoomSummaryDataSource {
+class FakeRoomListService : RoomListService {
 
     private val allRoomSummariesFlow = MutableStateFlow>(emptyList())
     private val inviteRoomSummariesFlow = MutableStateFlow>(emptyList())
-    private val allRoomsLoadingStateFlow = MutableStateFlow(RoomSummaryDataSource.LoadingState.NotLoaded)
+    private val allRoomsLoadingStateFlow = MutableStateFlow(RoomList.LoadingState.NotLoaded)
+    private val inviteRoomsLoadingStateFlow = MutableStateFlow(RoomList.LoadingState.NotLoaded)
+    private val roomListStateFlow = MutableStateFlow(RoomListService.State.Idle)
 
     suspend fun postAllRooms(roomSummaries: List) {
         allRoomSummariesFlow.emit(roomSummaries)
@@ -35,20 +38,16 @@ class FakeRoomSummaryDataSource : RoomSummaryDataSource {
         inviteRoomSummariesFlow.emit(roomSummaries)
     }
 
-    suspend fun postLoadingState(loadingState: RoomSummaryDataSource.LoadingState) {
+    suspend fun postAllRoomsLoadingState(loadingState: RoomList.LoadingState) {
         allRoomsLoadingStateFlow.emit(loadingState)
     }
 
-    override fun allRoomsLoadingState(): StateFlow {
-        return allRoomsLoadingStateFlow
+    suspend fun postInviteRoomsLoadingState(loadingState: RoomList.LoadingState) {
+        inviteRoomsLoadingStateFlow.emit(loadingState)
     }
 
-    override fun allRooms(): StateFlow> {
-        return allRoomSummariesFlow
-    }
-
-    override fun inviteRooms(): StateFlow> {
-        return inviteRoomSummariesFlow
+    suspend fun postState(state: RoomListService.State) {
+        roomListStateFlow.emit(state)
     }
 
     var latestSlidingSyncRange: IntRange? = null
@@ -57,4 +56,20 @@ class FakeRoomSummaryDataSource : RoomSummaryDataSource {
     override fun updateAllRoomsVisibleRange(range: IntRange) {
         latestSlidingSyncRange = range
     }
+
+    override fun allRooms(): RoomList {
+        return SimpleRoomList(
+            summaries = allRoomSummariesFlow,
+            loadingState = allRoomsLoadingStateFlow
+        )
+    }
+
+    override fun invites(): RoomList {
+        return SimpleRoomList(
+            summaries = inviteRoomSummariesFlow,
+            loadingState = inviteRoomsLoadingStateFlow
+        )
+    }
+
+    override val state: StateFlow = roomListStateFlow
 }
diff --git a/libraries/matrix/test/src/main/kotlin/io/element/android/libraries/matrix/test/roomlist/SimpleRoomList.kt b/libraries/matrix/test/src/main/kotlin/io/element/android/libraries/matrix/test/roomlist/SimpleRoomList.kt
new file mode 100644
index 0000000000..28b04ae318
--- /dev/null
+++ b/libraries/matrix/test/src/main/kotlin/io/element/android/libraries/matrix/test/roomlist/SimpleRoomList.kt
@@ -0,0 +1,26 @@
+/*
+ * Copyright (c) 2023 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
+ *
+ *     http://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.test.roomlist
+
+import io.element.android.libraries.matrix.api.roomlist.RoomList
+import io.element.android.libraries.matrix.api.roomlist.RoomSummary
+import kotlinx.coroutines.flow.StateFlow
+
+data class SimpleRoomList(
+    override val summaries: StateFlow>,
+    override val loadingState: StateFlow
+) : RoomList
diff --git a/libraries/matrix/test/src/main/kotlin/io/element/android/libraries/matrix/test/sync/FakeSyncService.kt b/libraries/matrix/test/src/main/kotlin/io/element/android/libraries/matrix/test/sync/FakeSyncService.kt
index dd653a76ec..4e618deb9a 100644
--- a/libraries/matrix/test/src/main/kotlin/io/element/android/libraries/matrix/test/sync/FakeSyncService.kt
+++ b/libraries/matrix/test/src/main/kotlin/io/element/android/libraries/matrix/test/sync/FakeSyncService.kt
@@ -34,7 +34,7 @@ class FakeSyncService : SyncService {
         return Result.success(Unit)
     }
 
-    override fun stopSync(): Result {
+    override suspend fun stopSync(): Result {
         syncStateFlow.value = SyncState.Terminated
         return Result.success(Unit)
     }
diff --git a/libraries/matrixui/src/main/kotlin/io/element/android/libraries/matrix/ui/components/AvatarActionBottomSheet.kt b/libraries/matrixui/src/main/kotlin/io/element/android/libraries/matrix/ui/components/AvatarActionBottomSheet.kt
index b12f577c36..d541b534b1 100644
--- a/libraries/matrixui/src/main/kotlin/io/element/android/libraries/matrix/ui/components/AvatarActionBottomSheet.kt
+++ b/libraries/matrixui/src/main/kotlin/io/element/android/libraries/matrix/ui/components/AvatarActionBottomSheet.kt
@@ -111,12 +111,12 @@ private fun AvatarActionBottomSheetContent(
 
 @Preview
 @Composable
-fun AvatarActionBottomSheetLightPreview() =
+internal fun AvatarActionBottomSheetLightPreview() =
     ElementPreviewLight { ContentToPreview() }
 
 @Preview
 @Composable
-fun AvatarActionBottomSheetDarkPreview() =
+internal fun AvatarActionBottomSheetDarkPreview() =
     ElementPreviewDark { ContentToPreview() }
 
 @Composable
diff --git a/libraries/matrixui/src/main/kotlin/io/element/android/libraries/matrix/ui/components/MatrixUserHeader.kt b/libraries/matrixui/src/main/kotlin/io/element/android/libraries/matrix/ui/components/MatrixUserHeader.kt
index 6054aa53af..a42d44b642 100644
--- a/libraries/matrixui/src/main/kotlin/io/element/android/libraries/matrix/ui/components/MatrixUserHeader.kt
+++ b/libraries/matrixui/src/main/kotlin/io/element/android/libraries/matrix/ui/components/MatrixUserHeader.kt
@@ -103,12 +103,12 @@ private fun MatrixUserHeaderContent(
 
 @Preview
 @Composable
-fun MatrixUserHeaderLightPreview(@PreviewParameter(MatrixUserProvider::class) matrixUser: MatrixUser) =
+internal fun MatrixUserHeaderLightPreview(@PreviewParameter(MatrixUserProvider::class) matrixUser: MatrixUser) =
     ElementPreviewLight { ContentToPreview(matrixUser) }
 
 @Preview
 @Composable
-fun MatrixUserHeaderDarkPreview(@PreviewParameter(MatrixUserProvider::class) matrixUser: MatrixUser) =
+internal fun MatrixUserHeaderDarkPreview(@PreviewParameter(MatrixUserProvider::class) matrixUser: MatrixUser) =
     ElementPreviewDark { ContentToPreview(matrixUser) }
 
 @Composable
diff --git a/libraries/matrixui/src/main/kotlin/io/element/android/libraries/matrix/ui/components/MatrixUserHeaderPlaceholder.kt b/libraries/matrixui/src/main/kotlin/io/element/android/libraries/matrix/ui/components/MatrixUserHeaderPlaceholder.kt
index 57901edc03..faa80f82e6 100644
--- a/libraries/matrixui/src/main/kotlin/io/element/android/libraries/matrix/ui/components/MatrixUserHeaderPlaceholder.kt
+++ b/libraries/matrixui/src/main/kotlin/io/element/android/libraries/matrix/ui/components/MatrixUserHeaderPlaceholder.kt
@@ -68,12 +68,12 @@ fun MatrixUserHeaderPlaceholder(
 
 @Preview
 @Composable
-fun MatrixUserHeaderPlaceholderLightPreview() =
+internal fun MatrixUserHeaderPlaceholderLightPreview() =
     ElementPreviewLight { ContentToPreview() }
 
 @Preview
 @Composable
-fun MatrixUserHeaderPlaceholderDarkPreview() =
+internal fun MatrixUserHeaderPlaceholderDarkPreview() =
     ElementPreviewDark { ContentToPreview() }
 
 @Composable
diff --git a/libraries/matrixui/src/main/kotlin/io/element/android/libraries/matrix/ui/components/SelectedRoom.kt b/libraries/matrixui/src/main/kotlin/io/element/android/libraries/matrix/ui/components/SelectedRoom.kt
index 2881235335..da6f69d830 100644
--- a/libraries/matrixui/src/main/kotlin/io/element/android/libraries/matrix/ui/components/SelectedRoom.kt
+++ b/libraries/matrixui/src/main/kotlin/io/element/android/libraries/matrix/ui/components/SelectedRoom.kt
@@ -46,7 +46,7 @@ import io.element.android.libraries.designsystem.theme.components.Icon
 import io.element.android.libraries.designsystem.theme.components.Surface
 import io.element.android.libraries.designsystem.theme.components.Text
 import io.element.android.libraries.matrix.api.core.RoomId
-import io.element.android.libraries.matrix.api.room.RoomSummaryDetails
+import io.element.android.libraries.matrix.api.roomlist.RoomSummaryDetails
 import io.element.android.libraries.ui.strings.CommonStrings
 
 @Composable
diff --git a/libraries/matrixui/src/main/kotlin/io/element/android/libraries/matrix/ui/components/SelectedUsersList.kt b/libraries/matrixui/src/main/kotlin/io/element/android/libraries/matrix/ui/components/SelectedUsersList.kt
index c0ed0460dc..f9649e1b34 100644
--- a/libraries/matrixui/src/main/kotlin/io/element/android/libraries/matrix/ui/components/SelectedUsersList.kt
+++ b/libraries/matrixui/src/main/kotlin/io/element/android/libraries/matrix/ui/components/SelectedUsersList.kt
@@ -88,7 +88,7 @@ fun SelectedUsersList(
                 val maxVisibleUsers = rowWidth / userWidthWithSpacing
 
                 // Round down the number of visible users to end with a state where one is half visible
-                val targetFraction = (userWidth / 2) / userWidthWithSpacing
+                val targetFraction = userWidth / 2 / userWidthWithSpacing
                 val targetUsers = floor(maxVisibleUsers - targetFraction) + targetFraction
 
                 // Work out how much extra spacing we need to reduce the number of users that much, then split it evenly amongst the visible users
@@ -153,7 +153,7 @@ private fun ContentToPreview() {
             SelectedUsersList(
                 selectedUsers = aMatrixUserList().take(6).toImmutableList(),
                 modifier = Modifier
-                    .width((200 + (i * 20)).dp)
+                    .width((200 + i * 20).dp)
                     .border(1.dp, Color.Red)
             )
         }
diff --git a/libraries/matrixui/src/main/kotlin/io/element/android/libraries/matrix/ui/components/UnsavedAvatar.kt b/libraries/matrixui/src/main/kotlin/io/element/android/libraries/matrix/ui/components/UnsavedAvatar.kt
index 2b5d2f6800..13fcb40792 100644
--- a/libraries/matrixui/src/main/kotlin/io/element/android/libraries/matrix/ui/components/UnsavedAvatar.kt
+++ b/libraries/matrixui/src/main/kotlin/io/element/android/libraries/matrix/ui/components/UnsavedAvatar.kt
@@ -85,11 +85,11 @@ fun UnsavedAvatar(
 
 @Preview
 @Composable
-fun UnsavedAvatarLightPreview() = ElementPreviewLight { ContentToPreview() }
+internal fun UnsavedAvatarLightPreview() = ElementPreviewLight { ContentToPreview() }
 
 @Preview
 @Composable
-fun UnsavedAvatarDarkPreview() = ElementPreviewDark { ContentToPreview() }
+internal fun UnsavedAvatarDarkPreview() = ElementPreviewDark { ContentToPreview() }
 
 @Composable
 private fun ContentToPreview() {
diff --git a/libraries/matrixui/src/main/kotlin/io/element/android/libraries/matrix/ui/room/MatrixRoomMembers.kt b/libraries/matrixui/src/main/kotlin/io/element/android/libraries/matrix/ui/room/MatrixRoomMembers.kt
index 7995672e92..668b963bf1 100644
--- a/libraries/matrixui/src/main/kotlin/io/element/android/libraries/matrix/ui/room/MatrixRoomMembers.kt
+++ b/libraries/matrixui/src/main/kotlin/io/element/android/libraries/matrix/ui/room/MatrixRoomMembers.kt
@@ -57,14 +57,9 @@ fun MatrixRoom.getDirectRoomMember(roomMembersState: MatrixRoomMembersState): St
     val roomMembers = roomMembersState.roomMembers()
     return remember(roomMembersState) {
         derivedStateOf {
-            if (roomMembers == null) {
-                null
-            } else if (roomMembers.size == 2 && isDirect && isEncrypted) {
-                roomMembers.find { it.userId != this.sessionId }
-            } else {
-                null
-            }
+            roomMembers
+                ?.takeIf { it.size == 2 && isDirect && isEncrypted }
+                ?.find { it.userId != sessionId }
         }
     }
 }
-
diff --git a/libraries/matrixui/src/main/kotlin/io/element/android/libraries/matrix/ui/room/MatrixRoomState.kt b/libraries/matrixui/src/main/kotlin/io/element/android/libraries/matrix/ui/room/MatrixRoomState.kt
index 005a0ac747..f2a73545bf 100644
--- a/libraries/matrixui/src/main/kotlin/io/element/android/libraries/matrix/ui/room/MatrixRoomState.kt
+++ b/libraries/matrixui/src/main/kotlin/io/element/android/libraries/matrix/ui/room/MatrixRoomState.kt
@@ -21,6 +21,7 @@ import androidx.compose.runtime.State
 import androidx.compose.runtime.produceState
 import io.element.android.libraries.matrix.api.room.MatrixRoom
 import io.element.android.libraries.matrix.api.room.MessageEventType
+import io.element.android.libraries.matrix.api.room.powerlevels.canRedact
 import io.element.android.libraries.matrix.api.room.powerlevels.canSendMessage
 
 @Composable
@@ -30,3 +31,10 @@ fun MatrixRoom.canSendMessageAsState(type: MessageEventType, updateKey: Long): S
     }
 }
 
+@Composable
+fun MatrixRoom.canRedactAsState(updateKey: Long): State {
+    return produceState(initialValue = false, key1 = updateKey) {
+        value = canRedact().getOrElse { false }
+    }
+}
+
diff --git a/libraries/mediaupload/api/src/main/kotlin/io/element/android/libraries/mediaupload/api/MediaSender.kt b/libraries/mediaupload/api/src/main/kotlin/io/element/android/libraries/mediaupload/api/MediaSender.kt
index cfa59d65d3..1622ab2eef 100644
--- a/libraries/mediaupload/api/src/main/kotlin/io/element/android/libraries/mediaupload/api/MediaSender.kt
+++ b/libraries/mediaupload/api/src/main/kotlin/io/element/android/libraries/mediaupload/api/MediaSender.kt
@@ -82,7 +82,6 @@ class MediaSender @Inject constructor(
                     progressCallback = progressCallback
                 )
             }
-            else -> Result.failure(IllegalStateException("Unexpected MediaUploadInfo format: $uploadInfo"))
         }
     }
 }
diff --git a/libraries/mediaupload/impl/src/main/kotlin/io/element/android/libraries/mediaupload/ImageCompressor.kt b/libraries/mediaupload/impl/src/main/kotlin/io/element/android/libraries/mediaupload/ImageCompressor.kt
index 2b8669fe42..938072433a 100644
--- a/libraries/mediaupload/impl/src/main/kotlin/io/element/android/libraries/mediaupload/ImageCompressor.kt
+++ b/libraries/mediaupload/impl/src/main/kotlin/io/element/android/libraries/mediaupload/ImageCompressor.kt
@@ -19,7 +19,6 @@ package io.element.android.libraries.mediaupload
 import android.content.Context
 import android.graphics.Bitmap
 import android.graphics.BitmapFactory
-import com.vanniktech.blurhash.BlurHash
 import io.element.android.libraries.androidutils.bitmap.calculateInSampleSize
 import io.element.android.libraries.androidutils.bitmap.resizeToMax
 import io.element.android.libraries.androidutils.bitmap.rotateToMetadataOrientation
@@ -92,7 +91,7 @@ class ImageCompressor @Inject constructor(
     ) {
         val (width, height) = when (resizeMode) {
             is ResizeMode.Approximate -> resizeMode.desiredWidth to resizeMode.desiredHeight
-            is ResizeMode.Strict -> (resizeMode.maxWidth / 2) to (resizeMode.maxHeight / 2)
+            is ResizeMode.Strict -> resizeMode.maxWidth / 2 to resizeMode.maxHeight / 2
             is ResizeMode.None -> return
         }
         // Read bounds only
diff --git a/libraries/mediaupload/impl/src/main/kotlin/io/element/android/libraries/mediaupload/ThumbnailFactory.kt b/libraries/mediaupload/impl/src/main/kotlin/io/element/android/libraries/mediaupload/ThumbnailFactory.kt
index a9ed6319cb..2cee2566d1 100644
--- a/libraries/mediaupload/impl/src/main/kotlin/io/element/android/libraries/mediaupload/ThumbnailFactory.kt
+++ b/libraries/mediaupload/impl/src/main/kotlin/io/element/android/libraries/mediaupload/ThumbnailFactory.kt
@@ -69,6 +69,7 @@ class ThumbnailFactory @Inject constructor(
                     cancellationSignal
                 )
             } else {
+                @Suppress("DEPRECATION")
                 ThumbnailUtils.createImageThumbnail(
                     file.path,
                     MediaStore.Images.Thumbnails.MINI_KIND,
diff --git a/libraries/permissions/api/src/main/kotlin/io/element/android/libraries/permissions/api/PermissionsView.kt b/libraries/permissions/api/src/main/kotlin/io/element/android/libraries/permissions/api/PermissionsView.kt
index 30f19aa31c..d9dba2a0d3 100644
--- a/libraries/permissions/api/src/main/kotlin/io/element/android/libraries/permissions/api/PermissionsView.kt
+++ b/libraries/permissions/api/src/main/kotlin/io/element/android/libraries/permissions/api/PermissionsView.kt
@@ -83,12 +83,12 @@ fun PermissionsView(
 
 @Preview
 @Composable
-fun PermissionsViewLightPreview(@PreviewParameter(PermissionsViewStateProvider::class) state: PermissionsState) =
+internal fun PermissionsViewLightPreview(@PreviewParameter(PermissionsViewStateProvider::class) state: PermissionsState) =
     ElementPreviewLight { ContentToPreview(state) }
 
 @Preview
 @Composable
-fun PermissionsViewDarkPreview(@PreviewParameter(PermissionsViewStateProvider::class) state: PermissionsState) =
+internal fun PermissionsViewDarkPreview(@PreviewParameter(PermissionsViewStateProvider::class) state: PermissionsState) =
     ElementPreviewDark { ContentToPreview(state) }
 
 @Composable
diff --git a/libraries/permissions/impl/build.gradle.kts b/libraries/permissions/impl/build.gradle.kts
index 31a4e4bbb1..9808986f8f 100644
--- a/libraries/permissions/impl/build.gradle.kts
+++ b/libraries/permissions/impl/build.gradle.kts
@@ -57,7 +57,5 @@ dependencies {
     testImplementation(libs.test.turbine)
     testImplementation(projects.libraries.matrix.test)
 
-    androidTestImplementation(libs.test.junitext)
-
     ksp(libs.showkase.processor)
 }
diff --git a/libraries/permissions/impl/src/test/kotlin/io/element/android/libraries/permissions/impl/DefaultPermissionsPresenterTest.kt b/libraries/permissions/impl/src/test/kotlin/io/element/android/libraries/permissions/impl/DefaultPermissionsPresenterTest.kt
index 24b174426c..f501bcee8a 100644
--- a/libraries/permissions/impl/src/test/kotlin/io/element/android/libraries/permissions/impl/DefaultPermissionsPresenterTest.kt
+++ b/libraries/permissions/impl/src/test/kotlin/io/element/android/libraries/permissions/impl/DefaultPermissionsPresenterTest.kt
@@ -18,7 +18,7 @@
 
 package io.element.android.libraries.permissions.impl
 
-import app.cash.molecule.RecompositionClock
+import app.cash.molecule.RecompositionMode
 import app.cash.molecule.moleculeFlow
 import app.cash.turbine.test
 import com.google.accompanist.permissions.ExperimentalPermissionsApi
@@ -41,7 +41,7 @@ class DefaultPermissionsPresenterTest {
             permissionsStore,
             permissionStateProvider
         )
-        moleculeFlow(RecompositionClock.Immediate) {
+        moleculeFlow(RecompositionMode.Immediate) {
             presenter.present()
         }.test {
             val initialState = awaitItem()
@@ -64,7 +64,7 @@ class DefaultPermissionsPresenterTest {
             permissionsStore,
             permissionStateProvider
         )
-        moleculeFlow(RecompositionClock.Immediate) {
+        moleculeFlow(RecompositionMode.Immediate) {
             presenter.present()
         }.test {
             val initialState = awaitItem()
@@ -84,7 +84,7 @@ class DefaultPermissionsPresenterTest {
             permissionsStore,
             permissionStateProvider
         )
-        moleculeFlow(RecompositionClock.Immediate) {
+        moleculeFlow(RecompositionMode.Immediate) {
             presenter.present()
         }.test {
             val initialState = awaitItem()
@@ -113,7 +113,7 @@ class DefaultPermissionsPresenterTest {
             permissionsStore,
             permissionStateProvider
         )
-        moleculeFlow(RecompositionClock.Immediate) {
+        moleculeFlow(RecompositionMode.Immediate) {
             presenter.present()
         }.test {
             val initialState = awaitItem()
@@ -142,7 +142,7 @@ class DefaultPermissionsPresenterTest {
             permissionsStore,
             permissionStateProvider
         )
-        moleculeFlow(RecompositionClock.Immediate) {
+        moleculeFlow(RecompositionMode.Immediate) {
             presenter.present()
         }.test {
             skipItems(1)
@@ -164,7 +164,7 @@ class DefaultPermissionsPresenterTest {
             permissionsStore,
             permissionStateProvider
         )
-        moleculeFlow(RecompositionClock.Immediate) {
+        moleculeFlow(RecompositionMode.Immediate) {
             presenter.present()
         }.test {
             val initialState = awaitItem()
diff --git a/libraries/permissions/noop/src/test/kotlin/io/element/android/libraries/permissions/noop/NoopPermissionsPresenterTest.kt b/libraries/permissions/noop/src/test/kotlin/io/element/android/libraries/permissions/noop/NoopPermissionsPresenterTest.kt
index 9992480436..912edd9294 100644
--- a/libraries/permissions/noop/src/test/kotlin/io/element/android/libraries/permissions/noop/NoopPermissionsPresenterTest.kt
+++ b/libraries/permissions/noop/src/test/kotlin/io/element/android/libraries/permissions/noop/NoopPermissionsPresenterTest.kt
@@ -16,7 +16,7 @@
 
 package io.element.android.libraries.permissions.noop
 
-import app.cash.molecule.RecompositionClock
+import app.cash.molecule.RecompositionMode
 import app.cash.molecule.moleculeFlow
 import app.cash.turbine.test
 import com.google.common.truth.Truth.assertThat
@@ -27,7 +27,7 @@ class NoopPermissionsPresenterTest {
     @Test
     fun `present - initial state`() = runTest {
         val presenter = NoopPermissionsPresenter()
-        moleculeFlow(RecompositionClock.Immediate) {
+        moleculeFlow(RecompositionMode.Immediate) {
             presenter.present()
         }.test {
             val initialState = awaitItem()
diff --git a/libraries/push/impl/build.gradle.kts b/libraries/push/impl/build.gradle.kts
index b639f61b8b..b0f3be6deb 100644
--- a/libraries/push/impl/build.gradle.kts
+++ b/libraries/push/impl/build.gradle.kts
@@ -52,9 +52,6 @@ dependencies {
     implementation(projects.services.appnavstate.api)
     implementation(projects.services.toolbox.api)
 
-    // TODO Temporary use the deprecated LocalBroadcastManager, to be changed later.
-    implementation("androidx.localbroadcastmanager:localbroadcastmanager:1.1.0")
-
     testImplementation(libs.test.junit)
     testImplementation(libs.test.mockk)
     testImplementation(libs.test.truth)
diff --git a/libraries/push/impl/src/main/kotlin/io/element/android/libraries/push/impl/PushersManager.kt b/libraries/push/impl/src/main/kotlin/io/element/android/libraries/push/impl/PushersManager.kt
index 81a86c5345..f3afb940cd 100644
--- a/libraries/push/impl/src/main/kotlin/io/element/android/libraries/push/impl/PushersManager.kt
+++ b/libraries/push/impl/src/main/kotlin/io/element/android/libraries/push/impl/PushersManager.kt
@@ -103,33 +103,6 @@ class PushersManager @Inject constructor(
         return "{\"cs\":\"$secretForUser\"}"
     }
 
-    suspend fun registerEmailForPush(email: String) {
-        TODO()
-        /*
-        val currentSession = activeSessionHolder.getActiveSession()
-        val appName = appNameProvider.getAppName()
-        currentSession.pushersService().addEmailPusher(
-            email = email,
-            lang = localeProvider.current().language,
-            emailBranding = appName,
-            appDisplayName = appName,
-            deviceDisplayName = currentSession.sessionParams.deviceId ?: "MOBILE"
-        )
-        */
-    }
-
-    fun getPusherForCurrentSession() {}/*: Pusher? {
-        val session = activeSessionHolder.getSafeActiveSession() ?: return null
-        val deviceId = session.sessionParams.deviceId
-        return session.pushersService().getPushers().firstOrNull { it.deviceId == deviceId }
-    }
-    */
-
-    suspend fun unregisterEmailPusher(email: String) {
-        // val currentSession = activeSessionHolder.getSafeActiveSession() ?: return
-        // currentSession.pushersService().removeEmailPusher(email)
-    }
-
     override suspend fun unregisterPusher(matrixClient: MatrixClient, pushKey: String, gateway: String) {
         matrixClient.pushersService().unsetHttpPusher()
     }
diff --git a/libraries/push/impl/src/main/kotlin/io/element/android/libraries/push/impl/notifications/DefaultNotificationDrawerManager.kt b/libraries/push/impl/src/main/kotlin/io/element/android/libraries/push/impl/notifications/DefaultNotificationDrawerManager.kt
index 9cd4956dca..91b3987251 100644
--- a/libraries/push/impl/src/main/kotlin/io/element/android/libraries/push/impl/notifications/DefaultNotificationDrawerManager.kt
+++ b/libraries/push/impl/src/main/kotlin/io/element/android/libraries/push/impl/notifications/DefaultNotificationDrawerManager.kt
@@ -23,17 +23,17 @@ import io.element.android.libraries.core.data.tryOrNull
 import io.element.android.libraries.core.meta.BuildMeta
 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.matrix.api.core.EventId
 import io.element.android.libraries.matrix.api.core.RoomId
 import io.element.android.libraries.matrix.api.core.SessionId
 import io.element.android.libraries.matrix.api.core.ThreadId
 import io.element.android.libraries.matrix.api.user.MatrixUser
-import io.element.android.libraries.matrix.api.MatrixClientProvider
 import io.element.android.libraries.push.api.notifications.NotificationDrawerManager
-import io.element.android.libraries.push.api.store.PushDataStore
 import io.element.android.libraries.push.impl.notifications.model.NotifiableEvent
-import io.element.android.services.appnavstate.api.NavigationState
 import io.element.android.services.appnavstate.api.AppNavigationStateService
+import io.element.android.services.appnavstate.api.NavigationState
+import io.element.android.services.appnavstate.api.currentSessionId
 import kotlinx.coroutines.CoroutineScope
 import kotlinx.coroutines.delay
 import kotlinx.coroutines.launch
@@ -48,7 +48,6 @@ import javax.inject.Inject
  */
 @SingleIn(AppScope::class)
 class DefaultNotificationDrawerManager @Inject constructor(
-    private val pushDataStore: PushDataStore,
     private val notifiableEventProcessor: NotifiableEventProcessor,
     private val notificationRenderer: NotificationRenderer,
     private val notificationEventPersistence: NotificationEventPersistence,
@@ -76,9 +75,16 @@ class DefaultNotificationDrawerManager @Inject constructor(
         }
     }
 
+    private var currentAppNavigationState: NavigationState? = null
+
     private fun onAppNavigationStateChange(navigationState: NavigationState) {
         when (navigationState) {
-            NavigationState.Root -> {}
+            NavigationState.Root -> {
+                currentAppNavigationState?.currentSessionId()?.let { sessionId ->
+                    // User signed out, clear all notifications related to the session.
+                    clearAllEvents(sessionId)
+                }
+            }
             is NavigationState.Session -> {}
             is NavigationState.Space -> {}
             is NavigationState.Room -> {
@@ -93,6 +99,7 @@ class DefaultNotificationDrawerManager @Inject constructor(
                 )
             }
         }
+        currentAppNavigationState = navigationState
     }
 
     private fun createInitialNotificationState(): NotificationState {
@@ -133,12 +140,21 @@ class DefaultNotificationDrawerManager @Inject constructor(
     /**
      * Clear all known events and refresh the notification drawer.
      */
-    fun clearAllEvents(sessionId: SessionId) {
+    fun clearAllMessagesEvents(sessionId: SessionId) {
         updateEvents {
             it.clearMessagesForSession(sessionId)
         }
     }
 
+    /**
+     * Clear all notifications related to the session and refresh the notification drawer.
+     */
+    fun clearAllEvents(sessionId: SessionId) {
+        updateEvents {
+            it.clearAllForSession(sessionId)
+        }
+    }
+
     /**
      * Should be called when the application is currently opened and showing timeline for the given roomId.
      * Used to ignore events related to that room (no need to display notification) and clean any existing notification on this room.
diff --git a/libraries/push/impl/src/main/kotlin/io/element/android/libraries/push/impl/notifications/FilteredEventDetector.kt b/libraries/push/impl/src/main/kotlin/io/element/android/libraries/push/impl/notifications/FilteredEventDetector.kt
index a24f088998..2d4d27472b 100644
--- a/libraries/push/impl/src/main/kotlin/io/element/android/libraries/push/impl/notifications/FilteredEventDetector.kt
+++ b/libraries/push/impl/src/main/kotlin/io/element/android/libraries/push/impl/notifications/FilteredEventDetector.kt
@@ -27,7 +27,7 @@ class FilteredEventDetector @Inject constructor(
      * Returns true if the given event should be ignored.
      * Used to skip notifications if a non expected message is received.
      */
-    fun shouldBeIgnored(notifiableEvent: NotifiableEvent): Boolean {
+    fun shouldBeIgnored(@Suppress("UNUSED_PARAMETER") notifiableEvent: NotifiableEvent): Boolean {
         /* TODO EAx
         val session = activeSessionDataSource.currentValue?.orNull() ?: return false
 
diff --git a/libraries/push/impl/src/main/kotlin/io/element/android/libraries/push/impl/notifications/NotifiableEventResolver.kt b/libraries/push/impl/src/main/kotlin/io/element/android/libraries/push/impl/notifications/NotifiableEventResolver.kt
index dbdddf1ac9..e5af7785db 100644
--- a/libraries/push/impl/src/main/kotlin/io/element/android/libraries/push/impl/notifications/NotifiableEventResolver.kt
+++ b/libraries/push/impl/src/main/kotlin/io/element/android/libraries/push/impl/notifications/NotifiableEventResolver.kt
@@ -17,11 +17,12 @@
 package io.element.android.libraries.push.impl.notifications
 
 import io.element.android.libraries.core.log.logger.LoggerTag
-import io.element.android.libraries.core.meta.BuildMeta
+import io.element.android.libraries.matrix.api.MatrixClientProvider
 import io.element.android.libraries.matrix.api.core.EventId
 import io.element.android.libraries.matrix.api.core.RoomId
 import io.element.android.libraries.matrix.api.core.SessionId
 import io.element.android.libraries.matrix.api.core.ThreadId
+import io.element.android.libraries.matrix.api.core.UserId
 import io.element.android.libraries.matrix.api.notification.NotificationContent
 import io.element.android.libraries.matrix.api.notification.NotificationData
 import io.element.android.libraries.matrix.api.room.RoomMembershipState
@@ -34,7 +35,6 @@ import io.element.android.libraries.matrix.api.timeline.item.event.NoticeMessage
 import io.element.android.libraries.matrix.api.timeline.item.event.TextMessageType
 import io.element.android.libraries.matrix.api.timeline.item.event.UnknownMessageType
 import io.element.android.libraries.matrix.api.timeline.item.event.VideoMessageType
-import io.element.android.libraries.matrix.api.MatrixClientProvider
 import io.element.android.libraries.push.impl.R
 import io.element.android.libraries.push.impl.log.pushLoggerTag
 import io.element.android.libraries.push.impl.notifications.model.FallbackNotifiableEvent
@@ -57,9 +57,6 @@ private val loggerTag = LoggerTag("NotifiableEventResolver", pushLoggerTag)
  */
 class NotifiableEventResolver @Inject constructor(
     private val stringProvider: StringProvider,
-    // private val noticeEventFormatter: NoticeEventFormatter,
-    // private val displayableEventFormatter: DisplayableEventFormatter,
-    private val buildMeta: BuildMeta,
     private val clock: SystemClock,
     private val matrixClientProvider: MatrixClientProvider,
 ) {
@@ -72,31 +69,27 @@ class NotifiableEventResolver @Inject constructor(
             userId = sessionId,
             roomId = roomId,
             eventId = eventId,
-            // FIXME should be true in the future, but right now it's broken
-            //  (https://github.com/vector-im/element-x-android/issues/640#issuecomment-1612913658)
-            filterByPushRules = false,
         ).onFailure {
             Timber.tag(loggerTag.value).e(it, "Unable to resolve event: $eventId.")
         }.getOrNull()
 
         // TODO this notificationData is not always valid at the moment, sometimes the Rust SDK can't fetch the matching event
         return notificationData?.asNotifiableEvent(sessionId)
-            ?: fallbackNotifiableEvent(sessionId, roomId, eventId)
     }
 
     private fun NotificationData.asNotifiableEvent(userId: SessionId): NotifiableEvent? {
-        return when (val content = this.event.content) {
+        return when (val content = this.content) {
             is NotificationContent.MessageLike.RoomMessage -> {
                 buildNotifiableMessageEvent(
                     sessionId = userId,
+                    senderId = content.senderId,
                     roomId = roomId,
                     eventId = eventId,
                     noisy = isNoisy,
-                    timestamp = event.timestamp,
+                    timestamp = this.timestamp,
                     senderName = senderDisplayName,
-                    senderId = senderId.value,
                     body = descriptionFromMessageContent(content),
-                    imageUriString = event.contentUrl,
+                    imageUriString = this.contentUrl,
                     roomName = roomDisplayName,
                     roomIsDirect = isDirect,
                     roomAvatarPath = roomAvatarUrl,
@@ -113,7 +106,7 @@ class NotifiableEventResolver @Inject constructor(
                         canBeReplaced = true,
                         roomName = roomDisplayName,
                         noisy = isNoisy,
-                        timestamp = event.timestamp,
+                        timestamp = this.timestamp,
                         soundName = null,
                         isRedacted = false,
                         isUpdated = false,
@@ -122,10 +115,10 @@ class NotifiableEventResolver @Inject constructor(
                         title = null, // TODO check if title is needed anymore
                     )
                 } else {
-                    null
+                    fallbackNotifiableEvent(userId, roomId, eventId)
                 }
             }
-            else -> null
+            else -> fallbackNotifiableEvent(userId, roomId, eventId)
         }
     }
 
@@ -181,6 +174,7 @@ class NotifiableEventResolver @Inject constructor(
 @Suppress("LongParameterList")
 private fun buildNotifiableMessageEvent(
     sessionId: SessionId,
+    senderId: UserId,
     roomId: RoomId,
     eventId: EventId,
     editedEventId: EventId? = null,
@@ -188,7 +182,6 @@ private fun buildNotifiableMessageEvent(
     noisy: Boolean,
     timestamp: Long,
     senderName: String?,
-    senderId: String?,
     body: String?,
     // We cannot use Uri? type here, as that could trigger a
     // NotSerializableException when persisting this to storage
@@ -206,6 +199,7 @@ private fun buildNotifiableMessageEvent(
     isUpdated: Boolean = false
 ) = NotifiableMessageEvent(
     sessionId = sessionId,
+    senderId = senderId,
     roomId = roomId,
     eventId = eventId,
     editedEventId = editedEventId,
@@ -213,7 +207,6 @@ private fun buildNotifiableMessageEvent(
     noisy = noisy,
     timestamp = timestamp,
     senderName = senderName,
-    senderId = senderId,
     body = body,
     imageUriString = imageUriString,
     threadId = threadId,
diff --git a/libraries/push/impl/src/main/kotlin/io/element/android/libraries/push/impl/notifications/NotificationBroadcastReceiver.kt b/libraries/push/impl/src/main/kotlin/io/element/android/libraries/push/impl/notifications/NotificationBroadcastReceiver.kt
index d5df1001ca..59a763bd55 100644
--- a/libraries/push/impl/src/main/kotlin/io/element/android/libraries/push/impl/notifications/NotificationBroadcastReceiver.kt
+++ b/libraries/push/impl/src/main/kotlin/io/element/android/libraries/push/impl/notifications/NotificationBroadcastReceiver.kt
@@ -19,15 +19,12 @@ package io.element.android.libraries.push.impl.notifications
 import android.content.BroadcastReceiver
 import android.content.Context
 import android.content.Intent
-import androidx.core.app.RemoteInput
 import io.element.android.libraries.architecture.bindings
 import io.element.android.libraries.core.log.logger.LoggerTag
 import io.element.android.libraries.matrix.api.core.EventId
 import io.element.android.libraries.matrix.api.core.RoomId
 import io.element.android.libraries.matrix.api.core.SessionId
-import io.element.android.libraries.matrix.api.core.ThreadId
 import io.element.android.libraries.push.impl.log.notificationLoggerTag
-import io.element.android.services.toolbox.api.systemclock.SystemClock
 import timber.log.Timber
 import javax.inject.Inject
 
@@ -39,10 +36,6 @@ private val loggerTag = LoggerTag("NotificationBroadcastReceiver", notificationL
 class NotificationBroadcastReceiver : BroadcastReceiver() {
 
     @Inject lateinit var defaultNotificationDrawerManager: DefaultNotificationDrawerManager
-
-    //@Inject lateinit var activeSessionHolder: ActiveSessionHolder
-    //@Inject lateinit var analyticsTracker: AnalyticsTracker
-    @Inject lateinit var clock: SystemClock
     @Inject lateinit var actionIds: NotificationActionIds
 
     override fun onReceive(context: Context?, intent: Intent?) {
@@ -59,7 +52,7 @@ class NotificationBroadcastReceiver : BroadcastReceiver() {
                 defaultNotificationDrawerManager.clearMessagesForRoom(sessionId, roomId)
             }
             actionIds.dismissSummary ->
-                defaultNotificationDrawerManager.clearAllEvents(sessionId)
+                defaultNotificationDrawerManager.clearAllMessagesEvents(sessionId)
             actionIds.dismissInvite -> if (roomId != null) {
                 defaultNotificationDrawerManager.clearMembershipNotificationForRoom(sessionId, roomId)
             }
@@ -81,6 +74,7 @@ class NotificationBroadcastReceiver : BroadcastReceiver() {
         }
     }
 
+    @Suppress("UNUSED_PARAMETER")
     private fun handleJoinRoom(sessionId: SessionId, roomId: RoomId) {
         /*
         activeSessionHolder.getSafeActiveSession()?.let { session ->
@@ -94,10 +88,10 @@ class NotificationBroadcastReceiver : BroadcastReceiver() {
                 }
             }
         }
-
          */
     }
 
+    @Suppress("UNUSED_PARAMETER")
     private fun handleRejectRoom(sessionId: SessionId, roomId: RoomId) {
         /*
         activeSessionHolder.getSafeActiveSession()?.let { session ->
@@ -109,6 +103,7 @@ class NotificationBroadcastReceiver : BroadcastReceiver() {
          */
     }
 
+    @Suppress("UNUSED_PARAMETER")
     private fun handleMarkAsRead(sessionId: SessionId, roomId: RoomId) {
         /*
         activeSessionHolder.getActiveSession().let { session ->
@@ -123,7 +118,9 @@ class NotificationBroadcastReceiver : BroadcastReceiver() {
          */
     }
 
+    @Suppress("UNUSED_PARAMETER")
     private fun handleSmartReply(intent: Intent, context: Context) {
+        /*
         val message = getReplyMessage(intent)
         val sessionId = intent.getStringExtra(KEY_SESSION_ID)?.let(::SessionId)
         val roomId = intent.getStringExtra(KEY_ROOM_ID)?.let(::RoomId)
@@ -134,13 +131,11 @@ class NotificationBroadcastReceiver : BroadcastReceiver() {
             // Can this happen? should we update notification?
             return
         }
-        /*
         activeSessionHolder.getActiveSession().let { session ->
             session.getRoom(roomId)?.let { room ->
                 sendMatrixEvent(message, threadId, session, room, context)
             }
         }
-
          */
     }
 
@@ -234,6 +229,7 @@ class NotificationBroadcastReceiver : BroadcastReceiver() {
 
      */
 
+    /*
     private fun getReplyMessage(intent: Intent?): String? {
         if (intent != null) {
             val remoteInput = RemoteInput.getResultsFromIntent(intent)
@@ -243,6 +239,7 @@ class NotificationBroadcastReceiver : BroadcastReceiver() {
         }
         return null
     }
+     */
 
     companion object {
         const val KEY_SESSION_ID = "sessionID"
diff --git a/libraries/push/impl/src/main/kotlin/io/element/android/libraries/push/impl/notifications/NotificationEventQueue.kt b/libraries/push/impl/src/main/kotlin/io/element/android/libraries/push/impl/notifications/NotificationEventQueue.kt
index 97b90476b0..6b6730c904 100644
--- a/libraries/push/impl/src/main/kotlin/io/element/android/libraries/push/impl/notifications/NotificationEventQueue.kt
+++ b/libraries/push/impl/src/main/kotlin/io/element/android/libraries/push/impl/notifications/NotificationEventQueue.kt
@@ -154,6 +154,11 @@ data class NotificationEventQueue constructor(
         queue.removeAll { it is NotifiableMessageEvent && it.sessionId == sessionId }
     }
 
+    fun clearAllForSession(sessionId: SessionId) {
+        Timber.d("clearAllForSession $sessionId")
+        queue.removeAll { it.sessionId == sessionId }
+    }
+
     fun clearMessagesForRoom(sessionId: SessionId, roomId: RoomId) {
         Timber.d("clearMessageEventOfRoom $sessionId, $roomId")
         queue.removeAll { it is NotifiableMessageEvent && it.sessionId == sessionId && it.roomId == roomId }
diff --git a/libraries/push/impl/src/main/kotlin/io/element/android/libraries/push/impl/notifications/OutdatedEventDetector.kt b/libraries/push/impl/src/main/kotlin/io/element/android/libraries/push/impl/notifications/OutdatedEventDetector.kt
index 5b15dc78d2..27713399fc 100644
--- a/libraries/push/impl/src/main/kotlin/io/element/android/libraries/push/impl/notifications/OutdatedEventDetector.kt
+++ b/libraries/push/impl/src/main/kotlin/io/element/android/libraries/push/impl/notifications/OutdatedEventDetector.kt
@@ -28,7 +28,7 @@ class OutdatedEventDetector @Inject constructor(
      * Used to clean up notifications if a displayed message has been read on an
      * other device.
      */
-    fun isMessageOutdated(notifiableEvent: NotifiableEvent): Boolean {
+    fun isMessageOutdated(@Suppress("UNUSED_PARAMETER") notifiableEvent: NotifiableEvent): Boolean {
         /* TODO EAx
         val session = activeSessionDataSource.currentValue?.orNull() ?: return false
 
diff --git a/libraries/push/impl/src/main/kotlin/io/element/android/libraries/push/impl/notifications/RoomEventGroupInfo.kt b/libraries/push/impl/src/main/kotlin/io/element/android/libraries/push/impl/notifications/RoomEventGroupInfo.kt
index 734c34b051..96a8b90f06 100644
--- a/libraries/push/impl/src/main/kotlin/io/element/android/libraries/push/impl/notifications/RoomEventGroupInfo.kt
+++ b/libraries/push/impl/src/main/kotlin/io/element/android/libraries/push/impl/notifications/RoomEventGroupInfo.kt
@@ -23,17 +23,15 @@ import io.element.android.libraries.matrix.api.core.SessionId
  * Data class to hold information about a group of notifications for a room.
  */
 data class RoomEventGroupInfo(
-        val sessionId: SessionId,
-        val roomId: RoomId,
-        val roomDisplayName: String,
-        val isDirect: Boolean = false
-) {
+    val sessionId: SessionId,
+    val roomId: RoomId,
+    val roomDisplayName: String,
+    val isDirect: Boolean = false,
     // An event in the list has not yet been display
-    var hasNewEvent: Boolean = false
-
+    val hasNewEvent: Boolean = false,
     // true if at least one on the not yet displayed event is noisy
-    var shouldBing: Boolean = false
-    var customSound: String? = null
-    var hasSmartReplyError: Boolean = false
-    var isUpdated: Boolean = false
-}
+    val shouldBing: Boolean = false,
+    val customSound: String? = null,
+    val hasSmartReplyError: Boolean = false,
+    val isUpdated: Boolean = false,
+)
diff --git a/libraries/push/impl/src/main/kotlin/io/element/android/libraries/push/impl/notifications/RoomGroupMessageCreator.kt b/libraries/push/impl/src/main/kotlin/io/element/android/libraries/push/impl/notifications/RoomGroupMessageCreator.kt
index 5f2f6db263..29d828d34c 100644
--- a/libraries/push/impl/src/main/kotlin/io/element/android/libraries/push/impl/notifications/RoomGroupMessageCreator.kt
+++ b/libraries/push/impl/src/main/kotlin/io/element/android/libraries/push/impl/notifications/RoomGroupMessageCreator.kt
@@ -69,7 +69,7 @@ class RoomGroupMessageCreator @Inject constructor(
 
         val lastMessageTimestamp = events.last().timestamp
         val smartReplyErrors = events.filter { it.isSmartReplyError() }
-        val messageCount = (events.size - smartReplyErrors.size)
+        val messageCount = events.size - smartReplyErrors.size
         val meta = RoomNotification.Message.Meta(
             summaryLine = createRoomMessagesGroupSummaryLine(events, roomName, roomIsDirect = !roomIsGroup),
             messageCount = messageCount,
@@ -85,12 +85,11 @@ class RoomGroupMessageCreator @Inject constructor(
                     roomId = roomId,
                     roomDisplayName = roomName,
                     isDirect = !roomIsGroup,
-                ).also {
-                    it.hasSmartReplyError = smartReplyErrors.isNotEmpty()
-                    it.shouldBing = meta.shouldBing
-                    it.customSound = events.last().soundName
-                    it.isUpdated = events.last().isUpdated
-                },
+                    hasSmartReplyError = smartReplyErrors.isNotEmpty(),
+                    shouldBing = meta.shouldBing,
+                    customSound = events.last().soundName,
+                    isUpdated = events.last().isUpdated,
+                ),
                 threadId = lastKnownRoomEvent.threadId,
                 largeIcon = largeBitmap,
                 lastMessageTimestamp,
@@ -108,7 +107,7 @@ class RoomGroupMessageCreator @Inject constructor(
                 Person.Builder()
                     .setName(event.senderName?.annotateForDebug(70))
                     .setIcon(bitmapLoader.getUserIcon(event.senderAvatarPath))
-                    .setKey(event.senderId)
+                    .setKey(event.senderId.value)
                     .build()
             }
             when {
diff --git a/libraries/push/impl/src/main/kotlin/io/element/android/libraries/push/impl/notifications/TestNotificationReceiver.kt b/libraries/push/impl/src/main/kotlin/io/element/android/libraries/push/impl/notifications/TestNotificationReceiver.kt
index 42c0fe61af..a7135cee74 100644
--- a/libraries/push/impl/src/main/kotlin/io/element/android/libraries/push/impl/notifications/TestNotificationReceiver.kt
+++ b/libraries/push/impl/src/main/kotlin/io/element/android/libraries/push/impl/notifications/TestNotificationReceiver.kt
@@ -19,12 +19,10 @@ package io.element.android.libraries.push.impl.notifications
 import android.content.BroadcastReceiver
 import android.content.Context
 import android.content.Intent
-import androidx.localbroadcastmanager.content.LocalBroadcastManager
 
 class TestNotificationReceiver : BroadcastReceiver() {
 
     override fun onReceive(context: Context, intent: Intent) {
-        // Internal broadcast to any one interested
-        LocalBroadcastManager.getInstance(context).sendBroadcast(intent)
+        // TODO The test notification has been clicked, notify the ui
     }
 }
diff --git a/libraries/push/impl/src/main/kotlin/io/element/android/libraries/push/impl/notifications/channels/NotificationChannels.kt b/libraries/push/impl/src/main/kotlin/io/element/android/libraries/push/impl/notifications/channels/NotificationChannels.kt
index 0624b863ed..ab115262de 100644
--- a/libraries/push/impl/src/main/kotlin/io/element/android/libraries/push/impl/notifications/channels/NotificationChannels.kt
+++ b/libraries/push/impl/src/main/kotlin/io/element/android/libraries/push/impl/notifications/channels/NotificationChannels.kt
@@ -162,7 +162,7 @@ class NotificationChannels @Inject constructor(
         private const val CALL_NOTIFICATION_CHANNEL_ID = "CALL_NOTIFICATION_CHANNEL_ID_V2"
 
         @ChecksSdkIntAtLeast(api = Build.VERSION_CODES.O)
-        private fun supportNotificationChannels() = (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O)
+        private fun supportNotificationChannels() = Build.VERSION.SDK_INT >= Build.VERSION_CODES.O
 
         fun openSystemSettingsForSilentCategory(activity: Activity) {
             activity.startNotificationChannelSettingsIntent(SILENT_NOTIFICATION_CHANNEL_ID)
diff --git a/libraries/push/impl/src/main/kotlin/io/element/android/libraries/push/impl/notifications/model/NotifiableMessageEvent.kt b/libraries/push/impl/src/main/kotlin/io/element/android/libraries/push/impl/notifications/model/NotifiableMessageEvent.kt
index 57a3eb45aa..1b6bb8a67a 100644
--- a/libraries/push/impl/src/main/kotlin/io/element/android/libraries/push/impl/notifications/model/NotifiableMessageEvent.kt
+++ b/libraries/push/impl/src/main/kotlin/io/element/android/libraries/push/impl/notifications/model/NotifiableMessageEvent.kt
@@ -20,6 +20,7 @@ import io.element.android.libraries.matrix.api.core.EventId
 import io.element.android.libraries.matrix.api.core.RoomId
 import io.element.android.libraries.matrix.api.core.SessionId
 import io.element.android.libraries.matrix.api.core.ThreadId
+import io.element.android.libraries.matrix.api.core.UserId
 import io.element.android.libraries.matrix.api.timeline.item.event.EventType
 import io.element.android.services.appnavstate.api.AppNavigationState
 import io.element.android.services.appnavstate.api.currentRoomId
@@ -32,10 +33,10 @@ data class NotifiableMessageEvent(
     override val eventId: EventId,
     override val editedEventId: EventId?,
     override val canBeReplaced: Boolean,
+    val senderId: UserId,
     val noisy: Boolean,
     val timestamp: Long,
     val senderName: String?,
-    val senderId: String?,
     val body: String?,
     // We cannot use Uri? type here, as that could trigger a
     // NotSerializableException when persisting this to storage
diff --git a/libraries/push/impl/src/main/kotlin/io/element/android/libraries/push/impl/notifications/model/SimpleNotifiableEvent.kt b/libraries/push/impl/src/main/kotlin/io/element/android/libraries/push/impl/notifications/model/SimpleNotifiableEvent.kt
index f252765530..4b262983d4 100644
--- a/libraries/push/impl/src/main/kotlin/io/element/android/libraries/push/impl/notifications/model/SimpleNotifiableEvent.kt
+++ b/libraries/push/impl/src/main/kotlin/io/element/android/libraries/push/impl/notifications/model/SimpleNotifiableEvent.kt
@@ -30,7 +30,7 @@ data class SimpleNotifiableEvent(
     val type: String?,
     val timestamp: Long,
     val soundName: String?,
-    override var canBeReplaced: Boolean,
+    override val canBeReplaced: Boolean,
     override val isRedacted: Boolean = false,
     override val isUpdated: Boolean = false
 ) : NotifiableEvent
diff --git a/libraries/push/impl/src/main/kotlin/io/element/android/libraries/push/impl/push/DefaultPushHandler.kt b/libraries/push/impl/src/main/kotlin/io/element/android/libraries/push/impl/push/DefaultPushHandler.kt
index 3ad848aeb4..c3d68e52ac 100644
--- a/libraries/push/impl/src/main/kotlin/io/element/android/libraries/push/impl/push/DefaultPushHandler.kt
+++ b/libraries/push/impl/src/main/kotlin/io/element/android/libraries/push/impl/push/DefaultPushHandler.kt
@@ -16,22 +16,17 @@
 
 package io.element.android.libraries.push.impl.push
 
-import android.content.Context
-import android.content.Intent
 import android.os.Handler
 import android.os.Looper
-import androidx.localbroadcastmanager.content.LocalBroadcastManager
 import com.squareup.anvil.annotations.ContributesBinding
 import io.element.android.libraries.core.log.logger.LoggerTag
 import io.element.android.libraries.core.meta.BuildMeta
 import io.element.android.libraries.di.AppScope
-import io.element.android.libraries.di.ApplicationContext
 import io.element.android.libraries.matrix.api.auth.MatrixAuthenticationService
 import io.element.android.libraries.push.impl.PushersManager
 import io.element.android.libraries.push.impl.log.pushLoggerTag
-import io.element.android.libraries.push.impl.notifications.NotifiableEventResolver
-import io.element.android.libraries.push.impl.notifications.NotificationActionIds
 import io.element.android.libraries.push.impl.notifications.DefaultNotificationDrawerManager
+import io.element.android.libraries.push.impl.notifications.NotifiableEventResolver
 import io.element.android.libraries.push.impl.store.DefaultPushDataStore
 import io.element.android.libraries.pushproviders.api.PushData
 import io.element.android.libraries.pushproviders.api.PushHandler
@@ -53,8 +48,7 @@ class DefaultPushHandler @Inject constructor(
     private val defaultPushDataStore: DefaultPushDataStore,
     private val userPushStoreFactory: UserPushStoreFactory,
     private val pushClientSecret: PushClientSecret,
-    private val actionIds: NotificationActionIds,
-    @ApplicationContext private val context: Context,
+    // private val actionIds: NotificationActionIds,
     private val buildMeta: BuildMeta,
     private val matrixAuthenticationService: MatrixAuthenticationService,
 ) : PushHandler {
@@ -82,8 +76,8 @@ class DefaultPushHandler @Inject constructor(
 
         // Diagnostic Push
         if (pushData.eventId == PushersManager.TEST_EVENT_ID) {
-            val intent = Intent(actionIds.push)
-            LocalBroadcastManager.getInstance(context).sendBroadcast(intent)
+            // val intent = Intent(actionIds.push)
+            // TODO The test push has been received, notify the ui
             return
         }
 
@@ -106,15 +100,15 @@ class DefaultPushHandler @Inject constructor(
             }
 
             val clientSecret = pushData.clientSecret
-            val userId = if (clientSecret == null) {
-                // Should not happen. In this case, restore default session
-                null
-            } else {
-                // Get userId from client secret
-                pushClientSecret.getUserIdFromSecret(clientSecret)
-            } ?: run {
-                matrixAuthenticationService.getLatestSessionId()
-            }
+            // clientSecret should not be null. If this happens, restore default session
+            val userId = clientSecret
+                ?.let {
+                    // Get userId from client secret
+                    pushClientSecret.getUserIdFromSecret(clientSecret)
+                }
+                ?: run {
+                    matrixAuthenticationService.getLatestSessionId()
+                }
 
             if (userId == null) {
                 Timber.w("Unable to get a session")
diff --git a/libraries/push/impl/src/main/res/values-ru/translations.xml b/libraries/push/impl/src/main/res/values-ru/translations.xml
new file mode 100644
index 0000000000..697a0f01d8
--- /dev/null
+++ b/libraries/push/impl/src/main/res/values-ru/translations.xml
@@ -0,0 +1,58 @@
+
+
+  "Позвонить"
+  "Прослушивание событий"
+  "Шумные уведомления"
+  "Бесшумные уведомления"
+  "** Не удалось отправить - пожалуйста, откройте комнату"
+  "Присоединиться"
+  "Отклонить"
+  "Пригласил вас в чат"
+  "Новые сообщения"
+  "Отреагировал на %1$s"
+  "Отметить как прочитанное"
+  "Пригласил вас в комнату"
+  "Я"
+  "Вы просматриваете уведомление! Нажмите на меня!"
+  "%1$s: %2$s"
+  "%1$s: %2$s %3$s"
+  "%1$s и %2$s"
+  "%1$s в %2$s"
+  "%1$s в %2$s и %3$s"
+  
+    "%1$s: %2$d сообщение"
+    "%1$s: %2$d сообщения"
+    "%1$s: %2$d сообщений"
+  
+  
+    "%d уведомление"
+    "%d уведомления"
+    "%d уведомлений"
+  
+  
+    "%d приглашение"
+    "%d приглашения"
+    "%d приглашений"
+  
+  
+    "%d новое сообщение"
+    "%d новых сообщения"
+    "%d новых сообщений"
+  
+  
+    "%d непрочитанное уведомление"
+    "%d непрочитанных уведомления"
+    "%d непрочитанных уведомлений"
+  
+  
+    "%d комната"
+    "%d комнаты"
+    "%d комнат"
+  
+  "Выберите способ получения уведомлений"
+  "Фоновая синхронизация"
+  "Сервисы Google"
+  "Не найдены действующие службы Google Play. Уведомления могут работать некорректно."
+  "Уведомление"
+  "Быстрый ответ"
+
diff --git a/libraries/push/impl/src/main/res/values-zh-rTW/translations.xml b/libraries/push/impl/src/main/res/values-zh-rTW/translations.xml
new file mode 100644
index 0000000000..248fae8b0b
--- /dev/null
+++ b/libraries/push/impl/src/main/res/values-zh-rTW/translations.xml
@@ -0,0 +1,33 @@
+
+
+  "通話"
+  "無聲通知"
+  "加入"
+  "拒絕"
+  "邀請您聊天"
+  "新訊息"
+  "標示為已讀"
+  "邀請您加入聊天室"
+  "我"
+  "您正在查看通知!點我!"
+  
+    "%1$s:%2$d 則訊息"
+  
+  
+    "%d 個通知"
+  
+  
+    "%d 個邀請"
+  
+  
+    "%d 則新訊息"
+  
+  
+    "%d 個聊天室"
+  
+  "選擇接收通知的機制"
+  "背景同步"
+  "Google 服務"
+  "通知"
+  "快速回覆"
+
diff --git a/libraries/push/impl/src/test/kotlin/io/element/android/libraries/push/impl/notifications/NotificationIdProviderTest.kt b/libraries/push/impl/src/test/kotlin/io/element/android/libraries/push/impl/notifications/NotificationIdProviderTest.kt
index 57f28e72db..b9664ef577 100644
--- a/libraries/push/impl/src/test/kotlin/io/element/android/libraries/push/impl/notifications/NotificationIdProviderTest.kt
+++ b/libraries/push/impl/src/test/kotlin/io/element/android/libraries/push/impl/notifications/NotificationIdProviderTest.kt
@@ -25,7 +25,7 @@ class NotificationIdProviderTest {
     @Test
     fun `test notification id provider`() {
         val sut = NotificationIdProvider()
-        val offsetForASessionId = 305410
+        val offsetForASessionId = 305_410
         assertThat(sut.getSummaryNotificationId(A_SESSION_ID)).isEqualTo(offsetForASessionId + 0)
         assertThat(sut.getRoomMessagesNotificationId(A_SESSION_ID)).isEqualTo(offsetForASessionId + 1)
         assertThat(sut.getRoomEventNotificationId(A_SESSION_ID)).isEqualTo(offsetForASessionId + 2)
diff --git a/libraries/push/impl/src/test/kotlin/io/element/android/libraries/push/impl/notifications/fixtures/NotifiableEventFixture.kt b/libraries/push/impl/src/test/kotlin/io/element/android/libraries/push/impl/notifications/fixtures/NotifiableEventFixture.kt
index 9a998abf43..780d2abb71 100644
--- a/libraries/push/impl/src/test/kotlin/io/element/android/libraries/push/impl/notifications/fixtures/NotifiableEventFixture.kt
+++ b/libraries/push/impl/src/test/kotlin/io/element/android/libraries/push/impl/notifications/fixtures/NotifiableEventFixture.kt
@@ -20,6 +20,7 @@ import io.element.android.libraries.matrix.api.core.EventId
 import io.element.android.libraries.matrix.api.core.RoomId
 import io.element.android.libraries.matrix.api.core.SessionId
 import io.element.android.libraries.matrix.api.core.ThreadId
+import io.element.android.libraries.matrix.api.core.UserId
 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_SESSION_ID
@@ -84,7 +85,7 @@ fun aNotifiableMessageEvent(
     noisy = false,
     timestamp = 0,
     senderName = "sender-name",
-    senderId = "sending-id",
+    senderId = UserId("@sending-id:domain.com"),
     body = "message-body",
     roomId = roomId,
     threadId = threadId,
diff --git a/libraries/pushproviders/firebase/src/main/kotlin/io/element/android/libraries/pushproviders/firebase/EnsureFcmTokenIsRetrievedUseCase.kt b/libraries/pushproviders/firebase/src/main/kotlin/io/element/android/libraries/pushproviders/firebase/EnsureFcmTokenIsRetrievedUseCase.kt
deleted file mode 100644
index d557aa0334..0000000000
--- a/libraries/pushproviders/firebase/src/main/kotlin/io/element/android/libraries/pushproviders/firebase/EnsureFcmTokenIsRetrievedUseCase.kt
+++ /dev/null
@@ -1,45 +0,0 @@
-/*
- * Copyright (c) 2023 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
- *
- *     http://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.pushproviders.firebase
-
-import javax.inject.Inject
-
-// TODO
-class EnsureFcmTokenIsRetrievedUseCase @Inject constructor(
-//    private val unifiedPushHelper: UnifiedPushHelper,
-//    private val fcmHelper: FcmHelper,
-        // private val activeSessionHolder: ActiveSessionHolder,
-) {
-
-//    fun execute(pushersManager: PushersManager, registerPusher: Boolean) {
-//        if (unifiedPushHelper.isEmbeddedDistributor()) {
-//            fcmHelper.ensureFcmTokenIsRetrieved(pushersManager, shouldAddHttpPusher(registerPusher))
-//        }
-//    }
-
-    private fun shouldAddHttpPusher(registerPusher: Boolean) = if (registerPusher) {
-        /*
-        TODO EAx
-        val currentSession = activeSessionHolder.getActiveSession()
-        val currentPushers = currentSession.pushersService().getPushers()
-        currentPushers.none { it.deviceId == currentSession.sessionParams.deviceId }
-         */
-        true
-    } else {
-        false
-    }
-}
diff --git a/libraries/pushproviders/firebase/src/main/kotlin/io/element/android/libraries/pushproviders/firebase/PushDataFirebase.kt b/libraries/pushproviders/firebase/src/main/kotlin/io/element/android/libraries/pushproviders/firebase/PushDataFirebase.kt
index 9dedf9648f..795c8bb1e8 100644
--- a/libraries/pushproviders/firebase/src/main/kotlin/io/element/android/libraries/pushproviders/firebase/PushDataFirebase.kt
+++ b/libraries/pushproviders/firebase/src/main/kotlin/io/element/android/libraries/pushproviders/firebase/PushDataFirebase.kt
@@ -36,7 +36,7 @@ import io.element.android.libraries.pushproviders.api.PushData
 data class PushDataFirebase(
     val eventId: String?,
     val roomId: String?,
-    var unread: Int?,
+    val unread: Int?,
     val clientSecret: String?
 )
 
diff --git a/libraries/pushproviders/firebase/src/main/res/values/firebase.xml b/libraries/pushproviders/firebase/src/main/res/values/firebase.xml
index 163717db91..b73238c79d 100644
--- a/libraries/pushproviders/firebase/src/main/res/values/firebase.xml
+++ b/libraries/pushproviders/firebase/src/main/res/values/firebase.xml
@@ -1,10 +1,10 @@
 
-
+
     912726360885-e87n3jva9uoj4vbidvijq78ebg02asv2.apps.googleusercontent.com
     https://vector-alpha.firebaseio.com
     912726360885
     AIzaSyAFZX8IhIfgzdOZvxDP_ISO5WYoU7jmQ5c
     AIzaSyAFZX8IhIfgzdOZvxDP_ISO5WYoU7jmQ5c
     vector-alpha.appspot.com
-    vector-alpha
+    vector-alpha
 
diff --git a/libraries/pushproviders/unifiedpush/src/main/kotlin/io/element/android/libraries/pushproviders/unifiedpush/PushDataUnifiedPush.kt b/libraries/pushproviders/unifiedpush/src/main/kotlin/io/element/android/libraries/pushproviders/unifiedpush/PushDataUnifiedPush.kt
index f092d0167c..4485cb2c7f 100644
--- a/libraries/pushproviders/unifiedpush/src/main/kotlin/io/element/android/libraries/pushproviders/unifiedpush/PushDataUnifiedPush.kt
+++ b/libraries/pushproviders/unifiedpush/src/main/kotlin/io/element/android/libraries/pushproviders/unifiedpush/PushDataUnifiedPush.kt
@@ -47,7 +47,7 @@ data class PushDataUnifiedPush(
 data class PushDataUnifiedPushNotification(
     @SerialName("event_id") val eventId: String? = null,
     @SerialName("room_id") val roomId: String? = null,
-    @SerialName("counts") var counts: PushDataUnifiedPushCounts? = null,
+    @SerialName("counts") val counts: PushDataUnifiedPushCounts? = null,
 )
 
 @Serializable
diff --git a/libraries/pushproviders/unifiedpush/src/main/kotlin/io/element/android/libraries/pushproviders/unifiedpush/UnregisterUnifiedPushUseCase.kt b/libraries/pushproviders/unifiedpush/src/main/kotlin/io/element/android/libraries/pushproviders/unifiedpush/UnregisterUnifiedPushUseCase.kt
index 4efaacbf3a..4bf8217914 100644
--- a/libraries/pushproviders/unifiedpush/src/main/kotlin/io/element/android/libraries/pushproviders/unifiedpush/UnregisterUnifiedPushUseCase.kt
+++ b/libraries/pushproviders/unifiedpush/src/main/kotlin/io/element/android/libraries/pushproviders/unifiedpush/UnregisterUnifiedPushUseCase.kt
@@ -26,7 +26,7 @@ class UnregisterUnifiedPushUseCase @Inject constructor(
     @ApplicationContext private val context: Context,
     //private val pushDataStore: PushDataStore,
     private val unifiedPushStore: UnifiedPushStore,
-    private val unifiedPushGatewayResolver: UnifiedPushGatewayResolver,
+    // private val unifiedPushGatewayResolver: UnifiedPushGatewayResolver,
 ) {
 
     suspend fun execute(clientSecret: String /*pushersManager: PushersManager?*/) {
diff --git a/libraries/pushstore/impl/build.gradle.kts b/libraries/pushstore/impl/build.gradle.kts
index dca5c82a4d..5946e77694 100644
--- a/libraries/pushstore/impl/build.gradle.kts
+++ b/libraries/pushstore/impl/build.gradle.kts
@@ -20,6 +20,11 @@ plugins {
 
 android {
     namespace = "io.element.android.libraries.push.pushstore.impl"
+
+    defaultConfig {
+        testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner"
+        testInstrumentationRunnerArguments["clearPackageData"] = "true"
+    }
 }
 
 anvil {
@@ -43,4 +48,13 @@ dependencies {
     testImplementation(libs.coroutines.test)
     testImplementation(projects.libraries.matrix.test)
     testImplementation(projects.services.appnavstate.test)
+
+    androidTestImplementation(libs.coroutines.test)
+    androidTestImplementation(libs.test.core)
+    androidTestImplementation(libs.test.junit)
+    androidTestImplementation(libs.test.truth)
+    androidTestImplementation(libs.test.runner)
+    androidTestImplementation(projects.libraries.sessionStorage.test)
+
+    coreLibraryDesugaring(libs.android.desugar)
 }
diff --git a/libraries/pushstore/impl/src/androidTest/kotlin/io/element/android/libraries/pushstore/impl/DefaultUserPushStoreFactoryTest.kt b/libraries/pushstore/impl/src/androidTest/kotlin/io/element/android/libraries/pushstore/impl/DefaultUserPushStoreFactoryTest.kt
new file mode 100644
index 0000000000..c87c772ddf
--- /dev/null
+++ b/libraries/pushstore/impl/src/androidTest/kotlin/io/element/android/libraries/pushstore/impl/DefaultUserPushStoreFactoryTest.kt
@@ -0,0 +1,56 @@
+/*
+ * Copyright (c) 2023 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
+ *
+ *     http://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.pushstore.impl
+
+import androidx.test.platform.app.InstrumentationRegistry
+import io.element.android.libraries.matrix.api.core.SessionId
+import io.element.android.libraries.pushstore.api.UserPushStore
+import io.element.android.libraries.sessionstorage.test.observer.NoOpSessionObserver
+import kotlinx.coroutines.runBlocking
+import org.junit.Test
+import kotlin.concurrent.thread
+
+/**
+ * Note: to clear the emulator, invoke:
+ * adb uninstall io.element.android.libraries.push.pushstore.impl.test
+ */
+class DefaultUserPushStoreFactoryTest {
+
+    /**
+     * Ensure that creating UserPushStore is thread safe.
+     */
+    @Test
+    fun testParallelCreation() {
+        val context = InstrumentationRegistry.getInstrumentation().targetContext.applicationContext
+        val sessionId = SessionId("@alice:server.org")
+        val userPushStoreFactory = DefaultUserPushStoreFactory(context, NoOpSessionObserver())
+        var userPushStore1: UserPushStore? = null
+        val thread1 = thread {
+            userPushStore1 = userPushStoreFactory.create(sessionId)
+        }
+        var userPushStore2: UserPushStore? = null
+        val thread2 = thread {
+            userPushStore2 = userPushStoreFactory.create(sessionId)
+        }
+        thread1.join()
+        thread2.join()
+        runBlocking {
+            userPushStore1!!.areNotificationEnabledForDevice()
+            userPushStore2!!.areNotificationEnabledForDevice()
+        }
+    }
+}
diff --git a/libraries/pushstore/impl/src/main/kotlin/io/element/android/libraries/pushstore/impl/DefaultUserPushStoreFactory.kt b/libraries/pushstore/impl/src/main/kotlin/io/element/android/libraries/pushstore/impl/DefaultUserPushStoreFactory.kt
index a84fe2ea69..8c85dca80c 100644
--- a/libraries/pushstore/impl/src/main/kotlin/io/element/android/libraries/pushstore/impl/DefaultUserPushStoreFactory.kt
+++ b/libraries/pushstore/impl/src/main/kotlin/io/element/android/libraries/pushstore/impl/DefaultUserPushStoreFactory.kt
@@ -26,6 +26,7 @@ import io.element.android.libraries.pushstore.api.UserPushStore
 import io.element.android.libraries.pushstore.api.UserPushStoreFactory
 import io.element.android.libraries.sessionstorage.api.observer.SessionListener
 import io.element.android.libraries.sessionstorage.api.observer.SessionObserver
+import java.util.concurrent.ConcurrentHashMap
 import javax.inject.Inject
 
 @SingleIn(AppScope::class)
@@ -39,7 +40,7 @@ class DefaultUserPushStoreFactory @Inject constructor(
     }
 
     // We can have only one class accessing a single data store, so keep a cache of them.
-    private val cache = mutableMapOf()
+    private val cache = ConcurrentHashMap()
     override fun create(userId: SessionId): UserPushStore {
         return cache.getOrPut(userId) {
             UserPushStoreDataStore(
diff --git a/libraries/session-storage/test/build.gradle.kts b/libraries/session-storage/test/build.gradle.kts
new file mode 100644
index 0000000000..0c8de84669
--- /dev/null
+++ b/libraries/session-storage/test/build.gradle.kts
@@ -0,0 +1,26 @@
+/*
+ * Copyright (c) 2023 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
+ *
+ *     http://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.
+ */
+plugins {
+    id("io.element.android-library")
+}
+
+android {
+    namespace = "io.element.android.libraries.sessionstorage.test"
+}
+
+dependencies {
+    implementation(projects.libraries.sessionStorage.api)
+}
diff --git a/libraries/session-storage/test/src/main/kotlin/io/element/android/libraries/sessionstorage/test/observer/NoOpSessionObserver.kt b/libraries/session-storage/test/src/main/kotlin/io/element/android/libraries/sessionstorage/test/observer/NoOpSessionObserver.kt
new file mode 100644
index 0000000000..03487a3701
--- /dev/null
+++ b/libraries/session-storage/test/src/main/kotlin/io/element/android/libraries/sessionstorage/test/observer/NoOpSessionObserver.kt
@@ -0,0 +1,25 @@
+/*
+ * Copyright (c) 2023 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
+ *
+ *     http://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.sessionstorage.test.observer
+
+import io.element.android.libraries.sessionstorage.api.observer.SessionListener
+import io.element.android.libraries.sessionstorage.api.observer.SessionObserver
+
+class NoOpSessionObserver : SessionObserver {
+    override fun addListener(listener: SessionListener) = Unit
+    override fun removeListener(listener: SessionListener) = Unit
+}
diff --git a/libraries/textcomposer/src/main/kotlin/io/element/android/libraries/textcomposer/TextComposer.kt b/libraries/textcomposer/src/main/kotlin/io/element/android/libraries/textcomposer/TextComposer.kt
index 8c4c361707..d407924323 100644
--- a/libraries/textcomposer/src/main/kotlin/io/element/android/libraries/textcomposer/TextComposer.kt
+++ b/libraries/textcomposer/src/main/kotlin/io/element/android/libraries/textcomposer/TextComposer.kt
@@ -38,6 +38,7 @@ import androidx.compose.foundation.layout.width
 import androidx.compose.foundation.shape.CircleShape
 import androidx.compose.foundation.shape.RoundedCornerShape
 import androidx.compose.foundation.text.BasicTextField
+import androidx.compose.foundation.text.KeyboardOptions
 import androidx.compose.material.icons.Icons
 import androidx.compose.material.icons.filled.Close
 import androidx.compose.material.ripple.rememberRipple
@@ -65,6 +66,7 @@ import androidx.compose.ui.layout.ContentScale
 import androidx.compose.ui.platform.LocalSoftwareKeyboardController
 import androidx.compose.ui.res.painterResource
 import androidx.compose.ui.res.stringResource
+import androidx.compose.ui.text.input.KeyboardCapitalization
 import androidx.compose.ui.text.input.VisualTransformation
 import androidx.compose.ui.text.style.TextAlign
 import androidx.compose.ui.text.style.TextOverflow
@@ -73,6 +75,7 @@ import io.element.android.libraries.designsystem.VectorIcons
 import io.element.android.libraries.designsystem.modifiers.applyIf
 import io.element.android.libraries.designsystem.preview.DayNightPreviews
 import io.element.android.libraries.designsystem.preview.ElementPreview
+import io.element.android.libraries.designsystem.text.applyScaleUp
 import io.element.android.libraries.designsystem.theme.components.Icon
 import io.element.android.libraries.designsystem.theme.components.Surface
 import io.element.android.libraries.designsystem.theme.components.Text
@@ -109,12 +112,15 @@ fun TextComposer(
     ) {
         AttachmentButton(onClick = onAddAttachment, modifier = Modifier.padding(vertical = 6.dp))
         Spacer(modifier = Modifier.width(12.dp))
+        val roundCornerSmall = 20.dp.applyScaleUp()
+        val roundCornerLarge = 28.dp.applyScaleUp()
+
         var lineCount by remember { mutableStateOf(0) }
         val roundedCornerSize = remember(lineCount, composerMode) {
             if (lineCount > 1 || composerMode is MessageComposerMode.Special) {
-                20.dp
+                roundCornerSmall
             } else {
-                28.dp
+                roundCornerLarge
             }
         }
         val roundedCornerSizeState = animateDpAsState(
@@ -124,7 +130,7 @@ fun TextComposer(
             )
         )
         val roundedCorners = RoundedCornerShape(roundedCornerSizeState.value)
-        val minHeight = 42.dp
+        val minHeight = 42.dp.applyScaleUp()
         val bgColor = ElementTheme.colors.bgSubtleSecondary
         // Change border color depending on focus
         var hasFocus by remember { mutableStateOf(false) }
@@ -155,6 +161,9 @@ fun TextComposer(
                     onTextLayout = {
                         lineCount = it.lineCount
                     },
+                    keyboardOptions = KeyboardOptions(
+                        capitalization = KeyboardCapitalization.Sentences,
+                    ),
                     textStyle = defaultTypography.copy(color = MaterialTheme.colorScheme.primary),
                     cursorBrush = SolidColor(ElementTheme.colors.iconAccentTertiary),
                     decorationBox = { innerTextField ->
@@ -165,7 +174,12 @@ fun TextComposer(
                             singleLine = false,
                             visualTransformation = VisualTransformation.None,
                             shape = roundedCorners,
-                            contentPadding = PaddingValues(top = 10.dp, bottom = 10.dp, start = 12.dp, end = 42.dp),
+                            contentPadding = PaddingValues(
+                                top = 10.dp.applyScaleUp(),
+                                bottom = 10.dp.applyScaleUp(),
+                                start = 12.dp.applyScaleUp(),
+                                end = 42.dp.applyScaleUp(),
+                            ),
                             interactionSource = remember { MutableInteractionSource() },
                             placeholder = {
                                 Text(stringResource(CommonStrings.common_message), style = defaultTypography)
@@ -193,7 +207,7 @@ fun TextComposer(
                     canSendMessage = composerCanSendMessage,
                     onSendMessage = onSendMessage,
                     composerMode = composerMode,
-                    modifier = Modifier.padding(end = 6.dp, bottom = 6.dp)
+                    modifier = Modifier.padding(end = 6.dp.applyScaleUp(), bottom = 6.dp.applyScaleUp())
                 )
             }
         }
@@ -253,7 +267,7 @@ private fun EditingModeView(
             tint = ElementTheme.materialColors.secondary,
             modifier = Modifier
                 .padding(vertical = 8.dp)
-                .size(16.dp),
+                .size(16.dp.applyScaleUp()),
         )
         Text(
             stringResource(CommonStrings.common_editing),
@@ -270,7 +284,7 @@ private fun EditingModeView(
             tint = ElementTheme.materialColors.secondary,
             modifier = Modifier
                 .padding(top = 8.dp, bottom = 8.dp, start = 16.dp, end = 12.dp)
-                .size(16.dp)
+                .size(16.dp.applyScaleUp())
                 .clickable(
                     enabled = true,
                     onClick = onResetComposerMode,
@@ -333,7 +347,7 @@ private fun ReplyToModeView(
             tint = MaterialTheme.colorScheme.secondary,
             modifier = Modifier
                 .padding(end = 4.dp, top = 4.dp, start = 16.dp, bottom = 16.dp)
-                .size(16.dp)
+                .size(16.dp.applyScaleUp())
                 .clickable(
                     enabled = true,
                     onClick = onResetComposerMode,
@@ -351,13 +365,13 @@ private fun AttachmentButton(
 ) {
     Surface(
         modifier
-            .size(30.dp)
+            .size(30.dp.applyScaleUp())
             .clickable(onClick = onClick),
         shape = CircleShape,
         color = ElementTheme.colors.iconPrimary
     ) {
         Image(
-            modifier = Modifier.size(12.5f.dp),
+            modifier = Modifier.size(12.5f.dp.applyScaleUp()),
             painter = painterResource(R.drawable.ic_add_attachment),
             contentDescription = stringResource(R.string.rich_text_editor_a11y_add_attachment),
             contentScale = ContentScale.Inside,
@@ -381,10 +395,10 @@ private fun BoxScope.SendButton(
         modifier = modifier
             .clip(CircleShape)
             .background(if (canSendMessage) ElementTheme.colors.iconAccentTertiary else Color.Transparent)
-            .size(30.dp)
+            .size(30.dp.applyScaleUp())
             .align(Alignment.BottomEnd)
             .applyIf(composerMode !is MessageComposerMode.Edit, ifTrue = {
-                padding(start = 1.dp) // Center the arrow in the circle
+                padding(start = 1.dp.applyScaleUp()) // Center the arrow in the circle
             })
             .clickable(
                 enabled = canSendMessage,
@@ -404,7 +418,7 @@ private fun BoxScope.SendButton(
             else -> stringResource(CommonStrings.action_send)
         }
         Icon(
-            modifier = Modifier.size(16.dp),
+            modifier = Modifier.size(16.dp.applyScaleUp()),
             resourceId = iconId,
             contentDescription = contentDescription,
             // Exception here, we use Color.White instead of ElementTheme.colors.iconOnSolidPrimary
@@ -415,7 +429,7 @@ private fun BoxScope.SendButton(
 
 @DayNightPreviews
 @Composable
-fun TextComposerSimplePreview() = ElementPreview {
+internal fun TextComposerSimplePreview() = ElementPreview {
     Column {
         TextComposer(
             onSendMessage = {},
@@ -446,7 +460,7 @@ fun TextComposerSimplePreview() = ElementPreview {
 
 @DayNightPreviews
 @Composable
-fun TextComposerEditPreview() = ElementPreview {
+internal fun TextComposerEditPreview() = ElementPreview {
     TextComposer(
         onSendMessage = {},
         onComposerTextChange = {},
@@ -459,7 +473,7 @@ fun TextComposerEditPreview() = ElementPreview {
 
 @DayNightPreviews
 @Composable
-fun TextComposerReplyPreview() = ElementPreview {
+internal fun TextComposerReplyPreview() = ElementPreview {
     Column {
         TextComposer(
             onSendMessage = {},
diff --git a/libraries/textcomposer/src/main/res/values-ru/translations.xml b/libraries/textcomposer/src/main/res/values-ru/translations.xml
new file mode 100644
index 0000000000..9f7324f086
--- /dev/null
+++ b/libraries/textcomposer/src/main/res/values-ru/translations.xml
@@ -0,0 +1,18 @@
+
+
+  "Прикрепить файл"
+  "Переключить список маркеров"
+  "Переключить блок кода"
+  "Сообщение"
+  "Применить жирный шрифт"
+  "Применить курсивный формат"
+  "Применить формат зачеркивания"
+  "Применить формат подчеркивания"
+  "Переключение полноэкранного режима"
+  "Отступ"
+  "Применить встроенный формат кода"
+  "Установить ссылку"
+  "Переключить нумерованный список"
+  "Переключить цитату"
+  "Без отступа"
+
diff --git a/libraries/textcomposer/src/main/res/values-sk/translations.xml b/libraries/textcomposer/src/main/res/values-sk/translations.xml
index a5f42a60f8..26ac1df436 100644
--- a/libraries/textcomposer/src/main/res/values-sk/translations.xml
+++ b/libraries/textcomposer/src/main/res/values-sk/translations.xml
@@ -1,5 +1,6 @@
 
 
+  "Pridať prílohu"
   "Prepnúť zoznam odrážok"
   "Prepnúť blok kódu"
   "Správa…"
diff --git a/libraries/textcomposer/src/main/res/values-zh-rTW/translations.xml b/libraries/textcomposer/src/main/res/values-zh-rTW/translations.xml
new file mode 100644
index 0000000000..93777d4ca5
--- /dev/null
+++ b/libraries/textcomposer/src/main/res/values-zh-rTW/translations.xml
@@ -0,0 +1,17 @@
+
+
+  "新增附件"
+  "切換項目編號"
+  "切換程式碼區塊"
+  "訊息"
+  "套用粗體"
+  "套用斜體"
+  "套用刪除線"
+  "套用底線"
+  "切換全螢幕模式"
+  "增加縮排"
+  "設定連結"
+  "切換數字編號"
+  "切換引用"
+  "減少縮排"
+
diff --git a/libraries/theme/src/main/kotlin/io/element/android/libraries/theme/ElementTheme.kt b/libraries/theme/src/main/kotlin/io/element/android/libraries/theme/ElementTheme.kt
index f273c2dd64..62c87b39bb 100644
--- a/libraries/theme/src/main/kotlin/io/element/android/libraries/theme/ElementTheme.kt
+++ b/libraries/theme/src/main/kotlin/io/element/android/libraries/theme/ElementTheme.kt
@@ -68,6 +68,14 @@ object ElementTheme {
      */
     val typography: TypographyTokens = TypographyTokens
 
+    /**
+     * Material 3 [Typography] tokens. In Figma, these have the `M3 Typography/` prefix.
+     */
+    val materialTypography: Typography
+        @Composable
+        @ReadOnlyComposable
+        get()= MaterialTheme.typography
+
     /**
      * Returns whether the theme version used is the light or the dark one.
      */
diff --git a/libraries/theme/src/main/kotlin/io/element/android/libraries/theme/LegacyColors.kt b/libraries/theme/src/main/kotlin/io/element/android/libraries/theme/LegacyColors.kt
index b797dab86a..2e705c8c79 100644
--- a/libraries/theme/src/main/kotlin/io/element/android/libraries/theme/LegacyColors.kt
+++ b/libraries/theme/src/main/kotlin/io/element/android/libraries/theme/LegacyColors.kt
@@ -17,6 +17,8 @@
 package io.element.android.libraries.theme
 
 import androidx.compose.ui.graphics.Color
+import io.element.android.libraries.theme.compound.generated.internal.DarkDesignTokens
+import io.element.android.libraries.theme.compound.generated.internal.LightDesignTokens
 
 // =================================================================================================
 // IMPORTANT!
@@ -26,3 +28,6 @@ import androidx.compose.ui.graphics.Color
 // =================================================================================================
 
 val LinkColor = Color(0xFF0086E6)
+
+val SnackBarLabelColorLight = LightDesignTokens.colorGray700
+val SnackBarLabelColorDark = DarkDesignTokens.colorGray700
diff --git a/libraries/theme/src/main/kotlin/io/element/android/libraries/theme/MaterialThemeColors.kt b/libraries/theme/src/main/kotlin/io/element/android/libraries/theme/MaterialThemeColors.kt
index d211869f71..3d359594e1 100644
--- a/libraries/theme/src/main/kotlin/io/element/android/libraries/theme/MaterialThemeColors.kt
+++ b/libraries/theme/src/main/kotlin/io/element/android/libraries/theme/MaterialThemeColors.kt
@@ -91,7 +91,7 @@ internal val materialColorSchemeDark = darkColorScheme(
 
 @Preview
 @Composable
-fun ColorsSchemePreviewLight() = ColorsSchemePreview(
+internal fun ColorsSchemePreviewLight() = ColorsSchemePreview(
     Color.Black,
     Color.White,
     materialColorSchemeLight,
@@ -99,7 +99,7 @@ fun ColorsSchemePreviewLight() = ColorsSchemePreview(
 
 @Preview
 @Composable
-fun ColorsSchemePreviewDark() = ColorsSchemePreview(
+internal fun ColorsSchemePreviewDark() = ColorsSchemePreview(
     Color.White,
     Color.Black,
     materialColorSchemeDark,
diff --git a/libraries/theme/src/main/res/drawable/ic_chat.xml b/libraries/theme/src/main/res/drawable/ic_chat.xml
deleted file mode 100644
index 1fef824a1d..0000000000
--- a/libraries/theme/src/main/res/drawable/ic_chat.xml
+++ /dev/null
@@ -1,9 +0,0 @@
-
-    
-
diff --git a/libraries/theme/src/main/res/drawable/ic_check.xml b/libraries/theme/src/main/res/drawable/ic_check.xml
deleted file mode 100644
index e92733095b..0000000000
--- a/libraries/theme/src/main/res/drawable/ic_check.xml
+++ /dev/null
@@ -1,9 +0,0 @@
-
-    
-
diff --git a/libraries/theme/src/main/res/drawable/ic_check_circle.xml b/libraries/theme/src/main/res/drawable/ic_check_circle.xml
deleted file mode 100644
index ad3aacbe28..0000000000
--- a/libraries/theme/src/main/res/drawable/ic_check_circle.xml
+++ /dev/null
@@ -1,9 +0,0 @@
-
-    
-
diff --git a/libraries/theme/src/main/res/drawable/ic_chevron.xml b/libraries/theme/src/main/res/drawable/ic_chevron.xml
deleted file mode 100644
index 4ecd3f16b0..0000000000
--- a/libraries/theme/src/main/res/drawable/ic_chevron.xml
+++ /dev/null
@@ -1,9 +0,0 @@
-
-    
-
diff --git a/libraries/theme/src/main/res/drawable/ic_close.xml b/libraries/theme/src/main/res/drawable/ic_close.xml
deleted file mode 100644
index f334767b67..0000000000
--- a/libraries/theme/src/main/res/drawable/ic_close.xml
+++ /dev/null
@@ -1,9 +0,0 @@
-
-    
-
diff --git a/libraries/theme/src/main/res/drawable/ic_computer.xml b/libraries/theme/src/main/res/drawable/ic_computer.xml
deleted file mode 100644
index e2748c2d4a..0000000000
--- a/libraries/theme/src/main/res/drawable/ic_computer.xml
+++ /dev/null
@@ -1,9 +0,0 @@
-
-    
-
diff --git a/libraries/theme/src/main/res/drawable/ic_delete.xml b/libraries/theme/src/main/res/drawable/ic_delete.xml
deleted file mode 100644
index 413a570210..0000000000
--- a/libraries/theme/src/main/res/drawable/ic_delete.xml
+++ /dev/null
@@ -1,9 +0,0 @@
-
-    
-
diff --git a/libraries/theme/src/main/res/drawable/ic_error.xml b/libraries/theme/src/main/res/drawable/ic_error.xml
deleted file mode 100644
index d978824039..0000000000
--- a/libraries/theme/src/main/res/drawable/ic_error.xml
+++ /dev/null
@@ -1,9 +0,0 @@
-
-    
-
diff --git a/libraries/theme/src/main/res/drawable/ic_info.xml b/libraries/theme/src/main/res/drawable/ic_info.xml
deleted file mode 100644
index 69865e325a..0000000000
--- a/libraries/theme/src/main/res/drawable/ic_info.xml
+++ /dev/null
@@ -1,9 +0,0 @@
-
-    
-
diff --git a/libraries/theme/src/main/res/drawable/ic_lock.xml b/libraries/theme/src/main/res/drawable/ic_lock.xml
deleted file mode 100644
index 2ada59e82f..0000000000
--- a/libraries/theme/src/main/res/drawable/ic_lock.xml
+++ /dev/null
@@ -1,9 +0,0 @@
-
-    
-
diff --git a/libraries/theme/src/main/res/drawable/ic_mobile.xml b/libraries/theme/src/main/res/drawable/ic_mobile.xml
deleted file mode 100644
index f2c46be357..0000000000
--- a/libraries/theme/src/main/res/drawable/ic_mobile.xml
+++ /dev/null
@@ -1,9 +0,0 @@
-
-    
-
diff --git a/libraries/theme/src/main/res/drawable/ic_thread.xml b/libraries/theme/src/main/res/drawable/ic_thread.xml
deleted file mode 100644
index d3293fab5a..0000000000
--- a/libraries/theme/src/main/res/drawable/ic_thread.xml
+++ /dev/null
@@ -1,13 +0,0 @@
-
-    
-    
-
diff --git a/libraries/theme/src/main/res/drawable/ic_user.xml b/libraries/theme/src/main/res/drawable/ic_user.xml
deleted file mode 100644
index 5f61985ce4..0000000000
--- a/libraries/theme/src/main/res/drawable/ic_user.xml
+++ /dev/null
@@ -1,11 +0,0 @@
-
-    
-
diff --git a/libraries/theme/src/main/res/drawable/ic_visibility_invisible.xml b/libraries/theme/src/main/res/drawable/ic_visibility_invisible.xml
deleted file mode 100644
index 3f20783ee4..0000000000
--- a/libraries/theme/src/main/res/drawable/ic_visibility_invisible.xml
+++ /dev/null
@@ -1,9 +0,0 @@
-
-    
-
diff --git a/libraries/theme/src/main/res/drawable/ic_visibility_visible.xml b/libraries/theme/src/main/res/drawable/ic_visibility_visible.xml
deleted file mode 100644
index 1283a1512b..0000000000
--- a/libraries/theme/src/main/res/drawable/ic_visibility_visible.xml
+++ /dev/null
@@ -1,9 +0,0 @@
-
-    
-
diff --git a/libraries/theme/src/main/res/drawable/ic_web_browser.xml b/libraries/theme/src/main/res/drawable/ic_web_browser.xml
deleted file mode 100644
index 080ce75905..0000000000
--- a/libraries/theme/src/main/res/drawable/ic_web_browser.xml
+++ /dev/null
@@ -1,9 +0,0 @@
-
-    
-
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 10694181da..0f5259e663 100644
--- a/libraries/ui-strings/src/main/res/values-de/translations.xml
+++ b/libraries/ui-strings/src/main/res/values-de/translations.xml
@@ -94,7 +94,7 @@
   "Passwort"
   "Personen"
   "Permalink"
-  "Datenschutzerklärung"
+  "Datenschutz­erklärung"
   "Reaktionen"
   "Aktualisiere…"
   "Auf %1$s antworten"
@@ -145,7 +145,7 @@
   "%1$s konnte nicht auf deinen Standort zugreifen. Bitte versuche es später erneut."
   "Einige Nachrichten wurden nicht gesendet"
   "Entschuldigung, ein Fehler ist aufgetreten."
-  "🔐️ Besuchen Sie mich auf %1$s"
+  "🔐️ Besuche mich auf %1$s"
   "Hey, sprich mit mir auf %1$s: %2$s"
   "Bist du sicher, dass du diesen Raum verlassen willst? Du bist die einzige Person hier. Wenn du gehst, kann in Zukunft niemand mehr beitreten, auch du nicht."
   "Bist du dir sicher, dass du den Raum verlassen möchtest? Dieser Raum ist nicht öffentlich und du kannst ihm ohne eine Einladung nicht mehr beitreten."
@@ -164,10 +164,10 @@
   "Neu"
   "Teile Analyse-Daten"
   "Medienauswahl fehlgeschlagen, bitte versuche es erneut."
-  "Fehler bei der Verarbeitung von Medien zum Hochladen, bitte versuchen Sie es erneut."
+  "Fehler bei der Verarbeitung von Medien zum Hochladen, bitte versuche es erneut."
   "Hochladen von Medien fehlgeschlagen, bitte versuchen Sie es erneut."
   "Dies ist ein einmaliger Vorgang, danke fürs Warten."
-  "Deinen Account einrichten"
+  "Dein Konto einrichten"
   "Prüfe, ob du alle aktuellen und zukünftigen Nachrichten dieses Benutzers ausblenden möchtest"
   "Standort teilen"
   "Meinen Standort teilen"
@@ -184,7 +184,7 @@
   "Fehler"
   "Erfolg"
   "Teile anonyme Nutzungsdaten, um uns bei der Identifizierung von Problemen zu helfen."
-  "Sie können alle unsere Nutzerbedingungen %1$s lesen."
+  "Du kannst alle unsere Nutzerbedingungen %1$s lesen."
   "hier"
   "Nutzer blockieren"
 
diff --git a/libraries/ui-strings/src/main/res/values-ru/translations.xml b/libraries/ui-strings/src/main/res/values-ru/translations.xml
new file mode 100644
index 0000000000..d4830e9127
--- /dev/null
+++ b/libraries/ui-strings/src/main/res/values-ru/translations.xml
@@ -0,0 +1,213 @@
+
+
+  "Скрыть пароль"
+  "Отправить файлы"
+  "Показать пароль"
+  "Меню пользователя"
+  "Разрешить"
+  "Назад"
+  "Отмена"
+  "Выбрать фото"
+  "Очистить"
+  "Закрыть"
+  "Полная проверка"
+  "Подтвердить"
+  "Продолжить"
+  "Копировать"
+  "Скопировать ссылку"
+  "Скопировать ссылку в сообщение"
+  "Создать"
+  "Создать комнату"
+  "Отклонить"
+  "Отключить"
+  "Готово"
+  "Редактировать"
+  "Включить"
+  "Забыли пароль?"
+  "Переслать"
+  "Пригласить"
+  "Пригласить друзей"
+  "Пригласить друзей в %1$s"
+  "Пригласите пользователей в %1$s"
+  "Приглашения"
+  "Подробнее"
+  "Выйти"
+  "Покинуть комнату"
+  "Далее"
+  "Нет"
+  "Не сейчас"
+  "Ок"
+  "Открыть с помощью"
+  "Быстрый ответ"
+  "Цитата"
+  "Реакция"
+  "Удалить"
+  "Ответить"
+  "Сообщить об ошибке"
+  "Пожаловаться на содержание"
+  "Повторить"
+  "Повторите расшифровку"
+  "Сохранить"
+  "Поиск"
+  "Отправить"
+  "Отправить сообщение"
+  "Поделиться"
+  "Поделиться ссылкой"
+  "Пропустить"
+  "Начать"
+  "Начать чат "
+  "Начать подтверждение"
+  "Нажмите, чтобы загрузить карту"
+  "Сделать фото"
+  "Показать источник"
+  "Да"
+  "О приложении"
+  "Политика допустимого использования"
+  "Аналитика"
+  "Аудио"
+  "Пузыри"
+  "Авторское право"
+  "Создание комнаты…"
+  "Покинул комнату"
+  "Ошибка расшифровки"
+  "Для разработчика"
+  "(изменено)"
+  "Редактирование"
+  "%1$s%2$s"
+  "Шифрование включено"
+  "Ошибка"
+  "Файл"
+  "Файл сохранен в «Загрузки»"
+  "Переслать сообщение"
+  "GIF"
+  "Изображения"
+  "Идентификатор Matrix ID не найден, приглашение может быть не получено."
+  "Покинуть комнату"
+  "Ссылка скопирована в буфер обмена"
+  "Загрузка…"
+  "Сообщение"
+  "Оформление сообщений"
+  "Сообщение удалено"
+  "Современный"
+  "Без звука"
+  "Ничего не найдено"
+  "Не в сети"
+  "Пароль"
+  "Пользователи"
+  "Постоянная ссылка"
+  "Политика конфиденциальности"
+  "Реакции"
+  "Обновление…"
+  "Отвечает на %1$s"
+  "Сообщить об ошибке"
+  "Отчет отправлен"
+  "Название комнаты"
+  "например, название вашего проекта"
+  "Поиск человека"
+  "Результаты поиска"
+  "Безопасность"
+  "Выберите свой сервер"
+  "Отправка…"
+  "Сервер не поддерживается"
+  "Адрес сервера"
+  "Настройки"
+  "Делится местонахождением"
+  "Начало чата…"
+  "Стикер"
+  "Успешно"
+  "Рекомендации"
+  "Синхронизация"
+  "Уведомление о третьей стороне"
+  "Тема"
+  "О чем эта комната?"
+  "Невозможно расшифровать"
+  "Не удалось отправить приглашения одному или нескольким пользователям."
+  "Не удалось отправить приглашение(я)"
+  "Включить звук"
+  "Неподдерживаемое событие"
+  "Имя пользователя"
+  "Проверка отменена"
+  "Проверка завершена"
+  "Видео"
+  "Ожидание…"
+  "Подтверждение"
+  "Предупреждение"
+  "Деятельность"
+  "Флаги"
+  "Еда и напитки"
+  "Животные и природа"
+  "Объекты"
+  "Смайлы и люди"
+  "Путешествия и места"
+  "Символы"
+  "Не удалось создать постоянную ссылку"
+  "Не удалось загрузить карту %1$s. Пожалуйста, повторите попытку позже."
+  "Не удалось загрузить сообщения"
+  "%1$s не удалось получить доступ к вашему местоположению. Пожалуйста, повторите попытку позже."
+  "У %1$s нет разрешения на доступ к вашему местоположению. Вы можете разрешить доступ в Настройках."
+  "У %1$s нет разрешения на доступ к вашему местоположению. Разрешите доступ ниже."
+  "Некоторые сообщения не были отправлены"
+  "Извините, произошла ошибка"
+  "🔐️ Присоединяйтесь ко мне в %1$s"
+  "Привет, поговори со мной по %1$s: %2$s"
+  "Вы уверены, что хотите покинуть эту комнату? Вы здесь единственный человек. Если вы уйдете, никто не сможет присоединиться в будущем, включая вас."
+  "Вы уверены, что хотите покинуть эту комнату? Эта комната не является публичной, и Вы не сможете присоединиться к ней без приглашения."
+  "Вы уверены, что хотите покинуть комнату?"
+  "%1$s Android"
+  
+    "%1$d участник"
+    "%1$d участников"
+    "%1$d участников"
+  
+  
+    "%d голос"
+    "%d голоса"
+    "%d голосов"
+  
+  "Rageshake сообщит об ошибке"
+  "Кажется, вы трясли телефон. Хотите открыть экран отчета об ошибке?"
+  "Это сообщение будет передано администратору вашего домашнего сервера. Они не смогут прочитать зашифрованные сообщения."
+  "Причина, по которой вы пожаловались на этот контент"
+  "Это начало %1$s."
+  "Это начало разговора."
+  "Новый"
+  "Делитесь данными аналитики"
+  "Не удалось выбрать носитель, попробуйте еще раз."
+  "Не удалось обработать медиафайл для загрузки, попробуйте еще раз."
+  "Не удалось загрузить медиафайлы, попробуйте еще раз."
+  "Это одноразовый процесс, спасибо, что подождали."
+  "Настройка учетной записи."
+  "Дополнительные параметры"
+  "Аудио и видео звонки"
+  "Прямые чаты"
+  "Включить уведомления на данном устройстве"
+  "Групповые чаты"
+  "Упоминания"
+  "Все"
+  "Упоминания"
+  "Уведомить меня"
+  "Уведомить меня в @room"
+  "Чтобы получать уведомления, измените свой %1$s."
+  "Настройки системы"
+  "Системные уведомления выключены"
+  "Уведомления"
+  "Отметьте, хотите ли вы скрыть все текущие и будущие сообщения от этого пользователя"
+  "Поделиться местоположением"
+  "Поделиться моим местоположением"
+  "Открыть в Apple Maps"
+  "Открыть в Google Картах"
+  "Открыть в OpenStreetMap"
+  "Поделиться этим местоположением"
+  "Местоположение"
+  "Rageshake"
+  "Порог обнаружения"
+  "Основные"
+  "Версия: %1$s (%2$s)"
+  "en"
+  "Ошибка"
+  "Успешно"
+  "Предоставлять анонимные данные об использовании, чтобы помочь нам выявить проблемы."
+  "Вы можете ознакомиться со всеми нашими условиями %1$s."
+  "здесь"
+  "Заблокировать пользователя"
+
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 654f3d7cbe..14dd5626c8 100644
--- a/libraries/ui-strings/src/main/res/values-sk/translations.xml
+++ b/libraries/ui-strings/src/main/res/values-sk/translations.xml
@@ -40,6 +40,7 @@
   "Otvoriť pomocou"
   "Rýchla odpoveď"
   "Citovať"
+  "Reagovať"
   "Odstrániť"
   "Odpovedať"
   "Nahlásiť chybu"
@@ -94,6 +95,9 @@
   "Heslo"
   "Ľudia"
   "Trvalý odkaz"
+  "Výsledné hlasovanie: %1$s"
+  "Celkový počet hlasov: %1$s"
+  "Výsledky sa zobrazia po ukončení ankety"
   "Zásady ochrany osobných údajov"
   "Reakcie"
   "Obnovuje sa…"
@@ -143,6 +147,8 @@
   "%1$s nedokázal načítať mapu. Skúste to prosím neskôr."
   "Načítanie správ zlyhalo"
   "%1$s nemohol získať prístup k vašej polohe. Skúste to prosím neskôr."
+  "%1$s nemá povolenie na prístup k vašej polohe. Prístup môžete zapnúť v Nastaveniach."
+  "%1$s nemá povolenie na prístup k vašej polohe. Povoľte prístup nižšie."
   "Niektoré správy neboli odoslané"
   "Prepáčte, vyskytla sa chyba"
   "🔐️ Pripojte sa ku mne na %1$s"
@@ -156,6 +162,11 @@
     "%1$d členovia"
     "%1$d členov"
   
+  
+    "1 hlas"
+    "%d hlasy"
+    "%d hlasov"
+  
   "Zúrivo potriasť pre nahlásenie chyby"
   "Zdá sa, že zúrivo trasiete telefónom. Chcete otvoriť obrazovku s nahlásením chýb?"
   "Táto správa bude nahlásená správcovi vášho domovského servera. Nebude môcť prečítať žiadne šifrované správy."
@@ -169,7 +180,18 @@
   "Nepodarilo sa nahrať médiá, skúste to prosím znova."
   "Ide o jednorazový proces, ďakujeme za trpezlivosť."
   "Nastavenie vášho účtu."
+  "Ďalšie nastavenia"
+  "Audio a video hovory"
+  "Priame konverzácie"
+  "Pri priamych rozhovoroch ma upozorniť na"
+  "Pri skupinových rozhovoroch ma upozorniť na"
   "Povoliť oznámenia na tomto zariadení"
+  "Skupinové rozhovory"
+  "Zmienky"
+  "Všetky"
+  "Zmienky"
+  "Upozorniť ma na"
+  "Upozorniť ma na @miestnosť"
   "Ak chcete dostávať oznámenia, zmeňte prosím svoje %1$s."
   "nastavenia systému"
   "Systémové oznámenia sú vypnuté"
diff --git a/libraries/ui-strings/src/main/res/values-zh-rTW/translations.xml b/libraries/ui-strings/src/main/res/values-zh-rTW/translations.xml
new file mode 100644
index 0000000000..701a6243ac
--- /dev/null
+++ b/libraries/ui-strings/src/main/res/values-zh-rTW/translations.xml
@@ -0,0 +1,169 @@
+
+
+  "隱藏密碼"
+  "傳送檔案"
+  "顯示密碼"
+  "使用者選單"
+  "接受"
+  "返回"
+  "取消"
+  "選擇照片"
+  "清除"
+  "關閉"
+  "完成驗證"
+  "確認"
+  "繼續"
+  "複製"
+  "複製連結"
+  "建立"
+  "建立聊天室"
+  "停用"
+  "完成"
+  "編輯"
+  "啟用"
+  "忘記密碼?"
+  "轉寄"
+  "邀請"
+  "邀請朋友"
+  "邀請朋友使用%1$s"
+  "邀請夥伴使用%1$s"
+  "邀請"
+  "了解更多"
+  "離開"
+  "離開聊天室"
+  "下一個"
+  "否"
+  "以後再說"
+  "OK"
+  "用其他方式開啟"
+  "快速回覆"
+  "引用"
+  "回應"
+  "移除"
+  "回覆"
+  "檢舉內容"
+  "再試一次"
+  "再次嘗試解密"
+  "儲存"
+  "搜尋"
+  "傳送"
+  "傳送訊息"
+  "分享"
+  "分享連結"
+  "跳過"
+  "開始"
+  "開始聊天"
+  "開始驗證"
+  "點擊以載入地圖"
+  "拍照"
+  "檢視原始碼"
+  "是"
+  "關於"
+  "分析"
+  "音訊"
+  "著作權"
+  "正在建立聊天室…"
+  "離開聊天室"
+  "解密錯誤"
+  "開發者選項"
+  "(已編輯)"
+  "編輯中"
+  "已啟用加密"
+  "錯誤"
+  "檔案"
+  "檔案已儲存至 Downloads"
+  "訊息轉寄"
+  "GIF"
+  "圖片"
+  "找不到此 Matrix ID,因此可能沒有人會收到邀請。"
+  "正在離開聊天室"
+  "連結已複製到剪貼簿"
+  "載入中…"
+  "訊息"
+  "訊息布局"
+  "訊息已移除"
+  "現代"
+  "關閉通知"
+  "查無結果"
+  "離線"
+  "密碼"
+  "夥伴"
+  "永久連結"
+  "結果將在投票結束後公佈"
+  "隱私權政策"
+  "回應"
+  "重新整理…"
+  "正在回覆%1$s"
+  "聊天室名稱"
+  "範例:您的計畫名稱"
+  "搜尋結果"
+  "選擇您的伺服器"
+  "傳送中…"
+  "伺服器 URL"
+  "設定"
+  "貼圖"
+  "成功"
+  "建議"
+  "同步中"
+  "主題"
+  "無法解密"
+  "無法發送邀請給一或多個使用者。"
+  "無法發送邀請"
+  "開啟通知"
+  "使用者名稱"
+  "驗證已取消"
+  "驗證完成"
+  "影片"
+  "等待中…"
+  "確認"
+  "警告"
+  "活動"
+  "旗幟"
+  "食物與飲料"
+  "動物與大自然"
+  "物品"
+  "表情與人物"
+  "旅行與景點"
+  "標誌"
+  "無法建立永久連結"
+  "%1$s無法載入地圖。請稍後再試。"
+  "無法載入訊息"
+  "%1$s無法取得您的位置。請稍後再試。"
+  "有些訊息尚未傳送"
+  "您確定要離開聊天室嗎?這裡只有您一個人。如果您離開了,包含您在內的所有人都無法再進入此聊天室。"
+  "您確定要離開聊天室嗎?此聊天室不是公開的,如果沒有收到邀請,您無法重新加入。"
+  "您確定要離開聊天室嗎?"
+  "%1$s Android"
+  
+    "%1$d 位成員"
+  
+  
+    "%d 票"
+  
+  "檢舉這個內容的原因"
+  "新訊息"
+  "無法上傳媒體檔案,請稍後再試。"
+  "設定您的帳號"
+  "其他設定"
+  "私訊"
+  "在這個裝置上開啟通知"
+  "群組聊天"
+  "提及"
+  "提及"
+  "系統設定"
+  "已關閉系統通知"
+  "通知"
+  "分享位置"
+  "分享我的位置"
+  "在 Apple 地圖中開啟"
+  "在 Google 地圖中開啟"
+  "在開放街圖(OpenStreetMap) 中開啟"
+  "分享這個位置"
+  "位置"
+  "一般"
+  "版本:%1$s(%2$s)"
+  "zh-tw"
+  "錯誤"
+  "成功"
+  "封鎖使用者"
+
diff --git a/libraries/ui-strings/src/main/res/values/donottranslate.xml b/libraries/ui-strings/src/main/res/values/donottranslate.xml
deleted file mode 100755
index 910ce31c41..0000000000
--- a/libraries/ui-strings/src/main/res/values/donottranslate.xml
+++ /dev/null
@@ -1,17 +0,0 @@
-
-
-
-    
-    
-
-    
-    Not implemented yet in ${app_name}
-
-    
-    Cut the slack from teams.
-
-    Crash the application.
-
-    
-    © MapTiler © OpenStreetMap contributors
-
diff --git a/libraries/ui-strings/src/main/res/values/localazy.xml b/libraries/ui-strings/src/main/res/values/localazy.xml
index 10952f4194..3b4c305ffc 100644
--- a/libraries/ui-strings/src/main/res/values/localazy.xml
+++ b/libraries/ui-strings/src/main/res/values/localazy.xml
@@ -40,6 +40,7 @@
   "Open with"
   "Quick reply"
   "Quote"
+  "React"
   "Remove"
   "Reply"
   "Report bug"
@@ -94,6 +95,9 @@
   "Password"
   "People"
   "Permalink"
+  "Final votes: %1$s"
+  "Total votes: %1$s"
+  "Results will show after the poll has ended"
   "Privacy policy"
   "Reactions"
   "Refreshing…"
@@ -143,8 +147,8 @@
   "%1$s could not load the map. Please try again later."
   "Failed loading messages"
   "%1$s could not access your location. Please try again later."
-  "To send a location, allow %1$s to access your location from its settings screen."
-  "To send a location, allow %1$s to access your location in the next dialog."
+  "%1$s does not have permission to access your location. You can enable access in Settings."
+  "%1$s does not have permission to access your location. Enable access below."
   "Some messages have not been sent"
   "Sorry, an error occurred"
   "🔐️ Join me on %1$s"
@@ -157,6 +161,10 @@
     "%1$d member"
     "%1$d members"
   
+  
+    "%d vote"
+    "%d votes"
+  
   "Rageshake to report bug"
   "You seem to be shaking the phone in frustration. Would you like to open the bug report screen?"
   "This message will be reported to your homeserver’s administrator. They will not be able to read any encrypted messages."
@@ -170,7 +178,19 @@
   "Failed uploading media, please try again."
   "This is a one time process, thanks for waiting."
   "Setting up your account."
+  "Additional settings"
+  "Audio and video calls"
+  "Direct chats"
+  "An error occurred while updating the notification setting."
+  "On direct chats, notify me for"
+  "On group chats, notify me for"
   "Enable notifications on this device"
+  "Group chats"
+  "Mentions"
+  "All"
+  "Mentions"
+  "Notify me for"
+  "Notify me on @room"
   "To receive notifications, please change your %1$s."
   "system settings"
   "System notifications turned off"
diff --git a/plugins/settings.gradle.kts b/plugins/settings.gradle.kts
index defcb6f17b..7e2ce1ea50 100644
--- a/plugins/settings.gradle.kts
+++ b/plugins/settings.gradle.kts
@@ -14,6 +14,8 @@
  * limitations under the License.
  */
 
+rootProject.name = "ElementX_plugins"
+
 dependencyResolutionManagement {
     repositories {
         mavenCentral()
diff --git a/plugins/src/main/kotlin/Versions.kt b/plugins/src/main/kotlin/Versions.kt
index 36a3a33e70..2e89afa70f 100644
--- a/plugins/src/main/kotlin/Versions.kt
+++ b/plugins/src/main/kotlin/Versions.kt
@@ -17,10 +17,50 @@
 import org.gradle.api.JavaVersion
 import org.gradle.jvm.toolchain.JavaLanguageVersion
 
-object Versions {
-    const val versionCode = 100100
-    const val versionName = "0.1.0"
+/**
+ * Version codes are quite sensitive, because there is a mix between bundle and APKs, and we have to take into
+ * account the future upgrade of Element Android.
+ * Max versionCode allowed by the PlayStore (for information):
+ * 2_100_000_000
+ * Current version code of EAx on the PlayStore, for the first uploaded beta (we cannot go below):
+ * ----1_001_000
+ * Current version code of EAx on the nightly:
+ * ----1_001_000
+ * Current version of Element Android (at some point EAx will replace this app) (v1.6.3)
+ * ----40_106_03a where a stands for the architecture: 1, 2, 3, 4 and 0 for the universal APK
+ * Current version of EAx distributed with Firebase app distribution:
+ * ----1_002_000
+ * Latest version of EAx distributed with Firebase app distribution (downgrading, so that's a problem)
+ * -------10_200
+ * Version when running the current debug build
+ * -------10_200
+ *
+ * So adding 4_000_000 to the current version Code computed here should be fine, and since the versionCode
+ * is multiplied by 10 in app/build.gradle.kts#L168:
+ * ```
+ * output.versionCode.set((output.versionCode.get() ?: 0) * 10 + abiCode))
+ * ```
+ * we will have:
+ * Release version:
+ * ---40_001_020
+ * Nightly version:
+ * ---40_001_020
+ * Debug version:
+ * ---40_010_200
+ */
 
+// Note: 2 digits max for each value
+private const val versionMajor = 0
+private const val versionMinor = 1
+
+// 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 = 2
+
+object Versions {
+    val versionCode = 4_000_000 + versionMajor * 1_00_00 + versionMinor * 1_00 + versionPatch
+    val versionName = "$versionMajor.$versionMinor.$versionPatch"
     const val compileSdk = 33
     const val targetSdk = 33
     const val minSdk = 23
diff --git a/plugins/src/main/kotlin/extension/DependencyHandleScope.kt b/plugins/src/main/kotlin/extension/DependencyHandleScope.kt
index 88f499b993..fb082e27a7 100644
--- a/plugins/src/main/kotlin/extension/DependencyHandleScope.kt
+++ b/plugins/src/main/kotlin/extension/DependencyHandleScope.kt
@@ -103,8 +103,12 @@ fun DependencyHandlerScope.allLibrariesImpl() {
 }
 
 fun DependencyHandlerScope.allServicesImpl() {
+    // For analytics configuration, either use noop, or use the impl, with at least one analyticsproviders implementation
+    // implementation(project(":services:analytics:noop"))
     implementation(project(":services:analytics:impl"))
     implementation(project(":services:analyticsproviders:posthog"))
+    implementation(project(":services:analyticsproviders:sentry"))
+
     implementation(project(":services:apperror:impl"))
     implementation(project(":services:appnavstate:impl"))
     implementation(project(":services:toolbox:impl"))
diff --git a/samples/minimal/src/main/kotlin/io/element/android/samples/minimal/MainActivity.kt b/samples/minimal/src/main/kotlin/io/element/android/samples/minimal/MainActivity.kt
index 21d6648a41..a915e70046 100644
--- a/samples/minimal/src/main/kotlin/io/element/android/samples/minimal/MainActivity.kt
+++ b/samples/minimal/src/main/kotlin/io/element/android/samples/minimal/MainActivity.kt
@@ -26,11 +26,12 @@ import androidx.compose.runtime.getValue
 import androidx.compose.ui.Modifier
 import androidx.compose.ui.platform.LocalContext
 import androidx.core.view.WindowCompat
-import io.element.android.libraries.theme.ElementTheme
 import io.element.android.libraries.matrix.api.auth.MatrixAuthenticationService
+import io.element.android.libraries.matrix.impl.RustMatrixClientFactory
 import io.element.android.libraries.matrix.impl.auth.RustMatrixAuthenticationService
 import io.element.android.libraries.network.useragent.SimpleUserAgentProvider
 import io.element.android.libraries.sessionstorage.impl.memory.InMemorySessionStore
+import io.element.android.libraries.theme.ElementTheme
 import io.element.android.services.toolbox.impl.systemclock.DefaultSystemClock
 import kotlinx.coroutines.runBlocking
 import java.io.File
@@ -39,15 +40,22 @@ class MainActivity : ComponentActivity() {
 
     private val matrixAuthenticationService: MatrixAuthenticationService by lazy {
         val baseDirectory = File(applicationContext.filesDir, "sessions")
-
+        val userAgentProvider = SimpleUserAgentProvider("MinimalSample")
+        val sessionStore = InMemorySessionStore()
         RustMatrixAuthenticationService(
-            context = applicationContext,
             baseDirectory = baseDirectory,
-            appCoroutineScope = Singleton.appScope,
             coroutineDispatchers = Singleton.coroutineDispatchers,
-            sessionStore = InMemorySessionStore(),
-            clock = DefaultSystemClock(),
-            userAgentProvider = SimpleUserAgentProvider("MinimalSample")
+            sessionStore = sessionStore,
+            userAgentProvider = userAgentProvider,
+            rustMatrixClientFactory = RustMatrixClientFactory(
+                context = applicationContext,
+                baseDirectory = baseDirectory,
+                appCoroutineScope = Singleton.appScope,
+                coroutineDispatchers = Singleton.coroutineDispatchers,
+                sessionStore = sessionStore,
+                userAgentProvider = userAgentProvider,
+                clock = DefaultSystemClock()
+            )
         )
     }
 
diff --git a/samples/minimal/src/main/kotlin/io/element/android/samples/minimal/RoomListScreen.kt b/samples/minimal/src/main/kotlin/io/element/android/samples/minimal/RoomListScreen.kt
index f66de878fb..faaccc9b8e 100644
--- a/samples/minimal/src/main/kotlin/io/element/android/samples/minimal/RoomListScreen.kt
+++ b/samples/minimal/src/main/kotlin/io/element/android/samples/minimal/RoomListScreen.kt
@@ -68,7 +68,7 @@ class RoomListScreen(
         inviteStateDataSource = DefaultInviteStateDataSource(matrixClient, DefaultSeenInvitesStore(context), coroutineDispatchers),
         leaveRoomPresenter = LeaveRoomPresenterImpl(matrixClient, RoomMembershipObserver(), coroutineDispatchers),
         roomListDataSource = RoomListDataSource(
-            roomSummaryDataSource = matrixClient.roomSummaryDataSource,
+            roomListService = matrixClient.roomListService,
             lastMessageTimestampFormatter = DefaultLastMessageTimestampFormatter(dateTimeProvider, dateFormatters),
             roomLastMessageFormatter = DefaultRoomLastMessageFormatter(
                 sp = stringProvider,
@@ -87,7 +87,6 @@ class RoomListScreen(
             Singleton.appScope.launch {
                 withContext(coroutineDispatchers.io) {
                     matrixClient.getRoom(roomId)!!.use { room ->
-                        room.open()
                         room.timeline.paginateBackwards(20, 50)
                     }
                 }
@@ -114,7 +113,9 @@ class RoomListScreen(
             }
             onDispose {
                 Timber.w("Stop sync!")
-                matrixClient.syncService().stopSync()
+                runBlocking {
+                    matrixClient.syncService().stopSync()
+                }
             }
         }
     }
diff --git a/samples/minimal/src/main/kotlin/io/element/android/samples/minimal/Singleton.kt b/samples/minimal/src/main/kotlin/io/element/android/samples/minimal/Singleton.kt
index 5f8c6555a5..027da552fa 100644
--- a/samples/minimal/src/main/kotlin/io/element/android/samples/minimal/Singleton.kt
+++ b/samples/minimal/src/main/kotlin/io/element/android/samples/minimal/Singleton.kt
@@ -17,19 +17,41 @@
 package io.element.android.samples.minimal
 
 import io.element.android.libraries.core.coroutine.CoroutineDispatchers
-import io.element.android.libraries.matrix.impl.tracing.setupTracing
-import io.element.android.libraries.matrix.api.tracing.TracingConfigurations
+import io.element.android.libraries.core.meta.BuildMeta
+import io.element.android.libraries.core.meta.BuildType
+import io.element.android.libraries.matrix.api.tracing.TracingConfiguration
+import io.element.android.libraries.matrix.api.tracing.TracingFilterConfigurations
+import io.element.android.libraries.matrix.api.tracing.WriteToFilesConfiguration
+import io.element.android.libraries.matrix.impl.tracing.RustTracingService
 import kotlinx.coroutines.CoroutineName
 import kotlinx.coroutines.Dispatchers
 import kotlinx.coroutines.MainScope
 import kotlinx.coroutines.plus
-import timber.log.Timber
 
 object Singleton {
 
+    private val buildMeta = BuildMeta(
+        isDebuggable = true,
+        buildType = BuildType.DEBUG,
+        applicationName = "EAX-Minimal",
+        applicationId = "io.element.android.samples.minimal",
+        lowPrivacyLoggingEnabled = false,
+        versionName = "0.1.0",
+        versionCode = 1,
+        gitRevision = "TODO", // BuildConfig.GIT_REVISION,
+        gitRevisionDate = "TODO", //  BuildConfig.GIT_REVISION_DATE,
+        gitBranchName = "TODO", //  BuildConfig.GIT_BRANCH_NAME,
+        flavorDescription = "TODO", //  BuildConfig.FLAVOR_DESCRIPTION,
+        flavorShortDescription = "TODO", //  BuildConfig.SHORT_FLAVOR_DESCRIPTION,
+    )
+
     init {
-        Timber.plant(Timber.DebugTree())
-        setupTracing(TracingConfigurations.debug)
+        val tracingConfiguration = TracingConfiguration(
+            filterConfiguration = TracingFilterConfigurations.debug,
+            writesToLogcat = true,
+            writesToFilesConfiguration = WriteToFilesConfiguration.Disabled
+        )
+        RustTracingService(buildMeta).setupTracing(tracingConfiguration)
     }
 
     val appScope = MainScope() + CoroutineName("Minimal Scope")
diff --git a/services/analytics/api/src/main/kotlin/io/element/android/services/analytics/api/AnalyticsService.kt b/services/analytics/api/src/main/kotlin/io/element/android/services/analytics/api/AnalyticsService.kt
index 9c6fb2d522..309a885ad2 100644
--- a/services/analytics/api/src/main/kotlin/io/element/android/services/analytics/api/AnalyticsService.kt
+++ b/services/analytics/api/src/main/kotlin/io/element/android/services/analytics/api/AnalyticsService.kt
@@ -22,7 +22,10 @@ import io.element.android.services.analyticsproviders.api.trackers.ErrorTracker
 import kotlinx.coroutines.flow.Flow
 
 interface AnalyticsService: AnalyticsTracker, ErrorTracker {
-    fun getAvailableAnalyticsProviders(): List
+    /**
+     * Get the available analytics providers.
+     */
+    fun getAvailableAnalyticsProviders(): Set
 
     /**
      * Return a Flow of Boolean, true if the user has given their consent.
diff --git a/services/analytics/impl/src/main/kotlin/io/element/android/services/analytics/impl/DefaultAnalyticsService.kt b/services/analytics/impl/src/main/kotlin/io/element/android/services/analytics/impl/DefaultAnalyticsService.kt
index 5639f954ac..42acd29b56 100644
--- a/services/analytics/impl/src/main/kotlin/io/element/android/services/analytics/impl/DefaultAnalyticsService.kt
+++ b/services/analytics/impl/src/main/kotlin/io/element/android/services/analytics/impl/DefaultAnalyticsService.kt
@@ -56,8 +56,8 @@ class DefaultAnalyticsService @Inject constructor(
         observeSessions()
     }
 
-    override fun getAvailableAnalyticsProviders(): List {
-        return analyticsProviders.sortedBy { it.index }
+    override fun getAvailableAnalyticsProviders(): Set {
+        return analyticsProviders
     }
 
     override fun getUserConsent(): Flow {
diff --git a/services/analytics/noop/build.gradle.kts b/services/analytics/noop/build.gradle.kts
index a5678f5cb3..000434a05c 100644
--- a/services/analytics/noop/build.gradle.kts
+++ b/services/analytics/noop/build.gradle.kts
@@ -19,7 +19,7 @@ plugins {
 }
 
 android {
-    namespace = "io.element.android.services.analytics.impl"
+    namespace = "io.element.android.services.analytics.noop"
 }
 
 anvil {
@@ -28,6 +28,7 @@ anvil {
 
 dependencies {
     implementation(libs.dagger)
+    implementation(projects.libraries.architecture)
     implementation(projects.libraries.di)
     api(projects.services.analytics.api)
 }
diff --git a/services/analytics/noop/src/main/kotlin/io/element/android/services/analytics/noop/NoopAnalyticsService.kt b/services/analytics/noop/src/main/kotlin/io/element/android/services/analytics/noop/NoopAnalyticsService.kt
new file mode 100644
index 0000000000..f82e7ff550
--- /dev/null
+++ b/services/analytics/noop/src/main/kotlin/io/element/android/services/analytics/noop/NoopAnalyticsService.kt
@@ -0,0 +1,48 @@
+/*
+ * Copyright (c) 2023 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
+ *
+ *     http://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.services.analytics.noop
+
+import com.squareup.anvil.annotations.ContributesBinding
+import im.vector.app.features.analytics.itf.VectorAnalyticsEvent
+import im.vector.app.features.analytics.itf.VectorAnalyticsScreen
+import im.vector.app.features.analytics.plan.UserProperties
+import io.element.android.libraries.di.AppScope
+import io.element.android.libraries.di.SingleIn
+import io.element.android.services.analytics.api.AnalyticsService
+import io.element.android.services.analyticsproviders.api.AnalyticsProvider
+import kotlinx.coroutines.flow.Flow
+import kotlinx.coroutines.flow.flowOf
+import javax.inject.Inject
+
+@SingleIn(AppScope::class)
+@ContributesBinding(AppScope::class)
+class NoopAnalyticsService @Inject constructor(
+) : AnalyticsService {
+    override fun getAvailableAnalyticsProviders(): Set = emptySet()
+    override fun getUserConsent(): Flow = flowOf(false)
+    override suspend fun setUserConsent(userConsent: Boolean) = Unit
+    override fun didAskUserConsent(): Flow = flowOf(true)
+    override suspend fun setDidAskUserConsent() = Unit
+    override fun getAnalyticsId(): Flow = flowOf("")
+    override suspend fun setAnalyticsId(analyticsId: String) = Unit
+    override suspend fun onSignOut() = Unit
+    override suspend fun reset() = Unit
+    override fun capture(event: VectorAnalyticsEvent) = Unit
+    override fun screen(screen: VectorAnalyticsScreen) = Unit
+    override fun updateUserProperties(userProperties: UserProperties) = Unit
+    override fun trackError(throwable: Throwable) = Unit
+}
diff --git a/services/analyticsproviders/api/src/main/kotlin/io/element/android/services/analyticsproviders/api/AnalyticsProvider.kt b/services/analyticsproviders/api/src/main/kotlin/io/element/android/services/analyticsproviders/api/AnalyticsProvider.kt
index 548f47d7ad..807c8d1413 100644
--- a/services/analyticsproviders/api/src/main/kotlin/io/element/android/services/analyticsproviders/api/AnalyticsProvider.kt
+++ b/services/analyticsproviders/api/src/main/kotlin/io/element/android/services/analyticsproviders/api/AnalyticsProvider.kt
@@ -20,11 +20,6 @@ import io.element.android.services.analyticsproviders.api.trackers.AnalyticsTrac
 import io.element.android.services.analyticsproviders.api.trackers.ErrorTracker
 
 interface AnalyticsProvider: AnalyticsTracker, ErrorTracker {
-    /**
-     * Allow to sort providers, from lower index to higher index.
-     */
-    val index: Int
-
     /**
      * User friendly name.
      */
diff --git a/services/analyticsproviders/posthog/src/main/kotlin/io/element/android/services/analyticsproviders/posthog/PosthogAnalyticsProvider.kt b/services/analyticsproviders/posthog/src/main/kotlin/io/element/android/services/analyticsproviders/posthog/PosthogAnalyticsProvider.kt
index 92e73195c0..fb2e341e1e 100644
--- a/services/analyticsproviders/posthog/src/main/kotlin/io/element/android/services/analyticsproviders/posthog/PosthogAnalyticsProvider.kt
+++ b/services/analyticsproviders/posthog/src/main/kotlin/io/element/android/services/analyticsproviders/posthog/PosthogAnalyticsProvider.kt
@@ -16,7 +16,6 @@
 
 package io.element.android.services.analyticsproviders.posthog
 
-import com.posthog.android.Options
 import com.posthog.android.PostHog
 import com.posthog.android.Properties
 import com.squareup.anvil.annotations.ContributesMultibinding
@@ -29,14 +28,13 @@ import io.element.android.services.analyticsproviders.posthog.log.analyticsTag
 import timber.log.Timber
 import javax.inject.Inject
 
-private val REUSE_EXISTING_ID: String? = null
-private val IGNORED_OPTIONS: Options? = null
+// private val REUSE_EXISTING_ID: String? = null
+// private val IGNORED_OPTIONS: Options? = null
 
 @ContributesMultibinding(AppScope::class)
 class PosthogAnalyticsProvider @Inject constructor(
     private val postHogFactory: PostHogFactory,
 ) : AnalyticsProvider {
-    override val index = PosthogConfig.index
     override val name = PosthogConfig.name
 
     private var posthog: PostHog? = null
@@ -101,9 +99,11 @@ class PosthogAnalyticsProvider @Inject constructor(
      * We avoid sending nulls as part of the UserProperties as this will reset the values across all devices.
      * The UserProperties event has nullable properties to allow for clients to opt in.
      */
+    /*
     private fun Map.toPostHogUserProperties(): Properties {
         return Properties().apply {
             putAll(this@toPostHogUserProperties.filter { it.value != null })
         }
     }
+     */
 }
diff --git a/services/analyticsproviders/posthog/src/main/kotlin/io/element/android/services/analyticsproviders/posthog/PosthogConfig.kt b/services/analyticsproviders/posthog/src/main/kotlin/io/element/android/services/analyticsproviders/posthog/PosthogConfig.kt
index 877fb7dc9a..96d8659b11 100644
--- a/services/analyticsproviders/posthog/src/main/kotlin/io/element/android/services/analyticsproviders/posthog/PosthogConfig.kt
+++ b/services/analyticsproviders/posthog/src/main/kotlin/io/element/android/services/analyticsproviders/posthog/PosthogConfig.kt
@@ -17,7 +17,6 @@
 package io.element.android.services.analyticsproviders.posthog
 
 object PosthogConfig {
-    const val index = 0
     const val name = "Posthog"
     const val postHogHost = "https://posthog.element.dev"
     const val postHogApiKey = "phc_VtA1L35nw3aeAtHIx1ayrGdzGkss7k1xINeXcoIQzXN"
diff --git a/services/analyticsproviders/posthog/src/main/kotlin/io/element/android/services/analyticsproviders/posthog/log/AnalyticsLoggerTag.kt b/services/analyticsproviders/posthog/src/main/kotlin/io/element/android/services/analyticsproviders/posthog/log/AnalyticsLoggerTag.kt
index 8e64ca100d..a298bda1c5 100644
--- a/services/analyticsproviders/posthog/src/main/kotlin/io/element/android/services/analyticsproviders/posthog/log/AnalyticsLoggerTag.kt
+++ b/services/analyticsproviders/posthog/src/main/kotlin/io/element/android/services/analyticsproviders/posthog/log/AnalyticsLoggerTag.kt
@@ -18,4 +18,4 @@ package io.element.android.services.analyticsproviders.posthog.log
 
 import io.element.android.libraries.core.log.logger.LoggerTag
 
-val analyticsTag = LoggerTag("Analytics")
+internal val analyticsTag = LoggerTag("Posthog")
diff --git a/services/analyticsproviders/sentry/build.gradle.kts b/services/analyticsproviders/sentry/build.gradle.kts
new file mode 100644
index 0000000000..34c444eb7d
--- /dev/null
+++ b/services/analyticsproviders/sentry/build.gradle.kts
@@ -0,0 +1,35 @@
+/*
+ * Copyright (c) 2023 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
+ *
+ *     http://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.
+ */
+plugins {
+    id("io.element.android-library")
+    alias(libs.plugins.anvil)
+}
+
+android {
+    namespace = "io.element.android.services.analyticsproviders.sentry"
+}
+
+anvil {
+    generateDaggerFactories.set(true)
+}
+
+dependencies {
+    implementation(libs.dagger)
+    implementation(libs.sentry)
+    implementation(projects.libraries.core)
+    implementation(projects.libraries.di)
+    implementation(projects.services.analyticsproviders.api)
+}
diff --git a/libraries/push/impl/src/main/res/values/dimens.xml b/services/analyticsproviders/sentry/src/main/AndroidManifest.xml
similarity index 70%
rename from libraries/push/impl/src/main/res/values/dimens.xml
rename to services/analyticsproviders/sentry/src/main/AndroidManifest.xml
index ce2fee2015..079912fc00 100644
--- a/libraries/push/impl/src/main/res/values/dimens.xml
+++ b/services/analyticsproviders/sentry/src/main/AndroidManifest.xml
@@ -14,8 +14,13 @@
   ~ limitations under the License.
   -->
 
-
+
 
-    50dp
+    
+        
+        
+    
 
-
+
diff --git a/services/analyticsproviders/sentry/src/main/kotlin/io/element/android/services/analyticsproviders/sentry/SentryAnalyticsProvider.kt b/services/analyticsproviders/sentry/src/main/kotlin/io/element/android/services/analyticsproviders/sentry/SentryAnalyticsProvider.kt
new file mode 100644
index 0000000000..6bc4df426f
--- /dev/null
+++ b/services/analyticsproviders/sentry/src/main/kotlin/io/element/android/services/analyticsproviders/sentry/SentryAnalyticsProvider.kt
@@ -0,0 +1,79 @@
+/*
+ * Copyright (c) 2023 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
+ *
+ *     http://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.services.analyticsproviders.sentry
+
+import android.content.Context
+import com.squareup.anvil.annotations.ContributesMultibinding
+import im.vector.app.features.analytics.itf.VectorAnalyticsEvent
+import im.vector.app.features.analytics.itf.VectorAnalyticsScreen
+import im.vector.app.features.analytics.plan.UserProperties
+import io.element.android.libraries.core.meta.BuildMeta
+import io.element.android.libraries.core.meta.BuildType
+import io.element.android.libraries.di.AppScope
+import io.element.android.libraries.di.ApplicationContext
+import io.element.android.services.analyticsproviders.api.AnalyticsProvider
+import io.element.android.services.analyticsproviders.sentry.log.analyticsTag
+import io.sentry.Sentry
+import io.sentry.SentryOptions
+import io.sentry.android.core.SentryAndroid
+import timber.log.Timber
+import javax.inject.Inject
+
+@ContributesMultibinding(AppScope::class)
+class SentryAnalyticsProvider @Inject constructor(
+    @ApplicationContext private val context: Context,
+    private val buildMeta: BuildMeta,
+) : AnalyticsProvider {
+    override val name = SentryConfig.name
+
+    override fun init() {
+        Timber.tag(analyticsTag.value).d("Initializing Sentry")
+        if (Sentry.isEnabled()) return
+        SentryAndroid.init(context) { options ->
+            options.dsn = SentryConfig.dns
+            options.beforeSend = SentryOptions.BeforeSendCallback { event, _ -> event }
+            options.tracesSampleRate = 1.0
+            options.isEnableUserInteractionTracing = true
+            options.environment = buildMeta.buildType.toSentryEnv()
+            options.diagnosticLevel
+        }
+    }
+
+    override fun stop() {
+        Timber.tag(analyticsTag.value).d("Stopping Sentry")
+        Sentry.close()
+    }
+
+    override fun capture(event: VectorAnalyticsEvent) {
+    }
+
+    override fun screen(screen: VectorAnalyticsScreen) {
+    }
+
+    override fun updateUserProperties(userProperties: UserProperties) {
+    }
+
+    override fun trackError(throwable: Throwable) {
+        Sentry.captureException(throwable)
+    }
+}
+
+private fun BuildType.toSentryEnv() = when (this) {
+    BuildType.RELEASE -> SentryConfig.envRelease
+    BuildType.NIGHTLY,
+    BuildType.DEBUG -> SentryConfig.envDebug
+}
diff --git a/services/analyticsproviders/sentry/src/main/kotlin/io/element/android/services/analyticsproviders/sentry/SentryConfig.kt b/services/analyticsproviders/sentry/src/main/kotlin/io/element/android/services/analyticsproviders/sentry/SentryConfig.kt
new file mode 100644
index 0000000000..f2048b59f0
--- /dev/null
+++ b/services/analyticsproviders/sentry/src/main/kotlin/io/element/android/services/analyticsproviders/sentry/SentryConfig.kt
@@ -0,0 +1,24 @@
+/*
+ * Copyright (c) 2023 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
+ *
+ *     http://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.services.analyticsproviders.sentry
+
+object SentryConfig {
+    const val name = "Sentry"
+    const val dns = "https://32f7ff6a6e724f90838b7654042b2e81@sentry.tools.element.io/59"
+    const val envDebug = "DEBUG"
+    const val envRelease = "RELEASE"
+}
diff --git a/services/analyticsproviders/sentry/src/main/kotlin/io/element/android/services/analyticsproviders/sentry/log/AnalyticsLoggerTag.kt b/services/analyticsproviders/sentry/src/main/kotlin/io/element/android/services/analyticsproviders/sentry/log/AnalyticsLoggerTag.kt
new file mode 100644
index 0000000000..f792009ee4
--- /dev/null
+++ b/services/analyticsproviders/sentry/src/main/kotlin/io/element/android/services/analyticsproviders/sentry/log/AnalyticsLoggerTag.kt
@@ -0,0 +1,21 @@
+/*
+ * Copyright (c) 2023 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
+ *
+ *     http://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.services.analyticsproviders.sentry.log
+
+import io.element.android.libraries.core.log.logger.LoggerTag
+
+internal val analyticsTag = LoggerTag("Sentry")
diff --git a/settings.gradle.kts b/settings.gradle.kts
index 408c9e2934..751c65d388 100644
--- a/settings.gradle.kts
+++ b/settings.gradle.kts
@@ -36,6 +36,10 @@ dependencyResolutionManagement {
                 includeModule("com.github.matrix-org", "matrix-analytics-events")
             }
         }
+        // To have immediate access to Rust SDK versions
+        maven {
+            url = URI("https://s01.oss.sonatype.org/content/repositories/releases")
+        }
         flatDir {
             dirs("libraries/matrix/libs")
         }
diff --git a/tests/testutils/build.gradle.kts b/tests/testutils/build.gradle.kts
index d7c17c7895..184bbc418a 100644
--- a/tests/testutils/build.gradle.kts
+++ b/tests/testutils/build.gradle.kts
@@ -30,4 +30,5 @@ dependencies {
     implementation(libs.test.junit)
     implementation(libs.coroutines.test)
     implementation(projects.libraries.core)
+    implementation(libs.test.turbine)
 }
diff --git a/tests/testutils/src/main/kotlin/io/element/android/tests/testutils/ReceiveTurbine.kt b/tests/testutils/src/main/kotlin/io/element/android/tests/testutils/ReceiveTurbine.kt
new file mode 100644
index 0000000000..06b6b3d3ea
--- /dev/null
+++ b/tests/testutils/src/main/kotlin/io/element/android/tests/testutils/ReceiveTurbine.kt
@@ -0,0 +1,60 @@
+/*
+ * Copyright (c) 2023 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
+ *
+ *     http://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.tests.testutils
+
+import app.cash.turbine.Event
+import app.cash.turbine.ReceiveTurbine
+import app.cash.turbine.withTurbineTimeout
+import io.element.android.libraries.core.data.tryOrNull
+import kotlin.time.Duration
+import kotlin.time.Duration.Companion.milliseconds
+
+/**
+ * Consume all items until timeout is reached waiting for an event or we receive terminal event.
+ * The timeout is applied for each event.
+ * @return the list of consumed items.
+ */
+suspend fun  ReceiveTurbine.consumeItemsUntilTimeout(timeout: Duration = 100.milliseconds): List {
+    return consumeItemsUntilPredicate(timeout) { false }
+}
+
+/**
+ * Consume items until predicate is true, or timeout is reached waiting for an event, or we receive terminal event.
+ * The timeout is applied for each event.
+ * @return the list of consumed items.
+ */
+suspend fun  ReceiveTurbine.consumeItemsUntilPredicate(
+    timeout: Duration = 100.milliseconds,
+    predicate: (T) -> Boolean,
+): List {
+    val items = ArrayList()
+    tryOrNull {
+        var foundItemOrFinished = false
+        while (!foundItemOrFinished) {
+            when (val event = withTurbineTimeout(timeout) { awaitEvent() }) {
+                is Event.Item -> {
+                    items.add(event.value)
+                    if (predicate(event.value)) {
+                        foundItemOrFinished = true
+                    }
+                }
+                Event.Complete, is Event.Error -> foundItemOrFinished = true
+            }
+        }
+    }
+    return items
+}
diff --git a/tests/uitests/build.gradle.kts b/tests/uitests/build.gradle.kts
index 729899c4f8..1881822691 100644
--- a/tests/uitests/build.gradle.kts
+++ b/tests/uitests/build.gradle.kts
@@ -42,7 +42,6 @@ dependencies {
     testImplementation(libs.test.junit)
     testImplementation(libs.test.parameter.injector)
     testImplementation(projects.libraries.designsystem)
-    androidTestImplementation(libs.test.junitext)
     ksp(libs.showkase.processor)
     kspTest(libs.showkase.processor)
 
diff --git a/tests/uitests/src/main/kotlin/io/element/android/tests/uitests/ShowkaseNavigation.kt b/tests/uitests/src/main/kotlin/io/element/android/tests/uitests/ShowkaseNavigation.kt
index 8a33430340..cb7795c05a 100644
--- a/tests/uitests/src/main/kotlin/io/element/android/tests/uitests/ShowkaseNavigation.kt
+++ b/tests/uitests/src/main/kotlin/io/element/android/tests/uitests/ShowkaseNavigation.kt
@@ -18,7 +18,6 @@ package io.element.android.tests.uitests
 
 import android.app.Activity
 import android.content.Intent
-import com.airbnb.android.showkase.models.Showkase
 import com.airbnb.android.showkase.ui.ShowkaseBrowserActivity
 
 fun openShowkase(activity: Activity) {
diff --git a/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.appnav.room_null_DefaultGroup_LoadingRoomNodeViewDarkPreview_0_null_0,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.appnav.room_null_DefaultGroup_LoadingRoomNodeViewDarkPreview_0_null_0,NEXUS_5,1.0,en].png
index 7870560dd4..500f0a57f7 100644
--- a/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.appnav.room_null_DefaultGroup_LoadingRoomNodeViewDarkPreview_0_null_0,NEXUS_5,1.0,en].png
+++ b/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.appnav.room_null_DefaultGroup_LoadingRoomNodeViewDarkPreview_0_null_0,NEXUS_5,1.0,en].png
@@ -1,3 +1,3 @@
 version https://git-lfs.github.com/spec/v1
-oid sha256:da4188dc606f0735fd4093acad34897c866d8c4d20b3e0ec0618685f7302cbf5
-size 9288
+oid sha256:3f18e74bfbebd69109f36a7154b20d3ee61071bff0d8ebf28f4b3b35c58e2938
+size 9256
diff --git a/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.appnav.room_null_DefaultGroup_LoadingRoomNodeViewDarkPreview_0_null_1,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.appnav.room_null_DefaultGroup_LoadingRoomNodeViewDarkPreview_0_null_1,NEXUS_5,1.0,en].png
index 7edd6f9ee7..17ed1eee99 100644
--- a/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.appnav.room_null_DefaultGroup_LoadingRoomNodeViewDarkPreview_0_null_1,NEXUS_5,1.0,en].png
+++ b/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.appnav.room_null_DefaultGroup_LoadingRoomNodeViewDarkPreview_0_null_1,NEXUS_5,1.0,en].png
@@ -1,3 +1,3 @@
 version https://git-lfs.github.com/spec/v1
-oid sha256:e27b1ea7bfa4eb97af3c2d433fbe3f5ca21458e4458d91b39c9c2bb3d7b02abc
-size 11306
+oid sha256:eea203b9527f7c3dc3692e7db3e9d5cee20ca08fddf04977c948933dc2784022
+size 11274
diff --git a/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.appnav.room_null_DefaultGroup_LoadingRoomNodeViewLightPreview_0_null_0,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.appnav.room_null_DefaultGroup_LoadingRoomNodeViewLightPreview_0_null_0,NEXUS_5,1.0,en].png
index c87156e8c6..3bbf79781a 100644
--- a/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.appnav.room_null_DefaultGroup_LoadingRoomNodeViewLightPreview_0_null_0,NEXUS_5,1.0,en].png
+++ b/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.appnav.room_null_DefaultGroup_LoadingRoomNodeViewLightPreview_0_null_0,NEXUS_5,1.0,en].png
@@ -1,3 +1,3 @@
 version https://git-lfs.github.com/spec/v1
-oid sha256:2bbeb21faf320226f42aad179b955952ad8e4b5d5645c45bfbbc02166baf0662
-size 9641
+oid sha256:b5c69ae7d27eb7024e9a2f9c7100b308562ef2fc702e28604098180cb02a3813
+size 9645
diff --git a/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.appnav.room_null_DefaultGroup_LoadingRoomNodeViewLightPreview_0_null_1,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.appnav.room_null_DefaultGroup_LoadingRoomNodeViewLightPreview_0_null_1,NEXUS_5,1.0,en].png
index 6391f1dec0..1b135effbf 100644
--- a/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.appnav.room_null_DefaultGroup_LoadingRoomNodeViewLightPreview_0_null_1,NEXUS_5,1.0,en].png
+++ b/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.appnav.room_null_DefaultGroup_LoadingRoomNodeViewLightPreview_0_null_1,NEXUS_5,1.0,en].png
@@ -1,3 +1,3 @@
 version https://git-lfs.github.com/spec/v1
-oid sha256:499e17b52d57f8b0d8984e32457b3922c0647be5b835c02a01ed927fe004ec4d
-size 11610
+oid sha256:62149a4d9b0dd62ddb56e1cdb24fe401f189fda05d17dd16f8c0bc511eab6561
+size 11616
diff --git a/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.appnav.root_null_DefaultGroup_RootDarkPreview_0_null_0,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.appnav.root_null_DefaultGroup_RootDarkPreview_0_null_0,NEXUS_5,1.0,en].png
index a4d544ce2d..d4098db0e0 100644
--- a/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.appnav.root_null_DefaultGroup_RootDarkPreview_0_null_0,NEXUS_5,1.0,en].png
+++ b/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.appnav.root_null_DefaultGroup_RootDarkPreview_0_null_0,NEXUS_5,1.0,en].png
@@ -1,3 +1,3 @@
 version https://git-lfs.github.com/spec/v1
-oid sha256:c51726746993ad3ed0f6da9fe49a02b87ec518495e04f6cdb28ab4454dc72938
-size 25457
+oid sha256:862bbfc81d7c4ccc16e6d8d1db4f81306c0219b45b3630cd2f73dcabf0550b3b
+size 26007
diff --git a/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.appnav.root_null_DefaultGroup_RootDarkPreview_0_null_1,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.appnav.root_null_DefaultGroup_RootDarkPreview_0_null_1,NEXUS_5,1.0,en].png
index c5627b9105..9c873827d1 100644
--- a/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.appnav.root_null_DefaultGroup_RootDarkPreview_0_null_1,NEXUS_5,1.0,en].png
+++ b/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.appnav.root_null_DefaultGroup_RootDarkPreview_0_null_1,NEXUS_5,1.0,en].png
@@ -1,3 +1,3 @@
 version https://git-lfs.github.com/spec/v1
-oid sha256:14ffd433679cbadf1bb325257786a834fce3e362d2ed763c1823b0c958c0f38a
-size 27496
+oid sha256:32f331dd755437c67fd5251e3034b63d1e099f1032043b86b6f6f989680e390f
+size 28184
diff --git a/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.appnav.root_null_DefaultGroup_RootDarkPreview_0_null_2,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.appnav.root_null_DefaultGroup_RootDarkPreview_0_null_2,NEXUS_5,1.0,en].png
index c4f2de8348..f92d333a61 100644
--- a/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.appnav.root_null_DefaultGroup_RootDarkPreview_0_null_2,NEXUS_5,1.0,en].png
+++ b/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.appnav.root_null_DefaultGroup_RootDarkPreview_0_null_2,NEXUS_5,1.0,en].png
@@ -1,3 +1,3 @@
 version https://git-lfs.github.com/spec/v1
-oid sha256:85d3ea85f270fae4db7e14ab9c2c19a6c4f3a68e1c2112010471cb69cdb71b2b
-size 22071
+oid sha256:250a6ae8cb93c781d570c40054f34b21832434f9a692adf637cf9e2560c6a09e
+size 21538
diff --git a/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.appnav.root_null_DefaultGroup_RootLightPreview_0_null_0,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.appnav.root_null_DefaultGroup_RootLightPreview_0_null_0,NEXUS_5,1.0,en].png
index 1aecdf6d10..735efd3e6c 100644
--- a/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.appnav.root_null_DefaultGroup_RootLightPreview_0_null_0,NEXUS_5,1.0,en].png
+++ b/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.appnav.root_null_DefaultGroup_RootLightPreview_0_null_0,NEXUS_5,1.0,en].png
@@ -1,3 +1,3 @@
 version https://git-lfs.github.com/spec/v1
-oid sha256:fd79483dea8ce19284069511ec96dfc68704a9ff2f1a33be312bbcdb387123c6
-size 26655
+oid sha256:087d4e2355b7b64f930c8e4c149f565b77304ba0f62fc16ce0ff99696dc51b5e
+size 27966
diff --git a/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.appnav.root_null_DefaultGroup_RootLightPreview_0_null_1,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.appnav.root_null_DefaultGroup_RootLightPreview_0_null_1,NEXUS_5,1.0,en].png
index 192e7b90a4..0c885e9c4d 100644
--- a/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.appnav.root_null_DefaultGroup_RootLightPreview_0_null_1,NEXUS_5,1.0,en].png
+++ b/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.appnav.root_null_DefaultGroup_RootLightPreview_0_null_1,NEXUS_5,1.0,en].png
@@ -1,3 +1,3 @@
 version https://git-lfs.github.com/spec/v1
-oid sha256:931423fea194fb1bede5cb3d73083fb65335716ca088fbda707f4f4727eae4dd
-size 28757
+oid sha256:702d61eabe690c6b7a259d3773ed7e25011b0a8a99c7a1109930c2ea78b234a2
+size 30106
diff --git a/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.appnav.root_null_DefaultGroup_RootLightPreview_0_null_2,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.appnav.root_null_DefaultGroup_RootLightPreview_0_null_2,NEXUS_5,1.0,en].png
index 7ae3d51e4a..05d952ea66 100644
--- a/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.appnav.root_null_DefaultGroup_RootLightPreview_0_null_2,NEXUS_5,1.0,en].png
+++ b/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.appnav.root_null_DefaultGroup_RootLightPreview_0_null_2,NEXUS_5,1.0,en].png
@@ -1,3 +1,3 @@
 version https://git-lfs.github.com/spec/v1
-oid sha256:bfa6e3d8698a2327d6e3cc14318856f221355581e6c661b92d2e215daf8f30cd
-size 22879
+oid sha256:85b0c428cf44532739245c8303cc2c86ab5e0c6ffc060871f1eef8e1bce9955b
+size 23123
diff --git a/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.analytics.impl_null_DefaultGroup_AnalyticsOptInViewDarkPreview_0_null_0,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.analytics.impl_null_DefaultGroup_AnalyticsOptInViewDarkPreview_0_null_0,NEXUS_5,1.0,en].png
index 02064ef869..482d85290c 100644
--- a/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.analytics.impl_null_DefaultGroup_AnalyticsOptInViewDarkPreview_0_null_0,NEXUS_5,1.0,en].png
+++ b/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.analytics.impl_null_DefaultGroup_AnalyticsOptInViewDarkPreview_0_null_0,NEXUS_5,1.0,en].png
@@ -1,3 +1,3 @@
 version https://git-lfs.github.com/spec/v1
-oid sha256:434f7619fb6bd337ede775fc343acc05950907987523acbd0f578624e5d26857
-size 49246
+oid sha256:5fd66b90f0566317a48565be56e75496a7b156fc96354ea61a0cc0a7f036625a
+size 49329
diff --git a/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.analytics.impl_null_DefaultGroup_AnalyticsOptInViewLightPreview_0_null_0,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.analytics.impl_null_DefaultGroup_AnalyticsOptInViewLightPreview_0_null_0,NEXUS_5,1.0,en].png
index 293c11b5c8..9dc5bdf600 100644
--- a/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.analytics.impl_null_DefaultGroup_AnalyticsOptInViewLightPreview_0_null_0,NEXUS_5,1.0,en].png
+++ b/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.analytics.impl_null_DefaultGroup_AnalyticsOptInViewLightPreview_0_null_0,NEXUS_5,1.0,en].png
@@ -1,3 +1,3 @@
 version https://git-lfs.github.com/spec/v1
-oid sha256:93036a30e1af96805c20ea5d65b6d3eb40d2ee11f8f3420436e936dd5b4ca38b
-size 50201
+oid sha256:5b6dc784e88a7c9ef9d5812ee474e8cbc5cafc55dfd21adeb15d3ace99a41db0
+size 50340
diff --git a/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.createroom.impl.addpeople_null_DefaultGroup_AddPeopleViewDarkPreview_0_null_0,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.createroom.impl.addpeople_null_DefaultGroup_AddPeopleViewDarkPreview_0_null_0,NEXUS_5,1.0,en].png
index 772474c81f..bdd263e811 100644
--- a/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.createroom.impl.addpeople_null_DefaultGroup_AddPeopleViewDarkPreview_0_null_0,NEXUS_5,1.0,en].png
+++ b/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.createroom.impl.addpeople_null_DefaultGroup_AddPeopleViewDarkPreview_0_null_0,NEXUS_5,1.0,en].png
@@ -1,3 +1,3 @@
 version https://git-lfs.github.com/spec/v1
-oid sha256:92fda75e246b46ab786da2f54f920bf96959618ac20cece5f6ca754f7fcf6914
-size 14161
+oid sha256:7e62ff59a909d9fc8c255236756a6f7f9d7efbb85e222de92843251367e2f774
+size 14150
diff --git a/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.createroom.impl.addpeople_null_DefaultGroup_AddPeopleViewDarkPreview_0_null_1,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.createroom.impl.addpeople_null_DefaultGroup_AddPeopleViewDarkPreview_0_null_1,NEXUS_5,1.0,en].png
index b88f3011ca..7961ed97ba 100644
--- a/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.createroom.impl.addpeople_null_DefaultGroup_AddPeopleViewDarkPreview_0_null_1,NEXUS_5,1.0,en].png
+++ b/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.createroom.impl.addpeople_null_DefaultGroup_AddPeopleViewDarkPreview_0_null_1,NEXUS_5,1.0,en].png
@@ -1,3 +1,3 @@
 version https://git-lfs.github.com/spec/v1
-oid sha256:a2a005b84bbf1be15028d36e153e79eb5acbe41e65e3f274a6d78b22be95efb5
-size 28509
+oid sha256:a3b008e2364af89731ba0431b7a97998452aa4d0ab7b25cb3d5130737b017a9e
+size 28525
diff --git a/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.createroom.impl.addpeople_null_DefaultGroup_AddPeopleViewLightPreview_0_null_0,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.createroom.impl.addpeople_null_DefaultGroup_AddPeopleViewLightPreview_0_null_0,NEXUS_5,1.0,en].png
index 7cfc3e1c03..4cfb07c3ec 100644
--- a/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.createroom.impl.addpeople_null_DefaultGroup_AddPeopleViewLightPreview_0_null_0,NEXUS_5,1.0,en].png
+++ b/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.createroom.impl.addpeople_null_DefaultGroup_AddPeopleViewLightPreview_0_null_0,NEXUS_5,1.0,en].png
@@ -1,3 +1,3 @@
 version https://git-lfs.github.com/spec/v1
-oid sha256:6bb2d3d6e83f5b0ca17809c415e636bf5dbfa846259e8fabd6c3afae37d7d1f9
-size 15231
+oid sha256:92a09f9c5915b444e92853809d6d42b0b2b76152f9fa58a1ac9856b15ee15373
+size 15222
diff --git a/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.createroom.impl.addpeople_null_DefaultGroup_AddPeopleViewLightPreview_0_null_1,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.createroom.impl.addpeople_null_DefaultGroup_AddPeopleViewLightPreview_0_null_1,NEXUS_5,1.0,en].png
index 965959b5ee..5ada26de58 100644
--- a/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.createroom.impl.addpeople_null_DefaultGroup_AddPeopleViewLightPreview_0_null_1,NEXUS_5,1.0,en].png
+++ b/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.createroom.impl.addpeople_null_DefaultGroup_AddPeopleViewLightPreview_0_null_1,NEXUS_5,1.0,en].png
@@ -1,3 +1,3 @@
 version https://git-lfs.github.com/spec/v1
-oid sha256:d3f7631f15054ac55688f76805a6f1924e79058881957b67284865b6508886cc
-size 29249
+oid sha256:d5ac056ba00dd474b08e1a1de0886c5e6989c12ea97a106e379fff9394aa5b90
+size 29263
diff --git a/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.createroom.impl.components_null_DefaultGroup_RoomPrivacyOptionDarkPreview_0_null,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.createroom.impl.components_null_DefaultGroup_RoomPrivacyOptionDarkPreview_0_null,NEXUS_5,1.0,en].png
index 9e1ddd2ddb..e4ad0b75e4 100644
--- a/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.createroom.impl.components_null_DefaultGroup_RoomPrivacyOptionDarkPreview_0_null,NEXUS_5,1.0,en].png
+++ b/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.createroom.impl.components_null_DefaultGroup_RoomPrivacyOptionDarkPreview_0_null,NEXUS_5,1.0,en].png
@@ -1,3 +1,3 @@
 version https://git-lfs.github.com/spec/v1
-oid sha256:d47034cafef80cdac5d702e52092f07ebc0bb96dbdd7f9f0c1ea2e302cbe9917
-size 33858
+oid sha256:7b42afece0186cbbcb9ca5b716c3c535147d27bf1c57cabf033339fe9100edeb
+size 33889
diff --git a/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.createroom.impl.components_null_DefaultGroup_RoomPrivacyOptionLightPreview_0_null,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.createroom.impl.components_null_DefaultGroup_RoomPrivacyOptionLightPreview_0_null,NEXUS_5,1.0,en].png
index d50e567f72..5d7bb98cc3 100644
--- a/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.createroom.impl.components_null_DefaultGroup_RoomPrivacyOptionLightPreview_0_null,NEXUS_5,1.0,en].png
+++ b/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.createroom.impl.components_null_DefaultGroup_RoomPrivacyOptionLightPreview_0_null,NEXUS_5,1.0,en].png
@@ -1,3 +1,3 @@
 version https://git-lfs.github.com/spec/v1
-oid sha256:84ea420320bd406588cb4d9aa3fea79d63ec37fc31a00d4fa77a06a7c8499145
-size 35452
+oid sha256:248817743f94c09d5bb02580687f5d9150dcf22b1670289955197491f375ad65
+size 35640
diff --git a/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.createroom.impl.components_null_DefaultGroup_SearchMultipleUsersResultItemPreview_0_null,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.createroom.impl.components_null_DefaultGroup_SearchMultipleUsersResultItemPreview_0_null,NEXUS_5,1.0,en].png
index 6595be90cb..687420defd 100644
--- a/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.createroom.impl.components_null_DefaultGroup_SearchMultipleUsersResultItemPreview_0_null,NEXUS_5,1.0,en].png
+++ b/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.createroom.impl.components_null_DefaultGroup_SearchMultipleUsersResultItemPreview_0_null,NEXUS_5,1.0,en].png
@@ -1,3 +1,3 @@
 version https://git-lfs.github.com/spec/v1
-oid sha256:d01eaadfd0b9508c44145ba2e6cd85a6a24fdb43f665188404f9da1cf3e03321
-size 86292
+oid sha256:a4f987d8b03013d3aacbcc2b5a7374148c29d2c24dc41211781db15a06f3d52a
+size 86365
diff --git a/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.createroom.impl.components_null_DefaultGroup_UserListViewDarkPreview_0_null_6,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.createroom.impl.components_null_DefaultGroup_UserListViewDarkPreview_0_null_6,NEXUS_5,1.0,en].png
index 3245d6013a..2e34348af3 100644
--- a/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.createroom.impl.components_null_DefaultGroup_UserListViewDarkPreview_0_null_6,NEXUS_5,1.0,en].png
+++ b/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.createroom.impl.components_null_DefaultGroup_UserListViewDarkPreview_0_null_6,NEXUS_5,1.0,en].png
@@ -1,3 +1,3 @@
 version https://git-lfs.github.com/spec/v1
-oid sha256:45f4c5a3edbf61d815a7b1221a73123b09c8767d15ae2d9ae04f11ae3defe697
-size 67911
+oid sha256:90a7a6bc46fea5d6a02c9e3b6a29018e51fe270fc5034fdd7f9045f6fbbbc1d9
+size 67916
diff --git a/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.createroom.impl.components_null_DefaultGroup_UserListViewLightPreview_0_null_6,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.createroom.impl.components_null_DefaultGroup_UserListViewLightPreview_0_null_6,NEXUS_5,1.0,en].png
index 879d41bd8a..4f7bc094a8 100644
--- a/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.createroom.impl.components_null_DefaultGroup_UserListViewLightPreview_0_null_6,NEXUS_5,1.0,en].png
+++ b/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.createroom.impl.components_null_DefaultGroup_UserListViewLightPreview_0_null_6,NEXUS_5,1.0,en].png
@@ -1,3 +1,3 @@
 version https://git-lfs.github.com/spec/v1
-oid sha256:6811324cfc868722c57a02f2544ffcbbb2f2247fc9284e4e6fe869e33447c7b1
-size 69939
+oid sha256:037e24e82436183ed2ff4138a997c232e331076dd5374958e11efcfa8063b4d2
+size 69962
diff --git a/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.createroom.impl.configureroom_null_DefaultGroup_ConfigureRoomViewDarkPreview_0_null_0,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.createroom.impl.configureroom_null_DefaultGroup_ConfigureRoomViewDarkPreview_0_null_0,NEXUS_5,1.0,en].png
index 74124f825f..c1299a57ea 100644
--- a/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.createroom.impl.configureroom_null_DefaultGroup_ConfigureRoomViewDarkPreview_0_null_0,NEXUS_5,1.0,en].png
+++ b/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.createroom.impl.configureroom_null_DefaultGroup_ConfigureRoomViewDarkPreview_0_null_0,NEXUS_5,1.0,en].png
@@ -1,3 +1,3 @@
 version https://git-lfs.github.com/spec/v1
-oid sha256:0169cdedfc56ba1b55f133ed41146a0ec3597123a88ed086f7584f06d235da26
-size 57732
+oid sha256:3f0c16ef939ce2625d8e6788c0ccba95a4bc85d96acf282bed01cd67db65a4de
+size 58090
diff --git a/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.createroom.impl.configureroom_null_DefaultGroup_ConfigureRoomViewDarkPreview_0_null_1,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.createroom.impl.configureroom_null_DefaultGroup_ConfigureRoomViewDarkPreview_0_null_1,NEXUS_5,1.0,en].png
index 50ee002c0c..c8928c442f 100644
--- a/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.createroom.impl.configureroom_null_DefaultGroup_ConfigureRoomViewDarkPreview_0_null_1,NEXUS_5,1.0,en].png
+++ b/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.createroom.impl.configureroom_null_DefaultGroup_ConfigureRoomViewDarkPreview_0_null_1,NEXUS_5,1.0,en].png
@@ -1,3 +1,3 @@
 version https://git-lfs.github.com/spec/v1
-oid sha256:a0cdeea89592fbad03e1ad29aa1616bd779403f022097ca11510ff9cda3457aa
-size 83656
+oid sha256:ab118e4c47a83d68eda51b8b077a3eb55f0b5ad829b670be56ddddb99545c2a3
+size 83648
diff --git a/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.createroom.impl.configureroom_null_DefaultGroup_ConfigureRoomViewLightPreview_0_null_0,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.createroom.impl.configureroom_null_DefaultGroup_ConfigureRoomViewLightPreview_0_null_0,NEXUS_5,1.0,en].png
index 6c4a4bcaba..49fc604d5f 100644
--- a/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.createroom.impl.configureroom_null_DefaultGroup_ConfigureRoomViewLightPreview_0_null_0,NEXUS_5,1.0,en].png
+++ b/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.createroom.impl.configureroom_null_DefaultGroup_ConfigureRoomViewLightPreview_0_null_0,NEXUS_5,1.0,en].png
@@ -1,3 +1,3 @@
 version https://git-lfs.github.com/spec/v1
-oid sha256:f61e37505ee1276d894641647ec34323f415f4a3cdc699de01579a92255c2a4e
-size 60941
+oid sha256:d016b99c433497a620543a4cdb1eae7207ca94bcd434b712b81d4ff72a886296
+size 61485
diff --git a/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.createroom.impl.configureroom_null_DefaultGroup_ConfigureRoomViewLightPreview_0_null_1,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.createroom.impl.configureroom_null_DefaultGroup_ConfigureRoomViewLightPreview_0_null_1,NEXUS_5,1.0,en].png
index c1f3859c0a..1fd2f7aa17 100644
--- a/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.createroom.impl.configureroom_null_DefaultGroup_ConfigureRoomViewLightPreview_0_null_1,NEXUS_5,1.0,en].png
+++ b/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.createroom.impl.configureroom_null_DefaultGroup_ConfigureRoomViewLightPreview_0_null_1,NEXUS_5,1.0,en].png
@@ -1,3 +1,3 @@
 version https://git-lfs.github.com/spec/v1
-oid sha256:630fa772c15d8f16461655b2c2763d8ca85dc29812fea7d01366d68e3a446eaf
-size 86660
+oid sha256:3cf250f67844c383047ca24b496f8539360467f8fb16c0623fce9c9fff942c1e
+size 86880
diff --git a/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.createroom.impl.root_null_DefaultGroup_CreateRoomRootViewDarkPreview_0_null_2,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.createroom.impl.root_null_DefaultGroup_CreateRoomRootViewDarkPreview_0_null_2,NEXUS_5,1.0,en].png
index 49d7942204..deccc2399a 100644
--- a/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.createroom.impl.root_null_DefaultGroup_CreateRoomRootViewDarkPreview_0_null_2,NEXUS_5,1.0,en].png
+++ b/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.createroom.impl.root_null_DefaultGroup_CreateRoomRootViewDarkPreview_0_null_2,NEXUS_5,1.0,en].png
@@ -1,3 +1,3 @@
 version https://git-lfs.github.com/spec/v1
-oid sha256:5312bd01a41dc0d1b022b6ce7258435d1cd9de75bd4231ce7f86ed6f84de2e4b
-size 26306
+oid sha256:1013f54744e6f5e31bbba2bf0567e2a9cfe080e6821f81153f31c8588c88a29e
+size 27219
diff --git a/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.createroom.impl.root_null_DefaultGroup_CreateRoomRootViewLightPreview_0_null_2,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.createroom.impl.root_null_DefaultGroup_CreateRoomRootViewLightPreview_0_null_2,NEXUS_5,1.0,en].png
index bd930af4d9..2c6bddd66a 100644
--- a/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.createroom.impl.root_null_DefaultGroup_CreateRoomRootViewLightPreview_0_null_2,NEXUS_5,1.0,en].png
+++ b/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.createroom.impl.root_null_DefaultGroup_CreateRoomRootViewLightPreview_0_null_2,NEXUS_5,1.0,en].png
@@ -1,3 +1,3 @@
 version https://git-lfs.github.com/spec/v1
-oid sha256:1b9b88deb5557da8b4670231ee41aa737543244d61abfd399d7de0f6d4496dde
-size 27439
+oid sha256:322b47618d1ac52742bd163d1e588ebb222e2d709ee92a6e0d7746efef975293
+size 29016
diff --git a/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.ftue.impl.welcome_null_DefaultGroup_WelcomeViewPreview-D-0_1_null,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.ftue.impl.welcome_null_DefaultGroup_WelcomeViewPreview-D-0_1_null,NEXUS_5,1.0,en].png
index f300f92921..14e58b56ce 100644
--- a/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.ftue.impl.welcome_null_DefaultGroup_WelcomeViewPreview-D-0_1_null,NEXUS_5,1.0,en].png
+++ b/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.ftue.impl.welcome_null_DefaultGroup_WelcomeViewPreview-D-0_1_null,NEXUS_5,1.0,en].png
@@ -1,3 +1,3 @@
 version https://git-lfs.github.com/spec/v1
-oid sha256:16de62092834bf803c8165e974f45e14ccfc0128a3e74295a58eef965abc10c5
-size 301336
+oid sha256:6d2eab27a1132893542b240399a4003b4049b72903a822077f69dd9dafd26f71
+size 299106
diff --git a/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.ftue.impl.welcome_null_DefaultGroup_WelcomeViewPreview-N-0_2_null,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.ftue.impl.welcome_null_DefaultGroup_WelcomeViewPreview-N-0_2_null,NEXUS_5,1.0,en].png
index 7465768560..d38be285ba 100644
--- a/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.ftue.impl.welcome_null_DefaultGroup_WelcomeViewPreview-N-0_2_null,NEXUS_5,1.0,en].png
+++ b/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.ftue.impl.welcome_null_DefaultGroup_WelcomeViewPreview-N-0_2_null,NEXUS_5,1.0,en].png
@@ -1,3 +1,3 @@
 version https://git-lfs.github.com/spec/v1
-oid sha256:6838e81cc5f2755ff76de7254e2c8bb445b76662d7ba9b4c83443b2c2ed03029
-size 406044
+oid sha256:fbad2f74e329a424e75ef96cb0c427a7baba044f3267346756324c39ebd6add6
+size 404196
diff --git a/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.invitelist.impl.components_null_DefaultGroup_InviteSummaryRowDarkPreview_0_null_0,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.invitelist.impl.components_null_DefaultGroup_InviteSummaryRowDarkPreview_0_null_0,NEXUS_5,1.0,en].png
index ddc9420223..d4db900fe9 100644
--- a/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.invitelist.impl.components_null_DefaultGroup_InviteSummaryRowDarkPreview_0_null_0,NEXUS_5,1.0,en].png
+++ b/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.invitelist.impl.components_null_DefaultGroup_InviteSummaryRowDarkPreview_0_null_0,NEXUS_5,1.0,en].png
@@ -1,3 +1,3 @@
 version https://git-lfs.github.com/spec/v1
-oid sha256:07e722c2936e1332168319059d5b4a553b1fc7f03da8aff40b005a05b203632d
-size 28679
+oid sha256:7ee847a64a963e1536e8fa118516cb58dd3ef450decbaafda3cae067bd44e8c4
+size 28447
diff --git a/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.invitelist.impl.components_null_DefaultGroup_InviteSummaryRowDarkPreview_0_null_1,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.invitelist.impl.components_null_DefaultGroup_InviteSummaryRowDarkPreview_0_null_1,NEXUS_5,1.0,en].png
index cfe7f4094d..22db922bfd 100644
--- a/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.invitelist.impl.components_null_DefaultGroup_InviteSummaryRowDarkPreview_0_null_1,NEXUS_5,1.0,en].png
+++ b/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.invitelist.impl.components_null_DefaultGroup_InviteSummaryRowDarkPreview_0_null_1,NEXUS_5,1.0,en].png
@@ -1,3 +1,3 @@
 version https://git-lfs.github.com/spec/v1
-oid sha256:eab30f7ec6ad8e289f4987d23f373ca8f96220a5d0762d46723058bca53d0a41
-size 33580
+oid sha256:0aa12e1e306c98dc03ce08acf178624c17622546ab32d93571d0e6f73530e95a
+size 33101
diff --git a/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.invitelist.impl.components_null_DefaultGroup_InviteSummaryRowDarkPreview_0_null_2,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.invitelist.impl.components_null_DefaultGroup_InviteSummaryRowDarkPreview_0_null_2,NEXUS_5,1.0,en].png
index f0155d216f..07f66bcad7 100644
--- a/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.invitelist.impl.components_null_DefaultGroup_InviteSummaryRowDarkPreview_0_null_2,NEXUS_5,1.0,en].png
+++ b/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.invitelist.impl.components_null_DefaultGroup_InviteSummaryRowDarkPreview_0_null_2,NEXUS_5,1.0,en].png
@@ -1,3 +1,3 @@
 version https://git-lfs.github.com/spec/v1
-oid sha256:6a344ef3f77b759e1d43733f85fc7ee9bee98d6eb3980ce13c435bb33c0703f0
-size 33720
+oid sha256:ad431cfafb873a27010ef2f5191efbbb7a7d43518f3fd72cc1d93bde3fbc5db4
+size 33246
diff --git a/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.invitelist.impl.components_null_DefaultGroup_InviteSummaryRowDarkPreview_0_null_3,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.invitelist.impl.components_null_DefaultGroup_InviteSummaryRowDarkPreview_0_null_3,NEXUS_5,1.0,en].png
index a38e7f59a4..5a0c58a0f6 100644
--- a/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.invitelist.impl.components_null_DefaultGroup_InviteSummaryRowDarkPreview_0_null_3,NEXUS_5,1.0,en].png
+++ b/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.invitelist.impl.components_null_DefaultGroup_InviteSummaryRowDarkPreview_0_null_3,NEXUS_5,1.0,en].png
@@ -1,3 +1,3 @@
 version https://git-lfs.github.com/spec/v1
-oid sha256:6e5874a0e224636c5ad13f4022e8f2ef3dff97206a5551734de560fbc40c562a
-size 14447
+oid sha256:f8edf269361969e35486f0bfdfcfe99c69c82adbeea87c5ccc7af244a68dfdbe
+size 14022
diff --git a/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.invitelist.impl.components_null_DefaultGroup_InviteSummaryRowDarkPreview_0_null_4,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.invitelist.impl.components_null_DefaultGroup_InviteSummaryRowDarkPreview_0_null_4,NEXUS_5,1.0,en].png
index 8f6d7d3782..0a3714c60a 100644
--- a/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.invitelist.impl.components_null_DefaultGroup_InviteSummaryRowDarkPreview_0_null_4,NEXUS_5,1.0,en].png
+++ b/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.invitelist.impl.components_null_DefaultGroup_InviteSummaryRowDarkPreview_0_null_4,NEXUS_5,1.0,en].png
@@ -1,3 +1,3 @@
 version https://git-lfs.github.com/spec/v1
-oid sha256:1e526f418f5c8d1d0c51509808e22548ce3c295752e7a1cf28cfe394fccc01f4
-size 28834
+oid sha256:36dbf0c8406baed1c3125173b0113e071e28e8370b7fe6ec7887687e59e98035
+size 28612
diff --git a/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.invitelist.impl.components_null_DefaultGroup_InviteSummaryRowLightPreview_0_null_0,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.invitelist.impl.components_null_DefaultGroup_InviteSummaryRowLightPreview_0_null_0,NEXUS_5,1.0,en].png
index 29cf018c14..76d31c9467 100644
--- a/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.invitelist.impl.components_null_DefaultGroup_InviteSummaryRowLightPreview_0_null_0,NEXUS_5,1.0,en].png
+++ b/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.invitelist.impl.components_null_DefaultGroup_InviteSummaryRowLightPreview_0_null_0,NEXUS_5,1.0,en].png
@@ -1,3 +1,3 @@
 version https://git-lfs.github.com/spec/v1
-oid sha256:97639d0985e0303e3a58120fbb7a2bba67b4279d198140a9f4cf6b19aa74bed0
-size 29199
+oid sha256:d7c5c16830d017da9d76cdf9469fe7e2d7e718b5d1cb2408e15fdcf773d707d6
+size 29132
diff --git a/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.invitelist.impl.components_null_DefaultGroup_InviteSummaryRowLightPreview_0_null_1,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.invitelist.impl.components_null_DefaultGroup_InviteSummaryRowLightPreview_0_null_1,NEXUS_5,1.0,en].png
index 1acc83ec3c..8560c591fe 100644
--- a/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.invitelist.impl.components_null_DefaultGroup_InviteSummaryRowLightPreview_0_null_1,NEXUS_5,1.0,en].png
+++ b/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.invitelist.impl.components_null_DefaultGroup_InviteSummaryRowLightPreview_0_null_1,NEXUS_5,1.0,en].png
@@ -1,3 +1,3 @@
 version https://git-lfs.github.com/spec/v1
-oid sha256:f0372c5389850f853652ad40ad54069e456aa33e13335e733d779a8d4d384049
-size 35297
+oid sha256:791944236c8027c25bad58e2a6db65a72d310fdc54095ed7475701a9fad689c7
+size 35006
diff --git a/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.invitelist.impl.components_null_DefaultGroup_InviteSummaryRowLightPreview_0_null_2,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.invitelist.impl.components_null_DefaultGroup_InviteSummaryRowLightPreview_0_null_2,NEXUS_5,1.0,en].png
index ddb0df10ed..07cd0f89ce 100644
--- a/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.invitelist.impl.components_null_DefaultGroup_InviteSummaryRowLightPreview_0_null_2,NEXUS_5,1.0,en].png
+++ b/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.invitelist.impl.components_null_DefaultGroup_InviteSummaryRowLightPreview_0_null_2,NEXUS_5,1.0,en].png
@@ -1,3 +1,3 @@
 version https://git-lfs.github.com/spec/v1
-oid sha256:62f57ee9fc205539ede541baf8e4b887ef7776675c4760acd5b27545cd021df8
-size 35420
+oid sha256:adfadfbbcd6920bca70c435cbb68c83e18cfd9e15eac4545fa5f1e404b258255
+size 35121
diff --git a/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.invitelist.impl.components_null_DefaultGroup_InviteSummaryRowLightPreview_0_null_3,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.invitelist.impl.components_null_DefaultGroup_InviteSummaryRowLightPreview_0_null_3,NEXUS_5,1.0,en].png
index 0b5b749dfd..4b96dac84e 100644
--- a/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.invitelist.impl.components_null_DefaultGroup_InviteSummaryRowLightPreview_0_null_3,NEXUS_5,1.0,en].png
+++ b/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.invitelist.impl.components_null_DefaultGroup_InviteSummaryRowLightPreview_0_null_3,NEXUS_5,1.0,en].png
@@ -1,3 +1,3 @@
 version https://git-lfs.github.com/spec/v1
-oid sha256:ea79f0de34ba0613fea7ba98c65f5ff925a336ddf2d6734ea77b1a2d559527f0
-size 14416
+oid sha256:1694a5589d39a7b4d7fcc823a0d6b2c86e9bb9c759ace8e5790df85ebc7ea3af
+size 14167
diff --git a/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.invitelist.impl.components_null_DefaultGroup_InviteSummaryRowLightPreview_0_null_4,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.invitelist.impl.components_null_DefaultGroup_InviteSummaryRowLightPreview_0_null_4,NEXUS_5,1.0,en].png
index d7bead23cf..cee0955c2c 100644
--- a/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.invitelist.impl.components_null_DefaultGroup_InviteSummaryRowLightPreview_0_null_4,NEXUS_5,1.0,en].png
+++ b/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.invitelist.impl.components_null_DefaultGroup_InviteSummaryRowLightPreview_0_null_4,NEXUS_5,1.0,en].png
@@ -1,3 +1,3 @@
 version https://git-lfs.github.com/spec/v1
-oid sha256:4b13ebc73e257d5f588f9e74d0a35bc9af951faece57556636378914786429e3
-size 29503
+oid sha256:5575ca96bb0b925109b5aad2207c304a0d1d54e8eeace250369e23982f23ec09
+size 29424
diff --git a/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.invitelist.impl_null_DefaultGroup_InviteListViewDarkPreview_0_null_0,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.invitelist.impl_null_DefaultGroup_InviteListViewDarkPreview_0_null_0,NEXUS_5,1.0,en].png
index bbd5173671..62e1d90606 100644
--- a/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.invitelist.impl_null_DefaultGroup_InviteListViewDarkPreview_0_null_0,NEXUS_5,1.0,en].png
+++ b/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.invitelist.impl_null_DefaultGroup_InviteListViewDarkPreview_0_null_0,NEXUS_5,1.0,en].png
@@ -1,3 +1,3 @@
 version https://git-lfs.github.com/spec/v1
-oid sha256:5fcd5bd88a1aea468c8f5e08a3e07a323bd0e76f8db913611929c80184c2f68c
-size 53541
+oid sha256:014ace4752ba1f47272fd5320aa567a3b825c159548b36a1cdea34eb933cf0f0
+size 52332
diff --git a/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.invitelist.impl_null_DefaultGroup_InviteListViewDarkPreview_0_null_2,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.invitelist.impl_null_DefaultGroup_InviteListViewDarkPreview_0_null_2,NEXUS_5,1.0,en].png
index 418e6be50b..c4a75a4b80 100644
--- a/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.invitelist.impl_null_DefaultGroup_InviteListViewDarkPreview_0_null_2,NEXUS_5,1.0,en].png
+++ b/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.invitelist.impl_null_DefaultGroup_InviteListViewDarkPreview_0_null_2,NEXUS_5,1.0,en].png
@@ -1,3 +1,3 @@
 version https://git-lfs.github.com/spec/v1
-oid sha256:d3a5f5dcad110d0fe9cc1e81537319feac59c7d25084d9b77ed22c44969a7237
-size 48499
+oid sha256:ef34ff577d23711414e082e08ad82548c307541ae384f695317232d66cd2e493
+size 50369
diff --git a/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.invitelist.impl_null_DefaultGroup_InviteListViewDarkPreview_0_null_3,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.invitelist.impl_null_DefaultGroup_InviteListViewDarkPreview_0_null_3,NEXUS_5,1.0,en].png
index f3aeeb5b53..a1bee8e1d4 100644
--- a/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.invitelist.impl_null_DefaultGroup_InviteListViewDarkPreview_0_null_3,NEXUS_5,1.0,en].png
+++ b/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.invitelist.impl_null_DefaultGroup_InviteListViewDarkPreview_0_null_3,NEXUS_5,1.0,en].png
@@ -1,3 +1,3 @@
 version https://git-lfs.github.com/spec/v1
-oid sha256:ee4f54670538988698e947dd42d6d3bc585f743684e83202d48f8d02d1bdf1f8
-size 49214
+oid sha256:9afbaa0b1fd0ae0e98db92688bba574e4279af51769bbe20e8c9bd2fe3cd6714
+size 51087
diff --git a/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.invitelist.impl_null_DefaultGroup_InviteListViewDarkPreview_0_null_4,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.invitelist.impl_null_DefaultGroup_InviteListViewDarkPreview_0_null_4,NEXUS_5,1.0,en].png
index f669883f45..7089e6c668 100644
--- a/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.invitelist.impl_null_DefaultGroup_InviteListViewDarkPreview_0_null_4,NEXUS_5,1.0,en].png
+++ b/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.invitelist.impl_null_DefaultGroup_InviteListViewDarkPreview_0_null_4,NEXUS_5,1.0,en].png
@@ -1,3 +1,3 @@
 version https://git-lfs.github.com/spec/v1
-oid sha256:442ff73662328311d0f8d9ef0000bf2be3b6141810b26f864847217081900411
-size 41007
+oid sha256:9fc1fd77ddc0abc5b26343e552895156797b6a3afa62fdebb277d04fc75273ed
+size 40830
diff --git a/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.invitelist.impl_null_DefaultGroup_InviteListViewDarkPreview_0_null_5,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.invitelist.impl_null_DefaultGroup_InviteListViewDarkPreview_0_null_5,NEXUS_5,1.0,en].png
index f669883f45..7089e6c668 100644
--- a/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.invitelist.impl_null_DefaultGroup_InviteListViewDarkPreview_0_null_5,NEXUS_5,1.0,en].png
+++ b/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.invitelist.impl_null_DefaultGroup_InviteListViewDarkPreview_0_null_5,NEXUS_5,1.0,en].png
@@ -1,3 +1,3 @@
 version https://git-lfs.github.com/spec/v1
-oid sha256:442ff73662328311d0f8d9ef0000bf2be3b6141810b26f864847217081900411
-size 41007
+oid sha256:9fc1fd77ddc0abc5b26343e552895156797b6a3afa62fdebb277d04fc75273ed
+size 40830
diff --git a/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.invitelist.impl_null_DefaultGroup_InviteListViewLightPreview_0_null_0,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.invitelist.impl_null_DefaultGroup_InviteListViewLightPreview_0_null_0,NEXUS_5,1.0,en].png
index e123bbbe3f..23026cee2b 100644
--- a/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.invitelist.impl_null_DefaultGroup_InviteListViewLightPreview_0_null_0,NEXUS_5,1.0,en].png
+++ b/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.invitelist.impl_null_DefaultGroup_InviteListViewLightPreview_0_null_0,NEXUS_5,1.0,en].png
@@ -1,3 +1,3 @@
 version https://git-lfs.github.com/spec/v1
-oid sha256:f20e6a88d40320286d73dfa346a02783a00b1fb4a10c804c2f147e2f909c5a2a
-size 56083
+oid sha256:0219335bf2f3be0a4a785d7ca2e05700278401aa090d5972a76ce077cfbe5be6
+size 55406
diff --git a/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.invitelist.impl_null_DefaultGroup_InviteListViewLightPreview_0_null_2,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.invitelist.impl_null_DefaultGroup_InviteListViewLightPreview_0_null_2,NEXUS_5,1.0,en].png
index 816e5fe57d..28647b48d9 100644
--- a/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.invitelist.impl_null_DefaultGroup_InviteListViewLightPreview_0_null_2,NEXUS_5,1.0,en].png
+++ b/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.invitelist.impl_null_DefaultGroup_InviteListViewLightPreview_0_null_2,NEXUS_5,1.0,en].png
@@ -1,3 +1,3 @@
 version https://git-lfs.github.com/spec/v1
-oid sha256:c25bf522377a036e8faae35e8afe458d82cf3c761e2df237a1a4d5785f44e188
-size 50202
+oid sha256:57da53bc60d35949fc3c762e0c2e57a73552a065107543819791610ea3aea327
+size 52509
diff --git a/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.invitelist.impl_null_DefaultGroup_InviteListViewLightPreview_0_null_3,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.invitelist.impl_null_DefaultGroup_InviteListViewLightPreview_0_null_3,NEXUS_5,1.0,en].png
index a57d29443c..e44fc33e53 100644
--- a/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.invitelist.impl_null_DefaultGroup_InviteListViewLightPreview_0_null_3,NEXUS_5,1.0,en].png
+++ b/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.invitelist.impl_null_DefaultGroup_InviteListViewLightPreview_0_null_3,NEXUS_5,1.0,en].png
@@ -1,3 +1,3 @@
 version https://git-lfs.github.com/spec/v1
-oid sha256:904a991dd0b753af68f0ab626d1f236dc9ea273a35f100475cadad8f4332d25d
-size 50896
+oid sha256:94b57a5760b3afb973af466a8eec26c40e8e70b5790061fbb343320e359e12d8
+size 53103
diff --git a/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.invitelist.impl_null_DefaultGroup_InviteListViewLightPreview_0_null_4,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.invitelist.impl_null_DefaultGroup_InviteListViewLightPreview_0_null_4,NEXUS_5,1.0,en].png
index d61deff1b1..024b035f6d 100644
--- a/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.invitelist.impl_null_DefaultGroup_InviteListViewLightPreview_0_null_4,NEXUS_5,1.0,en].png
+++ b/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.invitelist.impl_null_DefaultGroup_InviteListViewLightPreview_0_null_4,NEXUS_5,1.0,en].png
@@ -1,3 +1,3 @@
 version https://git-lfs.github.com/spec/v1
-oid sha256:98ff0c7db1cd224a6d9897b1daf49f57fc659b25e60a9d670e8b1c66811d4fed
-size 42505
+oid sha256:c2e9ffe60a426543aacb68bdb73d7019d9271673762edd3e4011b0ac445fadc1
+size 43067
diff --git a/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.invitelist.impl_null_DefaultGroup_InviteListViewLightPreview_0_null_5,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.invitelist.impl_null_DefaultGroup_InviteListViewLightPreview_0_null_5,NEXUS_5,1.0,en].png
index d61deff1b1..024b035f6d 100644
--- a/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.invitelist.impl_null_DefaultGroup_InviteListViewLightPreview_0_null_5,NEXUS_5,1.0,en].png
+++ b/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.invitelist.impl_null_DefaultGroup_InviteListViewLightPreview_0_null_5,NEXUS_5,1.0,en].png
@@ -1,3 +1,3 @@
 version https://git-lfs.github.com/spec/v1
-oid sha256:98ff0c7db1cd224a6d9897b1daf49f57fc659b25e60a9d670e8b1c66811d4fed
-size 42505
+oid sha256:c2e9ffe60a426543aacb68bdb73d7019d9271673762edd3e4011b0ac445fadc1
+size 43067
diff --git a/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.leaveroom.api_null_DefaultGroup_LeaveRoomViewDarkPreview_0_null_1,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.leaveroom.api_null_DefaultGroup_LeaveRoomViewDarkPreview_0_null_1,NEXUS_5,1.0,en].png
index d36f847e7b..feca962b5c 100644
--- a/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.leaveroom.api_null_DefaultGroup_LeaveRoomViewDarkPreview_0_null_1,NEXUS_5,1.0,en].png
+++ b/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.leaveroom.api_null_DefaultGroup_LeaveRoomViewDarkPreview_0_null_1,NEXUS_5,1.0,en].png
@@ -1,3 +1,3 @@
 version https://git-lfs.github.com/spec/v1
-oid sha256:42d22676a81b8c1f313f2f21814b787c54fa52f8b344207b509fbb798f2f58a1
-size 20075
+oid sha256:8b4d93b1444cb814fe0d8471679dc492f10b78c2ba101884491bef16a567aba6
+size 20704
diff --git a/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.leaveroom.api_null_DefaultGroup_LeaveRoomViewDarkPreview_0_null_2,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.leaveroom.api_null_DefaultGroup_LeaveRoomViewDarkPreview_0_null_2,NEXUS_5,1.0,en].png
index 292f5d9f30..ca5aaa3076 100644
--- a/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.leaveroom.api_null_DefaultGroup_LeaveRoomViewDarkPreview_0_null_2,NEXUS_5,1.0,en].png
+++ b/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.leaveroom.api_null_DefaultGroup_LeaveRoomViewDarkPreview_0_null_2,NEXUS_5,1.0,en].png
@@ -1,3 +1,3 @@
 version https://git-lfs.github.com/spec/v1
-oid sha256:34645175d5acb2915d04b9306d648a287cae769bffcae7ecaffd293d43580683
-size 29023
+oid sha256:35e9b3412e3a64ec302899f44185d8a82680506be71bc4a8aa7b4705a1f9f6fb
+size 29736
diff --git a/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.leaveroom.api_null_DefaultGroup_LeaveRoomViewDarkPreview_0_null_3,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.leaveroom.api_null_DefaultGroup_LeaveRoomViewDarkPreview_0_null_3,NEXUS_5,1.0,en].png
index fe795d5c26..1e9705d92b 100644
--- a/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.leaveroom.api_null_DefaultGroup_LeaveRoomViewDarkPreview_0_null_3,NEXUS_5,1.0,en].png
+++ b/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.leaveroom.api_null_DefaultGroup_LeaveRoomViewDarkPreview_0_null_3,NEXUS_5,1.0,en].png
@@ -1,3 +1,3 @@
 version https://git-lfs.github.com/spec/v1
-oid sha256:56f203dce2ed8ff23a75eb66bcb116fb4af61b63b1ad095ecebf6d97ba557a2c
-size 31392
+oid sha256:a68d387ac86cadb030b44153ebb07864b59194d87465012fe5c45e5c5b6dd8cc
+size 32227
diff --git a/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.leaveroom.api_null_DefaultGroup_LeaveRoomViewDarkPreview_0_null_5,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.leaveroom.api_null_DefaultGroup_LeaveRoomViewDarkPreview_0_null_5,NEXUS_5,1.0,en].png
index 1393c4aa2a..3337e0b854 100644
--- a/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.leaveroom.api_null_DefaultGroup_LeaveRoomViewDarkPreview_0_null_5,NEXUS_5,1.0,en].png
+++ b/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.leaveroom.api_null_DefaultGroup_LeaveRoomViewDarkPreview_0_null_5,NEXUS_5,1.0,en].png
@@ -1,3 +1,3 @@
 version https://git-lfs.github.com/spec/v1
-oid sha256:1d23fb856aa3402cebf5c976fe32f0475f2f58b37a9ac9d028b0164dae4de397
-size 13357
+oid sha256:ba63eb801cfe25cc2ec7dab0b1277757b1f608eff5a596157a8c2c457e2bbdd0
+size 12568
diff --git a/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.leaveroom.api_null_DefaultGroup_LeaveRoomViewLightPreview_0_null_1,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.leaveroom.api_null_DefaultGroup_LeaveRoomViewLightPreview_0_null_1,NEXUS_5,1.0,en].png
index 7ab75f845d..0f4c367ecf 100644
--- a/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.leaveroom.api_null_DefaultGroup_LeaveRoomViewLightPreview_0_null_1,NEXUS_5,1.0,en].png
+++ b/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.leaveroom.api_null_DefaultGroup_LeaveRoomViewLightPreview_0_null_1,NEXUS_5,1.0,en].png
@@ -1,3 +1,3 @@
 version https://git-lfs.github.com/spec/v1
-oid sha256:e748443031dd55fdf60f13debd2484f8169b7eb23980786ad73898004c7bcbfe
-size 19615
+oid sha256:aec6ed6095cbdf2eabc46db41e4a6d5513a7a1a8f4610a0a68dfdbc006fea354
+size 21016
diff --git a/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.leaveroom.api_null_DefaultGroup_LeaveRoomViewLightPreview_0_null_2,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.leaveroom.api_null_DefaultGroup_LeaveRoomViewLightPreview_0_null_2,NEXUS_5,1.0,en].png
index 7b458addc7..22146dd734 100644
--- a/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.leaveroom.api_null_DefaultGroup_LeaveRoomViewLightPreview_0_null_2,NEXUS_5,1.0,en].png
+++ b/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.leaveroom.api_null_DefaultGroup_LeaveRoomViewLightPreview_0_null_2,NEXUS_5,1.0,en].png
@@ -1,3 +1,3 @@
 version https://git-lfs.github.com/spec/v1
-oid sha256:5c2419ccf59c98899071e705b63feb83e8976acca53ccb8f375551aa056f9950
-size 29204
+oid sha256:6dd7b26eca3d0c40bd38d02833c0c43c348608574997a5e35d91c61c19928b76
+size 30473
diff --git a/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.leaveroom.api_null_DefaultGroup_LeaveRoomViewLightPreview_0_null_3,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.leaveroom.api_null_DefaultGroup_LeaveRoomViewLightPreview_0_null_3,NEXUS_5,1.0,en].png
index c64c365b53..f3933c1a22 100644
--- a/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.leaveroom.api_null_DefaultGroup_LeaveRoomViewLightPreview_0_null_3,NEXUS_5,1.0,en].png
+++ b/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.leaveroom.api_null_DefaultGroup_LeaveRoomViewLightPreview_0_null_3,NEXUS_5,1.0,en].png
@@ -1,3 +1,3 @@
 version https://git-lfs.github.com/spec/v1
-oid sha256:598f0a995896c32b1755951779f3784dbbe5062b7039bb8952d383acf2399efd
-size 31871
+oid sha256:fa450e9ad1db65fee62ad2fad4de118e1b1f335fce7b2e685d25063006521fb3
+size 33305
diff --git a/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.leaveroom.api_null_DefaultGroup_LeaveRoomViewLightPreview_0_null_5,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.leaveroom.api_null_DefaultGroup_LeaveRoomViewLightPreview_0_null_5,NEXUS_5,1.0,en].png
index c4d8cc0f03..ff0b013334 100644
--- a/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.leaveroom.api_null_DefaultGroup_LeaveRoomViewLightPreview_0_null_5,NEXUS_5,1.0,en].png
+++ b/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.leaveroom.api_null_DefaultGroup_LeaveRoomViewLightPreview_0_null_5,NEXUS_5,1.0,en].png
@@ -1,3 +1,3 @@
 version https://git-lfs.github.com/spec/v1
-oid sha256:9bf0bc49ba28e3e31414b1d1eb177c119529bc7c95209a8bbefafa6fc07a6fba
-size 12603
+oid sha256:b25270512a267079055363bdb6d54cb5444bbfcad4e60f2ca0e0466452b28ae4
+size 12238
diff --git a/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.location.impl.send_null_DefaultGroup_SendLocationViewPreview-D-0_1_null_0,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.location.impl.send_null_DefaultGroup_SendLocationViewPreview-D-0_1_null_0,NEXUS_5,1.0,en].png
index fe104f1c2f..c092db7ce4 100644
--- a/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.location.impl.send_null_DefaultGroup_SendLocationViewPreview-D-0_1_null_0,NEXUS_5,1.0,en].png
+++ b/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.location.impl.send_null_DefaultGroup_SendLocationViewPreview-D-0_1_null_0,NEXUS_5,1.0,en].png
@@ -1,3 +1,3 @@
 version https://git-lfs.github.com/spec/v1
-oid sha256:69535debd585127a4ce8b490ef6682c2e6c3c4d16478e6b9e9687ee1c1133637
-size 20879
+oid sha256:84581aac943c5065f1e5438465ee7d1845555e68aa005d8b596542ce3830dc83
+size 21258
diff --git a/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.location.impl.send_null_DefaultGroup_SendLocationViewPreview-D-0_1_null_1,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.location.impl.send_null_DefaultGroup_SendLocationViewPreview-D-0_1_null_1,NEXUS_5,1.0,en].png
index 09e7be69f8..5032df6d49 100644
--- a/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.location.impl.send_null_DefaultGroup_SendLocationViewPreview-D-0_1_null_1,NEXUS_5,1.0,en].png
+++ b/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.location.impl.send_null_DefaultGroup_SendLocationViewPreview-D-0_1_null_1,NEXUS_5,1.0,en].png
@@ -1,3 +1,3 @@
 version https://git-lfs.github.com/spec/v1
-oid sha256:356756de9f08042c3c2f3033d3f8a39cd9b49c5cfbcfbc274933c3efedd80d3d
-size 34534
+oid sha256:d430ee7f8f505a7fb42bb4f1ac795fa339ff9048837ee9f4c4166c4df78004fb
+size 37584
diff --git a/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.location.impl.send_null_DefaultGroup_SendLocationViewPreview-D-0_1_null_2,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.location.impl.send_null_DefaultGroup_SendLocationViewPreview-D-0_1_null_2,NEXUS_5,1.0,en].png
index 5311a17e6e..8c58e965e3 100644
--- a/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.location.impl.send_null_DefaultGroup_SendLocationViewPreview-D-0_1_null_2,NEXUS_5,1.0,en].png
+++ b/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.location.impl.send_null_DefaultGroup_SendLocationViewPreview-D-0_1_null_2,NEXUS_5,1.0,en].png
@@ -1,3 +1,3 @@
 version https://git-lfs.github.com/spec/v1
-oid sha256:51ac3c4bb27d78419f73b99cb24327514ce56a64a03bf74ce41f158c2c3bd516
-size 33605
+oid sha256:b7ffd042ba4e4a6b10f6c566765bf3fe4c992513f09169ca89a263983f162d79
+size 35994
diff --git a/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.location.impl.send_null_DefaultGroup_SendLocationViewPreview-D-0_1_null_3,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.location.impl.send_null_DefaultGroup_SendLocationViewPreview-D-0_1_null_3,NEXUS_5,1.0,en].png
index fe104f1c2f..c092db7ce4 100644
--- a/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.location.impl.send_null_DefaultGroup_SendLocationViewPreview-D-0_1_null_3,NEXUS_5,1.0,en].png
+++ b/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.location.impl.send_null_DefaultGroup_SendLocationViewPreview-D-0_1_null_3,NEXUS_5,1.0,en].png
@@ -1,3 +1,3 @@
 version https://git-lfs.github.com/spec/v1
-oid sha256:69535debd585127a4ce8b490ef6682c2e6c3c4d16478e6b9e9687ee1c1133637
-size 20879
+oid sha256:84581aac943c5065f1e5438465ee7d1845555e68aa005d8b596542ce3830dc83
+size 21258
diff --git a/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.location.impl.send_null_DefaultGroup_SendLocationViewPreview-D-0_1_null_4,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.location.impl.send_null_DefaultGroup_SendLocationViewPreview-D-0_1_null_4,NEXUS_5,1.0,en].png
index 960bd96e80..c9c6837a0e 100644
--- a/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.location.impl.send_null_DefaultGroup_SendLocationViewPreview-D-0_1_null_4,NEXUS_5,1.0,en].png
+++ b/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.location.impl.send_null_DefaultGroup_SendLocationViewPreview-D-0_1_null_4,NEXUS_5,1.0,en].png
@@ -1,3 +1,3 @@
 version https://git-lfs.github.com/spec/v1
-oid sha256:1fa3b5aae9cee5e2fec8929697b0606b655c45b10a65bcd641da315e98c48e1e
-size 20951
+oid sha256:46ad7d3a46b54543f226e82fa4199e2e2de7e2e91748d663bed88dfb7afc5b61
+size 21350
diff --git a/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.location.impl.send_null_DefaultGroup_SendLocationViewPreview-N-0_2_null_0,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.location.impl.send_null_DefaultGroup_SendLocationViewPreview-N-0_2_null_0,NEXUS_5,1.0,en].png
index 643983770c..49bfbea7e2 100644
--- a/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.location.impl.send_null_DefaultGroup_SendLocationViewPreview-N-0_2_null_0,NEXUS_5,1.0,en].png
+++ b/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.location.impl.send_null_DefaultGroup_SendLocationViewPreview-N-0_2_null_0,NEXUS_5,1.0,en].png
@@ -1,3 +1,3 @@
 version https://git-lfs.github.com/spec/v1
-oid sha256:ce74fa2b0364763152e69dcfa4f8d598504b630fa1227f2fa685bc886ccd5afa
-size 19434
+oid sha256:6fb273e816484cb326ea4ba00948e749362542c1b964e23c5dc48b306b909136
+size 19843
diff --git a/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.location.impl.send_null_DefaultGroup_SendLocationViewPreview-N-0_2_null_1,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.location.impl.send_null_DefaultGroup_SendLocationViewPreview-N-0_2_null_1,NEXUS_5,1.0,en].png
index 173360baef..7259132ad6 100644
--- a/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.location.impl.send_null_DefaultGroup_SendLocationViewPreview-N-0_2_null_1,NEXUS_5,1.0,en].png
+++ b/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.location.impl.send_null_DefaultGroup_SendLocationViewPreview-N-0_2_null_1,NEXUS_5,1.0,en].png
@@ -1,3 +1,3 @@
 version https://git-lfs.github.com/spec/v1
-oid sha256:12a78fbc2d2e84e93d40d1e075d8b46c5366f3d323dd85f27be286a64231f884
-size 32120
+oid sha256:3cb01d6f6f798c3cf2528db2b6d974b1007a7520ade43370082a1479365c41a7
+size 34934
diff --git a/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.location.impl.send_null_DefaultGroup_SendLocationViewPreview-N-0_2_null_2,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.location.impl.send_null_DefaultGroup_SendLocationViewPreview-N-0_2_null_2,NEXUS_5,1.0,en].png
index 0fa0b9c5d2..c9f3716e82 100644
--- a/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.location.impl.send_null_DefaultGroup_SendLocationViewPreview-N-0_2_null_2,NEXUS_5,1.0,en].png
+++ b/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.location.impl.send_null_DefaultGroup_SendLocationViewPreview-N-0_2_null_2,NEXUS_5,1.0,en].png
@@ -1,3 +1,3 @@
 version https://git-lfs.github.com/spec/v1
-oid sha256:a1bd4187a3713153d6e9ed94594385c3806f59c4d36cc6f2867a38d630551505
-size 31302
+oid sha256:8862e4c3a185ffe807c1357c6a24aac4a9d6eac6405a73aa24b4772de67170dd
+size 33419
diff --git a/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.location.impl.send_null_DefaultGroup_SendLocationViewPreview-N-0_2_null_3,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.location.impl.send_null_DefaultGroup_SendLocationViewPreview-N-0_2_null_3,NEXUS_5,1.0,en].png
index 643983770c..49bfbea7e2 100644
--- a/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.location.impl.send_null_DefaultGroup_SendLocationViewPreview-N-0_2_null_3,NEXUS_5,1.0,en].png
+++ b/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.location.impl.send_null_DefaultGroup_SendLocationViewPreview-N-0_2_null_3,NEXUS_5,1.0,en].png
@@ -1,3 +1,3 @@
 version https://git-lfs.github.com/spec/v1
-oid sha256:ce74fa2b0364763152e69dcfa4f8d598504b630fa1227f2fa685bc886ccd5afa
-size 19434
+oid sha256:6fb273e816484cb326ea4ba00948e749362542c1b964e23c5dc48b306b909136
+size 19843
diff --git a/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.location.impl.send_null_DefaultGroup_SendLocationViewPreview-N-0_2_null_4,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.location.impl.send_null_DefaultGroup_SendLocationViewPreview-N-0_2_null_4,NEXUS_5,1.0,en].png
index ce8b5bf468..652c6b6492 100644
--- a/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.location.impl.send_null_DefaultGroup_SendLocationViewPreview-N-0_2_null_4,NEXUS_5,1.0,en].png
+++ b/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.location.impl.send_null_DefaultGroup_SendLocationViewPreview-N-0_2_null_4,NEXUS_5,1.0,en].png
@@ -1,3 +1,3 @@
 version https://git-lfs.github.com/spec/v1
-oid sha256:9390a3b8111ab0d31b3bbf3b6bf8794432d135130b37404ce4a646a74369d85b
-size 19502
+oid sha256:91378a7a126d1d9f9f234368930635ce85db3666721dc32b0646effa59d0fdee
+size 19991
diff --git a/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.location.impl.show_null_DefaultGroup_ShowLocationViewDarkPreview_0_null_0,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.location.impl.show_null_DefaultGroup_ShowLocationViewDarkPreview_0_null_0,NEXUS_5,1.0,en].png
index 5eb7294406..8bcbbee378 100644
--- a/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.location.impl.show_null_DefaultGroup_ShowLocationViewDarkPreview_0_null_0,NEXUS_5,1.0,en].png
+++ b/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.location.impl.show_null_DefaultGroup_ShowLocationViewDarkPreview_0_null_0,NEXUS_5,1.0,en].png
@@ -1,3 +1,3 @@
 version https://git-lfs.github.com/spec/v1
-oid sha256:364f107ffaa4844d0141361642ce3a494a187588f27be50b5fd27d44be21fa64
-size 8887
+oid sha256:016ca2c634b467ba6d98ed221506d5bbb250b58a5ea631a0076a572f745cfa84
+size 8710
diff --git a/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.location.impl.show_null_DefaultGroup_ShowLocationViewDarkPreview_0_null_1,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.location.impl.show_null_DefaultGroup_ShowLocationViewDarkPreview_0_null_1,NEXUS_5,1.0,en].png
index f317c61b6e..50577b4cbf 100644
--- a/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.location.impl.show_null_DefaultGroup_ShowLocationViewDarkPreview_0_null_1,NEXUS_5,1.0,en].png
+++ b/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.location.impl.show_null_DefaultGroup_ShowLocationViewDarkPreview_0_null_1,NEXUS_5,1.0,en].png
@@ -1,3 +1,3 @@
 version https://git-lfs.github.com/spec/v1
-oid sha256:8d0a5de3c4e09d76b6453ccc6ace5c690d540d945a62e630474932734209058a
-size 11716
+oid sha256:c129a4d13320fb3fec6039e37c802de33d7dd607faa3890f9f1b34f663eecc46
+size 11552
diff --git a/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.location.impl.show_null_DefaultGroup_ShowLocationViewDarkPreview_0_null_2,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.location.impl.show_null_DefaultGroup_ShowLocationViewDarkPreview_0_null_2,NEXUS_5,1.0,en].png
index 34c2f19861..6ace5373a3 100644
--- a/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.location.impl.show_null_DefaultGroup_ShowLocationViewDarkPreview_0_null_2,NEXUS_5,1.0,en].png
+++ b/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.location.impl.show_null_DefaultGroup_ShowLocationViewDarkPreview_0_null_2,NEXUS_5,1.0,en].png
@@ -1,3 +1,3 @@
 version https://git-lfs.github.com/spec/v1
-oid sha256:9218d1d514342c400051bebb10ef458c99103fda618bba45e61a524c5a58eb63
-size 11903
+oid sha256:abe3498282504f7b0bfa3a2713ea556b7d4d361d5173ea56bcdadb37766d0b93
+size 11742
diff --git a/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.location.impl.show_null_DefaultGroup_ShowLocationViewDarkPreview_0_null_3,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.location.impl.show_null_DefaultGroup_ShowLocationViewDarkPreview_0_null_3,NEXUS_5,1.0,en].png
index 471e59a5b0..209d16749b 100644
--- a/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.location.impl.show_null_DefaultGroup_ShowLocationViewDarkPreview_0_null_3,NEXUS_5,1.0,en].png
+++ b/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.location.impl.show_null_DefaultGroup_ShowLocationViewDarkPreview_0_null_3,NEXUS_5,1.0,en].png
@@ -1,3 +1,3 @@
 version https://git-lfs.github.com/spec/v1
-oid sha256:f19878925f3b5b377a91885540fb15d29a5b78d8be2282d64e8809af0bbf5ff4
-size 12195
+oid sha256:d52d7c6d6271577c80ad1ca170aeb9686d8bb572459212d6ef1fe97c490b382d
+size 12035
diff --git a/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.location.impl.show_null_DefaultGroup_ShowLocationViewDarkPreview_0_null_4,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.location.impl.show_null_DefaultGroup_ShowLocationViewDarkPreview_0_null_4,NEXUS_5,1.0,en].png
index b56214c49f..1e5b0e65de 100644
--- a/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.location.impl.show_null_DefaultGroup_ShowLocationViewDarkPreview_0_null_4,NEXUS_5,1.0,en].png
+++ b/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.location.impl.show_null_DefaultGroup_ShowLocationViewDarkPreview_0_null_4,NEXUS_5,1.0,en].png
@@ -1,3 +1,3 @@
 version https://git-lfs.github.com/spec/v1
-oid sha256:c936d2d804bc9e98fcc49430f11ddaa572b05fc8d3a0df93ad6521ee8e78f708
-size 21806
+oid sha256:3e6442ca746462345d0573abfb72028a613b08d53f6a5e3f0ef3c5f09beab423
+size 19491
diff --git a/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.location.impl.show_null_DefaultGroup_ShowLocationViewDarkPreview_0_null_5,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.location.impl.show_null_DefaultGroup_ShowLocationViewDarkPreview_0_null_5,NEXUS_5,1.0,en].png
new file mode 100644
index 0000000000..6c5d1f2553
--- /dev/null
+++ b/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.location.impl.show_null_DefaultGroup_ShowLocationViewDarkPreview_0_null_5,NEXUS_5,1.0,en].png
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:906b39149036cccadd5232c0373a6a94e039b374988ace3d732a5b63b7d81829
+size 21590
diff --git a/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.location.impl.show_null_DefaultGroup_ShowLocationViewLightPreview_0_null_0,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.location.impl.show_null_DefaultGroup_ShowLocationViewLightPreview_0_null_0,NEXUS_5,1.0,en].png
index ea8bf3f1bd..d25793cf30 100644
--- a/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.location.impl.show_null_DefaultGroup_ShowLocationViewLightPreview_0_null_0,NEXUS_5,1.0,en].png
+++ b/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.location.impl.show_null_DefaultGroup_ShowLocationViewLightPreview_0_null_0,NEXUS_5,1.0,en].png
@@ -1,3 +1,3 @@
 version https://git-lfs.github.com/spec/v1
-oid sha256:ac01bc1992e3fa27950c7071cd3e8a06b94a608238d55972816fa2a1a3175e7c
-size 9448
+oid sha256:545fcfe023789a167a5ee2fe11e7f65426890d794fa08ed32ea4e9fe0fe5f59a
+size 9387
diff --git a/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.location.impl.show_null_DefaultGroup_ShowLocationViewLightPreview_0_null_1,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.location.impl.show_null_DefaultGroup_ShowLocationViewLightPreview_0_null_1,NEXUS_5,1.0,en].png
index 342978d4f7..bf88ad0eee 100644
--- a/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.location.impl.show_null_DefaultGroup_ShowLocationViewLightPreview_0_null_1,NEXUS_5,1.0,en].png
+++ b/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.location.impl.show_null_DefaultGroup_ShowLocationViewLightPreview_0_null_1,NEXUS_5,1.0,en].png
@@ -1,3 +1,3 @@
 version https://git-lfs.github.com/spec/v1
-oid sha256:e39c5ba30983b034886a6adc330d1510b3a48c40511697edcaf6530716c7ba2e
-size 12500
+oid sha256:b7ebe27e257108881e4869213ea754926fceb8a047ccb81120fc1a1df19279f4
+size 12444
diff --git a/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.location.impl.show_null_DefaultGroup_ShowLocationViewLightPreview_0_null_2,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.location.impl.show_null_DefaultGroup_ShowLocationViewLightPreview_0_null_2,NEXUS_5,1.0,en].png
index c1fa61a838..2332b90a7e 100644
--- a/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.location.impl.show_null_DefaultGroup_ShowLocationViewLightPreview_0_null_2,NEXUS_5,1.0,en].png
+++ b/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.location.impl.show_null_DefaultGroup_ShowLocationViewLightPreview_0_null_2,NEXUS_5,1.0,en].png
@@ -1,3 +1,3 @@
 version https://git-lfs.github.com/spec/v1
-oid sha256:e4ff75e74c19280308878e3001a8791aaa735439cc667946fefd21070611630e
-size 12698
+oid sha256:ecb0ec0f6b9bffc5cd0ab19f85beb962610d5624652b8e6f21d8aedda69a0fb4
+size 12645
diff --git a/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.location.impl.show_null_DefaultGroup_ShowLocationViewLightPreview_0_null_3,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.location.impl.show_null_DefaultGroup_ShowLocationViewLightPreview_0_null_3,NEXUS_5,1.0,en].png
index 8ecfebb614..05ba2a726c 100644
--- a/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.location.impl.show_null_DefaultGroup_ShowLocationViewLightPreview_0_null_3,NEXUS_5,1.0,en].png
+++ b/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.location.impl.show_null_DefaultGroup_ShowLocationViewLightPreview_0_null_3,NEXUS_5,1.0,en].png
@@ -1,3 +1,3 @@
 version https://git-lfs.github.com/spec/v1
-oid sha256:065d2a09680e35540b870862ec0ba5c54182e016017938ef64e510b6132333c9
-size 13389
+oid sha256:989b630c0925f0a822b2b7460648e874357e1ecf0ab75caea56c78189d936349
+size 13329
diff --git a/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.location.impl.show_null_DefaultGroup_ShowLocationViewLightPreview_0_null_4,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.location.impl.show_null_DefaultGroup_ShowLocationViewLightPreview_0_null_4,NEXUS_5,1.0,en].png
index 7701a371c3..61448871c3 100644
--- a/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.location.impl.show_null_DefaultGroup_ShowLocationViewLightPreview_0_null_4,NEXUS_5,1.0,en].png
+++ b/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.location.impl.show_null_DefaultGroup_ShowLocationViewLightPreview_0_null_4,NEXUS_5,1.0,en].png
@@ -1,3 +1,3 @@
 version https://git-lfs.github.com/spec/v1
-oid sha256:0bb88c64bc68b10b1fb709135f445de5a5e4d78623448d0fef97504e025d5f6d
-size 24551
+oid sha256:caa94ed925e37306cc9453a5ade0266a897dc010cdde86b92a9e1d4710039edc
+size 22184
diff --git a/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.location.impl.show_null_DefaultGroup_ShowLocationViewLightPreview_0_null_5,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.location.impl.show_null_DefaultGroup_ShowLocationViewLightPreview_0_null_5,NEXUS_5,1.0,en].png
new file mode 100644
index 0000000000..c405ee9fea
--- /dev/null
+++ b/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.location.impl.show_null_DefaultGroup_ShowLocationViewLightPreview_0_null_5,NEXUS_5,1.0,en].png
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:6d9458392de2e0f291f752a8cd9558c9eb891d4140e07c5c61a42a16a3c77838
+size 24507
diff --git a/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.login.impl.screens.confirmaccountprovider_null_DefaultGroup_ConfirmAccountProviderViewDarkPreview_0_null_0,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.login.impl.screens.confirmaccountprovider_null_DefaultGroup_ConfirmAccountProviderViewDarkPreview_0_null_0,NEXUS_5,1.0,en].png
index 363280c1fa..b1ae254500 100644
--- a/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.login.impl.screens.confirmaccountprovider_null_DefaultGroup_ConfirmAccountProviderViewDarkPreview_0_null_0,NEXUS_5,1.0,en].png
+++ b/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.login.impl.screens.confirmaccountprovider_null_DefaultGroup_ConfirmAccountProviderViewDarkPreview_0_null_0,NEXUS_5,1.0,en].png
@@ -1,3 +1,3 @@
 version https://git-lfs.github.com/spec/v1
-oid sha256:52a5e65b23072ccfdc7220daca437e93342c04cee91cd971ba8d13872968ae7d
-size 36962
+oid sha256:c9fb80a007891ceba86d3cdf7711ba3a8d585358fea9558a0c451f67de58b94b
+size 37346
diff --git a/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.login.impl.screens.confirmaccountprovider_null_DefaultGroup_ConfirmAccountProviderViewLightPreview_0_null_0,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.login.impl.screens.confirmaccountprovider_null_DefaultGroup_ConfirmAccountProviderViewLightPreview_0_null_0,NEXUS_5,1.0,en].png
index 232ce0d49c..9f053deea5 100644
--- a/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.login.impl.screens.confirmaccountprovider_null_DefaultGroup_ConfirmAccountProviderViewLightPreview_0_null_0,NEXUS_5,1.0,en].png
+++ b/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.login.impl.screens.confirmaccountprovider_null_DefaultGroup_ConfirmAccountProviderViewLightPreview_0_null_0,NEXUS_5,1.0,en].png
@@ -1,3 +1,3 @@
 version https://git-lfs.github.com/spec/v1
-oid sha256:ea4a9e4b5488e925652ff747997dcbb58c55dd126c7b81f5222c30291270d7e6
-size 39147
+oid sha256:c9b3fcd78615bb01e7d6c044519a835222a5791547aa0c99a6bb7dc0a0ec72d4
+size 39687
diff --git a/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.login.impl.screens.loginpassword_null_DefaultGroup_LoginPasswordViewDarkPreview_0_null_0,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.login.impl.screens.loginpassword_null_DefaultGroup_LoginPasswordViewDarkPreview_0_null_0,NEXUS_5,1.0,en].png
index 79c5d3efd4..73636beab6 100644
--- a/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.login.impl.screens.loginpassword_null_DefaultGroup_LoginPasswordViewDarkPreview_0_null_0,NEXUS_5,1.0,en].png
+++ b/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.login.impl.screens.loginpassword_null_DefaultGroup_LoginPasswordViewDarkPreview_0_null_0,NEXUS_5,1.0,en].png
@@ -1,3 +1,3 @@
 version https://git-lfs.github.com/spec/v1
-oid sha256:7c60ca1b2273df93b927550e51d69f2b3a2b59f5060e0794b1cc7dbaa432dc51
-size 36879
+oid sha256:12ce43111318a2d77ea2dd878afb2dc8f668bb976b2a7367b732a0a5c86e71a3
+size 37168
diff --git a/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.login.impl.screens.loginpassword_null_DefaultGroup_LoginPasswordViewDarkPreview_0_null_1,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.login.impl.screens.loginpassword_null_DefaultGroup_LoginPasswordViewDarkPreview_0_null_1,NEXUS_5,1.0,en].png
index 3444da12ca..1077e0866b 100644
--- a/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.login.impl.screens.loginpassword_null_DefaultGroup_LoginPasswordViewDarkPreview_0_null_1,NEXUS_5,1.0,en].png
+++ b/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.login.impl.screens.loginpassword_null_DefaultGroup_LoginPasswordViewDarkPreview_0_null_1,NEXUS_5,1.0,en].png
@@ -1,3 +1,3 @@
 version https://git-lfs.github.com/spec/v1
-oid sha256:a47d3a323db2c60d2825eccbc28b2df21ff7c5f2f2da86e27c61059493b18f70
-size 38074
+oid sha256:d7702e2ac4263ad23d209bce8ad6fce2a7ba3f4ca20f47c7585ff7e6e0965eed
+size 38169
diff --git a/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.login.impl.screens.loginpassword_null_DefaultGroup_LoginPasswordViewDarkPreview_0_null_2,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.login.impl.screens.loginpassword_null_DefaultGroup_LoginPasswordViewDarkPreview_0_null_2,NEXUS_5,1.0,en].png
index 79c5d3efd4..73636beab6 100644
--- a/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.login.impl.screens.loginpassword_null_DefaultGroup_LoginPasswordViewDarkPreview_0_null_2,NEXUS_5,1.0,en].png
+++ b/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.login.impl.screens.loginpassword_null_DefaultGroup_LoginPasswordViewDarkPreview_0_null_2,NEXUS_5,1.0,en].png
@@ -1,3 +1,3 @@
 version https://git-lfs.github.com/spec/v1
-oid sha256:7c60ca1b2273df93b927550e51d69f2b3a2b59f5060e0794b1cc7dbaa432dc51
-size 36879
+oid sha256:12ce43111318a2d77ea2dd878afb2dc8f668bb976b2a7367b732a0a5c86e71a3
+size 37168
diff --git a/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.login.impl.screens.loginpassword_null_DefaultGroup_LoginPasswordViewLightPreview_0_null_0,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.login.impl.screens.loginpassword_null_DefaultGroup_LoginPasswordViewLightPreview_0_null_0,NEXUS_5,1.0,en].png
index e9acc8b13b..10967a68ff 100644
--- a/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.login.impl.screens.loginpassword_null_DefaultGroup_LoginPasswordViewLightPreview_0_null_0,NEXUS_5,1.0,en].png
+++ b/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.login.impl.screens.loginpassword_null_DefaultGroup_LoginPasswordViewLightPreview_0_null_0,NEXUS_5,1.0,en].png
@@ -1,3 +1,3 @@
 version https://git-lfs.github.com/spec/v1
-oid sha256:4c26b06e09a81b2990a7505b70a3bf2647e508d631e9fc65ee0a37364c685808
-size 38928
+oid sha256:7f133c65e9857599199920927e526d1c3a89b6eea0bbae6d3951f858de11530b
+size 39119
diff --git a/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.login.impl.screens.loginpassword_null_DefaultGroup_LoginPasswordViewLightPreview_0_null_1,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.login.impl.screens.loginpassword_null_DefaultGroup_LoginPasswordViewLightPreview_0_null_1,NEXUS_5,1.0,en].png
index b79bfe022e..01c9056835 100644
--- a/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.login.impl.screens.loginpassword_null_DefaultGroup_LoginPasswordViewLightPreview_0_null_1,NEXUS_5,1.0,en].png
+++ b/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.login.impl.screens.loginpassword_null_DefaultGroup_LoginPasswordViewLightPreview_0_null_1,NEXUS_5,1.0,en].png
@@ -1,3 +1,3 @@
 version https://git-lfs.github.com/spec/v1
-oid sha256:baa415403a4ecac05895381608a24844b5c6f90c561f561668c55fe821740cb8
-size 40193
+oid sha256:ad6ab5e91e5ef1ff565dda6e36c51bcd9458dba1aa99624afb63fea4f0f7f1d7
+size 40259
diff --git a/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.login.impl.screens.loginpassword_null_DefaultGroup_LoginPasswordViewLightPreview_0_null_2,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.login.impl.screens.loginpassword_null_DefaultGroup_LoginPasswordViewLightPreview_0_null_2,NEXUS_5,1.0,en].png
index e9acc8b13b..10967a68ff 100644
--- a/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.login.impl.screens.loginpassword_null_DefaultGroup_LoginPasswordViewLightPreview_0_null_2,NEXUS_5,1.0,en].png
+++ b/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.login.impl.screens.loginpassword_null_DefaultGroup_LoginPasswordViewLightPreview_0_null_2,NEXUS_5,1.0,en].png
@@ -1,3 +1,3 @@
 version https://git-lfs.github.com/spec/v1
-oid sha256:4c26b06e09a81b2990a7505b70a3bf2647e508d631e9fc65ee0a37364c685808
-size 38928
+oid sha256:7f133c65e9857599199920927e526d1c3a89b6eea0bbae6d3951f858de11530b
+size 39119
diff --git a/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.login.impl.screens.waitlistscreen_null_DefaultGroup_WaitListViewDarkPreview_0_null_0,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.login.impl.screens.waitlistscreen_null_DefaultGroup_WaitListViewDarkPreview_0_null_0,NEXUS_5,1.0,en].png
index 6b5e4c405f..d3dc127f68 100644
--- a/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.login.impl.screens.waitlistscreen_null_DefaultGroup_WaitListViewDarkPreview_0_null_0,NEXUS_5,1.0,en].png
+++ b/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.login.impl.screens.waitlistscreen_null_DefaultGroup_WaitListViewDarkPreview_0_null_0,NEXUS_5,1.0,en].png
@@ -1,3 +1,3 @@
 version https://git-lfs.github.com/spec/v1
-oid sha256:e97d88bef72c332cd145dc1080a989d163478c0252a9993f2f474bd51f2e4da8
-size 148762
+oid sha256:d40dd7970069fb798b738a1775b5843522cc28a581d904f44974d7ceefdbf3c9
+size 148087
diff --git a/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.login.impl.screens.waitlistscreen_null_DefaultGroup_WaitListViewDarkPreview_0_null_1,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.login.impl.screens.waitlistscreen_null_DefaultGroup_WaitListViewDarkPreview_0_null_1,NEXUS_5,1.0,en].png
index 151e09cfc0..8227daecf3 100644
--- a/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.login.impl.screens.waitlistscreen_null_DefaultGroup_WaitListViewDarkPreview_0_null_1,NEXUS_5,1.0,en].png
+++ b/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.login.impl.screens.waitlistscreen_null_DefaultGroup_WaitListViewDarkPreview_0_null_1,NEXUS_5,1.0,en].png
@@ -1,3 +1,3 @@
 version https://git-lfs.github.com/spec/v1
-oid sha256:e8edd6d72db9efaaed76ac64f9882a5b66ac30747355815955157a3f3fc98c2c
-size 149344
+oid sha256:47f20f3dc4e4bdbb6641f26b6e03d0dba0f2c7e0fe22fce927870d14f1472066
+size 148796
diff --git a/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.login.impl.screens.waitlistscreen_null_DefaultGroup_WaitListViewDarkPreview_0_null_2,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.login.impl.screens.waitlistscreen_null_DefaultGroup_WaitListViewDarkPreview_0_null_2,NEXUS_5,1.0,en].png
index 847b4e1273..b729e6d346 100644
--- a/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.login.impl.screens.waitlistscreen_null_DefaultGroup_WaitListViewDarkPreview_0_null_2,NEXUS_5,1.0,en].png
+++ b/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.login.impl.screens.waitlistscreen_null_DefaultGroup_WaitListViewDarkPreview_0_null_2,NEXUS_5,1.0,en].png
@@ -1,3 +1,3 @@
 version https://git-lfs.github.com/spec/v1
-oid sha256:2cb81f2228ad63ff38bb6abe44c305adc66378bf85d36264219427be58ac58e3
-size 63343
+oid sha256:71b2a1c6dba0b373e2abfe77e8327ac2e95c7286eeb53f83e5d802d10bbff96f
+size 64975
diff --git a/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.login.impl.screens.waitlistscreen_null_DefaultGroup_WaitListViewDarkPreview_0_null_3,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.login.impl.screens.waitlistscreen_null_DefaultGroup_WaitListViewDarkPreview_0_null_3,NEXUS_5,1.0,en].png
index 6b5e4c405f..d3dc127f68 100644
--- a/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.login.impl.screens.waitlistscreen_null_DefaultGroup_WaitListViewDarkPreview_0_null_3,NEXUS_5,1.0,en].png
+++ b/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.login.impl.screens.waitlistscreen_null_DefaultGroup_WaitListViewDarkPreview_0_null_3,NEXUS_5,1.0,en].png
@@ -1,3 +1,3 @@
 version https://git-lfs.github.com/spec/v1
-oid sha256:e97d88bef72c332cd145dc1080a989d163478c0252a9993f2f474bd51f2e4da8
-size 148762
+oid sha256:d40dd7970069fb798b738a1775b5843522cc28a581d904f44974d7ceefdbf3c9
+size 148087
diff --git a/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.login.impl.screens.waitlistscreen_null_DefaultGroup_WaitListViewDarkPreview_0_null_4,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.login.impl.screens.waitlistscreen_null_DefaultGroup_WaitListViewDarkPreview_0_null_4,NEXUS_5,1.0,en].png
index 822450c8af..56757c755b 100644
--- a/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.login.impl.screens.waitlistscreen_null_DefaultGroup_WaitListViewDarkPreview_0_null_4,NEXUS_5,1.0,en].png
+++ b/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.login.impl.screens.waitlistscreen_null_DefaultGroup_WaitListViewDarkPreview_0_null_4,NEXUS_5,1.0,en].png
@@ -1,3 +1,3 @@
 version https://git-lfs.github.com/spec/v1
-oid sha256:85222447b700315e6eea458fc72d61fb741018cb80c3a4530d4efc08ac9335ac
-size 129373
+oid sha256:74b7fa3ce27045b0349950e976c424a155ca5aef680a58789877cdf7a7e9a32d
+size 128877
diff --git a/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.login.impl.screens.waitlistscreen_null_DefaultGroup_WaitListViewLightPreview_0_null_0,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.login.impl.screens.waitlistscreen_null_DefaultGroup_WaitListViewLightPreview_0_null_0,NEXUS_5,1.0,en].png
index 6b5e4c405f..64c7da001e 100644
--- a/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.login.impl.screens.waitlistscreen_null_DefaultGroup_WaitListViewLightPreview_0_null_0,NEXUS_5,1.0,en].png
+++ b/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.login.impl.screens.waitlistscreen_null_DefaultGroup_WaitListViewLightPreview_0_null_0,NEXUS_5,1.0,en].png
@@ -1,3 +1,3 @@
 version https://git-lfs.github.com/spec/v1
-oid sha256:e97d88bef72c332cd145dc1080a989d163478c0252a9993f2f474bd51f2e4da8
-size 148762
+oid sha256:cafa0bf978a59ff5903429bcb605afd2cb347bb64c3d58e749b0dd7ddfca6199
+size 148827
diff --git a/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.login.impl.screens.waitlistscreen_null_DefaultGroup_WaitListViewLightPreview_0_null_1,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.login.impl.screens.waitlistscreen_null_DefaultGroup_WaitListViewLightPreview_0_null_1,NEXUS_5,1.0,en].png
index 151e09cfc0..dd99c63f05 100644
--- a/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.login.impl.screens.waitlistscreen_null_DefaultGroup_WaitListViewLightPreview_0_null_1,NEXUS_5,1.0,en].png
+++ b/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.login.impl.screens.waitlistscreen_null_DefaultGroup_WaitListViewLightPreview_0_null_1,NEXUS_5,1.0,en].png
@@ -1,3 +1,3 @@
 version https://git-lfs.github.com/spec/v1
-oid sha256:e8edd6d72db9efaaed76ac64f9882a5b66ac30747355815955157a3f3fc98c2c
-size 149344
+oid sha256:a19c6af3352ad430c6502ccc9dac1ae8b4b8d690c810ab424c61208fa31e52b0
+size 149411
diff --git a/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.login.impl.screens.waitlistscreen_null_DefaultGroup_WaitListViewLightPreview_0_null_2,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.login.impl.screens.waitlistscreen_null_DefaultGroup_WaitListViewLightPreview_0_null_2,NEXUS_5,1.0,en].png
index 13ea2accd4..8a7a211694 100644
--- a/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.login.impl.screens.waitlistscreen_null_DefaultGroup_WaitListViewLightPreview_0_null_2,NEXUS_5,1.0,en].png
+++ b/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.login.impl.screens.waitlistscreen_null_DefaultGroup_WaitListViewLightPreview_0_null_2,NEXUS_5,1.0,en].png
@@ -1,3 +1,3 @@
 version https://git-lfs.github.com/spec/v1
-oid sha256:d48708d932ca9111f74d75654663e66a5eba1b419130ca3f00f0d6f997f119b9
-size 64166
+oid sha256:852b7b5515cad1bb129273ba95fc528f9cc67bf4dde0995276a96521c4399cbe
+size 66851
diff --git a/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.login.impl.screens.waitlistscreen_null_DefaultGroup_WaitListViewLightPreview_0_null_3,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.login.impl.screens.waitlistscreen_null_DefaultGroup_WaitListViewLightPreview_0_null_3,NEXUS_5,1.0,en].png
index 6b5e4c405f..64c7da001e 100644
--- a/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.login.impl.screens.waitlistscreen_null_DefaultGroup_WaitListViewLightPreview_0_null_3,NEXUS_5,1.0,en].png
+++ b/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.login.impl.screens.waitlistscreen_null_DefaultGroup_WaitListViewLightPreview_0_null_3,NEXUS_5,1.0,en].png
@@ -1,3 +1,3 @@
 version https://git-lfs.github.com/spec/v1
-oid sha256:e97d88bef72c332cd145dc1080a989d163478c0252a9993f2f474bd51f2e4da8
-size 148762
+oid sha256:cafa0bf978a59ff5903429bcb605afd2cb347bb64c3d58e749b0dd7ddfca6199
+size 148827
diff --git a/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.login.impl.screens.waitlistscreen_null_DefaultGroup_WaitListViewLightPreview_0_null_4,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.login.impl.screens.waitlistscreen_null_DefaultGroup_WaitListViewLightPreview_0_null_4,NEXUS_5,1.0,en].png
index 822450c8af..56757c755b 100644
--- a/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.login.impl.screens.waitlistscreen_null_DefaultGroup_WaitListViewLightPreview_0_null_4,NEXUS_5,1.0,en].png
+++ b/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.login.impl.screens.waitlistscreen_null_DefaultGroup_WaitListViewLightPreview_0_null_4,NEXUS_5,1.0,en].png
@@ -1,3 +1,3 @@
 version https://git-lfs.github.com/spec/v1
-oid sha256:85222447b700315e6eea458fc72d61fb741018cb80c3a4530d4efc08ac9335ac
-size 129373
+oid sha256:74b7fa3ce27045b0349950e976c424a155ca5aef680a58789877cdf7a7e9a32d
+size 128877
diff --git a/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.messages.impl.actionlist_null_DefaultGroup_SheetContentPreview-D-0_1_null_2,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.messages.impl.actionlist_null_DefaultGroup_SheetContentPreview-D-0_1_null_2,NEXUS_5,1.0,en].png
index 40cbe16de5..a72d4958d8 100644
--- a/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.messages.impl.actionlist_null_DefaultGroup_SheetContentPreview-D-0_1_null_2,NEXUS_5,1.0,en].png
+++ b/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.messages.impl.actionlist_null_DefaultGroup_SheetContentPreview-D-0_1_null_2,NEXUS_5,1.0,en].png
@@ -1,3 +1,3 @@
 version https://git-lfs.github.com/spec/v1
-oid sha256:e635091747a867b0acbaac27225bb4a5c6e77a3b63005a03e80244425bffc839
-size 40314
+oid sha256:62e7ab953183e59348f5229dd398c6ffeeb7b60bffec9197139c58cfb335825c
+size 38257
diff --git a/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.messages.impl.actionlist_null_DefaultGroup_SheetContentPreview-D-0_1_null_3,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.messages.impl.actionlist_null_DefaultGroup_SheetContentPreview-D-0_1_null_3,NEXUS_5,1.0,en].png
index cdb2102b99..b755ac33c2 100644
--- a/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.messages.impl.actionlist_null_DefaultGroup_SheetContentPreview-D-0_1_null_3,NEXUS_5,1.0,en].png
+++ b/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.messages.impl.actionlist_null_DefaultGroup_SheetContentPreview-D-0_1_null_3,NEXUS_5,1.0,en].png
@@ -1,3 +1,3 @@
 version https://git-lfs.github.com/spec/v1
-oid sha256:0b68e89219ad178eb4a4854d8a0800975628b098aea016ea74d3f9e3e6790363
-size 46990
+oid sha256:3d4e87ee1dceb9c0d9c464d3db5433e849eaafde2e6241ea00a72f7abc5ba971
+size 44852
diff --git a/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.messages.impl.actionlist_null_DefaultGroup_SheetContentPreview-D-0_1_null_4,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.messages.impl.actionlist_null_DefaultGroup_SheetContentPreview-D-0_1_null_4,NEXUS_5,1.0,en].png
index f9c5109ceb..0fce5968de 100644
--- a/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.messages.impl.actionlist_null_DefaultGroup_SheetContentPreview-D-0_1_null_4,NEXUS_5,1.0,en].png
+++ b/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.messages.impl.actionlist_null_DefaultGroup_SheetContentPreview-D-0_1_null_4,NEXUS_5,1.0,en].png
@@ -1,3 +1,3 @@
 version https://git-lfs.github.com/spec/v1
-oid sha256:e456ca95ee33cf14cac839b2b57879d17ca47b156da65c8a870882a90ef2c84c
-size 40664
+oid sha256:f54a07228afae0a4e03f824438fef9ac498551adc4740aca8bce0f79d7b5085e
+size 38626
diff --git a/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.messages.impl.actionlist_null_DefaultGroup_SheetContentPreview-D-0_1_null_5,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.messages.impl.actionlist_null_DefaultGroup_SheetContentPreview-D-0_1_null_5,NEXUS_5,1.0,en].png
index b0937d3b09..542d0d8682 100644
--- a/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.messages.impl.actionlist_null_DefaultGroup_SheetContentPreview-D-0_1_null_5,NEXUS_5,1.0,en].png
+++ b/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.messages.impl.actionlist_null_DefaultGroup_SheetContentPreview-D-0_1_null_5,NEXUS_5,1.0,en].png
@@ -1,3 +1,3 @@
 version https://git-lfs.github.com/spec/v1
-oid sha256:e4bcce9d53c7c094698f07de6c6a25be2c7831707581861df4b0cdf0c3d6d1fd
-size 40906
+oid sha256:cabf78c9278e2edcca8dac55f9bae26b38bf7a7be12e2ee5094922c2d0edc113
+size 38876
diff --git a/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.messages.impl.actionlist_null_DefaultGroup_SheetContentPreview-D-0_1_null_6,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.messages.impl.actionlist_null_DefaultGroup_SheetContentPreview-D-0_1_null_6,NEXUS_5,1.0,en].png
index e561c5d902..16ce32c2bd 100644
--- a/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.messages.impl.actionlist_null_DefaultGroup_SheetContentPreview-D-0_1_null_6,NEXUS_5,1.0,en].png
+++ b/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.messages.impl.actionlist_null_DefaultGroup_SheetContentPreview-D-0_1_null_6,NEXUS_5,1.0,en].png
@@ -1,3 +1,3 @@
 version https://git-lfs.github.com/spec/v1
-oid sha256:849d063e18b29fd54021cfd0db6088221e53179563d1c044d7a10510cfa717ee
-size 42158
+oid sha256:08d92ec4975dc62fe3b5bd332128da4b59b9f0c28bc797bb40df708ceb03fe5d
+size 40325
diff --git a/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.messages.impl.actionlist_null_DefaultGroup_SheetContentPreview-N-0_2_null_2,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.messages.impl.actionlist_null_DefaultGroup_SheetContentPreview-N-0_2_null_2,NEXUS_5,1.0,en].png
index 34754d19d9..361f1efce8 100644
--- a/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.messages.impl.actionlist_null_DefaultGroup_SheetContentPreview-N-0_2_null_2,NEXUS_5,1.0,en].png
+++ b/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.messages.impl.actionlist_null_DefaultGroup_SheetContentPreview-N-0_2_null_2,NEXUS_5,1.0,en].png
@@ -1,3 +1,3 @@
 version https://git-lfs.github.com/spec/v1
-oid sha256:0321155131e845672b07cdbec0820892acd0728770befafa07dac888a4a44fc1
-size 38836
+oid sha256:2d1b47d5457264255a631e07bb8c109f1e4a90a50b2159d9bda42e8b94fb7ed6
+size 36919
diff --git a/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.messages.impl.actionlist_null_DefaultGroup_SheetContentPreview-N-0_2_null_3,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.messages.impl.actionlist_null_DefaultGroup_SheetContentPreview-N-0_2_null_3,NEXUS_5,1.0,en].png
index 3f28eedfa0..744c2d05e6 100644
--- a/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.messages.impl.actionlist_null_DefaultGroup_SheetContentPreview-N-0_2_null_3,NEXUS_5,1.0,en].png
+++ b/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.messages.impl.actionlist_null_DefaultGroup_SheetContentPreview-N-0_2_null_3,NEXUS_5,1.0,en].png
@@ -1,3 +1,3 @@
 version https://git-lfs.github.com/spec/v1
-oid sha256:a51de9335637898863151a3a3ffa81da9a0743189c854d11ad666d81d9f2b2f8
-size 45228
+oid sha256:3d61ec70383611690046153defdaf1580ab156a97e789d4dd7db76e30f0fd29b
+size 43129
diff --git a/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.messages.impl.actionlist_null_DefaultGroup_SheetContentPreview-N-0_2_null_4,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.messages.impl.actionlist_null_DefaultGroup_SheetContentPreview-N-0_2_null_4,NEXUS_5,1.0,en].png
index 410fe4da24..19cc8a54f0 100644
--- a/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.messages.impl.actionlist_null_DefaultGroup_SheetContentPreview-N-0_2_null_4,NEXUS_5,1.0,en].png
+++ b/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.messages.impl.actionlist_null_DefaultGroup_SheetContentPreview-N-0_2_null_4,NEXUS_5,1.0,en].png
@@ -1,3 +1,3 @@
 version https://git-lfs.github.com/spec/v1
-oid sha256:66a7d55b40a9d5d7bc02f531bd3c80a1ba96e24a619c123f68549df355019558
-size 38989
+oid sha256:e7a4e6302b585ad904ebb029afa0c835383c2fa75e43e26cb3a1712caa150371
+size 37083
diff --git a/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.messages.impl.actionlist_null_DefaultGroup_SheetContentPreview-N-0_2_null_5,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.messages.impl.actionlist_null_DefaultGroup_SheetContentPreview-N-0_2_null_5,NEXUS_5,1.0,en].png
index 6cc64a9ea3..3fa174aa4b 100644
--- a/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.messages.impl.actionlist_null_DefaultGroup_SheetContentPreview-N-0_2_null_5,NEXUS_5,1.0,en].png
+++ b/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.messages.impl.actionlist_null_DefaultGroup_SheetContentPreview-N-0_2_null_5,NEXUS_5,1.0,en].png
@@ -1,3 +1,3 @@
 version https://git-lfs.github.com/spec/v1
-oid sha256:9bb3eab588d8cc20eb2bcbbcb8a7acdf6431299bf575a124ed7aff8a4fe6cd15
-size 39182
+oid sha256:5aad5fda07e4add870d0e1835d136b54fa459bfc1c113b9d36b1564d21c2a15b
+size 37252
diff --git a/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.messages.impl.actionlist_null_DefaultGroup_SheetContentPreview-N-0_2_null_6,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.messages.impl.actionlist_null_DefaultGroup_SheetContentPreview-N-0_2_null_6,NEXUS_5,1.0,en].png
index 5107c6fc5f..0a2c54c087 100644
--- a/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.messages.impl.actionlist_null_DefaultGroup_SheetContentPreview-N-0_2_null_6,NEXUS_5,1.0,en].png
+++ b/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.messages.impl.actionlist_null_DefaultGroup_SheetContentPreview-N-0_2_null_6,NEXUS_5,1.0,en].png
@@ -1,3 +1,3 @@
 version https://git-lfs.github.com/spec/v1
-oid sha256:aa5d6c7d504ab6436cfef4787a955422d9cc6b7c652ee70afedd0c6ca776d50a
-size 40651
+oid sha256:e846c3d8ab9c2fffadf60cfc6ad9d959f50bcfe14c6006c3c303c5f8171430a3
+size 38646
diff --git a/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.messages.impl.attachments.preview_null_DefaultGroup_AttachmentsPreviewViewDarkPreview_0_null_0,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.messages.impl.attachments.preview_null_DefaultGroup_AttachmentsPreviewViewDarkPreview_0_null_0,NEXUS_5,1.0,en].png
index a3c7eda016..f4eb37f23a 100644
--- a/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.messages.impl.attachments.preview_null_DefaultGroup_AttachmentsPreviewViewDarkPreview_0_null_0,NEXUS_5,1.0,en].png
+++ b/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.messages.impl.attachments.preview_null_DefaultGroup_AttachmentsPreviewViewDarkPreview_0_null_0,NEXUS_5,1.0,en].png
@@ -1,3 +1,3 @@
 version https://git-lfs.github.com/spec/v1
-oid sha256:a8e33e4ccb77ad7b3e317ee9b70360de9b0151f7391671455f0014a1a290974f
-size 395734
+oid sha256:285570b82885f1ae522c8ae79f6802028b53e76ebc08da4ee29bccc648001935
+size 396039
diff --git a/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.messages.impl.attachments.preview_null_DefaultGroup_AttachmentsPreviewViewDarkPreview_0_null_1,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.messages.impl.attachments.preview_null_DefaultGroup_AttachmentsPreviewViewDarkPreview_0_null_1,NEXUS_5,1.0,en].png
index d0e5516377..260f750e5c 100644
--- a/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.messages.impl.attachments.preview_null_DefaultGroup_AttachmentsPreviewViewDarkPreview_0_null_1,NEXUS_5,1.0,en].png
+++ b/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.messages.impl.attachments.preview_null_DefaultGroup_AttachmentsPreviewViewDarkPreview_0_null_1,NEXUS_5,1.0,en].png
@@ -1,3 +1,3 @@
 version https://git-lfs.github.com/spec/v1
-oid sha256:3b57f3a4ca9ac352fe3669a9388c85e25e91e0d54f309e9ca4f49fcb79b19527
-size 16083
+oid sha256:e8ea95bde8ba6ed5a069b2a6de2231267b6ea9a4e5d5c4a6efac166e0c563cff
+size 16388
diff --git a/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.messages.impl.attachments.preview_null_DefaultGroup_AttachmentsPreviewViewDarkPreview_0_null_2,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.messages.impl.attachments.preview_null_DefaultGroup_AttachmentsPreviewViewDarkPreview_0_null_2,NEXUS_5,1.0,en].png
index 8840b9892a..62b6486890 100644
--- a/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.messages.impl.attachments.preview_null_DefaultGroup_AttachmentsPreviewViewDarkPreview_0_null_2,NEXUS_5,1.0,en].png
+++ b/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.messages.impl.attachments.preview_null_DefaultGroup_AttachmentsPreviewViewDarkPreview_0_null_2,NEXUS_5,1.0,en].png
@@ -1,3 +1,3 @@
 version https://git-lfs.github.com/spec/v1
-oid sha256:3a968039c2fa94e89c75e395bab808d2960c37c43576b558438ec17bcd17e507
-size 184797
+oid sha256:3ce8ff927a9c9e414e2a37da8296b5a880a043d2e162f7169d58161c209adcae
+size 185108
diff --git a/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.messages.impl.attachments.preview_null_DefaultGroup_AttachmentsPreviewViewDarkPreview_0_null_3,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.messages.impl.attachments.preview_null_DefaultGroup_AttachmentsPreviewViewDarkPreview_0_null_3,NEXUS_5,1.0,en].png
index 7b19571de0..8392cf201a 100644
--- a/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.messages.impl.attachments.preview_null_DefaultGroup_AttachmentsPreviewViewDarkPreview_0_null_3,NEXUS_5,1.0,en].png
+++ b/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.messages.impl.attachments.preview_null_DefaultGroup_AttachmentsPreviewViewDarkPreview_0_null_3,NEXUS_5,1.0,en].png
@@ -1,3 +1,3 @@
 version https://git-lfs.github.com/spec/v1
-oid sha256:07da432732e812eaa091563610a3a0b490ca7f829260a5b61b4412d6c1875c8b
-size 99982
+oid sha256:3da137c4945b32fbebc70f4adb3bb2944d2f8d63aa0d30a1b10c52a9e8c233f5
+size 104677
diff --git a/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.messages.impl.forward_null_DefaultGroup_ForwardMessagesViewDarkPreview_0_null_0,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.messages.impl.forward_null_DefaultGroup_ForwardMessagesViewDarkPreview_0_null_0,NEXUS_5,1.0,en].png
index 749c81631f..80f87a5187 100644
--- a/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.messages.impl.forward_null_DefaultGroup_ForwardMessagesViewDarkPreview_0_null_0,NEXUS_5,1.0,en].png
+++ b/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.messages.impl.forward_null_DefaultGroup_ForwardMessagesViewDarkPreview_0_null_0,NEXUS_5,1.0,en].png
@@ -1,3 +1,3 @@
 version https://git-lfs.github.com/spec/v1
-oid sha256:8423bf9617b4834c42a0f0783d18c41b695cbb6e7716230a1f940b99a7b0efd9
-size 13283
+oid sha256:c479bc8fd2ba3cf33cc7a531fe31cea97df4939101f3b1f4cc200a29fa2fd2d4
+size 13736
diff --git a/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.messages.impl.forward_null_DefaultGroup_ForwardMessagesViewDarkPreview_0_null_1,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.messages.impl.forward_null_DefaultGroup_ForwardMessagesViewDarkPreview_0_null_1,NEXUS_5,1.0,en].png
index 735c9f5e32..9a1d495247 100644
--- a/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.messages.impl.forward_null_DefaultGroup_ForwardMessagesViewDarkPreview_0_null_1,NEXUS_5,1.0,en].png
+++ b/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.messages.impl.forward_null_DefaultGroup_ForwardMessagesViewDarkPreview_0_null_1,NEXUS_5,1.0,en].png
@@ -1,3 +1,3 @@
 version https://git-lfs.github.com/spec/v1
-oid sha256:4990c37241c349490619538b909e62bd76f8c49ffc3f9b7a2cf8fcaf9866bc08
-size 12852
+oid sha256:1de437e6f10abe8d703ee0596e625aa63c8f93d60c36fa7f30de9fbc53dcc60d
+size 13292
diff --git a/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.messages.impl.forward_null_DefaultGroup_ForwardMessagesViewDarkPreview_0_null_2,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.messages.impl.forward_null_DefaultGroup_ForwardMessagesViewDarkPreview_0_null_2,NEXUS_5,1.0,en].png
index 9685f02b12..0c4058c10e 100644
--- a/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.messages.impl.forward_null_DefaultGroup_ForwardMessagesViewDarkPreview_0_null_2,NEXUS_5,1.0,en].png
+++ b/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.messages.impl.forward_null_DefaultGroup_ForwardMessagesViewDarkPreview_0_null_2,NEXUS_5,1.0,en].png
@@ -1,3 +1,3 @@
 version https://git-lfs.github.com/spec/v1
-oid sha256:911217e791dc46e76b4866efc7eed59dc721795b0434f0a985078a9847347980
-size 26652
+oid sha256:a0c631199a337c8e057c2ec1c460bfb3fe2d0e078fc70d13fee96e057edc33b3
+size 26909
diff --git a/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.messages.impl.forward_null_DefaultGroup_ForwardMessagesViewDarkPreview_0_null_3,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.messages.impl.forward_null_DefaultGroup_ForwardMessagesViewDarkPreview_0_null_3,NEXUS_5,1.0,en].png
index b1f7c53c54..c065adbebf 100644
--- a/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.messages.impl.forward_null_DefaultGroup_ForwardMessagesViewDarkPreview_0_null_3,NEXUS_5,1.0,en].png
+++ b/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.messages.impl.forward_null_DefaultGroup_ForwardMessagesViewDarkPreview_0_null_3,NEXUS_5,1.0,en].png
@@ -1,3 +1,3 @@
 version https://git-lfs.github.com/spec/v1
-oid sha256:c1ccba126f5fef03ee24c6089088b2014911452a7c54eeab3caa49389b9859d3
-size 26253
+oid sha256:d170e350cce0f19d5635e59124a476cef4b4e58e723c13518f39249ca2144428
+size 26513
diff --git a/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.messages.impl.forward_null_DefaultGroup_ForwardMessagesViewDarkPreview_0_null_4,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.messages.impl.forward_null_DefaultGroup_ForwardMessagesViewDarkPreview_0_null_4,NEXUS_5,1.0,en].png
index 882791b675..62789f5fd4 100644
--- a/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.messages.impl.forward_null_DefaultGroup_ForwardMessagesViewDarkPreview_0_null_4,NEXUS_5,1.0,en].png
+++ b/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.messages.impl.forward_null_DefaultGroup_ForwardMessagesViewDarkPreview_0_null_4,NEXUS_5,1.0,en].png
@@ -1,3 +1,3 @@
 version https://git-lfs.github.com/spec/v1
-oid sha256:093b9faa97e65ad0108882964e8e8af7a980a2fdbde32d8ff83d8420cf8b6f95
-size 26425
+oid sha256:9077659f30e368e2e5f6cb78ccd1b04c03df01c14d2e94e3c4dace8554b0d2a4
+size 26502
diff --git a/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.messages.impl.forward_null_DefaultGroup_ForwardMessagesViewDarkPreview_0_null_5,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.messages.impl.forward_null_DefaultGroup_ForwardMessagesViewDarkPreview_0_null_5,NEXUS_5,1.0,en].png
index 882791b675..62789f5fd4 100644
--- a/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.messages.impl.forward_null_DefaultGroup_ForwardMessagesViewDarkPreview_0_null_5,NEXUS_5,1.0,en].png
+++ b/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.messages.impl.forward_null_DefaultGroup_ForwardMessagesViewDarkPreview_0_null_5,NEXUS_5,1.0,en].png
@@ -1,3 +1,3 @@
 version https://git-lfs.github.com/spec/v1
-oid sha256:093b9faa97e65ad0108882964e8e8af7a980a2fdbde32d8ff83d8420cf8b6f95
-size 26425
+oid sha256:9077659f30e368e2e5f6cb78ccd1b04c03df01c14d2e94e3c4dace8554b0d2a4
+size 26502
diff --git a/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.messages.impl.forward_null_DefaultGroup_ForwardMessagesViewDarkPreview_0_null_7,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.messages.impl.forward_null_DefaultGroup_ForwardMessagesViewDarkPreview_0_null_7,NEXUS_5,1.0,en].png
index 882791b675..62789f5fd4 100644
--- a/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.messages.impl.forward_null_DefaultGroup_ForwardMessagesViewDarkPreview_0_null_7,NEXUS_5,1.0,en].png
+++ b/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.messages.impl.forward_null_DefaultGroup_ForwardMessagesViewDarkPreview_0_null_7,NEXUS_5,1.0,en].png
@@ -1,3 +1,3 @@
 version https://git-lfs.github.com/spec/v1
-oid sha256:093b9faa97e65ad0108882964e8e8af7a980a2fdbde32d8ff83d8420cf8b6f95
-size 26425
+oid sha256:9077659f30e368e2e5f6cb78ccd1b04c03df01c14d2e94e3c4dace8554b0d2a4
+size 26502
diff --git a/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.messages.impl.forward_null_DefaultGroup_ForwardMessagesViewLightPreview_0_null_0,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.messages.impl.forward_null_DefaultGroup_ForwardMessagesViewLightPreview_0_null_0,NEXUS_5,1.0,en].png
index 1835595e41..806a6406be 100644
--- a/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.messages.impl.forward_null_DefaultGroup_ForwardMessagesViewLightPreview_0_null_0,NEXUS_5,1.0,en].png
+++ b/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.messages.impl.forward_null_DefaultGroup_ForwardMessagesViewLightPreview_0_null_0,NEXUS_5,1.0,en].png
@@ -1,3 +1,3 @@
 version https://git-lfs.github.com/spec/v1
-oid sha256:3c196974276b6e6e665140f5e45529d529ffa53b91ae714bbd24921e9a81c838
-size 14418
+oid sha256:7171960e43482db855e1f997d19604ca84958dd57caf35c39d8d34bd4dd803a9
+size 14791
diff --git a/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.messages.impl.forward_null_DefaultGroup_ForwardMessagesViewLightPreview_0_null_1,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.messages.impl.forward_null_DefaultGroup_ForwardMessagesViewLightPreview_0_null_1,NEXUS_5,1.0,en].png
index 01deacb825..6ed27f37fb 100644
--- a/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.messages.impl.forward_null_DefaultGroup_ForwardMessagesViewLightPreview_0_null_1,NEXUS_5,1.0,en].png
+++ b/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.messages.impl.forward_null_DefaultGroup_ForwardMessagesViewLightPreview_0_null_1,NEXUS_5,1.0,en].png
@@ -1,3 +1,3 @@
 version https://git-lfs.github.com/spec/v1
-oid sha256:1e9241a489f3d2fb93ce0b9678608418be5857a09e56b5726d1912599cc6e712
-size 13810
+oid sha256:860b7040447ebba7fcefbdf7ed33db2de3d756ca9f67000b845d547d443cd23e
+size 14185
diff --git a/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.messages.impl.forward_null_DefaultGroup_ForwardMessagesViewLightPreview_0_null_2,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.messages.impl.forward_null_DefaultGroup_ForwardMessagesViewLightPreview_0_null_2,NEXUS_5,1.0,en].png
index 80f1c30896..564db946e2 100644
--- a/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.messages.impl.forward_null_DefaultGroup_ForwardMessagesViewLightPreview_0_null_2,NEXUS_5,1.0,en].png
+++ b/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.messages.impl.forward_null_DefaultGroup_ForwardMessagesViewLightPreview_0_null_2,NEXUS_5,1.0,en].png
@@ -1,3 +1,3 @@
 version https://git-lfs.github.com/spec/v1
-oid sha256:162b68e63538b71e1b3a265281bebd7f56df3cd624caeafa94ab80d46326e2d4
-size 28162
+oid sha256:f59f7e98b77c9e4c82e1a10c24a439733bab9ba26472aa7ca13da8bb4f4052bf
+size 28694
diff --git a/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.messages.impl.forward_null_DefaultGroup_ForwardMessagesViewLightPreview_0_null_3,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.messages.impl.forward_null_DefaultGroup_ForwardMessagesViewLightPreview_0_null_3,NEXUS_5,1.0,en].png
index 099554b6c0..edbd888d35 100644
--- a/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.messages.impl.forward_null_DefaultGroup_ForwardMessagesViewLightPreview_0_null_3,NEXUS_5,1.0,en].png
+++ b/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.messages.impl.forward_null_DefaultGroup_ForwardMessagesViewLightPreview_0_null_3,NEXUS_5,1.0,en].png
@@ -1,3 +1,3 @@
 version https://git-lfs.github.com/spec/v1
-oid sha256:775effbea7088ea32b6eef036968d0be99bc267d4fdea2269d3ab1101f0ee240
-size 27542
+oid sha256:69cd17722c03402809b2a85ae18c02e3e7f934dd6526f18a40c64654a51d8d99
+size 28092
diff --git a/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.messages.impl.forward_null_DefaultGroup_ForwardMessagesViewLightPreview_0_null_4,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.messages.impl.forward_null_DefaultGroup_ForwardMessagesViewLightPreview_0_null_4,NEXUS_5,1.0,en].png
index 739e84de45..91573e4536 100644
--- a/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.messages.impl.forward_null_DefaultGroup_ForwardMessagesViewLightPreview_0_null_4,NEXUS_5,1.0,en].png
+++ b/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.messages.impl.forward_null_DefaultGroup_ForwardMessagesViewLightPreview_0_null_4,NEXUS_5,1.0,en].png
@@ -1,3 +1,3 @@
 version https://git-lfs.github.com/spec/v1
-oid sha256:95313cb1717aabbb275b4ed039741da2ddf95af02d177f426b354701cc9badd9
-size 27947
+oid sha256:9d322e159a4c5e39a1bdce0628093bdc9ae372ccfd9d1fa2088a3e3094a09048
+size 28096
diff --git a/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.messages.impl.forward_null_DefaultGroup_ForwardMessagesViewLightPreview_0_null_5,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.messages.impl.forward_null_DefaultGroup_ForwardMessagesViewLightPreview_0_null_5,NEXUS_5,1.0,en].png
index 739e84de45..91573e4536 100644
--- a/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.messages.impl.forward_null_DefaultGroup_ForwardMessagesViewLightPreview_0_null_5,NEXUS_5,1.0,en].png
+++ b/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.messages.impl.forward_null_DefaultGroup_ForwardMessagesViewLightPreview_0_null_5,NEXUS_5,1.0,en].png
@@ -1,3 +1,3 @@
 version https://git-lfs.github.com/spec/v1
-oid sha256:95313cb1717aabbb275b4ed039741da2ddf95af02d177f426b354701cc9badd9
-size 27947
+oid sha256:9d322e159a4c5e39a1bdce0628093bdc9ae372ccfd9d1fa2088a3e3094a09048
+size 28096
diff --git a/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.messages.impl.forward_null_DefaultGroup_ForwardMessagesViewLightPreview_0_null_7,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.messages.impl.forward_null_DefaultGroup_ForwardMessagesViewLightPreview_0_null_7,NEXUS_5,1.0,en].png
index 739e84de45..91573e4536 100644
--- a/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.messages.impl.forward_null_DefaultGroup_ForwardMessagesViewLightPreview_0_null_7,NEXUS_5,1.0,en].png
+++ b/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.messages.impl.forward_null_DefaultGroup_ForwardMessagesViewLightPreview_0_null_7,NEXUS_5,1.0,en].png
@@ -1,3 +1,3 @@
 version https://git-lfs.github.com/spec/v1
-oid sha256:95313cb1717aabbb275b4ed039741da2ddf95af02d177f426b354701cc9badd9
-size 27947
+oid sha256:9d322e159a4c5e39a1bdce0628093bdc9ae372ccfd9d1fa2088a3e3094a09048
+size 28096
diff --git a/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.messages.impl.media.viewer_null_DefaultGroup_MediaViewerViewDarkPreview_0_null_0,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.messages.impl.media.viewer_null_DefaultGroup_MediaViewerViewDarkPreview_0_null_0,NEXUS_5,1.0,en].png
index 93e9b663f7..0c6de663a2 100644
--- a/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.messages.impl.media.viewer_null_DefaultGroup_MediaViewerViewDarkPreview_0_null_0,NEXUS_5,1.0,en].png
+++ b/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.messages.impl.media.viewer_null_DefaultGroup_MediaViewerViewDarkPreview_0_null_0,NEXUS_5,1.0,en].png
@@ -1,3 +1,3 @@
 version https://git-lfs.github.com/spec/v1
-oid sha256:e3b5474c29a881c61032396785a5c62732fc06f1e551fd6fae8ab620782774ce
-size 395492
+oid sha256:5a55394e59395b36f7a1e964bdce7d9f7d5f33252c463d0de7a87c213117231a
+size 395169
diff --git a/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.messages.impl.media.viewer_null_DefaultGroup_MediaViewerViewDarkPreview_0_null_1,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.messages.impl.media.viewer_null_DefaultGroup_MediaViewerViewDarkPreview_0_null_1,NEXUS_5,1.0,en].png
index bbc32091b8..f644a8c108 100644
--- a/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.messages.impl.media.viewer_null_DefaultGroup_MediaViewerViewDarkPreview_0_null_1,NEXUS_5,1.0,en].png
+++ b/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.messages.impl.media.viewer_null_DefaultGroup_MediaViewerViewDarkPreview_0_null_1,NEXUS_5,1.0,en].png
@@ -1,3 +1,3 @@
 version https://git-lfs.github.com/spec/v1
-oid sha256:cde41cd981bd9ed350b6c4439cfda793946e2b7c14ea701af8fd5bb528329661
-size 395494
+oid sha256:44acd9adb83a35d38a9da31f8055988740d238e459d7e77145c5c2ad53725ad6
+size 395169
diff --git a/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.messages.impl.media.viewer_null_DefaultGroup_MediaViewerViewDarkPreview_0_null_2,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.messages.impl.media.viewer_null_DefaultGroup_MediaViewerViewDarkPreview_0_null_2,NEXUS_5,1.0,en].png
index 93e9b663f7..0c6de663a2 100644
--- a/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.messages.impl.media.viewer_null_DefaultGroup_MediaViewerViewDarkPreview_0_null_2,NEXUS_5,1.0,en].png
+++ b/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.messages.impl.media.viewer_null_DefaultGroup_MediaViewerViewDarkPreview_0_null_2,NEXUS_5,1.0,en].png
@@ -1,3 +1,3 @@
 version https://git-lfs.github.com/spec/v1
-oid sha256:e3b5474c29a881c61032396785a5c62732fc06f1e551fd6fae8ab620782774ce
-size 395492
+oid sha256:5a55394e59395b36f7a1e964bdce7d9f7d5f33252c463d0de7a87c213117231a
+size 395169
diff --git a/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.messages.impl.media.viewer_null_DefaultGroup_MediaViewerViewDarkPreview_0_null_3,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.messages.impl.media.viewer_null_DefaultGroup_MediaViewerViewDarkPreview_0_null_3,NEXUS_5,1.0,en].png
index 3d12f9a3f6..e2663fb42c 100644
--- a/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.messages.impl.media.viewer_null_DefaultGroup_MediaViewerViewDarkPreview_0_null_3,NEXUS_5,1.0,en].png
+++ b/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.messages.impl.media.viewer_null_DefaultGroup_MediaViewerViewDarkPreview_0_null_3,NEXUS_5,1.0,en].png
@@ -1,3 +1,3 @@
 version https://git-lfs.github.com/spec/v1
-oid sha256:77983bf8dfa0683d472683cdb7ad545beb6b05fdfb8b82ecf90db49d387db72e
-size 395299
+oid sha256:e4e9e0b3c5be9a07af8cd9a4f4ae725505148805327455350d9504a5974032c2
+size 395377
diff --git a/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.messages.impl.media.viewer_null_DefaultGroup_MediaViewerViewDarkPreview_0_null_5,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.messages.impl.media.viewer_null_DefaultGroup_MediaViewerViewDarkPreview_0_null_5,NEXUS_5,1.0,en].png
index 1b77de0157..d16aed691d 100644
--- a/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.messages.impl.media.viewer_null_DefaultGroup_MediaViewerViewDarkPreview_0_null_5,NEXUS_5,1.0,en].png
+++ b/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.messages.impl.media.viewer_null_DefaultGroup_MediaViewerViewDarkPreview_0_null_5,NEXUS_5,1.0,en].png
@@ -1,3 +1,3 @@
 version https://git-lfs.github.com/spec/v1
-oid sha256:9a28b7439185193fca0f389d36f287fa38d29d18bfc046a125f936026ffd1918
-size 6318
+oid sha256:9225a19843eb5c9e1a78a7bd307958c2cad544c58ca2637224455326dfcfffb6
+size 6315
diff --git a/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.messages.impl.media.viewer_null_DefaultGroup_MediaViewerViewDarkPreview_0_null_6,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.messages.impl.media.viewer_null_DefaultGroup_MediaViewerViewDarkPreview_0_null_6,NEXUS_5,1.0,en].png
index c6afff3c8f..890541aa37 100644
--- a/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.messages.impl.media.viewer_null_DefaultGroup_MediaViewerViewDarkPreview_0_null_6,NEXUS_5,1.0,en].png
+++ b/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.messages.impl.media.viewer_null_DefaultGroup_MediaViewerViewDarkPreview_0_null_6,NEXUS_5,1.0,en].png
@@ -1,3 +1,3 @@
 version https://git-lfs.github.com/spec/v1
-oid sha256:5e11d4107dc8894408eac31625b4061a59e2b5eb955229d4abc64ebb1191cdc9
-size 15614
+oid sha256:78bb8fcf8275cd3568f6f254c4d7ef1a4e7d251162c8b21bf2c85baaf2ab6c8d
+size 15257
diff --git a/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.messages.impl.media.viewer_null_DefaultGroup_MediaViewerViewDarkPreview_0_null_7,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.messages.impl.media.viewer_null_DefaultGroup_MediaViewerViewDarkPreview_0_null_7,NEXUS_5,1.0,en].png
index 2fff84f3a3..fcfe80f7b0 100644
--- a/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.messages.impl.media.viewer_null_DefaultGroup_MediaViewerViewDarkPreview_0_null_7,NEXUS_5,1.0,en].png
+++ b/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.messages.impl.media.viewer_null_DefaultGroup_MediaViewerViewDarkPreview_0_null_7,NEXUS_5,1.0,en].png
@@ -1,3 +1,3 @@
 version https://git-lfs.github.com/spec/v1
-oid sha256:459ff294007ea6238f87954e04e8e13614b7c5fa7ade01f44670014013ebfead
-size 15382
+oid sha256:628072ca45ae0d215ba9bbe965b68442153d81ad98f330ab1178a0f8fcff3e24
+size 15339
diff --git a/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.messages.impl.media.viewer_null_DefaultGroup_MediaViewerViewDarkPreview_0_null_8,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.messages.impl.media.viewer_null_DefaultGroup_MediaViewerViewDarkPreview_0_null_8,NEXUS_5,1.0,en].png
index 8aea9ffda4..82352056a3 100644
--- a/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.messages.impl.media.viewer_null_DefaultGroup_MediaViewerViewDarkPreview_0_null_8,NEXUS_5,1.0,en].png
+++ b/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.messages.impl.media.viewer_null_DefaultGroup_MediaViewerViewDarkPreview_0_null_8,NEXUS_5,1.0,en].png
@@ -1,3 +1,3 @@
 version https://git-lfs.github.com/spec/v1
-oid sha256:a1805563eccf45f507152722511cacfa3f0411d1ccb90dd8d539f9a4a697b56f
-size 14459
+oid sha256:43d8d24a65ab1174f6e262563b898d3168ce1e38a1af8e53b1a5a8af205f70f5
+size 14103
diff --git a/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.messages.impl.media.viewer_null_DefaultGroup_MediaViewerViewDarkPreview_0_null_9,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.messages.impl.media.viewer_null_DefaultGroup_MediaViewerViewDarkPreview_0_null_9,NEXUS_5,1.0,en].png
index 48767dad09..d3a5dd72ac 100644
--- a/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.messages.impl.media.viewer_null_DefaultGroup_MediaViewerViewDarkPreview_0_null_9,NEXUS_5,1.0,en].png
+++ b/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.messages.impl.media.viewer_null_DefaultGroup_MediaViewerViewDarkPreview_0_null_9,NEXUS_5,1.0,en].png
@@ -1,3 +1,3 @@
 version https://git-lfs.github.com/spec/v1
-oid sha256:b2824676afbff473eff8c8cfbcf8b3e58b2851e37324c6a8d9ba47d626b0f8bc
-size 14234
+oid sha256:93ca4c1155010d01315b00bb79d9807cf0e6f80a609be668cb5600c16e82ef4d
+size 14190
diff --git a/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.messages.impl.report_null_DefaultGroup_ReportMessageViewDarkPreview_0_null_0,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.messages.impl.report_null_DefaultGroup_ReportMessageViewDarkPreview_0_null_0,NEXUS_5,1.0,en].png
index 5b3f3b3f31..55b466482a 100644
--- a/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.messages.impl.report_null_DefaultGroup_ReportMessageViewDarkPreview_0_null_0,NEXUS_5,1.0,en].png
+++ b/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.messages.impl.report_null_DefaultGroup_ReportMessageViewDarkPreview_0_null_0,NEXUS_5,1.0,en].png
@@ -1,3 +1,3 @@
 version https://git-lfs.github.com/spec/v1
-oid sha256:9034720950ce90da57f7fb3b811dddf95cb5f621a917b2fb1e930fb8aecac02c
-size 44089
+oid sha256:93fc8ccac0599b3ad6e16b4cf706d53f7aa51c41b50afdb64eb66992c338c65c
+size 44392
diff --git a/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.messages.impl.report_null_DefaultGroup_ReportMessageViewDarkPreview_0_null_1,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.messages.impl.report_null_DefaultGroup_ReportMessageViewDarkPreview_0_null_1,NEXUS_5,1.0,en].png
index 3ec76db242..ddcffd970b 100644
--- a/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.messages.impl.report_null_DefaultGroup_ReportMessageViewDarkPreview_0_null_1,NEXUS_5,1.0,en].png
+++ b/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.messages.impl.report_null_DefaultGroup_ReportMessageViewDarkPreview_0_null_1,NEXUS_5,1.0,en].png
@@ -1,3 +1,3 @@
 version https://git-lfs.github.com/spec/v1
-oid sha256:cd04b0d19c47008bec4e2a458647bbf4f0e4157452d380db65210e3a7ebeed3e
-size 45123
+oid sha256:7d4dab3b14b9ef45c243621f4253f177623103b539df82166223291baf6622cd
+size 45080
diff --git a/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.messages.impl.report_null_DefaultGroup_ReportMessageViewDarkPreview_0_null_2,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.messages.impl.report_null_DefaultGroup_ReportMessageViewDarkPreview_0_null_2,NEXUS_5,1.0,en].png
index b600b0e223..35f6114312 100644
--- a/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.messages.impl.report_null_DefaultGroup_ReportMessageViewDarkPreview_0_null_2,NEXUS_5,1.0,en].png
+++ b/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.messages.impl.report_null_DefaultGroup_ReportMessageViewDarkPreview_0_null_2,NEXUS_5,1.0,en].png
@@ -1,3 +1,3 @@
 version https://git-lfs.github.com/spec/v1
-oid sha256:f7b4b03c456266fbc7b476f4340551a9acaf731678af59961bb0890032c8cc53
-size 44669
+oid sha256:1504172c389945b60733645f3166bd6053ad5af62aab9ca31da6e4089d27eb38
+size 44636
diff --git a/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.messages.impl.report_null_DefaultGroup_ReportMessageViewDarkPreview_0_null_3,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.messages.impl.report_null_DefaultGroup_ReportMessageViewDarkPreview_0_null_3,NEXUS_5,1.0,en].png
index f0d1df632d..f8198ed1a5 100644
--- a/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.messages.impl.report_null_DefaultGroup_ReportMessageViewDarkPreview_0_null_3,NEXUS_5,1.0,en].png
+++ b/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.messages.impl.report_null_DefaultGroup_ReportMessageViewDarkPreview_0_null_3,NEXUS_5,1.0,en].png
@@ -1,3 +1,3 @@
 version https://git-lfs.github.com/spec/v1
-oid sha256:5a3b32af711ee8de6e2efbef25c1b747883807f341a67f2fad5c343be89b3bcc
-size 42863
+oid sha256:afa74a13826fdfdb795c705ae537cf9cef516ebc2ff84a0f4e1d4bcf413ceada
+size 43221
diff --git a/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.messages.impl.report_null_DefaultGroup_ReportMessageViewDarkPreview_0_null_4,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.messages.impl.report_null_DefaultGroup_ReportMessageViewDarkPreview_0_null_4,NEXUS_5,1.0,en].png
index 682e400eb9..381ab955b3 100644
--- a/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.messages.impl.report_null_DefaultGroup_ReportMessageViewDarkPreview_0_null_4,NEXUS_5,1.0,en].png
+++ b/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.messages.impl.report_null_DefaultGroup_ReportMessageViewDarkPreview_0_null_4,NEXUS_5,1.0,en].png
@@ -1,3 +1,3 @@
 version https://git-lfs.github.com/spec/v1
-oid sha256:82183d73c4ec193b2833ef5a007facd98d61293864532a200799f1ed75291002
-size 35550
+oid sha256:430ad21d6faa861bda2a774b8e58891beced9a7a442a4518455f06c2cf6ea11f
+size 35061
diff --git a/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.messages.impl.report_null_DefaultGroup_ReportMessageViewLightPreview_0_null_0,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.messages.impl.report_null_DefaultGroup_ReportMessageViewLightPreview_0_null_0,NEXUS_5,1.0,en].png
index 325e083ec6..bb7fd6311b 100644
--- a/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.messages.impl.report_null_DefaultGroup_ReportMessageViewLightPreview_0_null_0,NEXUS_5,1.0,en].png
+++ b/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.messages.impl.report_null_DefaultGroup_ReportMessageViewLightPreview_0_null_0,NEXUS_5,1.0,en].png
@@ -1,3 +1,3 @@
 version https://git-lfs.github.com/spec/v1
-oid sha256:08465420dfb59d2fa6895106ed649787659e08898efdfac5957d70c6e36d64ae
-size 45770
+oid sha256:1b5737eab1418e738ef66397e5a2d2c8ee70369d1a84dd59ff35e7fbf4d3b520
+size 45979
diff --git a/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.messages.impl.report_null_DefaultGroup_ReportMessageViewLightPreview_0_null_1,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.messages.impl.report_null_DefaultGroup_ReportMessageViewLightPreview_0_null_1,NEXUS_5,1.0,en].png
index 1206c45222..ca9291e476 100644
--- a/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.messages.impl.report_null_DefaultGroup_ReportMessageViewLightPreview_0_null_1,NEXUS_5,1.0,en].png
+++ b/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.messages.impl.report_null_DefaultGroup_ReportMessageViewLightPreview_0_null_1,NEXUS_5,1.0,en].png
@@ -1,3 +1,3 @@
 version https://git-lfs.github.com/spec/v1
-oid sha256:07e4c2347902204df2860f5ff48412c31b9904e61d2e3e481806ceb79b2f8d2a
-size 47550
+oid sha256:1a58a45c850eb9f3095dff489b306c250484124d399421c9afece6d7061be253
+size 47472
diff --git a/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.messages.impl.report_null_DefaultGroup_ReportMessageViewLightPreview_0_null_2,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.messages.impl.report_null_DefaultGroup_ReportMessageViewLightPreview_0_null_2,NEXUS_5,1.0,en].png
index 1e8fe02f36..1b643ab7d8 100644
--- a/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.messages.impl.report_null_DefaultGroup_ReportMessageViewLightPreview_0_null_2,NEXUS_5,1.0,en].png
+++ b/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.messages.impl.report_null_DefaultGroup_ReportMessageViewLightPreview_0_null_2,NEXUS_5,1.0,en].png
@@ -1,3 +1,3 @@
 version https://git-lfs.github.com/spec/v1
-oid sha256:c31855849005a3bf4f5eb02b8461cc2d26ba84637115d7e8390aa0732caf6013
-size 47013
+oid sha256:9452d0ee6d79778004e4b68a089d0105d4f87a2de4d89c36b889c73c9087c96c
+size 46934
diff --git a/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.messages.impl.report_null_DefaultGroup_ReportMessageViewLightPreview_0_null_3,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.messages.impl.report_null_DefaultGroup_ReportMessageViewLightPreview_0_null_3,NEXUS_5,1.0,en].png
index 8a5d3932f4..fe16c0bce6 100644
--- a/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.messages.impl.report_null_DefaultGroup_ReportMessageViewLightPreview_0_null_3,NEXUS_5,1.0,en].png
+++ b/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.messages.impl.report_null_DefaultGroup_ReportMessageViewLightPreview_0_null_3,NEXUS_5,1.0,en].png
@@ -1,3 +1,3 @@
 version https://git-lfs.github.com/spec/v1
-oid sha256:2df48ac9b873b317c7cb1163bb96d2d0fac6f6c7e00747ec8e10e0e7a22d8cc4
-size 45129
+oid sha256:a9ce8f73922b6df91f3383f3d27464a2951595da9c63fbdbf8c0f87efd0d4115
+size 45445
diff --git a/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.messages.impl.report_null_DefaultGroup_ReportMessageViewLightPreview_0_null_4,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.messages.impl.report_null_DefaultGroup_ReportMessageViewLightPreview_0_null_4,NEXUS_5,1.0,en].png
index efd9526466..626414fc5b 100644
--- a/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.messages.impl.report_null_DefaultGroup_ReportMessageViewLightPreview_0_null_4,NEXUS_5,1.0,en].png
+++ b/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.messages.impl.report_null_DefaultGroup_ReportMessageViewLightPreview_0_null_4,NEXUS_5,1.0,en].png
@@ -1,3 +1,3 @@
 version https://git-lfs.github.com/spec/v1
-oid sha256:48738c3a3a6d9caee6590fb756cef164b58d3238fe0d86fb4cf8acfac627e71f
-size 36913
+oid sha256:1e48ec2f2e8a992be7dd3c12ae3780d3bb110ee66758f72586d4f3aee39d18e8
+size 36935
diff --git a/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.messages.impl.timeline.components.event_null_DefaultGroup_TimelineItemAudioViewPreview-D-8_9_null_0,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.messages.impl.timeline.components.event_null_DefaultGroup_TimelineItemAudioViewPreview-D-11_12_null_0,NEXUS_5,1.0,en].png
similarity index 100%
rename from tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.messages.impl.timeline.components.event_null_DefaultGroup_TimelineItemAudioViewPreview-D-8_9_null_0,NEXUS_5,1.0,en].png
rename to tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.messages.impl.timeline.components.event_null_DefaultGroup_TimelineItemAudioViewPreview-D-11_12_null_0,NEXUS_5,1.0,en].png
diff --git a/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.messages.impl.timeline.components.event_null_DefaultGroup_TimelineItemAudioViewPreview-D-8_9_null_1,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.messages.impl.timeline.components.event_null_DefaultGroup_TimelineItemAudioViewPreview-D-11_12_null_1,NEXUS_5,1.0,en].png
similarity index 100%
rename from tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.messages.impl.timeline.components.event_null_DefaultGroup_TimelineItemAudioViewPreview-D-8_9_null_1,NEXUS_5,1.0,en].png
rename to tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.messages.impl.timeline.components.event_null_DefaultGroup_TimelineItemAudioViewPreview-D-11_12_null_1,NEXUS_5,1.0,en].png
diff --git a/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.messages.impl.timeline.components.event_null_DefaultGroup_TimelineItemAudioViewPreview-D-8_9_null_2,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.messages.impl.timeline.components.event_null_DefaultGroup_TimelineItemAudioViewPreview-D-11_12_null_2,NEXUS_5,1.0,en].png
similarity index 100%
rename from tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.messages.impl.timeline.components.event_null_DefaultGroup_TimelineItemAudioViewPreview-D-8_9_null_2,NEXUS_5,1.0,en].png
rename to tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.messages.impl.timeline.components.event_null_DefaultGroup_TimelineItemAudioViewPreview-D-11_12_null_2,NEXUS_5,1.0,en].png
diff --git a/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.messages.impl.timeline.components.event_null_DefaultGroup_TimelineItemAudioViewPreview-N-8_10_null_0,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.messages.impl.timeline.components.event_null_DefaultGroup_TimelineItemAudioViewPreview-N-11_13_null_0,NEXUS_5,1.0,en].png
similarity index 100%
rename from tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.messages.impl.timeline.components.event_null_DefaultGroup_TimelineItemAudioViewPreview-N-8_10_null_0,NEXUS_5,1.0,en].png
rename to tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.messages.impl.timeline.components.event_null_DefaultGroup_TimelineItemAudioViewPreview-N-11_13_null_0,NEXUS_5,1.0,en].png
diff --git a/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.messages.impl.timeline.components.event_null_DefaultGroup_TimelineItemAudioViewPreview-N-8_10_null_1,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.messages.impl.timeline.components.event_null_DefaultGroup_TimelineItemAudioViewPreview-N-11_13_null_1,NEXUS_5,1.0,en].png
similarity index 100%
rename from tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.messages.impl.timeline.components.event_null_DefaultGroup_TimelineItemAudioViewPreview-N-8_10_null_1,NEXUS_5,1.0,en].png
rename to tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.messages.impl.timeline.components.event_null_DefaultGroup_TimelineItemAudioViewPreview-N-11_13_null_1,NEXUS_5,1.0,en].png
diff --git a/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.messages.impl.timeline.components.event_null_DefaultGroup_TimelineItemAudioViewPreview-N-8_10_null_2,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.messages.impl.timeline.components.event_null_DefaultGroup_TimelineItemAudioViewPreview-N-11_13_null_2,NEXUS_5,1.0,en].png
similarity index 100%
rename from tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.messages.impl.timeline.components.event_null_DefaultGroup_TimelineItemAudioViewPreview-N-8_10_null_2,NEXUS_5,1.0,en].png
rename to tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.messages.impl.timeline.components.event_null_DefaultGroup_TimelineItemAudioViewPreview-N-11_13_null_2,NEXUS_5,1.0,en].png
diff --git a/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.messages.impl.timeline.components.event_null_DefaultGroup_TimelineItemLocationViewPreview-D-9_10_null_0,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.messages.impl.timeline.components.event_null_DefaultGroup_TimelineItemLocationViewPreview-D-12_13_null_0,NEXUS_5,1.0,en].png
similarity index 100%
rename from tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.messages.impl.timeline.components.event_null_DefaultGroup_TimelineItemLocationViewPreview-D-9_10_null_0,NEXUS_5,1.0,en].png
rename to tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.messages.impl.timeline.components.event_null_DefaultGroup_TimelineItemLocationViewPreview-D-12_13_null_0,NEXUS_5,1.0,en].png
diff --git a/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.messages.impl.timeline.components.event_null_DefaultGroup_TimelineItemLocationViewPreview-D-9_10_null_1,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.messages.impl.timeline.components.event_null_DefaultGroup_TimelineItemLocationViewPreview-D-12_13_null_1,NEXUS_5,1.0,en].png
similarity index 100%
rename from tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.messages.impl.timeline.components.event_null_DefaultGroup_TimelineItemLocationViewPreview-D-9_10_null_1,NEXUS_5,1.0,en].png
rename to tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.messages.impl.timeline.components.event_null_DefaultGroup_TimelineItemLocationViewPreview-D-12_13_null_1,NEXUS_5,1.0,en].png
diff --git a/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.messages.impl.timeline.components.event_null_DefaultGroup_TimelineItemLocationViewPreview-N-9_11_null_0,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.messages.impl.timeline.components.event_null_DefaultGroup_TimelineItemLocationViewPreview-N-12_14_null_0,NEXUS_5,1.0,en].png
similarity index 100%
rename from tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.messages.impl.timeline.components.event_null_DefaultGroup_TimelineItemLocationViewPreview-N-9_11_null_0,NEXUS_5,1.0,en].png
rename to tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.messages.impl.timeline.components.event_null_DefaultGroup_TimelineItemLocationViewPreview-N-12_14_null_0,NEXUS_5,1.0,en].png
diff --git a/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.messages.impl.timeline.components.event_null_DefaultGroup_TimelineItemLocationViewPreview-N-9_11_null_1,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.messages.impl.timeline.components.event_null_DefaultGroup_TimelineItemLocationViewPreview-N-12_14_null_1,NEXUS_5,1.0,en].png
similarity index 100%
rename from tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.messages.impl.timeline.components.event_null_DefaultGroup_TimelineItemLocationViewPreview-N-9_11_null_1,NEXUS_5,1.0,en].png
rename to tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.messages.impl.timeline.components.event_null_DefaultGroup_TimelineItemLocationViewPreview-N-12_14_null_1,NEXUS_5,1.0,en].png
diff --git a/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.messages.impl.timeline.components.event_null_DefaultGroup_TimelineItemPollViewPreview-D-13_14_null_0,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.messages.impl.timeline.components.event_null_DefaultGroup_TimelineItemPollViewPreview-D-13_14_null_0,NEXUS_5,1.0,en].png
new file mode 100644
index 0000000000..05cf88f8f9
--- /dev/null
+++ b/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.messages.impl.timeline.components.event_null_DefaultGroup_TimelineItemPollViewPreview-D-13_14_null_0,NEXUS_5,1.0,en].png
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:1978bafb5fd079de3fe7945a0574b2b19b0480d9d7d146e034b749e674f76254
+size 48667
diff --git a/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.messages.impl.timeline.components.event_null_DefaultGroup_TimelineItemPollViewPreview-D-13_14_null_1,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.messages.impl.timeline.components.event_null_DefaultGroup_TimelineItemPollViewPreview-D-13_14_null_1,NEXUS_5,1.0,en].png
new file mode 100644
index 0000000000..05cf88f8f9
--- /dev/null
+++ b/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.messages.impl.timeline.components.event_null_DefaultGroup_TimelineItemPollViewPreview-D-13_14_null_1,NEXUS_5,1.0,en].png
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:1978bafb5fd079de3fe7945a0574b2b19b0480d9d7d146e034b749e674f76254
+size 48667
diff --git a/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.messages.impl.timeline.components.event_null_DefaultGroup_TimelineItemPollViewPreview-N-13_15_null_0,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.messages.impl.timeline.components.event_null_DefaultGroup_TimelineItemPollViewPreview-N-13_15_null_0,NEXUS_5,1.0,en].png
new file mode 100644
index 0000000000..c0d3cd8739
--- /dev/null
+++ b/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.messages.impl.timeline.components.event_null_DefaultGroup_TimelineItemPollViewPreview-N-13_15_null_0,NEXUS_5,1.0,en].png
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:df79a0bd1caa8ecf4b701eaa589cc90efc748b986388f9ae5636b9dceba4492c
+size 45928
diff --git a/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.messages.impl.timeline.components.event_null_DefaultGroup_TimelineItemPollViewPreview-N-13_15_null_1,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.messages.impl.timeline.components.event_null_DefaultGroup_TimelineItemPollViewPreview-N-13_15_null_1,NEXUS_5,1.0,en].png
new file mode 100644
index 0000000000..c0d3cd8739
--- /dev/null
+++ b/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.messages.impl.timeline.components.event_null_DefaultGroup_TimelineItemPollViewPreview-N-13_15_null_1,NEXUS_5,1.0,en].png
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:df79a0bd1caa8ecf4b701eaa589cc90efc748b986388f9ae5636b9dceba4492c
+size 45928
diff --git a/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.messages.impl.timeline.components.reactionsummary_null_DefaultGroup_SheetContentPreview-D-14_15_null_0,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.messages.impl.timeline.components.reactionsummary_null_DefaultGroup_SheetContentPreview-D-14_15_null_0,NEXUS_5,1.0,en].png
new file mode 100644
index 0000000000..c63cf7083a
--- /dev/null
+++ b/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.messages.impl.timeline.components.reactionsummary_null_DefaultGroup_SheetContentPreview-D-14_15_null_0,NEXUS_5,1.0,en].png
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:4e63f683ef130d77b55966e954a7cbc144dceb5960056bcd01d7c0c9583b3b03
+size 25358
diff --git a/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.messages.impl.timeline.components.reactionsummary_null_DefaultGroup_SheetContentPreview-N-14_16_null_0,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.messages.impl.timeline.components.reactionsummary_null_DefaultGroup_SheetContentPreview-N-14_16_null_0,NEXUS_5,1.0,en].png
new file mode 100644
index 0000000000..495f0b09a0
--- /dev/null
+++ b/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.messages.impl.timeline.components.reactionsummary_null_DefaultGroup_SheetContentPreview-N-14_16_null_0,NEXUS_5,1.0,en].png
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:5fd8aeb2e875a1280a70ba913dd913759af66fb4300ed69c7e109ec8e8378a09
+size 25051
diff --git a/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.messages.impl.timeline.components.virtual_null_DefaultGroup_TimelineEncryptedHistoryBannerViewPreview-D-10_11_null,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.messages.impl.timeline.components.virtual_null_DefaultGroup_TimelineEncryptedHistoryBannerViewPreview-D-15_16_null,NEXUS_5,1.0,en].png
similarity index 100%
rename from tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.messages.impl.timeline.components.virtual_null_DefaultGroup_TimelineEncryptedHistoryBannerViewPreview-D-10_11_null,NEXUS_5,1.0,en].png
rename to tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.messages.impl.timeline.components.virtual_null_DefaultGroup_TimelineEncryptedHistoryBannerViewPreview-D-15_16_null,NEXUS_5,1.0,en].png
diff --git a/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.messages.impl.timeline.components.virtual_null_DefaultGroup_TimelineEncryptedHistoryBannerViewPreview-N-10_12_null,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.messages.impl.timeline.components.virtual_null_DefaultGroup_TimelineEncryptedHistoryBannerViewPreview-N-15_17_null,NEXUS_5,1.0,en].png
similarity index 100%
rename from tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.messages.impl.timeline.components.virtual_null_DefaultGroup_TimelineEncryptedHistoryBannerViewPreview-N-10_12_null,NEXUS_5,1.0,en].png
rename to tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.messages.impl.timeline.components.virtual_null_DefaultGroup_TimelineEncryptedHistoryBannerViewPreview-N-15_17_null,NEXUS_5,1.0,en].png
diff --git a/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.messages.impl.timeline.components_null_DefaultGroup_EmojiPickerDarkPreview_0_null,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.messages.impl.timeline.components_null_DefaultGroup_EmojiPickerDarkPreview_0_null,NEXUS_5,1.0,en].png
index e10b00e85b..d6abcd7838 100644
--- a/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.messages.impl.timeline.components_null_DefaultGroup_EmojiPickerDarkPreview_0_null,NEXUS_5,1.0,en].png
+++ b/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.messages.impl.timeline.components_null_DefaultGroup_EmojiPickerDarkPreview_0_null,NEXUS_5,1.0,en].png
@@ -1,3 +1,3 @@
 version https://git-lfs.github.com/spec/v1
-oid sha256:dedb3940216fd18804157f708340a535008cc753a579ced3ac4153f99bf01218
-size 175737
+oid sha256:c5650ec2689d4ce0cf0785e12d5cb899c1bdfdad14c1f75106be1068df662f53
+size 188815
diff --git a/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.messages.impl.timeline.components_null_DefaultGroup_EmojiPickerLightPreview_0_null,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.messages.impl.timeline.components_null_DefaultGroup_EmojiPickerLightPreview_0_null,NEXUS_5,1.0,en].png
index e3804f7073..5898fc6fa7 100644
--- a/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.messages.impl.timeline.components_null_DefaultGroup_EmojiPickerLightPreview_0_null,NEXUS_5,1.0,en].png
+++ b/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.messages.impl.timeline.components_null_DefaultGroup_EmojiPickerLightPreview_0_null,NEXUS_5,1.0,en].png
@@ -1,3 +1,3 @@
 version https://git-lfs.github.com/spec/v1
-oid sha256:19d8a7e0d477cc7db1bea85407b71516347b158777db2e3889734f2129b69de3
-size 175762
+oid sha256:2e5e11d9c1e7d4b950a0d080e8104f08b26fac56332d243502430dbfdd02c60b
+size 188259
diff --git a/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.messages.impl.timeline.components_null_DefaultGroup_MessagesAddReactionButtonPreview-D-4_5_null,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.messages.impl.timeline.components_null_DefaultGroup_MessagesAddReactionButtonPreview-D-4_5_null,NEXUS_5,1.0,en].png
new file mode 100644
index 0000000000..91af1135e8
--- /dev/null
+++ b/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.messages.impl.timeline.components_null_DefaultGroup_MessagesAddReactionButtonPreview-D-4_5_null,NEXUS_5,1.0,en].png
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:1763f6e5114d406d9e2a5cbad96113d5d36f6ccfdee1cfade0146c1804d0a725
+size 5982
diff --git a/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.messages.impl.timeline.components_null_DefaultGroup_MessagesAddReactionButtonPreview-N-4_6_null,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.messages.impl.timeline.components_null_DefaultGroup_MessagesAddReactionButtonPreview-N-4_6_null,NEXUS_5,1.0,en].png
new file mode 100644
index 0000000000..25592c4b2f
--- /dev/null
+++ b/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.messages.impl.timeline.components_null_DefaultGroup_MessagesAddReactionButtonPreview-N-4_6_null,NEXUS_5,1.0,en].png
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:0582cf0802ca4a1e5fc823518f0dee9fbf31b3b2803c0a89baab35885139805e
+size 5917
diff --git a/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.messages.impl.timeline.components_null_DefaultGroup_MessagesReactionExtraButtonsPreview-D-4_5_null,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.messages.impl.timeline.components_null_DefaultGroup_MessagesReactionExtraButtonsPreview-D-4_5_null,NEXUS_5,1.0,en].png
deleted file mode 100644
index d732d1c37b..0000000000
--- a/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.messages.impl.timeline.components_null_DefaultGroup_MessagesReactionExtraButtonsPreview-D-4_5_null,NEXUS_5,1.0,en].png
+++ /dev/null
@@ -1,3 +0,0 @@
-version https://git-lfs.github.com/spec/v1
-oid sha256:724bc9b0db8f581119201a8db3c405c9a7e7261cccea45a354fd37a5e33fcb41
-size 11141
diff --git a/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.messages.impl.timeline.components_null_DefaultGroup_MessagesReactionExtraButtonsPreview-D-5_6_null,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.messages.impl.timeline.components_null_DefaultGroup_MessagesReactionExtraButtonsPreview-D-5_6_null,NEXUS_5,1.0,en].png
new file mode 100644
index 0000000000..08f201da01
--- /dev/null
+++ b/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.messages.impl.timeline.components_null_DefaultGroup_MessagesReactionExtraButtonsPreview-D-5_6_null,NEXUS_5,1.0,en].png
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:b009dd473a3a2d5eafae382f2477728cb7ef3053c52ec51bc3f3891769ae5f57
+size 10264
diff --git a/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.messages.impl.timeline.components_null_DefaultGroup_MessagesReactionExtraButtonsPreview-N-4_6_null,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.messages.impl.timeline.components_null_DefaultGroup_MessagesReactionExtraButtonsPreview-N-4_6_null,NEXUS_5,1.0,en].png
deleted file mode 100644
index 9b08510703..0000000000
--- a/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.messages.impl.timeline.components_null_DefaultGroup_MessagesReactionExtraButtonsPreview-N-4_6_null,NEXUS_5,1.0,en].png
+++ /dev/null
@@ -1,3 +0,0 @@
-version https://git-lfs.github.com/spec/v1
-oid sha256:109a1a9c6359a9fd7fe4258f022e845c9b8142f9e590a03e5c2efa9273cb572f
-size 10742
diff --git a/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.messages.impl.timeline.components_null_DefaultGroup_MessagesReactionExtraButtonsPreview-N-5_7_null,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.messages.impl.timeline.components_null_DefaultGroup_MessagesReactionExtraButtonsPreview-N-5_7_null,NEXUS_5,1.0,en].png
new file mode 100644
index 0000000000..1f7c631359
--- /dev/null
+++ b/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.messages.impl.timeline.components_null_DefaultGroup_MessagesReactionExtraButtonsPreview-N-5_7_null,NEXUS_5,1.0,en].png
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:153f8eb0807c8b34d2e990819e8f892382aae1125350d371d08a35454423a727
+size 9948
diff --git a/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.messages.impl.timeline.components_null_DefaultGroup_TimelineItemEventRowDarkPreview_0_null,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.messages.impl.timeline.components_null_DefaultGroup_TimelineItemEventRowDarkPreview_0_null,NEXUS_5,1.0,en].png
index 3fc8c841f2..e418577f55 100644
--- a/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.messages.impl.timeline.components_null_DefaultGroup_TimelineItemEventRowDarkPreview_0_null,NEXUS_5,1.0,en].png
+++ b/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.messages.impl.timeline.components_null_DefaultGroup_TimelineItemEventRowDarkPreview_0_null,NEXUS_5,1.0,en].png
@@ -1,3 +1,3 @@
 version https://git-lfs.github.com/spec/v1
-oid sha256:38c6d3f4a47ed89c3deb4150024b49c0a533a859f21a1592a82309b8c7316ea4
-size 152242
+oid sha256:5bb246e6f180d6eef61c3dc0f884a070761d03b4f396d2ead1c178507a6bc70d
+size 151279
diff --git a/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.messages.impl.timeline.components_null_DefaultGroup_TimelineItemEventRowLightPreview_0_null,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.messages.impl.timeline.components_null_DefaultGroup_TimelineItemEventRowLightPreview_0_null,NEXUS_5,1.0,en].png
index b204098bdc..f9e018c372 100644
--- a/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.messages.impl.timeline.components_null_DefaultGroup_TimelineItemEventRowLightPreview_0_null,NEXUS_5,1.0,en].png
+++ b/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.messages.impl.timeline.components_null_DefaultGroup_TimelineItemEventRowLightPreview_0_null,NEXUS_5,1.0,en].png
@@ -1,3 +1,3 @@
 version https://git-lfs.github.com/spec/v1
-oid sha256:f82840398e396e038ad68a5fe855394a0088c413e7aade339998b8ed63fb1c09
-size 157273
+oid sha256:2905961ddc979076374d5cd7fb0885b3e3fb7d13a3fa0ae915553d8bb0174c65
+size 156313
diff --git a/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.messages.impl.timeline.components_null_DefaultGroup_TimelineItemEventRowWithManyReactionsDarkPreview_0_null,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.messages.impl.timeline.components_null_DefaultGroup_TimelineItemEventRowWithManyReactionsDarkPreview_0_null,NEXUS_5,1.0,en].png
index d389368d7e..f7bd5a3551 100644
--- a/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.messages.impl.timeline.components_null_DefaultGroup_TimelineItemEventRowWithManyReactionsDarkPreview_0_null,NEXUS_5,1.0,en].png
+++ b/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.messages.impl.timeline.components_null_DefaultGroup_TimelineItemEventRowWithManyReactionsDarkPreview_0_null,NEXUS_5,1.0,en].png
@@ -1,3 +1,3 @@
 version https://git-lfs.github.com/spec/v1
-oid sha256:7c5ef7519aef3badeda3983b2ec5474f31404bc06b4b46b9829848dc7884fe1d
-size 81749
+oid sha256:35c0b796ce83fbe14b477f472344e4b3969033b77460a8744ccdb2a3235bec03
+size 81090
diff --git a/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.messages.impl.timeline.components_null_DefaultGroup_TimelineItemEventRowWithManyReactionsLightPreview_0_null,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.messages.impl.timeline.components_null_DefaultGroup_TimelineItemEventRowWithManyReactionsLightPreview_0_null,NEXUS_5,1.0,en].png
index 722a25f340..39a0c59701 100644
--- a/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.messages.impl.timeline.components_null_DefaultGroup_TimelineItemEventRowWithManyReactionsLightPreview_0_null,NEXUS_5,1.0,en].png
+++ b/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.messages.impl.timeline.components_null_DefaultGroup_TimelineItemEventRowWithManyReactionsLightPreview_0_null,NEXUS_5,1.0,en].png
@@ -1,3 +1,3 @@
 version https://git-lfs.github.com/spec/v1
-oid sha256:c9e9b769422e4714e87ace97058e5a8f064e3b927e3a7c6042494de8381d6b09
-size 85856
+oid sha256:26b0a776582b02bf1ccdc7a75720097f9f653635ff14c42f432aadda4e832d61
+size 85152
diff --git a/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.messages.impl.timeline.components_null_DefaultGroup_TimelineItemEventRowWithReplyDarkPreview_0_null,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.messages.impl.timeline.components_null_DefaultGroup_TimelineItemEventRowWithReplyDarkPreview_0_null,NEXUS_5,1.0,en].png
index f2add007e5..496a355edc 100644
--- a/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.messages.impl.timeline.components_null_DefaultGroup_TimelineItemEventRowWithReplyDarkPreview_0_null,NEXUS_5,1.0,en].png
+++ b/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.messages.impl.timeline.components_null_DefaultGroup_TimelineItemEventRowWithReplyDarkPreview_0_null,NEXUS_5,1.0,en].png
@@ -1,3 +1,3 @@
 version https://git-lfs.github.com/spec/v1
-oid sha256:4970830b042e7b6588c03bf632ae3ade5b39de7339e27618ee341cbd9861c0e9
-size 129351
+oid sha256:2c5f983843e2d0689de6316091ccecbe4442b377427c8a5d9edf6a76e4f1d885
+size 127276
diff --git a/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.messages.impl.timeline.components_null_DefaultGroup_TimelineItemEventRowWithReplyLightPreview_0_null,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.messages.impl.timeline.components_null_DefaultGroup_TimelineItemEventRowWithReplyLightPreview_0_null,NEXUS_5,1.0,en].png
index a048edf7d8..46037460cf 100644
--- a/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.messages.impl.timeline.components_null_DefaultGroup_TimelineItemEventRowWithReplyLightPreview_0_null,NEXUS_5,1.0,en].png
+++ b/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.messages.impl.timeline.components_null_DefaultGroup_TimelineItemEventRowWithReplyLightPreview_0_null,NEXUS_5,1.0,en].png
@@ -1,3 +1,3 @@
 version https://git-lfs.github.com/spec/v1
-oid sha256:4aba48e03e8424e5ff131c22fd5a606280745dd318f5822e2167f3b39794ff41
-size 134569
+oid sha256:b412cc33626f9987b35549c1cd693af7e16c79179093a74b7b38da5964da19c8
+size 132594
diff --git a/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.messages.impl.timeline.components_null_DefaultGroup_TimelineItemReactionsLayoutPreview-D-6_7_null,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.messages.impl.timeline.components_null_DefaultGroup_TimelineItemReactionsLayoutPreview-D-6_7_null,NEXUS_5,1.0,en].png
new file mode 100644
index 0000000000..e9c109b99c
--- /dev/null
+++ b/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.messages.impl.timeline.components_null_DefaultGroup_TimelineItemReactionsLayoutPreview-D-6_7_null,NEXUS_5,1.0,en].png
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:6c6a8e9a5fb8dac5bbcd7e0c0ac9df56759dc2e94a5d5195dd9102aba0c18617
+size 26509
diff --git a/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.messages.impl.timeline.components_null_DefaultGroup_TimelineItemReactionsLayoutPreview-N-6_8_null,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.messages.impl.timeline.components_null_DefaultGroup_TimelineItemReactionsLayoutPreview-N-6_8_null,NEXUS_5,1.0,en].png
new file mode 100644
index 0000000000..555d89e509
--- /dev/null
+++ b/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.messages.impl.timeline.components_null_DefaultGroup_TimelineItemReactionsLayoutPreview-N-6_8_null,NEXUS_5,1.0,en].png
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:79997cff1c86462be9b743f1c561d3b8667570b474e0187352d7d2e2cd056888
+size 26107
diff --git a/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.messages.impl.timeline.components_null_DefaultGroup_TimelineItemReactionsViewCollapsedPreview-D-6_7_null,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.messages.impl.timeline.components_null_DefaultGroup_TimelineItemReactionsViewCollapsedPreview-D-6_7_null,NEXUS_5,1.0,en].png
deleted file mode 100644
index c838261a0d..0000000000
--- a/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.messages.impl.timeline.components_null_DefaultGroup_TimelineItemReactionsViewCollapsedPreview-D-6_7_null,NEXUS_5,1.0,en].png
+++ /dev/null
@@ -1,3 +0,0 @@
-version https://git-lfs.github.com/spec/v1
-oid sha256:dfccebdef9523a984d9edc2414aa159ed025aec14f891945abed73472e462df8
-size 13641
diff --git a/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.messages.impl.timeline.components_null_DefaultGroup_TimelineItemReactionsViewCollapsedPreview-N-6_8_null,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.messages.impl.timeline.components_null_DefaultGroup_TimelineItemReactionsViewCollapsedPreview-N-6_8_null,NEXUS_5,1.0,en].png
deleted file mode 100644
index 001fbca040..0000000000
--- a/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.messages.impl.timeline.components_null_DefaultGroup_TimelineItemReactionsViewCollapsedPreview-N-6_8_null,NEXUS_5,1.0,en].png
+++ /dev/null
@@ -1,3 +0,0 @@
-version https://git-lfs.github.com/spec/v1
-oid sha256:9c971ed744305a474f182bf3d6fde281b9034f99cee4f4207460a733ac8490a7
-size 13464
diff --git a/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.messages.impl.timeline.components_null_DefaultGroup_TimelineItemReactionsViewExpandedPreview-D-7_8_null,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.messages.impl.timeline.components_null_DefaultGroup_TimelineItemReactionsViewExpandedPreview-D-7_8_null,NEXUS_5,1.0,en].png
deleted file mode 100644
index 53c52d9a7d..0000000000
--- a/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.messages.impl.timeline.components_null_DefaultGroup_TimelineItemReactionsViewExpandedPreview-D-7_8_null,NEXUS_5,1.0,en].png
+++ /dev/null
@@ -1,3 +0,0 @@
-version https://git-lfs.github.com/spec/v1
-oid sha256:999475ddc51f74a590e5ef2810ab31222127e55cba01fadbeb8cb8e9058ad6f0
-size 27170
diff --git a/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.messages.impl.timeline.components_null_DefaultGroup_TimelineItemReactionsViewExpandedPreview-N-7_9_null,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.messages.impl.timeline.components_null_DefaultGroup_TimelineItemReactionsViewExpandedPreview-N-7_9_null,NEXUS_5,1.0,en].png
deleted file mode 100644
index cbed0a0752..0000000000
--- a/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.messages.impl.timeline.components_null_DefaultGroup_TimelineItemReactionsViewExpandedPreview-N-7_9_null,NEXUS_5,1.0,en].png
+++ /dev/null
@@ -1,3 +0,0 @@
-version https://git-lfs.github.com/spec/v1
-oid sha256:6fb7202b53005274d98f0aee8014326f02bb62fcd323b38b4d8a447078499dd8
-size 26965
diff --git a/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.messages.impl.timeline.components_null_DefaultGroup_TimelineItemReactionsViewFewPreview-D-8_9_null,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.messages.impl.timeline.components_null_DefaultGroup_TimelineItemReactionsViewFewPreview-D-8_9_null,NEXUS_5,1.0,en].png
new file mode 100644
index 0000000000..2ddf5837cb
--- /dev/null
+++ b/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.messages.impl.timeline.components_null_DefaultGroup_TimelineItemReactionsViewFewPreview-D-8_9_null,NEXUS_5,1.0,en].png
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:064001a5d6bdf0c3c9c160e95c137789d874e8a595d3f30def3d7d77a049d4f9
+size 12113
diff --git a/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.messages.impl.timeline.components_null_DefaultGroup_TimelineItemReactionsViewFewPreview-N-8_10_null,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.messages.impl.timeline.components_null_DefaultGroup_TimelineItemReactionsViewFewPreview-N-8_10_null,NEXUS_5,1.0,en].png
new file mode 100644
index 0000000000..42e074b9b7
--- /dev/null
+++ b/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.messages.impl.timeline.components_null_DefaultGroup_TimelineItemReactionsViewFewPreview-N-8_10_null,NEXUS_5,1.0,en].png
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:36e2d799245e69505f55bfae68401570d983deb7747bbdfdd5f01372003587b3
+size 11994
diff --git a/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.messages.impl.timeline.components_null_DefaultGroup_TimelineItemReactionsViewIncomingPreview-D-9_10_null,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.messages.impl.timeline.components_null_DefaultGroup_TimelineItemReactionsViewIncomingPreview-D-9_10_null,NEXUS_5,1.0,en].png
new file mode 100644
index 0000000000..2ebedc0722
--- /dev/null
+++ b/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.messages.impl.timeline.components_null_DefaultGroup_TimelineItemReactionsViewIncomingPreview-D-9_10_null,NEXUS_5,1.0,en].png
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:4efea594700a66b3a8aa2fdf95d4eafd937fe3adce0c70982e3cf713aa662739
+size 25743
diff --git a/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.messages.impl.timeline.components_null_DefaultGroup_TimelineItemReactionsViewIncomingPreview-N-9_11_null,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.messages.impl.timeline.components_null_DefaultGroup_TimelineItemReactionsViewIncomingPreview-N-9_11_null,NEXUS_5,1.0,en].png
new file mode 100644
index 0000000000..924713cef0
--- /dev/null
+++ b/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.messages.impl.timeline.components_null_DefaultGroup_TimelineItemReactionsViewIncomingPreview-N-9_11_null,NEXUS_5,1.0,en].png
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:76d8e1608b83151e5f444669713808d48db77666b33b5ff44c8ee94b27b6bbca
+size 25465
diff --git a/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.messages.impl.timeline.components_null_DefaultGroup_TimelineItemReactionsViewOutgoingPreview-D-10_11_null,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.messages.impl.timeline.components_null_DefaultGroup_TimelineItemReactionsViewOutgoingPreview-D-10_11_null,NEXUS_5,1.0,en].png
new file mode 100644
index 0000000000..33128653fe
--- /dev/null
+++ b/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.messages.impl.timeline.components_null_DefaultGroup_TimelineItemReactionsViewOutgoingPreview-D-10_11_null,NEXUS_5,1.0,en].png
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:8bbfc46af47025d2e2e22839b939f32b3fdfde904a7a08edcc4cfd270d20b9bf
+size 25750
diff --git a/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.messages.impl.timeline.components_null_DefaultGroup_TimelineItemReactionsViewOutgoingPreview-N-10_12_null,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.messages.impl.timeline.components_null_DefaultGroup_TimelineItemReactionsViewOutgoingPreview-N-10_12_null,NEXUS_5,1.0,en].png
new file mode 100644
index 0000000000..6d5ff5d621
--- /dev/null
+++ b/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.messages.impl.timeline.components_null_DefaultGroup_TimelineItemReactionsViewOutgoingPreview-N-10_12_null,NEXUS_5,1.0,en].png
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:c5ed3ac2e9d4f7c1090677a49ac25bf997ea09d53423ccbdd6b6ab330cf30098
+size 25518
diff --git a/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.messages.impl.timeline.components_null_DefaultGroup_TimelineItemReactionsViewPreview-D-5_6_null,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.messages.impl.timeline.components_null_DefaultGroup_TimelineItemReactionsViewPreview-D-5_6_null,NEXUS_5,1.0,en].png
deleted file mode 100644
index 119678a386..0000000000
--- a/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.messages.impl.timeline.components_null_DefaultGroup_TimelineItemReactionsViewPreview-D-5_6_null,NEXUS_5,1.0,en].png
+++ /dev/null
@@ -1,3 +0,0 @@
-version https://git-lfs.github.com/spec/v1
-oid sha256:82550de45d39c52f34fca45f84b6e9eff53dfef6d2e9622dcaf49c707927d665
-size 7873
diff --git a/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.messages.impl.timeline.components_null_DefaultGroup_TimelineItemReactionsViewPreview-D-7_8_null,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.messages.impl.timeline.components_null_DefaultGroup_TimelineItemReactionsViewPreview-D-7_8_null,NEXUS_5,1.0,en].png
new file mode 100644
index 0000000000..ba0bb563bd
--- /dev/null
+++ b/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.messages.impl.timeline.components_null_DefaultGroup_TimelineItemReactionsViewPreview-D-7_8_null,NEXUS_5,1.0,en].png
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:d75da9638e70268c303f7f1f8affa9302e449d00edef0f21df5155be3ce3ff3e
+size 7646
diff --git a/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.messages.impl.timeline.components_null_DefaultGroup_TimelineItemReactionsViewPreview-N-5_7_null,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.messages.impl.timeline.components_null_DefaultGroup_TimelineItemReactionsViewPreview-N-5_7_null,NEXUS_5,1.0,en].png
deleted file mode 100644
index 896fd1051e..0000000000
--- a/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.messages.impl.timeline.components_null_DefaultGroup_TimelineItemReactionsViewPreview-N-5_7_null,NEXUS_5,1.0,en].png
+++ /dev/null
@@ -1,3 +0,0 @@
-version https://git-lfs.github.com/spec/v1
-oid sha256:fc39041ac035aa372640ca7b2e9af254564aa10ce7a7f4c55fbc4bca9f6dc6d9
-size 7844
diff --git a/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.messages.impl.timeline.components_null_DefaultGroup_TimelineItemReactionsViewPreview-N-7_9_null,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.messages.impl.timeline.components_null_DefaultGroup_TimelineItemReactionsViewPreview-N-7_9_null,NEXUS_5,1.0,en].png
new file mode 100644
index 0000000000..396e287a9d
--- /dev/null
+++ b/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.messages.impl.timeline.components_null_DefaultGroup_TimelineItemReactionsViewPreview-N-7_9_null,NEXUS_5,1.0,en].png
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:cc554dfec200c02710c7ef21be0cb22753b4457e96738d3a74500617d8854e41
+size 7656
diff --git a/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.messages.impl.timeline_null_DefaultGroup_TimelineViewPreview-D-2_3_null_0,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.messages.impl.timeline_null_DefaultGroup_TimelineViewPreview-D-2_3_null_0,NEXUS_5,1.0,en].png
index 7c99f5e856..7a219f8773 100644
--- a/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.messages.impl.timeline_null_DefaultGroup_TimelineViewPreview-D-2_3_null_0,NEXUS_5,1.0,en].png
+++ b/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.messages.impl.timeline_null_DefaultGroup_TimelineViewPreview-D-2_3_null_0,NEXUS_5,1.0,en].png
@@ -1,3 +1,3 @@
 version https://git-lfs.github.com/spec/v1
-oid sha256:54c12970e3563de958f88e4c538dd368f9810266060627393256a91741f7c6cf
-size 53340
+oid sha256:efe8b8964a4588512338873afcdad87ef9d6d1983032997c38e2f74c5cbd279b
+size 52046
diff --git a/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.messages.impl.timeline_null_DefaultGroup_TimelineViewPreview-D-2_3_null_1,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.messages.impl.timeline_null_DefaultGroup_TimelineViewPreview-D-2_3_null_1,NEXUS_5,1.0,en].png
index def9cbe0d1..a66dc2643a 100644
--- a/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.messages.impl.timeline_null_DefaultGroup_TimelineViewPreview-D-2_3_null_1,NEXUS_5,1.0,en].png
+++ b/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.messages.impl.timeline_null_DefaultGroup_TimelineViewPreview-D-2_3_null_1,NEXUS_5,1.0,en].png
@@ -1,3 +1,3 @@
 version https://git-lfs.github.com/spec/v1
-oid sha256:3b7ae3084cb9d1ecee2e4db49c228516bdd7352683e797edf737c8d216922dec
-size 65601
+oid sha256:44135b12caaa2fd0bb814a311e54ccd899c302c10daa4bce09330815ac7fef77
+size 64155
diff --git a/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.messages.impl.timeline_null_DefaultGroup_TimelineViewPreview-D-2_3_null_10,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.messages.impl.timeline_null_DefaultGroup_TimelineViewPreview-D-2_3_null_10,NEXUS_5,1.0,en].png
index 258ce3f3de..3665a2f820 100644
--- a/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.messages.impl.timeline_null_DefaultGroup_TimelineViewPreview-D-2_3_null_10,NEXUS_5,1.0,en].png
+++ b/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.messages.impl.timeline_null_DefaultGroup_TimelineViewPreview-D-2_3_null_10,NEXUS_5,1.0,en].png
@@ -1,3 +1,3 @@
 version https://git-lfs.github.com/spec/v1
-oid sha256:dd034d439c08793e0dfd59f6bd5dcd88c06ded6cbe98172bf3cf296888e6d575
-size 51244
+oid sha256:aa580473120654d5e49e1386c03bc2f813f588af7eb9962c45b9896f6b7b7124
+size 50003
diff --git a/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.messages.impl.timeline_null_DefaultGroup_TimelineViewPreview-D-2_3_null_11,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.messages.impl.timeline_null_DefaultGroup_TimelineViewPreview-D-2_3_null_11,NEXUS_5,1.0,en].png
index b2f16a9d23..f03ba74880 100644
--- a/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.messages.impl.timeline_null_DefaultGroup_TimelineViewPreview-D-2_3_null_11,NEXUS_5,1.0,en].png
+++ b/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.messages.impl.timeline_null_DefaultGroup_TimelineViewPreview-D-2_3_null_11,NEXUS_5,1.0,en].png
@@ -1,3 +1,3 @@
 version https://git-lfs.github.com/spec/v1
-oid sha256:d9d835cb1a420117b4d967181e2ca0fad71ba243d6a17bea08b82cae41f6b8e2
-size 68760
+oid sha256:aa77a7edb5d8194dc7cbfff08d86f3d4b86ceaa900e3391c0d20258a39da95fa
+size 67333
diff --git a/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.messages.impl.timeline_null_DefaultGroup_TimelineViewPreview-D-2_3_null_12,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.messages.impl.timeline_null_DefaultGroup_TimelineViewPreview-D-2_3_null_12,NEXUS_5,1.0,en].png
index 3bbd94a1c8..35f86e9a4a 100644
--- a/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.messages.impl.timeline_null_DefaultGroup_TimelineViewPreview-D-2_3_null_12,NEXUS_5,1.0,en].png
+++ b/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.messages.impl.timeline_null_DefaultGroup_TimelineViewPreview-D-2_3_null_12,NEXUS_5,1.0,en].png
@@ -1,3 +1,3 @@
 version https://git-lfs.github.com/spec/v1
-oid sha256:4ad09278ae2ebb8171adba96d9f6e91d0cc4f120b0b2368087796dadb37eeb87
-size 58539
+oid sha256:5122e480cb7c386427961e1e262dbee7e75b37939a7430235ed6e1d0c47cf544
+size 57260
diff --git a/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.messages.impl.timeline_null_DefaultGroup_TimelineViewPreview-D-2_3_null_2,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.messages.impl.timeline_null_DefaultGroup_TimelineViewPreview-D-2_3_null_2,NEXUS_5,1.0,en].png
index 1c32b14777..b9b4cf2174 100644
--- a/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.messages.impl.timeline_null_DefaultGroup_TimelineViewPreview-D-2_3_null_2,NEXUS_5,1.0,en].png
+++ b/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.messages.impl.timeline_null_DefaultGroup_TimelineViewPreview-D-2_3_null_2,NEXUS_5,1.0,en].png
@@ -1,3 +1,3 @@
 version https://git-lfs.github.com/spec/v1
-oid sha256:145856c3a7ff43702403ee5b86a7119b0475f03fdbc0f2e7f84e10350a64b150
-size 229842
+oid sha256:21b5e874428ef5912442d3a92ed694f0f016c3236781a02886c5c3a589bbb317
+size 229385
diff --git a/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.messages.impl.timeline_null_DefaultGroup_TimelineViewPreview-D-2_3_null_3,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.messages.impl.timeline_null_DefaultGroup_TimelineViewPreview-D-2_3_null_3,NEXUS_5,1.0,en].png
index 53f57d95d2..450b33d8c2 100644
--- a/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.messages.impl.timeline_null_DefaultGroup_TimelineViewPreview-D-2_3_null_3,NEXUS_5,1.0,en].png
+++ b/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.messages.impl.timeline_null_DefaultGroup_TimelineViewPreview-D-2_3_null_3,NEXUS_5,1.0,en].png
@@ -1,3 +1,3 @@
 version https://git-lfs.github.com/spec/v1
-oid sha256:c1f0939b0c22ab89466953889e5bb63e11c45f02af79eeba3f377409af61d356
-size 230809
+oid sha256:0883699f8e551930478d0e43540497bea6f1cd9fe6f2b95df5c5e36370eb3a9a
+size 230368
diff --git a/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.messages.impl.timeline_null_DefaultGroup_TimelineViewPreview-D-2_3_null_4,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.messages.impl.timeline_null_DefaultGroup_TimelineViewPreview-D-2_3_null_4,NEXUS_5,1.0,en].png
index 4c991e3c30..86f0aa481a 100644
--- a/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.messages.impl.timeline_null_DefaultGroup_TimelineViewPreview-D-2_3_null_4,NEXUS_5,1.0,en].png
+++ b/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.messages.impl.timeline_null_DefaultGroup_TimelineViewPreview-D-2_3_null_4,NEXUS_5,1.0,en].png
@@ -1,3 +1,3 @@
 version https://git-lfs.github.com/spec/v1
-oid sha256:082206122d4e6d9e6171b3b2444c576ff7bd47fb3946d8d98e2812654f39cd40
-size 73641
+oid sha256:dae5b99b3234fe999673593dfe75feb44b0122e872af62dd2bed0db610132655
+size 72595
diff --git a/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.messages.impl.timeline_null_DefaultGroup_TimelineViewPreview-D-2_3_null_5,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.messages.impl.timeline_null_DefaultGroup_TimelineViewPreview-D-2_3_null_5,NEXUS_5,1.0,en].png
index 80eeb03c19..fffa0ebe9c 100644
--- a/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.messages.impl.timeline_null_DefaultGroup_TimelineViewPreview-D-2_3_null_5,NEXUS_5,1.0,en].png
+++ b/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.messages.impl.timeline_null_DefaultGroup_TimelineViewPreview-D-2_3_null_5,NEXUS_5,1.0,en].png
@@ -1,3 +1,3 @@
 version https://git-lfs.github.com/spec/v1
-oid sha256:dc695bfc589e8e5a852eeb9b2828ce968d17519bb5be957cf2734a7d6d9cc356
-size 89482
+oid sha256:74880d4c54a6ec9eff418ffdaa1da5888cc1b1ce4d92f958c36c36c7947a6321
+size 88190
diff --git a/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.messages.impl.timeline_null_DefaultGroup_TimelineViewPreview-D-2_3_null_6,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.messages.impl.timeline_null_DefaultGroup_TimelineViewPreview-D-2_3_null_6,NEXUS_5,1.0,en].png
index 727cfa4b3c..d49e704e4b 100644
--- a/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.messages.impl.timeline_null_DefaultGroup_TimelineViewPreview-D-2_3_null_6,NEXUS_5,1.0,en].png
+++ b/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.messages.impl.timeline_null_DefaultGroup_TimelineViewPreview-D-2_3_null_6,NEXUS_5,1.0,en].png
@@ -1,3 +1,3 @@
 version https://git-lfs.github.com/spec/v1
-oid sha256:9efb4310c2eed085f8f72be66d725c628e07373cd18c262c18be510d7b042f69
-size 393373
+oid sha256:a71e1d72dd7af142b2a8bb09810a416f43f619c697ed9c0c1cdf3d85df0259f5
+size 392639
diff --git a/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.messages.impl.timeline_null_DefaultGroup_TimelineViewPreview-D-2_3_null_7,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.messages.impl.timeline_null_DefaultGroup_TimelineViewPreview-D-2_3_null_7,NEXUS_5,1.0,en].png
index 9c29642146..0290995c54 100644
--- a/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.messages.impl.timeline_null_DefaultGroup_TimelineViewPreview-D-2_3_null_7,NEXUS_5,1.0,en].png
+++ b/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.messages.impl.timeline_null_DefaultGroup_TimelineViewPreview-D-2_3_null_7,NEXUS_5,1.0,en].png
@@ -1,3 +1,3 @@
 version https://git-lfs.github.com/spec/v1
-oid sha256:19982d091ffcb15a422e75461adb3d039775645eaf74b6bfd4a3ee617dd4555f
-size 347932
+oid sha256:52d83b9001db80db98e0a837672f218a77736e65549f5e31466f8aecadbfff54
+size 347295
diff --git a/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.messages.impl.timeline_null_DefaultGroup_TimelineViewPreview-D-2_3_null_8,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.messages.impl.timeline_null_DefaultGroup_TimelineViewPreview-D-2_3_null_8,NEXUS_5,1.0,en].png
index ef081b76b8..1f8e834b83 100644
--- a/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.messages.impl.timeline_null_DefaultGroup_TimelineViewPreview-D-2_3_null_8,NEXUS_5,1.0,en].png
+++ b/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.messages.impl.timeline_null_DefaultGroup_TimelineViewPreview-D-2_3_null_8,NEXUS_5,1.0,en].png
@@ -1,3 +1,3 @@
 version https://git-lfs.github.com/spec/v1
-oid sha256:9a243d53d10ca2eaa249b22af8a9fddf1a8ccf60db4f3ad9374e31cf494fe878
-size 54909
+oid sha256:79a36eab1ad6523438954ff55aa21ac92cd349f119e8eab4b61d25b4c44a56b1
+size 53627
diff --git a/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.messages.impl.timeline_null_DefaultGroup_TimelineViewPreview-D-2_3_null_9,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.messages.impl.timeline_null_DefaultGroup_TimelineViewPreview-D-2_3_null_9,NEXUS_5,1.0,en].png
index 0b13a93b0c..585b1e3980 100644
--- a/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.messages.impl.timeline_null_DefaultGroup_TimelineViewPreview-D-2_3_null_9,NEXUS_5,1.0,en].png
+++ b/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.messages.impl.timeline_null_DefaultGroup_TimelineViewPreview-D-2_3_null_9,NEXUS_5,1.0,en].png
@@ -1,3 +1,3 @@
 version https://git-lfs.github.com/spec/v1
-oid sha256:3fdd478be89b47fcaf9725ca14c1e775087f1ccf2a266f3476a537bbc2b29922
-size 67476
+oid sha256:f7b35322f9f344fb49ab2e2642a28c1c04bfd960a0354b4382240886616658bc
+size 66053
diff --git a/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.messages.impl.timeline_null_DefaultGroup_TimelineViewPreview-N-2_4_null_0,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.messages.impl.timeline_null_DefaultGroup_TimelineViewPreview-N-2_4_null_0,NEXUS_5,1.0,en].png
index 9f5b7d48c6..d52711f7e7 100644
--- a/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.messages.impl.timeline_null_DefaultGroup_TimelineViewPreview-N-2_4_null_0,NEXUS_5,1.0,en].png
+++ b/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.messages.impl.timeline_null_DefaultGroup_TimelineViewPreview-N-2_4_null_0,NEXUS_5,1.0,en].png
@@ -1,3 +1,3 @@
 version https://git-lfs.github.com/spec/v1
-oid sha256:1a3b5bbcdd1593e81384b335045bdcb0b3e01782868993e9f6437a15ca39dbca
-size 51380
+oid sha256:3e6daf18be28261abd6753b39faa6f7bfc0b820d9e42a1bb0188cb4cc8ced6b4
+size 50224
diff --git a/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.messages.impl.timeline_null_DefaultGroup_TimelineViewPreview-N-2_4_null_1,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.messages.impl.timeline_null_DefaultGroup_TimelineViewPreview-N-2_4_null_1,NEXUS_5,1.0,en].png
index ba9f8a8d63..ac85571fb0 100644
--- a/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.messages.impl.timeline_null_DefaultGroup_TimelineViewPreview-N-2_4_null_1,NEXUS_5,1.0,en].png
+++ b/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.messages.impl.timeline_null_DefaultGroup_TimelineViewPreview-N-2_4_null_1,NEXUS_5,1.0,en].png
@@ -1,3 +1,3 @@
 version https://git-lfs.github.com/spec/v1
-oid sha256:7e26db0a0a8d767d6e732c1d2742cba3c3475d761b0c3017ff01cee7e3d362a5
-size 62773
+oid sha256:5146396bf9b765169c583b14da54b43d55b2d306cf35890d500fde90be3fd36b
+size 61348
diff --git a/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.messages.impl.timeline_null_DefaultGroup_TimelineViewPreview-N-2_4_null_10,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.messages.impl.timeline_null_DefaultGroup_TimelineViewPreview-N-2_4_null_10,NEXUS_5,1.0,en].png
index 7d12d81b18..4a9590eb47 100644
--- a/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.messages.impl.timeline_null_DefaultGroup_TimelineViewPreview-N-2_4_null_10,NEXUS_5,1.0,en].png
+++ b/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.messages.impl.timeline_null_DefaultGroup_TimelineViewPreview-N-2_4_null_10,NEXUS_5,1.0,en].png
@@ -1,3 +1,3 @@
 version https://git-lfs.github.com/spec/v1
-oid sha256:3d5cae7d73178aecc12fbf5f1f27c9e66608b90d462deec862a881b403469e93
-size 49475
+oid sha256:28d13b05def8bc769e61a5814b6c96afe704c773d1d86f6d11b2021ebce81035
+size 48407
diff --git a/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.messages.impl.timeline_null_DefaultGroup_TimelineViewPreview-N-2_4_null_11,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.messages.impl.timeline_null_DefaultGroup_TimelineViewPreview-N-2_4_null_11,NEXUS_5,1.0,en].png
index 44fd92b664..06b5d396e4 100644
--- a/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.messages.impl.timeline_null_DefaultGroup_TimelineViewPreview-N-2_4_null_11,NEXUS_5,1.0,en].png
+++ b/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.messages.impl.timeline_null_DefaultGroup_TimelineViewPreview-N-2_4_null_11,NEXUS_5,1.0,en].png
@@ -1,3 +1,3 @@
 version https://git-lfs.github.com/spec/v1
-oid sha256:fe9456f4446104142221e28167a578a2b5cac772dc35aeb14352c0d422dd6fb0
-size 65726
+oid sha256:2d23ccbe1a72f6b375cd1eca980127ada3b8aa39aeb8b29e2a7caf80aea76165
+size 64255
diff --git a/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.messages.impl.timeline_null_DefaultGroup_TimelineViewPreview-N-2_4_null_12,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.messages.impl.timeline_null_DefaultGroup_TimelineViewPreview-N-2_4_null_12,NEXUS_5,1.0,en].png
index ee3a9ae3fe..289c358d9e 100644
--- a/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.messages.impl.timeline_null_DefaultGroup_TimelineViewPreview-N-2_4_null_12,NEXUS_5,1.0,en].png
+++ b/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.messages.impl.timeline_null_DefaultGroup_TimelineViewPreview-N-2_4_null_12,NEXUS_5,1.0,en].png
@@ -1,3 +1,3 @@
 version https://git-lfs.github.com/spec/v1
-oid sha256:cad3b5ce023d890fd4a5ff0f5bbabb678bc6d5c76d3476e8053673c06f360c8b
-size 56102
+oid sha256:9adc9689e6e88eea0fa467713bcf8941ca645219ce6e6f3cf4dd215c3d1301de
+size 54965
diff --git a/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.messages.impl.timeline_null_DefaultGroup_TimelineViewPreview-N-2_4_null_2,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.messages.impl.timeline_null_DefaultGroup_TimelineViewPreview-N-2_4_null_2,NEXUS_5,1.0,en].png
index 8e578cb1f9..6bd18e0e57 100644
--- a/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.messages.impl.timeline_null_DefaultGroup_TimelineViewPreview-N-2_4_null_2,NEXUS_5,1.0,en].png
+++ b/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.messages.impl.timeline_null_DefaultGroup_TimelineViewPreview-N-2_4_null_2,NEXUS_5,1.0,en].png
@@ -1,3 +1,3 @@
 version https://git-lfs.github.com/spec/v1
-oid sha256:71b3c712fb8e4bca178afed2de6f4184bb717e3415622e97f14bb4fe36aaf9d5
-size 229097
+oid sha256:c471afa95f769bc06f52ccead68e7f50db5f6be436380e43b47c564b299fc2ee
+size 228623
diff --git a/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.messages.impl.timeline_null_DefaultGroup_TimelineViewPreview-N-2_4_null_3,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.messages.impl.timeline_null_DefaultGroup_TimelineViewPreview-N-2_4_null_3,NEXUS_5,1.0,en].png
index 13d92ee329..a841399bab 100644
--- a/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.messages.impl.timeline_null_DefaultGroup_TimelineViewPreview-N-2_4_null_3,NEXUS_5,1.0,en].png
+++ b/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.messages.impl.timeline_null_DefaultGroup_TimelineViewPreview-N-2_4_null_3,NEXUS_5,1.0,en].png
@@ -1,3 +1,3 @@
 version https://git-lfs.github.com/spec/v1
-oid sha256:f44d772e5b9fe65a79e05aaaa82536b19382f9d821c0412c47a7d330d539ffd2
-size 230080
+oid sha256:be72eda04000150aefc4570d68015d21e7647f448bbcd69ea2d75e62ec0b4caf
+size 229617
diff --git a/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.messages.impl.timeline_null_DefaultGroup_TimelineViewPreview-N-2_4_null_4,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.messages.impl.timeline_null_DefaultGroup_TimelineViewPreview-N-2_4_null_4,NEXUS_5,1.0,en].png
index 4a58253b47..3eca13fcfa 100644
--- a/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.messages.impl.timeline_null_DefaultGroup_TimelineViewPreview-N-2_4_null_4,NEXUS_5,1.0,en].png
+++ b/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.messages.impl.timeline_null_DefaultGroup_TimelineViewPreview-N-2_4_null_4,NEXUS_5,1.0,en].png
@@ -1,3 +1,3 @@
 version https://git-lfs.github.com/spec/v1
-oid sha256:41a6c2dd81698696708802276b615a78ff22cc7cb8ae2d4b8d8cc862bfe44a24
-size 70856
+oid sha256:c14449fed7d0364077dc8c5804064dccb7b2969595c4c58e8da07fe03ccbe1bc
+size 69731
diff --git a/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.messages.impl.timeline_null_DefaultGroup_TimelineViewPreview-N-2_4_null_5,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.messages.impl.timeline_null_DefaultGroup_TimelineViewPreview-N-2_4_null_5,NEXUS_5,1.0,en].png
index fdb8345d8c..6ebc0f4cd2 100644
--- a/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.messages.impl.timeline_null_DefaultGroup_TimelineViewPreview-N-2_4_null_5,NEXUS_5,1.0,en].png
+++ b/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.messages.impl.timeline_null_DefaultGroup_TimelineViewPreview-N-2_4_null_5,NEXUS_5,1.0,en].png
@@ -1,3 +1,3 @@
 version https://git-lfs.github.com/spec/v1
-oid sha256:167f8368e0b94aa05e5d1cc30055e3b0c2c910752d719092ef2d34aae09dc832
-size 84649
+oid sha256:5e29e1504333aa44eae6c3eb4af64c337fce01af895c7b920781ca895e6ea5a8
+size 83402
diff --git a/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.messages.impl.timeline_null_DefaultGroup_TimelineViewPreview-N-2_4_null_6,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.messages.impl.timeline_null_DefaultGroup_TimelineViewPreview-N-2_4_null_6,NEXUS_5,1.0,en].png
index 2a6187d9a3..f8c0aa4bd2 100644
--- a/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.messages.impl.timeline_null_DefaultGroup_TimelineViewPreview-N-2_4_null_6,NEXUS_5,1.0,en].png
+++ b/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.messages.impl.timeline_null_DefaultGroup_TimelineViewPreview-N-2_4_null_6,NEXUS_5,1.0,en].png
@@ -1,3 +1,3 @@
 version https://git-lfs.github.com/spec/v1
-oid sha256:6ee754e789926bfd12212a21b6ff882ffca337d6903125ba5e1d7cd0c1c218ec
-size 189364
+oid sha256:9045218a096f1104f1672f733fd0cfa21114dbc41d11062d4418febadb659c54
+size 189065
diff --git a/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.messages.impl.timeline_null_DefaultGroup_TimelineViewPreview-N-2_4_null_7,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.messages.impl.timeline_null_DefaultGroup_TimelineViewPreview-N-2_4_null_7,NEXUS_5,1.0,en].png
index a65dbca59c..5f16ee28ee 100644
--- a/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.messages.impl.timeline_null_DefaultGroup_TimelineViewPreview-N-2_4_null_7,NEXUS_5,1.0,en].png
+++ b/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.messages.impl.timeline_null_DefaultGroup_TimelineViewPreview-N-2_4_null_7,NEXUS_5,1.0,en].png
@@ -1,3 +1,3 @@
 version https://git-lfs.github.com/spec/v1
-oid sha256:29f9ba8c19287b037f67aec5af4469174eb878b7ed5baf222f66e159faee6e16
-size 178410
+oid sha256:17afd91f19020067c3ef1b739834222e208d378e0a51cf37aa31063e187c7244
+size 178149
diff --git a/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.messages.impl.timeline_null_DefaultGroup_TimelineViewPreview-N-2_4_null_8,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.messages.impl.timeline_null_DefaultGroup_TimelineViewPreview-N-2_4_null_8,NEXUS_5,1.0,en].png
index 08c13f8f2a..b5dbff5ef8 100644
--- a/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.messages.impl.timeline_null_DefaultGroup_TimelineViewPreview-N-2_4_null_8,NEXUS_5,1.0,en].png
+++ b/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.messages.impl.timeline_null_DefaultGroup_TimelineViewPreview-N-2_4_null_8,NEXUS_5,1.0,en].png
@@ -1,3 +1,3 @@
 version https://git-lfs.github.com/spec/v1
-oid sha256:789ee5ccad8356198cdc0634b4e9a65ed44be2d26e7ce83a8662598c1bd8d4c2
-size 52765
+oid sha256:45974a6f6a441f1214bd557c218877bc756ad49b4bd3e03313915ef9cfb9ac3c
+size 51578
diff --git a/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.messages.impl.timeline_null_DefaultGroup_TimelineViewPreview-N-2_4_null_9,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.messages.impl.timeline_null_DefaultGroup_TimelineViewPreview-N-2_4_null_9,NEXUS_5,1.0,en].png
index 300bcf7167..f04e4afe02 100644
--- a/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.messages.impl.timeline_null_DefaultGroup_TimelineViewPreview-N-2_4_null_9,NEXUS_5,1.0,en].png
+++ b/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.messages.impl.timeline_null_DefaultGroup_TimelineViewPreview-N-2_4_null_9,NEXUS_5,1.0,en].png
@@ -1,3 +1,3 @@
 version https://git-lfs.github.com/spec/v1
-oid sha256:7b40a2e5d60a906d7c35c3ece1854671f5b319b00ad077322d094cbf906c07f7
-size 64803
+oid sha256:713006427939a992312a0d7023afe3c81810caa5b879792c92ee89ee93881113
+size 63357
diff --git a/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.messages.impl_null_DefaultGroup_MessagesViewDarkPreview_0_null_0,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.messages.impl_null_DefaultGroup_MessagesViewDarkPreview_0_null_0,NEXUS_5,1.0,en].png
index 101f913aa8..791a623ef1 100644
--- a/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.messages.impl_null_DefaultGroup_MessagesViewDarkPreview_0_null_0,NEXUS_5,1.0,en].png
+++ b/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.messages.impl_null_DefaultGroup_MessagesViewDarkPreview_0_null_0,NEXUS_5,1.0,en].png
@@ -1,3 +1,3 @@
 version https://git-lfs.github.com/spec/v1
-oid sha256:7c724bc77185a9ceec2cf092cb1d7865b13718d5320bd7ac4850bb85590f05b2
-size 52294
+oid sha256:3959ae6151f02d7f41afe498b57a9b55255ea88335504d9d17750259100db1bc
+size 51232
diff --git a/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.messages.impl_null_DefaultGroup_MessagesViewDarkPreview_0_null_1,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.messages.impl_null_DefaultGroup_MessagesViewDarkPreview_0_null_1,NEXUS_5,1.0,en].png
index cb28314caa..633b9ae8b1 100644
--- a/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.messages.impl_null_DefaultGroup_MessagesViewDarkPreview_0_null_1,NEXUS_5,1.0,en].png
+++ b/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.messages.impl_null_DefaultGroup_MessagesViewDarkPreview_0_null_1,NEXUS_5,1.0,en].png
@@ -1,3 +1,3 @@
 version https://git-lfs.github.com/spec/v1
-oid sha256:a303894134ed06348b609e41cf109dcafcd994c3dffabc6d9ab436fe92605245
-size 53710
+oid sha256:432f2a5451368679c076515406808f1b136b3db8239841b7ffa65417c3d9b901
+size 52632
diff --git a/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.messages.impl_null_DefaultGroup_MessagesViewDarkPreview_0_null_2,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.messages.impl_null_DefaultGroup_MessagesViewDarkPreview_0_null_2,NEXUS_5,1.0,en].png
index 2ba437739f..a8162ad980 100644
--- a/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.messages.impl_null_DefaultGroup_MessagesViewDarkPreview_0_null_2,NEXUS_5,1.0,en].png
+++ b/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.messages.impl_null_DefaultGroup_MessagesViewDarkPreview_0_null_2,NEXUS_5,1.0,en].png
@@ -1,3 +1,3 @@
 version https://git-lfs.github.com/spec/v1
-oid sha256:7523ec0d6defd7074af0c804fdde64fb8d421f6cfa729bc1c4f9858bd87c42d0
-size 52554
+oid sha256:610aeadaa817fd4e50471fda96fe24aceb48ddb03a0e58d0305abdb96553e8ec
+size 51463
diff --git a/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.messages.impl_null_DefaultGroup_MessagesViewDarkPreview_0_null_3,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.messages.impl_null_DefaultGroup_MessagesViewDarkPreview_0_null_3,NEXUS_5,1.0,en].png
index 73715a33a2..b36175d6f2 100644
--- a/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.messages.impl_null_DefaultGroup_MessagesViewDarkPreview_0_null_3,NEXUS_5,1.0,en].png
+++ b/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.messages.impl_null_DefaultGroup_MessagesViewDarkPreview_0_null_3,NEXUS_5,1.0,en].png
@@ -1,3 +1,3 @@
 version https://git-lfs.github.com/spec/v1
-oid sha256:1f48089147f7e089abfa64254143a80857ccc9f840aa60403e1aabc67e2b6d51
-size 55458
+oid sha256:ca313b8e0c24369bee836649c7984ac18783893211df46f792e36261bbac0bc5
+size 54170
diff --git a/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.messages.impl_null_DefaultGroup_MessagesViewDarkPreview_0_null_4,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.messages.impl_null_DefaultGroup_MessagesViewDarkPreview_0_null_4,NEXUS_5,1.0,en].png
index 9ce6f92309..cffa085a04 100644
--- a/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.messages.impl_null_DefaultGroup_MessagesViewDarkPreview_0_null_4,NEXUS_5,1.0,en].png
+++ b/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.messages.impl_null_DefaultGroup_MessagesViewDarkPreview_0_null_4,NEXUS_5,1.0,en].png
@@ -1,3 +1,3 @@
 version https://git-lfs.github.com/spec/v1
-oid sha256:7ff682ee8363d450bb76db72ea06deea87fa47692ce319b7dff315d2a10dfb6a
-size 51033
+oid sha256:9272791f4ed5afde353ea893988fd1140bb6b090f19901c0bbfb25ba37e07e52
+size 51100
diff --git a/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.messages.impl_null_DefaultGroup_MessagesViewDarkPreview_0_null_5,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.messages.impl_null_DefaultGroup_MessagesViewDarkPreview_0_null_5,NEXUS_5,1.0,en].png
new file mode 100644
index 0000000000..5bb2141eb2
--- /dev/null
+++ b/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.messages.impl_null_DefaultGroup_MessagesViewDarkPreview_0_null_5,NEXUS_5,1.0,en].png
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:51320b6491f229241d6ed52aaab871ea217d32ebe42ac42496bd702543ee45ff
+size 48800
diff --git a/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.messages.impl_null_DefaultGroup_MessagesViewLightPreview_0_null_0,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.messages.impl_null_DefaultGroup_MessagesViewLightPreview_0_null_0,NEXUS_5,1.0,en].png
index 57eeca6786..5a207ffda8 100644
--- a/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.messages.impl_null_DefaultGroup_MessagesViewLightPreview_0_null_0,NEXUS_5,1.0,en].png
+++ b/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.messages.impl_null_DefaultGroup_MessagesViewLightPreview_0_null_0,NEXUS_5,1.0,en].png
@@ -1,3 +1,3 @@
 version https://git-lfs.github.com/spec/v1
-oid sha256:e84edf8adf1a89153dd45272d36e04561d66f2ea765ad9edecfd8d750ba99f97
-size 54237
+oid sha256:2d1da7016a99ce5c913f1f0c3c7c8047531af13412b846685683160212e88ef5
+size 53061
diff --git a/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.messages.impl_null_DefaultGroup_MessagesViewLightPreview_0_null_1,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.messages.impl_null_DefaultGroup_MessagesViewLightPreview_0_null_1,NEXUS_5,1.0,en].png
index 8baf81c8b1..4583dd5346 100644
--- a/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.messages.impl_null_DefaultGroup_MessagesViewLightPreview_0_null_1,NEXUS_5,1.0,en].png
+++ b/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.messages.impl_null_DefaultGroup_MessagesViewLightPreview_0_null_1,NEXUS_5,1.0,en].png
@@ -1,3 +1,3 @@
 version https://git-lfs.github.com/spec/v1
-oid sha256:0bc9521bd1576d47ca6f643adf43ce3638d40328207d908ec863c72503d34f24
-size 55682
+oid sha256:962cebd43ee1f0872c25413d8a62c9dd279751e00b9c2154f156e49fd8c25ebd
+size 54554
diff --git a/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.messages.impl_null_DefaultGroup_MessagesViewLightPreview_0_null_2,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.messages.impl_null_DefaultGroup_MessagesViewLightPreview_0_null_2,NEXUS_5,1.0,en].png
index 40900d7e92..2d30ca5d01 100644
--- a/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.messages.impl_null_DefaultGroup_MessagesViewLightPreview_0_null_2,NEXUS_5,1.0,en].png
+++ b/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.messages.impl_null_DefaultGroup_MessagesViewLightPreview_0_null_2,NEXUS_5,1.0,en].png
@@ -1,3 +1,3 @@
 version https://git-lfs.github.com/spec/v1
-oid sha256:c2209c3cc4e7de32ed92b3b0da4616b54d19091d43d21c0e4013728450d0d3f7
-size 54595
+oid sha256:50b8c157da1134708777ce4940c58f50a48414e837762064059d44082a0303f7
+size 53415
diff --git a/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.messages.impl_null_DefaultGroup_MessagesViewLightPreview_0_null_3,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.messages.impl_null_DefaultGroup_MessagesViewLightPreview_0_null_3,NEXUS_5,1.0,en].png
index 5777c7f77e..7d4f85fbe9 100644
--- a/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.messages.impl_null_DefaultGroup_MessagesViewLightPreview_0_null_3,NEXUS_5,1.0,en].png
+++ b/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.messages.impl_null_DefaultGroup_MessagesViewLightPreview_0_null_3,NEXUS_5,1.0,en].png
@@ -1,3 +1,3 @@
 version https://git-lfs.github.com/spec/v1
-oid sha256:d7bdd0ca39534b31c9d421e28337712b1cf2aaf841a766fcc6bdaf996c756bfa
-size 57524
+oid sha256:e5ef4489d60dcb1ae6f976e229849af0c89dbeb7bcd4e37a92f18e2514387a1d
+size 56253
diff --git a/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.messages.impl_null_DefaultGroup_MessagesViewLightPreview_0_null_4,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.messages.impl_null_DefaultGroup_MessagesViewLightPreview_0_null_4,NEXUS_5,1.0,en].png
index 2e2bfa89cb..d33576a149 100644
--- a/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.messages.impl_null_DefaultGroup_MessagesViewLightPreview_0_null_4,NEXUS_5,1.0,en].png
+++ b/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.messages.impl_null_DefaultGroup_MessagesViewLightPreview_0_null_4,NEXUS_5,1.0,en].png
@@ -1,3 +1,3 @@
 version https://git-lfs.github.com/spec/v1
-oid sha256:ba349f81d5c417c612cae1263504ea5b4e83dc606ec20c3942368e8992b87ad4
-size 52886
+oid sha256:4d6f69846650213dc6b218c97e2eb8319b5fccaa9451822b23c6c2cf9d46b339
+size 53653
diff --git a/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.messages.impl_null_DefaultGroup_MessagesViewLightPreview_0_null_5,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.messages.impl_null_DefaultGroup_MessagesViewLightPreview_0_null_5,NEXUS_5,1.0,en].png
new file mode 100644
index 0000000000..5405001cce
--- /dev/null
+++ b/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.messages.impl_null_DefaultGroup_MessagesViewLightPreview_0_null_5,NEXUS_5,1.0,en].png
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:a0a704d06f30f34414495bc6c74ac9a69bae32f62d0d9608c8ac43550c0cc7be
+size 50426
diff --git a/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.networkmonitor.api.ui_null_DefaultGroup_PreviewDarkConnectivityIndicatorView_0_null,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.networkmonitor.api.ui_null_DefaultGroup_PreviewDarkConnectivityIndicatorView_0_null,NEXUS_5,1.0,en].png
index fd00dfae33..41503c31be 100644
--- a/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.networkmonitor.api.ui_null_DefaultGroup_PreviewDarkConnectivityIndicatorView_0_null,NEXUS_5,1.0,en].png
+++ b/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.networkmonitor.api.ui_null_DefaultGroup_PreviewDarkConnectivityIndicatorView_0_null,NEXUS_5,1.0,en].png
@@ -1,3 +1,3 @@
 version https://git-lfs.github.com/spec/v1
-oid sha256:9e0c73b8d86c064ce46ade6477cc91803d543199657e597a15a7e21bdacab7be
-size 6541
+oid sha256:774ece5436ab5a025a6a7134120069922276329bf87408a90263bb8c425a0568
+size 6510
diff --git a/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.networkmonitor.api.ui_null_DefaultGroup_PreviewLightConnectivityIndicatorView_0_null,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.networkmonitor.api.ui_null_DefaultGroup_PreviewLightConnectivityIndicatorView_0_null,NEXUS_5,1.0,en].png
index 820b688066..b41bc75694 100644
--- a/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.networkmonitor.api.ui_null_DefaultGroup_PreviewLightConnectivityIndicatorView_0_null,NEXUS_5,1.0,en].png
+++ b/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.networkmonitor.api.ui_null_DefaultGroup_PreviewLightConnectivityIndicatorView_0_null,NEXUS_5,1.0,en].png
@@ -1,3 +1,3 @@
 version https://git-lfs.github.com/spec/v1
-oid sha256:3af4d7ce438da56851aa3041138558d8e57ac181775476b983646039a1cb62ae
-size 6602
+oid sha256:55aff072541c752abd0a8fe48c73b38b42ea47ab4779a2a3ae37a449f88ffd24
+size 6606
diff --git a/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.onboarding.impl_null_DefaultGroup_OnBoardingScreenPreview-D-0_0_null_0,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.onboarding.impl_null_DefaultGroup_OnBoardingScreenPreview-D-0_0_null_0,NEXUS_5,1.0,en].png
index 636c99bead..232570b461 100644
--- a/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.onboarding.impl_null_DefaultGroup_OnBoardingScreenPreview-D-0_0_null_0,NEXUS_5,1.0,en].png
+++ b/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.onboarding.impl_null_DefaultGroup_OnBoardingScreenPreview-D-0_0_null_0,NEXUS_5,1.0,en].png
@@ -1,3 +1,3 @@
 version https://git-lfs.github.com/spec/v1
-oid sha256:75bea68dfb5165f0f8c755237b627f5c61411fb2ff4d55a18d1daedf054d15ff
-size 338382
+oid sha256:56f53e2c13480d5f31d38c671612c81fa802e1f35a55ada99d544917f01b91ba
+size 338952
diff --git a/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.onboarding.impl_null_DefaultGroup_OnBoardingScreenPreview-D-0_0_null_1,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.onboarding.impl_null_DefaultGroup_OnBoardingScreenPreview-D-0_0_null_1,NEXUS_5,1.0,en].png
index 14d6ab78da..45d008bb1b 100644
--- a/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.onboarding.impl_null_DefaultGroup_OnBoardingScreenPreview-D-0_0_null_1,NEXUS_5,1.0,en].png
+++ b/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.onboarding.impl_null_DefaultGroup_OnBoardingScreenPreview-D-0_0_null_1,NEXUS_5,1.0,en].png
@@ -1,3 +1,3 @@
 version https://git-lfs.github.com/spec/v1
-oid sha256:66e66c919bcc118c87c1d1095d03a105d42f3d630466f0a08d2cef011e67e9e4
-size 327542
+oid sha256:cfe3663daab250bcd733ab746e4864472691b40cf927a3cd73d15b323dec2b68
+size 329945
diff --git a/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.onboarding.impl_null_DefaultGroup_OnBoardingScreenPreview-D-0_0_null_2,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.onboarding.impl_null_DefaultGroup_OnBoardingScreenPreview-D-0_0_null_2,NEXUS_5,1.0,en].png
index 5cadf29e4c..7349cf6808 100644
--- a/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.onboarding.impl_null_DefaultGroup_OnBoardingScreenPreview-D-0_0_null_2,NEXUS_5,1.0,en].png
+++ b/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.onboarding.impl_null_DefaultGroup_OnBoardingScreenPreview-D-0_0_null_2,NEXUS_5,1.0,en].png
@@ -1,3 +1,3 @@
 version https://git-lfs.github.com/spec/v1
-oid sha256:9c3c01fb242bd0be1dd894542b3980d359e9276a55afe019ba95423eb7eec7a2
-size 340958
+oid sha256:c449e6e4162f12a6be7faa668b930b294489ae217c2a7493f5671145a926079e
+size 340944
diff --git a/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.onboarding.impl_null_DefaultGroup_OnBoardingScreenPreview-D-0_0_null_3,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.onboarding.impl_null_DefaultGroup_OnBoardingScreenPreview-D-0_0_null_3,NEXUS_5,1.0,en].png
index 68cacc0096..e6a8465877 100644
--- a/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.onboarding.impl_null_DefaultGroup_OnBoardingScreenPreview-D-0_0_null_3,NEXUS_5,1.0,en].png
+++ b/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.onboarding.impl_null_DefaultGroup_OnBoardingScreenPreview-D-0_0_null_3,NEXUS_5,1.0,en].png
@@ -1,3 +1,3 @@
 version https://git-lfs.github.com/spec/v1
-oid sha256:595309f942c0ddc37965b8c1e2ef7afd2dc896929e71efd0696ad9214178c9ab
-size 322751
+oid sha256:0355120442254880360b982df6c2c7cce84a471f632436c96e79ffafed35de14
+size 324378
diff --git a/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.onboarding.impl_null_DefaultGroup_OnBoardingScreenPreview-N-0_1_null_0,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.onboarding.impl_null_DefaultGroup_OnBoardingScreenPreview-N-0_1_null_0,NEXUS_5,1.0,en].png
index f32ba6cbaf..98974210b9 100644
--- a/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.onboarding.impl_null_DefaultGroup_OnBoardingScreenPreview-N-0_1_null_0,NEXUS_5,1.0,en].png
+++ b/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.onboarding.impl_null_DefaultGroup_OnBoardingScreenPreview-N-0_1_null_0,NEXUS_5,1.0,en].png
@@ -1,3 +1,3 @@
 version https://git-lfs.github.com/spec/v1
-oid sha256:69c933682865e48212cad79bb2194f2bb20a8133e7c76ac1f53f8691445e840d
-size 421976
+oid sha256:5d05151967955c961ca47619de2f28f86d0350299b61fbef0371c1706439a844
+size 421908
diff --git a/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.onboarding.impl_null_DefaultGroup_OnBoardingScreenPreview-N-0_1_null_1,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.onboarding.impl_null_DefaultGroup_OnBoardingScreenPreview-N-0_1_null_1,NEXUS_5,1.0,en].png
index ebb9513813..28985b1af6 100644
--- a/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.onboarding.impl_null_DefaultGroup_OnBoardingScreenPreview-N-0_1_null_1,NEXUS_5,1.0,en].png
+++ b/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.onboarding.impl_null_DefaultGroup_OnBoardingScreenPreview-N-0_1_null_1,NEXUS_5,1.0,en].png
@@ -1,3 +1,3 @@
 version https://git-lfs.github.com/spec/v1
-oid sha256:afcb322f07f594e26b051146b22919daf35317c844669e6204c1f4d29f9fb7ad
-size 404245
+oid sha256:3a2056882e65afe8fc2d0dc60efc7912ca5674acb57e3690136a8704f9f063ed
+size 407942
diff --git a/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.onboarding.impl_null_DefaultGroup_OnBoardingScreenPreview-N-0_1_null_2,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.onboarding.impl_null_DefaultGroup_OnBoardingScreenPreview-N-0_1_null_2,NEXUS_5,1.0,en].png
index 2c884eeef0..2622fa3931 100644
--- a/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.onboarding.impl_null_DefaultGroup_OnBoardingScreenPreview-N-0_1_null_2,NEXUS_5,1.0,en].png
+++ b/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.onboarding.impl_null_DefaultGroup_OnBoardingScreenPreview-N-0_1_null_2,NEXUS_5,1.0,en].png
@@ -1,3 +1,3 @@
 version https://git-lfs.github.com/spec/v1
-oid sha256:88d2194ffc00644a2666175e86ca49dfbad8988fbb98346128d0add77c79b8eb
-size 421289
+oid sha256:6521d409bc1fc70fa422ffec400d9f20d0b7fe16adebb7f5b0a9e5f135328ffc
+size 422213
diff --git a/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.onboarding.impl_null_DefaultGroup_OnBoardingScreenPreview-N-0_1_null_3,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.onboarding.impl_null_DefaultGroup_OnBoardingScreenPreview-N-0_1_null_3,NEXUS_5,1.0,en].png
index 5ce6c750e1..e28f44bb13 100644
--- a/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.onboarding.impl_null_DefaultGroup_OnBoardingScreenPreview-N-0_1_null_3,NEXUS_5,1.0,en].png
+++ b/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.onboarding.impl_null_DefaultGroup_OnBoardingScreenPreview-N-0_1_null_3,NEXUS_5,1.0,en].png
@@ -1,3 +1,3 @@
 version https://git-lfs.github.com/spec/v1
-oid sha256:2c3c17831149c3a6a5b058e8b557b357e84157cb6a0bc56b945c9e2dd3bdc0de
-size 393706
+oid sha256:d39cfdb0db12a6d14f3105aa168ea002a845d2083f07ecfabe0858739507018d
+size 396789
diff --git a/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.poll.api_null_DefaultGroup_ActivePollContentNoResultsPreview-D-0_0_null,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.poll.api_null_DefaultGroup_ActivePollContentNoResultsPreview-D-0_0_null,NEXUS_5,1.0,en].png
new file mode 100644
index 0000000000..3b7a5b286f
--- /dev/null
+++ b/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.poll.api_null_DefaultGroup_ActivePollContentNoResultsPreview-D-0_0_null,NEXUS_5,1.0,en].png
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:1fb1d9bb4ab01a0af8ee20c08084fd01baba0f77a4c4a39c179a8e19d1dadd47
+size 46624
diff --git a/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.poll.api_null_DefaultGroup_ActivePollContentNoResultsPreview-N-0_1_null,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.poll.api_null_DefaultGroup_ActivePollContentNoResultsPreview-N-0_1_null,NEXUS_5,1.0,en].png
new file mode 100644
index 0000000000..1244226217
--- /dev/null
+++ b/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.poll.api_null_DefaultGroup_ActivePollContentNoResultsPreview-N-0_1_null,NEXUS_5,1.0,en].png
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:18749d3e3a8b4e1176fa6c8303439d07306c3518e6be625d5ec236e2f24433b5
+size 43265
diff --git a/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.poll.api_null_DefaultGroup_ActivePollContentWithResultsPreview-D-1_1_null,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.poll.api_null_DefaultGroup_ActivePollContentWithResultsPreview-D-1_1_null,NEXUS_5,1.0,en].png
new file mode 100644
index 0000000000..05cf88f8f9
--- /dev/null
+++ b/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.poll.api_null_DefaultGroup_ActivePollContentWithResultsPreview-D-1_1_null,NEXUS_5,1.0,en].png
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:1978bafb5fd079de3fe7945a0574b2b19b0480d9d7d146e034b749e674f76254
+size 48667
diff --git a/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.poll.api_null_DefaultGroup_ActivePollContentWithResultsPreview-N-1_2_null,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.poll.api_null_DefaultGroup_ActivePollContentWithResultsPreview-N-1_2_null,NEXUS_5,1.0,en].png
new file mode 100644
index 0000000000..c0d3cd8739
--- /dev/null
+++ b/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.poll.api_null_DefaultGroup_ActivePollContentWithResultsPreview-N-1_2_null,NEXUS_5,1.0,en].png
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:df79a0bd1caa8ecf4b701eaa589cc90efc748b986388f9ae5636b9dceba4492c
+size 45928
diff --git a/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.poll.api_null_DefaultGroup_PollAnswerViewNoResultsPreview-D-2_2_null,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.poll.api_null_DefaultGroup_PollAnswerViewNoResultsPreview-D-2_2_null,NEXUS_5,1.0,en].png
new file mode 100644
index 0000000000..d5c1931df5
--- /dev/null
+++ b/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.poll.api_null_DefaultGroup_PollAnswerViewNoResultsPreview-D-2_2_null,NEXUS_5,1.0,en].png
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:239eaab2812e0e2968f52a41a741b8782b28ceaf72f029267de6248a5ce67fc6
+size 23063
diff --git a/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.poll.api_null_DefaultGroup_PollAnswerViewNoResultsPreview-N-2_3_null,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.poll.api_null_DefaultGroup_PollAnswerViewNoResultsPreview-N-2_3_null,NEXUS_5,1.0,en].png
new file mode 100644
index 0000000000..560952376b
--- /dev/null
+++ b/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.poll.api_null_DefaultGroup_PollAnswerViewNoResultsPreview-N-2_3_null,NEXUS_5,1.0,en].png
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:a9cf7435b528b3920e621d6bd688a8692c8bd366db1522d2947d5e204f905644
+size 21563
diff --git a/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.poll.api_null_DefaultGroup_PollAnswerViewWithResultPreview-D-3_3_null,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.poll.api_null_DefaultGroup_PollAnswerViewWithResultPreview-D-3_3_null,NEXUS_5,1.0,en].png
new file mode 100644
index 0000000000..d5c1931df5
--- /dev/null
+++ b/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.poll.api_null_DefaultGroup_PollAnswerViewWithResultPreview-D-3_3_null,NEXUS_5,1.0,en].png
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:239eaab2812e0e2968f52a41a741b8782b28ceaf72f029267de6248a5ce67fc6
+size 23063
diff --git a/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.poll.api_null_DefaultGroup_PollAnswerViewWithResultPreview-N-3_4_null,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.poll.api_null_DefaultGroup_PollAnswerViewWithResultPreview-N-3_4_null,NEXUS_5,1.0,en].png
new file mode 100644
index 0000000000..560952376b
--- /dev/null
+++ b/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.poll.api_null_DefaultGroup_PollAnswerViewWithResultPreview-N-3_4_null,NEXUS_5,1.0,en].png
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:a9cf7435b528b3920e621d6bd688a8692c8bd366db1522d2947d5e204f905644
+size 21563
diff --git a/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.preferences.impl.analytics_null_DefaultGroup_AnalyticsSettingsViewDarkPreview_0_null_0,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.preferences.impl.analytics_null_DefaultGroup_AnalyticsSettingsViewDarkPreview_0_null_0,NEXUS_5,1.0,en].png
index 923e05f0fc..9f41d45892 100644
--- a/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.preferences.impl.analytics_null_DefaultGroup_AnalyticsSettingsViewDarkPreview_0_null_0,NEXUS_5,1.0,en].png
+++ b/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.preferences.impl.analytics_null_DefaultGroup_AnalyticsSettingsViewDarkPreview_0_null_0,NEXUS_5,1.0,en].png
@@ -1,3 +1,3 @@
 version https://git-lfs.github.com/spec/v1
-oid sha256:ba708a48280a4f42196d61b0cfbb7f0bf6e4a818b8e76ba981e5cbacff37c9dd
-size 25493
+oid sha256:e8c4254a13c72f1e6e710caafb173623697b3aba5472ddbf14a9a8a8a16722d1
+size 25454
diff --git a/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.preferences.impl.analytics_null_DefaultGroup_AnalyticsSettingsViewLightPreview_0_null_0,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.preferences.impl.analytics_null_DefaultGroup_AnalyticsSettingsViewLightPreview_0_null_0,NEXUS_5,1.0,en].png
index 9358cd9f18..4839079fb2 100644
--- a/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.preferences.impl.analytics_null_DefaultGroup_AnalyticsSettingsViewLightPreview_0_null_0,NEXUS_5,1.0,en].png
+++ b/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.preferences.impl.analytics_null_DefaultGroup_AnalyticsSettingsViewLightPreview_0_null_0,NEXUS_5,1.0,en].png
@@ -1,3 +1,3 @@
 version https://git-lfs.github.com/spec/v1
-oid sha256:8b75a4207e4dc3fc0e3a124574e0352eeb7e731558d90b4d19060d3a046b76e7
-size 26656
+oid sha256:bfa0258b099d0fb6451eddcf38dc2184bad611355f56054ede8c874ea28b9fe8
+size 26579
diff --git a/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.preferences.impl.developer_null_DefaultGroup_DeveloperSettingsViewDarkPreview_0_null_0,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.preferences.impl.developer_null_DefaultGroup_DeveloperSettingsViewDarkPreview_0_null_0,NEXUS_5,1.0,en].png
index 4fb8f691f4..b87cf23f84 100644
--- a/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.preferences.impl.developer_null_DefaultGroup_DeveloperSettingsViewDarkPreview_0_null_0,NEXUS_5,1.0,en].png
+++ b/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.preferences.impl.developer_null_DefaultGroup_DeveloperSettingsViewDarkPreview_0_null_0,NEXUS_5,1.0,en].png
@@ -1,3 +1,3 @@
 version https://git-lfs.github.com/spec/v1
-oid sha256:fb77df9e072715ed947537e4474d504b5b5d533bfe9cd888362a421fea5b53b5
-size 44068
+oid sha256:4a9a3902dd33ab3e528fa9c534302228113cc468914025766a21397ad3eda9e2
+size 45064
diff --git a/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.preferences.impl.developer_null_DefaultGroup_DeveloperSettingsViewDarkPreview_0_null_1,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.preferences.impl.developer_null_DefaultGroup_DeveloperSettingsViewDarkPreview_0_null_1,NEXUS_5,1.0,en].png
index 4fb8f691f4..b87cf23f84 100644
--- a/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.preferences.impl.developer_null_DefaultGroup_DeveloperSettingsViewDarkPreview_0_null_1,NEXUS_5,1.0,en].png
+++ b/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.preferences.impl.developer_null_DefaultGroup_DeveloperSettingsViewDarkPreview_0_null_1,NEXUS_5,1.0,en].png
@@ -1,3 +1,3 @@
 version https://git-lfs.github.com/spec/v1
-oid sha256:fb77df9e072715ed947537e4474d504b5b5d533bfe9cd888362a421fea5b53b5
-size 44068
+oid sha256:4a9a3902dd33ab3e528fa9c534302228113cc468914025766a21397ad3eda9e2
+size 45064
diff --git a/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.preferences.impl.developer_null_DefaultGroup_DeveloperSettingsViewLightPreview_0_null_0,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.preferences.impl.developer_null_DefaultGroup_DeveloperSettingsViewLightPreview_0_null_0,NEXUS_5,1.0,en].png
index ff0fc9708e..30360f9f5e 100644
--- a/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.preferences.impl.developer_null_DefaultGroup_DeveloperSettingsViewLightPreview_0_null_0,NEXUS_5,1.0,en].png
+++ b/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.preferences.impl.developer_null_DefaultGroup_DeveloperSettingsViewLightPreview_0_null_0,NEXUS_5,1.0,en].png
@@ -1,3 +1,3 @@
 version https://git-lfs.github.com/spec/v1
-oid sha256:004a25de04aac1ca9cbbad77581e0b52a6f8fba30aa2e64c03a791c54b297d5a
-size 48875
+oid sha256:cd1cc710443af62efddf0ea165a6289912f471f669803255368d3266b872f5f6
+size 49829
diff --git a/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.preferences.impl.developer_null_DefaultGroup_DeveloperSettingsViewLightPreview_0_null_1,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.preferences.impl.developer_null_DefaultGroup_DeveloperSettingsViewLightPreview_0_null_1,NEXUS_5,1.0,en].png
index ff0fc9708e..30360f9f5e 100644
--- a/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.preferences.impl.developer_null_DefaultGroup_DeveloperSettingsViewLightPreview_0_null_1,NEXUS_5,1.0,en].png
+++ b/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.preferences.impl.developer_null_DefaultGroup_DeveloperSettingsViewLightPreview_0_null_1,NEXUS_5,1.0,en].png
@@ -1,3 +1,3 @@
 version https://git-lfs.github.com/spec/v1
-oid sha256:004a25de04aac1ca9cbbad77581e0b52a6f8fba30aa2e64c03a791c54b297d5a
-size 48875
+oid sha256:cd1cc710443af62efddf0ea165a6289912f471f669803255368d3266b872f5f6
+size 49829
diff --git a/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.rageshake.api.crash_null_DefaultGroup_CrashDetectionViewDarkPreview_0_null,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.rageshake.api.crash_null_DefaultGroup_CrashDetectionViewDarkPreview_0_null,NEXUS_5,1.0,en].png
index 2d5adfdf5c..1bc1883b8c 100644
--- a/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.rageshake.api.crash_null_DefaultGroup_CrashDetectionViewDarkPreview_0_null,NEXUS_5,1.0,en].png
+++ b/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.rageshake.api.crash_null_DefaultGroup_CrashDetectionViewDarkPreview_0_null,NEXUS_5,1.0,en].png
@@ -1,3 +1,3 @@
 version https://git-lfs.github.com/spec/v1
-oid sha256:bf048607d3003004608786fe123bca039b5a6175aa52194ca54b4d54a69b7213
-size 24135
+oid sha256:27410489a8b575564662f64fe4149ebe08a9b9b3136f9a3047acca100616830e
+size 24618
diff --git a/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.rageshake.api.crash_null_DefaultGroup_CrashDetectionViewLightPreview_0_null,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.rageshake.api.crash_null_DefaultGroup_CrashDetectionViewLightPreview_0_null,NEXUS_5,1.0,en].png
index d96d3a80f6..7419093421 100644
--- a/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.rageshake.api.crash_null_DefaultGroup_CrashDetectionViewLightPreview_0_null,NEXUS_5,1.0,en].png
+++ b/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.rageshake.api.crash_null_DefaultGroup_CrashDetectionViewLightPreview_0_null,NEXUS_5,1.0,en].png
@@ -1,3 +1,3 @@
 version https://git-lfs.github.com/spec/v1
-oid sha256:57c119c7b2291b4a6431f9ed7805e74464a175e0a169f147ba77627b9174d2bc
-size 25074
+oid sha256:75507bd9d98b762bb67b732f47f6409476e4886239b2450df4d2e54309c52cf2
+size 26303
diff --git a/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.rageshake.api.detection_null_DefaultGroup_RageshakeDialogContentDarkPreview_0_null,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.rageshake.api.detection_null_DefaultGroup_RageshakeDialogContentDarkPreview_0_null,NEXUS_5,1.0,en].png
index aa6c59c6f7..3524f4eaa1 100644
--- a/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.rageshake.api.detection_null_DefaultGroup_RageshakeDialogContentDarkPreview_0_null,NEXUS_5,1.0,en].png
+++ b/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.rageshake.api.detection_null_DefaultGroup_RageshakeDialogContentDarkPreview_0_null,NEXUS_5,1.0,en].png
@@ -1,3 +1,3 @@
 version https://git-lfs.github.com/spec/v1
-oid sha256:8415a958d4157f226fed8456fc0d004c1163d1ab9e24e57bfb2b369b4f7d0eb0
-size 26039
+oid sha256:e5ecc29cd0aaa41be1652d8b035951d287adf1e28bb9c825c99d79a5f8fbac34
+size 26661
diff --git a/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.rageshake.api.detection_null_DefaultGroup_RageshakeDialogContentLightPreview_0_null,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.rageshake.api.detection_null_DefaultGroup_RageshakeDialogContentLightPreview_0_null,NEXUS_5,1.0,en].png
index 7b5233f7b2..893e73d603 100644
--- a/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.rageshake.api.detection_null_DefaultGroup_RageshakeDialogContentLightPreview_0_null,NEXUS_5,1.0,en].png
+++ b/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.rageshake.api.detection_null_DefaultGroup_RageshakeDialogContentLightPreview_0_null,NEXUS_5,1.0,en].png
@@ -1,3 +1,3 @@
 version https://git-lfs.github.com/spec/v1
-oid sha256:2de43d9a1e0652b2326f6b5462a915296388b61806ab2c8c62e4a7c15808a8a1
-size 27112
+oid sha256:c47014cbad6ac7446bc4dc1c21560f8a0b107fc8da25b8c85b89fb2591733efa
+size 28466
diff --git a/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.rageshake.impl.bugreport_null_DefaultGroup_BugReportViewDarkPreview_0_null_0,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.rageshake.impl.bugreport_null_DefaultGroup_BugReportViewDarkPreview_0_null_0,NEXUS_5,1.0,en].png
index 0a43709e00..4f09628e11 100644
--- a/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.rageshake.impl.bugreport_null_DefaultGroup_BugReportViewDarkPreview_0_null_0,NEXUS_5,1.0,en].png
+++ b/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.rageshake.impl.bugreport_null_DefaultGroup_BugReportViewDarkPreview_0_null_0,NEXUS_5,1.0,en].png
@@ -1,3 +1,3 @@
 version https://git-lfs.github.com/spec/v1
-oid sha256:07e1283e5ac86cf9c77b0695a6622682e7257abce1e7787440f50c8f42ca0291
-size 64632
+oid sha256:67144695fd2efa7e81d910606e2ca4486a4365b54067fb4d9c1fb26303f86bfe
+size 65099
diff --git a/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.rageshake.impl.bugreport_null_DefaultGroup_BugReportViewDarkPreview_0_null_1,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.rageshake.impl.bugreport_null_DefaultGroup_BugReportViewDarkPreview_0_null_1,NEXUS_5,1.0,en].png
index e26b93adf7..888cba3741 100644
--- a/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.rageshake.impl.bugreport_null_DefaultGroup_BugReportViewDarkPreview_0_null_1,NEXUS_5,1.0,en].png
+++ b/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.rageshake.impl.bugreport_null_DefaultGroup_BugReportViewDarkPreview_0_null_1,NEXUS_5,1.0,en].png
@@ -1,3 +1,3 @@
 version https://git-lfs.github.com/spec/v1
-oid sha256:dac098de353f8dce2d8eea77bccdcebf997c642f05afaa15c02a9bcf230fa37a
-size 200158
+oid sha256:a7f9a86df68cb0595c23c86e7b91f73af55531dd0495f0409471fb94165bdeb6
+size 200178
diff --git a/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.rageshake.impl.bugreport_null_DefaultGroup_BugReportViewDarkPreview_0_null_2,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.rageshake.impl.bugreport_null_DefaultGroup_BugReportViewDarkPreview_0_null_2,NEXUS_5,1.0,en].png
index da4cf4461a..7da87c44da 100644
--- a/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.rageshake.impl.bugreport_null_DefaultGroup_BugReportViewDarkPreview_0_null_2,NEXUS_5,1.0,en].png
+++ b/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.rageshake.impl.bugreport_null_DefaultGroup_BugReportViewDarkPreview_0_null_2,NEXUS_5,1.0,en].png
@@ -1,3 +1,3 @@
 version https://git-lfs.github.com/spec/v1
-oid sha256:c4b2f7af207e8d2f951474575de12969e0fdf0831ce68fdfde5b67b364c67156
-size 55013
+oid sha256:647b616a0153b433399004436b2d7259b2e0c12a4cb621d87df4cb0d576e6fcf
+size 55422
diff --git a/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.rageshake.impl.bugreport_null_DefaultGroup_BugReportViewLightPreview_0_null_0,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.rageshake.impl.bugreport_null_DefaultGroup_BugReportViewLightPreview_0_null_0,NEXUS_5,1.0,en].png
index 5ebb85150a..2884bfee01 100644
--- a/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.rageshake.impl.bugreport_null_DefaultGroup_BugReportViewLightPreview_0_null_0,NEXUS_5,1.0,en].png
+++ b/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.rageshake.impl.bugreport_null_DefaultGroup_BugReportViewLightPreview_0_null_0,NEXUS_5,1.0,en].png
@@ -1,3 +1,3 @@
 version https://git-lfs.github.com/spec/v1
-oid sha256:91fcd5dc74788d4f597dfc265a1d6a7511e5f4db47323d930f7c54c7df7d62bd
-size 67464
+oid sha256:abf293ca05d36da1de3f68d8b3d60b2da80c26dfb189698b949cd06c48239f73
+size 67839
diff --git a/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.rageshake.impl.bugreport_null_DefaultGroup_BugReportViewLightPreview_0_null_1,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.rageshake.impl.bugreport_null_DefaultGroup_BugReportViewLightPreview_0_null_1,NEXUS_5,1.0,en].png
index b999544c27..6eb72a9709 100644
--- a/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.rageshake.impl.bugreport_null_DefaultGroup_BugReportViewLightPreview_0_null_1,NEXUS_5,1.0,en].png
+++ b/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.rageshake.impl.bugreport_null_DefaultGroup_BugReportViewLightPreview_0_null_1,NEXUS_5,1.0,en].png
@@ -1,3 +1,3 @@
 version https://git-lfs.github.com/spec/v1
-oid sha256:3583a0758b9c02c7e165dc593f7a090a54d70bcfa0f39853ba3bddb42850d404
-size 204354
+oid sha256:d10808329ac9280334c5bad3230eace88eb768a9e13b7d736c4e99cc74124c84
+size 204325
diff --git a/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.rageshake.impl.bugreport_null_DefaultGroup_BugReportViewLightPreview_0_null_2,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.rageshake.impl.bugreport_null_DefaultGroup_BugReportViewLightPreview_0_null_2,NEXUS_5,1.0,en].png
index 784d1dbe36..bb6eead4a7 100644
--- a/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.rageshake.impl.bugreport_null_DefaultGroup_BugReportViewLightPreview_0_null_2,NEXUS_5,1.0,en].png
+++ b/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.rageshake.impl.bugreport_null_DefaultGroup_BugReportViewLightPreview_0_null_2,NEXUS_5,1.0,en].png
@@ -1,3 +1,3 @@
 version https://git-lfs.github.com/spec/v1
-oid sha256:3dac3ed1e6c46265e8b0f7bb479042271668178ff2ad34baae3cb2d777c7902a
-size 59091
+oid sha256:92b64a2dd7c5c268a12ac1ae154c5daeaeb267c0590852b3bb83793b4a01f631
+size 60229
diff --git a/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.roomdetails.impl.edit_null_DefaultGroup_RoomDetailsEditViewDarkPreview_0_null_0,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.roomdetails.impl.edit_null_DefaultGroup_RoomDetailsEditViewDarkPreview_0_null_0,NEXUS_5,1.0,en].png
index 1bbdba6045..6e81844720 100644
--- a/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.roomdetails.impl.edit_null_DefaultGroup_RoomDetailsEditViewDarkPreview_0_null_0,NEXUS_5,1.0,en].png
+++ b/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.roomdetails.impl.edit_null_DefaultGroup_RoomDetailsEditViewDarkPreview_0_null_0,NEXUS_5,1.0,en].png
@@ -1,3 +1,3 @@
 version https://git-lfs.github.com/spec/v1
-oid sha256:07ce6ce83db08f8801f83dca8256c3fd133fc3501e237db6518d482f2248fc76
-size 29665
+oid sha256:99181f0a4a721479e0c2e2eaae91f4637a7a01054159c5b2b3c9173ebdf6a1dd
+size 29649
diff --git a/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.roomdetails.impl.edit_null_DefaultGroup_RoomDetailsEditViewDarkPreview_0_null_1,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.roomdetails.impl.edit_null_DefaultGroup_RoomDetailsEditViewDarkPreview_0_null_1,NEXUS_5,1.0,en].png
index e10aecaa41..aa92897b18 100644
--- a/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.roomdetails.impl.edit_null_DefaultGroup_RoomDetailsEditViewDarkPreview_0_null_1,NEXUS_5,1.0,en].png
+++ b/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.roomdetails.impl.edit_null_DefaultGroup_RoomDetailsEditViewDarkPreview_0_null_1,NEXUS_5,1.0,en].png
@@ -1,3 +1,3 @@
 version https://git-lfs.github.com/spec/v1
-oid sha256:378b3d99b8a5c4f30a6148af614526a376b02f30afe97f2d6a7c10c097d70593
-size 23386
+oid sha256:ac2fff68f6580426fd3273f084ec375123fabaab4a706e7cd153332d2947173a
+size 23369
diff --git a/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.roomdetails.impl.edit_null_DefaultGroup_RoomDetailsEditViewDarkPreview_0_null_2,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.roomdetails.impl.edit_null_DefaultGroup_RoomDetailsEditViewDarkPreview_0_null_2,NEXUS_5,1.0,en].png
index 9e1c8d9f20..883d55bf0b 100644
--- a/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.roomdetails.impl.edit_null_DefaultGroup_RoomDetailsEditViewDarkPreview_0_null_2,NEXUS_5,1.0,en].png
+++ b/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.roomdetails.impl.edit_null_DefaultGroup_RoomDetailsEditViewDarkPreview_0_null_2,NEXUS_5,1.0,en].png
@@ -1,3 +1,3 @@
 version https://git-lfs.github.com/spec/v1
-oid sha256:e07de26f3432ed6b5a6b85490a52ea7324d11ce7722657770ba88c0ebba5f37d
-size 54138
+oid sha256:9e490123827e4275fd69bbc21990d8f10575da224432fb9aa3c93bcc51078bb0
+size 54114
diff --git a/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.roomdetails.impl.edit_null_DefaultGroup_RoomDetailsEditViewDarkPreview_0_null_3,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.roomdetails.impl.edit_null_DefaultGroup_RoomDetailsEditViewDarkPreview_0_null_3,NEXUS_5,1.0,en].png
index 3cad85cbf3..bfd46c52f3 100644
--- a/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.roomdetails.impl.edit_null_DefaultGroup_RoomDetailsEditViewDarkPreview_0_null_3,NEXUS_5,1.0,en].png
+++ b/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.roomdetails.impl.edit_null_DefaultGroup_RoomDetailsEditViewDarkPreview_0_null_3,NEXUS_5,1.0,en].png
@@ -1,3 +1,3 @@
 version https://git-lfs.github.com/spec/v1
-oid sha256:685460d930fee9e3c2f982b2245bce5c47e1a40570b5a69151cb3b12ad0cf2c0
-size 28315
+oid sha256:e8eec289c3e262da582a77de0229d818f061ae40818556461d0a31ac3065dc2f
+size 28650
diff --git a/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.roomdetails.impl.edit_null_DefaultGroup_RoomDetailsEditViewDarkPreview_0_null_4,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.roomdetails.impl.edit_null_DefaultGroup_RoomDetailsEditViewDarkPreview_0_null_4,NEXUS_5,1.0,en].png
index fc0e472e08..a7210f34cc 100644
--- a/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.roomdetails.impl.edit_null_DefaultGroup_RoomDetailsEditViewDarkPreview_0_null_4,NEXUS_5,1.0,en].png
+++ b/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.roomdetails.impl.edit_null_DefaultGroup_RoomDetailsEditViewDarkPreview_0_null_4,NEXUS_5,1.0,en].png
@@ -1,3 +1,3 @@
 version https://git-lfs.github.com/spec/v1
-oid sha256:d7ef8974e2d69d8ae325a3465088c93018312716636fa1624d5fdf66813aac4b
-size 27887
+oid sha256:fef45ba584f1edcc9ea0aa27c3e13678bbe3c834ff88a71a91ca19545b94b280
+size 28227
diff --git a/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.roomdetails.impl.edit_null_DefaultGroup_RoomDetailsEditViewDarkPreview_0_null_5,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.roomdetails.impl.edit_null_DefaultGroup_RoomDetailsEditViewDarkPreview_0_null_5,NEXUS_5,1.0,en].png
index d42d35871e..e01891c06d 100644
--- a/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.roomdetails.impl.edit_null_DefaultGroup_RoomDetailsEditViewDarkPreview_0_null_5,NEXUS_5,1.0,en].png
+++ b/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.roomdetails.impl.edit_null_DefaultGroup_RoomDetailsEditViewDarkPreview_0_null_5,NEXUS_5,1.0,en].png
@@ -1,3 +1,3 @@
 version https://git-lfs.github.com/spec/v1
-oid sha256:3d2d88ed1abec3c370b0794ad81647a4d6885545b57f171ee98907c59e8a689e
+oid sha256:d3c1fb883194c1137e4696b1fcf02b87aab42814f1e13f07383585159de615a7
 size 28903
diff --git a/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.roomdetails.impl.edit_null_DefaultGroup_RoomDetailsEditViewDarkPreview_0_null_6,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.roomdetails.impl.edit_null_DefaultGroup_RoomDetailsEditViewDarkPreview_0_null_6,NEXUS_5,1.0,en].png
index 1ac04e5716..54dd5050d6 100644
--- a/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.roomdetails.impl.edit_null_DefaultGroup_RoomDetailsEditViewDarkPreview_0_null_6,NEXUS_5,1.0,en].png
+++ b/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.roomdetails.impl.edit_null_DefaultGroup_RoomDetailsEditViewDarkPreview_0_null_6,NEXUS_5,1.0,en].png
@@ -1,3 +1,3 @@
 version https://git-lfs.github.com/spec/v1
-oid sha256:90246e3319170b6dbad8c4a18db08f82c1d09a62856f6b8f457479b84e81061a
-size 25384
+oid sha256:ab9225695d5c1c7a42da36cd78378713e7056808de3dea01e2cef92e9972c64e
+size 24875
diff --git a/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.roomdetails.impl.edit_null_DefaultGroup_RoomDetailsEditViewLightPreview_0_null_0,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.roomdetails.impl.edit_null_DefaultGroup_RoomDetailsEditViewLightPreview_0_null_0,NEXUS_5,1.0,en].png
index 70780621e1..a5c3fe25c9 100644
--- a/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.roomdetails.impl.edit_null_DefaultGroup_RoomDetailsEditViewLightPreview_0_null_0,NEXUS_5,1.0,en].png
+++ b/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.roomdetails.impl.edit_null_DefaultGroup_RoomDetailsEditViewLightPreview_0_null_0,NEXUS_5,1.0,en].png
@@ -1,3 +1,3 @@
 version https://git-lfs.github.com/spec/v1
-oid sha256:2ea01e575d960dc098a747b6f37891535e2a1028722d9923c92b81c97b99be3c
-size 30740
+oid sha256:5dda2d8f3a0fce6d47e25cbbd862a740d0f06c7b6c9ae9590210cf07ab840d5d
+size 30769
diff --git a/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.roomdetails.impl.edit_null_DefaultGroup_RoomDetailsEditViewLightPreview_0_null_1,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.roomdetails.impl.edit_null_DefaultGroup_RoomDetailsEditViewLightPreview_0_null_1,NEXUS_5,1.0,en].png
index e5687588c6..20c39d6876 100644
--- a/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.roomdetails.impl.edit_null_DefaultGroup_RoomDetailsEditViewLightPreview_0_null_1,NEXUS_5,1.0,en].png
+++ b/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.roomdetails.impl.edit_null_DefaultGroup_RoomDetailsEditViewLightPreview_0_null_1,NEXUS_5,1.0,en].png
@@ -1,3 +1,3 @@
 version https://git-lfs.github.com/spec/v1
-oid sha256:af817f9b053559a95b43bc40d4ad289f3fe72f28cbd6088f4bc6fceab52d2c48
-size 24201
+oid sha256:57048d99d5de2857fed428c8f9d99d6a59c9856c78a1c6d21967d12297b1bd16
+size 24231
diff --git a/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.roomdetails.impl.edit_null_DefaultGroup_RoomDetailsEditViewLightPreview_0_null_2,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.roomdetails.impl.edit_null_DefaultGroup_RoomDetailsEditViewLightPreview_0_null_2,NEXUS_5,1.0,en].png
index aefafbc1e3..bfb9ec187a 100644
--- a/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.roomdetails.impl.edit_null_DefaultGroup_RoomDetailsEditViewLightPreview_0_null_2,NEXUS_5,1.0,en].png
+++ b/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.roomdetails.impl.edit_null_DefaultGroup_RoomDetailsEditViewLightPreview_0_null_2,NEXUS_5,1.0,en].png
@@ -1,3 +1,3 @@
 version https://git-lfs.github.com/spec/v1
-oid sha256:cbd283f464eefde6a8f99d4546d89de62aa88aa57eea87115a11ac2de90c02a8
-size 55627
+oid sha256:04af2a4120f7bda8b883d68327f0a2f5d0ac4072a86d120354f2c3bfbde2ff27
+size 55652
diff --git a/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.roomdetails.impl.edit_null_DefaultGroup_RoomDetailsEditViewLightPreview_0_null_3,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.roomdetails.impl.edit_null_DefaultGroup_RoomDetailsEditViewLightPreview_0_null_3,NEXUS_5,1.0,en].png
index a71e49a925..0e6eaae2f4 100644
--- a/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.roomdetails.impl.edit_null_DefaultGroup_RoomDetailsEditViewLightPreview_0_null_3,NEXUS_5,1.0,en].png
+++ b/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.roomdetails.impl.edit_null_DefaultGroup_RoomDetailsEditViewLightPreview_0_null_3,NEXUS_5,1.0,en].png
@@ -1,3 +1,3 @@
 version https://git-lfs.github.com/spec/v1
-oid sha256:b334c7d8bb45aef8b7c6bb4f9b016f344283e36b45f762c49b0acac195b214eb
-size 30407
+oid sha256:f81e2754d4152b993f3572bfe0505ea5f88019e4133bc379c9e0eff28fcfac74
+size 30596
diff --git a/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.roomdetails.impl.edit_null_DefaultGroup_RoomDetailsEditViewLightPreview_0_null_4,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.roomdetails.impl.edit_null_DefaultGroup_RoomDetailsEditViewLightPreview_0_null_4,NEXUS_5,1.0,en].png
index db80f0d5c2..f4667da358 100644
--- a/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.roomdetails.impl.edit_null_DefaultGroup_RoomDetailsEditViewLightPreview_0_null_4,NEXUS_5,1.0,en].png
+++ b/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.roomdetails.impl.edit_null_DefaultGroup_RoomDetailsEditViewLightPreview_0_null_4,NEXUS_5,1.0,en].png
@@ -1,3 +1,3 @@
 version https://git-lfs.github.com/spec/v1
-oid sha256:7198551e3d09343b6ba499349d7634b116d42707077ad31220493098051b3bff
-size 29152
+oid sha256:2aa961419706ae0409f7903f54634bea33342a35884f6ddf970279c4e0fdd512
+size 29325
diff --git a/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.roomdetails.impl.edit_null_DefaultGroup_RoomDetailsEditViewLightPreview_0_null_5,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.roomdetails.impl.edit_null_DefaultGroup_RoomDetailsEditViewLightPreview_0_null_5,NEXUS_5,1.0,en].png
index 99e13a9113..400b59412c 100644
--- a/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.roomdetails.impl.edit_null_DefaultGroup_RoomDetailsEditViewLightPreview_0_null_5,NEXUS_5,1.0,en].png
+++ b/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.roomdetails.impl.edit_null_DefaultGroup_RoomDetailsEditViewLightPreview_0_null_5,NEXUS_5,1.0,en].png
@@ -1,3 +1,3 @@
 version https://git-lfs.github.com/spec/v1
-oid sha256:4493895c285381147d7ee542166fdc946b1fd1a8bcbdeb23df391f63e0f731fe
-size 29369
+oid sha256:5841e8de48a2ccac2f3cec3d228b2136fc8c876687e971869cdb4c8aa83b524b
+size 29413
diff --git a/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.roomdetails.impl.edit_null_DefaultGroup_RoomDetailsEditViewLightPreview_0_null_6,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.roomdetails.impl.edit_null_DefaultGroup_RoomDetailsEditViewLightPreview_0_null_6,NEXUS_5,1.0,en].png
index f5566a7ddc..4bf226735e 100644
--- a/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.roomdetails.impl.edit_null_DefaultGroup_RoomDetailsEditViewLightPreview_0_null_6,NEXUS_5,1.0,en].png
+++ b/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.roomdetails.impl.edit_null_DefaultGroup_RoomDetailsEditViewLightPreview_0_null_6,NEXUS_5,1.0,en].png
@@ -1,3 +1,3 @@
 version https://git-lfs.github.com/spec/v1
-oid sha256:d4131fae961f950e77a6c435703fd6193e9bcee80b5c0fea32bc9383c4db787b
-size 26352
+oid sha256:090bfe363dbe3ab64533549bd37db81b54962af57062e2ea09c45d5e5efec362
+size 26496
diff --git a/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.roomdetails.impl.invite_null_DefaultGroup_RoomInviteMembersDarkPreview_0_null_0,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.roomdetails.impl.invite_null_DefaultGroup_RoomInviteMembersDarkPreview_0_null_0,NEXUS_5,1.0,en].png
index 5a29b71fcb..5659fbd79d 100644
--- a/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.roomdetails.impl.invite_null_DefaultGroup_RoomInviteMembersDarkPreview_0_null_0,NEXUS_5,1.0,en].png
+++ b/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.roomdetails.impl.invite_null_DefaultGroup_RoomInviteMembersDarkPreview_0_null_0,NEXUS_5,1.0,en].png
@@ -1,3 +1,3 @@
 version https://git-lfs.github.com/spec/v1
-oid sha256:f19d6be4e6e65007ee9548cb6494c6f760f8282f24ada04a53089a142fe8d0b7
-size 14028
+oid sha256:3c11260ddfc0a62f6d530096ab38f9d372d68383ba62f5edd081df776c300abc
+size 14454
diff --git a/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.roomdetails.impl.invite_null_DefaultGroup_RoomInviteMembersDarkPreview_0_null_1,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.roomdetails.impl.invite_null_DefaultGroup_RoomInviteMembersDarkPreview_0_null_1,NEXUS_5,1.0,en].png
index 195813c9b1..1e9422aff0 100644
--- a/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.roomdetails.impl.invite_null_DefaultGroup_RoomInviteMembersDarkPreview_0_null_1,NEXUS_5,1.0,en].png
+++ b/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.roomdetails.impl.invite_null_DefaultGroup_RoomInviteMembersDarkPreview_0_null_1,NEXUS_5,1.0,en].png
@@ -1,3 +1,3 @@
 version https://git-lfs.github.com/spec/v1
-oid sha256:445afeb50307433ab21756b60d2d0f1f365db74a99d81db9ab994927d823ccaa
-size 28495
+oid sha256:79150e1801fc222685c31f2997476b68b41f3b0d99f16abf027aae373144d39a
+size 28585
diff --git a/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.roomdetails.impl.invite_null_DefaultGroup_RoomInviteMembersDarkPreview_0_null_2,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.roomdetails.impl.invite_null_DefaultGroup_RoomInviteMembersDarkPreview_0_null_2,NEXUS_5,1.0,en].png
index 7158d39702..dae86440d4 100644
--- a/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.roomdetails.impl.invite_null_DefaultGroup_RoomInviteMembersDarkPreview_0_null_2,NEXUS_5,1.0,en].png
+++ b/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.roomdetails.impl.invite_null_DefaultGroup_RoomInviteMembersDarkPreview_0_null_2,NEXUS_5,1.0,en].png
@@ -1,3 +1,3 @@
 version https://git-lfs.github.com/spec/v1
-oid sha256:2947b905a604c522696036b5ab408ec22d2ec6dd8b75579c5727c6626776abdd
-size 11520
+oid sha256:db0f0208e41db2043aca84b138bdb114377a56764f8b548e35410d45c8d9fa2d
+size 11950
diff --git a/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.roomdetails.impl.invite_null_DefaultGroup_RoomInviteMembersDarkPreview_0_null_3,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.roomdetails.impl.invite_null_DefaultGroup_RoomInviteMembersDarkPreview_0_null_3,NEXUS_5,1.0,en].png
index 8124a1de37..05c06cc679 100644
--- a/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.roomdetails.impl.invite_null_DefaultGroup_RoomInviteMembersDarkPreview_0_null_3,NEXUS_5,1.0,en].png
+++ b/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.roomdetails.impl.invite_null_DefaultGroup_RoomInviteMembersDarkPreview_0_null_3,NEXUS_5,1.0,en].png
@@ -1,3 +1,3 @@
 version https://git-lfs.github.com/spec/v1
-oid sha256:7c7dcf21a708c134ac856b5b27c398330c73f25a69d9d46fc839e7aa8f2c02ef
-size 26291
+oid sha256:9473eed03afdfca91ba2f869767bdfa9cb426a2309517d9ed475cc765da005cc
+size 26623
diff --git a/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.roomdetails.impl.invite_null_DefaultGroup_RoomInviteMembersDarkPreview_0_null_4,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.roomdetails.impl.invite_null_DefaultGroup_RoomInviteMembersDarkPreview_0_null_4,NEXUS_5,1.0,en].png
index e8ebb07f1c..2ae3ae37f7 100644
--- a/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.roomdetails.impl.invite_null_DefaultGroup_RoomInviteMembersDarkPreview_0_null_4,NEXUS_5,1.0,en].png
+++ b/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.roomdetails.impl.invite_null_DefaultGroup_RoomInviteMembersDarkPreview_0_null_4,NEXUS_5,1.0,en].png
@@ -1,3 +1,3 @@
 version https://git-lfs.github.com/spec/v1
-oid sha256:6ea55df98f4ef544494dabbf661c1623d567291702a68993ab65f4a67770954f
-size 13576
+oid sha256:f7d7e82e1ca64dc7e18a6499e83d1deb1a1d7f55da70d0690f7c5f2bf2ae3675
+size 13976
diff --git a/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.roomdetails.impl.invite_null_DefaultGroup_RoomInviteMembersDarkPreview_0_null_5,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.roomdetails.impl.invite_null_DefaultGroup_RoomInviteMembersDarkPreview_0_null_5,NEXUS_5,1.0,en].png
index 4c91cdb1a9..3959b492c7 100644
--- a/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.roomdetails.impl.invite_null_DefaultGroup_RoomInviteMembersDarkPreview_0_null_5,NEXUS_5,1.0,en].png
+++ b/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.roomdetails.impl.invite_null_DefaultGroup_RoomInviteMembersDarkPreview_0_null_5,NEXUS_5,1.0,en].png
@@ -1,3 +1,3 @@
 version https://git-lfs.github.com/spec/v1
-oid sha256:cc5794eba22329603285fa264519fd9c4c7dae4ddb867ebe54f5c87f4af646fb
-size 45438
+oid sha256:d6a9233053173c4e85792c665df900ce4823508820e504cb76c2185f193a122e
+size 45527
diff --git a/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.roomdetails.impl.invite_null_DefaultGroup_RoomInviteMembersDarkPreview_0_null_6,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.roomdetails.impl.invite_null_DefaultGroup_RoomInviteMembersDarkPreview_0_null_6,NEXUS_5,1.0,en].png
index 58e7a0d034..171d9ed71d 100644
--- a/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.roomdetails.impl.invite_null_DefaultGroup_RoomInviteMembersDarkPreview_0_null_6,NEXUS_5,1.0,en].png
+++ b/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.roomdetails.impl.invite_null_DefaultGroup_RoomInviteMembersDarkPreview_0_null_6,NEXUS_5,1.0,en].png
@@ -1,3 +1,3 @@
 version https://git-lfs.github.com/spec/v1
-oid sha256:f67bdbeedafdaf59f1bb643d86dbfdf10442900d7d426e2e31cf62ed5fe43d9d
-size 38555
+oid sha256:64970dcd4086509e796cd67fe862053d4c5b1eb14234647ccba6abbb978b2aed
+size 38643
diff --git a/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.roomdetails.impl.invite_null_DefaultGroup_RoomInviteMembersLightPreview_0_null_0,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.roomdetails.impl.invite_null_DefaultGroup_RoomInviteMembersLightPreview_0_null_0,NEXUS_5,1.0,en].png
index 751bfeff5d..d6d69dfc15 100644
--- a/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.roomdetails.impl.invite_null_DefaultGroup_RoomInviteMembersLightPreview_0_null_0,NEXUS_5,1.0,en].png
+++ b/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.roomdetails.impl.invite_null_DefaultGroup_RoomInviteMembersLightPreview_0_null_0,NEXUS_5,1.0,en].png
@@ -1,3 +1,3 @@
 version https://git-lfs.github.com/spec/v1
-oid sha256:a9c4c8b226405f3c92536e329eea5f8ed73b66f9bf8b18c484472212551ab13c
-size 15034
+oid sha256:72f6737a9e2612f6b3ca309150d7cfdb57e0a28793a4d9bbbc2b3ae280fd8205
+size 15397
diff --git a/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.roomdetails.impl.invite_null_DefaultGroup_RoomInviteMembersLightPreview_0_null_1,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.roomdetails.impl.invite_null_DefaultGroup_RoomInviteMembersLightPreview_0_null_1,NEXUS_5,1.0,en].png
index e722eddaf7..301449fde7 100644
--- a/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.roomdetails.impl.invite_null_DefaultGroup_RoomInviteMembersLightPreview_0_null_1,NEXUS_5,1.0,en].png
+++ b/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.roomdetails.impl.invite_null_DefaultGroup_RoomInviteMembersLightPreview_0_null_1,NEXUS_5,1.0,en].png
@@ -1,3 +1,3 @@
 version https://git-lfs.github.com/spec/v1
-oid sha256:71612a9c2685e71e2075d8f592833448fae446edeee64f996626fb713142d02b
-size 29353
+oid sha256:0cbb9fa12c3856df22741ecc4bcf9bba25fe113b8ca9f4bb0a7bf3e21232a0d4
+size 29491
diff --git a/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.roomdetails.impl.invite_null_DefaultGroup_RoomInviteMembersLightPreview_0_null_2,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.roomdetails.impl.invite_null_DefaultGroup_RoomInviteMembersLightPreview_0_null_2,NEXUS_5,1.0,en].png
index 85ea57bf0f..7efb05c9f8 100644
--- a/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.roomdetails.impl.invite_null_DefaultGroup_RoomInviteMembersLightPreview_0_null_2,NEXUS_5,1.0,en].png
+++ b/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.roomdetails.impl.invite_null_DefaultGroup_RoomInviteMembersLightPreview_0_null_2,NEXUS_5,1.0,en].png
@@ -1,3 +1,3 @@
 version https://git-lfs.github.com/spec/v1
-oid sha256:dee1f76c085ea1779e79f6e3f1f67d63c154989bb07efff4af8261073980ed84
-size 12354
+oid sha256:7efaf993aaf2c43ed4ce4bbace39c6e19d4551bac1488f0efad1e9251090c457
+size 12715
diff --git a/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.roomdetails.impl.invite_null_DefaultGroup_RoomInviteMembersLightPreview_0_null_3,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.roomdetails.impl.invite_null_DefaultGroup_RoomInviteMembersLightPreview_0_null_3,NEXUS_5,1.0,en].png
index 767762b05a..ff73b1eef3 100644
--- a/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.roomdetails.impl.invite_null_DefaultGroup_RoomInviteMembersLightPreview_0_null_3,NEXUS_5,1.0,en].png
+++ b/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.roomdetails.impl.invite_null_DefaultGroup_RoomInviteMembersLightPreview_0_null_3,NEXUS_5,1.0,en].png
@@ -1,3 +1,3 @@
 version https://git-lfs.github.com/spec/v1
-oid sha256:0b1dd6dc2e1c333203063f86a1dcf442ba6aabaf1a4210a8d6429f402ccda5a1
-size 27229
+oid sha256:cc38ae9ae3ce7d632c6599d600e6095be2453804837d556653c8ef3fc5d407e3
+size 27470
diff --git a/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.roomdetails.impl.invite_null_DefaultGroup_RoomInviteMembersLightPreview_0_null_4,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.roomdetails.impl.invite_null_DefaultGroup_RoomInviteMembersLightPreview_0_null_4,NEXUS_5,1.0,en].png
index 596de325e2..4a64d0aefa 100644
--- a/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.roomdetails.impl.invite_null_DefaultGroup_RoomInviteMembersLightPreview_0_null_4,NEXUS_5,1.0,en].png
+++ b/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.roomdetails.impl.invite_null_DefaultGroup_RoomInviteMembersLightPreview_0_null_4,NEXUS_5,1.0,en].png
@@ -1,3 +1,3 @@
 version https://git-lfs.github.com/spec/v1
-oid sha256:2a0d5a7fe904c98ece401a8e91685f9f15f02647eb269acbc20d93ead9d5665a
-size 14439
+oid sha256:492e4ba89d4033242f4b22da255a241f86330ee3eeb244ef5102c9d4319e80b6
+size 14793
diff --git a/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.roomdetails.impl.invite_null_DefaultGroup_RoomInviteMembersLightPreview_0_null_5,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.roomdetails.impl.invite_null_DefaultGroup_RoomInviteMembersLightPreview_0_null_5,NEXUS_5,1.0,en].png
index 3e1241affa..676e76b3d5 100644
--- a/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.roomdetails.impl.invite_null_DefaultGroup_RoomInviteMembersLightPreview_0_null_5,NEXUS_5,1.0,en].png
+++ b/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.roomdetails.impl.invite_null_DefaultGroup_RoomInviteMembersLightPreview_0_null_5,NEXUS_5,1.0,en].png
@@ -1,3 +1,3 @@
 version https://git-lfs.github.com/spec/v1
-oid sha256:af4c302e55c391b0aa69a418f80f8df514157a9c30d3f33b28cf6c322c458182
-size 46942
+oid sha256:7911d3f2ce4cf00f97de32e7ef3775abc354352555428dfbdb7761fa2a4d79fb
+size 47055
diff --git a/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.roomdetails.impl.invite_null_DefaultGroup_RoomInviteMembersLightPreview_0_null_6,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.roomdetails.impl.invite_null_DefaultGroup_RoomInviteMembersLightPreview_0_null_6,NEXUS_5,1.0,en].png
index 37ba85ea50..4771d083c4 100644
--- a/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.roomdetails.impl.invite_null_DefaultGroup_RoomInviteMembersLightPreview_0_null_6,NEXUS_5,1.0,en].png
+++ b/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.roomdetails.impl.invite_null_DefaultGroup_RoomInviteMembersLightPreview_0_null_6,NEXUS_5,1.0,en].png
@@ -1,3 +1,3 @@
 version https://git-lfs.github.com/spec/v1
-oid sha256:aca6a614db1bcaec2a0b8ad4c3a64c761fda757e32865f535e75f470fda97774
-size 40683
+oid sha256:cf6c53f13773361c289f05141935c591a96d0f91dec16504a3ba74cac7436862
+size 40831
diff --git a/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.roomdetails.impl.members.details_null_DefaultGroup_RoomMemberDetailsViewDarkPreview--3_3_null_0,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.roomdetails.impl.members.details_null_DefaultGroup_RoomMemberDetailsViewDarkPreview--3_3_null_0,NEXUS_5,1.0,en].png
index 7c5af2c6d3..e7a9157488 100644
--- a/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.roomdetails.impl.members.details_null_DefaultGroup_RoomMemberDetailsViewDarkPreview--3_3_null_0,NEXUS_5,1.0,en].png
+++ b/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.roomdetails.impl.members.details_null_DefaultGroup_RoomMemberDetailsViewDarkPreview--3_3_null_0,NEXUS_5,1.0,en].png
@@ -1,3 +1,3 @@
 version https://git-lfs.github.com/spec/v1
-oid sha256:0e61170e31a1fb6d697e08c73e13dec40e88759f880a5c1720788a3b231800d7
-size 19587
+oid sha256:b32936346c597afcdc11ed72650e8651f77a5e2e3db88e12ae95bf65961c415b
+size 19662
diff --git a/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.roomdetails.impl.members.details_null_DefaultGroup_RoomMemberDetailsViewDarkPreview--3_3_null_1,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.roomdetails.impl.members.details_null_DefaultGroup_RoomMemberDetailsViewDarkPreview--3_3_null_1,NEXUS_5,1.0,en].png
index 0e2b1f9c70..47fea63910 100644
--- a/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.roomdetails.impl.members.details_null_DefaultGroup_RoomMemberDetailsViewDarkPreview--3_3_null_1,NEXUS_5,1.0,en].png
+++ b/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.roomdetails.impl.members.details_null_DefaultGroup_RoomMemberDetailsViewDarkPreview--3_3_null_1,NEXUS_5,1.0,en].png
@@ -1,3 +1,3 @@
 version https://git-lfs.github.com/spec/v1
-oid sha256:37722b8d9c417f8b1a22083dcf9f1d48b166e39c64f6e11713b6f85b6182ce6f
-size 17510
+oid sha256:a9143534f5405494e1cc2c0335d0652460d4a29aafb9efd1e1f6940c5917f281
+size 17542
diff --git a/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.roomdetails.impl.members.details_null_DefaultGroup_RoomMemberDetailsViewDarkPreview--3_3_null_2,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.roomdetails.impl.members.details_null_DefaultGroup_RoomMemberDetailsViewDarkPreview--3_3_null_2,NEXUS_5,1.0,en].png
index 1eea369e16..ba77e9e73e 100644
--- a/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.roomdetails.impl.members.details_null_DefaultGroup_RoomMemberDetailsViewDarkPreview--3_3_null_2,NEXUS_5,1.0,en].png
+++ b/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.roomdetails.impl.members.details_null_DefaultGroup_RoomMemberDetailsViewDarkPreview--3_3_null_2,NEXUS_5,1.0,en].png
@@ -1,3 +1,3 @@
 version https://git-lfs.github.com/spec/v1
-oid sha256:d979a957761c00848ca0ef3b115b5787d5a26eee5e4d4db6ba5b837c1f05be77
-size 20035
+oid sha256:5834c50a2faef01976abcf85b9d1800f4dd94fb02684fa2951d5367c326831f8
+size 20114
diff --git a/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.roomdetails.impl.members.details_null_DefaultGroup_RoomMemberDetailsViewDarkPreview--3_3_null_3,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.roomdetails.impl.members.details_null_DefaultGroup_RoomMemberDetailsViewDarkPreview--3_3_null_3,NEXUS_5,1.0,en].png
index 7c5af2c6d3..e7a9157488 100644
--- a/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.roomdetails.impl.members.details_null_DefaultGroup_RoomMemberDetailsViewDarkPreview--3_3_null_3,NEXUS_5,1.0,en].png
+++ b/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.roomdetails.impl.members.details_null_DefaultGroup_RoomMemberDetailsViewDarkPreview--3_3_null_3,NEXUS_5,1.0,en].png
@@ -1,3 +1,3 @@
 version https://git-lfs.github.com/spec/v1
-oid sha256:0e61170e31a1fb6d697e08c73e13dec40e88759f880a5c1720788a3b231800d7
-size 19587
+oid sha256:b32936346c597afcdc11ed72650e8651f77a5e2e3db88e12ae95bf65961c415b
+size 19662
diff --git a/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.roomdetails.impl.members.details_null_DefaultGroup_RoomMemberDetailsViewDarkPreview--3_3_null_4,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.roomdetails.impl.members.details_null_DefaultGroup_RoomMemberDetailsViewDarkPreview--3_3_null_4,NEXUS_5,1.0,en].png
index 7c5af2c6d3..e7a9157488 100644
--- a/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.roomdetails.impl.members.details_null_DefaultGroup_RoomMemberDetailsViewDarkPreview--3_3_null_4,NEXUS_5,1.0,en].png
+++ b/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.roomdetails.impl.members.details_null_DefaultGroup_RoomMemberDetailsViewDarkPreview--3_3_null_4,NEXUS_5,1.0,en].png
@@ -1,3 +1,3 @@
 version https://git-lfs.github.com/spec/v1
-oid sha256:0e61170e31a1fb6d697e08c73e13dec40e88759f880a5c1720788a3b231800d7
-size 19587
+oid sha256:b32936346c597afcdc11ed72650e8651f77a5e2e3db88e12ae95bf65961c415b
+size 19662
diff --git a/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.roomdetails.impl.members.details_null_DefaultGroup_RoomMemberDetailsViewDarkPreview--3_3_null_5,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.roomdetails.impl.members.details_null_DefaultGroup_RoomMemberDetailsViewDarkPreview--3_3_null_5,NEXUS_5,1.0,en].png
index 50217fd9f2..71459b1241 100644
--- a/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.roomdetails.impl.members.details_null_DefaultGroup_RoomMemberDetailsViewDarkPreview--3_3_null_5,NEXUS_5,1.0,en].png
+++ b/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.roomdetails.impl.members.details_null_DefaultGroup_RoomMemberDetailsViewDarkPreview--3_3_null_5,NEXUS_5,1.0,en].png
@@ -1,3 +1,3 @@
 version https://git-lfs.github.com/spec/v1
-oid sha256:c7ca068387cff8faf728a989488e7c4b5b07983c4b24162ff82a14fd90b82d05
-size 20609
+oid sha256:213318b5c5556a6667b9a48701f738e7c55a40c763f3bd79df05e321b1fdc74a
+size 20684
diff --git a/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.roomdetails.impl.members.details_null_DefaultGroup_RoomMemberDetailsViewLightPreview--2_2_null_0,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.roomdetails.impl.members.details_null_DefaultGroup_RoomMemberDetailsViewLightPreview--2_2_null_0,NEXUS_5,1.0,en].png
index 10c5bccfea..ab29e8c5cf 100644
--- a/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.roomdetails.impl.members.details_null_DefaultGroup_RoomMemberDetailsViewLightPreview--2_2_null_0,NEXUS_5,1.0,en].png
+++ b/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.roomdetails.impl.members.details_null_DefaultGroup_RoomMemberDetailsViewLightPreview--2_2_null_0,NEXUS_5,1.0,en].png
@@ -1,3 +1,3 @@
 version https://git-lfs.github.com/spec/v1
-oid sha256:57a16092b5e13be5f76f4cc42cf3e0c2bad983695a6b761fdb400a885c239ddb
-size 20078
+oid sha256:db61e15a906b09def466314727c21809c8019863ba4365e9bca54bca1f00bcfd
+size 20100
diff --git a/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.roomdetails.impl.members.details_null_DefaultGroup_RoomMemberDetailsViewLightPreview--2_2_null_1,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.roomdetails.impl.members.details_null_DefaultGroup_RoomMemberDetailsViewLightPreview--2_2_null_1,NEXUS_5,1.0,en].png
index 044efd7841..b02bda6284 100644
--- a/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.roomdetails.impl.members.details_null_DefaultGroup_RoomMemberDetailsViewLightPreview--2_2_null_1,NEXUS_5,1.0,en].png
+++ b/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.roomdetails.impl.members.details_null_DefaultGroup_RoomMemberDetailsViewLightPreview--2_2_null_1,NEXUS_5,1.0,en].png
@@ -1,3 +1,3 @@
 version https://git-lfs.github.com/spec/v1
-oid sha256:802a6878cd7eaabdccea21f1d430f0e498ef7470ca963c6b2b869913d2a2d0a9
-size 17859
+oid sha256:755af35da6c6e3238201b016c8de7af8e5adba70904ab99f3320406490753b41
+size 17932
diff --git a/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.roomdetails.impl.members.details_null_DefaultGroup_RoomMemberDetailsViewLightPreview--2_2_null_2,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.roomdetails.impl.members.details_null_DefaultGroup_RoomMemberDetailsViewLightPreview--2_2_null_2,NEXUS_5,1.0,en].png
index ef2f9cde70..6a4762181e 100644
--- a/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.roomdetails.impl.members.details_null_DefaultGroup_RoomMemberDetailsViewLightPreview--2_2_null_2,NEXUS_5,1.0,en].png
+++ b/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.roomdetails.impl.members.details_null_DefaultGroup_RoomMemberDetailsViewLightPreview--2_2_null_2,NEXUS_5,1.0,en].png
@@ -1,3 +1,3 @@
 version https://git-lfs.github.com/spec/v1
-oid sha256:f1e93f5807f4a1dad7be55a918f2bcbdfb9ea1b95140bab26005812c3e363e1b
-size 20558
+oid sha256:bf0402f33d86d5b112c1ba6ae50f9135d87ba6fcad1f73add6eed56ae520b4ee
+size 20579
diff --git a/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.roomdetails.impl.members.details_null_DefaultGroup_RoomMemberDetailsViewLightPreview--2_2_null_3,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.roomdetails.impl.members.details_null_DefaultGroup_RoomMemberDetailsViewLightPreview--2_2_null_3,NEXUS_5,1.0,en].png
index 10c5bccfea..ab29e8c5cf 100644
--- a/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.roomdetails.impl.members.details_null_DefaultGroup_RoomMemberDetailsViewLightPreview--2_2_null_3,NEXUS_5,1.0,en].png
+++ b/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.roomdetails.impl.members.details_null_DefaultGroup_RoomMemberDetailsViewLightPreview--2_2_null_3,NEXUS_5,1.0,en].png
@@ -1,3 +1,3 @@
 version https://git-lfs.github.com/spec/v1
-oid sha256:57a16092b5e13be5f76f4cc42cf3e0c2bad983695a6b761fdb400a885c239ddb
-size 20078
+oid sha256:db61e15a906b09def466314727c21809c8019863ba4365e9bca54bca1f00bcfd
+size 20100
diff --git a/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.roomdetails.impl.members.details_null_DefaultGroup_RoomMemberDetailsViewLightPreview--2_2_null_4,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.roomdetails.impl.members.details_null_DefaultGroup_RoomMemberDetailsViewLightPreview--2_2_null_4,NEXUS_5,1.0,en].png
index 10c5bccfea..ab29e8c5cf 100644
--- a/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.roomdetails.impl.members.details_null_DefaultGroup_RoomMemberDetailsViewLightPreview--2_2_null_4,NEXUS_5,1.0,en].png
+++ b/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.roomdetails.impl.members.details_null_DefaultGroup_RoomMemberDetailsViewLightPreview--2_2_null_4,NEXUS_5,1.0,en].png
@@ -1,3 +1,3 @@
 version https://git-lfs.github.com/spec/v1
-oid sha256:57a16092b5e13be5f76f4cc42cf3e0c2bad983695a6b761fdb400a885c239ddb
-size 20078
+oid sha256:db61e15a906b09def466314727c21809c8019863ba4365e9bca54bca1f00bcfd
+size 20100
diff --git a/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.roomdetails.impl.members.details_null_DefaultGroup_RoomMemberDetailsViewLightPreview--2_2_null_5,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.roomdetails.impl.members.details_null_DefaultGroup_RoomMemberDetailsViewLightPreview--2_2_null_5,NEXUS_5,1.0,en].png
index cab17c4d00..0306b6170d 100644
--- a/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.roomdetails.impl.members.details_null_DefaultGroup_RoomMemberDetailsViewLightPreview--2_2_null_5,NEXUS_5,1.0,en].png
+++ b/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.roomdetails.impl.members.details_null_DefaultGroup_RoomMemberDetailsViewLightPreview--2_2_null_5,NEXUS_5,1.0,en].png
@@ -1,3 +1,3 @@
 version https://git-lfs.github.com/spec/v1
-oid sha256:e1599be0c5a37083c015378ee47a78a90dcf670f4df5d85dd25d39f4b2edbdf6
-size 21147
+oid sha256:edd5b6edd1e7b3217ae5502758de3c65333244c308ae1280a61d99e10c3438c5
+size 21167
diff --git a/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.roomdetails.impl.members_null_DefaultGroup_RoomMemberListDarkPreview_0_null_0,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.roomdetails.impl.members_null_DefaultGroup_RoomMemberListDarkPreview_0_null_0,NEXUS_5,1.0,en].png
index 8952186a4e..f916d90928 100644
--- a/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.roomdetails.impl.members_null_DefaultGroup_RoomMemberListDarkPreview_0_null_0,NEXUS_5,1.0,en].png
+++ b/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.roomdetails.impl.members_null_DefaultGroup_RoomMemberListDarkPreview_0_null_0,NEXUS_5,1.0,en].png
@@ -1,3 +1,3 @@
 version https://git-lfs.github.com/spec/v1
-oid sha256:8850f5c0e52e9441f92010bebe8828cdf5e3715250aadb68f31d996ec1fb7520
-size 38042
+oid sha256:b7a8ca9eb62e3988fd6adc3d3992bb6a8577b91b44d05a6c45a4af48b3bdbb4f
+size 38282
diff --git a/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.roomdetails.impl.members_null_DefaultGroup_RoomMemberListDarkPreview_0_null_2,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.roomdetails.impl.members_null_DefaultGroup_RoomMemberListDarkPreview_0_null_2,NEXUS_5,1.0,en].png
index 9db420c070..508f583f10 100644
--- a/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.roomdetails.impl.members_null_DefaultGroup_RoomMemberListDarkPreview_0_null_2,NEXUS_5,1.0,en].png
+++ b/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.roomdetails.impl.members_null_DefaultGroup_RoomMemberListDarkPreview_0_null_2,NEXUS_5,1.0,en].png
@@ -1,3 +1,3 @@
 version https://git-lfs.github.com/spec/v1
-oid sha256:41c107c84e391b34ca13210b904327ca348625393339b95de8e740ff231c53e8
-size 13120
+oid sha256:d9bc5229a0ea1f347f5030b2bb41e656a999c001958e44ec1aaa1b70bd612017
+size 13104
diff --git a/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.roomdetails.impl.members_null_DefaultGroup_RoomMemberListLightPreview_0_null_0,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.roomdetails.impl.members_null_DefaultGroup_RoomMemberListLightPreview_0_null_0,NEXUS_5,1.0,en].png
index 864c9083a3..3c3271d44f 100644
--- a/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.roomdetails.impl.members_null_DefaultGroup_RoomMemberListLightPreview_0_null_0,NEXUS_5,1.0,en].png
+++ b/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.roomdetails.impl.members_null_DefaultGroup_RoomMemberListLightPreview_0_null_0,NEXUS_5,1.0,en].png
@@ -1,3 +1,3 @@
 version https://git-lfs.github.com/spec/v1
-oid sha256:8338dfb26935d63918749a3dd0c3d06d752172aba69bc67969b4928667fa8da1
-size 39183
+oid sha256:29c635e2bfb59cea20c8ee2c4c008a2edc74127313c437d63f7e4ef4f0851921
+size 39425
diff --git a/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.roomdetails.impl.members_null_DefaultGroup_RoomMemberListLightPreview_0_null_2,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.roomdetails.impl.members_null_DefaultGroup_RoomMemberListLightPreview_0_null_2,NEXUS_5,1.0,en].png
index 1fb5bc6b4a..f5dba656cf 100644
--- a/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.roomdetails.impl.members_null_DefaultGroup_RoomMemberListLightPreview_0_null_2,NEXUS_5,1.0,en].png
+++ b/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.roomdetails.impl.members_null_DefaultGroup_RoomMemberListLightPreview_0_null_2,NEXUS_5,1.0,en].png
@@ -1,3 +1,3 @@
 version https://git-lfs.github.com/spec/v1
-oid sha256:a1ac52a5f865e8adcb8c6429e0d6a7f088bad2f0607b3362f899f3b87526aec6
-size 14016
+oid sha256:93a44977870bc32a5f4c742b508ddb4c884e1a65701c085eece2e576c61f26a6
+size 14053
diff --git a/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.roomdetails.impl_null_DefaultGroup_RoomDetailsDarkPreview--1_1_null_0,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.roomdetails.impl_null_DefaultGroup_RoomDetailsDarkPreview--1_1_null_0,NEXUS_5,1.0,en].png
index 41e47678d2..575ae56660 100644
--- a/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.roomdetails.impl_null_DefaultGroup_RoomDetailsDarkPreview--1_1_null_0,NEXUS_5,1.0,en].png
+++ b/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.roomdetails.impl_null_DefaultGroup_RoomDetailsDarkPreview--1_1_null_0,NEXUS_5,1.0,en].png
@@ -1,3 +1,3 @@
 version https://git-lfs.github.com/spec/v1
-oid sha256:41972465c065b84fe047cf59394a7e83c036ef21b2eed5e2ec8c8e57f76a1408
-size 53943
+oid sha256:34d2fd15e0a0d432b9e9399e69ae14e899676a7534f5860242d7fa7ec091b1ef
+size 54000
diff --git a/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.roomdetails.impl_null_DefaultGroup_RoomDetailsDarkPreview--1_1_null_1,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.roomdetails.impl_null_DefaultGroup_RoomDetailsDarkPreview--1_1_null_1,NEXUS_5,1.0,en].png
index e4cc063245..7929b4f76d 100644
--- a/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.roomdetails.impl_null_DefaultGroup_RoomDetailsDarkPreview--1_1_null_1,NEXUS_5,1.0,en].png
+++ b/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.roomdetails.impl_null_DefaultGroup_RoomDetailsDarkPreview--1_1_null_1,NEXUS_5,1.0,en].png
@@ -1,3 +1,3 @@
 version https://git-lfs.github.com/spec/v1
-oid sha256:a744e1072897c73906d1e87931586c9124b73c066e0fa4ab7d2c5d41d4abb344
-size 45347
+oid sha256:ebe4c5e10556936d62f1545e84605d9daf9ca3de3cef3d3f0dbe9bb02f1cf1b1
+size 45415
diff --git a/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.roomdetails.impl_null_DefaultGroup_RoomDetailsDarkPreview--1_1_null_2,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.roomdetails.impl_null_DefaultGroup_RoomDetailsDarkPreview--1_1_null_2,NEXUS_5,1.0,en].png
index 13164ca1d8..80960d8c10 100644
--- a/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.roomdetails.impl_null_DefaultGroup_RoomDetailsDarkPreview--1_1_null_2,NEXUS_5,1.0,en].png
+++ b/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.roomdetails.impl_null_DefaultGroup_RoomDetailsDarkPreview--1_1_null_2,NEXUS_5,1.0,en].png
@@ -1,3 +1,3 @@
 version https://git-lfs.github.com/spec/v1
-oid sha256:9b0d8fcf96f22d9f7c4d8b417c2dfa8956b46866c0123ad365122c3080d4ac25
-size 46231
+oid sha256:fb0b6c742691a788fb44896f738b936dba95c6c16eefbb9bd593aa6e6bfe4480
+size 46309
diff --git a/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.roomdetails.impl_null_DefaultGroup_RoomDetailsDarkPreview--1_1_null_3,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.roomdetails.impl_null_DefaultGroup_RoomDetailsDarkPreview--1_1_null_3,NEXUS_5,1.0,en].png
index 190dfb7155..542f79349c 100644
--- a/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.roomdetails.impl_null_DefaultGroup_RoomDetailsDarkPreview--1_1_null_3,NEXUS_5,1.0,en].png
+++ b/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.roomdetails.impl_null_DefaultGroup_RoomDetailsDarkPreview--1_1_null_3,NEXUS_5,1.0,en].png
@@ -1,3 +1,3 @@
 version https://git-lfs.github.com/spec/v1
-oid sha256:c134e38cf600120bf43d0329042c6b24ccd2fa25bd48c70c028606a8598dd546
-size 48409
+oid sha256:71a7a8ac71a073a6f4ce65b7ad3a4a2a35dd1512d7ecc4cdbf53c9d52be4dba1
+size 48463
diff --git a/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.roomdetails.impl_null_DefaultGroup_RoomDetailsDarkPreview--1_1_null_5,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.roomdetails.impl_null_DefaultGroup_RoomDetailsDarkPreview--1_1_null_5,NEXUS_5,1.0,en].png
index 85a3e18440..361ab0f9dc 100644
--- a/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.roomdetails.impl_null_DefaultGroup_RoomDetailsDarkPreview--1_1_null_5,NEXUS_5,1.0,en].png
+++ b/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.roomdetails.impl_null_DefaultGroup_RoomDetailsDarkPreview--1_1_null_5,NEXUS_5,1.0,en].png
@@ -1,3 +1,3 @@
 version https://git-lfs.github.com/spec/v1
-oid sha256:855bd0ec680f2e8f53d7e186c2f6228839f39c6e7b56ce3361f6b71740584ccf
-size 60275
+oid sha256:e73465a898e07b1c0d78aa87a771b574d50f536655dd63209426b79e1156efcf
+size 60356
diff --git a/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.roomdetails.impl_null_DefaultGroup_RoomDetailsDarkPreview--1_1_null_6,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.roomdetails.impl_null_DefaultGroup_RoomDetailsDarkPreview--1_1_null_6,NEXUS_5,1.0,en].png
index 85a3e18440..361ab0f9dc 100644
--- a/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.roomdetails.impl_null_DefaultGroup_RoomDetailsDarkPreview--1_1_null_6,NEXUS_5,1.0,en].png
+++ b/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.roomdetails.impl_null_DefaultGroup_RoomDetailsDarkPreview--1_1_null_6,NEXUS_5,1.0,en].png
@@ -1,3 +1,3 @@
 version https://git-lfs.github.com/spec/v1
-oid sha256:855bd0ec680f2e8f53d7e186c2f6228839f39c6e7b56ce3361f6b71740584ccf
-size 60275
+oid sha256:e73465a898e07b1c0d78aa87a771b574d50f536655dd63209426b79e1156efcf
+size 60356
diff --git a/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.roomdetails.impl_null_DefaultGroup_RoomDetailsDarkPreview--1_1_null_7,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.roomdetails.impl_null_DefaultGroup_RoomDetailsDarkPreview--1_1_null_7,NEXUS_5,1.0,en].png
index ec3d5c8824..13872ec88b 100644
--- a/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.roomdetails.impl_null_DefaultGroup_RoomDetailsDarkPreview--1_1_null_7,NEXUS_5,1.0,en].png
+++ b/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.roomdetails.impl_null_DefaultGroup_RoomDetailsDarkPreview--1_1_null_7,NEXUS_5,1.0,en].png
@@ -1,3 +1,3 @@
 version https://git-lfs.github.com/spec/v1
-oid sha256:368f31f5485fe14f49b727c05328027ed7026bc6ec466f0c08d013832abfa084
-size 49190
+oid sha256:a8ea686919da2a33f9ecde5efb70ac9c434a24c28c30138f425acc56350a5590
+size 49227
diff --git a/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.roomdetails.impl_null_DefaultGroup_RoomDetailsDarkPreview--1_1_null_8,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.roomdetails.impl_null_DefaultGroup_RoomDetailsDarkPreview--1_1_null_8,NEXUS_5,1.0,en].png
index 8d253ef56a..02b9bfb526 100644
--- a/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.roomdetails.impl_null_DefaultGroup_RoomDetailsDarkPreview--1_1_null_8,NEXUS_5,1.0,en].png
+++ b/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.roomdetails.impl_null_DefaultGroup_RoomDetailsDarkPreview--1_1_null_8,NEXUS_5,1.0,en].png
@@ -1,3 +1,3 @@
 version https://git-lfs.github.com/spec/v1
-oid sha256:6e7796a991784b30ec4117d304d7eecc09777019703bba1eb97deacf175f566c
-size 54205
+oid sha256:8242b5826755b17c8a1bd919bc87358b701fc8431ba107c7624c69d2d6a61085
+size 54268
diff --git a/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.roomdetails.impl_null_DefaultGroup_RoomDetailsLightPreview--0_0_null_0,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.roomdetails.impl_null_DefaultGroup_RoomDetailsLightPreview--0_0_null_0,NEXUS_5,1.0,en].png
index 10ddb50653..dec71d834c 100644
--- a/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.roomdetails.impl_null_DefaultGroup_RoomDetailsLightPreview--0_0_null_0,NEXUS_5,1.0,en].png
+++ b/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.roomdetails.impl_null_DefaultGroup_RoomDetailsLightPreview--0_0_null_0,NEXUS_5,1.0,en].png
@@ -1,3 +1,3 @@
 version https://git-lfs.github.com/spec/v1
-oid sha256:f1a1489ff6a9e2929209aac79d57b4ec8868e7a17d4830bfac4cc764a1af4714
-size 56054
+oid sha256:34ca7db5dc561482c657b7617740848aafdbd144fe755276d8cf92f5dbccf077
+size 56119
diff --git a/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.roomdetails.impl_null_DefaultGroup_RoomDetailsLightPreview--0_0_null_1,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.roomdetails.impl_null_DefaultGroup_RoomDetailsLightPreview--0_0_null_1,NEXUS_5,1.0,en].png
index 0955f6d69b..9765798cd8 100644
--- a/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.roomdetails.impl_null_DefaultGroup_RoomDetailsLightPreview--0_0_null_1,NEXUS_5,1.0,en].png
+++ b/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.roomdetails.impl_null_DefaultGroup_RoomDetailsLightPreview--0_0_null_1,NEXUS_5,1.0,en].png
@@ -1,3 +1,3 @@
 version https://git-lfs.github.com/spec/v1
-oid sha256:7862b2b99c0879ec4fda3904795cecb87a7beb6dc317635c4efcaf815a7eb6b4
-size 47428
+oid sha256:bd706136ddd94395eb8587e068578d281f5a4d20908121e4584bf98459533299
+size 47485
diff --git a/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.roomdetails.impl_null_DefaultGroup_RoomDetailsLightPreview--0_0_null_2,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.roomdetails.impl_null_DefaultGroup_RoomDetailsLightPreview--0_0_null_2,NEXUS_5,1.0,en].png
index 0ec49ca16f..7394a4c8bc 100644
--- a/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.roomdetails.impl_null_DefaultGroup_RoomDetailsLightPreview--0_0_null_2,NEXUS_5,1.0,en].png
+++ b/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.roomdetails.impl_null_DefaultGroup_RoomDetailsLightPreview--0_0_null_2,NEXUS_5,1.0,en].png
@@ -1,3 +1,3 @@
 version https://git-lfs.github.com/spec/v1
-oid sha256:7e22a7534c46b166706ea0161f57b1b826d31e2a6ed971afcec7878049e820f8
-size 48394
+oid sha256:7007f5a568a31a9580ceea6c694dd3311066ef22c76eaf50e5e62476b48ae31f
+size 48465
diff --git a/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.roomdetails.impl_null_DefaultGroup_RoomDetailsLightPreview--0_0_null_3,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.roomdetails.impl_null_DefaultGroup_RoomDetailsLightPreview--0_0_null_3,NEXUS_5,1.0,en].png
index 3e8ac11ef0..4a1333ff1a 100644
--- a/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.roomdetails.impl_null_DefaultGroup_RoomDetailsLightPreview--0_0_null_3,NEXUS_5,1.0,en].png
+++ b/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.roomdetails.impl_null_DefaultGroup_RoomDetailsLightPreview--0_0_null_3,NEXUS_5,1.0,en].png
@@ -1,3 +1,3 @@
 version https://git-lfs.github.com/spec/v1
-oid sha256:34862731fdb1ae399e38ba2f45fef6a976241652b1188ee66e3d8be4c5fb49d1
-size 49668
+oid sha256:c8d76d954e33c53fd9d658e8cef59ca7c2ffbd0f51322572a99e8e74803d9a9c
+size 49731
diff --git a/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.roomdetails.impl_null_DefaultGroup_RoomDetailsLightPreview--0_0_null_5,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.roomdetails.impl_null_DefaultGroup_RoomDetailsLightPreview--0_0_null_5,NEXUS_5,1.0,en].png
index 1800fdf719..8b6ea82885 100644
--- a/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.roomdetails.impl_null_DefaultGroup_RoomDetailsLightPreview--0_0_null_5,NEXUS_5,1.0,en].png
+++ b/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.roomdetails.impl_null_DefaultGroup_RoomDetailsLightPreview--0_0_null_5,NEXUS_5,1.0,en].png
@@ -1,3 +1,3 @@
 version https://git-lfs.github.com/spec/v1
-oid sha256:10b32d81962ba03e246ee359ce64fec133345459e5bafc9976f8c9e1f2409960
-size 62345
+oid sha256:613eb68e1d88b3374c5b23884f5c992c548e636bc958e215cf3e5fec34186a88
+size 62364
diff --git a/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.roomdetails.impl_null_DefaultGroup_RoomDetailsLightPreview--0_0_null_6,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.roomdetails.impl_null_DefaultGroup_RoomDetailsLightPreview--0_0_null_6,NEXUS_5,1.0,en].png
index 1800fdf719..8b6ea82885 100644
--- a/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.roomdetails.impl_null_DefaultGroup_RoomDetailsLightPreview--0_0_null_6,NEXUS_5,1.0,en].png
+++ b/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.roomdetails.impl_null_DefaultGroup_RoomDetailsLightPreview--0_0_null_6,NEXUS_5,1.0,en].png
@@ -1,3 +1,3 @@
 version https://git-lfs.github.com/spec/v1
-oid sha256:10b32d81962ba03e246ee359ce64fec133345459e5bafc9976f8c9e1f2409960
-size 62345
+oid sha256:613eb68e1d88b3374c5b23884f5c992c548e636bc958e215cf3e5fec34186a88
+size 62364
diff --git a/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.roomdetails.impl_null_DefaultGroup_RoomDetailsLightPreview--0_0_null_7,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.roomdetails.impl_null_DefaultGroup_RoomDetailsLightPreview--0_0_null_7,NEXUS_5,1.0,en].png
index ad0685df73..f514a29a5b 100644
--- a/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.roomdetails.impl_null_DefaultGroup_RoomDetailsLightPreview--0_0_null_7,NEXUS_5,1.0,en].png
+++ b/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.roomdetails.impl_null_DefaultGroup_RoomDetailsLightPreview--0_0_null_7,NEXUS_5,1.0,en].png
@@ -1,3 +1,3 @@
 version https://git-lfs.github.com/spec/v1
-oid sha256:297ea8debad4e91466865615e197b51b4ef719fbba45d26993f4a7d82e6c9a85
-size 50504
+oid sha256:977d10c74342d1d25ce19add8793cca2b4d4b400881163e58c5f8298308e29e7
+size 50563
diff --git a/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.roomdetails.impl_null_DefaultGroup_RoomDetailsLightPreview--0_0_null_8,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.roomdetails.impl_null_DefaultGroup_RoomDetailsLightPreview--0_0_null_8,NEXUS_5,1.0,en].png
index 240dbb251e..57d3d81732 100644
--- a/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.roomdetails.impl_null_DefaultGroup_RoomDetailsLightPreview--0_0_null_8,NEXUS_5,1.0,en].png
+++ b/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.roomdetails.impl_null_DefaultGroup_RoomDetailsLightPreview--0_0_null_8,NEXUS_5,1.0,en].png
@@ -1,3 +1,3 @@
 version https://git-lfs.github.com/spec/v1
-oid sha256:0b062c4ff23b014d270fa414cef3870aa47eba6c5096075c1508000d16631d8e
-size 56292
+oid sha256:05588cb33208fb210e7953509edc739cf9401f713132a7b44a9883615a4423c0
+size 56365
diff --git a/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.roomlist.impl.components_null_DefaultGroup_PreviewRequestVerificationHeaderDark_0_null,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.roomlist.impl.components_null_DefaultGroup_PreviewRequestVerificationHeaderDark_0_null,NEXUS_5,1.0,en].png
index 82120c314f..225ec899ce 100644
--- a/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.roomlist.impl.components_null_DefaultGroup_PreviewRequestVerificationHeaderDark_0_null,NEXUS_5,1.0,en].png
+++ b/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.roomlist.impl.components_null_DefaultGroup_PreviewRequestVerificationHeaderDark_0_null,NEXUS_5,1.0,en].png
@@ -1,3 +1,3 @@
 version https://git-lfs.github.com/spec/v1
-oid sha256:9a7fa18ff871febb39ed15e617a873cc77b7a2bb1f8263ca6078086d5cd9b7c9
-size 28752
+oid sha256:0c3327e517224d5896e737f357a0a6edfd54c034e6da3c6c3302d91a6122a336
+size 28604
diff --git a/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.roomlist.impl.components_null_DefaultGroup_PreviewRequestVerificationHeaderLight_0_null,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.roomlist.impl.components_null_DefaultGroup_PreviewRequestVerificationHeaderLight_0_null,NEXUS_5,1.0,en].png
index 2182656f2c..8a2465e607 100644
--- a/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.roomlist.impl.components_null_DefaultGroup_PreviewRequestVerificationHeaderLight_0_null,NEXUS_5,1.0,en].png
+++ b/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.roomlist.impl.components_null_DefaultGroup_PreviewRequestVerificationHeaderLight_0_null,NEXUS_5,1.0,en].png
@@ -1,3 +1,3 @@
 version https://git-lfs.github.com/spec/v1
-oid sha256:3ed90625ca0a30b12cdf53c34afdc7a29f410be83588adf64da7290345810f15
-size 28893
+oid sha256:5a5545f6fc8a18336e655c50787b706cfb5fde10b6b075b16013c6c90d27726f
+size 28732
diff --git a/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.roomlist.impl_null_DefaultGroup_RoomListViewDarkPreview_0_null_1,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.roomlist.impl_null_DefaultGroup_RoomListViewDarkPreview_0_null_1,NEXUS_5,1.0,en].png
index 37560a5913..ae17140c2d 100644
--- a/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.roomlist.impl_null_DefaultGroup_RoomListViewDarkPreview_0_null_1,NEXUS_5,1.0,en].png
+++ b/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.roomlist.impl_null_DefaultGroup_RoomListViewDarkPreview_0_null_1,NEXUS_5,1.0,en].png
@@ -1,3 +1,3 @@
 version https://git-lfs.github.com/spec/v1
-oid sha256:0334a218c09298714de3ad44fbc2dc310efe542cc21609902d962a5059194cec
-size 58860
+oid sha256:1a4308687706a3f04660151013d63dab0c674650b1c158a9fd41f35898ae0b80
+size 58675
diff --git a/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.roomlist.impl_null_DefaultGroup_RoomListViewDarkPreview_0_null_3,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.roomlist.impl_null_DefaultGroup_RoomListViewDarkPreview_0_null_3,NEXUS_5,1.0,en].png
index 6ef66d5ddf..a613701e1a 100644
--- a/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.roomlist.impl_null_DefaultGroup_RoomListViewDarkPreview_0_null_3,NEXUS_5,1.0,en].png
+++ b/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.roomlist.impl_null_DefaultGroup_RoomListViewDarkPreview_0_null_3,NEXUS_5,1.0,en].png
@@ -1,3 +1,3 @@
 version https://git-lfs.github.com/spec/v1
-oid sha256:8aa48154bf2cf3a6ec6da96e24a86c6a3f1e6eb11865c2301a4f2638e471bd34
-size 37408
+oid sha256:9c6477d7476baccee037e491930d99f7ea00e313d1285fdd882be3de99f705b0
+size 37376
diff --git a/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.roomlist.impl_null_DefaultGroup_RoomListViewLightPreview_0_null_1,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.roomlist.impl_null_DefaultGroup_RoomListViewLightPreview_0_null_1,NEXUS_5,1.0,en].png
index f3c4d30238..dc017f51f6 100644
--- a/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.roomlist.impl_null_DefaultGroup_RoomListViewLightPreview_0_null_1,NEXUS_5,1.0,en].png
+++ b/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.roomlist.impl_null_DefaultGroup_RoomListViewLightPreview_0_null_1,NEXUS_5,1.0,en].png
@@ -1,3 +1,3 @@
 version https://git-lfs.github.com/spec/v1
-oid sha256:05d71406e279c54b23d9a3731b624d643ab820c3cee180536d1d4cbb50fa0d3f
-size 62283
+oid sha256:8359eb7337d0b58151e282f7686ebfc75b9b046f6bacc9fa750cba6ff57866df
+size 62060
diff --git a/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.roomlist.impl_null_DefaultGroup_RoomListViewLightPreview_0_null_3,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.roomlist.impl_null_DefaultGroup_RoomListViewLightPreview_0_null_3,NEXUS_5,1.0,en].png
index 75268923f9..de27672e6f 100644
--- a/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.roomlist.impl_null_DefaultGroup_RoomListViewLightPreview_0_null_3,NEXUS_5,1.0,en].png
+++ b/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.roomlist.impl_null_DefaultGroup_RoomListViewLightPreview_0_null_3,NEXUS_5,1.0,en].png
@@ -1,3 +1,3 @@
 version https://git-lfs.github.com/spec/v1
-oid sha256:a8f155381ccc3f8833b58e076e797034dfa528bd55bafd982c34fb997e4db491
-size 39830
+oid sha256:5b589817850bc30e336e9d5e443b2153133991aa5ea919838bddef26d2b1df9e
+size 39840
diff --git a/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.verifysession.impl_null_DefaultGroup_VerifySelfSessionViewDarkPreview_0_null_0,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.verifysession.impl_null_DefaultGroup_VerifySelfSessionViewDarkPreview_0_null_0,NEXUS_5,1.0,en].png
index 936fe4c686..64f3005666 100644
--- a/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.verifysession.impl_null_DefaultGroup_VerifySelfSessionViewDarkPreview_0_null_0,NEXUS_5,1.0,en].png
+++ b/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.verifysession.impl_null_DefaultGroup_VerifySelfSessionViewDarkPreview_0_null_0,NEXUS_5,1.0,en].png
@@ -1,3 +1,3 @@
 version https://git-lfs.github.com/spec/v1
-oid sha256:9b17397fbe00c25f0ec2012c84daa0483d53a4618777444d4cfd180d50c3cfc1
-size 27247
+oid sha256:ec007743c395328cc4b276221aaec7bbfd71d04d79470f94cb6576785d04c6b3
+size 27088
diff --git a/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.verifysession.impl_null_DefaultGroup_VerifySelfSessionViewDarkPreview_0_null_2,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.verifysession.impl_null_DefaultGroup_VerifySelfSessionViewDarkPreview_0_null_2,NEXUS_5,1.0,en].png
index 0c3abd6102..5d1f622540 100644
--- a/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.verifysession.impl_null_DefaultGroup_VerifySelfSessionViewDarkPreview_0_null_2,NEXUS_5,1.0,en].png
+++ b/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.verifysession.impl_null_DefaultGroup_VerifySelfSessionViewDarkPreview_0_null_2,NEXUS_5,1.0,en].png
@@ -1,3 +1,3 @@
 version https://git-lfs.github.com/spec/v1
-oid sha256:52854ce12dcc8304004a2b6ebc2def5513dc390483f59d51ca30e149ec12d8e2
-size 56374
+oid sha256:085ec9629209f6b08ec436c95b7df7db4b0cc5bb87c3389aa4f23f8d02dc1158
+size 56221
diff --git a/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.verifysession.impl_null_DefaultGroup_VerifySelfSessionViewDarkPreview_0_null_3,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.verifysession.impl_null_DefaultGroup_VerifySelfSessionViewDarkPreview_0_null_3,NEXUS_5,1.0,en].png
index d9d8c00aa8..548fad8c57 100644
--- a/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.verifysession.impl_null_DefaultGroup_VerifySelfSessionViewDarkPreview_0_null_3,NEXUS_5,1.0,en].png
+++ b/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.verifysession.impl_null_DefaultGroup_VerifySelfSessionViewDarkPreview_0_null_3,NEXUS_5,1.0,en].png
@@ -1,3 +1,3 @@
 version https://git-lfs.github.com/spec/v1
-oid sha256:ac9abae6c6ac9b3b5d774f091ec89a40131b81a408624957cb16e33586f464e0
-size 57241
+oid sha256:7e3dc126bd7d1009b2b4296d22aa88047f7e71d1a5d9ff39523d2358cc4a34f2
+size 57563
diff --git a/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.verifysession.impl_null_DefaultGroup_VerifySelfSessionViewDarkPreview_0_null_4,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.verifysession.impl_null_DefaultGroup_VerifySelfSessionViewDarkPreview_0_null_4,NEXUS_5,1.0,en].png
index 0ebaa9612b..ac6fbdffcc 100644
--- a/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.verifysession.impl_null_DefaultGroup_VerifySelfSessionViewDarkPreview_0_null_4,NEXUS_5,1.0,en].png
+++ b/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.verifysession.impl_null_DefaultGroup_VerifySelfSessionViewDarkPreview_0_null_4,NEXUS_5,1.0,en].png
@@ -1,3 +1,3 @@
 version https://git-lfs.github.com/spec/v1
-oid sha256:115e7b766c41009e2ab75d0fc5b44e967e9e53e141bf36003fa8dfc1993cff83
-size 30679
+oid sha256:75248001be16310b2860afb8dd6eae5cbbb3b89d22467493a64e2dbb0ddb161f
+size 30563
diff --git a/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.verifysession.impl_null_DefaultGroup_VerifySelfSessionViewDarkPreview_0_null_5,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.verifysession.impl_null_DefaultGroup_VerifySelfSessionViewDarkPreview_0_null_5,NEXUS_5,1.0,en].png
index c432ea640a..4edb7f637a 100644
--- a/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.verifysession.impl_null_DefaultGroup_VerifySelfSessionViewDarkPreview_0_null_5,NEXUS_5,1.0,en].png
+++ b/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.verifysession.impl_null_DefaultGroup_VerifySelfSessionViewDarkPreview_0_null_5,NEXUS_5,1.0,en].png
@@ -1,3 +1,3 @@
 version https://git-lfs.github.com/spec/v1
-oid sha256:408ee6e94c45930a4c4ad7413e65eaf314a848f6bea7f3740a49cc68a7bd6f88
-size 25834
+oid sha256:0b149df2993eda450c861d97a78b36d823696b0068ab45552086eaaac92b49b6
+size 25699
diff --git a/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.verifysession.impl_null_DefaultGroup_VerifySelfSessionViewLightPreview_0_null_0,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.verifysession.impl_null_DefaultGroup_VerifySelfSessionViewLightPreview_0_null_0,NEXUS_5,1.0,en].png
index 3bf8f2f81e..3417705d4c 100644
--- a/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.verifysession.impl_null_DefaultGroup_VerifySelfSessionViewLightPreview_0_null_0,NEXUS_5,1.0,en].png
+++ b/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.verifysession.impl_null_DefaultGroup_VerifySelfSessionViewLightPreview_0_null_0,NEXUS_5,1.0,en].png
@@ -1,3 +1,3 @@
 version https://git-lfs.github.com/spec/v1
-oid sha256:ee6e86ac798549910a5350dd371219ad0e0a1616d3f616e31dc2c38482ac2453
-size 28724
+oid sha256:3f13fc514ffc482bf2d863b6e8e2c305bef5568df9ceb21046714a9f6aed4592
+size 28594
diff --git a/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.verifysession.impl_null_DefaultGroup_VerifySelfSessionViewLightPreview_0_null_2,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.verifysession.impl_null_DefaultGroup_VerifySelfSessionViewLightPreview_0_null_2,NEXUS_5,1.0,en].png
index 36a54d5785..d4440d8324 100644
--- a/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.verifysession.impl_null_DefaultGroup_VerifySelfSessionViewLightPreview_0_null_2,NEXUS_5,1.0,en].png
+++ b/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.verifysession.impl_null_DefaultGroup_VerifySelfSessionViewLightPreview_0_null_2,NEXUS_5,1.0,en].png
@@ -1,3 +1,3 @@
 version https://git-lfs.github.com/spec/v1
-oid sha256:2b8870f4e25d40bac82e6f252f74d12f89a00b89b5ede2cdbfc613fbb3a4bc8f
-size 56838
+oid sha256:9497101bca7966cfa64cfc203201a20cc97add051dcd25b64d4297d0d4df8864
+size 56821
diff --git a/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.verifysession.impl_null_DefaultGroup_VerifySelfSessionViewLightPreview_0_null_3,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.verifysession.impl_null_DefaultGroup_VerifySelfSessionViewLightPreview_0_null_3,NEXUS_5,1.0,en].png
index 1c70233409..20937eae64 100644
--- a/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.verifysession.impl_null_DefaultGroup_VerifySelfSessionViewLightPreview_0_null_3,NEXUS_5,1.0,en].png
+++ b/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.verifysession.impl_null_DefaultGroup_VerifySelfSessionViewLightPreview_0_null_3,NEXUS_5,1.0,en].png
@@ -1,3 +1,3 @@
 version https://git-lfs.github.com/spec/v1
-oid sha256:01485b9e3264e64273d720474b947b3372b7b3368b8eb5b575d4ca1593e0eb9d
-size 58058
+oid sha256:53dd35c89ef71da224c1dcd677de042fa356f82040bdab8d2653a656ecc5fced
+size 58248
diff --git a/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.verifysession.impl_null_DefaultGroup_VerifySelfSessionViewLightPreview_0_null_4,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.verifysession.impl_null_DefaultGroup_VerifySelfSessionViewLightPreview_0_null_4,NEXUS_5,1.0,en].png
index 06d46ba33b..214dd48f88 100644
--- a/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.verifysession.impl_null_DefaultGroup_VerifySelfSessionViewLightPreview_0_null_4,NEXUS_5,1.0,en].png
+++ b/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.verifysession.impl_null_DefaultGroup_VerifySelfSessionViewLightPreview_0_null_4,NEXUS_5,1.0,en].png
@@ -1,3 +1,3 @@
 version https://git-lfs.github.com/spec/v1
-oid sha256:fe8368c7bc5a16f178c114391aa7a2f7801aeb4b73f8df0f2ad9bda1e690059b
-size 32121
+oid sha256:b943326eb8a8dfad99c7e47108a8459246d3f22c0f7fce55c2c9a30c404ed39b
+size 32050
diff --git a/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.verifysession.impl_null_DefaultGroup_VerifySelfSessionViewLightPreview_0_null_5,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.verifysession.impl_null_DefaultGroup_VerifySelfSessionViewLightPreview_0_null_5,NEXUS_5,1.0,en].png
index df4474d272..ea653c834e 100644
--- a/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.verifysession.impl_null_DefaultGroup_VerifySelfSessionViewLightPreview_0_null_5,NEXUS_5,1.0,en].png
+++ b/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.verifysession.impl_null_DefaultGroup_VerifySelfSessionViewLightPreview_0_null_5,NEXUS_5,1.0,en].png
@@ -1,3 +1,3 @@
 version https://git-lfs.github.com/spec/v1
-oid sha256:5f8fe0565a38d640227b5d4ffd552d7fba2c0fea7978a3d578c34b1dbc36ed9d
-size 26670
+oid sha256:802e5a13191b96fd002f88b489cf3a353eb99ee721749a979d5cc4f1627938fe
+size 26576
diff --git a/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.libraries.designsystem.atomic.molecules_null_DefaultGroup_ButtonColumnMoleculeDarkPreview_0_null,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.libraries.designsystem.atomic.molecules_null_DefaultGroup_ButtonColumnMoleculeDarkPreview_0_null,NEXUS_5,1.0,en].png
index 45788b5180..7686fdfe0b 100644
--- a/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.libraries.designsystem.atomic.molecules_null_DefaultGroup_ButtonColumnMoleculeDarkPreview_0_null,NEXUS_5,1.0,en].png
+++ b/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.libraries.designsystem.atomic.molecules_null_DefaultGroup_ButtonColumnMoleculeDarkPreview_0_null,NEXUS_5,1.0,en].png
@@ -1,3 +1,3 @@
 version https://git-lfs.github.com/spec/v1
-oid sha256:6fbd442e62fc2c8e02040d0ef42be06af5a1d554ee386e983c4bccae199004aa
-size 9456
+oid sha256:b4cece3ca4908302854c57084313d89320e4b5d645a3b43406b9876d70deb2ea
+size 14549
diff --git a/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.libraries.designsystem.atomic.molecules_null_DefaultGroup_ButtonColumnMoleculeLightPreview_0_null,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.libraries.designsystem.atomic.molecules_null_DefaultGroup_ButtonColumnMoleculeLightPreview_0_null,NEXUS_5,1.0,en].png
index f02f83b162..e4cc246047 100644
--- a/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.libraries.designsystem.atomic.molecules_null_DefaultGroup_ButtonColumnMoleculeLightPreview_0_null,NEXUS_5,1.0,en].png
+++ b/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.libraries.designsystem.atomic.molecules_null_DefaultGroup_ButtonColumnMoleculeLightPreview_0_null,NEXUS_5,1.0,en].png
@@ -1,3 +1,3 @@
 version https://git-lfs.github.com/spec/v1
-oid sha256:7f9e941ab8eceefdd858c81667a5bafa33a4efc7d232ad0d501547ecda37758d
-size 9616
+oid sha256:9031a4cbdc155e05c4aa56e774fc01ed09f32cbae7ab443cdeb42a2f2d41a8a2
+size 14942
diff --git a/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.libraries.designsystem.atomic.molecules_null_DefaultGroup_ButtonRowMoleculeDarkPreview_0_null,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.libraries.designsystem.atomic.molecules_null_DefaultGroup_ButtonRowMoleculeDarkPreview_0_null,NEXUS_5,1.0,en].png
index dfdb106006..26fd28c090 100644
--- a/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.libraries.designsystem.atomic.molecules_null_DefaultGroup_ButtonRowMoleculeDarkPreview_0_null,NEXUS_5,1.0,en].png
+++ b/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.libraries.designsystem.atomic.molecules_null_DefaultGroup_ButtonRowMoleculeDarkPreview_0_null,NEXUS_5,1.0,en].png
@@ -1,3 +1,3 @@
 version https://git-lfs.github.com/spec/v1
-oid sha256:f35e88e2b096b989eb669b8fee4196025177b29a9c9b729b843dcf7978df6add
-size 7420
+oid sha256:483bc7356a610804ec07c2794108850dafe04b4c86b653b0199fe0f5b8b85567
+size 7743
diff --git a/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.libraries.designsystem.atomic.molecules_null_DefaultGroup_ButtonRowMoleculeLightPreview_0_null,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.libraries.designsystem.atomic.molecules_null_DefaultGroup_ButtonRowMoleculeLightPreview_0_null,NEXUS_5,1.0,en].png
index 0cff850500..8923f6297f 100644
--- a/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.libraries.designsystem.atomic.molecules_null_DefaultGroup_ButtonRowMoleculeLightPreview_0_null,NEXUS_5,1.0,en].png
+++ b/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.libraries.designsystem.atomic.molecules_null_DefaultGroup_ButtonRowMoleculeLightPreview_0_null,NEXUS_5,1.0,en].png
@@ -1,3 +1,3 @@
 version https://git-lfs.github.com/spec/v1
-oid sha256:60c7dc93e9f13f1452473f783e7ecf7fc776610108a0a5e8fdf92c9e4f93a6a3
-size 7528
+oid sha256:5fd715882bbac80af31176491c97c2af711a4454a88832a086a55e5ece04e255
+size 7821
diff --git a/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.libraries.designsystem.atomic.molecules_null_DefaultGroup_IconTitlePlaceholdersRowMoleculePreview-D_0_null,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.libraries.designsystem.atomic.molecules_null_DefaultGroup_IconTitlePlaceholdersRowMoleculePreview-D_0_null,NEXUS_5,1.0,en].png
new file mode 100644
index 0000000000..08f5a24c49
--- /dev/null
+++ b/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.libraries.designsystem.atomic.molecules_null_DefaultGroup_IconTitlePlaceholdersRowMoleculePreview-D_0_null,NEXUS_5,1.0,en].png
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:ebb2d33b0f8aa473b9deb44e57df4edec1346f164098eec87163ebd5c8db9ebd
+size 5314
diff --git a/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.libraries.designsystem.atomic.molecules_null_DefaultGroup_IconTitlePlaceholdersRowMoleculePreview-N_1_null,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.libraries.designsystem.atomic.molecules_null_DefaultGroup_IconTitlePlaceholdersRowMoleculePreview-N_1_null,NEXUS_5,1.0,en].png
new file mode 100644
index 0000000000..52309e0c28
--- /dev/null
+++ b/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.libraries.designsystem.atomic.molecules_null_DefaultGroup_IconTitlePlaceholdersRowMoleculePreview-N_1_null,NEXUS_5,1.0,en].png
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:0b71348d0a316569c389682f5904c2d5b67180bd6c4ae13112d81afdb6cdada6
+size 5273
diff --git a/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.libraries.designsystem.components.async_null_DefaultGroup_AsyncFailurePreviewDark_0_null,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.libraries.designsystem.components.async_null_DefaultGroup_AsyncFailurePreviewDark_0_null,NEXUS_5,1.0,en].png
index c84d42e293..c6a4eab5da 100644
--- a/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.libraries.designsystem.components.async_null_DefaultGroup_AsyncFailurePreviewDark_0_null,NEXUS_5,1.0,en].png
+++ b/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.libraries.designsystem.components.async_null_DefaultGroup_AsyncFailurePreviewDark_0_null,NEXUS_5,1.0,en].png
@@ -1,3 +1,3 @@
 version https://git-lfs.github.com/spec/v1
-oid sha256:12075b74ecb0d505b38c99bac410d4195ed85e6cf8efd2ac07848962b7970238
-size 10972
+oid sha256:7b354e5d775173757829e50113b4859afd0883f0441ebd22d05545e2e882a3dd
+size 11177
diff --git a/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.libraries.designsystem.components.async_null_DefaultGroup_AsyncFailurePreviewLight_0_null,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.libraries.designsystem.components.async_null_DefaultGroup_AsyncFailurePreviewLight_0_null,NEXUS_5,1.0,en].png
index 926dab7b5b..ca80beb9e9 100644
--- a/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.libraries.designsystem.components.async_null_DefaultGroup_AsyncFailurePreviewLight_0_null,NEXUS_5,1.0,en].png
+++ b/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.libraries.designsystem.components.async_null_DefaultGroup_AsyncFailurePreviewLight_0_null,NEXUS_5,1.0,en].png
@@ -1,3 +1,3 @@
 version https://git-lfs.github.com/spec/v1
-oid sha256:d7e2f73cd2a33a946b256dffb97ff4485a17040a2f7358a4773bfe028ccd9e4c
-size 11042
+oid sha256:7aacb9ba54c904060cc40ab5e5725d92a152c9f3b9441fa2fb6d0fdd8449583a
+size 11230
diff --git a/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.libraries.designsystem.components.button_null_Buttons_BackButtonPreview_0_null,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.libraries.designsystem.components.button_null_Buttons_BackButtonPreview_0_null,NEXUS_5,1.0,en].png
index 3713f657e8..b7bbe45340 100644
--- a/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.libraries.designsystem.components.button_null_Buttons_BackButtonPreview_0_null,NEXUS_5,1.0,en].png
+++ b/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.libraries.designsystem.components.button_null_Buttons_BackButtonPreview_0_null,NEXUS_5,1.0,en].png
@@ -1,3 +1,3 @@
 version https://git-lfs.github.com/spec/v1
-oid sha256:0186b4f2d64220e1b0341f5007f0577d82a0c0424ad53937b6669e772fbecc4d
-size 7711
+oid sha256:c37c5cb1394da3a0b28fdd749f356f8a5d132f5408a88bc6e367052452a828d0
+size 7607
diff --git a/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.libraries.designsystem.components.button_null_Buttons_ButtonWithProgressPreview_0_null,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.libraries.designsystem.components.button_null_Buttons_ButtonWithProgressPreview_0_null,NEXUS_5,1.0,en].png
deleted file mode 100644
index 31e652eda3..0000000000
--- a/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.libraries.designsystem.components.button_null_Buttons_ButtonWithProgressPreview_0_null,NEXUS_5,1.0,en].png
+++ /dev/null
@@ -1,3 +0,0 @@
-version https://git-lfs.github.com/spec/v1
-oid sha256:f8b30dd030cae4bd394796da45e3e067c7aca5fb5176bdd73a8a24938f8571a1
-size 17707
diff --git a/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.libraries.designsystem.components.dialogs_null_Dialogs_ConfirmationDialogPreview_0_null,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.libraries.designsystem.components.dialogs_null_Dialogs_ConfirmationDialogPreview_0_null,NEXUS_5,1.0,en].png
new file mode 100644
index 0000000000..1fd95a27de
--- /dev/null
+++ b/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.libraries.designsystem.components.dialogs_null_Dialogs_ConfirmationDialogPreview_0_null,NEXUS_5,1.0,en].png
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:2c66c42d9c687bb41743117b83c65e348f5fb921865070afcf3352b618f79937
+size 23759
diff --git a/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.libraries.designsystem.components.dialogs_null_Dialogs_ConfirmationDialogPreview_0_null_0,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.libraries.designsystem.components.dialogs_null_Dialogs_ConfirmationDialogPreview_0_null_0,NEXUS_5,1.0,en].png
deleted file mode 100644
index 178db99946..0000000000
--- a/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.libraries.designsystem.components.dialogs_null_Dialogs_ConfirmationDialogPreview_0_null_0,NEXUS_5,1.0,en].png
+++ /dev/null
@@ -1,3 +0,0 @@
-version https://git-lfs.github.com/spec/v1
-oid sha256:a66a098b4d029369637ffaf9d5ac24f7a76d168b526382c78167132756476c2c
-size 22945
diff --git a/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.libraries.designsystem.components.dialogs_null_Dialogs_ConfirmationDialogPreview_0_null_1,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.libraries.designsystem.components.dialogs_null_Dialogs_ConfirmationDialogPreview_0_null_1,NEXUS_5,1.0,en].png
deleted file mode 100644
index 7376ab8e10..0000000000
--- a/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.libraries.designsystem.components.dialogs_null_Dialogs_ConfirmationDialogPreview_0_null_1,NEXUS_5,1.0,en].png
+++ /dev/null
@@ -1,3 +0,0 @@
-version https://git-lfs.github.com/spec/v1
-oid sha256:8a32ebcf17a8906570bc08df47cccac1ff4b5c7f7cd0bc414a188c9e302f6934
-size 22931
diff --git a/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.libraries.designsystem.components.dialogs_null_Dialogs_ErrorDialogPreview_0_null,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.libraries.designsystem.components.dialogs_null_Dialogs_ErrorDialogPreview_0_null,NEXUS_5,1.0,en].png
index 4e240079ab..42ee6936cb 100644
--- a/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.libraries.designsystem.components.dialogs_null_Dialogs_ErrorDialogPreview_0_null,NEXUS_5,1.0,en].png
+++ b/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.libraries.designsystem.components.dialogs_null_Dialogs_ErrorDialogPreview_0_null,NEXUS_5,1.0,en].png
@@ -1,3 +1,3 @@
 version https://git-lfs.github.com/spec/v1
-oid sha256:5c0be8e52cbd3d139601bcfe093174fa5d873f2433709a1306645062c9a8bfb9
-size 17921
+oid sha256:0e42b60613f27563e3d6921854fb9feccdd17ba7ce332a40e954b4b3bafb969f
+size 17468
diff --git a/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.libraries.designsystem.components.dialogs_null_Dialogs_RetryDialogPreview_0_null,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.libraries.designsystem.components.dialogs_null_Dialogs_RetryDialogPreview_0_null,NEXUS_5,1.0,en].png
index ecace25254..b57806c97e 100644
--- a/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.libraries.designsystem.components.dialogs_null_Dialogs_RetryDialogPreview_0_null,NEXUS_5,1.0,en].png
+++ b/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.libraries.designsystem.components.dialogs_null_Dialogs_RetryDialogPreview_0_null,NEXUS_5,1.0,en].png
@@ -1,3 +1,3 @@
 version https://git-lfs.github.com/spec/v1
-oid sha256:73c68fc2181960285410a51007a033b461abbd9ad89844d18eae10dcda26bdd4
-size 21302
+oid sha256:b939ee5229bd4c0f1d5533b492cbb24741a98e20cd8a848aca3ab02527cfc818
+size 23228
diff --git a/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.libraries.designsystem.components_null_Dialogs_ProgressDialogPreview_0_null,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.libraries.designsystem.components_null_Dialogs_ProgressDialogPreview_0_null,NEXUS_5,1.0,en].png
index 9d7ab1352b..29f5373201 100644
--- a/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.libraries.designsystem.components_null_Dialogs_ProgressDialogPreview_0_null,NEXUS_5,1.0,en].png
+++ b/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.libraries.designsystem.components_null_Dialogs_ProgressDialogPreview_0_null,NEXUS_5,1.0,en].png
@@ -1,3 +1,3 @@
 version https://git-lfs.github.com/spec/v1
-oid sha256:22747c979bf704a554dfa4ee3ace1551e78f1180bc594c55f1497ec1d6529aa2
-size 21211
+oid sha256:fcd06348851e32f3c08bc30e774006c493d9dc91402840af8edd057377a27acd
+size 21618
diff --git a/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.libraries.designsystem.ruler_null_DefaultGroup_WithRulerDarkPreview_0_null,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.libraries.designsystem.ruler_null_DefaultGroup_WithRulerDarkPreview_0_null,NEXUS_5,1.0,en].png
index 767844a2e8..7afa167e0a 100644
--- a/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.libraries.designsystem.ruler_null_DefaultGroup_WithRulerDarkPreview_0_null,NEXUS_5,1.0,en].png
+++ b/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.libraries.designsystem.ruler_null_DefaultGroup_WithRulerDarkPreview_0_null,NEXUS_5,1.0,en].png
@@ -1,3 +1,3 @@
 version https://git-lfs.github.com/spec/v1
-oid sha256:c9dadf14d9538191b4f9be41d8deb4e441008d80eb687d3f01484d6e497dcadb
-size 14291
+oid sha256:49a7579caea03ac759e5201bb88e131cad9447afbad3c250703ece49cf025e6b
+size 13561
diff --git a/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.libraries.designsystem.ruler_null_DefaultGroup_WithRulerLightPreview_0_null,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.libraries.designsystem.ruler_null_DefaultGroup_WithRulerLightPreview_0_null,NEXUS_5,1.0,en].png
index cd36276b8a..050cbf8497 100644
--- a/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.libraries.designsystem.ruler_null_DefaultGroup_WithRulerLightPreview_0_null,NEXUS_5,1.0,en].png
+++ b/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.libraries.designsystem.ruler_null_DefaultGroup_WithRulerLightPreview_0_null,NEXUS_5,1.0,en].png
@@ -1,3 +1,3 @@
 version https://git-lfs.github.com/spec/v1
-oid sha256:16f731c6c1d2cb9b462b22ab56475fda53844747eb0c587d801456903c3d7bcf
-size 13697
+oid sha256:df1ee64f9a226fc3113caedab7b7e7450d155477b52694f134cf4da53523cfb6
+size 13124
diff --git a/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.libraries.designsystem.text_null_DefaultGroup_DpScalePreview_0_75f_0_null,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.libraries.designsystem.text_null_DefaultGroup_DpScalePreview_0_75f_0_null,NEXUS_5,1.0,en].png
new file mode 100644
index 0000000000..60a3b8f39e
--- /dev/null
+++ b/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.libraries.designsystem.text_null_DefaultGroup_DpScalePreview_0_75f_0_null,NEXUS_5,1.0,en].png
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:373fcfdea163cd59d1b929adb1abf7163c0e1aaa203033292931fd22cd5c60d6
+size 22378
diff --git a/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.libraries.designsystem.text_null_DefaultGroup_DpScalePreview_1_0f_0_null,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.libraries.designsystem.text_null_DefaultGroup_DpScalePreview_1_0f_0_null,NEXUS_5,1.0,en].png
new file mode 100644
index 0000000000..9a02d72493
--- /dev/null
+++ b/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.libraries.designsystem.text_null_DefaultGroup_DpScalePreview_1_0f_0_null,NEXUS_5,1.0,en].png
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:c1e171c6295cd93af0fc0533b8c3099c75d5343132477709e231848c0c51b35f
+size 24366
diff --git a/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.libraries.designsystem.text_null_DefaultGroup_DpScalePreview_1_5f_0_null,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.libraries.designsystem.text_null_DefaultGroup_DpScalePreview_1_5f_0_null,NEXUS_5,1.0,en].png
new file mode 100644
index 0000000000..9600daf12b
--- /dev/null
+++ b/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.libraries.designsystem.text_null_DefaultGroup_DpScalePreview_1_5f_0_null,NEXUS_5,1.0,en].png
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:45485288d1cd0552c371aa868600e1fd8c30232ea2d9cb26420ec36c539cdb6f
+size 28228
diff --git a/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.libraries.designsystem.theme.components.previews_null_DateTimepickers_DatePickerPreviewDark_0_null,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.libraries.designsystem.theme.components.previews_null_DateTimepickers_DatePickerPreviewDark_0_null,NEXUS_5,1.0,en].png
index 22efc21bb1..bb199bf0cd 100644
--- a/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.libraries.designsystem.theme.components.previews_null_DateTimepickers_DatePickerPreviewDark_0_null,NEXUS_5,1.0,en].png
+++ b/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.libraries.designsystem.theme.components.previews_null_DateTimepickers_DatePickerPreviewDark_0_null,NEXUS_5,1.0,en].png
@@ -1,3 +1,3 @@
 version https://git-lfs.github.com/spec/v1
-oid sha256:8c539176a004d4664f8f0eba24cdc00950b42284dcab249ef3bc87b0347df85d
-size 32949
+oid sha256:0192cbadf07b54899608c57e094fd30d86a9856a4354b9e540a1ce05d4da393d
+size 33460
diff --git a/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.libraries.designsystem.theme.components.previews_null_DateTimepickers_DatePickerPreviewLight_0_null,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.libraries.designsystem.theme.components.previews_null_DateTimepickers_DatePickerPreviewLight_0_null,NEXUS_5,1.0,en].png
index c1cdbcc5b5..f26aa74393 100644
--- a/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.libraries.designsystem.theme.components.previews_null_DateTimepickers_DatePickerPreviewLight_0_null,NEXUS_5,1.0,en].png
+++ b/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.libraries.designsystem.theme.components.previews_null_DateTimepickers_DatePickerPreviewLight_0_null,NEXUS_5,1.0,en].png
@@ -1,3 +1,3 @@
 version https://git-lfs.github.com/spec/v1
-oid sha256:ee41ce428593fc4d8f329e623314c2200a55cb99950e6896f8df17bef5f7f3a1
-size 34187
+oid sha256:6fe1c01d5b8b16c1c6d6a8ff427a6050ce9347676ce87523fc93d5a69ae244bf
+size 34582
diff --git a/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.libraries.designsystem.theme.components.previews_null_DateTimepickers_TimePickerHorizontalPreview_0_null,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.libraries.designsystem.theme.components.previews_null_DateTimepickers_TimePickerHorizontalPreview_0_null,NEXUS_5,1.0,en].png
index 5fbf7f31c1..3fc3b275fe 100644
--- a/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.libraries.designsystem.theme.components.previews_null_DateTimepickers_TimePickerHorizontalPreview_0_null,NEXUS_5,1.0,en].png
+++ b/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.libraries.designsystem.theme.components.previews_null_DateTimepickers_TimePickerHorizontalPreview_0_null,NEXUS_5,1.0,en].png
@@ -1,3 +1,3 @@
 version https://git-lfs.github.com/spec/v1
-oid sha256:899b8d8bcb319ccf50867ce0e6f1333eddbcb232427098ea15fcacd37bdd6f43
-size 35981
+oid sha256:5ce469fe16d6b06c0425082ae37bde3c1931a69e390dd85a6f05ac7619a0e001
+size 36525
diff --git a/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.libraries.designsystem.theme.components.previews_null_DateTimepickers_TimePickerVerticalPreviewDark_0_null,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.libraries.designsystem.theme.components.previews_null_DateTimepickers_TimePickerVerticalPreviewDark_0_null,NEXUS_5,1.0,en].png
index 51138d72e5..8e81c65ca3 100644
--- a/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.libraries.designsystem.theme.components.previews_null_DateTimepickers_TimePickerVerticalPreviewDark_0_null,NEXUS_5,1.0,en].png
+++ b/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.libraries.designsystem.theme.components.previews_null_DateTimepickers_TimePickerVerticalPreviewDark_0_null,NEXUS_5,1.0,en].png
@@ -1,3 +1,3 @@
 version https://git-lfs.github.com/spec/v1
-oid sha256:ab443d66a938f968fab3ce8c26d7b567dab72ecc3c505ab1fa9f87c30822057c
-size 25451
+oid sha256:ae68c7bef1afc22da25dd84ff9068119a1c8e77ea5a6688e930d8f633f9ca654
+size 25548
diff --git a/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.libraries.designsystem.theme.components.previews_null_DateTimepickers_TimePickerVerticalPreviewLight_0_null,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.libraries.designsystem.theme.components.previews_null_DateTimepickers_TimePickerVerticalPreviewLight_0_null,NEXUS_5,1.0,en].png
index e17d053854..f3f354976e 100644
--- a/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.libraries.designsystem.theme.components.previews_null_DateTimepickers_TimePickerVerticalPreviewLight_0_null,NEXUS_5,1.0,en].png
+++ b/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.libraries.designsystem.theme.components.previews_null_DateTimepickers_TimePickerVerticalPreviewLight_0_null,NEXUS_5,1.0,en].png
@@ -1,3 +1,3 @@
 version https://git-lfs.github.com/spec/v1
-oid sha256:7c4db502fdc68ba5c1d391bc7b14b9a5c852154f0c1ee48788ebfddaa8bac21e
-size 26441
+oid sha256:9107edd0eec824d18b2cc1d4a8c3263979a946fbc1f919772f7f6e65f7a91d0e
+size 26601
diff --git a/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.libraries.designsystem.theme.components.previews_null_Menus_MenuPreview_0_null,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.libraries.designsystem.theme.components.previews_null_Menus_MenuPreview_0_null,NEXUS_5,1.0,en].png
index 8d195dfdef..4444536299 100644
--- a/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.libraries.designsystem.theme.components.previews_null_Menus_MenuPreview_0_null,NEXUS_5,1.0,en].png
+++ b/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.libraries.designsystem.theme.components.previews_null_Menus_MenuPreview_0_null,NEXUS_5,1.0,en].png
@@ -1,3 +1,3 @@
 version https://git-lfs.github.com/spec/v1
-oid sha256:6dc928db8fab90762a934c10dfc8d50aa0ed7ebe776bd2705c4f0cba2eac74fb
-size 11262
+oid sha256:7cf38f5423e4d7163cf29495b01b5dc716f348a50f9c9683d293d1189d10b71c
+size 11681
diff --git a/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.libraries.designsystem.theme.components.previews_null_Toggles_SwitchPreview_0_null,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.libraries.designsystem.theme.components.previews_null_Toggles_SwitchPreview_0_null,NEXUS_5,1.0,en].png
deleted file mode 100644
index 4cd2f5661a..0000000000
--- a/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.libraries.designsystem.theme.components.previews_null_Toggles_SwitchPreview_0_null,NEXUS_5,1.0,en].png
+++ /dev/null
@@ -1,3 +0,0 @@
-version https://git-lfs.github.com/spec/v1
-oid sha256:265ddc2f480f343efbb8717a66f5f933714e5320e837f0d26d825ed595612f2d
-size 21039
diff --git a/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.libraries.designsystem.theme.components_null_AppBars_MediumTopAppBarPreview_0_null,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.libraries.designsystem.theme.components_null_AppBars_MediumTopAppBarPreview_0_null,NEXUS_5,1.0,en].png
index 3c6579753b..fee0b4bc86 100644
--- a/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.libraries.designsystem.theme.components_null_AppBars_MediumTopAppBarPreview_0_null,NEXUS_5,1.0,en].png
+++ b/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.libraries.designsystem.theme.components_null_AppBars_MediumTopAppBarPreview_0_null,NEXUS_5,1.0,en].png
@@ -1,3 +1,3 @@
 version https://git-lfs.github.com/spec/v1
-oid sha256:c7f0987b11f1ecc5e8359b668ac8cf29f0d5b6ef6f5c74d3660e68696be699ae
-size 7219
+oid sha256:c591956dbbc4265381b6bff537efe21bdb70f3ab14862b63976ff2038b193dc6
+size 12176
diff --git a/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.libraries.designsystem.theme.components_null_AppBars_TopAppBarPreview_0_null,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.libraries.designsystem.theme.components_null_AppBars_TopAppBarPreview_0_null,NEXUS_5,1.0,en].png
index a6ece5f74f..4d3cfde8d2 100644
--- a/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.libraries.designsystem.theme.components_null_AppBars_TopAppBarPreview_0_null,NEXUS_5,1.0,en].png
+++ b/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.libraries.designsystem.theme.components_null_AppBars_TopAppBarPreview_0_null,NEXUS_5,1.0,en].png
@@ -1,3 +1,3 @@
 version https://git-lfs.github.com/spec/v1
-oid sha256:5f470f47f972d0c948a308622e49855bb88365675d8b251cd1cce9972f5569c9
-size 6878
+oid sha256:b47ed55d8919fd15da1e3877df6fa32a58bd51ebd676a7ff303e09ddb1d2d7fd
+size 11604
diff --git a/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.libraries.designsystem.theme.components_null_Buttons_ButtonPreview_0_null,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.libraries.designsystem.theme.components_null_Buttons_ButtonPreview_0_null,NEXUS_5,1.0,en].png
deleted file mode 100644
index 53e4ece077..0000000000
--- a/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.libraries.designsystem.theme.components_null_Buttons_ButtonPreview_0_null,NEXUS_5,1.0,en].png
+++ /dev/null
@@ -1,3 +0,0 @@
-version https://git-lfs.github.com/spec/v1
-oid sha256:3ffe5901b54ac442c8b71a7ff1d59bb3903ef2374c6fad378e55fa857e2ff34c
-size 23162
diff --git a/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.libraries.designsystem.theme.components_null_Buttons_FilledButtonLargePreview_0_null,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.libraries.designsystem.theme.components_null_Buttons_FilledButtonLargePreview_0_null,NEXUS_5,1.0,en].png
new file mode 100644
index 0000000000..4bc307ba70
--- /dev/null
+++ b/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.libraries.designsystem.theme.components_null_Buttons_FilledButtonLargePreview_0_null,NEXUS_5,1.0,en].png
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:fcae0955e194993a9cfe55a4279d7b9b601d4fa91e6ff67962d9339ec32eb952
+size 43832
diff --git a/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.libraries.designsystem.theme.components_null_Buttons_FilledButtonMediumPreview_0_null,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.libraries.designsystem.theme.components_null_Buttons_FilledButtonMediumPreview_0_null,NEXUS_5,1.0,en].png
new file mode 100644
index 0000000000..ce6e549f68
--- /dev/null
+++ b/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.libraries.designsystem.theme.components_null_Buttons_FilledButtonMediumPreview_0_null,NEXUS_5,1.0,en].png
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:13c793c97dc51d2cef3e3590efb65957e58bf77501f5791b2a0a8edb01a48c5f
+size 42358
diff --git a/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.libraries.designsystem.theme.components_null_Buttons_IconButtonPreview_0_null,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.libraries.designsystem.theme.components_null_Buttons_IconButtonPreview_0_null,NEXUS_5,1.0,en].png
index f6c9fc64dc..d25604d927 100644
--- a/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.libraries.designsystem.theme.components_null_Buttons_IconButtonPreview_0_null,NEXUS_5,1.0,en].png
+++ b/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.libraries.designsystem.theme.components_null_Buttons_IconButtonPreview_0_null,NEXUS_5,1.0,en].png
@@ -1,3 +1,3 @@
 version https://git-lfs.github.com/spec/v1
-oid sha256:19db35d98bc8f6e4525e297616b564c9c2acbc2e9f7422292aca4a5d485c4314
-size 7682
+oid sha256:0de49c41130b525fd6baf687ccd63b3d98997d9a31d23a0ea826d0dbe7c1998e
+size 10404
diff --git a/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.libraries.designsystem.theme.components_null_Buttons_OutlinedButtonLargePreview_0_null,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.libraries.designsystem.theme.components_null_Buttons_OutlinedButtonLargePreview_0_null,NEXUS_5,1.0,en].png
new file mode 100644
index 0000000000..757ac6640e
--- /dev/null
+++ b/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.libraries.designsystem.theme.components_null_Buttons_OutlinedButtonLargePreview_0_null,NEXUS_5,1.0,en].png
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:3093cd24a222f9854c3927fdd3fb39d26b1ad602b6e8580966ecae36ff937358
+size 47957
diff --git a/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.libraries.designsystem.theme.components_null_Buttons_OutlinedButtonMediumPreview_0_null,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.libraries.designsystem.theme.components_null_Buttons_OutlinedButtonMediumPreview_0_null,NEXUS_5,1.0,en].png
new file mode 100644
index 0000000000..2cdea2bdc1
--- /dev/null
+++ b/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.libraries.designsystem.theme.components_null_Buttons_OutlinedButtonMediumPreview_0_null,NEXUS_5,1.0,en].png
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:8c6b89df7fc0d8cda26ec10ffcb5c5ca266e913c75da9f1943a22b6bb56691f9
+size 47167
diff --git a/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.libraries.designsystem.theme.components_null_Buttons_OutlinedButtonsPreview_0_null,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.libraries.designsystem.theme.components_null_Buttons_OutlinedButtonsPreview_0_null,NEXUS_5,1.0,en].png
deleted file mode 100644
index f918f32903..0000000000
--- a/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.libraries.designsystem.theme.components_null_Buttons_OutlinedButtonsPreview_0_null,NEXUS_5,1.0,en].png
+++ /dev/null
@@ -1,3 +0,0 @@
-version https://git-lfs.github.com/spec/v1
-oid sha256:6efea5a0c9cd8e5626c16248e020b88a069ce878b4471e93dd9ccb956ddd41df
-size 26956
diff --git a/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.libraries.designsystem.theme.components_null_Buttons_TextButtonLargePreview_0_null,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.libraries.designsystem.theme.components_null_Buttons_TextButtonLargePreview_0_null,NEXUS_5,1.0,en].png
new file mode 100644
index 0000000000..b64970ee0e
--- /dev/null
+++ b/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.libraries.designsystem.theme.components_null_Buttons_TextButtonLargePreview_0_null,NEXUS_5,1.0,en].png
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:b57120ea3e2b2ca243a738000f89aa3bbc6d9bc87d76d597b594165a5d4c489d
+size 32489
diff --git a/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.libraries.designsystem.theme.components_null_Buttons_TextButtonMediumPreview_0_null,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.libraries.designsystem.theme.components_null_Buttons_TextButtonMediumPreview_0_null,NEXUS_5,1.0,en].png
new file mode 100644
index 0000000000..afa63e44bd
--- /dev/null
+++ b/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.libraries.designsystem.theme.components_null_Buttons_TextButtonMediumPreview_0_null,NEXUS_5,1.0,en].png
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:2fb4d0d2ce2c59edf9f55c30e9221b192dd421cb83e56acb7c1ae7218ceff761
+size 30776
diff --git a/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.libraries.designsystem.theme.components_null_Buttons_TextButtonPreview_0_null,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.libraries.designsystem.theme.components_null_Buttons_TextButtonPreview_0_null,NEXUS_5,1.0,en].png
deleted file mode 100644
index ebcd57bd3b..0000000000
--- a/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.libraries.designsystem.theme.components_null_Buttons_TextButtonPreview_0_null,NEXUS_5,1.0,en].png
+++ /dev/null
@@ -1,3 +0,0 @@
-version https://git-lfs.github.com/spec/v1
-oid sha256:640035df43196f84a7031578feb4b54f9702801c7974fc7af6a80eb907c40097
-size 17486
diff --git a/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.libraries.designsystem.theme.components_null_Dialogs_Dialogwithonlymessageandokbutton_0_null,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.libraries.designsystem.theme.components_null_Dialogs_Dialogwithonlymessageandokbutton_0_null,NEXUS_5,1.0,en].png
new file mode 100644
index 0000000000..f9ba6a7ce2
--- /dev/null
+++ b/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.libraries.designsystem.theme.components_null_Dialogs_Dialogwithonlymessageandokbutton_0_null,NEXUS_5,1.0,en].png
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:dc702968f26dcbc042d1c44de84cf200cd1b08e6c160bf454ea8ec5ee002b63a
+size 50858
diff --git a/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.libraries.designsystem.theme.components_null_Dialogs_Dialogwithtitle,iconandokbutton_0_null,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.libraries.designsystem.theme.components_null_Dialogs_Dialogwithtitle,iconandokbutton_0_null,NEXUS_5,1.0,en].png
new file mode 100644
index 0000000000..ab9564627c
--- /dev/null
+++ b/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.libraries.designsystem.theme.components_null_Dialogs_Dialogwithtitle,iconandokbutton_0_null,NEXUS_5,1.0,en].png
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:9bd1e84d97db0588e6bea339acab2aec499c99730e93381f8a019d6201e129f7
+size 56998
diff --git a/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.libraries.designsystem.theme.components_null_Dialogs_Dialogwithtitleandokbutton_0_null,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.libraries.designsystem.theme.components_null_Dialogs_Dialogwithtitleandokbutton_0_null,NEXUS_5,1.0,en].png
new file mode 100644
index 0000000000..6665e0a034
--- /dev/null
+++ b/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.libraries.designsystem.theme.components_null_Dialogs_Dialogwithtitleandokbutton_0_null,NEXUS_5,1.0,en].png
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:18d9b58bdba48472cc32110e4d032b7b4a4cbc80cdf9e8ee44964fdbdde5e976
+size 55508
diff --git a/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.libraries.designsystem.theme.components_null_Menus_DropdownMenuItemPreview_0_null,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.libraries.designsystem.theme.components_null_Menus_DropdownMenuItemPreview_0_null,NEXUS_5,1.0,en].png
index 4c91805426..305257631f 100644
--- a/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.libraries.designsystem.theme.components_null_Menus_DropdownMenuItemPreview_0_null,NEXUS_5,1.0,en].png
+++ b/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.libraries.designsystem.theme.components_null_Menus_DropdownMenuItemPreview_0_null,NEXUS_5,1.0,en].png
@@ -1,3 +1,3 @@
 version https://git-lfs.github.com/spec/v1
-oid sha256:1765f4842cbd6e3c1b7daa9a9cc13fc0f4c47ff73c2cb1fdd7f3d2377eea0553
-size 9053
+oid sha256:e425d58f766655f1003c595637ab7387cdf74ba7ae7862bf2f137f3ffd33f3f3
+size 21202
diff --git a/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.libraries.designsystem.theme.components_null_ProgressIndicators_LinearProgressIndicatorPreview_0_null,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.libraries.designsystem.theme.components_null_ProgressIndicators_LinearProgressIndicatorPreview_0_null,NEXUS_5,1.0,en].png
new file mode 100644
index 0000000000..2f67b451b6
--- /dev/null
+++ b/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.libraries.designsystem.theme.components_null_ProgressIndicators_LinearProgressIndicatorPreview_0_null,NEXUS_5,1.0,en].png
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:b756303958d8234c0e8c0f9ca16335c54d8bd610c73790058d6389eb7c8c3fae
+size 4875
diff --git a/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.libraries.designsystem.theme.components_null_Snackbars_Snackbar_0_null,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.libraries.designsystem.theme.components_null_Snackbars_Snackbar_0_null,NEXUS_5,1.0,en].png
new file mode 100644
index 0000000000..a686a3827e
--- /dev/null
+++ b/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.libraries.designsystem.theme.components_null_Snackbars_Snackbar_0_null,NEXUS_5,1.0,en].png
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:313860648fc6bf47ec98182ff018c54df61703fd8c1e302811a1e3a79a35b72a
+size 15933
diff --git a/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.libraries.designsystem.theme.components_null_Snackbars_Snackbarwithaction_0_null,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.libraries.designsystem.theme.components_null_Snackbars_Snackbarwithaction_0_null,NEXUS_5,1.0,en].png
new file mode 100644
index 0000000000..c112d357b8
--- /dev/null
+++ b/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.libraries.designsystem.theme.components_null_Snackbars_Snackbarwithaction_0_null,NEXUS_5,1.0,en].png
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:92ffb912aeeea5d161bd8c94ce7ac865eee13de50a7bc15217bfd0955e5a9b32
+size 18516
diff --git a/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.libraries.designsystem.theme.components_null_Snackbars_Snackbarwithactionandclosebutton_0_null,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.libraries.designsystem.theme.components_null_Snackbars_Snackbarwithactionandclosebutton_0_null,NEXUS_5,1.0,en].png
new file mode 100644
index 0000000000..fd4c9b3d18
--- /dev/null
+++ b/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.libraries.designsystem.theme.components_null_Snackbars_Snackbarwithactionandclosebutton_0_null,NEXUS_5,1.0,en].png
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:55e08f85f71dc07addee6079425158831ed50209f4a43fad9a8d0252d55d0f4a
+size 19486
diff --git a/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.libraries.designsystem.theme.components_null_Snackbars_Snackbarwithactionandclosebuttononnewline_0_null,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.libraries.designsystem.theme.components_null_Snackbars_Snackbarwithactionandclosebuttononnewline_0_null,NEXUS_5,1.0,en].png
new file mode 100644
index 0000000000..84918c94b2
--- /dev/null
+++ b/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.libraries.designsystem.theme.components_null_Snackbars_Snackbarwithactionandclosebuttononnewline_0_null,NEXUS_5,1.0,en].png
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:de21230c271bc78f767f130e07403d778ac65d347cbb4ba564d883c679a283ad
+size 20084
diff --git a/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.libraries.designsystem.theme.components_null_Snackbars_Snackbarwithactiononnewline_0_null,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.libraries.designsystem.theme.components_null_Snackbars_Snackbarwithactiononnewline_0_null,NEXUS_5,1.0,en].png
new file mode 100644
index 0000000000..b2689c1029
--- /dev/null
+++ b/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.libraries.designsystem.theme.components_null_Snackbars_Snackbarwithactiononnewline_0_null,NEXUS_5,1.0,en].png
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:62b5669a3f1a1138f5b982d27a1d4b2f0a2f79e862a4e50eb238c1d09de3d390
+size 18833
diff --git a/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.libraries.designsystem.theme.components_null_Toggles_CheckboxesPreview_0_null,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.libraries.designsystem.theme.components_null_Toggles_CheckboxesPreview_0_null,NEXUS_5,1.0,en].png
index 84068bb6f7..e4e7faaccd 100644
--- a/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.libraries.designsystem.theme.components_null_Toggles_CheckboxesPreview_0_null,NEXUS_5,1.0,en].png
+++ b/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.libraries.designsystem.theme.components_null_Toggles_CheckboxesPreview_0_null,NEXUS_5,1.0,en].png
@@ -1,3 +1,3 @@
 version https://git-lfs.github.com/spec/v1
-oid sha256:eb51ba92db07682afe5727078f8e8b0a44cad16566b97430ca92132689bf25e7
-size 10188
+oid sha256:30dc47ea866c8d8c1faab02ce12e9d00441a70b778bb267a3c52a5eb8635e6ad
+size 16686
diff --git a/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.libraries.designsystem.theme.components_null_Toggles_RadioButtonPreview_0_null,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.libraries.designsystem.theme.components_null_Toggles_RadioButtonPreview_0_null,NEXUS_5,1.0,en].png
index b7dfb49de8..97f012d11b 100644
--- a/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.libraries.designsystem.theme.components_null_Toggles_RadioButtonPreview_0_null,NEXUS_5,1.0,en].png
+++ b/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.libraries.designsystem.theme.components_null_Toggles_RadioButtonPreview_0_null,NEXUS_5,1.0,en].png
@@ -1,3 +1,3 @@
 version https://git-lfs.github.com/spec/v1
-oid sha256:ae7c673ab96eaa30a72ffa4b960b93f7c5971be1155aba7d03ac4c43652098ca
-size 16361
+oid sha256:88c7be1a8cff74b057ee0f7ba09922c814c8c0b6a3dbaa69ea58ec287c425fca
+size 14357
diff --git a/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.libraries.designsystem.theme.components_null_Toggles_SwitchPreview_0_null,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.libraries.designsystem.theme.components_null_Toggles_SwitchPreview_0_null,NEXUS_5,1.0,en].png
new file mode 100644
index 0000000000..209eac0f23
--- /dev/null
+++ b/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.libraries.designsystem.theme.components_null_Toggles_SwitchPreview_0_null,NEXUS_5,1.0,en].png
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:3812e3a220997be68aca7817c6c93987009f81079aa979161f297d529b91d8a1
+size 21505
diff --git a/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.libraries.matrix.ui.components_null_DefaultGroup_CheckableMatrixUserRowDarkPreview_0_null_0,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.libraries.matrix.ui.components_null_DefaultGroup_CheckableMatrixUserRowDarkPreview_0_null_0,NEXUS_5,1.0,en].png
index 7bdf26fe6c..80b9d8d46d 100644
--- a/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.libraries.matrix.ui.components_null_DefaultGroup_CheckableMatrixUserRowDarkPreview_0_null_0,NEXUS_5,1.0,en].png
+++ b/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.libraries.matrix.ui.components_null_DefaultGroup_CheckableMatrixUserRowDarkPreview_0_null_0,NEXUS_5,1.0,en].png
@@ -1,3 +1,3 @@
 version https://git-lfs.github.com/spec/v1
-oid sha256:254850b3a638c4d54d9f6642c15caf3e4037c47ce50ae48102e2346df6e8947f
-size 29282
+oid sha256:b49f3a925c6652957bbb90c71d2dc47618d47cf76ceec50d71d9ee8758a41ea8
+size 29262
diff --git a/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.libraries.matrix.ui.components_null_DefaultGroup_CheckableMatrixUserRowDarkPreview_0_null_1,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.libraries.matrix.ui.components_null_DefaultGroup_CheckableMatrixUserRowDarkPreview_0_null_1,NEXUS_5,1.0,en].png
index 8bdc8eb362..8ab9358d5b 100644
--- a/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.libraries.matrix.ui.components_null_DefaultGroup_CheckableMatrixUserRowDarkPreview_0_null_1,NEXUS_5,1.0,en].png
+++ b/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.libraries.matrix.ui.components_null_DefaultGroup_CheckableMatrixUserRowDarkPreview_0_null_1,NEXUS_5,1.0,en].png
@@ -1,3 +1,3 @@
 version https://git-lfs.github.com/spec/v1
-oid sha256:b8f5077f75ee156faae31e73d464840fda51f82b0666f0a8e661295eb193b133
-size 27442
+oid sha256:3a12ecd968f65e56fb995dcc05f7c9e3160a37dc1d9a95c8b6c52ba488fb1b22
+size 27454
diff --git a/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.libraries.matrix.ui.components_null_DefaultGroup_CheckableMatrixUserRowLightPreview_0_null_0,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.libraries.matrix.ui.components_null_DefaultGroup_CheckableMatrixUserRowLightPreview_0_null_0,NEXUS_5,1.0,en].png
index cb3c20fb27..1446cdefd5 100644
--- a/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.libraries.matrix.ui.components_null_DefaultGroup_CheckableMatrixUserRowLightPreview_0_null_0,NEXUS_5,1.0,en].png
+++ b/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.libraries.matrix.ui.components_null_DefaultGroup_CheckableMatrixUserRowLightPreview_0_null_0,NEXUS_5,1.0,en].png
@@ -1,3 +1,3 @@
 version https://git-lfs.github.com/spec/v1
-oid sha256:4f59b518dafea7d576a888661d740afeb1a6e72d432527a5f27d4a0a695eab35
-size 29718
+oid sha256:f428d22f64900a84904f02d7f49c0c7e9b295facaba3b86cec7175d98385dca9
+size 29663
diff --git a/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.libraries.matrix.ui.components_null_DefaultGroup_CheckableMatrixUserRowLightPreview_0_null_1,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.libraries.matrix.ui.components_null_DefaultGroup_CheckableMatrixUserRowLightPreview_0_null_1,NEXUS_5,1.0,en].png
index 26e1ff331d..fb2e423ef8 100644
--- a/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.libraries.matrix.ui.components_null_DefaultGroup_CheckableMatrixUserRowLightPreview_0_null_1,NEXUS_5,1.0,en].png
+++ b/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.libraries.matrix.ui.components_null_DefaultGroup_CheckableMatrixUserRowLightPreview_0_null_1,NEXUS_5,1.0,en].png
@@ -1,3 +1,3 @@
 version https://git-lfs.github.com/spec/v1
-oid sha256:7988848232d0f44f6fd04b1a8a8ce17681659be7e63a9f68f4f3743d51f3a679
-size 29382
+oid sha256:26a2304fe3e5ad79241843a8dfdb9cb81d47a8cd4b4c9ce7cc0552d8be91d03d
+size 29404
diff --git a/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.libraries.matrix.ui.components_null_DefaultGroup_CheckableUnresolvedUserRowPreview_0_null,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.libraries.matrix.ui.components_null_DefaultGroup_CheckableUnresolvedUserRowPreview_0_null,NEXUS_5,1.0,en].png
index 1ab026adf0..6da1f135d4 100644
--- a/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.libraries.matrix.ui.components_null_DefaultGroup_CheckableUnresolvedUserRowPreview_0_null,NEXUS_5,1.0,en].png
+++ b/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.libraries.matrix.ui.components_null_DefaultGroup_CheckableUnresolvedUserRowPreview_0_null,NEXUS_5,1.0,en].png
@@ -1,3 +1,3 @@
 version https://git-lfs.github.com/spec/v1
-oid sha256:3f6792f7963608fd167889be3e657ac6ca6eafa6949bfbf03fa21f9a07b34573
-size 115873
+oid sha256:d192c21d0da760d33517a226e93d8e994d6a83bbcebc422deae1dcca7e512f71
+size 115822
diff --git a/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.libraries.permissions.api_null_DefaultGroup_PermissionsViewDarkPreview_0_null_0,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.libraries.permissions.api_null_DefaultGroup_PermissionsViewDarkPreview_0_null_0,NEXUS_5,1.0,en].png
index 0ce9bb484a..22750d6377 100644
--- a/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.libraries.permissions.api_null_DefaultGroup_PermissionsViewDarkPreview_0_null_0,NEXUS_5,1.0,en].png
+++ b/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.libraries.permissions.api_null_DefaultGroup_PermissionsViewDarkPreview_0_null_0,NEXUS_5,1.0,en].png
@@ -1,3 +1,3 @@
 version https://git-lfs.github.com/spec/v1
-oid sha256:583910d40d3832aec4f2f1970f203e208ff6c8d4ea4a77fbbb3012a16d74b1d7
-size 23588
+oid sha256:922897d98edecf37a08b818edf88ca5ab2a62b810d3b8d1d70fdff611ec30e4f
+size 24272
diff --git a/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.libraries.permissions.api_null_DefaultGroup_PermissionsViewDarkPreview_0_null_1,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.libraries.permissions.api_null_DefaultGroup_PermissionsViewDarkPreview_0_null_1,NEXUS_5,1.0,en].png
index 4f1e3774a2..1ba3aa364c 100644
--- a/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.libraries.permissions.api_null_DefaultGroup_PermissionsViewDarkPreview_0_null_1,NEXUS_5,1.0,en].png
+++ b/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.libraries.permissions.api_null_DefaultGroup_PermissionsViewDarkPreview_0_null_1,NEXUS_5,1.0,en].png
@@ -1,3 +1,3 @@
 version https://git-lfs.github.com/spec/v1
-oid sha256:eece69f07544c8e61080cdc4391a12bbb52b30759a330a0967678af73112fda5
-size 32910
+oid sha256:e1a418d5bad67aba70ffba07e6d7d44b19962ea8433f4aa050b58784874a83c4
+size 33567
diff --git a/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.libraries.permissions.api_null_DefaultGroup_PermissionsViewDarkPreview_0_null_2,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.libraries.permissions.api_null_DefaultGroup_PermissionsViewDarkPreview_0_null_2,NEXUS_5,1.0,en].png
index e1933a744c..dfbfd18cfa 100644
--- a/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.libraries.permissions.api_null_DefaultGroup_PermissionsViewDarkPreview_0_null_2,NEXUS_5,1.0,en].png
+++ b/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.libraries.permissions.api_null_DefaultGroup_PermissionsViewDarkPreview_0_null_2,NEXUS_5,1.0,en].png
@@ -1,3 +1,3 @@
 version https://git-lfs.github.com/spec/v1
-oid sha256:9a5a75e7614025e08e320771628ddb7e3b24f055bc5ced0785b9b259f183200c
-size 27249
+oid sha256:0920fdd5ec77504fb5b94e3e77dd1afade7f917282b2fecab2fc30d986a34ca1
+size 27885
diff --git a/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.libraries.permissions.api_null_DefaultGroup_PermissionsViewLightPreview_0_null_0,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.libraries.permissions.api_null_DefaultGroup_PermissionsViewLightPreview_0_null_0,NEXUS_5,1.0,en].png
index 38772ec2da..8f982d38ac 100644
--- a/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.libraries.permissions.api_null_DefaultGroup_PermissionsViewLightPreview_0_null_0,NEXUS_5,1.0,en].png
+++ b/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.libraries.permissions.api_null_DefaultGroup_PermissionsViewLightPreview_0_null_0,NEXUS_5,1.0,en].png
@@ -1,3 +1,3 @@
 version https://git-lfs.github.com/spec/v1
-oid sha256:e8cb222bf65bcc884814d8af92f032a79a2bdbf6f66f5ca792e7f72ad3917fbe
-size 24442
+oid sha256:9525fb2cb0576268b8af4eed06d882d623a8f78e8581f6c9a63bf74403c88909
+size 26018
diff --git a/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.libraries.permissions.api_null_DefaultGroup_PermissionsViewLightPreview_0_null_1,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.libraries.permissions.api_null_DefaultGroup_PermissionsViewLightPreview_0_null_1,NEXUS_5,1.0,en].png
index d0f492d482..06367fb9b9 100644
--- a/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.libraries.permissions.api_null_DefaultGroup_PermissionsViewLightPreview_0_null_1,NEXUS_5,1.0,en].png
+++ b/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.libraries.permissions.api_null_DefaultGroup_PermissionsViewLightPreview_0_null_1,NEXUS_5,1.0,en].png
@@ -1,3 +1,3 @@
 version https://git-lfs.github.com/spec/v1
-oid sha256:a277bf8619ef6f8d52a83d33e855f03e28dfea14e2af2482db3f7ce1a89c35c4
-size 34396
+oid sha256:bca874faf9c1d1525744d8a4942df1d4f019a71aa4faf6ec9a8d4d368483a1ef
+size 35855
diff --git a/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.libraries.permissions.api_null_DefaultGroup_PermissionsViewLightPreview_0_null_2,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.libraries.permissions.api_null_DefaultGroup_PermissionsViewLightPreview_0_null_2,NEXUS_5,1.0,en].png
index 94861e6fda..d860328261 100644
--- a/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.libraries.permissions.api_null_DefaultGroup_PermissionsViewLightPreview_0_null_2,NEXUS_5,1.0,en].png
+++ b/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.libraries.permissions.api_null_DefaultGroup_PermissionsViewLightPreview_0_null_2,NEXUS_5,1.0,en].png
@@ -1,3 +1,3 @@
 version https://git-lfs.github.com/spec/v1
-oid sha256:5d61c7c8f802a9f1bfefbf4d2b0e666a9e2162fa13bab523584baedf380c1df6
-size 28484
+oid sha256:e1b3a38d1d502cf9fb54517f82afeaa7c47a0bb9968273a1e0a76ea60e181798
+size 29711
diff --git a/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.services.apperror.impl_null_DefaultGroup_AppErrorViewDarkPreview_0_null,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.services.apperror.impl_null_DefaultGroup_AppErrorViewDarkPreview_0_null,NEXUS_5,1.0,en].png
index 70da769e1f..a8f9374795 100644
--- a/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.services.apperror.impl_null_DefaultGroup_AppErrorViewDarkPreview_0_null,NEXUS_5,1.0,en].png
+++ b/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.services.apperror.impl_null_DefaultGroup_AppErrorViewDarkPreview_0_null,NEXUS_5,1.0,en].png
@@ -1,3 +1,3 @@
 version https://git-lfs.github.com/spec/v1
-oid sha256:484c56c1ab68d394200202bda364175a1fbd27df31630649010852a4c2552870
-size 20801
+oid sha256:3cd64fd3c8647a179c8cccb46878a3495bf2a41173c62d0a378c8ff003dfe7bc
+size 20148
diff --git a/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.services.apperror.impl_null_DefaultGroup_AppErrorViewLightPreview_0_null,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.services.apperror.impl_null_DefaultGroup_AppErrorViewLightPreview_0_null,NEXUS_5,1.0,en].png
index f2a152da09..a5b012cc36 100644
--- a/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.services.apperror.impl_null_DefaultGroup_AppErrorViewLightPreview_0_null,NEXUS_5,1.0,en].png
+++ b/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.services.apperror.impl_null_DefaultGroup_AppErrorViewLightPreview_0_null,NEXUS_5,1.0,en].png
@@ -1,3 +1,3 @@
 version https://git-lfs.github.com/spec/v1
-oid sha256:b8d6b5bcaa10f4ae2142edfef6745e22e0e9f8f52d9fedcbe77d3523ec4cb48d
-size 21476
+oid sha256:f458452cceef79d94ab3875c67e1664c60f13b77eb3ede7c0cdc04538bed9298
+size 21730
diff --git a/tools/check/check_code_quality.sh b/tools/check/check_code_quality.sh
index 9e8c964499..f37d661379 100755
--- a/tools/check/check_code_quality.sh
+++ b/tools/check/check_code_quality.sh
@@ -38,7 +38,7 @@ else
 fi
 
 echo
-echo "Search for forbidden patterns in code..."
+echo "Search for forbidden patterns in Kotlin source files..."
 
 # list all Kotlin folders of the project.
 allKotlinDirs=`find . -type d |grep -v build |grep -v \.git |grep -v \.gradle |grep kotlin$`
@@ -47,9 +47,20 @@ ${searchForbiddenStringsScript} ./tools/check/forbidden_strings_in_code.txt $all
 
 resultForbiddenStringInCode=$?
 
-if [[ ${resultForbiddenStringInCode} -eq 0 ]]; then
-   echo "MAIN OK"
+echo
+echo "Search for forbidden patterns in XML resource files..."
+
+# list all res folders of the project.
+allResDirs=`find . -type d |grep -v build |grep -v \.git |grep -v \.gradle |grep /res$`
+
+${searchForbiddenStringsScript} ./tools/check/forbidden_strings_in_xml.txt $allResDirs
+
+resultForbiddenStringInXml=$?
+
+if [[ ${resultForbiddenStringInCode} -eq 0 ]] \
+   && [[ ${resultForbiddenStringInXml} -eq 0 ]]; then
+   echo "OK"
 else
-   echo "❌ MAIN ERROR"
+   echo "❌ ERROR, please check the logs above."
    exit 1
 fi
diff --git a/tools/check/forbidden_strings_in_xml.txt b/tools/check/forbidden_strings_in_xml.txt
new file mode 100755
index 0000000000..ee0e4c7136
--- /dev/null
+++ b/tools/check/forbidden_strings_in_xml.txt
@@ -0,0 +1,38 @@
+#
+# Copyright 2023 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
+#
+#     http://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.
+#
+
+# This file list String which are not allowed in resource.
+# Use Perl regex to write forbidden strings
+# Note: line cannot start with a space. Use \s instead.
+# It is possible to specify an authorized number of occurrence with === suffix. Default is 0
+# Example:
+# AuthorizedStringThreeTimes===3
+
+# Extension:xml
+
+### Empty tag detected. Empty translation or plurals?
+">"">>>>>>
+
+### "DO NOT COMMIT" has been committed
+DO NOT COMMIT
+
+### Tab char is forbidden. Use only spaces
+\t
diff --git a/tools/detekt/detekt.yml b/tools/detekt/detekt.yml
index a3bad54ab3..14193a1c70 100644
--- a/tools/detekt/detekt.yml
+++ b/tools/detekt/detekt.yml
@@ -1,6 +1,21 @@
 # Default rules: https://github.com/detekt/detekt/blob/main/detekt-core/src/main/resources/default-detekt-config.yml
 
 style:
+  AlsoCouldBeApply:
+    active: true
+  CascadingCallWrapping:
+    active: true
+    includeElvis: true
+  DataClassShouldBeImmutable:
+    active: true
+  EqualsNullCall:
+    active: true
+  EqualsOnSignatureLine:
+    active: true
+  ExplicitCollectionElementAccessMethod:
+    active: true
+  ExplicitItLambdaParameter:
+    active: true
   MaxLineLength:
     # Default is 120
     maxLineLength: 160
@@ -9,38 +24,117 @@ style:
   ReturnCount:
     active: false
   UnnecessaryAbstractClass:
-    active: false
+    active: true
   FunctionOnlyReturningConstant:
     active: false
   UnusedPrivateMember:
-    # TODO Enable it
-    active: false
+    active: true
   UnusedParameter:
-    # TODO Enable it
-    active: false
+    active: true
+  UnnecessaryInnerClass:
+    active: true
+  UnnecessaryLet:
+    active: true
+  UnnecessaryParentheses:
+    active: true
+    allowForUnclearPrecedence: false
+  UntilInsteadOfRangeTo:
+    active: true
+  UnusedImports:
+    active: true
   UnusedPrivateProperty:
-    # TODO Enable it
-    active: false
+    active: true
   ThrowsCount:
     active: false
   LoopWithTooManyJumpStatements:
-    active: false
+    active: true
   SerialVersionUIDInSerializableClass:
     active: false
   ProtectedMemberInFinalClass:
-    active: false
+    active: true
   UseCheckOrError:
+    active: true
+  OptionalUnit:
+    active: true
+  PreferToOverPairSyntax:
+    active: true
+  RedundantExplicitType:
+    active: true
+  TrailingWhitespace:
+    active: true
+  TrimMultilineRawString:
+    active: true
+    trimmingMethods:
+      - 'trimIndent'
+      - 'trimMargin'
+  UnderscoresInNumericLiterals:
+    active: true
+    acceptableLength: 4
+    allowNonStandardGrouping: false
+  UnnecessaryAnnotationUseSiteTarget:
+    active: true
+  UnnecessaryBackticks:
+    active: true
+  UnnecessaryBracesAroundTrailingLambda:
+    active: true
+  UseDataClass:
+    active: true
+    allowVars: false
+  UseEmptyCounterpart:
+    active: true
+  UseIfEmptyOrIfBlank:
+    active: true
+  UseLet:
+    active: true
+  UseSumOfInsteadOfFlatMapSize:
+    active: true
+
+coroutines:
+  GlobalCoroutineUsage:
+    # Keep false for now.
     active: false
+  SuspendFunSwallowedCancellation:
+    active: true
+  SuspendFunWithCoroutineScopeReceiver:
+    active: true
 
 empty-blocks:
   EmptyFunctionBlock:
     active: false
   EmptySecondaryConstructor:
-    active: false
+    active: true
 
 potential-bugs:
   ImplicitDefaultLocale:
-    active: false
+    active: true
+  CastNullableToNonNullableType:
+    active: true
+  CastToNullableType:
+    active: true
+  Deprecation:
+    active: true
+  DontDowncastCollectionTypes:
+    active: true
+  ElseCaseInsteadOfExhaustiveWhen:
+    active: true
+  ExitOutsideMain:
+    active: true
+  ImplicitUnitReturnType:
+    active: true
+    allowExplicitReturnType: false
+  MissingPackageDeclaration:
+    active: true
+    excludes: ['**/*.kts']
+  NullCheckOnMutableProperty:
+    active: true
+  NullableToStringCall:
+    active: true
+  PropertyUsedBeforeDeclaration:
+    active: true
+  UnconditionalJumpStatementInLoop:
+    active: true
+  UnnecessaryNotNullCheck:
+    active: true
 
 exceptions:
   TooGenericExceptionCaught:
@@ -48,11 +142,13 @@ exceptions:
   SwallowedException:
     active: false
   ThrowingExceptionsWithoutMessageOrCause:
-    active: false
+    active: true
   TooGenericExceptionThrown:
-    active: false
+    active: true
   InstanceOfCheckForException:
-    active: false
+    active: true
+  ObjectExtendsThrowable:
+    active: true
 
 complexity:
   TooManyFunctions:
@@ -66,24 +162,32 @@ complexity:
   NestedBlockDepth:
     active: false
   ComplexCondition:
-    active: false
+    active: true
   LargeClass:
-    active: false
+    active: true
 
 naming:
   VariableNaming:
-    # TODO Enable it
-    active: false
+    active: true
   TopLevelPropertyNaming:
-    # TODO Enable it
-    active: false
+    active: true
   FunctionNaming:
     active: true
     ignoreAnnotated: ['Composable']
+  LambdaParameterNaming:
+    active: true
+  NonBooleanPropertyPrefixedWithIs:
+    active: true
+  VariableMaxLength:
+    active: true
 
 performance:
   SpreadOperator:
     active: false
+  CouldBeSequence:
+    active: true
+  UnnecessaryPartOfBinaryExpression:
+    active: true
 
 # Note: all rules for `comments` are disabled by default, but I put them here to be aware of their existence
 comments:
@@ -143,15 +247,10 @@ Compose:
   PreviewNaming:
     active: true
   PreviewPublic:
-    active: false
+    active: true
     # You can optionally disable that only previews with @PreviewParameter are flagged
     previewPublicOnlyIfParams: false
   RememberMissing:
     active: true
   UnstableCollections:
     active: true
-  ViewModelForwarding:
-    ## TODO Set to true later
-    active: false
-  ViewModelInjection:
-    active: true
diff --git a/tools/gitflow/gitflow-init.sh b/tools/gitflow/gitflow-init.sh
new file mode 100755
index 0000000000..5068a37575
--- /dev/null
+++ b/tools/gitflow/gitflow-init.sh
@@ -0,0 +1,19 @@
+#!/usr/bin/env bash
+
+#
+# Copyright (c) 2023 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
+#
+#     http://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.
+
+git flow init -d
+git config gitflow.prefix.versiontag v
diff --git a/tools/github/download_github_artifacts.py b/tools/github/download_github_artifacts.py
new file mode 100755
index 0000000000..892a4affa6
--- /dev/null
+++ b/tools/github/download_github_artifacts.py
@@ -0,0 +1,154 @@
+#!/usr/bin/env python3
+#
+# Copyright 2022 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
+#
+#     http://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.
+#
+
+import argparse
+import hashlib
+import json
+import os
+# Run `pip3 install requests` if not installed yet
+import requests
+
+# This script downloads artifacts from GitHub.
+# Ref: https://docs.github.com/en/rest/actions/artifacts#get-an-artifact
+
+error = False
+
+### Arguments
+
+parser = argparse.ArgumentParser(description='Download artifacts from GitHub.')
+parser.add_argument('-t',
+                    '--token',
+                    required=True,
+                    help='The GitHub token with read access.')
+parser.add_argument('-a',
+                    '--artifactUrl',
+                    required=True,
+                    help='the artifact_url from GitHub.')
+parser.add_argument('-f',
+                    '--filename',
+                    help='the filename, if not provided, will use the artifact name.')
+parser.add_argument('-i',
+                    '--ignoreErrors',
+                    help='Ignore errors that can be ignored. Build state and number of artifacts.',
+                    action="store_true")
+parser.add_argument('-d',
+                    '--directory',
+                    default="",
+                    help='the target directory, where files will be downloaded. If not provided the build number will be used to create a directory.')
+parser.add_argument('-v',
+                    '--verbose',
+                    help="increase output verbosity.",
+                    action="store_true")
+parser.add_argument('-s',
+                    '--simulate',
+                    help="simulate action, do not create folder or download any file.",
+                    action="store_true")
+
+args = parser.parse_args()
+
+if args.verbose:
+    print("Argument:")
+    print(args)
+
+# Split the artifact URL to get information
+# Ex: https://github.com/vector-im/element-android/suites/9293388174/artifacts/435942121
+artifactUrl = args.artifactUrl
+if not artifactUrl.startswith('https://github.com/'):
+    print("❌ Invalid parameter --artifactUrl %s. Must start with 'https://github.com/'" % artifactUrl)
+    exit(1)
+if "/artifacts/" not in artifactUrl:
+    print("❌ Invalid parameter --artifactUrl %s. Must contain '/artifacts/'" % artifactUrl)
+    exit(1)
+artifactItems = artifactUrl.split("/")
+if len(artifactItems) != 9:
+    print("❌ Invalid parameter --artifactUrl %s. Please check the format." % (artifactUrl))
+    exit(1)
+
+gitHubRepoOwner = artifactItems[3]
+gitHubRepo = artifactItems[4]
+artifactId = artifactItems[8]
+
+if args.verbose:
+    print("gitHubRepoOwner: %s, gitHubRepo: %s, artifactId: %s" % (gitHubRepoOwner, gitHubRepo, artifactId))
+
+headers = {
+   'Authorization': "Bearer %s" % args.token,
+   'Accept': 'application/vnd.github+json'
+}
+base_url = "https://api.github.com/repos/%s/%s/actions/artifacts/%s" % (gitHubRepoOwner, gitHubRepo, artifactId)
+
+### Fetch build state
+
+print("Getting artifacts data of project '%s/%s' artifactId '%s'..." % (gitHubRepoOwner, gitHubRepo, artifactId))
+
+if args.verbose:
+    print("Url: %s" % base_url)
+
+r = requests.get(base_url, headers=headers)
+data = json.loads(r.content.decode())
+
+if args.verbose:
+    print("Json data:")
+    print(data)
+
+if args.verbose:
+    print("Create subfolder %s to download artifacts..." % artifactId)
+
+if args.directory == "":
+    targetDir = artifactId
+else:
+    targetDir = args.directory
+
+if not args.simulate:
+    os.makedirs(targetDir, exist_ok=True)
+
+url = data.get("archive_download_url")
+if args.filename is not None:
+    filename = args.filename
+else:
+    filename = data.get("name") + ".zip"
+
+## Print some info about the artifact origin
+commitLink = "https://github.com/%s/%s/commit/%s" % (gitHubRepoOwner, gitHubRepo, data.get("workflow_run").get("head_sha"))
+print("Preparing to download artifact `%s`, built from branch: `%s` (commit %s)" % (data.get("name"), data.get("workflow_run").get("head_branch"), commitLink))
+
+if args.verbose:
+    print()
+    print("Artifact url: %s" % url)
+
+target = targetDir + "/" + filename
+sizeInBytes = data.get("size_in_bytes")
+print("Downloading %s to '%s' (file size is %s bytes, this may take a while)..." % (filename, targetDir, sizeInBytes))
+if not args.simulate:
+    # open file to write in binary mode
+    with open(target, "wb") as file:
+        # get request
+        response = requests.get(url, headers=headers)
+        # write to file
+        file.write(response.content)
+    print("Verifying file size...")
+    # get the file size
+    size = os.path.getsize(target)
+    if sizeInBytes != size:
+        # error = True
+        print("Warning, file size mismatch: expecting %s and get %s. This is just a warning for now..." % (sizeInBytes, size))
+
+if error:
+    print("❌ Error(s) occurred, please check the log")
+    exit(1)
+else:
+    print("Done!")
diff --git a/tools/lint/lint.xml b/tools/lint/lint.xml
index 914c9e7b68..db1a20701c 100644
--- a/tools/lint/lint.xml
+++ b/tools/lint/lint.xml
@@ -25,7 +25,7 @@
     
     
     
-    
+    
     
     
     
@@ -43,24 +43,11 @@
         
     
 
-    
+    
         
         
         
         
-
-        
-        
-        
-        
-
-        
-        
-        
-        
-        
-        
-        
     
 
     
@@ -81,7 +68,6 @@
     
     
     
-    
 
     
     
diff --git a/tools/localazy/README.md b/tools/localazy/README.md
index c1ad1d0ee0..b0b5c7e980 100644
--- a/tools/localazy/README.md
+++ b/tools/localazy/README.md
@@ -16,6 +16,8 @@ Localazy is used to host the source strings and their translations.
 
 ## Localazy project
 
+[![Localazy](https://img.shields.io/endpoint?url=https%3A%2F%2Fconnect.localazy.com%2Fstatus%2Felement%2Fdata%3Fcontent%3Dall%26title%3Dlocalazy%26logo%3Dtrue)](https://localazy.com/p/element)
+
 To add new strings, or to translate existing strings, go the the Localazy project: [https://localazy.com/p/element](https://localazy.com/p/element). Please follow the key naming rules (see below).
 
 Never edit manually the files `localazy.xml` or `translations.xml`!.
diff --git a/tools/quality/check.sh b/tools/quality/check.sh
new file mode 100755
index 0000000000..c3f87b3018
--- /dev/null
+++ b/tools/quality/check.sh
@@ -0,0 +1,30 @@
+#!/usr/bin/env bash
+
+#
+# Copyright 2023 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
+#
+#     http://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.
+#
+
+# List of tasks to run before creating a PR, to limit the risk of getting rejected by the CI.
+# Can be used as a git hook if you want.
+
+# exit when any command fails
+set -e
+
+# First run the quickest script
+./tools/check/check_code_quality.sh
+
+# Build, test and check the project, with warning as errors
+# It also check that the minimal app is compiling.
+./gradlew check -PallWarningsAsErrors=true
diff --git a/tools/release/release.sh b/tools/release/release.sh
new file mode 100755
index 0000000000..20005d2816
--- /dev/null
+++ b/tools/release/release.sh
@@ -0,0 +1,320 @@
+#!/usr/bin/env bash
+
+#
+# Copyright (c) 2023 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
+#
+#     http://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.
+#
+
+# do not exit when any command fails (issue with git flow)
+set +e
+
+printf "\n================================================================================\n"
+printf "|                    Welcome to the release script!                            |\n"
+printf "================================================================================\n"
+
+printf "Checking environment...\n"
+envError=0
+
+# Check that bundletool is installed
+if ! command -v bundletool &> /dev/null
+then
+    printf "Fatal: bundletool is not installed. You can install it running \`brew install bundletool\`\n"
+    envError=1
+fi
+
+# Path of the key store (it's a file)
+keyStorePath="${ELEMENT_X_KEYSTORE_PATH}"
+if [[ -z "${keyStorePath}" ]]; then
+    printf "Fatal: ELEMENT_X_KEYSTORE_PATH is not defined in the environment.\n"
+    envError=1
+fi
+# Keystore password
+keyStorePassword="${ELEMENT_X_KEYSTORE_PASSWORD}"
+if [[ -z "${keyStorePassword}" ]]; then
+    printf "Fatal: ELEMENT_X_KEYSTORE_PASSWORD is not defined in the environment.\n"
+    envError=1
+fi
+# Key password
+keyPassword="${ELEMENT_X_KEY_PASSWORD}"
+if [[ -z "${keyPassword}" ]]; then
+    printf "Fatal: ELEMENT_X_KEY_PASSWORD is not defined in the environment.\n"
+    envError=1
+fi
+# GitHub token
+gitHubToken="${ELEMENT_GITHUB_TOKEN}"
+if [[ -z "${gitHubToken}" ]]; then
+    printf "Fatal: ELEMENT_GITHUB_TOKEN is not defined in the environment.\n"
+    envError=1
+fi
+# Android home
+androidHome="${ANDROID_HOME}"
+if [[ -z "${androidHome}" ]]; then
+    printf "Fatal: ANDROID_HOME is not defined in the environment.\n"
+    envError=1
+fi
+# @elementbot:matrix.org matrix token / Not mandatory
+elementBotToken="${ELEMENT_BOT_MATRIX_TOKEN}"
+if [[ -z "${elementBotToken}" ]]; then
+    printf "Warning: ELEMENT_BOT_MATRIX_TOKEN is not defined in the environment.\n"
+fi
+
+if [ ${envError} == 1 ]; then
+  exit 1
+fi
+
+minSdkVersion=23
+buildToolsVersion="32.0.0"
+buildToolsPath="${androidHome}/build-tools/${buildToolsVersion}"
+
+if [[ ! -d ${buildToolsPath} ]]; then
+    printf "Fatal: ${buildToolsPath} folder not found, ensure that you have installed the SDK version ${buildToolsVersion}.\n"
+    exit 1
+fi
+
+# Check if git flow is enabled
+gitFlowDevelop=`git config gitflow.branch.develop`
+if [[ ${gitFlowDevelop} != "" ]]
+then
+    printf "Git flow is initialized\n"
+else
+    printf "Git flow is not initialized. Initializing...\n"
+    ./tools/gitflow/gitflow-init.sh
+fi
+
+printf "OK\n"
+
+printf "\n================================================================================\n"
+printf "Ensuring main and develop branches are up to date...\n"
+
+git checkout main
+git pull
+git checkout develop
+git pull
+
+printf "\n================================================================================\n"
+# Guessing version to propose a default version
+versionsFile="./plugins/src/main/kotlin/Versions.kt"
+versionMajorCandidate=`grep "val versionMajor" ${versionsFile} | cut  -d " " -f6`
+versionMinorCandidate=`grep "val versionMinor" ${versionsFile} | cut  -d " " -f6`
+versionPatchCandidate=`grep "val versionPatch" ${versionsFile} | cut  -d " " -f6`
+versionCandidate="${versionMajorCandidate}.${versionMinorCandidate}.${versionPatchCandidate}"
+
+read -p "Please enter the release version (example: ${versionCandidate}). Just press enter if ${versionCandidate} is correct. " version
+version=${version:-${versionCandidate}}
+
+# extract major, minor and patch for future use
+versionMajor=`echo ${version} | cut  -d "." -f1`
+versionMinor=`echo ${version} | cut  -d "." -f2`
+versionPatch=`echo ${version} | cut  -d "." -f3`
+nextPatchVersion=$((versionPatch + 2))
+
+printf "\n================================================================================\n"
+printf "Starting the release ${version}\n"
+git flow release start ${version}
+
+# Note: in case the release is already started and the script is started again, checkout the release branch again.
+ret=$?
+if [[ $ret -ne 0 ]]; then
+  printf "Mmh, it seems that the release is already started. Checking out the release branch...\n"
+  git checkout "release/${version}"
+fi
+
+# Ensure version is OK
+versionsFileBak="${versionsFile}.bak"
+cp ${versionsFile} ${versionsFileBak}
+sed "s/private const val versionMajor = .*/private const val versionMajor = ${versionMajor}/" ${versionsFileBak} > ${versionsFile}
+sed "s/private const val versionMinor = .*/private const val versionMinor = ${versionMinor}/" ${versionsFile}    > ${versionsFileBak}
+sed "s/private const val versionPatch = .*/private const val versionPatch = ${versionPatch}/" ${versionsFileBak} > ${versionsFile}
+rm ${versionsFileBak}
+
+# This commit may have no effect because generally we do not change the version during the release.
+git commit -a -m "Setting version for the release ${version}"
+
+printf "\n================================================================================\n"
+printf "Building the bundle locally first...\n"
+./gradlew clean bundleRelease
+
+printf "\n================================================================================\n"
+printf "Running towncrier...\n"
+yes | towncrier build --version "v${version}"
+
+printf "\n================================================================================\n"
+read -p "Check the file CHANGES.md consistency. It's possible to reorder items (most important changes first) or change their section if relevant. Also an opportunity to fix some typo, or rewrite things. Do not commit your change. Press enter when it's done."
+
+# Get the changes to use it to create the GitHub release
+changelogUrlEncoded=`git diff CHANGES.md | grep ^+ | tail -n +2 | cut -c2- | jq -sRr @uri | sed s/\(/%28/g | sed s/\)/%29/g`
+
+printf "\n================================================================================\n"
+printf "Committing...\n"
+git commit -a -m "Changelog for version ${version}"
+
+printf "\n================================================================================\n"
+printf "Creating fastlane file...\n"
+printf -v versionMajor2Digits "%02d" ${versionMajor}
+printf -v versionMinor2Digits "%02d" ${versionMinor}
+printf -v versionPatch2Digits "%02d" ${versionPatch}
+fastlaneFile="4${versionMajor2Digits}${versionMinor2Digits}${versionPatch2Digits}0.txt"
+fastlanePathFile="./fastlane/metadata/android/en-US/changelogs/${fastlaneFile}"
+printf "Main changes in this version: TODO.\nFull changelog: https://github.com/vector-im/element-x-android/releases" > ${fastlanePathFile}
+
+read -p "I have created the file ${fastlanePathFile}, please edit it and press enter when it's done."
+git add ${fastlanePathFile}
+git commit -a -m "Adding fastlane file for version ${version}"
+
+printf "\n================================================================================\n"
+printf "OK, finishing the release...\n"
+git flow release finish "${version}"
+
+printf "\n================================================================================\n"
+read -p "Done, push the branch 'main' and the new tag (yes/no) default to yes? " doPush
+doPush=${doPush:-yes}
+
+if [ ${doPush} == "yes" ]; then
+  printf "Pushing branch 'main' and tag 'v${version}'...\n"
+  git push origin main
+  git push origin "v${version}"
+else
+    printf "Not pushing, do not forget to push manually!\n"
+fi
+
+printf "\n================================================================================\n"
+printf "Checking out develop...\n"
+git checkout develop
+
+# Set next version
+printf "\n================================================================================\n"
+printf "Setting next version on file '${versionsFile}'...\n"
+cp ${versionsFile} ${versionsFileBak}
+sed "s/private const val versionPatch = .*/private const val versionPatch = ${nextPatchVersion}/" ${versionsFileBak} > ${versionsFile}
+rm ${versionsFileBak}
+
+printf "\n================================================================================\n"
+read -p "I have updated the versions to prepare the next release, please check that the change are correct and press enter so I can commit."
+
+printf "Committing...\n"
+git commit -a -m 'version++'
+
+printf "\n================================================================================\n"
+read -p "Done, push the branch 'develop' (yes/no) default to yes? (A rebase may be necessary in case develop got new commits) " doPush
+doPush=${doPush:-yes}
+
+if [ ${doPush} == "yes" ]; then
+  printf "Pushing branch 'develop'...\n"
+  git push origin develop
+else
+    printf "Not pushing, do not forget to push manually!\n"
+fi
+
+printf "\n================================================================================\n"
+printf "Wait for the GitHub action https://github.com/vector-im/element-x-android/actions/workflows/release.yml?query=branch%%3Amain to build the 'main' branch.\n"
+read -p "After GHA is finished, please enter the artifact URL (for 'elementx-app-bundle-unsigned'): " artifactUrl
+
+printf "\n================================================================================\n"
+printf "Downloading the artifact...\n"
+
+ # Download files
+targetPath="./tmp/Element/${version}"
+
+python3 ./tools/github/download_github_artifacts.py \
+     --token ${gitHubToken} \
+     --artifactUrl ${artifactUrl} \
+     --directory ${targetPath} \
+     --ignoreErrors
+
+printf "\n================================================================================\n"
+printf "Unzipping the artifact...\n"
+
+unzip ${targetPath}/elementx-app-bundle-unsigned.zip -d ${targetPath}
+
+unsignedBundlePath="${targetPath}/app-release.aab"
+signedBundlePath="${targetPath}/app-release-signed.aab"
+
+printf "\n================================================================================\n"
+printf "Signing file ${unsignedBundlePath} with build-tools version ${buildToolsVersion} for min SDK version ${minSdkVersion}...\n"
+
+cp ${unsignedBundlePath} ${signedBundlePath}
+
+${buildToolsPath}/apksigner sign \
+    -v \
+    --ks ${keyStorePath} \
+    --ks-pass pass:${keyStorePassword} \
+    --ks-key-alias elementx \
+    --key-pass pass:${keyPassword} \
+    --min-sdk-version ${minSdkVersion} \
+    ${signedBundlePath}
+
+printf "\n================================================================================\n"
+printf "Please check the information below:\n"
+
+printf "Version code: "
+bundletool dump manifest --bundle=${signedBundlePath} --xpath=/manifest/@android:versionCode
+printf "Version name: "
+bundletool dump manifest --bundle=${signedBundlePath} --xpath=/manifest/@android:versionName
+
+printf "\n"
+read -p "Does it look correct? Press enter when it's done."
+
+printf "\n================================================================================\n"
+printf "The file ${signedBundlePath} has been signed and can be uploaded to the PlayStore!\n"
+
+printf "\n================================================================================\n"
+read -p "Do you want to install the application to your device? Make sure there is a connected device first. (yes/no) default to yes " doDeploy
+doDeploy=${doDeploy:-yes}
+
+if [ ${doDeploy} == "yes" ]; then
+  printf "Building apks...\n"
+  bundletool build-apks --bundle=${signedBundlePath} --output=${targetPath}/elementx.apks \
+      --ks=./app/signature/debug.keystore --ks-pass=pass:android --ks-key-alias=androiddebugkey --key-pass=pass:android \
+      --overwrite
+  printf "Installing apk for your device...\n"
+  bundletool install-apks --apks=${targetPath}/elementx.apks
+  read -p "Please run the application on your phone to check that the upgrade went well (no init sync, etc.). Press enter when it's done."
+else
+  printf "Apk will not be deployed!\n"
+fi
+
+printf "\n================================================================================\n"
+githubCreateReleaseLink="https://github.com/vector-im/element-x-android/releases/new?tag=v${version}&title=Element%20X%20Android%20v${version}&body=${changelogUrlEncoded}"
+printf "Creating the release on gitHub.\n"
+printf -- "Open this link: %s\n" ${githubCreateReleaseLink}
+printf "Then\n"
+printf " - copy paste the section of the file CHANGES.md for this release (if not there yet)\n"
+printf " - click on the 'Generate releases notes' button\n"
+printf " - Add the file ${signedBundlePath} to the GitHub release.\n"
+read -p ". Press enter when it's done. "
+
+printf "\n================================================================================\n"
+printf "Message for the Android internal room:\n\n"
+message="@room Element X Android ${version} is ready to be tested. You can get it from https://github.com/vector-im/element-x-android/releases/tag/v${version}. Please report any feedback here. Thanks!"
+printf "${message}\n\n"
+
+if [[ -z "${elementBotToken}" ]]; then
+  read -p "ELEMENT_BOT_MATRIX_TOKEN is not defined in the environment. Cannot send the message for you. Please send it manually, and press enter when it's done "
+else
+  read -p "Send this message to the room (yes/no) default to yes? " doSend
+  doSend=${doSend:-yes}
+  if [ ${doSend} == "yes" ]; then
+    printf "Sending message...\n"
+    transactionId=`openssl rand -hex 16`
+    # Element Android internal
+    matrixRoomId="!LiSLXinTDCsepePiYW:matrix.org"
+    curl -X PUT --data $"{\"msgtype\":\"m.text\",\"body\":\"${message}\"}" -H "Authorization: Bearer ${elementBotToken}" https://matrix-client.matrix.org/_matrix/client/r0/rooms/${matrixRoomId}/send/m.room.message/\$local.${transactionId}
+  else
+    printf "Message not sent, please send it manually!\n"
+  fi
+fi
+
+printf "\n================================================================================\n"
+printf "Congratulation! Kudos for using this script! Have a nice day!\n"
+printf "================================================================================\n"