diff --git a/.gitattributes b/.gitattributes
index 2062142284..d0cf036126 100644
--- a/.gitattributes
+++ b/.gitattributes
@@ -1,2 +1,3 @@
**/snapshots/**/*.png filter=lfs diff=lfs merge=lfs -text
**/docs/images-lfs/*.png filter=lfs diff=lfs merge=lfs -text
+libraries/mediaupload/impl/src/test/assets/* filter=lfs diff=lfs merge=lfs -text
diff --git a/.github/ISSUE_TEMPLATE/bug.yml b/.github/ISSUE_TEMPLATE/bug.yml
index 893a4298c7..73f8c96ebc 100644
--- a/.github/ISSUE_TEMPLATE/bug.yml
+++ b/.github/ISSUE_TEMPLATE/bug.yml
@@ -1,5 +1,5 @@
name: Bug report for the Element X Android app
-description: Report any issues that you have found with the Element X app. Please [check open issues](https://github.com/vector-im/element-x-android/issues) first, in case it has already been reported.
+description: Report any issues that you have found with the Element X app. Please [check open issues](https://github.com/element-hq/element-x-android/issues) first, in case it has already been reported.
labels: [T-Defect]
body:
- type: markdown
diff --git a/.github/ISSUE_TEMPLATE/enhancement.yml b/.github/ISSUE_TEMPLATE/enhancement.yml
index 0e51d5155e..114bc2bc65 100644
--- a/.github/ISSUE_TEMPLATE/enhancement.yml
+++ b/.github/ISSUE_TEMPLATE/enhancement.yml
@@ -5,7 +5,7 @@ body:
- type: markdown
attributes:
value: |
- Thank you for taking the time to propose an enhancement to an existing feature. If you would like to propose a new feature or a major cross-platform change, please [start a discussion here](https://github.com/vector-im/element-meta/discussions/new?category=ideas).
+ Thank you for taking the time to propose an enhancement to an existing feature. If you would like to propose a new feature or a major cross-platform change, please [start a discussion here](https://github.com/element-hq/element-meta/discussions/new?category=ideas).
- type: textarea
id: usecase
attributes:
diff --git a/.github/dependabot.yml b/.github/dependabot.yml
index 29542e98c6..ec67e56676 100644
--- a/.github/dependabot.yml
+++ b/.github/dependabot.yml
@@ -13,7 +13,7 @@ updates:
ignore:
- dependency-name: "*"
reviewers:
- - "vector-im/element-x-android-reviewers"
+ - "element-hq/element-x-android-reviewers"
# Updates for Gradle dependencies used in the app
- package-ecosystem: "gradle"
directory: "/"
@@ -23,4 +23,4 @@ updates:
ignore:
- dependency-name: "*"
reviewers:
- - "vector-im/element-x-android-reviewers"
+ - "element-hq/element-x-android-reviewers"
diff --git a/.github/pull_request_template.md b/.github/pull_request_template.md
index 7aabcb77aa..29c7e163f4 100644
--- a/.github/pull_request_template.md
+++ b/.github/pull_request_template.md
@@ -1,4 +1,4 @@
-
+
## Type of change
@@ -53,9 +53,9 @@ Uncomment this markdown table below and edit the last line `|||`:
- [ ] Changes have been tested on an Android device or Android emulator with API 23
- [ ] UI change has been tested on both light and dark themes
-- [ ] Accessibility has been taken into account. See https://github.com/vector-im/element-x-android/blob/develop/CONTRIBUTING.md#accessibility
+- [ ] Accessibility has been taken into account. See https://github.com/element-hq/element-x-android/blob/develop/CONTRIBUTING.md#accessibility
- [ ] Pull request is based on the develop branch
-- [ ] Pull request includes a new file under ./changelog.d. See https://github.com/vector-im/element-x-android/blob/develop/CONTRIBUTING.md#changelog
+- [ ] Pull request includes a new file under ./changelog.d. See https://github.com/element-hq/element-x-android/blob/develop/CONTRIBUTING.md#changelog
- [ ] Pull request includes screenshots or videos if containing UI changes
- [ ] Pull request includes a [sign off](https://matrix-org.github.io/synapse/latest/development/contributing_guide.html#sign-off)
- [ ] You've made a self review of your PR
diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml
index a1df487c9b..ef41b71b7f 100644
--- a/.github/workflows/build.yml
+++ b/.github/workflows/build.yml
@@ -38,7 +38,7 @@ jobs:
distribution: 'temurin' # See 'Supported distributions' for available options
java-version: '17'
- name: Configure gradle
- uses: gradle/gradle-build-action@v2.10.0
+ uses: gradle/gradle-build-action@v2.11.0
with:
cache-read-only: ${{ github.ref != 'refs/heads/develop' }}
- name: Assemble debug APK
diff --git a/.github/workflows/danger.yml b/.github/workflows/danger.yml
index 772df369b8..e1c9205473 100644
--- a/.github/workflows/danger.yml
+++ b/.github/workflows/danger.yml
@@ -11,7 +11,7 @@ jobs:
- run: |
npm install --save-dev @babel/plugin-transform-flow-strip-types
- name: Danger
- uses: danger/danger-js@11.3.0
+ uses: danger/danger-js@11.3.1
with:
args: "--dangerfile ./tools/danger/dangerfile.js"
env:
diff --git a/.github/workflows/gradle-wrapper-update.yml b/.github/workflows/gradle-wrapper-update.yml
index 351057fc89..b3493e3bf7 100644
--- a/.github/workflows/gradle-wrapper-update.yml
+++ b/.github/workflows/gradle-wrapper-update.yml
@@ -12,7 +12,7 @@ jobs:
- name: Update Gradle Wrapper
uses: gradle-update/update-gradle-wrapper-action@v1
# Skip in forks
- if: github.repository == 'vector-im/element-x-android'
+ if: github.repository == 'element-hq/element-x-android'
with:
repo-token: ${{ secrets.GITHUB_TOKEN }}
target-branch: develop
diff --git a/.github/workflows/nightly.yml b/.github/workflows/nightly.yml
index 4b0b1ff53c..91976f56a0 100644
--- a/.github/workflows/nightly.yml
+++ b/.github/workflows/nightly.yml
@@ -14,7 +14,7 @@ jobs:
nightly:
name: Build and publish nightly bundle to Firebase
runs-on: ubuntu-latest
- if: ${{ github.repository == 'vector-im/element-x-android' }}
+ if: ${{ github.repository == 'element-hq/element-x-android' }}
steps:
- uses: actions/checkout@v4
- name: Use JDK 17
diff --git a/.github/workflows/nightlyReports.yml b/.github/workflows/nightlyReports.yml
index d19e214f99..e22069652f 100644
--- a/.github/workflows/nightlyReports.yml
+++ b/.github/workflows/nightlyReports.yml
@@ -15,7 +15,7 @@ jobs:
nightlyReports:
name: Create kover report artifact and upload sonar result.
runs-on: ubuntu-latest
- if: ${{ github.repository == 'vector-im/element-x-android' }}
+ if: ${{ github.repository == 'element-hq/element-x-android' }}
steps:
- name: ⏬ Checkout with LFS
uses: nschloe/action-cached-lfs-checkout@v1.2.2
@@ -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.10.0
+ uses: gradle/gradle-build-action@v2.11.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 c9d2ea7d18..1a2b3f8182 100644
--- a/.github/workflows/quality.yml
+++ b/.github/workflows/quality.yml
@@ -40,7 +40,7 @@ jobs:
distribution: 'temurin' # See 'Supported distributions' for available options
java-version: '17'
- name: Configure gradle
- uses: gradle/gradle-build-action@v2.10.0
+ uses: gradle/gradle-build-action@v2.11.0
with:
cache-read-only: ${{ github.ref != 'refs/heads/develop' }}
- name: Run code quality check suite
@@ -60,7 +60,7 @@ jobs:
yarn add danger-plugin-lint-report --dev
- name: Danger lint
if: always()
- uses: danger/danger-js@11.3.0
+ uses: danger/danger-js@11.3.1
with:
args: "--dangerfile ./tools/danger/dangerfile-lint.js"
env:
diff --git a/.github/workflows/recordScreenshots.yml b/.github/workflows/recordScreenshots.yml
index 8f72e4ec4a..2da69ecd4d 100644
--- a/.github/workflows/recordScreenshots.yml
+++ b/.github/workflows/recordScreenshots.yml
@@ -39,7 +39,7 @@ jobs:
java-version: '17'
# Add gradle cache, this should speed up the process
- name: Configure gradle
- uses: gradle/gradle-build-action@v2.10.0
+ uses: gradle/gradle-build-action@v2.11.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
index 924d115046..a5a08396bf 100644
--- a/.github/workflows/release.yml
+++ b/.github/workflows/release.yml
@@ -25,7 +25,7 @@ jobs:
distribution: 'temurin' # See 'Supported distributions' for available options
java-version: '17'
- name: Configure gradle
- uses: gradle/gradle-build-action@v2.10.0
+ uses: gradle/gradle-build-action@v2.11.0
- name: Create app bundle
env:
ELEMENT_ANDROID_MAPTILER_API_KEY: ${{ secrets.MAPTILER_KEY }}
diff --git a/.github/workflows/sonar.yml b/.github/workflows/sonar.yml
index d73a885220..464e0ae56e 100644
--- a/.github/workflows/sonar.yml
+++ b/.github/workflows/sonar.yml
@@ -32,7 +32,7 @@ jobs:
distribution: 'temurin' # See 'Supported distributions' for available options
java-version: '17'
- name: Configure gradle
- uses: gradle/gradle-build-action@v2.10.0
+ uses: gradle/gradle-build-action@v2.11.0
with:
cache-read-only: ${{ github.ref != 'refs/heads/develop' }}
- name: 🔊 Publish results to Sonar
diff --git a/.github/workflows/sync-localazy.yml b/.github/workflows/sync-localazy.yml
index f3acb4675b..2f728fdf66 100644
--- a/.github/workflows/sync-localazy.yml
+++ b/.github/workflows/sync-localazy.yml
@@ -9,11 +9,11 @@ jobs:
sync-localazy:
runs-on: ubuntu-latest
# Skip in forks
- if: github.repository == 'vector-im/element-x-android'
+ if: github.repository == 'element-hq/element-x-android'
steps:
- uses: actions/checkout@v4
- name: Set up Python 3.9
- uses: actions/setup-python@v4
+ uses: actions/setup-python@v5
with:
python-version: 3.9
- name: Setup Localazy
diff --git a/.github/workflows/sync-sas-strings.yml b/.github/workflows/sync-sas-strings.yml
new file mode 100644
index 0000000000..52aded770e
--- /dev/null
+++ b/.github/workflows/sync-sas-strings.yml
@@ -0,0 +1,35 @@
+name: Sync SAS strings
+on:
+ workflow_dispatch:
+ schedule:
+ # At 00:00 on every Monday UTC
+ - cron: '0 0 * * 1'
+
+jobs:
+ sync-sas-strings:
+ runs-on: ubuntu-latest
+ # Skip in forks
+ if: github.repository == 'element-hq/element-x-android'
+ # No concurrency required, runs every time on a schedule.
+ steps:
+ - uses: actions/checkout@v4
+ - name: Set up Python 3.8
+ uses: actions/setup-python@v5
+ with:
+ python-version: 3.9
+ - name: Install Prerequisite dependencies
+ run: |
+ pip install requests
+ - name: Run SAS String script
+ run: ./tools/sas/import_sas_strings.py
+ - name: Create Pull Request for SAS Strings
+ uses: peter-evans/create-pull-request@v5
+ with:
+ commit-message: Sync SAS Strings
+ title: Sync SAS Strings
+ body: |
+ - Update SAS Strings from matrix-doc.
+ branch: sync-sas-strings
+ base: develop
+
+
diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml
index 49951cf350..396fd0e49b 100644
--- a/.github/workflows/tests.yml
+++ b/.github/workflows/tests.yml
@@ -44,7 +44,7 @@ jobs:
distribution: 'temurin' # See 'Supported distributions' for available options
java-version: '17'
- name: Configure gradle
- uses: gradle/gradle-build-action@v2.10.0
+ uses: gradle/gradle-build-action@v2.11.0
with:
cache-read-only: ${{ github.ref != 'refs/heads/develop' }}
diff --git a/.github/workflows/triage-incoming.yml b/.github/workflows/triage-incoming.yml
index 1232b11d92..109b8cc82d 100644
--- a/.github/workflows/triage-incoming.yml
+++ b/.github/workflows/triage-incoming.yml
@@ -10,5 +10,5 @@ jobs:
steps:
- uses: actions/add-to-project@main
with:
- project-url: https://github.com/orgs/vector-im/projects/91
+ project-url: https://github.com/orgs/element-hq/projects/91
github-token: ${{ secrets.ELEMENT_BOT_TOKEN }}
diff --git a/.github/workflows/triage-labelled.yml b/.github/workflows/triage-labelled.yml
index 5f7e6cc6ec..f6a9de700c 100644
--- a/.github/workflows/triage-labelled.yml
+++ b/.github/workflows/triage-labelled.yml
@@ -10,11 +10,11 @@ jobs:
runs-on: ubuntu-latest
# Skip in forks
if: >
- github.repository == 'vector-im/element-x-android'
+ github.repository == 'element-hq/element-x-android'
steps:
- uses: actions/add-to-project@main
with:
- project-url: https://github.com/orgs/vector-im/projects/43
+ project-url: https://github.com/orgs/element-hq/projects/43
github-token: ${{ secrets.ELEMENT_BOT_TOKEN }}
move_needs_info:
@@ -24,7 +24,7 @@ jobs:
- uses: actions/add-to-project@main
id: addItem
with:
- project-url: https://github.com/orgs/vector-im/projects/91
+ project-url: https://github.com/orgs/element-hq/projects/91
github-token: ${{ secrets.ELEMENT_BOT_TOKEN }}
labeled: X-Needs-Info
- name: Print itemId
@@ -32,7 +32,7 @@ jobs:
- uses: kalgurn/update-project-item-status@main
if: ${{ steps.addItem.outputs.itemId }}
with:
- project-url: https://github.com/orgs/vector-im/projects/91
+ project-url: https://github.com/orgs/element-hq/projects/91
github-token: ${{ secrets.ELEMENT_BOT_TOKEN }}
item-id: ${{ steps.addItem.outputs.itemId }}
status: "Needs info"
@@ -45,7 +45,7 @@ jobs:
steps:
- uses: actions/add-to-project@main
with:
- project-url: https://github.com/orgs/vector-im/projects/73
+ project-url: https://github.com/orgs/element-hq/projects/73
github-token: ${{ secrets.ELEMENT_BOT_TOKEN }}
verticals_feature:
@@ -56,7 +56,7 @@ jobs:
steps:
- uses: actions/add-to-project@main
with:
- project-url: https://github.com/orgs/vector-im/projects/57
+ project-url: https://github.com/orgs/element-hq/projects/57
github-token: ${{ secrets.ELEMENT_BOT_TOKEN }}
qa:
@@ -68,7 +68,7 @@ jobs:
steps:
- uses: actions/add-to-project@main
with:
- project-url: https://github.com/orgs/vector-im/projects/69
+ project-url: https://github.com/orgs/element-hq/projects/69
github-token: ${{ secrets.ELEMENT_BOT_TOKEN }}
signoff:
@@ -79,5 +79,5 @@ jobs:
steps:
- uses: actions/add-to-project@main
with:
- project-url: https://github.com/orgs/vector-im/projects/89
+ project-url: https://github.com/orgs/element-hq/projects/89
github-token: ${{ secrets.ELEMENT_BOT_TOKEN }}
diff --git a/.idea/kotlinc.xml b/.idea/kotlinc.xml
index e805548aaa..ae3f30ae18 100644
--- a/.idea/kotlinc.xml
+++ b/.idea/kotlinc.xml
@@ -1,6 +1,6 @@
-
+
\ No newline at end of file
diff --git a/.idea/migrations.xml b/.idea/migrations.xml
new file mode 100644
index 0000000000..f8051a6f97
--- /dev/null
+++ b/.idea/migrations.xml
@@ -0,0 +1,10 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/AUTHORS.md b/AUTHORS.md
index 89404cd73f..b3c2de6470 100644
--- a/AUTHORS.md
+++ b/AUTHORS.md
@@ -1,4 +1,4 @@
-A full developer contributors list can be found [here](https://github.com/vector-im/element-x-android/graphs/contributors).
+A full developer contributors list can be found [here](https://github.com/element-hq/element-x-android/graphs/contributors).
# Core team:
diff --git a/CHANGES.md b/CHANGES.md
index 3b4b5ca350..d3b2257815 100644
--- a/CHANGES.md
+++ b/CHANGES.md
@@ -3,21 +3,21 @@ Changes in Element X v0.3.2 (2023-11-22)
Features ✨
----------
- - Add ongoing call indicator to rooms lists items. ([#1158](https://github.com/vector-im/element-x-android/issues/1158))
- - Add support for typing mentions in the message composer. ([#1453](https://github.com/vector-im/element-x-android/issues/1453))
- - Add intentional mentions to messages. This needs to be enabled in developer options since it's disabled by default. ([#1591](https://github.com/vector-im/element-x-android/issues/1591))
- - Update voice message recording behaviour. Instead of holding the record button, users can now tap the record button to start recording and tap again to stop recording. ([#1784](https://github.com/vector-im/element-x-android/issues/1784))
+ - Add ongoing call indicator to rooms lists items. ([#1158](https://github.com/element-hq/element-x-android/issues/1158))
+ - Add support for typing mentions in the message composer. ([#1453](https://github.com/element-hq/element-x-android/issues/1453))
+ - Add intentional mentions to messages. This needs to be enabled in developer options since it's disabled by default. ([#1591](https://github.com/element-hq/element-x-android/issues/1591))
+ - Update voice message recording behaviour. Instead of holding the record button, users can now tap the record button to start recording and tap again to stop recording. ([#1784](https://github.com/element-hq/element-x-android/issues/1784))
Bugfixes 🐛
----------
- - Always ensure media temp dir exists ([#1790](https://github.com/vector-im/element-x-android/issues/1790))
+ - Always ensure media temp dir exists ([#1790](https://github.com/element-hq/element-x-android/issues/1790))
Other changes
-------------
- - Update icons and move away from `PreferenceText` components. ([#1718](https://github.com/vector-im/element-x-android/issues/1718))
- - Add item "This is the beginning of..." at the beginning of the timeline. ([#1801](https://github.com/vector-im/element-x-android/issues/1801))
- - LockScreen : rework LoggedInFlowNode and back management when locked. ([#1806](https://github.com/vector-im/element-x-android/issues/1806))
- - Suppress usage of removeTimeline method. ([#1824](https://github.com/vector-im/element-x-android/issues/1824))
+ - Update icons and move away from `PreferenceText` components. ([#1718](https://github.com/element-hq/element-x-android/issues/1718))
+ - Add item "This is the beginning of..." at the beginning of the timeline. ([#1801](https://github.com/element-hq/element-x-android/issues/1801))
+ - LockScreen : rework LoggedInFlowNode and back management when locked. ([#1806](https://github.com/element-hq/element-x-android/issues/1806))
+ - Suppress usage of removeTimeline method. ([#1824](https://github.com/element-hq/element-x-android/issues/1824))
- Remove Element Call feature flag, it's now always enabled.
- Reverted the EC base URL to `https://call.element.io`.
- Moved the option to override this URL to developer settings from advanced settings.
@@ -28,16 +28,16 @@ Changes in Element X v0.3.1 (2023-11-09)
Features ✨
----------
- - Chat backup is still under a feature flag, but when enabled, user can enter their recovery key (it's also possible to input a passphrase) to unlock the encrypted room history. ([#1770](https://github.com/vector-im/element-x-android/pull/1770))
+ - Chat backup is still under a feature flag, but when enabled, user can enter their recovery key (it's also possible to input a passphrase) to unlock the encrypted room history. ([#1770](https://github.com/element-hq/element-x-android/pull/1770))
Bugfixes 🐛
----------
- - Improve confusing text in the 'ready to start verification' screen. ([#879](https://github.com/vector-im/element-x-android/issues/879))
- - Message composer wasn't resized when selecting a several lines message to reply to, then a single line one. ([#1560](https://github.com/vector-im/element-x-android/issues/1560))
+ - Improve confusing text in the 'ready to start verification' screen. ([#879](https://github.com/element-hq/element-x-android/issues/879))
+ - Message composer wasn't resized when selecting a several lines message to reply to, then a single line one. ([#1560](https://github.com/element-hq/element-x-android/issues/1560))
Other changes
-------------
- - PIN: Set lock grace period to 0. ([#1732](https://github.com/vector-im/element-x-android/issues/1732))
+ - PIN: Set lock grace period to 0. ([#1732](https://github.com/element-hq/element-x-android/issues/1732))
Changes in Element X v0.3.0 (2023-10-31)
@@ -45,24 +45,24 @@ Changes in Element X v0.3.0 (2023-10-31)
Features ✨
----------
- - Element Call: change the 'join call' button in a chat room when there's an active call. ([#1158](https://github.com/vector-im/element-x-android/issues/1158))
- - Mentions: add mentions suggestion view in RTE ([#1452](https://github.com/vector-im/element-x-android/issues/1452))
- - Record and send voice messages ([#1596](https://github.com/vector-im/element-x-android/issues/1596))
- - Enable voice messages for all users ([#1669](https://github.com/vector-im/element-x-android/issues/1669))
- - Receive and play a voice message ([#2084](https://github.com/vector-im/element-x-android/issues/2084))
+ - Element Call: change the 'join call' button in a chat room when there's an active call. ([#1158](https://github.com/element-hq/element-x-android/issues/1158))
+ - Mentions: add mentions suggestion view in RTE ([#1452](https://github.com/element-hq/element-x-android/issues/1452))
+ - Record and send voice messages ([#1596](https://github.com/element-hq/element-x-android/issues/1596))
+ - Enable voice messages for all users ([#1669](https://github.com/element-hq/element-x-android/issues/1669))
+ - Receive and play a voice message ([#2084](https://github.com/element-hq/element-x-android/issues/2084))
- Enable Element Call integration in rooms by default, fix several issues when creating or joining calls.
Bugfixes 🐛
----------
- - Group fallback notification to avoid having plenty of them displayed. ([#994](https://github.com/vector-im/element-x-android/issues/994))
- - Hide keyboard when exiting the chat room screen. ([#1375](https://github.com/vector-im/element-x-android/issues/1375))
- - Always register the pusher when application starts ([#1481](https://github.com/vector-im/element-x-android/issues/1481))
- - Ensure screen does not turn off when playing a video ([#1519](https://github.com/vector-im/element-x-android/issues/1519))
- - Fix issue where text is cleared when cancelling a reply ([#1617](https://github.com/vector-im/element-x-android/issues/1617))
+ - Group fallback notification to avoid having plenty of them displayed. ([#994](https://github.com/element-hq/element-x-android/issues/994))
+ - Hide keyboard when exiting the chat room screen. ([#1375](https://github.com/element-hq/element-x-android/issues/1375))
+ - Always register the pusher when application starts ([#1481](https://github.com/element-hq/element-x-android/issues/1481))
+ - Ensure screen does not turn off when playing a video ([#1519](https://github.com/element-hq/element-x-android/issues/1519))
+ - Fix issue where text is cleared when cancelling a reply ([#1617](https://github.com/element-hq/element-x-android/issues/1617))
Other changes
-------------
- - Remove usage of blocking methods. ([#1563](https://github.com/vector-im/element-x-android/issues/1563))
+ - Remove usage of blocking methods. ([#1563](https://github.com/element-hq/element-x-android/issues/1563))
Changes in Element X v0.2.4 (2023-10-12)
@@ -70,20 +70,20 @@ Changes in Element X v0.2.4 (2023-10-12)
Features ✨
----------
- - [Rich text editor] Add full screen mode ([#1447](https://github.com/vector-im/element-x-android/issues/1447))
- - Improve rendering of m.emote. ([#1497](https://github.com/vector-im/element-x-android/issues/1497))
- - Improve deleted session behavior. ([#1520](https://github.com/vector-im/element-x-android/issues/1520))
+ - [Rich text editor] Add full screen mode ([#1447](https://github.com/element-hq/element-x-android/issues/1447))
+ - Improve rendering of m.emote. ([#1497](https://github.com/element-hq/element-x-android/issues/1497))
+ - Improve deleted session behavior. ([#1520](https://github.com/element-hq/element-x-android/issues/1520))
Bugfixes 🐛
----------
- - WebP images can't be sent as media. ([#1483](https://github.com/vector-im/element-x-android/issues/1483))
- - Fix back button not working in bottom sheets. ([#1517](https://github.com/vector-im/element-x-android/issues/1517))
- - Render body of unknown msgtype in the timeline and in the room list ([#1539](https://github.com/vector-im/element-x-android/issues/1539))
+ - WebP images can't be sent as media. ([#1483](https://github.com/element-hq/element-x-android/issues/1483))
+ - Fix back button not working in bottom sheets. ([#1517](https://github.com/element-hq/element-x-android/issues/1517))
+ - Render body of unknown msgtype in the timeline and in the room list ([#1539](https://github.com/element-hq/element-x-android/issues/1539))
Other changes
-------------
- - Room : makes subscribeToSync/unsubscribeFromSync suspendable. ([#1457](https://github.com/vector-im/element-x-android/issues/1457))
- - Add some Konsist tests. ([#1526](https://github.com/vector-im/element-x-android/issues/1526))
+ - Room : makes subscribeToSync/unsubscribeFromSync suspendable. ([#1457](https://github.com/element-hq/element-x-android/issues/1457))
+ - Add some Konsist tests. ([#1526](https://github.com/element-hq/element-x-android/issues/1526))
Changes in Element X v0.2.3 (2023-09-27)
@@ -91,12 +91,12 @@ Changes in Element X v0.2.3 (2023-09-27)
Features ✨
----------
- - Handle installation of Apks from the media viewer. ([#1432](https://github.com/vector-im/element-x-android/pull/1432))
- - Integrate SDK 0.1.58 ([#1437](https://github.com/vector-im/element-x-android/pull/1437))
+ - Handle installation of Apks from the media viewer. ([#1432](https://github.com/element-hq/element-x-android/pull/1432))
+ - Integrate SDK 0.1.58 ([#1437](https://github.com/element-hq/element-x-android/pull/1437))
Other changes
-------------
- - Element call: add custom parameters to Element Call urls. ([#1434](https://github.com/vector-im/element-x-android/issues/1434))
+ - Element call: add custom parameters to Element Call urls. ([#1434](https://github.com/element-hq/element-x-android/issues/1434))
Changes in Element X v0.2.2 (2023-09-21)
@@ -104,8 +104,8 @@ Changes in Element X v0.2.2 (2023-09-21)
Bugfixes 🐛
----------
- - Add animation when rendering the timeline to avoid glitches. ([#1323](https://github.com/vector-im/element-x-android/issues/1323))
- - Fix crash when trying to take a photo or record a video. ([#1395](https://github.com/vector-im/element-x-android/issues/1395))
+ - Add animation when rendering the timeline to avoid glitches. ([#1323](https://github.com/element-hq/element-x-android/issues/1323))
+ - Fix crash when trying to take a photo or record a video. ([#1395](https://github.com/element-hq/element-x-android/issues/1395))
Changes in Element X v0.2.1 (2023-09-20)
@@ -114,18 +114,18 @@ Changes in Element X v0.2.1 (2023-09-20)
Features ✨
----------
- Bump Rust SDK to `v0.1.56`
- - [Rich text editor] Add link support to rich text editor ([#1309](https://github.com/vector-im/element-x-android/issues/1309))
- - Let the SDK figure the best scheme given an homeserver URL (thus allowing HTTP homeservers) ([#1382](https://github.com/vector-im/element-x-android/issues/1382))
+ - [Rich text editor] Add link support to rich text editor ([#1309](https://github.com/element-hq/element-x-android/issues/1309))
+ - Let the SDK figure the best scheme given an homeserver URL (thus allowing HTTP homeservers) ([#1382](https://github.com/element-hq/element-x-android/issues/1382))
Bugfixes 🐛
----------
- - Fix ANR on RoomList when notification settings change. ([#1370](https://github.com/vector-im/element-x-android/issues/1370))
+ - Fix ANR on RoomList when notification settings change. ([#1370](https://github.com/element-hq/element-x-android/issues/1370))
Other changes
-------------
- - Element Call: support scheme `io.element.call` ([#1377](https://github.com/vector-im/element-x-android/issues/1377))
- - [DI] Rework how dagger components are created and provided. ([#1378](https://github.com/vector-im/element-x-android/issues/1378))
- - Remove usage of async-uniffi as it leads to a deadlocks and memory leaks. ([#1381](https://github.com/vector-im/element-x-android/issues/1381))
+ - Element Call: support scheme `io.element.call` ([#1377](https://github.com/element-hq/element-x-android/issues/1377))
+ - [DI] Rework how dagger components are created and provided. ([#1378](https://github.com/element-hq/element-x-android/issues/1378))
+ - Remove usage of async-uniffi as it leads to a deadlocks and memory leaks. ([#1381](https://github.com/element-hq/element-x-android/issues/1381))
Changes in Element X v0.2.0 (2023-09-18)
@@ -134,37 +134,37 @@ Changes in Element X v0.2.0 (2023-09-18)
Features ✨
----------
- Bump Rust SDK to `v0.1.54`
- - Add a "Mute" shortcut icon and a "Notifications" section in the room details screen ([#506](https://github.com/vector-im/element-x-android/issues/506))
- - Add a notification permission screen to the initial flow. ([#897](https://github.com/vector-im/element-x-android/issues/897))
- - Integrate Element Call into EX by embedding a call in a WebView. ([#1300](https://github.com/vector-im/element-x-android/issues/1300))
- - Implement Bloom effect modifier. ([#1217](https://github.com/vector-im/element-x-android/issues/1217))
- - Set color on display name and default avatar in the timeline. ([#1224](https://github.com/vector-im/element-x-android/issues/1224))
- - Display a thread decorator in timeline so we know when a message is coming from a thread. ([#1236](https://github.com/vector-im/element-x-android/issues/1236))
- - [Rich text editor] Integrate rich text editor library. Note that markdown is now not supported and further formatting support will be introduced through the rich text editor. ([#1172](https://github.com/vector-im/element-x-android/issues/1172))
- - [Rich text editor] Add formatting menu (accessible via the '+' button) ([#1261](https://github.com/vector-im/element-x-android/issues/1261))
- - [Rich text editor] Add feature flag for rich text editor. Markdown support can now be enabled by disabling the rich text editor. ([#1289](https://github.com/vector-im/element-x-android/issues/1289))
- - [Rich text editor] Update design ([#1332](https://github.com/vector-im/element-x-android/issues/1332))
+ - Add a "Mute" shortcut icon and a "Notifications" section in the room details screen ([#506](https://github.com/element-hq/element-x-android/issues/506))
+ - Add a notification permission screen to the initial flow. ([#897](https://github.com/element-hq/element-x-android/issues/897))
+ - Integrate Element Call into EX by embedding a call in a WebView. ([#1300](https://github.com/element-hq/element-x-android/issues/1300))
+ - Implement Bloom effect modifier. ([#1217](https://github.com/element-hq/element-x-android/issues/1217))
+ - Set color on display name and default avatar in the timeline. ([#1224](https://github.com/element-hq/element-x-android/issues/1224))
+ - Display a thread decorator in timeline so we know when a message is coming from a thread. ([#1236](https://github.com/element-hq/element-x-android/issues/1236))
+ - [Rich text editor] Integrate rich text editor library. Note that markdown is now not supported and further formatting support will be introduced through the rich text editor. ([#1172](https://github.com/element-hq/element-x-android/issues/1172))
+ - [Rich text editor] Add formatting menu (accessible via the '+' button) ([#1261](https://github.com/element-hq/element-x-android/issues/1261))
+ - [Rich text editor] Add feature flag for rich text editor. Markdown support can now be enabled by disabling the rich text editor. ([#1289](https://github.com/element-hq/element-x-android/issues/1289))
+ - [Rich text editor] Update design ([#1332](https://github.com/element-hq/element-x-android/issues/1332))
Bugfixes 🐛
----------
- - Make links in room topic clickable ([#612](https://github.com/vector-im/element-x-android/issues/612))
- - Reply action: harmonize conditions in bottom sheet and swipe to reply. ([#1173](https://github.com/vector-im/element-x-android/issues/1173))
- - Fix system bar color after login on light theme. ([#1222](https://github.com/vector-im/element-x-android/issues/1222))
- - Fix long click on simple formatted messages ([#1232](https://github.com/vector-im/element-x-android/issues/1232))
- - Enable polls in release build. ([#1241](https://github.com/vector-im/element-x-android/issues/1241))
- - Fix top padding in room list when app is opened in offline mode. ([#1297](https://github.com/vector-im/element-x-android/issues/1297))
- - [Rich text editor] Fix 'text formatting' option only partially visible ([#1335](https://github.com/vector-im/element-x-android/issues/1335))
- - [Rich text editor] Ensure keyboard opens for reply and text formatting modes ([#1337](https://github.com/vector-im/element-x-android/issues/1337))
- - [Rich text editor] Fix placeholder spilling onto multiple lines ([#1347](https://github.com/vector-im/element-x-android/issues/1347))
+ - Make links in room topic clickable ([#612](https://github.com/element-hq/element-x-android/issues/612))
+ - Reply action: harmonize conditions in bottom sheet and swipe to reply. ([#1173](https://github.com/element-hq/element-x-android/issues/1173))
+ - Fix system bar color after login on light theme. ([#1222](https://github.com/element-hq/element-x-android/issues/1222))
+ - Fix long click on simple formatted messages ([#1232](https://github.com/element-hq/element-x-android/issues/1232))
+ - Enable polls in release build. ([#1241](https://github.com/element-hq/element-x-android/issues/1241))
+ - Fix top padding in room list when app is opened in offline mode. ([#1297](https://github.com/element-hq/element-x-android/issues/1297))
+ - [Rich text editor] Fix 'text formatting' option only partially visible ([#1335](https://github.com/element-hq/element-x-android/issues/1335))
+ - [Rich text editor] Ensure keyboard opens for reply and text formatting modes ([#1337](https://github.com/element-hq/element-x-android/issues/1337))
+ - [Rich text editor] Fix placeholder spilling onto multiple lines ([#1347](https://github.com/element-hq/element-x-android/issues/1347))
Other changes
-------------
- - Add a sub-screen "Notifications" in the existing application Settings ([#510](https://github.com/vector-im/element-x-android/issues/510))
- - Exclude some groups related to analytics to be included. ([#1191](https://github.com/vector-im/element-x-android/issues/1191))
- - Use the new SyncIndicator API. ([#1244](https://github.com/vector-im/element-x-android/issues/1244))
- - Improve RoomSummary mapping by using RoomInfo. ([#1251](https://github.com/vector-im/element-x-android/issues/1251))
- - Ensure Posthog data are sent to "https://posthog.element.io" ([#1269](https://github.com/vector-im/element-x-android/issues/1269))
- - New app icon, with monochrome support. ([#1363](https://github.com/vector-im/element-x-android/issues/1363))
+ - Add a sub-screen "Notifications" in the existing application Settings ([#510](https://github.com/element-hq/element-x-android/issues/510))
+ - Exclude some groups related to analytics to be included. ([#1191](https://github.com/element-hq/element-x-android/issues/1191))
+ - Use the new SyncIndicator API. ([#1244](https://github.com/element-hq/element-x-android/issues/1244))
+ - Improve RoomSummary mapping by using RoomInfo. ([#1251](https://github.com/element-hq/element-x-android/issues/1251))
+ - Ensure Posthog data are sent to "https://posthog.element.io" ([#1269](https://github.com/element-hq/element-x-android/issues/1269))
+ - New app icon, with monochrome support. ([#1363](https://github.com/element-hq/element-x-android/issues/1363))
Changes in Element X v0.1.6 (2023-09-04)
@@ -172,22 +172,22 @@ Changes in Element X v0.1.6 (2023-09-04)
Features ✨
----------
- - Enable the Polls feature. Allows to create, view, vote and end polls. ([#1196](https://github.com/vector-im/element-x-android/issues/1196))
-- Create poll. ([#1143](https://github.com/vector-im/element-x-android/issues/1143))
+ - Enable the Polls feature. Allows to create, view, vote and end polls. ([#1196](https://github.com/element-hq/element-x-android/issues/1196))
+- Create poll. ([#1143](https://github.com/element-hq/element-x-android/issues/1143))
Bugfixes 🐛
----------
-- Ensure notification for Event from encrypted room get decrypted content. ([#1178](https://github.com/vector-im/element-x-android/issues/1178))
- - Make sure Snackbars are only displayed once. ([#928](https://github.com/vector-im/element-x-android/issues/928))
- - Fix the orientation of sent images. ([#1135](https://github.com/vector-im/element-x-android/issues/1135))
- - Bug reporter crashes when 'send logs' is disabled. ([#1168](https://github.com/vector-im/element-x-android/issues/1168))
- - Add missing link to the terms on the analytics setting screen. ([#1177](https://github.com/vector-im/element-x-android/issues/1177))
- - Re-enable `SyncService.withEncryptionSync` to improve decryption of notifications. ([#1198](https://github.com/vector-im/element-x-android/issues/1198))
- - Crash with `aspectRatio` modifier when `Float.NaN` was used as input. ([#1995](https://github.com/vector-im/element-x-android/issues/1995))
+- Ensure notification for Event from encrypted room get decrypted content. ([#1178](https://github.com/element-hq/element-x-android/issues/1178))
+ - Make sure Snackbars are only displayed once. ([#928](https://github.com/element-hq/element-x-android/issues/928))
+ - Fix the orientation of sent images. ([#1135](https://github.com/element-hq/element-x-android/issues/1135))
+ - Bug reporter crashes when 'send logs' is disabled. ([#1168](https://github.com/element-hq/element-x-android/issues/1168))
+ - Add missing link to the terms on the analytics setting screen. ([#1177](https://github.com/element-hq/element-x-android/issues/1177))
+ - Re-enable `SyncService.withEncryptionSync` to improve decryption of notifications. ([#1198](https://github.com/element-hq/element-x-android/issues/1198))
+ - Crash with `aspectRatio` modifier when `Float.NaN` was used as input. ([#1995](https://github.com/element-hq/element-x-android/issues/1995))
Other changes
-------------
- - Remove unnecessary year in copyright mention. ([#1187](https://github.com/vector-im/element-x-android/issues/1187))
+ - Remove unnecessary year in copyright mention. ([#1187](https://github.com/element-hq/element-x-android/issues/1187))
Changes in Element X v0.1.5 (2023-08-28)
@@ -195,7 +195,7 @@ Changes in Element X v0.1.5 (2023-08-28)
Bugfixes 🐛
----------
- - Fix crash when opening any room. ([#1160](https://github.com/vector-im/element-x-android/issues/1160))
+ - Fix crash when opening any room. ([#1160](https://github.com/element-hq/element-x-android/issues/1160))
Changes in Element X v0.1.4 (2023-08-28)
@@ -203,32 +203,32 @@ Changes in Element X v0.1.4 (2023-08-28)
Features ✨
----------
- - Allow cancelling media upload ([#769](https://github.com/vector-im/element-x-android/issues/769))
- - Enable OIDC support. ([#1127](https://github.com/vector-im/element-x-android/issues/1127))
- - Add a "Setting up account" screen, displayed the first time the user logs in to the app (per account). ([#1149](https://github.com/vector-im/element-x-android/issues/1149))
+ - Allow cancelling media upload ([#769](https://github.com/element-hq/element-x-android/issues/769))
+ - Enable OIDC support. ([#1127](https://github.com/element-hq/element-x-android/issues/1127))
+ - Add a "Setting up account" screen, displayed the first time the user logs in to the app (per account). ([#1149](https://github.com/element-hq/element-x-android/issues/1149))
Bugfixes 🐛
----------
- - Videos sent from the app were cropped in some cases. ([#862](https://github.com/vector-im/element-x-android/issues/862))
- - Timeline: sender names are now displayed in one single line. ([#1033](https://github.com/vector-im/element-x-android/issues/1033))
- - Fix `TextButtons` being displayed in black. ([#1077](https://github.com/vector-im/element-x-android/issues/1077))
- - Linkify links in HTML contents. ([#1079](https://github.com/vector-im/element-x-android/issues/1079))
- - Fix bug reporter failing after not finding some log files. ([#1082](https://github.com/vector-im/element-x-android/issues/1082))
- - Fix rendering of inline elements in list items. ([#1090](https://github.com/vector-im/element-x-android/issues/1090))
- - Fix crash RuntimeException "No matching key found for the ciphertext in the stream" ([#1101](https://github.com/vector-im/element-x-android/issues/1101))
- - Make links in messages clickable again. ([#1111](https://github.com/vector-im/element-x-android/issues/1111))
- - When event has no id, just cancel parsing the latest room message for a room. ([#1125](https://github.com/vector-im/element-x-android/issues/1125))
- - Only display verification prompt after initial sync is done. ([#1131](https://github.com/vector-im/element-x-android/issues/1131))
+ - Videos sent from the app were cropped in some cases. ([#862](https://github.com/element-hq/element-x-android/issues/862))
+ - Timeline: sender names are now displayed in one single line. ([#1033](https://github.com/element-hq/element-x-android/issues/1033))
+ - Fix `TextButtons` being displayed in black. ([#1077](https://github.com/element-hq/element-x-android/issues/1077))
+ - Linkify links in HTML contents. ([#1079](https://github.com/element-hq/element-x-android/issues/1079))
+ - Fix bug reporter failing after not finding some log files. ([#1082](https://github.com/element-hq/element-x-android/issues/1082))
+ - Fix rendering of inline elements in list items. ([#1090](https://github.com/element-hq/element-x-android/issues/1090))
+ - Fix crash RuntimeException "No matching key found for the ciphertext in the stream" ([#1101](https://github.com/element-hq/element-x-android/issues/1101))
+ - Make links in messages clickable again. ([#1111](https://github.com/element-hq/element-x-android/issues/1111))
+ - When event has no id, just cancel parsing the latest room message for a room. ([#1125](https://github.com/element-hq/element-x-android/issues/1125))
+ - Only display verification prompt after initial sync is done. ([#1131](https://github.com/element-hq/element-x-android/issues/1131))
In development 🚧
----------------
- - [Poll] Add feature flag in developer options ([#1064](https://github.com/vector-im/element-x-android/issues/1064))
- - [Polls] Improve UI and render ended state ([#1113](https://github.com/vector-im/element-x-android/issues/1113))
+ - [Poll] Add feature flag in developer options ([#1064](https://github.com/element-hq/element-x-android/issues/1064))
+ - [Polls] Improve UI and render ended state ([#1113](https://github.com/element-hq/element-x-android/issues/1113))
Other changes
-------------
- - Compound: add `ListItem` and `ListSectionHeader` components. ([#990](https://github.com/vector-im/element-x-android/issues/990))
- - Migrate `object` to `data object` in sealed interface / class #1135 ([#1135](https://github.com/vector-im/element-x-android/issues/1135))
+ - Compound: add `ListItem` and `ListSectionHeader` components. ([#990](https://github.com/element-hq/element-x-android/issues/990))
+ - Migrate `object` to `data object` in sealed interface / class #1135 ([#1135](https://github.com/element-hq/element-x-android/issues/1135))
Changes in Element X v0.1.2 (2023-08-16)
@@ -236,20 +236,20 @@ 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))
+ - Filter push notifications using push rules. ([#640](https://github.com/element-hq/element-x-android/issues/640))
+ - Use `for` instead of `forEach` in `DefaultDiffCacheInvalidator` to improve performance. ([#1035](https://github.com/element-hq/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))
+ - [Poll] Render start event in the timeline ([#1031](https://github.com/element-hq/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))
+ - Add Button component based on Compound designs ([#1021](https://github.com/element-hq/element-x-android/issues/1021))
+ - Compound: implement dialogs. ([#1043](https://github.com/element-hq/element-x-android/issues/1043))
+ - Compound: customise `IconButton` component. ([#1049](https://github.com/element-hq/element-x-android/issues/1049))
+ - Compound: implement `DropdownMenu` customisations. ([#1050](https://github.com/element-hq/element-x-android/issues/1050))
+ - Compound: implement Snackbar component. ([#1054](https://github.com/element-hq/element-x-android/issues/1054))
Changes in Element X v0.1.0 (2023-07-19)
diff --git a/CODEOWNERS b/CODEOWNERS
index 9db04197d5..40e24168c6 100644
--- a/CODEOWNERS
+++ b/CODEOWNERS
@@ -1 +1 @@
-* @vector-im/element-x-android-reviewers
+* @element-hq/element-x-android-reviewers
diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md
index 3a729e7992..5cf10c0fdf 100644
--- a/CONTRIBUTING.md
+++ b/CONTRIBUTING.md
@@ -187,7 +187,7 @@ internal fun PinIconPreview() = ElementPreview {
}
```
-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.
+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/element-hq/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 2a0d352187..477943aff7 100644
--- a/README.md
+++ b/README.md
@@ -1,4 +1,4 @@
-[](https://github.com/vector-im/element-x-android/actions/workflows/build.yml?query=branch%3Adevelop)
+[](https://github.com/element-hq/element-x-android/actions/workflows/build.yml?query=branch%3Adevelop)
[](https://sonarcloud.io/summary/new_code?id=vector-im_element-x-android)
[](https://sonarcloud.io/summary/new_code?id=vector-im_element-x-android)
[](https://sonarcloud.io/summary/new_code?id=vector-im_element-x-android)
@@ -10,7 +10,7 @@
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](https://developer.android.com/jetpack/compose), and the navigation is managed using [Appyx](https://github.com/bumble-tech/appyx).
+The application is a total rewrite of [Element-Android](https://github.com/element-hq/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/).
@@ -58,11 +58,11 @@ We're doing this as a way to share code between platforms and while we've seen p
## Status
-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).
+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/element-hq/element-x-android/issues/911).
## Contributing
-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.
+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/element-hq/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.
But first make sure to read our [contribution guide](CONTRIBUTING.md) first.
@@ -75,7 +75,7 @@ Makes sure to select the `app` configuration when building (as we also have samp
## Support
-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)
+When you are experiencing an issue on Element X Android, please first search in [GitHub issues](https://github.com/element-hq/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.
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
index 853412e403..8dc0bf0e0e 100644
--- a/app/src/main/kotlin/io/element/android/x/initializer/TracingInitializer.kt
+++ b/app/src/main/kotlin/io/element/android/x/initializer/TracingInitializer.kt
@@ -57,6 +57,7 @@ class TracingInitializer : Initializer {
)
}
bugReporter.cleanLogDirectoryIfNeeded()
+ bugReporter.setCurrentTracingFilter(tracingConfiguration.filterConfiguration.filter)
tracingService.setupTracing(tracingConfiguration)
// Also set env variable for rust back trace
Os.setenv("RUST_BACKTRACE", "1", true)
diff --git a/appnav/src/main/kotlin/io/element/android/appnav/LoggedInAppScopeFlowNode.kt b/appnav/src/main/kotlin/io/element/android/appnav/LoggedInAppScopeFlowNode.kt
index 7f36a7a51a..423228c110 100644
--- a/appnav/src/main/kotlin/io/element/android/appnav/LoggedInAppScopeFlowNode.kt
+++ b/appnav/src/main/kotlin/io/element/android/appnav/LoggedInAppScopeFlowNode.kt
@@ -33,13 +33,12 @@ import dagger.assisted.AssistedInject
import io.element.android.anvilannotations.ContributesNode
import io.element.android.appnav.di.SessionComponentFactory
import io.element.android.libraries.architecture.NodeInputs
-import io.element.android.libraries.architecture.bindings
import io.element.android.libraries.architecture.createNode
import io.element.android.libraries.architecture.inputs
import io.element.android.libraries.di.AppScope
import io.element.android.libraries.di.DaggerComponentOwner
import io.element.android.libraries.matrix.api.MatrixClient
-import io.element.android.libraries.matrix.ui.di.MatrixUIBindings
+import io.element.android.libraries.matrix.ui.media.ImageLoaderHolder
import kotlinx.parcelize.Parcelize
/**
@@ -52,6 +51,7 @@ class LoggedInAppScopeFlowNode @AssistedInject constructor(
@Assisted buildContext: BuildContext,
@Assisted plugins: List,
sessionComponentFactory: SessionComponentFactory,
+ private val imageLoaderHolder: ImageLoaderHolder,
) : ParentNode(
navModel = PermanentNavModel(
navTargets = setOf(NavTarget),
@@ -78,8 +78,7 @@ class LoggedInAppScopeFlowNode @AssistedInject constructor(
super.onBuilt()
lifecycle.subscribe(
onCreate = {
- val imageLoaderFactory = bindings().loggedInImageLoaderFactory()
- Coil.setImageLoader(imageLoaderFactory)
+ Coil.setImageLoader(imageLoaderHolder.get(inputs.matrixClient))
},
)
}
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 23c35b119a..80c1a06737 100644
--- a/appnav/src/main/kotlin/io/element/android/appnav/LoggedInFlowNode.kt
+++ b/appnav/src/main/kotlin/io/element/android/appnav/LoggedInFlowNode.kt
@@ -256,6 +256,10 @@ class LoggedInFlowNode @AssistedInject constructor(
}
is NavTarget.Room -> {
val callback = object : RoomLoadedFlowNode.Callback {
+ override fun onOpenRoom(roomId: RoomId) {
+ backstack.push(NavTarget.Room(roomId))
+ }
+
override fun onForwardedToSingleRoom(roomId: RoomId) {
coroutineScope.launch { attachRoom(roomId) }
}
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 b567395c1e..96febc3751 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
@@ -34,6 +34,8 @@ class IntentResolver @Inject constructor(
private val oidcIntentResolver: OidcIntentResolver
) {
fun resolve(intent: Intent): ResolvedIntent? {
+ if (intent.canBeIgnored()) return null
+
val deepLinkData = deeplinkParser.getFromIntent(intent)
if (deepLinkData != null) return ResolvedIntent.Navigation(deepLinkData)
@@ -45,3 +47,8 @@ class IntentResolver @Inject constructor(
return null
}
}
+
+private fun Intent.canBeIgnored(): Boolean {
+ return action == Intent.ACTION_MAIN &&
+ categories?.contains(Intent.CATEGORY_LAUNCHER) == true
+}
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 613ed650c8..3cc405d7fd 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
@@ -74,6 +74,7 @@ class RoomLoadedFlowNode @AssistedInject constructor(
), DaggerComponentOwner {
interface Callback : Plugin {
+ fun onOpenRoom(roomId: RoomId)
fun onForwardedToSingleRoom(roomId: RoomId)
fun onOpenGlobalNotificationSettings()
}
@@ -134,6 +135,10 @@ class RoomLoadedFlowNode @AssistedInject constructor(
override fun onOpenGlobalNotificationSettings() {
callbacks.forEach { it.onOpenGlobalNotificationSettings() }
}
+
+ override fun onOpenRoom(roomId: RoomId) {
+ callbacks.forEach { it.onOpenRoom(roomId) }
+ }
}
return roomDetailsEntryPoint.nodeBuilder(this, buildContext)
.params(RoomDetailsEntryPoint.Params(initialTarget))
diff --git a/appnav/src/test/kotlin/io/element/android/appnav/RoomFlowNodeTest.kt b/appnav/src/test/kotlin/io/element/android/appnav/RoomFlowNodeTest.kt
index fd5de85b1d..09ca595080 100644
--- a/appnav/src/test/kotlin/io/element/android/appnav/RoomFlowNodeTest.kt
+++ b/appnav/src/test/kotlin/io/element/android/appnav/RoomFlowNodeTest.kt
@@ -25,7 +25,7 @@ import com.bumble.appyx.core.plugin.Plugin
import com.bumble.appyx.navmodel.backstack.activeElement
import com.bumble.appyx.testing.junit4.util.MainDispatcherRule
import com.bumble.appyx.testing.unit.common.helper.parentNodeTestHelper
-import com.google.common.truth.Truth
+import com.google.common.truth.Truth.assertThat
import io.element.android.appnav.di.RoomComponentFactory
import io.element.android.appnav.room.RoomLoadedFlowNode
import io.element.android.features.messages.api.MessagesEntryPoint
@@ -83,7 +83,7 @@ class RoomFlowNodeTest {
}
override fun build(): Node {
- return node(buildContext) {}.also {
+ return node(buildContext) {}.also {
nodeId = it.id
}
}
@@ -122,10 +122,10 @@ class RoomFlowNodeTest {
val roomFlowNodeTestHelper = roomFlowNode.parentNodeTestHelper()
// THEN
- Truth.assertThat(roomFlowNode.backstack.activeElement).isEqualTo(RoomLoadedFlowNode.NavTarget.Messages)
+ assertThat(roomFlowNode.backstack.activeElement).isEqualTo(RoomLoadedFlowNode.NavTarget.Messages)
roomFlowNodeTestHelper.assertChildHasLifecycle(RoomLoadedFlowNode.NavTarget.Messages, Lifecycle.State.CREATED)
val messagesNode = roomFlowNode.childNode(RoomLoadedFlowNode.NavTarget.Messages)!!
- Truth.assertThat(messagesNode.id).isEqualTo(fakeMessagesEntryPoint.nodeId)
+ assertThat(messagesNode.id).isEqualTo(fakeMessagesEntryPoint.nodeId)
}
@Test
@@ -147,6 +147,6 @@ class RoomFlowNodeTest {
// THEN
roomFlowNodeTestHelper.assertChildHasLifecycle(RoomLoadedFlowNode.NavTarget.RoomDetails, Lifecycle.State.CREATED)
val roomDetailsNode = roomFlowNode.childNode(RoomLoadedFlowNode.NavTarget.RoomDetails)!!
- Truth.assertThat(roomDetailsNode.id).isEqualTo(fakeRoomDetailsEntryPoint.nodeId)
+ assertThat(roomDetailsNode.id).isEqualTo(fakeRoomDetailsEntryPoint.nodeId)
}
}
diff --git a/appnav/src/test/kotlin/io/element/android/appnav/intent/IntentResolverTest.kt b/appnav/src/test/kotlin/io/element/android/appnav/intent/IntentResolverTest.kt
index c2a4bcbd3a..3ad11787df 100644
--- a/appnav/src/test/kotlin/io/element/android/appnav/intent/IntentResolverTest.kt
+++ b/appnav/src/test/kotlin/io/element/android/appnav/intent/IntentResolverTest.kt
@@ -37,6 +37,17 @@ import org.robolectric.RuntimeEnvironment
@RunWith(RobolectricTestRunner::class)
class IntentResolverTest {
+ @Test
+ fun `resolve launcher intent should return null`() {
+ val sut = createIntentResolver()
+ val intent = Intent(RuntimeEnvironment.getApplication(), Activity::class.java).apply {
+ action = Intent.ACTION_MAIN
+ addCategory(Intent.CATEGORY_LAUNCHER)
+ }
+ val result = sut.resolve(intent)
+ assertThat(result).isNull()
+ }
+
@Test
fun `test resolve navigation intent root`() {
val sut = createIntentResolver()
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 f56367e5f8..6997f07233 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
@@ -17,7 +17,7 @@
package io.element.android.appnav.room
import app.cash.turbine.test
-import com.google.common.truth.Truth
+import com.google.common.truth.Truth.assertThat
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
@@ -39,8 +39,8 @@ class LoadingRoomStateFlowFactoryTest {
flowFactory
.create(this, A_ROOM_ID)
.test {
- Truth.assertThat(awaitItem()).isEqualTo(LoadingRoomState.Loading)
- Truth.assertThat(awaitItem()).isEqualTo(LoadingRoomState.Loaded(room))
+ assertThat(awaitItem()).isEqualTo(LoadingRoomState.Loading)
+ assertThat(awaitItem()).isEqualTo(LoadingRoomState.Loaded(room))
}
}
@@ -53,10 +53,10 @@ class LoadingRoomStateFlowFactoryTest {
flowFactory
.create(this, A_ROOM_ID)
.test {
- Truth.assertThat(awaitItem()).isEqualTo(LoadingRoomState.Loading)
+ assertThat(awaitItem()).isEqualTo(LoadingRoomState.Loading)
matrixClient.givenGetRoomResult(A_ROOM_ID, room)
roomListService.postAllRoomsLoadingState(RoomList.LoadingState.Loaded(1))
- Truth.assertThat(awaitItem()).isEqualTo(LoadingRoomState.Loaded(room))
+ assertThat(awaitItem()).isEqualTo(LoadingRoomState.Loaded(room))
}
}
@@ -68,12 +68,9 @@ class LoadingRoomStateFlowFactoryTest {
flowFactory
.create(this, A_ROOM_ID)
.test {
- Truth.assertThat(awaitItem()).isEqualTo(LoadingRoomState.Loading)
+ assertThat(awaitItem()).isEqualTo(LoadingRoomState.Loading)
roomListService.postAllRoomsLoadingState(RoomList.LoadingState.Loaded(1))
- Truth.assertThat(awaitItem()).isEqualTo(LoadingRoomState.Error)
+ assertThat(awaitItem()).isEqualTo(LoadingRoomState.Error)
}
}
-
-
-
}
diff --git a/build.gradle.kts b/build.gradle.kts
index 7d06c2bf18..20bd2e9066 100644
--- a/build.gradle.kts
+++ b/build.gradle.kts
@@ -62,7 +62,7 @@ allprojects {
config.from(files("$rootDir/tools/detekt/detekt.yml"))
}
dependencies {
- detektPlugins("io.nlopez.compose.rules:detekt:0.3.3")
+ detektPlugins("io.nlopez.compose.rules:detekt:0.3.5")
}
// KtLint
@@ -130,10 +130,10 @@ sonar {
property("sonar.host.url", "https://sonarcloud.io")
property("sonar.projectVersion", "1.0") // TODO project(":app").android.defaultConfig.versionName)
property("sonar.sourceEncoding", "UTF-8")
- property("sonar.links.homepage", "https://github.com/vector-im/element-x-android/")
- property("sonar.links.ci", "https://github.com/vector-im/element-x-android/actions")
- property("sonar.links.scm", "https://github.com/vector-im/element-x-android/")
- property("sonar.links.issue", "https://github.com/vector-im/element-x-android/issues")
+ property("sonar.links.homepage", "https://github.com/element-hq/element-x-android/")
+ property("sonar.links.ci", "https://github.com/element-hq/element-x-android/actions")
+ property("sonar.links.scm", "https://github.com/element-hq/element-x-android/")
+ property("sonar.links.issue", "https://github.com/element-hq/element-x-android/issues")
property("sonar.organization", "new_vector_ltd_organization")
property("sonar.login", if (project.hasProperty("SONAR_LOGIN")) project.property("SONAR_LOGIN")!! else "invalid")
diff --git a/changelog.d/1833.misc b/changelog.d/1833.misc
index a51a287765..ccb00c2c45 100644
--- a/changelog.d/1833.misc
+++ b/changelog.d/1833.misc
@@ -1 +1 @@
-Remove `:libraries:theme` module, extract theme and tokens to [Compound Android](https://github.com/vector-im/compound-android).
+Remove `:libraries:theme` module, extract theme and tokens to [Compound Android](https://github.com/element-hq/compound-android).
diff --git a/changelog.d/1944.misc b/changelog.d/1944.misc
new file mode 100644
index 0000000000..79e271fa8b
--- /dev/null
+++ b/changelog.d/1944.misc
@@ -0,0 +1 @@
+Add toggle in the notification settings to disable notifications for room invites.
diff --git a/changelog.d/1950.bugfix b/changelog.d/1950.bugfix
new file mode 100644
index 0000000000..2253ca74b8
--- /dev/null
+++ b/changelog.d/1950.bugfix
@@ -0,0 +1 @@
+Fix rendering of user name with vertical text by clipping the text.
diff --git a/changelog.d/1965.misc b/changelog.d/1965.misc
new file mode 100644
index 0000000000..49132f82ce
--- /dev/null
+++ b/changelog.d/1965.misc
@@ -0,0 +1 @@
+Update rendering of Emojis displayed during verification.
diff --git a/changelog.d/1979.misc b/changelog.d/1979.misc
new file mode 100644
index 0000000000..623a422481
--- /dev/null
+++ b/changelog.d/1979.misc
@@ -0,0 +1 @@
+Hide sender info in direct rooms
diff --git a/changelog.d/1991.bugfix b/changelog.d/1991.bugfix
new file mode 100644
index 0000000000..e1dfcdcb2a
--- /dev/null
+++ b/changelog.d/1991.bugfix
@@ -0,0 +1 @@
+Fix avatar not displayed in notification when the app is not in background
diff --git a/changelog.d/1991.misc b/changelog.d/1991.misc
new file mode 100644
index 0000000000..05a0367bed
--- /dev/null
+++ b/changelog.d/1991.misc
@@ -0,0 +1 @@
+Render images in Notification
diff --git a/docs/_developer_onboarding.md b/docs/_developer_onboarding.md
index a100a2beba..b4ea411710 100644
--- a/docs/_developer_onboarding.md
+++ b/docs/_developer_onboarding.md
@@ -117,7 +117,7 @@ You can also have access to the aars through the [release](https://github.com/ma
#### Build the SDK locally
-Easiest way: run the script [./tools/sdk/build_rust_sdk.sh](./tools/sdk/build_rust_sdk.sh) and just answer the questions.
+Easiest way: run the script [../tools/sdk/build_rust_sdk.sh](../tools/sdk/build_rust_sdk.sh) and just answer the questions.
Legacy way:
@@ -322,7 +322,7 @@ We are using [Gradle version catalog](https://docs.gradle.org/current/userguide/
All the dependencies (including android artifact, gradle plugin, etc.) should be declared in [../gradle/libs.versions.toml](libs.versions.toml) file.
Some dependency, mainly because they are not shared can be declared in `build.gradle.kts` files.
-[Renovate](https://github.com/apps/renovate) is set up on the project. This tool will automatically create Pull Request to upgrade our dependencies one by one. A [dependency dashboard issue](https://github.com/vector-im/element-x-android/issues/150) is maintained by the tool and allow to perform some actions.
+[Renovate](https://github.com/apps/renovate) is set up on the project. This tool will automatically create Pull Request to upgrade our dependencies one by one. A [dependency dashboard issue](https://github.com/element-hq/element-x-android/issues/150) is maintained by the tool and allow to perform some actions.
### Test
diff --git a/docs/danger.md b/docs/danger.md
index e6fa74dec2..5cf34ac055 100644
--- a/docs/danger.md
+++ b/docs/danger.md
@@ -63,7 +63,7 @@ bundle exec danger pr --dangerfile=./tools/danger/dangerfile.js
For instance:
```shell
-bundle exec danger pr https://github.com/vector-im/element-android/pull/6637 --dangerfile=./tools/danger/dangerfile.js
+bundle exec danger pr https://github.com/element-hq/element-android/pull/6637 --dangerfile=./tools/danger/dangerfile.js
```
We may need to create a GitHub token to have less API rate limiting, and then set the env var:
@@ -84,7 +84,7 @@ bundle exec danger-kotlin pr --dangerfile=./tools/danger/dangerfile.js
To let Danger check all the PRs, including PRs form forks, a GitHub account have been created:
- login: ElementBot
- password: Stored on Passbolt
-- GitHub token: A token with limited access has been created and added to the repository https://github.com/vector-im/element-android as secret DANGER_GITHUB_API_TOKEN. This token is not saved anywhere else. In case of problem, just delete it and create a new one, then update the secret.
+- GitHub token: A token with limited access has been created and added to the repository https://github.com/element-hq/element-x-android as secret DANGER_GITHUB_API_TOKEN. This token is not saved anywhere else. In case of problem, just delete it and create a new one, then update the secret.
PRs from forks do not always have access to the secret `secrets.DANGER_GITHUB_API_TOKEN`, so `secrets.GITHUB_TOKEN` is also provided to the job environment. If `secrets.DANGER_GITHUB_API_TOKEN` is available, it will be used, so user `ElementBot` will comment the PR. Else `secrets.GITHUB_TOKEN` will be used, and bot `github-actions` will comment the PR.
diff --git a/docs/debug_proxying.md b/docs/debug_proxying.md
index 77c109461b..a28163c959 100644
--- a/docs/debug_proxying.md
+++ b/docs/debug_proxying.md
@@ -8,15 +8,15 @@
1) Disable "Use Android Studio HTTP proxy settings" and pick "Manual proxy configuration".
1) Set `127.0.0.1` as "Host name" and `8080` as "Port number".
1) Click "Apply" and verify that "Proxy status" is "Success" and close the settings window.
-
+
1) Install the mitmproxy CA cert (this is needed to see traffic from java/kotlin code, it's not needed for traffic coming from native code e.g. the matrix-rust-sdk).
1) Open the emulator Chrome browser app
1) Go to the url `mitm.it`
1) Follow the instructions to install the CA cert on Android devices.
-
+
1) Slightly modify the Element X app source code.
1) Go to the `RustMatrixClientFactory.create()` method.
1) Add `.disableSslVerification()` in the `ClientBuilder` method chain.
1) Build and run the Element X app.
1) Enjoy, you will see all the traffic in mitmproxy's web interface.
-
+
diff --git a/docs/design.md b/docs/design.md
index 58723eb28d..bdcaba199f 100644
--- a/docs/design.md
+++ b/docs/design.md
@@ -64,7 +64,7 @@ A comprehensive [color definition documentation](https://compound.element.io/?pa
Most icons should be available as part of the [Compound icon library](https://compound.element.io/?path=/docs/tokens-icons--docs)
All drawable are auto-generated as part of the design tokens library. You can find
-all assets in [`vector-im/compound-design-tokens#assets/android`](https://github.com/vector-im/compound-design-tokens/tree/develop/assets/android)
+all assets in [`element-hq/compound-design-tokens#assets/android`](https://github.com/element-hq/compound-design-tokens/tree/main/assets/android)
If you are missing an icon, follow to [contribution guidelines for icons](https://www.figma.com/file/gkNXqPoiJhEv2wt0EJpew4/Compound-Icons?type=design&node-id=178-3119&t=j2uSJD9xPXJn5aRM-0)
diff --git a/docs/install_from_github_release.md b/docs/install_from_github_release.md
index de395f737a..069e1d97ec 100644
--- a/docs/install_from_github_release.md
+++ b/docs/install_from_github_release.md
@@ -18,11 +18,11 @@ The easiest way to do that is to use the debug signature that is shared between
You can clone the project by running:
```bash
-git clone git@github.com:vector-im/element-x-android.git
+git clone git@github.com:element-hq/element-x-android.git
```
or
```bash
-git clone https://github.com/vector-im/element-x-android.git
+git clone https://github.com/element-hq/element-x-android.git
```
You will also need to install [bundletool](https://developer.android.com/studio/command-line/bundletool). On MacOS, you can run the following command:
@@ -33,7 +33,7 @@ brew install bundletool
## Steps
-1. Open the GitHub release that you want to install from https://github.com/vector-im/element-x-android/releases
+1. Open the GitHub release that you want to install from https://github.com/element-hq/element-x-android/releases
2. Download the asset `app-release-signed.aab`
3. Navigate to the folder where you cloned the project and run the following command:
```bash
diff --git a/docs/oidc.md b/docs/oidc.md
index 0e4ad44852..94b22660c0 100644
--- a/docs/oidc.md
+++ b/docs/oidc.md
@@ -1,14 +1,14 @@
This file contains some rough notes about Oidc implementation, with some examples of actual data.
-[ios implementation](https://github.com/vector-im/element-x-ios/compare/develop...doug/oidc-temp)
+[ios implementation](https://github.com/element-hq/element-x-ios/compare/develop...doug/oidc-temp)
Rust sdk branch: https://github.com/matrix-org/matrix-rust-sdk/tree/oidc-ffi
Figma https://www.figma.com/file/o9p34zmiuEpZRyvZXJZAYL/FTUE?node-id=133-5426&t=yQXKeANatk6keoZF-0
-Server list: https://github.com/vector-im/oidc-playground
+Server list: https://github.com/element-hq/oidc-playground
-Metadata iOS: (from https://github.com/vector-im/element-x-ios/blob/5f9d07377cebc4f21d9668b1a25f6e3bb22f64a1/ElementX/Sources/Services/Authentication/AuthenticationServiceProxy.swift#L28)
+Metadata iOS: (from https://github.com/element-hq/element-x-ios/blob/5f9d07377cebc4f21d9668b1a25f6e3bb22f64a1/ElementX/Sources/Services/Authentication/AuthenticationServiceProxy.swift#L28)
clientName: InfoPlistReader.main.bundleDisplayName,
redirectUri: "io.element:/callback",
diff --git a/docs/pull_request.md b/docs/pull_request.md
index 6144dd0d92..7ff71a30e7 100644
--- a/docs/pull_request.md
+++ b/docs/pull_request.md
@@ -86,13 +86,13 @@ Exceptions can occur:
We use automatic assignment for PR reviews. **A PR is automatically routed by GitHub to one team member** using the round robin algorithm. Additional reviewers can be used for complex changes or when the first reviewer is not confident enough on the changes.
The process is the following:
-- The PR creator selects the [element-x-android-reviewers](https://github.com/orgs/vector-im/teams/element-x-android-reviewers) team as a reviewer.
+- The PR creator selects the [element-x-android-reviewers](https://github.com/orgs/element-hq/teams/element-x-android-reviewers) team as a reviewer.
- GitHub automatically assign the reviewer. If the reviewer is not available (holiday, etc.), remove them and set again the team, GitHub will select another reviewer.
- Alternatively, the PR creator can directly assign specific people if they have another Android developer in their team or they think a specific reviewer should take a look at their PR.
- Reviewers get a notification to make the review: they review the code following the good practice (see the rest of this document).
- After making their own review, if they feel not confident enough, they can ask another person for a full review, or they can tag someone within a PR comment to check specific lines.
-For PRs coming from the community, the issue wrangler can assign either the team [element-x-android-reviewers](https://github.com/orgs/vector-im/teams/element-x-android-reviewers) or any member directly.
+For PRs coming from the community, the issue wrangler can assign either the team [element-x-android-reviewers](https://github.com/orgs/element-hq/teams/element-x-android-reviewers) or any member directly.
##### PR review time
diff --git a/docs/screenshot_testing.md b/docs/screenshot_testing.md
index cd9af50cbc..eb973af087 100644
--- a/docs/screenshot_testing.md
+++ b/docs/screenshot_testing.md
@@ -30,7 +30,7 @@ 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.
+Recording of screenshots is done by triggering the GitHub action [Record screenshots](https://github.com/element-hq/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.
diff --git a/fastlane/metadata/android/en-US/changelogs/40001020.txt b/fastlane/metadata/android/en-US/changelogs/40001020.txt
index 8aacdd89af..54b983499a 100644
--- a/fastlane/metadata/android/en-US/changelogs/40001020.txt
+++ b/fastlane/metadata/android/en-US/changelogs/40001020.txt
@@ -1,2 +1,2 @@
First release of Element X 🚀!
-Full changelog: https://github.com/vector-im/element-x-android/releases
+Full changelog: https://github.com/element-hq/element-x-android/releases
diff --git a/fastlane/metadata/android/en-US/changelogs/40001040.txt b/fastlane/metadata/android/en-US/changelogs/40001040.txt
index 2593704785..8b8ede35c3 100644
--- a/fastlane/metadata/android/en-US/changelogs/40001040.txt
+++ b/fastlane/metadata/android/en-US/changelogs/40001040.txt
@@ -1,2 +1,2 @@
Main changes in this version: bug fixes and add OIDC support.
-Full changelog: https://github.com/vector-im/element-x-android/releases
+Full changelog: https://github.com/element-hq/element-x-android/releases
diff --git a/fastlane/metadata/android/en-US/changelogs/40001050.txt b/fastlane/metadata/android/en-US/changelogs/40001050.txt
index 2593704785..8b8ede35c3 100644
--- a/fastlane/metadata/android/en-US/changelogs/40001050.txt
+++ b/fastlane/metadata/android/en-US/changelogs/40001050.txt
@@ -1,2 +1,2 @@
Main changes in this version: bug fixes and add OIDC support.
-Full changelog: https://github.com/vector-im/element-x-android/releases
+Full changelog: https://github.com/element-hq/element-x-android/releases
diff --git a/fastlane/metadata/android/en-US/changelogs/40001060.txt b/fastlane/metadata/android/en-US/changelogs/40001060.txt
index ff4f86ce7e..b2d056f013 100644
--- a/fastlane/metadata/android/en-US/changelogs/40001060.txt
+++ b/fastlane/metadata/android/en-US/changelogs/40001060.txt
@@ -1,2 +1,2 @@
Main changes in this version: bugfixes.
-Full changelog: https://github.com/vector-im/element-x-android/releases
+Full changelog: https://github.com/element-hq/element-x-android/releases
diff --git a/fastlane/metadata/android/en-US/changelogs/40002000.txt b/fastlane/metadata/android/en-US/changelogs/40002000.txt
index 97ceaa8d5a..19e1babb9d 100644
--- a/fastlane/metadata/android/en-US/changelogs/40002000.txt
+++ b/fastlane/metadata/android/en-US/changelogs/40002000.txt
@@ -1,2 +1,2 @@
Main changes in this version: Element Call, design update, bugfixes
-Full changelog: https://github.com/vector-im/element-x-android/releases
+Full changelog: https://github.com/element-hq/element-x-android/releases
diff --git a/fastlane/metadata/android/en-US/changelogs/40002010.txt b/fastlane/metadata/android/en-US/changelogs/40002010.txt
index 97ceaa8d5a..19e1babb9d 100644
--- a/fastlane/metadata/android/en-US/changelogs/40002010.txt
+++ b/fastlane/metadata/android/en-US/changelogs/40002010.txt
@@ -1,2 +1,2 @@
Main changes in this version: Element Call, design update, bugfixes
-Full changelog: https://github.com/vector-im/element-x-android/releases
+Full changelog: https://github.com/element-hq/element-x-android/releases
diff --git a/fastlane/metadata/android/en-US/changelogs/40002020.txt b/fastlane/metadata/android/en-US/changelogs/40002020.txt
index 882eb88054..f9c0486e89 100644
--- a/fastlane/metadata/android/en-US/changelogs/40002020.txt
+++ b/fastlane/metadata/android/en-US/changelogs/40002020.txt
@@ -1,2 +1,2 @@
Main changes in this version: bugfixes
-Full changelog: https://github.com/vector-im/element-x-android/releases
+Full changelog: https://github.com/element-hq/element-x-android/releases
diff --git a/fastlane/metadata/android/en-US/changelogs/40002030.txt b/fastlane/metadata/android/en-US/changelogs/40002030.txt
index ff4f86ce7e..b2d056f013 100644
--- a/fastlane/metadata/android/en-US/changelogs/40002030.txt
+++ b/fastlane/metadata/android/en-US/changelogs/40002030.txt
@@ -1,2 +1,2 @@
Main changes in this version: bugfixes.
-Full changelog: https://github.com/vector-im/element-x-android/releases
+Full changelog: https://github.com/element-hq/element-x-android/releases
diff --git a/fastlane/metadata/android/en-US/changelogs/40002040.txt b/fastlane/metadata/android/en-US/changelogs/40002040.txt
index ff4f86ce7e..b2d056f013 100644
--- a/fastlane/metadata/android/en-US/changelogs/40002040.txt
+++ b/fastlane/metadata/android/en-US/changelogs/40002040.txt
@@ -1,2 +1,2 @@
Main changes in this version: bugfixes.
-Full changelog: https://github.com/vector-im/element-x-android/releases
+Full changelog: https://github.com/element-hq/element-x-android/releases
diff --git a/fastlane/metadata/android/en-US/changelogs/40003000.txt b/fastlane/metadata/android/en-US/changelogs/40003000.txt
index 0634ffa760..fb55ecbe98 100644
--- a/fastlane/metadata/android/en-US/changelogs/40003000.txt
+++ b/fastlane/metadata/android/en-US/changelogs/40003000.txt
@@ -1,2 +1,2 @@
Main changes in this version: Element Call, voice message.
-Full changelog: https://github.com/vector-im/element-x-android/releases
+Full changelog: https://github.com/element-hq/element-x-android/releases
diff --git a/fastlane/metadata/android/en-US/changelogs/40003010.txt b/fastlane/metadata/android/en-US/changelogs/40003010.txt
index b2c89b804f..cccc7477c2 100644
--- a/fastlane/metadata/android/en-US/changelogs/40003010.txt
+++ b/fastlane/metadata/android/en-US/changelogs/40003010.txt
@@ -1,2 +1,2 @@
Main changes in this version: Mainly bug fixes.
-Full changelog: https://github.com/vector-im/element-x-android/releases
+Full changelog: https://github.com/element-hq/element-x-android/releases
diff --git a/fastlane/metadata/android/en-US/changelogs/40003020.txt b/fastlane/metadata/android/en-US/changelogs/40003020.txt
index 415e29b2bf..610f99ec10 100644
--- a/fastlane/metadata/android/en-US/changelogs/40003020.txt
+++ b/fastlane/metadata/android/en-US/changelogs/40003020.txt
@@ -4,4 +4,4 @@ Main changes in this version:
- Adding mentions to a message is now possible, but it's disabled by default as it's a work in progress. They can be enabled in the developer options.
- Voice messages behavior changed: there is no need to keep pressing to record, to start recording a message just tap on the mic button, then tap again to stop recording.
- Added a marker in the timeline to indicate the starting point of the room messages.
-Full changelog: https://github.com/vector-im/element-x-android/releases
+Full changelog: https://github.com/element-hq/element-x-android/releases
diff --git a/features/analytics/api/src/main/res/values-hu/translations.xml b/features/analytics/api/src/main/res/values-hu/translations.xml
new file mode 100644
index 0000000000..13f7026038
--- /dev/null
+++ b/features/analytics/api/src/main/res/values-hu/translations.xml
@@ -0,0 +1,7 @@
+
+
+ "Elemzési adatok megosztása"
+ "Anonim használati adatok megosztása a problémák azonosítása érdekében."
+ "%1$s olvashatja el a feltételeinket."
+ "Itt"
+
diff --git a/features/analytics/api/src/main/res/values-in/translations.xml b/features/analytics/api/src/main/res/values-in/translations.xml
new file mode 100644
index 0000000000..ffe3dc729e
--- /dev/null
+++ b/features/analytics/api/src/main/res/values-in/translations.xml
@@ -0,0 +1,7 @@
+
+
+ "Bagikan data analitik"
+ "Bagikan data penggunaan anonim untuk membantu kami mengidentifikasi masalah."
+ "Anda dapat membaca semua persyaratan kami %1$s."
+ "di sini"
+
diff --git a/features/analytics/impl/src/main/res/values-hu/translations.xml b/features/analytics/impl/src/main/res/values-hu/translations.xml
new file mode 100644
index 0000000000..dea908fe08
--- /dev/null
+++ b/features/analytics/impl/src/main/res/values-hu/translations.xml
@@ -0,0 +1,10 @@
+
+
+ "Nem rögzítünk vagy profilozunk személyes adatokat"
+ "Anonim használati adatok megosztása a problémák azonosítása érdekében."
+ "%1$s olvashatja el a feltételeinket."
+ "Itt"
+ "Ezt bármikor kikapcsolhatja"
+ "Adatait nem osztjuk meg harmadik felekkel"
+ "Segítsen az %1$s fejlesztésében"
+
diff --git a/features/analytics/impl/src/main/res/values-in/translations.xml b/features/analytics/impl/src/main/res/values-in/translations.xml
new file mode 100644
index 0000000000..655b0c6d88
--- /dev/null
+++ b/features/analytics/impl/src/main/res/values-in/translations.xml
@@ -0,0 +1,10 @@
+
+
+ "Kami tidak akan merekam atau memprofil data pribadi apa pun"
+ "Bagikan data penggunaan anonim untuk membantu kami mengidentifikasi masalah."
+ "Anda dapat membaca semua persyaratan kami %1$s."
+ "di sini"
+ "Anda dapat mematikan ini kapan saja"
+ "Kami tidak akan membagikan data Anda dengan pihak ketiga"
+ "Bantu sempurnakan %1$s"
+
diff --git a/features/cachecleaner/impl/src/test/kotlin/io/element/android/features/cachecleaner/impl/DefaultCacheCleanerTest.kt b/features/cachecleaner/impl/src/test/kotlin/io/element/android/features/cachecleaner/impl/DefaultCacheCleanerTest.kt
index 7fe70028ac..f35bc518fa 100644
--- a/features/cachecleaner/impl/src/test/kotlin/io/element/android/features/cachecleaner/impl/DefaultCacheCleanerTest.kt
+++ b/features/cachecleaner/impl/src/test/kotlin/io/element/android/features/cachecleaner/impl/DefaultCacheCleanerTest.kt
@@ -16,7 +16,7 @@
package io.element.android.features.cachecleaner.impl
-import com.google.common.truth.Truth
+import com.google.common.truth.Truth.assertThat
import io.element.android.tests.testutils.testCoroutineDispatchers
import kotlinx.coroutines.test.TestScope
import kotlinx.coroutines.test.runTest
@@ -46,9 +46,9 @@ class DefaultCacheCleanerTest {
// Check the files are gone but the sub dirs are not.
DefaultCacheCleaner.SUBDIRS_TO_CLEANUP.forEach {
File(temporaryFolder.root, it).apply {
- Truth.assertThat(exists()).isTrue()
- Truth.assertThat(isDirectory).isTrue()
- Truth.assertThat(listFiles()).isEmpty()
+ assertThat(exists()).isTrue()
+ assertThat(isDirectory).isTrue()
+ assertThat(listFiles()).isEmpty()
}
}
}
diff --git a/features/call/src/main/res/values-hu/translations.xml b/features/call/src/main/res/values-hu/translations.xml
new file mode 100644
index 0000000000..fee5a163bb
--- /dev/null
+++ b/features/call/src/main/res/values-hu/translations.xml
@@ -0,0 +1,6 @@
+
+
+ "Folyamatban lévő hívás"
+ "Koppintson a híváshoz való visszatéréshez"
+ "☎️ Hívás folyamatban"
+
diff --git a/features/call/src/main/res/values-in/translations.xml b/features/call/src/main/res/values-in/translations.xml
new file mode 100644
index 0000000000..886dac5e33
--- /dev/null
+++ b/features/call/src/main/res/values-in/translations.xml
@@ -0,0 +1,6 @@
+
+
+ "Panggilan berlangsung"
+ "Ketuk untuk kembali ke panggilan"
+ "☎️ Panggilan sedang berlangsung"
+
diff --git a/features/call/src/test/kotlin/io/element/android/features/call/MapWebkitPermissionsTest.kt b/features/call/src/test/kotlin/io/element/android/features/call/MapWebkitPermissionsTest.kt
index 55b5f16771..fa60b348b1 100644
--- a/features/call/src/test/kotlin/io/element/android/features/call/MapWebkitPermissionsTest.kt
+++ b/features/call/src/test/kotlin/io/element/android/features/call/MapWebkitPermissionsTest.kt
@@ -39,7 +39,6 @@ class MapWebkitPermissionsTest {
@Test
fun `given any other permission, it returns nothing`() {
val permission = mapWebkitPermissions(arrayOf(PermissionRequest.RESOURCE_PROTECTED_MEDIA_ID))
- assertThat(permission).isEqualTo(emptyList())
+ assertThat(permission).isEmpty()
}
-
}
diff --git a/features/createroom/api/src/main/kotlin/io/element/android/features/createroom/api/StartDMAction.kt b/features/createroom/api/src/main/kotlin/io/element/android/features/createroom/api/StartDMAction.kt
new file mode 100644
index 0000000000..ef95f15dce
--- /dev/null
+++ b/features/createroom/api/src/main/kotlin/io/element/android/features/createroom/api/StartDMAction.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.features.createroom.api
+
+import androidx.compose.runtime.MutableState
+import io.element.android.libraries.architecture.Async
+import io.element.android.libraries.matrix.api.core.RoomId
+import io.element.android.libraries.matrix.api.core.UserId
+
+interface StartDMAction {
+ /**
+ * Try to find an existing DM with the given user, or create one if none exists.
+ * @param userId The user to start a DM with.
+ * @param actionState The state to update with the result of the action.
+ */
+ suspend fun execute(userId: UserId, actionState: MutableState>)
+}
diff --git a/features/createroom/impl/build.gradle.kts b/features/createroom/impl/build.gradle.kts
index ae9818b727..6cd9b30741 100644
--- a/features/createroom/impl/build.gradle.kts
+++ b/features/createroom/impl/build.gradle.kts
@@ -67,6 +67,7 @@ dependencies {
testImplementation(projects.libraries.mediaupload.test)
testImplementation(projects.libraries.permissions.test)
testImplementation(projects.libraries.usersearch.test)
+ testImplementation(projects.features.createroom.test)
testImplementation(projects.tests.testutils)
ksp(libs.showkase.processor)
diff --git a/features/createroom/impl/src/main/kotlin/io/element/android/features/createroom/impl/DefaultStartDMAction.kt b/features/createroom/impl/src/main/kotlin/io/element/android/features/createroom/impl/DefaultStartDMAction.kt
new file mode 100644
index 0000000000..7145ac671e
--- /dev/null
+++ b/features/createroom/impl/src/main/kotlin/io/element/android/features/createroom/impl/DefaultStartDMAction.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.createroom.impl
+
+import androidx.compose.runtime.MutableState
+import com.squareup.anvil.annotations.ContributesBinding
+import im.vector.app.features.analytics.plan.CreatedRoom
+import io.element.android.features.createroom.api.StartDMAction
+import io.element.android.libraries.architecture.Async
+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.core.UserId
+import io.element.android.libraries.matrix.api.room.StartDMResult
+import io.element.android.libraries.matrix.api.room.startDM
+import io.element.android.services.analytics.api.AnalyticsService
+import javax.inject.Inject
+
+@ContributesBinding(SessionScope::class)
+class DefaultStartDMAction @Inject constructor(
+ private val matrixClient: MatrixClient,
+ private val analyticsService: AnalyticsService,
+) : StartDMAction {
+
+ override suspend fun execute(userId: UserId, actionState: MutableState>) {
+ actionState.value = Async.Loading()
+ when (val result = matrixClient.startDM(userId)) {
+ is StartDMResult.Success -> {
+ if (result.isNew) {
+ analyticsService.capture(CreatedRoom(isDM = true))
+ }
+ actionState.value = Async.Success(result.roomId)
+ }
+ is StartDMResult.Failure -> {
+ actionState.value = Async.Failure(result.throwable)
+ }
+ }
+ }
+}
diff --git a/features/createroom/impl/src/main/kotlin/io/element/android/features/createroom/impl/root/CreateRoomRootPresenter.kt b/features/createroom/impl/src/main/kotlin/io/element/android/features/createroom/impl/root/CreateRoomRootPresenter.kt
index 839e4cd69e..9b60924ca4 100644
--- a/features/createroom/impl/src/main/kotlin/io/element/android/features/createroom/impl/root/CreateRoomRootPresenter.kt
+++ b/features/createroom/impl/src/main/kotlin/io/element/android/features/createroom/impl/root/CreateRoomRootPresenter.kt
@@ -21,21 +21,16 @@ import androidx.compose.runtime.MutableState
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.runtime.rememberCoroutineScope
-import im.vector.app.features.analytics.plan.CreatedRoom
+import io.element.android.features.createroom.api.StartDMAction
import io.element.android.features.createroom.impl.userlist.SelectionMode
import io.element.android.features.createroom.impl.userlist.UserListDataStore
import io.element.android.features.createroom.impl.userlist.UserListPresenter
import io.element.android.features.createroom.impl.userlist.UserListPresenterArgs
import io.element.android.libraries.architecture.Async
import io.element.android.libraries.architecture.Presenter
-import io.element.android.libraries.architecture.runCatchingUpdatingState
import io.element.android.libraries.core.meta.BuildMeta
-import io.element.android.libraries.matrix.api.MatrixClient
import io.element.android.libraries.matrix.api.core.RoomId
-import io.element.android.libraries.matrix.api.user.MatrixUser
import io.element.android.libraries.usersearch.api.UserRepository
-import io.element.android.services.analytics.api.AnalyticsService
-import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.launch
import javax.inject.Inject
@@ -43,8 +38,7 @@ class CreateRoomRootPresenter @Inject constructor(
presenterFactory: UserListPresenter.Factory,
userRepository: UserRepository,
userListDataStore: UserListDataStore,
- private val matrixClient: MatrixClient,
- private val analyticsService: AnalyticsService,
+ private val startDMAction: StartDMAction,
private val buildMeta: BuildMeta,
) : Presenter {
@@ -61,37 +55,22 @@ class CreateRoomRootPresenter @Inject constructor(
val userListState = presenter.present()
val localCoroutineScope = rememberCoroutineScope()
- val startDmAction: MutableState> = remember { mutableStateOf(Async.Uninitialized) }
+ val startDmActionState: MutableState> = remember { mutableStateOf(Async.Uninitialized) }
fun handleEvents(event: CreateRoomRootEvents) {
when (event) {
- is CreateRoomRootEvents.StartDM -> localCoroutineScope.startDm(event.matrixUser, startDmAction)
- CreateRoomRootEvents.CancelStartDM -> startDmAction.value = Async.Uninitialized
+ is CreateRoomRootEvents.StartDM -> localCoroutineScope.launch {
+ startDMAction.execute(event.matrixUser.userId, startDmActionState)
+ }
+ CreateRoomRootEvents.CancelStartDM -> startDmActionState.value = Async.Uninitialized
}
}
return CreateRoomRootState(
applicationName = buildMeta.applicationName,
userListState = userListState,
- startDmAction = startDmAction.value,
+ startDmAction = startDmActionState.value,
eventSink = ::handleEvents,
)
}
-
- private fun CoroutineScope.startDm(matrixUser: MatrixUser, startDmAction: MutableState>) = launch {
- suspend {
- matrixClient.findDM(matrixUser.userId).use { existingDM ->
- existingDM?.roomId ?: createDM(matrixUser)
- }
- }.runCatchingUpdatingState(startDmAction)
- }
-
- private suspend fun createDM(user: MatrixUser): RoomId {
- return matrixClient
- .createDM(user.userId)
- .onSuccess {
- analyticsService.capture(CreatedRoom(isDM = true))
- }
- .getOrThrow()
- }
}
diff --git a/features/createroom/impl/src/main/res/values-hu/translations.xml b/features/createroom/impl/src/main/res/values-hu/translations.xml
new file mode 100644
index 0000000000..29a403a091
--- /dev/null
+++ b/features/createroom/impl/src/main/res/values-hu/translations.xml
@@ -0,0 +1,15 @@
+
+
+ "Új szoba"
+ "Hívja meg ismerőseit az Elementbe"
+ "Emberek meghívása"
+ "Hiba történt a szoba létrehozásakor"
+ "A szobában lévő üzenetek titkosítottak. A titkosítást utólag nem lehet kikapcsolni."
+ "Privát szoba (csak meghívással)"
+ "Az üzenetek nincsenek titkosítva, és bárki elolvashatja őket. A titkosítást később is engedélyezheti."
+ "Nyilvános szoba (bárki)"
+ "Szoba neve"
+ "Téma (nem kötelező)"
+ "Hiba történt a csevegés indításakor"
+ "Szoba létrehozása"
+
diff --git a/features/createroom/impl/src/main/res/values-in/translations.xml b/features/createroom/impl/src/main/res/values-in/translations.xml
new file mode 100644
index 0000000000..aff7eab8b7
--- /dev/null
+++ b/features/createroom/impl/src/main/res/values-in/translations.xml
@@ -0,0 +1,15 @@
+
+
+ "Ruangan baru"
+ "Undang teman ke Element"
+ "Undang seseorang"
+ "Terjadi kesalahan saat membuat ruangan"
+ "Pesan di ruangan ini dienkripsi. Enkripsi tidak dapat dinonaktifkan setelahnya."
+ "Ruangan pribadi (hanya undangan)"
+ "Pesan tidak dienkripsi dan siapa pun dapat membacanya. Anda dapat mengaktifkan enkripsi di kemudian hari."
+ "Ruang publik (siapa saja)"
+ "Nama ruangan"
+ "Topik (opsional)"
+ "Terjadi kesalahan saat mencoba memulai obrolan"
+ "Buat ruangan"
+
diff --git a/features/createroom/impl/src/test/kotlin/io/element/android/features/createroom/impl/DefaultStartDMActionTests.kt b/features/createroom/impl/src/test/kotlin/io/element/android/features/createroom/impl/DefaultStartDMActionTests.kt
new file mode 100644
index 0000000000..f2ed30c58d
--- /dev/null
+++ b/features/createroom/impl/src/test/kotlin/io/element/android/features/createroom/impl/DefaultStartDMActionTests.kt
@@ -0,0 +1,82 @@
+/*
+ * 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.createroom.impl
+
+import androidx.compose.runtime.mutableStateOf
+import com.google.common.truth.Truth.assertThat
+import im.vector.app.features.analytics.plan.CreatedRoom
+import io.element.android.libraries.architecture.Async
+import io.element.android.libraries.matrix.api.MatrixClient
+import io.element.android.libraries.matrix.api.core.RoomId
+import io.element.android.libraries.matrix.test.A_ROOM_ID
+import io.element.android.libraries.matrix.test.A_THROWABLE
+import io.element.android.libraries.matrix.test.A_USER_ID
+import io.element.android.libraries.matrix.test.FakeMatrixClient
+import io.element.android.services.analytics.api.AnalyticsService
+import io.element.android.services.analytics.test.FakeAnalyticsService
+import kotlinx.coroutines.test.runTest
+import org.junit.Test
+
+class DefaultStartDMActionTests {
+
+ @Test
+ fun `when dm is found, assert state is updated with given room id`() = runTest {
+ val matrixClient = FakeMatrixClient().apply {
+ givenFindDmResult(A_ROOM_ID)
+ }
+ val action = createStartDMAction(matrixClient)
+ val state = mutableStateOf>(Async.Uninitialized)
+ action.execute(A_USER_ID, state)
+ assertThat(state.value).isEqualTo(Async.Success(A_ROOM_ID))
+ }
+
+ @Test
+ fun `when dm is not found, assert dm is created, state is updated with given room id and analytics get called`() = runTest {
+ val matrixClient = FakeMatrixClient().apply {
+ givenFindDmResult(null)
+ givenCreateDmResult(Result.success(A_ROOM_ID))
+ }
+ val analyticsService = FakeAnalyticsService()
+ val action = createStartDMAction(matrixClient, analyticsService)
+ val state = mutableStateOf>(Async.Uninitialized)
+ action.execute(A_USER_ID, state)
+ assertThat(state.value).isEqualTo(Async.Success(A_ROOM_ID))
+ assertThat(analyticsService.capturedEvents).containsExactly(CreatedRoom(isDM = true))
+ }
+
+ @Test
+ fun `when dm creation fails, assert state is updated with given error`() = runTest {
+ val matrixClient = FakeMatrixClient().apply {
+ givenFindDmResult(null)
+ givenCreateDmResult(Result.failure(A_THROWABLE))
+ }
+ val action = createStartDMAction(matrixClient)
+ val state = mutableStateOf>(Async.Uninitialized)
+ action.execute(A_USER_ID, state)
+ assertThat(state.value).isEqualTo(Async.Failure(A_THROWABLE))
+ }
+
+ private fun createStartDMAction(
+ matrixClient: MatrixClient = FakeMatrixClient(),
+ analyticsService: AnalyticsService = FakeAnalyticsService(),
+ ): DefaultStartDMAction {
+ return DefaultStartDMAction(
+ matrixClient = matrixClient,
+ analyticsService = analyticsService,
+ )
+ }
+}
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 bf4593bdbb..a0fb71dd31 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
@@ -20,25 +20,21 @@ import app.cash.molecule.RecompositionMode
import app.cash.molecule.moleculeFlow
import app.cash.turbine.test
import com.google.common.truth.Truth.assertThat
-import im.vector.app.features.analytics.plan.CreatedRoom
+import io.element.android.features.createroom.api.StartDMAction
import io.element.android.features.createroom.impl.userlist.FakeUserListPresenter
import io.element.android.features.createroom.impl.userlist.FakeUserListPresenterFactory
import io.element.android.features.createroom.impl.userlist.UserListDataStore
-import io.element.android.features.createroom.impl.userlist.aUserListState
+import io.element.android.features.createroom.test.FakeStartDMAction
import io.element.android.libraries.architecture.Async
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
+import io.element.android.libraries.matrix.test.A_ROOM_ID
import io.element.android.libraries.matrix.test.A_THROWABLE
-import io.element.android.libraries.matrix.test.FakeMatrixClient
import io.element.android.libraries.matrix.test.core.aBuildMeta
-import io.element.android.libraries.matrix.test.room.FakeMatrixRoom
import io.element.android.libraries.usersearch.test.FakeUserRepository
-import io.element.android.services.analytics.test.FakeAnalyticsService
import io.element.android.tests.testutils.WarmUpRule
-import kotlinx.collections.immutable.persistentListOf
import kotlinx.coroutines.test.runTest
-import org.junit.Before
import org.junit.Rule
import org.junit.Test
@@ -47,142 +43,57 @@ class CreateRoomRootPresenterTests {
@get:Rule
val warmUpRule = WarmUpRule()
- private lateinit var userRepository: FakeUserRepository
- private lateinit var presenter: CreateRoomRootPresenter
- private lateinit var fakeUserListPresenter: FakeUserListPresenter
- private lateinit var fakeMatrixClient: FakeMatrixClient
- private lateinit var fakeAnalyticsService: FakeAnalyticsService
-
- @Before
- fun setup() {
- fakeUserListPresenter = FakeUserListPresenter()
- fakeMatrixClient = FakeMatrixClient()
- fakeAnalyticsService = FakeAnalyticsService()
- userRepository = FakeUserRepository()
- presenter = CreateRoomRootPresenter(
- presenterFactory = FakeUserListPresenterFactory(fakeUserListPresenter),
- userRepository = userRepository,
- userListDataStore = UserListDataStore(),
- matrixClient = fakeMatrixClient,
- analyticsService = fakeAnalyticsService,
- buildMeta = aBuildMeta(),
- )
- }
-
@Test
- fun `present - initial state`() = runTest {
+ fun `present - start DM action complete scenario`() = runTest {
+ val startDMAction = FakeStartDMAction()
+ val presenter = createCreateRoomRootPresenter(startDMAction)
moleculeFlow(RecompositionMode.Immediate) {
presenter.present()
}.test {
val initialState = awaitItem()
+
assertThat(initialState.startDmAction).isInstanceOf(Async.Uninitialized::class.java)
assertThat(initialState.applicationName).isEqualTo(aBuildMeta().applicationName)
assertThat(initialState.userListState.selectedUsers).isEmpty()
assertThat(initialState.userListState.isSearchActive).isFalse()
assertThat(initialState.userListState.isMultiSelectionEnabled).isFalse()
- }
- }
- @Test
- fun `present - trigger create DM action`() = runTest {
- moleculeFlow(RecompositionMode.Immediate) {
- presenter.present()
- }.test {
- val initialState = awaitItem()
val matrixUser = MatrixUser(UserId("@name:domain"))
- val createDmResult = Result.success(RoomId("!createDmResult:domain"))
-
- fakeMatrixClient.givenFindDmResult(null)
- fakeMatrixClient.givenCreateDmResult(createDmResult)
-
- initialState.eventSink(CreateRoomRootEvents.StartDM(matrixUser))
- assertThat(awaitItem().startDmAction).isInstanceOf(Async.Loading::class.java)
- val stateAfterStartDM = awaitItem()
- assertThat(stateAfterStartDM.startDmAction).isInstanceOf(Async.Success::class.java)
- assertThat(stateAfterStartDM.startDmAction.dataOrNull()).isEqualTo(createDmResult.getOrNull())
- }
- }
-
- @Test
- fun `present - creating a DM records analytics event`() = runTest {
- moleculeFlow(RecompositionMode.Immediate) {
- presenter.present()
- }.test {
- val initialState = awaitItem()
- val matrixUser = MatrixUser(UserId("@name:domain"))
- val createDmResult = Result.success(RoomId("!createDmResult:domain"))
-
- fakeMatrixClient.givenFindDmResult(null)
- fakeMatrixClient.givenCreateDmResult(createDmResult)
-
- initialState.eventSink(CreateRoomRootEvents.StartDM(matrixUser))
- skipItems(2)
-
- val analyticsEvent = fakeAnalyticsService.capturedEvents.filterIsInstance().firstOrNull()
- assertThat(analyticsEvent).isNotNull()
- assertThat(analyticsEvent?.isDM).isTrue()
- }
- }
-
- @Test
- fun `present - trigger retrieve DM action`() = runTest {
- moleculeFlow(RecompositionMode.Immediate) {
- presenter.present()
- }.test {
- val initialState = awaitItem()
- val matrixUser = MatrixUser(UserId("@name:domain"))
- val fakeDmResult = FakeMatrixRoom(roomId = RoomId("!fakeDmResult:domain"))
-
- fakeMatrixClient.givenFindDmResult(fakeDmResult)
-
- initialState.eventSink(CreateRoomRootEvents.StartDM(matrixUser))
- val stateAfterStartDM = awaitItem()
- assertThat(stateAfterStartDM.startDmAction).isInstanceOf(Async.Success::class.java)
- assertThat(stateAfterStartDM.startDmAction.dataOrNull()).isEqualTo(fakeDmResult.roomId)
- assertThat(fakeAnalyticsService.capturedEvents.filterIsInstance()).isEmpty()
- }
- }
-
- @Test
- fun `present - trigger retry create DM action`() = runTest {
- moleculeFlow(RecompositionMode.Immediate) {
- presenter.present()
- }.test {
- val initialState = awaitItem()
- val matrixUser = MatrixUser(UserId("@name:domain"))
- val createDmResult = Result.success(RoomId("!createDmResult:domain"))
- fakeUserListPresenter.givenState(aUserListState().copy(selectedUsers = persistentListOf(matrixUser)))
-
- fakeMatrixClient.givenFindDmResult(null)
- fakeMatrixClient.givenCreateDmError(A_THROWABLE)
- fakeMatrixClient.givenCreateDmResult(createDmResult)
+ val startDMSuccessResult = Async.Success(A_ROOM_ID)
+ val startDMFailureResult = Async.Failure(A_THROWABLE)
// Failure
+ startDMAction.givenExecuteResult(startDMFailureResult)
initialState.eventSink(CreateRoomRootEvents.StartDM(matrixUser))
assertThat(awaitItem().startDmAction).isInstanceOf(Async.Loading::class.java)
- val stateAfterStartDM = awaitItem()
- assertThat(stateAfterStartDM.startDmAction).isInstanceOf(Async.Failure::class.java)
- assertThat(fakeAnalyticsService.capturedEvents.filterIsInstance()).isEmpty()
+ awaitItem().also { state ->
+ assertThat(state.startDmAction).isEqualTo(startDMFailureResult)
+ state.eventSink(CreateRoomRootEvents.CancelStartDM)
+ }
- // Cancel
- stateAfterStartDM.eventSink(CreateRoomRootEvents.CancelStartDM)
- val stateAfterCancel = awaitItem()
- assertThat(stateAfterCancel.startDmAction).isInstanceOf(Async.Uninitialized::class.java)
-
- // Failure
- stateAfterCancel.eventSink(CreateRoomRootEvents.StartDM(matrixUser))
+ // Success
+ startDMAction.givenExecuteResult(startDMSuccessResult)
+ awaitItem().also { state ->
+ assertThat(state.startDmAction).isEqualTo(Async.Uninitialized)
+ state.eventSink(CreateRoomRootEvents.StartDM(matrixUser))
+ }
assertThat(awaitItem().startDmAction).isInstanceOf(Async.Loading::class.java)
- val stateAfterSecondAttempt = awaitItem()
- assertThat(stateAfterSecondAttempt.startDmAction).isInstanceOf(Async.Failure::class.java)
- assertThat(fakeAnalyticsService.capturedEvents.filterIsInstance()).isEmpty()
+ awaitItem().also { state ->
+ assertThat(state.startDmAction).isEqualTo(startDMSuccessResult)
+ }
- // Retry with success
- fakeMatrixClient.givenCreateDmError(null)
- stateAfterSecondAttempt.eventSink(CreateRoomRootEvents.StartDM(matrixUser))
- assertThat(awaitItem().startDmAction).isInstanceOf(Async.Loading::class.java)
- val stateAfterRetryStartDM = awaitItem()
- assertThat(stateAfterRetryStartDM.startDmAction).isInstanceOf(Async.Success::class.java)
- assertThat(stateAfterRetryStartDM.startDmAction.dataOrNull()).isEqualTo(createDmResult.getOrNull())
}
}
+
+ private fun createCreateRoomRootPresenter(
+ startDMAction: StartDMAction = FakeStartDMAction(),
+ ): CreateRoomRootPresenter {
+ return CreateRoomRootPresenter(
+ presenterFactory = FakeUserListPresenterFactory(FakeUserListPresenter()),
+ userRepository = FakeUserRepository(),
+ userListDataStore = UserListDataStore(),
+ startDMAction = startDMAction,
+ buildMeta = aBuildMeta(),
+ )
+ }
}
diff --git a/features/createroom/test/build.gradle.kts b/features/createroom/test/build.gradle.kts
new file mode 100644
index 0000000000..53c3e6461a
--- /dev/null
+++ b/features/createroom/test/build.gradle.kts
@@ -0,0 +1,31 @@
+/*
+ * 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.
+ */
+
+plugins {
+ id("io.element.android-compose-library")
+}
+
+android {
+ namespace = "io.element.android.features.createroom.test"
+}
+
+dependencies {
+ implementation(libs.coroutines.core)
+ implementation(projects.libraries.matrix.api)
+ implementation(projects.libraries.matrix.test)
+ implementation(projects.libraries.architecture)
+ api(projects.features.createroom.api)
+}
diff --git a/features/createroom/test/src/main/kotlin/io/element/android/features/createroom/test/FakeStartDMAction.kt b/features/createroom/test/src/main/kotlin/io/element/android/features/createroom/test/FakeStartDMAction.kt
new file mode 100644
index 0000000000..c1888dc53f
--- /dev/null
+++ b/features/createroom/test/src/main/kotlin/io/element/android/features/createroom/test/FakeStartDMAction.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.features.createroom.test
+
+import androidx.compose.runtime.MutableState
+import io.element.android.features.createroom.api.StartDMAction
+import io.element.android.libraries.architecture.Async
+import io.element.android.libraries.matrix.api.core.RoomId
+import io.element.android.libraries.matrix.api.core.UserId
+import io.element.android.libraries.matrix.test.A_ROOM_ID
+import kotlinx.coroutines.delay
+
+class FakeStartDMAction : StartDMAction {
+
+ private var executeResult: Async = Async.Success(A_ROOM_ID)
+
+ fun givenExecuteResult(result: Async) {
+ executeResult = result
+ }
+
+ override suspend fun execute(userId: UserId, actionState: MutableState>) {
+ actionState.value = Async.Loading()
+ delay(1)
+ actionState.value = executeResult
+ }
+}
diff --git a/features/ftue/impl/src/main/res/values-hu/translations.xml b/features/ftue/impl/src/main/res/values-hu/translations.xml
new file mode 100644
index 0000000000..6585aaf4a8
--- /dev/null
+++ b/features/ftue/impl/src/main/res/values-hu/translations.xml
@@ -0,0 +1,13 @@
+
+
+ "Ez egy egyszeri folyamat, köszönjük a türelmét."
+ "A fiók beállítása."
+ "A beállításokat később is módosíthatja."
+ "Értesítések engedélyezése, hogy soha ne maradjon le egyetlen üzenetről sem"
+ "A hívások, szavazások, keresések és egyebek az év további részében kerülnek hozzáadásra."
+ "A titkosított szobák üzenetelőzményei nem lesznek elérhetők ebben a frissítésben."
+ "Szeretnénk hallani a véleményét, ossza meg velünk a beállítások oldalon."
+ "Lássunk neki!"
+ "A következőket kell tudnia:"
+ "Üdvözli az %1$s!"
+
diff --git a/features/ftue/impl/src/main/res/values-in/translations.xml b/features/ftue/impl/src/main/res/values-in/translations.xml
new file mode 100644
index 0000000000..126ce6376b
--- /dev/null
+++ b/features/ftue/impl/src/main/res/values-in/translations.xml
@@ -0,0 +1,13 @@
+
+
+ "Ini adalah proses satu kali, terima kasih telah menunggu."
+ "Menyiapkan akun Anda."
+ "Anda dapat mengubah pengaturan Anda nanti."
+ "Izinkan pemberitahuan dan jangan pernah melewatkan pesan"
+ "Panggilan, pemungutan suara, pencarian, dan lainnya akan ditambahkan di tahun ini."
+ "Riwayat pesan untuk ruangan terenkripsi tidak akan tersedia dalam pembaruan ini."
+ "Kami ingin mendengar dari Anda, beri tahu kami pendapat Anda melalui halaman pengaturan."
+ "Ayo!"
+ "Berikut adalah yang perlu Anda ketahui:"
+ "Selamat datang di %1$s!"
+
diff --git a/features/ftue/impl/src/test/kotlin/io/element/android/features/ftue/impl/notifications/NotificationsOptInPresenterTests.kt b/features/ftue/impl/src/test/kotlin/io/element/android/features/ftue/impl/notifications/NotificationsOptInPresenterTests.kt
index db71128efd..e5c4d37423 100644
--- a/features/ftue/impl/src/test/kotlin/io/element/android/features/ftue/impl/notifications/NotificationsOptInPresenterTests.kt
+++ b/features/ftue/impl/src/test/kotlin/io/element/android/features/ftue/impl/notifications/NotificationsOptInPresenterTests.kt
@@ -20,7 +20,7 @@ import android.os.Build
import app.cash.molecule.RecompositionMode
import app.cash.molecule.moleculeFlow
import app.cash.turbine.test
-import com.google.common.truth.Truth
+import com.google.common.truth.Truth.assertThat
import io.element.android.libraries.permissions.api.PermissionStateProvider
import io.element.android.libraries.permissions.api.PermissionsPresenter
import io.element.android.libraries.permissions.impl.FakePermissionStateProvider
@@ -52,7 +52,7 @@ class NotificationsOptInPresenterTests {
presenter.present()
}.test {
val initialState = awaitItem()
- Truth.assertThat(initialState.notificationsPermissionState.showDialog).isFalse()
+ assertThat(initialState.notificationsPermissionState.showDialog).isFalse()
}
}
@@ -65,7 +65,7 @@ class NotificationsOptInPresenterTests {
}.test {
val initialState = awaitItem()
initialState.eventSink(NotificationsOptInEvents.ContinueClicked)
- Truth.assertThat(awaitItem().notificationsPermissionState.showDialog).isTrue()
+ assertThat(awaitItem().notificationsPermissionState.showDialog).isTrue()
}
}
@@ -80,7 +80,7 @@ class NotificationsOptInPresenterTests {
}.test {
val initialState = awaitItem()
initialState.eventSink(NotificationsOptInEvents.ContinueClicked)
- Truth.assertThat(isFinished).isTrue()
+ assertThat(isFinished).isTrue()
}
}
@@ -96,7 +96,7 @@ class NotificationsOptInPresenterTests {
}.test {
val initialState = awaitItem()
initialState.eventSink(NotificationsOptInEvents.NotNowClicked)
- Truth.assertThat(isFinished).isTrue()
+ assertThat(isFinished).isTrue()
}
}
@@ -122,7 +122,7 @@ class NotificationsOptInPresenterTests {
val isPermissionDenied = runBlocking {
permissionStateProvider.isPermissionDenied("notifications").first()
}
- Truth.assertThat(isPermissionDenied).isTrue()
+ assertThat(isPermissionDenied).isTrue()
}
}
diff --git a/features/invitelist/impl/src/main/kotlin/io/element/android/features/invitelist/impl/model/InviteListInviteSummary.kt b/features/invitelist/impl/src/main/kotlin/io/element/android/features/invitelist/impl/model/InviteListInviteSummary.kt
index cb695d4eda..9f74b90142 100644
--- a/features/invitelist/impl/src/main/kotlin/io/element/android/features/invitelist/impl/model/InviteListInviteSummary.kt
+++ b/features/invitelist/impl/src/main/kotlin/io/element/android/features/invitelist/impl/model/InviteListInviteSummary.kt
@@ -33,7 +33,7 @@ data class InviteListInviteSummary(
val isNew: Boolean = false,
)
-data class InviteSender constructor(
+data class InviteSender(
val userId: UserId,
val displayName: String,
val avatarData: AvatarData = AvatarData(userId.value, displayName, size = AvatarSize.InviteSender),
diff --git a/features/invitelist/impl/src/main/res/values-hu/translations.xml b/features/invitelist/impl/src/main/res/values-hu/translations.xml
new file mode 100644
index 0000000000..e7faddd8f9
--- /dev/null
+++ b/features/invitelist/impl/src/main/res/values-hu/translations.xml
@@ -0,0 +1,9 @@
+
+
+ "Biztos, hogy elutasítja a meghívást, hogy csatlakozzon ehhez: %1$s?"
+ "Meghívás elutasítása"
+ "Biztos, hogy elutasítja ezt a privát csevegést vele: %1$s?"
+ "Csevegés elutasítása"
+ "Nincsenek meghívások"
+ "%1$s (%2$s) meghívta"
+
diff --git a/features/invitelist/impl/src/main/res/values-in/translations.xml b/features/invitelist/impl/src/main/res/values-in/translations.xml
new file mode 100644
index 0000000000..97866a9043
--- /dev/null
+++ b/features/invitelist/impl/src/main/res/values-in/translations.xml
@@ -0,0 +1,9 @@
+
+
+ "Apakah Anda yakin ingin menolak undangan untuk bergabung ke %1$s?"
+ "Tolak undangan"
+ "Apakah Anda yakin ingin menolak obrolan pribadi dengan %1$s?"
+ "Tolak obrolan"
+ "Tidak ada undangan"
+ "%1$s (%2$s) mengundang Anda"
+
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 ca0c73d53e..70908941a6 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
@@ -19,7 +19,7 @@ package io.element.android.features.invitelist.impl
import app.cash.molecule.RecompositionMode
import app.cash.molecule.moleculeFlow
import app.cash.turbine.test
-import com.google.common.truth.Truth
+import com.google.common.truth.Truth.assertThat
import io.element.android.features.invitelist.api.SeenInvitesStore
import io.element.android.features.invitelist.test.FakeSeenInvitesStore
import io.element.android.libraries.architecture.Async
@@ -63,14 +63,14 @@ class InviteListPresenterTests {
presenter.present()
}.test {
val initialState = awaitItem()
- Truth.assertThat(initialState.inviteList).isEmpty()
+ assertThat(initialState.inviteList).isEmpty()
roomListService.postInviteRooms(listOf(aRoomSummary()))
val withInviteState = awaitItem()
- Truth.assertThat(withInviteState.inviteList.size).isEqualTo(1)
- Truth.assertThat(withInviteState.inviteList[0].roomId).isEqualTo(A_ROOM_ID)
- Truth.assertThat(withInviteState.inviteList[0].roomName).isEqualTo(A_ROOM_NAME)
+ assertThat(withInviteState.inviteList.size).isEqualTo(1)
+ assertThat(withInviteState.inviteList[0].roomId).isEqualTo(A_ROOM_ID)
+ assertThat(withInviteState.inviteList[0].roomName).isEqualTo(A_ROOM_NAME)
}
}
@@ -84,11 +84,11 @@ class InviteListPresenterTests {
presenter.present()
}.test {
val withInviteState = awaitItem()
- Truth.assertThat(withInviteState.inviteList.size).isEqualTo(1)
- Truth.assertThat(withInviteState.inviteList[0].roomId).isEqualTo(A_ROOM_ID)
- Truth.assertThat(withInviteState.inviteList[0].roomAlias).isEqualTo(A_USER_ID.value)
- Truth.assertThat(withInviteState.inviteList[0].roomName).isEqualTo(A_ROOM_NAME)
- Truth.assertThat(withInviteState.inviteList[0].roomAvatarData).isEqualTo(
+ assertThat(withInviteState.inviteList.size).isEqualTo(1)
+ assertThat(withInviteState.inviteList[0].roomId).isEqualTo(A_ROOM_ID)
+ assertThat(withInviteState.inviteList[0].roomAlias).isEqualTo(A_USER_ID.value)
+ assertThat(withInviteState.inviteList[0].roomName).isEqualTo(A_ROOM_NAME)
+ assertThat(withInviteState.inviteList[0].roomAvatarData).isEqualTo(
AvatarData(
id = A_USER_ID.value,
name = A_USER_NAME,
@@ -96,7 +96,7 @@ class InviteListPresenterTests {
size = AvatarSize.RoomInviteItem,
)
)
- Truth.assertThat(withInviteState.inviteList[0].sender).isNull()
+ assertThat(withInviteState.inviteList[0].sender).isNull()
}
}
@@ -110,10 +110,10 @@ class InviteListPresenterTests {
presenter.present()
}.test {
val withInviteState = awaitItem()
- Truth.assertThat(withInviteState.inviteList.size).isEqualTo(1)
- Truth.assertThat(withInviteState.inviteList[0].sender?.displayName).isEqualTo(A_USER_NAME)
- Truth.assertThat(withInviteState.inviteList[0].sender?.userId).isEqualTo(A_USER_ID)
- Truth.assertThat(withInviteState.inviteList[0].sender?.avatarData).isEqualTo(
+ assertThat(withInviteState.inviteList.size).isEqualTo(1)
+ assertThat(withInviteState.inviteList[0].sender?.displayName).isEqualTo(A_USER_NAME)
+ assertThat(withInviteState.inviteList[0].sender?.userId).isEqualTo(A_USER_ID)
+ assertThat(withInviteState.inviteList[0].sender?.avatarData).isEqualTo(
AvatarData(
id = A_USER_ID.value,
name = A_USER_NAME,
@@ -142,11 +142,11 @@ class InviteListPresenterTests {
originalState.eventSink(InviteListEvents.DeclineInvite(originalState.inviteList[0]))
val newState = awaitItem()
- Truth.assertThat(newState.declineConfirmationDialog).isInstanceOf(InviteDeclineConfirmationDialog.Visible::class.java)
+ assertThat(newState.declineConfirmationDialog).isInstanceOf(InviteDeclineConfirmationDialog.Visible::class.java)
val confirmDialog = newState.declineConfirmationDialog as InviteDeclineConfirmationDialog.Visible
- Truth.assertThat(confirmDialog.isDirect).isTrue()
- Truth.assertThat(confirmDialog.name).isEqualTo(A_ROOM_NAME)
+ assertThat(confirmDialog.isDirect).isTrue()
+ assertThat(confirmDialog.name).isEqualTo(A_ROOM_NAME)
}
}
@@ -163,11 +163,11 @@ class InviteListPresenterTests {
originalState.eventSink(InviteListEvents.DeclineInvite(originalState.inviteList[0]))
val newState = awaitItem()
- Truth.assertThat(newState.declineConfirmationDialog).isInstanceOf(InviteDeclineConfirmationDialog.Visible::class.java)
+ assertThat(newState.declineConfirmationDialog).isInstanceOf(InviteDeclineConfirmationDialog.Visible::class.java)
val confirmDialog = newState.declineConfirmationDialog as InviteDeclineConfirmationDialog.Visible
- Truth.assertThat(confirmDialog.isDirect).isFalse()
- Truth.assertThat(confirmDialog.name).isEqualTo(A_ROOM_NAME)
+ assertThat(confirmDialog.isDirect).isFalse()
+ assertThat(confirmDialog.name).isEqualTo(A_ROOM_NAME)
}
}
@@ -188,7 +188,7 @@ class InviteListPresenterTests {
originalState.eventSink(InviteListEvents.CancelDeclineInvite)
val newState = awaitItem()
- Truth.assertThat(newState.declineConfirmationDialog).isInstanceOf(InviteDeclineConfirmationDialog.Hidden::class.java)
+ assertThat(newState.declineConfirmationDialog).isInstanceOf(InviteDeclineConfirmationDialog.Hidden::class.java)
}
}
@@ -215,7 +215,7 @@ class InviteListPresenterTests {
skipItems(2)
- Truth.assertThat(fakeNotificationDrawerManager.getClearMembershipNotificationForRoomCount(client.sessionId, A_ROOM_ID)).isEqualTo(1)
+ assertThat(fakeNotificationDrawerManager.getClearMembershipNotificationForRoomCount(client.sessionId, A_ROOM_ID)).isEqualTo(1)
}
}
@@ -245,7 +245,7 @@ class InviteListPresenterTests {
val newState = awaitItem()
- Truth.assertThat(newState.declinedAction).isEqualTo(Async.Failure(ex))
+ assertThat(newState.declinedAction).isEqualTo(Async.Failure(ex))
}
}
@@ -277,7 +277,7 @@ class InviteListPresenterTests {
val newState = awaitItem()
- Truth.assertThat(newState.declinedAction).isEqualTo(Async.Uninitialized)
+ assertThat(newState.declinedAction).isEqualTo(Async.Uninitialized)
}
}
@@ -300,8 +300,8 @@ class InviteListPresenterTests {
val newState = awaitItem()
- Truth.assertThat(newState.acceptedAction).isEqualTo(Async.Success(A_ROOM_ID))
- Truth.assertThat(fakeNotificationDrawerManager.getClearMembershipNotificationForRoomCount(client.sessionId, A_ROOM_ID)).isEqualTo(1)
+ assertThat(newState.acceptedAction).isEqualTo(Async.Success(A_ROOM_ID))
+ assertThat(fakeNotificationDrawerManager.getClearMembershipNotificationForRoomCount(client.sessionId, A_ROOM_ID)).isEqualTo(1)
}
}
@@ -323,7 +323,7 @@ class InviteListPresenterTests {
val originalState = awaitItem()
originalState.eventSink(InviteListEvents.AcceptInvite(originalState.inviteList[0]))
- Truth.assertThat(awaitItem().acceptedAction).isEqualTo(Async.Failure(ex))
+ assertThat(awaitItem().acceptedAction).isEqualTo(Async.Failure(ex))
}
}
@@ -350,7 +350,7 @@ class InviteListPresenterTests {
originalState.eventSink(InviteListEvents.DismissAcceptError)
val newState = awaitItem()
- Truth.assertThat(newState.acceptedAction).isEqualTo(Async.Uninitialized)
+ assertThat(newState.acceptedAction).isEqualTo(Async.Uninitialized)
}
}
@@ -375,19 +375,19 @@ class InviteListPresenterTests {
roomListService.postInviteRooms(listOf(aRoomSummary()))
awaitItem()
- Truth.assertThat(store.getProvidedRoomIds()).isEqualTo(setOf(A_ROOM_ID))
+ assertThat(store.getProvidedRoomIds()).isEqualTo(setOf(A_ROOM_ID))
// When a second is added, both are saved
roomListService.postInviteRooms(listOf(aRoomSummary(), aRoomSummary(A_ROOM_ID_2)))
awaitItem()
- Truth.assertThat(store.getProvidedRoomIds()).isEqualTo(setOf(A_ROOM_ID, A_ROOM_ID_2))
+ assertThat(store.getProvidedRoomIds()).isEqualTo(setOf(A_ROOM_ID, A_ROOM_ID_2))
// When they're both dismissed, an empty set is saved
roomListService.postInviteRooms(listOf())
awaitItem()
- Truth.assertThat(store.getProvidedRoomIds()).isEmpty()
+ assertThat(store.getProvidedRoomIds()).isEmpty()
}
}
@@ -413,11 +413,11 @@ class InviteListPresenterTests {
skipItems(1)
val withInviteState = awaitItem()
- Truth.assertThat(withInviteState.inviteList.size).isEqualTo(2)
- Truth.assertThat(withInviteState.inviteList[0].roomId).isEqualTo(A_ROOM_ID)
- Truth.assertThat(withInviteState.inviteList[0].isNew).isFalse()
- Truth.assertThat(withInviteState.inviteList[1].roomId).isEqualTo(A_ROOM_ID_2)
- Truth.assertThat(withInviteState.inviteList[1].isNew).isTrue()
+ assertThat(withInviteState.inviteList.size).isEqualTo(2)
+ assertThat(withInviteState.inviteList[0].roomId).isEqualTo(A_ROOM_ID)
+ assertThat(withInviteState.inviteList[0].isNew).isFalse()
+ assertThat(withInviteState.inviteList[1].roomId).isEqualTo(A_ROOM_ID_2)
+ assertThat(withInviteState.inviteList[1].isNew).isTrue()
}
}
diff --git a/features/leaveroom/api/src/main/res/values-hu/translations.xml b/features/leaveroom/api/src/main/res/values-hu/translations.xml
new file mode 100644
index 0000000000..824c088cdb
--- /dev/null
+++ b/features/leaveroom/api/src/main/res/values-hu/translations.xml
@@ -0,0 +1,6 @@
+
+
+ "Biztos, hogy elhagyja ezt a szobát? Ön az egyedüli ember itt. Ha kilép, akkor senki sem fog tudni csatlakozni a jövőben, Önt is beleértve."
+ "Biztos, hogy elhagyja ezt a szobát? Ez a szoba nem nyilvános, és meghívó nélkül nem fog tudni újra belépni."
+ "Biztos, hogy elhagyja a szobát?"
+
diff --git a/features/leaveroom/api/src/main/res/values-in/translations.xml b/features/leaveroom/api/src/main/res/values-in/translations.xml
new file mode 100644
index 0000000000..682da2d6a1
--- /dev/null
+++ b/features/leaveroom/api/src/main/res/values-in/translations.xml
@@ -0,0 +1,6 @@
+
+
+ "Apakah Anda yakin ingin meninggalkan ruangan ini? Anda adalah orang satu-satunya di sini. Jika Anda pergi, tidak akan ada yang bisa bergabung di masa depan, termasuk Anda."
+ "Apakah Anda yakin ingin meninggalkan ruangan ini? Ruangan ini tidak umum dan Anda tidak akan dapat bergabung kembali tanpa undangan."
+ "Apakah Anda yakin ingin meninggalkan ruangan?"
+
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 5b06090117..cfa52c4269 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
@@ -19,7 +19,7 @@ package io.element.android.features.location.impl.send
import app.cash.molecule.RecompositionMode
import app.cash.molecule.moleculeFlow
import app.cash.turbine.test
-import com.google.common.truth.Truth
+import com.google.common.truth.Truth.assertThat
import im.vector.app.features.analytics.plan.Composer
import io.element.android.features.location.api.Location
import io.element.android.features.location.impl.aPermissionsState
@@ -77,16 +77,16 @@ class SendLocationPresenterTest {
}.test {
val initialState = awaitItem()
- Truth.assertThat(initialState.permissionDialog).isEqualTo(SendLocationState.Dialog.None)
- Truth.assertThat(initialState.mode).isEqualTo(SendLocationState.Mode.SenderLocation)
- Truth.assertThat(initialState.hasLocationPermission).isEqualTo(true)
+ assertThat(initialState.permissionDialog).isEqualTo(SendLocationState.Dialog.None)
+ assertThat(initialState.mode).isEqualTo(SendLocationState.Mode.SenderLocation)
+ assertThat(initialState.hasLocationPermission).isTrue()
// Swipe the map to switch mode
initialState.eventSink(SendLocationEvents.SwitchToPinLocationMode)
val myLocationState = awaitItem()
- Truth.assertThat(myLocationState.permissionDialog).isEqualTo(SendLocationState.Dialog.None)
- Truth.assertThat(myLocationState.mode).isEqualTo(SendLocationState.Mode.PinLocation)
- Truth.assertThat(myLocationState.hasLocationPermission).isEqualTo(true)
+ assertThat(myLocationState.permissionDialog).isEqualTo(SendLocationState.Dialog.None)
+ assertThat(myLocationState.mode).isEqualTo(SendLocationState.Mode.PinLocation)
+ assertThat(myLocationState.hasLocationPermission).isTrue()
}
}
@@ -104,16 +104,16 @@ class SendLocationPresenterTest {
}.test {
val initialState = awaitItem()
- Truth.assertThat(initialState.permissionDialog).isEqualTo(SendLocationState.Dialog.None)
- Truth.assertThat(initialState.mode).isEqualTo(SendLocationState.Mode.SenderLocation)
- Truth.assertThat(initialState.hasLocationPermission).isEqualTo(true)
+ assertThat(initialState.permissionDialog).isEqualTo(SendLocationState.Dialog.None)
+ assertThat(initialState.mode).isEqualTo(SendLocationState.Mode.SenderLocation)
+ assertThat(initialState.hasLocationPermission).isTrue()
// Swipe the map to switch mode
initialState.eventSink(SendLocationEvents.SwitchToPinLocationMode)
val myLocationState = awaitItem()
- Truth.assertThat(myLocationState.permissionDialog).isEqualTo(SendLocationState.Dialog.None)
- Truth.assertThat(myLocationState.mode).isEqualTo(SendLocationState.Mode.PinLocation)
- Truth.assertThat(myLocationState.hasLocationPermission).isEqualTo(true)
+ assertThat(myLocationState.permissionDialog).isEqualTo(SendLocationState.Dialog.None)
+ assertThat(myLocationState.mode).isEqualTo(SendLocationState.Mode.PinLocation)
+ assertThat(myLocationState.hasLocationPermission).isTrue()
}
}
@@ -130,16 +130,16 @@ class SendLocationPresenterTest {
sendLocationPresenter.present()
}.test {
val initialState = awaitItem()
- Truth.assertThat(initialState.permissionDialog).isEqualTo(SendLocationState.Dialog.None)
- Truth.assertThat(initialState.mode).isEqualTo(SendLocationState.Mode.PinLocation)
- Truth.assertThat(initialState.hasLocationPermission).isEqualTo(false)
+ assertThat(initialState.permissionDialog).isEqualTo(SendLocationState.Dialog.None)
+ assertThat(initialState.mode).isEqualTo(SendLocationState.Mode.PinLocation)
+ assertThat(initialState.hasLocationPermission).isFalse()
// Click on the button to switch mode
initialState.eventSink(SendLocationEvents.SwitchToMyLocationMode)
val myLocationState = awaitItem()
- Truth.assertThat(myLocationState.permissionDialog).isEqualTo(SendLocationState.Dialog.PermissionDenied)
- Truth.assertThat(myLocationState.mode).isEqualTo(SendLocationState.Mode.PinLocation)
- Truth.assertThat(myLocationState.hasLocationPermission).isEqualTo(false)
+ assertThat(myLocationState.permissionDialog).isEqualTo(SendLocationState.Dialog.PermissionDenied)
+ assertThat(myLocationState.mode).isEqualTo(SendLocationState.Mode.PinLocation)
+ assertThat(myLocationState.hasLocationPermission).isFalse()
}
}
@@ -156,16 +156,16 @@ class SendLocationPresenterTest {
sendLocationPresenter.present()
}.test {
val initialState = awaitItem()
- Truth.assertThat(initialState.permissionDialog).isEqualTo(SendLocationState.Dialog.None)
- Truth.assertThat(initialState.mode).isEqualTo(SendLocationState.Mode.PinLocation)
- Truth.assertThat(initialState.hasLocationPermission).isEqualTo(false)
+ assertThat(initialState.permissionDialog).isEqualTo(SendLocationState.Dialog.None)
+ assertThat(initialState.mode).isEqualTo(SendLocationState.Mode.PinLocation)
+ assertThat(initialState.hasLocationPermission).isFalse()
// Click on the button to switch mode
initialState.eventSink(SendLocationEvents.SwitchToMyLocationMode)
val myLocationState = awaitItem()
- Truth.assertThat(myLocationState.permissionDialog).isEqualTo(SendLocationState.Dialog.PermissionRationale)
- Truth.assertThat(myLocationState.mode).isEqualTo(SendLocationState.Mode.PinLocation)
- Truth.assertThat(myLocationState.hasLocationPermission).isEqualTo(false)
+ assertThat(myLocationState.permissionDialog).isEqualTo(SendLocationState.Dialog.PermissionRationale)
+ assertThat(myLocationState.mode).isEqualTo(SendLocationState.Mode.PinLocation)
+ assertThat(myLocationState.hasLocationPermission).isFalse()
}
}
@@ -187,16 +187,16 @@ class SendLocationPresenterTest {
// Click on the button to switch mode
initialState.eventSink(SendLocationEvents.SwitchToMyLocationMode)
val myLocationState = awaitItem()
- Truth.assertThat(myLocationState.permissionDialog).isEqualTo(SendLocationState.Dialog.PermissionRationale)
- Truth.assertThat(myLocationState.mode).isEqualTo(SendLocationState.Mode.PinLocation)
- Truth.assertThat(myLocationState.hasLocationPermission).isEqualTo(false)
+ assertThat(myLocationState.permissionDialog).isEqualTo(SendLocationState.Dialog.PermissionRationale)
+ assertThat(myLocationState.mode).isEqualTo(SendLocationState.Mode.PinLocation)
+ assertThat(myLocationState.hasLocationPermission).isFalse()
// Dismiss the dialog
myLocationState.eventSink(SendLocationEvents.DismissDialog)
val dialogDismissedState = awaitItem()
- Truth.assertThat(dialogDismissedState.permissionDialog).isEqualTo(SendLocationState.Dialog.None)
- Truth.assertThat(dialogDismissedState.mode).isEqualTo(SendLocationState.Mode.PinLocation)
- Truth.assertThat(dialogDismissedState.hasLocationPermission).isEqualTo(false)
+ assertThat(dialogDismissedState.permissionDialog).isEqualTo(SendLocationState.Dialog.None)
+ assertThat(dialogDismissedState.mode).isEqualTo(SendLocationState.Mode.PinLocation)
+ assertThat(dialogDismissedState.hasLocationPermission).isFalse()
}
}
@@ -218,13 +218,13 @@ class SendLocationPresenterTest {
// Click on the button to switch mode
initialState.eventSink(SendLocationEvents.SwitchToMyLocationMode)
val myLocationState = awaitItem()
- Truth.assertThat(myLocationState.permissionDialog).isEqualTo(SendLocationState.Dialog.PermissionRationale)
- Truth.assertThat(myLocationState.mode).isEqualTo(SendLocationState.Mode.PinLocation)
- Truth.assertThat(myLocationState.hasLocationPermission).isEqualTo(false)
+ assertThat(myLocationState.permissionDialog).isEqualTo(SendLocationState.Dialog.PermissionRationale)
+ assertThat(myLocationState.mode).isEqualTo(SendLocationState.Mode.PinLocation)
+ assertThat(myLocationState.hasLocationPermission).isFalse()
// Continue the dialog sends permission request to the permissions presenter
myLocationState.eventSink(SendLocationEvents.RequestPermissions)
- Truth.assertThat(permissionsPresenterFake.events.last()).isEqualTo(PermissionsEvents.RequestPermissions)
+ assertThat(permissionsPresenterFake.events.last()).isEqualTo(PermissionsEvents.RequestPermissions)
}
}
@@ -246,16 +246,16 @@ class SendLocationPresenterTest {
// Click on the button to switch mode
initialState.eventSink(SendLocationEvents.SwitchToMyLocationMode)
val myLocationState = awaitItem()
- Truth.assertThat(myLocationState.permissionDialog).isEqualTo(SendLocationState.Dialog.PermissionDenied)
- Truth.assertThat(myLocationState.mode).isEqualTo(SendLocationState.Mode.PinLocation)
- Truth.assertThat(myLocationState.hasLocationPermission).isEqualTo(false)
+ assertThat(myLocationState.permissionDialog).isEqualTo(SendLocationState.Dialog.PermissionDenied)
+ assertThat(myLocationState.mode).isEqualTo(SendLocationState.Mode.PinLocation)
+ assertThat(myLocationState.hasLocationPermission).isFalse()
// Dismiss the dialog
myLocationState.eventSink(SendLocationEvents.DismissDialog)
val dialogDismissedState = awaitItem()
- Truth.assertThat(dialogDismissedState.permissionDialog).isEqualTo(SendLocationState.Dialog.None)
- Truth.assertThat(dialogDismissedState.mode).isEqualTo(SendLocationState.Mode.PinLocation)
- Truth.assertThat(dialogDismissedState.hasLocationPermission).isEqualTo(false)
+ assertThat(dialogDismissedState.permissionDialog).isEqualTo(SendLocationState.Dialog.None)
+ assertThat(dialogDismissedState.mode).isEqualTo(SendLocationState.Mode.PinLocation)
+ assertThat(dialogDismissedState.hasLocationPermission).isFalse()
}
}
@@ -292,8 +292,8 @@ class SendLocationPresenterTest {
delay(1) // Wait for the coroutine to finish
- Truth.assertThat(fakeMatrixRoom.sentLocations.size).isEqualTo(1)
- Truth.assertThat(fakeMatrixRoom.sentLocations.last()).isEqualTo(
+ assertThat(fakeMatrixRoom.sentLocations.size).isEqualTo(1)
+ assertThat(fakeMatrixRoom.sentLocations.last()).isEqualTo(
SendLocationInvocation(
body = "Location was shared at geo:3.0,4.0;u=5.0",
geoUri = "geo:3.0,4.0;u=5.0",
@@ -303,8 +303,8 @@ class SendLocationPresenterTest {
)
)
- Truth.assertThat(fakeAnalyticsService.capturedEvents.size).isEqualTo(1)
- Truth.assertThat(fakeAnalyticsService.capturedEvents.last()).isEqualTo(
+ assertThat(fakeAnalyticsService.capturedEvents.size).isEqualTo(1)
+ assertThat(fakeAnalyticsService.capturedEvents.last()).isEqualTo(
Composer(
inThread = false,
isEditing = false,
@@ -348,8 +348,8 @@ class SendLocationPresenterTest {
delay(1) // Wait for the coroutine to finish
- Truth.assertThat(fakeMatrixRoom.sentLocations.size).isEqualTo(1)
- Truth.assertThat(fakeMatrixRoom.sentLocations.last()).isEqualTo(
+ assertThat(fakeMatrixRoom.sentLocations.size).isEqualTo(1)
+ assertThat(fakeMatrixRoom.sentLocations.last()).isEqualTo(
SendLocationInvocation(
body = "Location was shared at geo:0.0,1.0",
geoUri = "geo:0.0,1.0",
@@ -359,8 +359,8 @@ class SendLocationPresenterTest {
)
)
- Truth.assertThat(fakeAnalyticsService.capturedEvents.size).isEqualTo(1)
- Truth.assertThat(fakeAnalyticsService.capturedEvents.last()).isEqualTo(
+ assertThat(fakeAnalyticsService.capturedEvents.size).isEqualTo(1)
+ assertThat(fakeAnalyticsService.capturedEvents.last()).isEqualTo(
Composer(
inThread = false,
isEditing = false,
@@ -405,8 +405,8 @@ class SendLocationPresenterTest {
delay(1) // Wait for the coroutine to finish
- Truth.assertThat(fakeAnalyticsService.capturedEvents.size).isEqualTo(1)
- Truth.assertThat(fakeAnalyticsService.capturedEvents.last()).isEqualTo(
+ assertThat(fakeAnalyticsService.capturedEvents.size).isEqualTo(1)
+ assertThat(fakeAnalyticsService.capturedEvents.last()).isEqualTo(
Composer(
inThread = false,
isEditing = true,
@@ -444,8 +444,8 @@ class SendLocationPresenterTest {
dialogShownState.eventSink(SendLocationEvents.OpenAppSettings)
val settingsOpenedState = awaitItem()
- Truth.assertThat(settingsOpenedState.permissionDialog).isEqualTo(SendLocationState.Dialog.None)
- Truth.assertThat(fakeLocationActions.openSettingsInvocationsCount).isEqualTo(1)
+ assertThat(settingsOpenedState.permissionDialog).isEqualTo(SendLocationState.Dialog.None)
+ assertThat(fakeLocationActions.openSettingsInvocationsCount).isEqualTo(1)
}
}
@@ -455,7 +455,7 @@ class SendLocationPresenterTest {
sendLocationPresenter.present()
}.test {
val initialState = awaitItem()
- Truth.assertThat(initialState.appName).isEqualTo("app name")
+ assertThat(initialState.appName).isEqualTo("app name")
}
}
}
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 28beb77819..4db3755fbd 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
@@ -19,7 +19,7 @@ package io.element.android.features.location.impl.show
import app.cash.molecule.RecompositionMode
import app.cash.molecule.moleculeFlow
import app.cash.turbine.test
-import com.google.common.truth.Truth
+import com.google.common.truth.Truth.assertThat
import io.element.android.features.location.api.Location
import io.element.android.features.location.impl.aPermissionsState
import io.element.android.features.location.impl.common.actions.FakeLocationActions
@@ -66,10 +66,10 @@ class ShowLocationPresenterTest {
presenter.present()
}.test {
val initialState = awaitItem()
- Truth.assertThat(initialState.location).isEqualTo(location)
- Truth.assertThat(initialState.description).isEqualTo(A_DESCRIPTION)
- Truth.assertThat(initialState.hasLocationPermission).isEqualTo(false)
- Truth.assertThat(initialState.isTrackMyLocation).isEqualTo(false)
+ assertThat(initialState.location).isEqualTo(location)
+ assertThat(initialState.description).isEqualTo(A_DESCRIPTION)
+ assertThat(initialState.hasLocationPermission).isFalse()
+ assertThat(initialState.isTrackMyLocation).isFalse()
}
}
@@ -86,10 +86,10 @@ class ShowLocationPresenterTest {
presenter.present()
}.test {
val initialState = awaitItem()
- Truth.assertThat(initialState.location).isEqualTo(location)
- Truth.assertThat(initialState.description).isEqualTo(A_DESCRIPTION)
- Truth.assertThat(initialState.hasLocationPermission).isEqualTo(false)
- Truth.assertThat(initialState.isTrackMyLocation).isEqualTo(false)
+ assertThat(initialState.location).isEqualTo(location)
+ assertThat(initialState.description).isEqualTo(A_DESCRIPTION)
+ assertThat(initialState.hasLocationPermission).isFalse()
+ assertThat(initialState.isTrackMyLocation).isFalse()
}
}
@@ -101,10 +101,10 @@ class ShowLocationPresenterTest {
presenter.present()
}.test {
val initialState = awaitItem()
- Truth.assertThat(initialState.location).isEqualTo(location)
- Truth.assertThat(initialState.description).isEqualTo(A_DESCRIPTION)
- Truth.assertThat(initialState.hasLocationPermission).isEqualTo(true)
- Truth.assertThat(initialState.isTrackMyLocation).isEqualTo(false)
+ assertThat(initialState.location).isEqualTo(location)
+ assertThat(initialState.description).isEqualTo(A_DESCRIPTION)
+ assertThat(initialState.hasLocationPermission).isTrue()
+ assertThat(initialState.isTrackMyLocation).isFalse()
}
}
@@ -116,10 +116,10 @@ class ShowLocationPresenterTest {
presenter.present()
}.test {
val initialState = awaitItem()
- Truth.assertThat(initialState.location).isEqualTo(location)
- Truth.assertThat(initialState.description).isEqualTo(A_DESCRIPTION)
- Truth.assertThat(initialState.hasLocationPermission).isEqualTo(true)
- Truth.assertThat(initialState.isTrackMyLocation).isEqualTo(false)
+ assertThat(initialState.location).isEqualTo(location)
+ assertThat(initialState.description).isEqualTo(A_DESCRIPTION)
+ assertThat(initialState.hasLocationPermission).isTrue()
+ assertThat(initialState.isTrackMyLocation).isFalse()
}
}
@@ -131,8 +131,8 @@ class ShowLocationPresenterTest {
val initialState = awaitItem()
initialState.eventSink(ShowLocationEvents.Share)
- Truth.assertThat(fakeLocationActions.sharedLocation).isEqualTo(location)
- Truth.assertThat(fakeLocationActions.sharedLabel).isEqualTo(A_DESCRIPTION)
+ assertThat(fakeLocationActions.sharedLocation).isEqualTo(location)
+ assertThat(fakeLocationActions.sharedLabel).isEqualTo(A_DESCRIPTION)
}
}
@@ -144,23 +144,23 @@ class ShowLocationPresenterTest {
presenter.present()
}.test {
val initialState = awaitItem()
- Truth.assertThat(initialState.hasLocationPermission).isEqualTo(true)
- Truth.assertThat(initialState.isTrackMyLocation).isEqualTo(false)
+ assertThat(initialState.hasLocationPermission).isTrue()
+ assertThat(initialState.isTrackMyLocation).isFalse()
initialState.eventSink(ShowLocationEvents.TrackMyLocation(true))
val trackMyLocationState = awaitItem()
delay(1)
- Truth.assertThat(trackMyLocationState.hasLocationPermission).isEqualTo(true)
- Truth.assertThat(trackMyLocationState.isTrackMyLocation).isEqualTo(true)
+ assertThat(trackMyLocationState.hasLocationPermission).isTrue()
+ assertThat(trackMyLocationState.isTrackMyLocation).isTrue()
// Swipe the map to switch mode
initialState.eventSink(ShowLocationEvents.TrackMyLocation(false))
val trackLocationDisabledState = awaitItem()
- Truth.assertThat(trackLocationDisabledState.permissionDialog).isEqualTo(ShowLocationState.Dialog.None)
- Truth.assertThat(trackLocationDisabledState.isTrackMyLocation).isEqualTo(false)
- Truth.assertThat(trackLocationDisabledState.hasLocationPermission).isEqualTo(true)
+ assertThat(trackLocationDisabledState.permissionDialog).isEqualTo(ShowLocationState.Dialog.None)
+ assertThat(trackLocationDisabledState.isTrackMyLocation).isFalse()
+ assertThat(trackLocationDisabledState.hasLocationPermission).isTrue()
}
}
@@ -182,16 +182,16 @@ class ShowLocationPresenterTest {
// Click on the button to switch mode
initialState.eventSink(ShowLocationEvents.TrackMyLocation(true))
val trackLocationState = awaitItem()
- Truth.assertThat(trackLocationState.permissionDialog).isEqualTo(ShowLocationState.Dialog.PermissionRationale)
- Truth.assertThat(trackLocationState.isTrackMyLocation).isEqualTo(false)
- Truth.assertThat(trackLocationState.hasLocationPermission).isEqualTo(false)
+ assertThat(trackLocationState.permissionDialog).isEqualTo(ShowLocationState.Dialog.PermissionRationale)
+ assertThat(trackLocationState.isTrackMyLocation).isFalse()
+ assertThat(trackLocationState.hasLocationPermission).isFalse()
// Dismiss the dialog
initialState.eventSink(ShowLocationEvents.DismissDialog)
val dialogDismissedState = awaitItem()
- Truth.assertThat(dialogDismissedState.permissionDialog).isEqualTo(ShowLocationState.Dialog.None)
- Truth.assertThat(dialogDismissedState.isTrackMyLocation).isEqualTo(false)
- Truth.assertThat(dialogDismissedState.hasLocationPermission).isEqualTo(false)
+ assertThat(dialogDismissedState.permissionDialog).isEqualTo(ShowLocationState.Dialog.None)
+ assertThat(dialogDismissedState.isTrackMyLocation).isFalse()
+ assertThat(dialogDismissedState.hasLocationPermission).isFalse()
}
}
@@ -213,13 +213,13 @@ class ShowLocationPresenterTest {
// Click on the button to switch mode
initialState.eventSink(ShowLocationEvents.TrackMyLocation(true))
val trackLocationState = awaitItem()
- Truth.assertThat(trackLocationState.permissionDialog).isEqualTo(ShowLocationState.Dialog.PermissionRationale)
- Truth.assertThat(trackLocationState.isTrackMyLocation).isEqualTo(false)
- Truth.assertThat(trackLocationState.hasLocationPermission).isEqualTo(false)
+ assertThat(trackLocationState.permissionDialog).isEqualTo(ShowLocationState.Dialog.PermissionRationale)
+ assertThat(trackLocationState.isTrackMyLocation).isFalse()
+ assertThat(trackLocationState.hasLocationPermission).isFalse()
// Continue the dialog sends permission request to the permissions presenter
trackLocationState.eventSink(ShowLocationEvents.RequestPermissions)
- Truth.assertThat(permissionsPresenterFake.events.last()).isEqualTo(PermissionsEvents.RequestPermissions)
+ assertThat(permissionsPresenterFake.events.last()).isEqualTo(PermissionsEvents.RequestPermissions)
}
}
@@ -241,16 +241,16 @@ class ShowLocationPresenterTest {
// Click on the button to switch mode
initialState.eventSink(ShowLocationEvents.TrackMyLocation(true))
val trackLocationState = awaitItem()
- Truth.assertThat(trackLocationState.permissionDialog).isEqualTo(ShowLocationState.Dialog.PermissionDenied)
- Truth.assertThat(trackLocationState.isTrackMyLocation).isEqualTo(false)
- Truth.assertThat(trackLocationState.hasLocationPermission).isEqualTo(false)
+ assertThat(trackLocationState.permissionDialog).isEqualTo(ShowLocationState.Dialog.PermissionDenied)
+ assertThat(trackLocationState.isTrackMyLocation).isFalse()
+ assertThat(trackLocationState.hasLocationPermission).isFalse()
// Dismiss the dialog
initialState.eventSink(ShowLocationEvents.DismissDialog)
val dialogDismissedState = awaitItem()
- Truth.assertThat(dialogDismissedState.permissionDialog).isEqualTo(ShowLocationState.Dialog.None)
- Truth.assertThat(dialogDismissedState.isTrackMyLocation).isEqualTo(false)
- Truth.assertThat(dialogDismissedState.hasLocationPermission).isEqualTo(false)
+ assertThat(dialogDismissedState.permissionDialog).isEqualTo(ShowLocationState.Dialog.None)
+ assertThat(dialogDismissedState.isTrackMyLocation).isFalse()
+ assertThat(dialogDismissedState.hasLocationPermission).isFalse()
}
}
@@ -276,8 +276,8 @@ class ShowLocationPresenterTest {
dialogShownState.eventSink(ShowLocationEvents.OpenAppSettings)
val settingsOpenedState = awaitItem()
- Truth.assertThat(settingsOpenedState.permissionDialog).isEqualTo(ShowLocationState.Dialog.None)
- Truth.assertThat(fakeLocationActions.openSettingsInvocationsCount).isEqualTo(1)
+ assertThat(settingsOpenedState.permissionDialog).isEqualTo(ShowLocationState.Dialog.None)
+ assertThat(fakeLocationActions.openSettingsInvocationsCount).isEqualTo(1)
}
}
@@ -287,7 +287,7 @@ class ShowLocationPresenterTest {
presenter.present()
}.test {
val initialState = awaitItem()
- Truth.assertThat(initialState.appName).isEqualTo("app name")
+ assertThat(initialState.appName).isEqualTo("app name")
}
}
diff --git a/features/lockscreen/impl/src/main/res/values-de/translations.xml b/features/lockscreen/impl/src/main/res/values-de/translations.xml
index 9491e2e1a0..e4ea07f578 100644
--- a/features/lockscreen/impl/src/main/res/values-de/translations.xml
+++ b/features/lockscreen/impl/src/main/res/values-de/translations.xml
@@ -1,4 +1,37 @@
+
+ - "Du hast %1$d Versuch zu entsperren"
+ - "Du hast %1$d Versuche zum Entsperren"
+
+
+ - "Falsche PIN. Du hast %1$d weitere Chance"
+ - "Falsche PIN. Du hast %1$d weitere Chancen"
+
+ "biometrische Authentifizierung"
+ "biometrisches Entsperren"
+ "Mit Biometrie entsperren"
+ "PIN vergessen?"
+ "PIN-Code ändern"
+ "Biometrisches Entsperren zulassen"
+ "Pin entfernen"
+ "Bist du sicher, dass du die PIN entfernen willst?"
+ "PIN entfernen?"
+ "%1$s zulassen"
+ "Ich verwende lieber die PIN"
+ "Spare dir etwas Zeit und benutze %1$s, um die App jedes Mal zu entsperren"
+ "PIN wählen"
+ "PIN bestätigen"
+ "Aus Sicherheitsgründen kannst du das nicht als deinen PIN-Code wählen"
+ "Wähle eine andere PIN"
+ "Sperre %1$s, um deine Chats noch sicherer zu machen.
+
+Wähle etwas Einprägsames. Wenn du diese PIN vergisst, wirst du aus der App ausgeloggt."
+ "Bitte gib die gleiche PIN zweimal ein"
+ "Die PINs stimmen nicht überein"
+ "Um fortzufahren, musst du dich erneut anmelden und eine neue PIN erstellen"
+ "Du wirst abgemeldet"
+ "Biometrie verwenden"
+ "PIN verwenden"
"Abmelden…"
diff --git a/features/lockscreen/impl/src/main/res/values-hu/translations.xml b/features/lockscreen/impl/src/main/res/values-hu/translations.xml
new file mode 100644
index 0000000000..5f456e7ff2
--- /dev/null
+++ b/features/lockscreen/impl/src/main/res/values-hu/translations.xml
@@ -0,0 +1,37 @@
+
+
+
+ - "%1$d próbálkozása van a feloldáshoz"
+ - "%1$d próbálkozása van a feloldáshoz"
+
+
+ - "Hibás PIN-kód. Még %1$d próbálkozási lehetősége maradt."
+ - "Hibás PIN-kód. Még %1$d próbálkozási lehetősége maradt."
+
+ "biometrikus hitelesítés"
+ "biometrikus feloldás"
+ "Feloldás biometrikus adatokkal"
+ "Elfelejtette a PIN-kódot?"
+ "PIN-kód módosítása"
+ "Biometrikus feloldás engedélyezése"
+ "PIN-kód eltávolítása"
+ "Biztos, hogy eltávolítja a PIN-kódot?"
+ "PIN-kód eltávolítása?"
+ "A %1$s engedélyezése"
+ "Inkább PIN-kód használata"
+ "Spóroljon meg némi időt, és használja a %1$st az alkalmazás feloldásához"
+ "PIN-kód kiválasztása"
+ "PIN-kód megerősítése"
+ "Ezt biztonsági okokból nem választhatja PIN-kódként"
+ "Válasszon egy másik PIN-kódot"
+ "Az %1$s zárolása a csevegései nagyobb biztonsága érdekében.
+
+Válasszon valami megjegyezhetőt. Ha elfelejti a PIN-kódot, akkor ki lesz jelentkeztetve az alkalmazásból."
+ "Adja meg a PIN-kódját kétszer"
+ "A PIN-kódok nem egyeznek"
+ "A folytatáshoz újra be kell jelentkeznie, és létre kell hoznia egy új PIN-kódot"
+ "Kijelentkeztetésre kerül"
+ "Biometrikus adatok használata"
+ "PIN-kód használata"
+ "Kijelentkezés…"
+
diff --git a/features/lockscreen/impl/src/main/res/values-in/translations.xml b/features/lockscreen/impl/src/main/res/values-in/translations.xml
new file mode 100644
index 0000000000..a82fff5621
--- /dev/null
+++ b/features/lockscreen/impl/src/main/res/values-in/translations.xml
@@ -0,0 +1,35 @@
+
+
+
+ - "Anda memiliki %1$d percobaan lagi untuk membuka kunci"
+
+
+ - "PIN salah. Anda memiliki %1$d percobaan lagi"
+
+ "autentikasi biometrik"
+ "pembukaan biometrik"
+ "Buka kunci dengan biometrik"
+ "Lupa PIN?"
+ "Ubah kode PIN"
+ "Perbolehkan pembukaan biometrik"
+ "Hapus PIN"
+ "Apakah Anda yakin ingin menghapus PIN?"
+ "Hapus PIN?"
+ "Perbolehkan %1$s"
+ "Saya lebih suka menggunakan PIN"
+ "Hemat waktu Anda dan gunakan %1$s untuk membuka kunci aplikasi setiap kalinya"
+ "Pilih PIN"
+ "Konfirmasi PIN"
+ "Anda tidak dapat memilih PIN ini demi keamanan"
+ "Pilih PIN yang lain"
+ "Kunci %1$s untuk menambahkan keamanan tambahan pada percakapan Anda.
+
+Pilih sesuatu yang mudah untuk diingat. Jika Anda lupa PIN ini, Anda akan dikeluarkan dari aplikasi."
+ "Silakan masukkan PIN yang sama dua kali"
+ "PIN tidak cocok"
+ "Anda harus masuk ulang dan membuat PIN baru untuk melanjutkan"
+ "Anda sedang dikeluarkan"
+ "Gunakan biometrik"
+ "Gunakan PIN"
+ "Mengeluarkan dari akun…"
+
diff --git a/features/lockscreen/impl/src/test/kotlin/io/element/android/features/lockscreen/impl/unlock/PinUnlockPresenterTest.kt b/features/lockscreen/impl/src/test/kotlin/io/element/android/features/lockscreen/impl/unlock/PinUnlockPresenterTest.kt
index 021f0132a2..87d673066d 100644
--- a/features/lockscreen/impl/src/test/kotlin/io/element/android/features/lockscreen/impl/unlock/PinUnlockPresenterTest.kt
+++ b/features/lockscreen/impl/src/test/kotlin/io/element/android/features/lockscreen/impl/unlock/PinUnlockPresenterTest.kt
@@ -94,8 +94,8 @@ class PinUnlockPresenterTest {
}
awaitLastSequentialItem().also { state ->
assertThat(state.remainingAttempts.dataOrNull()).isEqualTo(0)
- assertThat(state.showSignOutPrompt).isEqualTo(true)
- assertThat(state.isSignOutPromptCancellable).isEqualTo(false)
+ assertThat(state.showSignOutPrompt).isTrue()
+ assertThat(state.isSignOutPromptCancellable).isFalse()
}
}
}
@@ -112,16 +112,16 @@ class PinUnlockPresenterTest {
state.eventSink(PinUnlockEvents.OnForgetPin)
}
awaitLastSequentialItem().also { state ->
- assertThat(state.showSignOutPrompt).isEqualTo(true)
- assertThat(state.isSignOutPromptCancellable).isEqualTo(true)
+ assertThat(state.showSignOutPrompt).isTrue()
+ assertThat(state.isSignOutPromptCancellable).isTrue()
state.eventSink(PinUnlockEvents.ClearSignOutPrompt)
}
awaitLastSequentialItem().also { state ->
- assertThat(state.showSignOutPrompt).isEqualTo(false)
+ assertThat(state.showSignOutPrompt).isFalse()
state.eventSink(PinUnlockEvents.OnForgetPin)
}
awaitLastSequentialItem().also { state ->
- assertThat(state.showSignOutPrompt).isEqualTo(true)
+ assertThat(state.showSignOutPrompt).isTrue()
state.eventSink(PinUnlockEvents.SignOut)
}
consumeItemsUntilPredicate { state ->
diff --git a/features/login/impl/src/main/kotlin/io/element/android/features/login/impl/resolver/HomeserverData.kt b/features/login/impl/src/main/kotlin/io/element/android/features/login/impl/resolver/HomeserverData.kt
index c1f0158605..64e4c11723 100644
--- a/features/login/impl/src/main/kotlin/io/element/android/features/login/impl/resolver/HomeserverData.kt
+++ b/features/login/impl/src/main/kotlin/io/element/android/features/login/impl/resolver/HomeserverData.kt
@@ -16,7 +16,7 @@
package io.element.android.features.login.impl.resolver
-data class HomeserverData constructor(
+data class HomeserverData(
// The computed homeserver url, for which a wellknown file has been retrieved, or just a valid Url
val homeserverUrl: String,
// True if a wellknown file has been found and is valid. If false, it means that the [homeserverUrl] is valid
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 0e757190a9..2603548cab 100644
--- a/features/login/impl/src/main/res/values-de/translations.xml
+++ b/features/login/impl/src/main/res/values-de/translations.xml
@@ -18,6 +18,7 @@
"Homeserver-URL"
"Du kannst nur eine Verbindung zu einem vorhandenen Server herstellen, der Sliding Sync unterstützt. Dein Homeserver-Administrator muss das konfigurieren. %1$s"
"Wie lautet die Adresse deines Servers?"
+ "Wähle deinen Server aus"
"Dieses Konto wurde deaktiviert."
"Falscher Benutzername und/oder Passwort"
"Dies ist keine gültige Benutzerkennung. Erwartetes Format: \'@user:homeserver.org\'"
diff --git a/features/login/impl/src/main/res/values-hu/translations.xml b/features/login/impl/src/main/res/values-hu/translations.xml
new file mode 100644
index 0000000000..defe5e41a4
--- /dev/null
+++ b/features/login/impl/src/main/res/values-hu/translations.xml
@@ -0,0 +1,42 @@
+
+
+ "Fiókszolgáltató módosítása"
+ "Matrix-kiszolgáló webcíme"
+ "Adjon meg egy keresési kifejezést vagy egy tartománycímet."
+ "Keresés egy cégre, közösségre vagy privát kiszolgálóra."
+ "Fiókszolgáltató keresése"
+ "Itt lesznek a beszélgetései – ahogyan egy e-mail-szolgáltatást is használna a levelei kezeléséhez."
+ "Hamarosan bejelentkezik ide: %s"
+ "Itt lesznek a beszélgetései – ahogyan egy e-mail-szolgáltatást is használna a levelei kezeléséhez."
+ "Hamarosan létrehoz egy fiókot itt: %s"
+ "A Matrix.org egy nagy, ingyenes kiszolgáló a nyilvános Matrix-hálózaton, a biztonságos, decentralizált kommunikáció érdekében, amelyet a Matrix.org Alapítvány üzemeltet."
+ "Egyéb"
+ "Másik fiókszolgáltató, például a saját privát kiszolgáló vagy egy munkahelyi fiók használata."
+ "Fiókszolgáltató módosítása"
+ "Nem sikerült elérni ezt a Matrix-kiszolgálót. Ellenőrizze, hogy helyesen adta-e meg a Matrix-kiszolgáló webcímét. Ha a webcím helyes, akkor további segítségért lépjen kapcsolatba a Matrix-kiszolgáló rendszergazdájával."
+ "A kiszolgáló jelenleg nem támogatja a Sliding sync protokollt."
+ "Matrix-kiszolgáló webcíme"
+ "Csak olyan meglévő kiszolgálóhoz csatlakozhat, amely támogatja a Sliding sync protokollt. Ezt a Matrix-kiszolgáló rendszergazdájának kell beállítania. %1$s"
+ "Mi a kiszolgálója címe?"
+ "Válassza ki a kiszolgálóját"
+ "Ez a fiók deaktiválva lett."
+ "Helytelen felhasználónév vagy jelszó"
+ "Ez nem érvényes felhasználóazonosító. A várt formátum: „@user:homeserver.org”"
+ "A kiválasztott Matrix-kiszolgáló nem támogatja a jelszavas vagy OIDC-alapú bejelentkezést. Lépjen kapcsolatba a kiszolgáló rendszergazdájával, vagy válasszon másik Matrix-kiszolgálót."
+ "Adja meg adatait"
+ "Örülünk, hogy visszatért!"
+ "Bejelentkezés ide: %1$s"
+ "Fiókszolgáltató módosítása"
+ "Egy privát kiszolgáló az Element alkalmazottai számára."
+ "A Matrix egy nyitott hálózat a biztonságos, decentralizált kommunikációhoz."
+ "Itt lesznek a beszélgetései – ahogyan egy e-mail-szolgáltatást is használna a levelei kezeléséhez."
+ "Hamarosan bejelentkezik ebbe: %1$s"
+ "Hamarosan létrehoz egy fiókot ezen: %1$s"
+ "Jelenleg nagy a kereslet a(z) %2$s oldalon futó %1$s iránt. Térjen vissza néhány nap múlva az alkalmazáshoz, és próbálja újra.
+
+Köszönjük a türelmét!"
+ "Már majdnem kész van."
+ "Bent van."
+ "A Matrix egy nyitott hálózat a biztonságos, decentralizált kommunikációhoz."
+ "Üdvözli az %1$s!"
+
diff --git a/features/login/impl/src/main/res/values-in/translations.xml b/features/login/impl/src/main/res/values-in/translations.xml
new file mode 100644
index 0000000000..6d4cb91baa
--- /dev/null
+++ b/features/login/impl/src/main/res/values-in/translations.xml
@@ -0,0 +1,42 @@
+
+
+ "Ubah penyedia akun"
+ "Alamat homeserver"
+ "Masukkan istilah pencarian atau alamat domain."
+ "Cari perusahaan, komunitas, atau server pribadi."
+ "Cari penyedia akun"
+ "Di sinilah percakapan Anda akan berlangsung — sama seperti Anda menggunakan penyedia surel untuk menyimpan surel Anda."
+ "Anda akan masuk ke %s"
+ "Di sinilah percakapan Anda akan berlangsung — sama seperti Anda menggunakan penyedia surel untuk menyimpan surel Anda."
+ "Anda akan membuat akun di %s"
+ "Matrix.org adalah server besar dan gratis di jaringan Matrix publik untuk komunikasi yang aman dan terdesentralisasi, disediakan oleh Yayasan Matrix.org."
+ "Lainnya"
+ "Gunakan penyedia akun yang berbeda, seperti server pribadi Anda sendiri atau akun kerja."
+ "Ubah penyedia akun"
+ "Kami tidak dapat menjangkau server ini. Periksa apakah Anda telah memasukkan URL homeserver dengan benar. Jika URL sudah benar, hubungi administrator homeserver Anda untuk bantuan lebih lanjut."
+ "Server ini saat ini tidak mendukung sinkronisasi geser."
+ "URL Homeserver"
+ "Anda hanya dapat terhubung ke server yang ada yang mendukung sinkronisasi geser. Admin homeserver Anda perlu mengaturnya. %1$s"
+ "Apa alamat server Anda?"
+ "Pilih server Anda"
+ "Akun ini telah dinonaktifkan."
+ "Nama pengguna dan/atau kata sandi salah"
+ "Ini bukan pengenal pengguna yang valid. Format yang diharapkan: \'@pengguna:homeserver.org\'"
+ "Homeserver yang dipilih tidak mendukung log masuk kata sandi atau OIDC. Silakan hubungi admin Anda atau pilih homeserver yang lain."
+ "Masukkan detail Anda"
+ "Selamat datang kembali!"
+ "Masuk ke %1$s"
+ "Ubah penyedia akun"
+ "Server pribadi untuk karyawan Element."
+ "Matrix adalah jaringan terbuka untuk komunikasi yang aman dan terdesentralisasi."
+ "Di sinilah percakapan Anda akan berlangsung — sama seperti Anda menggunakan penyedia surel untuk menyimpan surel Anda."
+ "Anda akan masuk ke %1$s"
+ "Anda akan membuat akun di %1$s"
+ "Ada permintaan tinggi untuk %1$s di %2$s saat ini. Kembalilah ke aplikasi dalam beberapa hari dan coba lagi.
+
+Terima kasih atas kesabaran Anda!"
+ "Anda hampir selesai."
+ "Anda sudah masuk."
+ "Matrix adalah jaringan terbuka untuk komunikasi yang aman dan terdesentralisasi."
+ "Selamat datang di %1$s!"
+
diff --git a/features/logout/impl/src/main/res/values-de/translations.xml b/features/logout/impl/src/main/res/values-de/translations.xml
index 2b86bd3a3d..b4368bfca7 100644
--- a/features/logout/impl/src/main/res/values-de/translations.xml
+++ b/features/logout/impl/src/main/res/values-de/translations.xml
@@ -2,4 +2,17 @@
"Bist du sicher, dass du dich abmelden willst?"
"Abmelden…"
+ "Du bist dabei, dich von deiner letzten Sitzung abzumelden. Wenn du dich jetzt abmeldest, verlierst du den Zugriff auf deine verschlüsselten Nachrichten."
+ "Du hast das Backup ausgeschaltet"
+ "Deine Schlüssel wurden noch gesichert, als du offline gegangen bist. Stelle die Verbindung wieder her, damit deine Schlüssel gesichert werden können, bevor du dich abmeldest."
+ "Deine Schlüssel werden noch gesichert"
+ "Bitte warte, bis der Vorgang abgeschlossen ist, bevor du dich abmeldest."
+ "Deine Schlüssel werden noch gesichert"
+ "Du bist dabei, dich von deiner letzten Sitzung abzumelden. Wenn du dich jetzt abmeldest, verlierst du den Zugriff auf deine verschlüsselten Nachrichten."
+ "Wiederherstellung nicht eingerichtet"
+ "Du bist dabei, dich von deiner letzten Sitzung abzumelden. Wenn du dich jetzt abmeldest, verlierst du möglicherweise den Zugriff auf deine verschlüsselten Nachrichten."
+ "Hast du deinen Wiederherstellungsschlüssel gespeichert?"
+ "Abmelden"
+ "Abmelden"
+ "Abmelden"
diff --git a/features/logout/impl/src/main/res/values-hu/translations.xml b/features/logout/impl/src/main/res/values-hu/translations.xml
new file mode 100644
index 0000000000..124fa50468
--- /dev/null
+++ b/features/logout/impl/src/main/res/values-hu/translations.xml
@@ -0,0 +1,18 @@
+
+
+ "Biztos, hogy kijelentkezik?"
+ "Kijelentkezés…"
+ "Arra készül, hogy kijelentkezzen az utolsó munkamenetéből is. Ha most kijelentkezik, akkor elveszti a hozzáférését a titkosított üzeneteihez."
+ "Kikapcsolta a biztonsági mentést"
+ "A kulcsai mentése során bontotta a kapcsolatot. Kapcsolódjon újra, hogy a kulcsai továbbra is mentésre kerüljenek mielőtt kijelentkezik."
+ "A kulcsai mentése még folyamatban van"
+ "Kijelentkezés előtt várja meg a befejezését."
+ "A kulcsai mentése még folyamatban van"
+ "Arra készül, hogy kijelentkezzen az utolsó munkamenetéből is. Ha most kijelentkezik, akkor elveszti a hozzáférését a titkosított üzeneteihez."
+ "A helyreállítás nincs beállítva"
+ "Arra készül, hogy kijelentkezzen az utolsó munkamenetéből is. Ha most kijelentkezik, akkor elveszítheti a hozzáférését a titkosított üzeneteihez."
+ "Mentette a helyreállítási kulcsát?"
+ "Kijelentkezés"
+ "Kijelentkezés"
+ "Kijelentkezés"
+
diff --git a/features/logout/impl/src/main/res/values-in/translations.xml b/features/logout/impl/src/main/res/values-in/translations.xml
new file mode 100644
index 0000000000..537ac904ec
--- /dev/null
+++ b/features/logout/impl/src/main/res/values-in/translations.xml
@@ -0,0 +1,18 @@
+
+
+ "Apakah Anda yakin ingin keluar dari akun?"
+ "Mengeluarkan dari akun…"
+ "Anda akan keluar dari sesi terakhir Anda. Jika Anda keluar sekarang, Anda akan kehilangan akses ke pesan terenkripsi Anda."
+ "Anda telah menonaktifkan pencadangan"
+ "Kunci Anda masih dicadangkan saat Anda luring. Sambungkan kembali sehingga kunci Anda dapat dicadangkan sebelum keluar."
+ "Kunci Anda masih dicadangkan"
+ "Mohon tunggu hingga proses ini selesai sebelum keluar."
+ "Kunci Anda masih dicadangkan"
+ "Anda akan keluar dari sesi Anda yang terakhir. Jika Anda keluar sekarang, Anda akan kehilangan akses ke pesan terenkripsi Anda."
+ "Pemulihan belum disiapkan"
+ "Anda akan keluar dari sesi terakhir Anda. Jika Anda keluar sekarang, Anda mungkin kehilangan akses ke pesan terenkripsi Anda."
+ "Apakah Anda sudah menyimpan kunci pemulihan Anda?"
+ "Keluar dari akun"
+ "Keluar dari akun"
+ "Keluar dari akun"
+
diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/attachments/preview/AttachmentsPreviewPresenter.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/attachments/preview/AttachmentsPreviewPresenter.kt
index 983d016854..28d403c9a6 100644
--- a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/attachments/preview/AttachmentsPreviewPresenter.kt
+++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/attachments/preview/AttachmentsPreviewPresenter.kt
@@ -33,6 +33,7 @@ import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Job
import kotlinx.coroutines.isActive
import kotlinx.coroutines.launch
+import timber.log.Timber
import kotlin.coroutines.coroutineContext
class AttachmentsPreviewPresenter @AssistedInject constructor(
@@ -114,6 +115,7 @@ class AttachmentsPreviewPresenter @AssistedInject constructor(
sendActionState.value = SendActionState.Done
},
onFailure = { error ->
+ Timber.e(error, "Failed to send attachment")
if (error is CancellationException) {
throw error
} else {
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 04ca34ac08..7a5c06721c 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
@@ -72,6 +72,7 @@ import kotlinx.coroutines.flow.filter
import kotlinx.coroutines.flow.merge
import kotlinx.coroutines.isActive
import kotlinx.coroutines.launch
+import timber.log.Timber
import javax.inject.Inject
import kotlin.coroutines.coroutineContext
import kotlin.time.Duration.Companion.seconds
@@ -432,6 +433,7 @@ class MessageComposerPresenter @Inject constructor(
attachmentState.value = AttachmentsState.None
}
.onFailure { cause ->
+ Timber.e(cause, "Failed to send attachment")
attachmentState.value = AttachmentsState.None
if (cause is CancellationException) {
throw cause
diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/TimelinePresenter.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/TimelinePresenter.kt
index 00728efc1e..d0ff255b02 100644
--- a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/TimelinePresenter.kt
+++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/TimelinePresenter.kt
@@ -175,6 +175,9 @@ class TimelinePresenter @AssistedInject constructor(
}
return TimelineState(
+ timelineRoomInfo = TimelineRoomInfo(
+ isDirect = room.isDirect
+ ),
highlightedEventId = highlightedEventId.value,
userHasPermissionToSendMessage = userHasPermissionToSendMessage,
paginationState = paginationState,
diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/TimelineState.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/TimelineState.kt
index 36fa6d33d2..d334aebf8c 100644
--- a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/TimelineState.kt
+++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/TimelineState.kt
@@ -27,6 +27,7 @@ import kotlinx.collections.immutable.ImmutableList
@Immutable
data class TimelineState(
val timelineItems: ImmutableList,
+ val timelineRoomInfo: TimelineRoomInfo,
val showReadReceipts: Boolean,
val highlightedEventId: EventId?,
val userHasPermissionToSendMessage: Boolean,
@@ -35,3 +36,8 @@ data class TimelineState(
val sessionState: SessionState,
val eventSink: (TimelineEvents) -> Unit
)
+
+@Immutable
+data class TimelineRoomInfo(
+ val isDirect: Boolean,
+)
diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/TimelineStateProvider.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/TimelineStateProvider.kt
index 8616ecbc8f..63d8f0ed01 100644
--- a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/TimelineStateProvider.kt
+++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/TimelineStateProvider.kt
@@ -47,6 +47,7 @@ import kotlin.random.Random
fun aTimelineState(timelineItems: ImmutableList = persistentListOf()) = TimelineState(
timelineItems = timelineItems,
+ timelineRoomInfo = aTimelineRoomInfo(),
showReadReceipts = false,
paginationState = MatrixTimeline.PaginationState(
isBackPaginating = false,
@@ -212,3 +213,9 @@ internal fun aGroupedEvents(id: Long = 0): TimelineItem.GroupedEvents {
aggregatedReadReceipts = events.flatMap { it.readReceiptState.receipts }.toImmutableList(),
)
}
+
+internal fun aTimelineRoomInfo(
+ isDirect: Boolean = false,
+) = TimelineRoomInfo(
+ isDirect = isDirect,
+)
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 44f8fce876..bc285b0bc5 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
@@ -118,6 +118,7 @@ fun TimelineView(
) { timelineItem ->
TimelineItemRow(
timelineItem = timelineItem,
+ timelineRoomInfo = state.timelineRoomInfo,
showReadReceipts = state.showReadReceipts,
isLastOutgoingMessage = (timelineItem as? TimelineItem.Event)?.isMine == true
&& state.timelineItems.first().identifier() == timelineItem.identifier(),
diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/ATimelineItemEventRow.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/ATimelineItemEventRow.kt
index 6cd28c7f94..a2a0ae5f4e 100644
--- a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/ATimelineItemEventRow.kt
+++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/ATimelineItemEventRow.kt
@@ -17,17 +17,21 @@
package io.element.android.features.messages.impl.timeline.components
import androidx.compose.runtime.Composable
+import io.element.android.features.messages.impl.timeline.TimelineRoomInfo
+import io.element.android.features.messages.impl.timeline.aTimelineRoomInfo
import io.element.android.features.messages.impl.timeline.model.TimelineItem
// For previews
@Composable
internal fun ATimelineItemEventRow(
event: TimelineItem.Event,
+ timelineRoomInfo: TimelineRoomInfo = aTimelineRoomInfo(),
showReadReceipts: Boolean = false,
isLastOutgoingMessage: Boolean = false,
isHighlighted: Boolean = false,
) = TimelineItemEventRow(
event = event,
+ timelineRoomInfo = timelineRoomInfo,
showReadReceipts = showReadReceipts,
isLastOutgoingMessage = isLastOutgoingMessage,
isHighlighted = isHighlighted,
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 a395f963dc..5132aa5621 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,17 +35,17 @@ import androidx.compose.ui.draw.clip
import androidx.compose.ui.graphics.Shape
import androidx.compose.ui.tooling.preview.PreviewParameter
import androidx.compose.ui.unit.dp
+import io.element.android.compound.theme.ElementTheme
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
import io.element.android.libraries.core.extensions.to01
-import io.element.android.libraries.designsystem.preview.PreviewsDayNight
import io.element.android.libraries.designsystem.preview.ElementPreview
+import io.element.android.libraries.designsystem.preview.PreviewsDayNight
import io.element.android.libraries.designsystem.theme.components.Surface
import io.element.android.libraries.designsystem.theme.components.Text
import io.element.android.libraries.designsystem.theme.messageFromMeBackground
import io.element.android.libraries.designsystem.theme.messageFromOtherBackground
-import io.element.android.compound.theme.ElementTheme
private val BUBBLE_RADIUS = 12.dp
private val BUBBLE_INCOMING_OFFSET = 16.dp
@@ -91,10 +91,10 @@ fun MessageEventBubble(
}
fun Modifier.offsetForItem(): Modifier {
- return if (state.isMine) {
- this
- } else {
- offset(x = BUBBLE_INCOMING_OFFSET)
+ return when {
+ state.isMine -> this
+ state.timelineRoomInfo.isDirect -> this
+ else -> offset(x = BUBBLE_INCOMING_OFFSET)
}
}
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 7a35d565ef..11b94e0080 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
@@ -60,6 +60,7 @@ import androidx.compose.ui.zIndex
import androidx.constraintlayout.compose.ConstrainScope
import androidx.constraintlayout.compose.ConstraintLayout
import io.element.android.compound.theme.ElementTheme
+import io.element.android.features.messages.impl.timeline.TimelineRoomInfo
import io.element.android.features.messages.impl.timeline.TimelineEvents
import io.element.android.features.messages.impl.timeline.aTimelineItemEvent
import io.element.android.features.messages.impl.timeline.components.event.TimelineItemEventContentView
@@ -101,6 +102,7 @@ import kotlin.math.roundToInt
@Composable
fun TimelineItemEventRow(
event: TimelineItem.Event,
+ timelineRoomInfo: TimelineRoomInfo,
showReadReceipts: Boolean,
isLastOutgoingMessage: Boolean,
isHighlighted: Boolean,
@@ -163,9 +165,8 @@ fun TimelineItemEventRow(
state = state.draggableState,
),
event = event,
- showReadReceipts = showReadReceipts,
- isLastOutgoingMessage = isLastOutgoingMessage,
isHighlighted = isHighlighted,
+ timelineRoomInfo = timelineRoomInfo,
interactionSource = interactionSource,
onClick = onClick,
onLongClick = onLongClick,
@@ -175,7 +176,6 @@ fun TimelineItemEventRow(
onReactionClicked = { emoji -> onReactionClick(emoji, event) },
onReactionLongClicked = { emoji -> onReactionLongClick(emoji, event) },
onMoreReactionsClicked = { onMoreReactionsClick(event) },
- onReadReceiptsClicked = { onReadReceiptClick(event) },
eventSink = eventSink,
)
}
@@ -183,9 +183,8 @@ fun TimelineItemEventRow(
} else {
TimelineItemEventRowContent(
event = event,
- showReadReceipts = showReadReceipts,
- isLastOutgoingMessage = isLastOutgoingMessage,
isHighlighted = isHighlighted,
+ timelineRoomInfo = timelineRoomInfo,
interactionSource = interactionSource,
onClick = onClick,
onLongClick = onLongClick,
@@ -195,10 +194,20 @@ fun TimelineItemEventRow(
onReactionClicked = { emoji -> onReactionClick(emoji, event) },
onReactionLongClicked = { emoji -> onReactionLongClick(emoji, event) },
onMoreReactionsClicked = { onMoreReactionsClick(event) },
- onReadReceiptsClicked = { onReadReceiptClick(event) },
eventSink = eventSink,
)
}
+ // Read receipts / Send state
+ TimelineItemReadReceiptView(
+ state = ReadReceiptViewState(
+ sendState = event.localSendState,
+ isLastOutgoingMessage = isLastOutgoingMessage,
+ receipts = event.readReceiptState.receipts,
+ ),
+ showReadReceipts = showReadReceipts,
+ onReadReceiptsClicked = { onReadReceiptClick(event) },
+ modifier = Modifier.padding(top = 4.dp),
+ )
}
}
@@ -228,9 +237,8 @@ private fun SwipeSensitivity(
@Composable
private fun TimelineItemEventRowContent(
event: TimelineItem.Event,
- showReadReceipts: Boolean,
- isLastOutgoingMessage: Boolean,
isHighlighted: Boolean,
+ timelineRoomInfo: TimelineRoomInfo,
interactionSource: MutableInteractionSource,
onClick: () -> Unit,
onLongClick: () -> Unit,
@@ -238,7 +246,6 @@ private fun TimelineItemEventRowContent(
inReplyToClicked: () -> Unit,
onUserDataClicked: () -> Unit,
onReactionClicked: (emoji: String) -> Unit,
- onReadReceiptsClicked: () -> Unit,
onReactionLongClicked: (emoji: String) -> Unit,
onMoreReactionsClicked: (event: TimelineItem.Event) -> Unit,
eventSink: (TimelineEvents) -> Unit,
@@ -259,12 +266,11 @@ private fun TimelineItemEventRowContent(
sender,
message,
reactions,
- readReceipts,
) = createRefs()
// Sender
val avatarStrokeSize = 3.dp
- if (event.showSenderInformation) {
+ if (event.showSenderInformation && !timelineRoomInfo.isDirect) {
MessageSenderInformation(
event.safeSenderName,
event.senderAvatar,
@@ -284,6 +290,7 @@ private fun TimelineItemEventRowContent(
groupPosition = event.groupPosition,
isMine = event.isMine,
isHighlighted = isHighlighted,
+ timelineRoomInfo = timelineRoomInfo,
)
MessageEventBubble(
modifier = Modifier
@@ -326,25 +333,6 @@ private fun TimelineItemEventRowContent(
.padding(start = if (event.isMine) 16.dp else 36.dp, end = 16.dp)
)
}
-
- // Read receipts / Send state
- TimelineItemReadReceiptView(
- state = ReadReceiptViewState(
- sendState = event.localSendState,
- isLastOutgoingMessage = isLastOutgoingMessage,
- receipts = event.readReceiptState.receipts,
- ),
- showReadReceipts = showReadReceipts,
- onReadReceiptsClicked = onReadReceiptsClicked,
- modifier = Modifier
- .constrainAs(readReceipts) {
- if (event.reactionsState.reactions.isNotEmpty()) {
- top.linkTo(reactions.bottom, margin = 4.dp)
- } else {
- top.linkTo(message.bottom, margin = 4.dp)
- }
- }
- )
}
}
@@ -378,6 +366,7 @@ private fun MessageSenderInformation(
Avatar(senderAvatar)
Spacer(modifier = Modifier.width(4.dp))
Text(
+ modifier = Modifier.clipToBounds(),
text = sender,
maxLines = 1,
overflow = TextOverflow.Ellipsis,
diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/TimelineItemEventRowForDirectRoomPreview.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/TimelineItemEventRowForDirectRoomPreview.kt
new file mode 100644
index 0000000000..4443c00f3d
--- /dev/null
+++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/TimelineItemEventRowForDirectRoomPreview.kt
@@ -0,0 +1,62 @@
+/*
+ * 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.foundation.layout.Column
+import androidx.compose.runtime.Composable
+import io.element.android.features.messages.impl.timeline.aTimelineItemEvent
+import io.element.android.features.messages.impl.timeline.aTimelineRoomInfo
+import io.element.android.features.messages.impl.timeline.model.TimelineItemGroupPosition
+import io.element.android.features.messages.impl.timeline.model.event.aTimelineItemImageContent
+import io.element.android.features.messages.impl.timeline.model.event.aTimelineItemTextContent
+import io.element.android.libraries.designsystem.preview.ElementPreview
+import io.element.android.libraries.designsystem.preview.PreviewsDayNight
+
+@PreviewsDayNight
+@Composable
+internal fun TimelineItemEventRowForDirectRoomPreview() = ElementPreview {
+ Column {
+ sequenceOf(false, true).forEach {
+ ATimelineItemEventRow(
+ event = aTimelineItemEvent(
+ isMine = it,
+ content = aTimelineItemTextContent().copy(
+ body = "A long text which will be displayed on several lines and" +
+ " hopefully can be manually adjusted to test different behaviors."
+ ),
+ groupPosition = TimelineItemGroupPosition.First,
+ ),
+ timelineRoomInfo = aTimelineRoomInfo(
+ isDirect = true,
+ ),
+ )
+ ATimelineItemEventRow(
+ event = aTimelineItemEvent(
+ isMine = it,
+ content = aTimelineItemImageContent().copy(
+ aspectRatio = 5f
+ ),
+ groupPosition = TimelineItemGroupPosition.Last,
+ ),
+ timelineRoomInfo = aTimelineRoomInfo(
+ isDirect = true,
+ ),
+ )
+ }
+ }
+}
+
diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/TimelineItemGroupedEventsRow.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/TimelineItemGroupedEventsRow.kt
index 718a29e3ca..d52795c052 100644
--- a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/TimelineItemGroupedEventsRow.kt
+++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/TimelineItemGroupedEventsRow.kt
@@ -24,8 +24,10 @@ import androidx.compose.runtime.saveable.rememberSaveable
import androidx.compose.ui.Modifier
import androidx.compose.ui.res.pluralStringResource
import io.element.android.features.messages.impl.R
+import io.element.android.features.messages.impl.timeline.TimelineRoomInfo
import io.element.android.features.messages.impl.timeline.TimelineEvents
import io.element.android.features.messages.impl.timeline.aGroupedEvents
+import io.element.android.features.messages.impl.timeline.aTimelineRoomInfo
import io.element.android.features.messages.impl.timeline.components.group.GroupHeaderView
import io.element.android.features.messages.impl.timeline.components.receipt.ReadReceiptViewState
import io.element.android.features.messages.impl.timeline.components.receipt.TimelineItemReadReceiptView
@@ -40,6 +42,7 @@ import io.element.android.libraries.matrix.api.core.UserId
@Composable
fun TimelineItemGroupedEventsRow(
timelineItem: TimelineItem.GroupedEvents,
+ timelineRoomInfo: TimelineRoomInfo,
showReadReceipts: Boolean,
isLastOutgoingMessage: Boolean,
highlightedItem: String?,
@@ -66,6 +69,7 @@ fun TimelineItemGroupedEventsRow(
isExpanded = isExpanded.value,
onExpandGroupClick = ::onExpandGroupClick,
timelineItem = timelineItem,
+ timelineRoomInfo = timelineRoomInfo,
highlightedItem = highlightedItem,
showReadReceipts = showReadReceipts,
isLastOutgoingMessage = isLastOutgoingMessage,
@@ -89,6 +93,7 @@ private fun TimelineItemGroupedEventsRowContent(
isExpanded: Boolean,
onExpandGroupClick: () -> Unit,
timelineItem: TimelineItem.GroupedEvents,
+ timelineRoomInfo: TimelineRoomInfo,
highlightedItem: String?,
showReadReceipts: Boolean,
isLastOutgoingMessage: Boolean,
@@ -121,6 +126,7 @@ private fun TimelineItemGroupedEventsRowContent(
timelineItem.events.forEach { subGroupEvent ->
TimelineItemRow(
timelineItem = subGroupEvent,
+ timelineRoomInfo = timelineRoomInfo,
showReadReceipts = showReadReceipts,
isLastOutgoingMessage = isLastOutgoingMessage,
highlightedItem = highlightedItem,
@@ -148,7 +154,8 @@ private fun TimelineItemGroupedEventsRowContent(
receipts = timelineItem.aggregatedReadReceipts,
),
showReadReceipts = true,
- onReadReceiptsClicked = { /* No op for group event */ })
+ onReadReceiptsClicked = onExpandGroupClick
+ )
}
}
}
@@ -160,6 +167,7 @@ internal fun TimelineItemGroupedEventsRowContentExpandedPreview() = ElementPrevi
isExpanded = true,
onExpandGroupClick = {},
timelineItem = aGroupedEvents(),
+ timelineRoomInfo = aTimelineRoomInfo(),
highlightedItem = null,
showReadReceipts = true,
isLastOutgoingMessage = false,
@@ -184,6 +192,7 @@ internal fun TimelineItemGroupedEventsRowContentCollapsePreview() = ElementPrevi
isExpanded = false,
onExpandGroupClick = {},
timelineItem = aGroupedEvents(),
+ timelineRoomInfo = aTimelineRoomInfo(),
highlightedItem = null,
showReadReceipts = true,
isLastOutgoingMessage = false,
diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/TimelineItemRow.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/TimelineItemRow.kt
index f77319259b..92dbbe46b6 100644
--- a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/TimelineItemRow.kt
+++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/TimelineItemRow.kt
@@ -18,6 +18,7 @@ package io.element.android.features.messages.impl.timeline.components
import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier
+import io.element.android.features.messages.impl.timeline.TimelineRoomInfo
import io.element.android.features.messages.impl.timeline.TimelineEvents
import io.element.android.features.messages.impl.timeline.model.TimelineItem
import io.element.android.features.messages.impl.timeline.model.event.TimelineItemStateContent
@@ -29,6 +30,7 @@ import io.element.android.libraries.matrix.api.core.UserId
@Composable
internal fun TimelineItemRow(
timelineItem: TimelineItem,
+ timelineRoomInfo: TimelineRoomInfo,
showReadReceipts: Boolean,
isLastOutgoingMessage: Boolean,
highlightedItem: String?,
@@ -71,6 +73,7 @@ internal fun TimelineItemRow(
} else {
TimelineItemEventRow(
event = timelineItem,
+ timelineRoomInfo = timelineRoomInfo,
showReadReceipts = showReadReceipts,
isLastOutgoingMessage = isLastOutgoingMessage,
isHighlighted = highlightedItem == timelineItem.identifier(),
@@ -93,6 +96,7 @@ internal fun TimelineItemRow(
is TimelineItem.GroupedEvents -> {
TimelineItemGroupedEventsRow(
timelineItem = timelineItem,
+ timelineRoomInfo = timelineRoomInfo,
showReadReceipts = showReadReceipts,
isLastOutgoingMessage = isLastOutgoingMessage,
highlightedItem = highlightedItem,
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 8a4d52c358..1d50509844 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
@@ -16,6 +16,8 @@
package io.element.android.features.messages.impl.timeline.components.group
+import androidx.compose.animation.core.animateFloatAsState
+import androidx.compose.animation.core.tween
import androidx.compose.foundation.clickable
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Box
@@ -26,6 +28,7 @@ import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.material3.MaterialTheme
import androidx.compose.runtime.Composable
+import androidx.compose.runtime.getValue
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.clip
@@ -76,9 +79,17 @@ fun GroupHeaderView(
color = MaterialTheme.colorScheme.secondary,
style = ElementTheme.typography.fontBodyMdRegular,
)
+ val rotation: Float by animateFloatAsState(
+ targetValue = if (isExpanded) 90f else 0f,
+ animationSpec = tween(
+ delayMillis = 0,
+ durationMillis = 300,
+ ),
+ label = "chevron"
+ )
Icon(
- modifier = Modifier.rotate(if (isExpanded) 180f else 0f),
- imageVector = CompoundIcons.ChevronDown,
+ modifier = Modifier.rotate(rotation),
+ imageVector = CompoundIcons.ChevronRight,
contentDescription = null,
tint = MaterialTheme.colorScheme.secondary
)
diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/model/bubble/BubbleState.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/model/bubble/BubbleState.kt
index 1912aac668..4f1fc3c546 100644
--- a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/model/bubble/BubbleState.kt
+++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/model/bubble/BubbleState.kt
@@ -16,10 +16,12 @@
package io.element.android.features.messages.impl.timeline.model.bubble
+import io.element.android.features.messages.impl.timeline.TimelineRoomInfo
import io.element.android.features.messages.impl.timeline.model.TimelineItemGroupPosition
data class BubbleState(
val groupPosition: TimelineItemGroupPosition,
val isMine: Boolean,
val isHighlighted: Boolean,
+ val timelineRoomInfo: TimelineRoomInfo,
)
diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/model/bubble/BubbleStateProvider.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/model/bubble/BubbleStateProvider.kt
index fbcbcc5454..9c50a73a6b 100644
--- a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/model/bubble/BubbleStateProvider.kt
+++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/model/bubble/BubbleStateProvider.kt
@@ -17,6 +17,8 @@
package io.element.android.features.messages.impl.timeline.model.bubble
import androidx.compose.ui.tooling.preview.PreviewParameterProvider
+import io.element.android.features.messages.impl.timeline.TimelineRoomInfo
+import io.element.android.features.messages.impl.timeline.aTimelineRoomInfo
import io.element.android.features.messages.impl.timeline.model.TimelineItemGroupPosition
open class BubbleStateProvider : PreviewParameterProvider {
@@ -29,7 +31,11 @@ open class BubbleStateProvider : PreviewParameterProvider {
).map { groupPosition ->
sequenceOf(false, true).map { isMine ->
sequenceOf(false, true).map { isHighlighted ->
- BubbleState(groupPosition, isMine = isMine, isHighlighted = isHighlighted)
+ aBubbleState(
+ groupPosition = groupPosition,
+ isMine = isMine,
+ isHighlighted = isHighlighted,
+ )
}
}
.flatten()
@@ -37,8 +43,14 @@ open class BubbleStateProvider : PreviewParameterProvider {
.flatten()
}
-fun aBubbleState() = BubbleState(
- groupPosition = TimelineItemGroupPosition.First,
- isMine = false,
- isHighlighted = false,
+internal fun aBubbleState(
+ groupPosition: TimelineItemGroupPosition = TimelineItemGroupPosition.First,
+ isMine: Boolean = false,
+ isHighlighted: Boolean = false,
+ timelineRoomInfo: TimelineRoomInfo = aTimelineRoomInfo(),
+) = BubbleState(
+ groupPosition = groupPosition,
+ isMine = isMine,
+ isHighlighted = isHighlighted,
+ timelineRoomInfo = timelineRoomInfo,
)
diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/voicemessages/timeline/VoiceMessageMediaRepo.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/voicemessages/timeline/VoiceMessageMediaRepo.kt
index cc8bd1945f..62ddc4845b 100644
--- a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/voicemessages/timeline/VoiceMessageMediaRepo.kt
+++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/voicemessages/timeline/VoiceMessageMediaRepo.kt
@@ -24,6 +24,7 @@ import io.element.android.libraries.di.CacheDirectory
import io.element.android.libraries.di.RoomScope
import io.element.android.libraries.matrix.api.media.MatrixMediaLoader
import io.element.android.libraries.matrix.api.media.MediaSource
+import io.element.android.libraries.matrix.api.mxc.MxcTools
import java.io.File
/**
@@ -66,6 +67,7 @@ interface VoiceMessageMediaRepo {
class DefaultVoiceMessageMediaRepo @AssistedInject constructor(
@CacheDirectory private val cacheDir: File,
+ mxcTools: MxcTools,
private val matrixMediaLoader: MatrixMediaLoader,
@Assisted private val mediaSource: MediaSource,
@Assisted("mimeType") private val mimeType: String?,
@@ -101,7 +103,7 @@ class DefaultVoiceMessageMediaRepo @AssistedInject constructor(
}
}
- private val cachedFile: File? = mxcUri2FilePath(mediaSource.url)?.let {
+ private val cachedFile: File? = mxcTools.mxcUri2FilePath(mediaSource.url)?.let {
File("${cacheDir.path}/$CACHE_VOICE_SUBDIR/$it")
}
}
@@ -110,24 +112,3 @@ class DefaultVoiceMessageMediaRepo @AssistedInject constructor(
* Subdirectory of the application's cache directory where voice messages are stored.
*/
private const val CACHE_VOICE_SUBDIR = "temp/voice"
-
-/**
- * Regex to match a Matrix Content (mxc://) URI.
- *
- * See: https://spec.matrix.org/v1.8/client-server-api/#matrix-content-mxc-uris
- */
-private val mxcRegex = Regex("""^mxc:\/\/([^\/]+)\/([^\/]+)$""")
-
-/**
- * Sanitizes an mxcUri to be used as a relative file path.
- *
- * @param mxcUri the Matrix Content (mxc://) URI of the voice message.
- * @return the relative file path as "/" or null if the mxcUri is invalid.
- */
-private fun mxcUri2FilePath(mxcUri: String): String? = mxcRegex.matchEntire(mxcUri)?.let { match ->
- buildString {
- append(match.groupValues[1])
- append("/")
- append(match.groupValues[2])
- }
-}
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 16580c21c5..4798aaf696 100644
--- a/features/messages/impl/src/main/res/values-de/translations.xml
+++ b/features/messages/impl/src/main/res/values-de/translations.xml
@@ -17,6 +17,7 @@
"Dies ist der Anfang von %1$s."
"Dies ist der Anfang dieses Gesprächs."
"Neu"
+ "Den ganzen Raum benachrichtigen"
"Prüfe, ob du alle aktuellen und zukünftigen Nachrichten dieses Benutzers ausblenden möchtest"
"Kamera"
"Foto machen"
@@ -27,6 +28,7 @@
"Umfrage"
"Textformatierung"
"Der Nachrichtenverlauf ist derzeit in diesem Raum nicht verfügbar"
+ "Der Nachrichtenverlauf ist in diesem Raum nicht verfügbar. Verifiziere dieses Gerät, um deinen Nachrichtenverlauf zu sehen."
"Benutzerdetails konnten nicht abgerufen werden"
"Möchtest du sie wieder einladen?"
"Du bist allein in diesem Chat"
@@ -42,6 +44,7 @@
"Beim Laden der Benachrichtigungseinstellungen ist ein Fehler aufgetreten."
"Fehler beim Wiederherstellen des Standardmodus. Bitte versuche es erneut."
"Fehler beim Einstellen des Modus. Bitte versuche es erneut."
+ "Dein Homeserver unterstützt diese Option in verschlüsselten Räumen nicht. Du wirst in diesem Raum nicht benachrichtigt."
"Alle Nachrichten"
"Benachrichtige mich in diesem Raum bei"
"Weniger anzeigen"
@@ -50,6 +53,8 @@
"Deine Nachricht konnte nicht gesendet werden"
"Emoji hinzufügen"
"Weniger anzeigen"
+ "Zum Aufnehmen gedrückt halten"
+ "Alle"
"Benutzer sperren"
"Fehler beim Verarbeiten des hochgeladenen Mediums. Bitte versuche es erneut."
"Nur Erwähnungen und Schlüsselwörter"
diff --git a/features/messages/impl/src/main/res/values-hu/translations.xml b/features/messages/impl/src/main/res/values-hu/translations.xml
new file mode 100644
index 0000000000..a7d1aa576e
--- /dev/null
+++ b/features/messages/impl/src/main/res/values-hu/translations.xml
@@ -0,0 +1,57 @@
+
+
+ "Tevékenységek"
+ "Zászlók"
+ "Étel és ital"
+ "Állatok és természet"
+ "Tárgyak"
+ "Mosolyok és emberek"
+ "Utazás és helyek"
+ "Szimbólumok"
+ "Ez az üzenet jelentve lesz a Matrix-kiszolgáló rendszergazdájának. Nem fogja tudni elolvasni a titkosított üzeneteket."
+ "A tartalom jelentésének oka"
+ "Ez a(z) %1$s kezdete."
+ "Ez a beszélgetés kezdete."
+ "Új"
+ "Teljes szoba értesítése"
+ "Jelölje be, ha el akarja rejteni az összes jelenlegi és jövőbeli üzenetet ettől a felhasználótól"
+ "Kamera"
+ "Fénykép készítése"
+ "Videó rögzítése"
+ "Melléklet"
+ "Fénykép- és videótár"
+ "Hely"
+ "Szavazás"
+ "Szövegformázás"
+ "Az üzenetelőzmények jelenleg nem érhetők el."
+ "Az üzenetelőzmények nem érhetők el ebben a szobában. Ellenőrizze ezt az eszközt, hogy lássa az előzményeket."
+ "Nem sikerült letölteni a felhasználói adatokat"
+ "Visszahívja?"
+ "Egyedül van ebben a csevegésben"
+ "Üzenet másolva"
+ "Nincs jogosultsága arra, hogy bejegyzést tegyen közzé ebben a szobában"
+ "Egyéni beállítás engedélyezése"
+ "Ennek bekapcsolása felülírja az alapértelmezett beállítást"
+ "Értesítések kérése ebben a csevegésben ezekről:"
+ "Megváltoztathatja a %1$s."
+ "globális beállításokban"
+ "Alapértelmezett beállítás"
+ "Egyéni beállítás eltávolítása"
+ "Hiba történt az értesítési beállítások betöltésekor."
+ "Nem sikerült visszaállítani az alapértelmezett módot, próbálja újra."
+ "Nem sikerült a mód beállítása, próbálja újra."
+ "A Matrix-kiszolgálója nem támogatja ezt a beállítást a titkosított szobákban, egyes szobákban nem fog értesítéseket kapni."
+ "Összes üzenet"
+ "Ebben a szobában, értesítés ezekről:"
+ "Kevesebb megjelenítése"
+ "Több megjelenítése"
+ "Újraküldés"
+ "Az üzenet elküldése sikertelen"
+ "Emodzsi hozzáadása"
+ "Kevesebb megjelenítése"
+ "Tartsa a rögzítéshez"
+ "Mindenki"
+ "Felhasználó letiltása"
+ "Nem sikerült feldolgozni a feltöltendő médiát, próbálja újra."
+ "Csak említések és kulcsszavak"
+
diff --git a/features/messages/impl/src/main/res/values-in/translations.xml b/features/messages/impl/src/main/res/values-in/translations.xml
new file mode 100644
index 0000000000..3e792da48f
--- /dev/null
+++ b/features/messages/impl/src/main/res/values-in/translations.xml
@@ -0,0 +1,60 @@
+
+
+ "Aktivitas"
+ "Bendera"
+ "Makanan & Minuman"
+ "Hewan & Alam"
+ "Objek"
+ "Senyuman & Orang"
+ "Wisata & Tempat"
+ "Simbol"
+
+ - "%1$d perubahan ruangan"
+
+ "Pesan ini akan dilaporkan ke administrator homeserver Anda. Mereka tidak akan dapat membaca pesan terenkripsi apa pun."
+ "Alasan melaporkan konten ini"
+ "Ini adalah awal dari %1$s."
+ "Ini adalah awal dari percakapan ini."
+ "Baru"
+ "Beri tahu seluruh ruangan"
+ "Centang jika Anda ingin menyembunyikan semua pesan saat ini dan yang akan datang dari pengguna ini"
+ "Kamera"
+ "Ambil foto"
+ "Rekam video"
+ "Lampiran"
+ "Pustaka Foto & Video"
+ "Lokasi"
+ "Pemungutan suara"
+ "Pemformatan Teks"
+ "Riwayat pesan saat ini tidak tersedia di ruangan ini"
+ "Riwayat pesan tidak tersedia di ruangan ini. Verifikasi perangkat ini untuk melihat riwayat pesan."
+ "Tidak dapat mengambil detail pengguna"
+ "Apakah Anda ingin mengundang mereka kembali?"
+ "Anda sendirian di obrolan ini"
+ "Pesan disalin"
+ "Anda tidak memiliki izin untuk mengirim di ruangan ini"
+ "Izinkan pengaturan khusus"
+ "Mengaktifkan ini akan mengganti pengaturan bawaan Anda"
+ "Beri tahu saya di obrolan ini tentang"
+ "Anda dapat mengubahnya di %1$s Anda."
+ "pengaturan global"
+ "Pengaturan bawaan"
+ "Hapus pengaturan khusus"
+ "Terjadi kesalahan saat memuat pengaturan pemberitahuan."
+ "Gagal memulihkan mode bawaan, silakan coba lagi."
+ "Gagal mengatur mode, silakan coba lagi."
+ "Homeserver Anda tidak mendukung opsi ini dalam ruangan terenkripsi, Anda tidak akan diberi tahu dalam ruangan ini."
+ "Semua pesan"
+ "Di ruangan ini, beri tahu saya tentang"
+ "Tampilkan lebih sedikit"
+ "Tampilkan lebih banyak"
+ "Kirim ulang"
+ "Pesan Anda gagal dikirim"
+ "Tambahkan emoji"
+ "Tampilkan lebih sedikit"
+ "Tahan untuk merekam"
+ "Semua orang"
+ "Blokir pengguna"
+ "Gagal memproses media untuk diunggah, silakan coba lagi."
+ "Sebutan dan Kata Kunci saja"
+
diff --git a/features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/textcomposer/MessageComposerPresenterTest.kt b/features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/textcomposer/MessageComposerPresenterTest.kt
index ef7891b953..e8a1559409 100644
--- a/features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/textcomposer/MessageComposerPresenterTest.kt
+++ b/features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/textcomposer/MessageComposerPresenterTest.kt
@@ -379,9 +379,9 @@ class MessageComposerPresenterTest {
}.test {
skipItems(1)
val initialState = awaitItem()
- assertThat(initialState.showAttachmentSourcePicker).isEqualTo(false)
+ assertThat(initialState.showAttachmentSourcePicker).isFalse()
initialState.eventSink(MessageComposerEvents.AddAttachment)
- assertThat(awaitItem().showAttachmentSourcePicker).isEqualTo(true)
+ assertThat(awaitItem().showAttachmentSourcePicker).isTrue()
}
}
diff --git a/features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/timeline/components/reactionsummary/ReactionSummaryPresenterTests.kt b/features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/timeline/components/reactionsummary/ReactionSummaryPresenterTests.kt
index 9d70e03fcd..d7d51c5eb4 100644
--- a/features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/timeline/components/reactionsummary/ReactionSummaryPresenterTests.kt
+++ b/features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/timeline/components/reactionsummary/ReactionSummaryPresenterTests.kt
@@ -53,7 +53,7 @@ class ReactionSummaryPresenterTests {
presenter.present()
}.test {
val initialState = awaitItem()
- assertThat(initialState.target).isEqualTo(null)
+ assertThat(initialState.target).isNull()
initialState.eventSink(summaryEvent)
assertThat(awaitItem().target).isNotNull()
@@ -69,7 +69,7 @@ class ReactionSummaryPresenterTests {
presenter.present()
}.test {
val initialState = awaitItem()
- assertThat(initialState.target).isEqualTo(null)
+ assertThat(initialState.target).isNull()
initialState.eventSink(summaryEvent)
val reactions = awaitItem().target?.reactions
diff --git a/features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/timeline/model/InReplyToMetadataKtTest.kt b/features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/timeline/model/InReplyToMetadataKtTest.kt
index 4f4fa296bc..646a6e372f 100644
--- a/features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/timeline/model/InReplyToMetadataKtTest.kt
+++ b/features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/timeline/model/InReplyToMetadataKtTest.kt
@@ -26,7 +26,7 @@ import androidx.test.ext.junit.runners.AndroidJUnit4
import app.cash.molecule.RecompositionMode
import app.cash.molecule.moleculeFlow
import app.cash.turbine.test
-import com.google.common.truth.Truth
+import com.google.common.truth.Truth.assertThat
import io.element.android.libraries.matrix.api.core.EventId
import io.element.android.libraries.matrix.api.core.UserId
import io.element.android.libraries.matrix.api.media.AudioInfo
@@ -59,7 +59,7 @@ class InReplyToMetadataKtTest {
anInReplyToDetails(eventContent = aMessageContent()).metadata()
}.test {
awaitItem().let {
- Truth.assertThat(it).isEqualTo(InReplyToMetadata.Text("textContent"))
+ assertThat(it).isEqualTo(InReplyToMetadata.Text("textContent"))
}
}
}
@@ -78,7 +78,7 @@ class InReplyToMetadataKtTest {
).metadata()
}.test {
awaitItem().let {
- Truth.assertThat(it).isEqualTo(
+ assertThat(it).isEqualTo(
InReplyToMetadata.Thumbnail(
attachmentThumbnailInfo = AttachmentThumbnailInfo(
thumbnailSource = aMediaSource(),
@@ -115,7 +115,7 @@ class InReplyToMetadataKtTest {
).metadata()
}.test {
awaitItem().let {
- Truth.assertThat(it).isEqualTo(
+ assertThat(it).isEqualTo(
InReplyToMetadata.Thumbnail(
attachmentThumbnailInfo = AttachmentThumbnailInfo(
thumbnailSource = aMediaSource(),
@@ -148,7 +148,7 @@ class InReplyToMetadataKtTest {
).metadata()
}.test {
awaitItem().let {
- Truth.assertThat(it).isEqualTo(
+ assertThat(it).isEqualTo(
InReplyToMetadata.Thumbnail(
attachmentThumbnailInfo = AttachmentThumbnailInfo(
thumbnailSource = aMediaSource(),
@@ -180,7 +180,7 @@ class InReplyToMetadataKtTest {
).metadata()
}.test {
awaitItem().let {
- Truth.assertThat(it).isEqualTo(
+ assertThat(it).isEqualTo(
InReplyToMetadata.Thumbnail(
attachmentThumbnailInfo = AttachmentThumbnailInfo(
textContent = "body",
@@ -209,7 +209,7 @@ class InReplyToMetadataKtTest {
}
}.test {
awaitItem().let {
- Truth.assertThat(it).isEqualTo(
+ assertThat(it).isEqualTo(
InReplyToMetadata.Thumbnail(
attachmentThumbnailInfo = AttachmentThumbnailInfo(
thumbnailSource = null,
@@ -240,7 +240,7 @@ class InReplyToMetadataKtTest {
}
}.test {
awaitItem().let {
- Truth.assertThat(it).isEqualTo(
+ assertThat(it).isEqualTo(
InReplyToMetadata.Thumbnail(
attachmentThumbnailInfo = AttachmentThumbnailInfo(
thumbnailSource = null,
@@ -262,7 +262,7 @@ class InReplyToMetadataKtTest {
).metadata()
}.test {
awaitItem().let {
- Truth.assertThat(it).isEqualTo(
+ assertThat(it).isEqualTo(
InReplyToMetadata.Thumbnail(
attachmentThumbnailInfo = AttachmentThumbnailInfo(
thumbnailSource = null,
@@ -284,7 +284,7 @@ class InReplyToMetadataKtTest {
).metadata()
}.test {
awaitItem().let {
- Truth.assertThat(it).isEqualTo(null)
+ assertThat(it).isNull()
}
}
}
diff --git a/features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/voicemessages/timeline/DefaultVoiceMessageMediaRepoTest.kt b/features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/voicemessages/timeline/DefaultVoiceMessageMediaRepoTest.kt
index e562d66815..0208d06e95 100644
--- a/features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/voicemessages/timeline/DefaultVoiceMessageMediaRepoTest.kt
+++ b/features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/voicemessages/timeline/DefaultVoiceMessageMediaRepoTest.kt
@@ -16,10 +16,11 @@
package io.element.android.features.messages.impl.voicemessages.timeline
-import com.google.common.truth.Truth
+import com.google.common.truth.Truth.assertThat
import io.element.android.libraries.core.mimetype.MimeTypes
import io.element.android.libraries.matrix.api.media.MatrixMediaLoader
import io.element.android.libraries.matrix.api.media.MediaSource
+import io.element.android.libraries.matrix.api.mxc.MxcTools
import io.element.android.libraries.matrix.test.media.FakeMediaLoader
import kotlinx.coroutines.test.runTest
import org.junit.Rule
@@ -43,10 +44,10 @@ class DefaultVoiceMessageMediaRepoTest {
)
repo.getMediaFile().let { result ->
- Truth.assertThat(result.isSuccess).isTrue()
+ assertThat(result.isSuccess).isTrue()
result.getOrThrow().let { file ->
- Truth.assertThat(file.path).isEqualTo(temporaryFolder.cachedFilePath)
- Truth.assertThat(file.exists()).isTrue()
+ assertThat(file.path).isEqualTo(temporaryFolder.cachedFilePath)
+ assertThat(file.exists()).isTrue()
}
}
}
@@ -62,9 +63,9 @@ class DefaultVoiceMessageMediaRepoTest {
)
repo.getMediaFile().let { result ->
- Truth.assertThat(result.isFailure).isTrue()
+ assertThat(result.isFailure).isTrue()
result.exceptionOrNull()!!.let { exception ->
- Truth.assertThat(exception).isInstanceOf(RuntimeException::class.java)
+ assertThat(exception).isInstanceOf(RuntimeException::class.java)
}
}
}
@@ -87,9 +88,9 @@ class DefaultVoiceMessageMediaRepoTest {
)
repo.getMediaFile().let { result ->
- Truth.assertThat(result.isFailure).isTrue()
+ assertThat(result.isFailure).isTrue()
result.exceptionOrNull()?.let { exception ->
- Truth.assertThat(exception).apply {
+ assertThat(exception).apply {
isInstanceOf(IllegalStateException::class.java)
hasMessageThat().isEqualTo("Failed to move file to cache.")
}
@@ -109,10 +110,10 @@ class DefaultVoiceMessageMediaRepoTest {
)
repo.getMediaFile().let { result ->
- Truth.assertThat(result.isSuccess).isTrue()
+ assertThat(result.isSuccess).isTrue()
result.getOrThrow().let { file ->
- Truth.assertThat(file.path).isEqualTo(temporaryFolder.cachedFilePath)
- Truth.assertThat(file.exists()).isTrue()
+ assertThat(file.path).isEqualTo(temporaryFolder.cachedFilePath)
+ assertThat(file.exists()).isTrue()
}
}
}
@@ -124,10 +125,10 @@ class DefaultVoiceMessageMediaRepoTest {
mxcUri = INVALID_MXC_URI,
)
repo.getMediaFile().let { result ->
- Truth.assertThat(result.isFailure).isTrue()
+ assertThat(result.isFailure).isTrue()
result.exceptionOrNull()!!.let { exception ->
- Truth.assertThat(exception).isInstanceOf(RuntimeException::class.java)
- Truth.assertThat(exception).hasMessageThat().isEqualTo("Invalid mxcUri.")
+ assertThat(exception).isInstanceOf(RuntimeException::class.java)
+ assertThat(exception).hasMessageThat().isEqualTo("Invalid mxcUri.")
}
}
}
@@ -139,6 +140,7 @@ private fun createDefaultVoiceMessageMediaRepo(
mxcUri: String = MXC_URI,
) = DefaultVoiceMessageMediaRepo(
cacheDir = temporaryFolder.root,
+ mxcTools = MxcTools(),
matrixMediaLoader = matrixMediaLoader,
mediaSource = MediaSource(
url = mxcUri,
diff --git a/features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/voicemessages/timeline/DefaultVoiceMessagePlayerTest.kt b/features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/voicemessages/timeline/DefaultVoiceMessagePlayerTest.kt
index c84487da1d..eb2c08d2be 100644
--- a/features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/voicemessages/timeline/DefaultVoiceMessagePlayerTest.kt
+++ b/features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/voicemessages/timeline/DefaultVoiceMessagePlayerTest.kt
@@ -18,7 +18,7 @@ package io.element.android.features.messages.impl.voicemessages.timeline
import app.cash.turbine.TurbineTestContext
import app.cash.turbine.test
-import com.google.common.truth.Truth
+import com.google.common.truth.Truth.assertThat
import io.element.android.libraries.core.mimetype.MimeTypes
import io.element.android.libraries.matrix.api.core.EventId
import io.element.android.libraries.matrix.api.media.MediaSource
@@ -42,7 +42,7 @@ class DefaultVoiceMessagePlayerTest {
val player = createDefaultVoiceMessagePlayer()
player.state.test {
matchInitialState()
- Truth.assertThat(player.prepare().isSuccess).isTrue()
+ assertThat(player.prepare().isSuccess).isTrue()
matchReadyState()
}
}
@@ -56,7 +56,7 @@ class DefaultVoiceMessagePlayerTest {
)
player.state.test {
matchInitialState()
- Truth.assertThat(player.prepare().isFailure).isTrue()
+ assertThat(player.prepare().isFailure).isTrue()
}
}
@@ -67,7 +67,7 @@ class DefaultVoiceMessagePlayerTest {
)
player.state.test {
matchInitialState()
- Truth.assertThat(player.prepare().isFailure).isTrue()
+ assertThat(player.prepare().isFailure).isTrue()
}
}
@@ -76,12 +76,12 @@ class DefaultVoiceMessagePlayerTest {
val player = createDefaultVoiceMessagePlayer()
player.state.test {
matchInitialState()
- Truth.assertThat(player.prepare().isSuccess).isTrue()
+ assertThat(player.prepare().isSuccess).isTrue()
matchReadyState()
player.play()
awaitItem().let {
- Truth.assertThat(it.isPlaying).isEqualTo(true)
- Truth.assertThat(it.currentPosition).isEqualTo(1000)
+ assertThat(it.isPlaying).isTrue()
+ assertThat(it.currentPosition).isEqualTo(1000)
}
}
}
@@ -96,15 +96,15 @@ class DefaultVoiceMessagePlayerTest {
)
player.state.test {
matchInitialState()
- Truth.assertThat(player.prepare().isSuccess).isTrue()
+ assertThat(player.prepare().isSuccess).isTrue()
matchReadyState(fakeTotalDurationMs = 1000)
player.play()
awaitItem().let {
- Truth.assertThat(it.isReady).isEqualTo(false)
- Truth.assertThat(it.isPlaying).isEqualTo(false)
- Truth.assertThat(it.isEnded).isEqualTo(true)
- Truth.assertThat(it.currentPosition).isEqualTo(1000)
- Truth.assertThat(it.duration).isEqualTo(1000)
+ assertThat(it.isReady).isFalse()
+ assertThat(it.isPlaying).isFalse()
+ assertThat(it.isEnded).isTrue()
+ assertThat(it.currentPosition).isEqualTo(1000)
+ assertThat(it.duration).isEqualTo(1000)
}
}
}
@@ -121,72 +121,72 @@ class DefaultVoiceMessagePlayerTest {
// Play player1 until the end.
player1.state.test {
matchInitialState()
- Truth.assertThat(player1.prepare().isSuccess).isTrue()
+ assertThat(player1.prepare().isSuccess).isTrue()
matchReadyState(1_000L)
player1.play()
awaitItem().let { // it plays until the end.
- Truth.assertThat(it.isReady).isEqualTo(false)
- Truth.assertThat(it.isPlaying).isEqualTo(false)
- Truth.assertThat(it.isEnded).isEqualTo(true)
- Truth.assertThat(it.currentPosition).isEqualTo(1000)
- Truth.assertThat(it.duration).isEqualTo(1000)
+ assertThat(it.isReady).isFalse()
+ assertThat(it.isPlaying).isFalse()
+ assertThat(it.isEnded).isTrue()
+ assertThat(it.currentPosition).isEqualTo(1000)
+ assertThat(it.duration).isEqualTo(1000)
}
}
// Play player2 until the end.
player2.state.test {
matchInitialState()
- Truth.assertThat(player2.prepare().isSuccess).isTrue()
+ assertThat(player2.prepare().isSuccess).isTrue()
awaitItem().let { // Additional spurious state due to MediaPlayer owner change.
- Truth.assertThat(it.isReady).isEqualTo(false)
- Truth.assertThat(it.isPlaying).isEqualTo(false)
- Truth.assertThat(it.isEnded).isEqualTo(true)
- Truth.assertThat(it.currentPosition).isEqualTo(1000)
- Truth.assertThat(it.duration).isEqualTo(1000)
+ assertThat(it.isReady).isFalse()
+ assertThat(it.isPlaying).isFalse()
+ assertThat(it.isEnded).isTrue()
+ assertThat(it.currentPosition).isEqualTo(1000)
+ assertThat(it.duration).isEqualTo(1000)
}
awaitItem().let {// Additional spurious state due to MediaPlayer owner change.
- Truth.assertThat(it.isReady).isEqualTo(false)
- Truth.assertThat(it.isPlaying).isEqualTo(false)
- Truth.assertThat(it.isEnded).isEqualTo(false)
- Truth.assertThat(it.currentPosition).isEqualTo(0)
- Truth.assertThat(it.duration).isEqualTo(null)
+ assertThat(it.isReady).isFalse()
+ assertThat(it.isPlaying).isFalse()
+ assertThat(it.isEnded).isFalse()
+ assertThat(it.currentPosition).isEqualTo(0)
+ assertThat(it.duration).isNull()
}
matchReadyState(1_000L)
player2.play()
awaitItem().let { // it plays until the end.
- Truth.assertThat(it.isReady).isEqualTo(false)
- Truth.assertThat(it.isPlaying).isEqualTo(false)
- Truth.assertThat(it.isEnded).isEqualTo(true)
- Truth.assertThat(it.currentPosition).isEqualTo(1000)
- Truth.assertThat(it.duration).isEqualTo(1000)
+ assertThat(it.isReady).isFalse()
+ assertThat(it.isPlaying).isFalse()
+ assertThat(it.isEnded).isTrue()
+ assertThat(it.currentPosition).isEqualTo(1000)
+ assertThat(it.duration).isEqualTo(1000)
}
}
// Play player1 again.
player1.state.test {
awaitItem().let {// Last previous state/
- Truth.assertThat(it.isReady).isEqualTo(false)
- Truth.assertThat(it.isPlaying).isEqualTo(false)
- Truth.assertThat(it.isEnded).isEqualTo(true)
- Truth.assertThat(it.currentPosition).isEqualTo(1000)
- Truth.assertThat(it.duration).isEqualTo(1000)
+ assertThat(it.isReady).isFalse()
+ assertThat(it.isPlaying).isFalse()
+ assertThat(it.isEnded).isTrue()
+ assertThat(it.currentPosition).isEqualTo(1000)
+ assertThat(it.duration).isEqualTo(1000)
}
- Truth.assertThat(player1.prepare().isSuccess).isTrue()
+ assertThat(player1.prepare().isSuccess).isTrue()
awaitItem().let {// Additional spurious state due to MediaPlayer owner change.
- Truth.assertThat(it.isReady).isEqualTo(false)
- Truth.assertThat(it.isPlaying).isEqualTo(false)
- Truth.assertThat(it.isEnded).isEqualTo(false)
- Truth.assertThat(it.currentPosition).isEqualTo(0)
- Truth.assertThat(it.duration).isEqualTo(null)
+ assertThat(it.isReady).isFalse()
+ assertThat(it.isPlaying).isFalse()
+ assertThat(it.isEnded).isFalse()
+ assertThat(it.currentPosition).isEqualTo(0)
+ assertThat(it.duration).isNull()
}
matchReadyState(1_000L)
player1.play()
awaitItem().let { // it played again until the end.
- Truth.assertThat(it.isReady).isEqualTo(false)
- Truth.assertThat(it.isPlaying).isEqualTo(false)
- Truth.assertThat(it.isEnded).isEqualTo(true)
- Truth.assertThat(it.currentPosition).isEqualTo(1000)
- Truth.assertThat(it.duration).isEqualTo(1000)
+ assertThat(it.isReady).isFalse()
+ assertThat(it.isPlaying).isFalse()
+ assertThat(it.isEnded).isTrue()
+ assertThat(it.currentPosition).isEqualTo(1000)
+ assertThat(it.duration).isEqualTo(1000)
}
}
}
@@ -196,14 +196,14 @@ class DefaultVoiceMessagePlayerTest {
val player = createDefaultVoiceMessagePlayer()
player.state.test {
matchInitialState()
- Truth.assertThat(player.prepare().isSuccess).isTrue()
+ assertThat(player.prepare().isSuccess).isTrue()
matchReadyState()
player.play()
skipItems(1) // skip play state
player.pause()
awaitItem().let {
- Truth.assertThat(it.isPlaying).isEqualTo(false)
- Truth.assertThat(it.currentPosition).isEqualTo(1000)
+ assertThat(it.isPlaying).isFalse()
+ assertThat(it.currentPosition).isEqualTo(1000)
}
}
}
@@ -213,7 +213,7 @@ class DefaultVoiceMessagePlayerTest {
val player = createDefaultVoiceMessagePlayer()
player.state.test {
matchInitialState()
- Truth.assertThat(player.prepare().isSuccess).isTrue()
+ assertThat(player.prepare().isSuccess).isTrue()
matchReadyState()
player.play()
skipItems(1) // skip play state
@@ -221,8 +221,8 @@ class DefaultVoiceMessagePlayerTest {
skipItems(1) // skip pause state
player.play()
awaitItem().let {
- Truth.assertThat(it.isPlaying).isEqualTo(true)
- Truth.assertThat(it.currentPosition).isEqualTo(2000)
+ assertThat(it.isPlaying).isTrue()
+ assertThat(it.currentPosition).isEqualTo(2000)
}
}
}
@@ -234,19 +234,19 @@ class DefaultVoiceMessagePlayerTest {
matchInitialState()
player.seekTo(2000)
awaitItem().let {
- Truth.assertThat(it.isReady).isEqualTo(false)
- Truth.assertThat(it.isPlaying).isEqualTo(false)
- Truth.assertThat(it.isEnded).isEqualTo(false)
- Truth.assertThat(it.currentPosition).isEqualTo(2000)
- Truth.assertThat(it.duration).isEqualTo(null)
+ assertThat(it.isReady).isFalse()
+ assertThat(it.isPlaying).isFalse()
+ assertThat(it.isEnded).isFalse()
+ assertThat(it.currentPosition).isEqualTo(2000)
+ assertThat(it.duration).isNull()
}
- Truth.assertThat(player.prepare().isSuccess).isTrue()
+ assertThat(player.prepare().isSuccess).isTrue()
awaitItem().let {
- Truth.assertThat(it.isReady).isEqualTo(true)
- Truth.assertThat(it.isPlaying).isEqualTo(false)
- Truth.assertThat(it.isEnded).isEqualTo(false)
- Truth.assertThat(it.currentPosition).isEqualTo(2000)
- Truth.assertThat(it.duration).isEqualTo(FAKE_TOTAL_DURATION_MS)
+ assertThat(it.isReady).isTrue()
+ assertThat(it.isPlaying).isFalse()
+ assertThat(it.isEnded).isFalse()
+ assertThat(it.currentPosition).isEqualTo(2000)
+ assertThat(it.duration).isEqualTo(FAKE_TOTAL_DURATION_MS)
}
}
}
@@ -256,15 +256,15 @@ class DefaultVoiceMessagePlayerTest {
val player = createDefaultVoiceMessagePlayer()
player.state.test {
matchInitialState()
- Truth.assertThat(player.prepare().isSuccess).isTrue()
+ assertThat(player.prepare().isSuccess).isTrue()
matchReadyState()
player.seekTo(2000)
awaitItem().let {
- Truth.assertThat(it.isReady).isEqualTo(true)
- Truth.assertThat(it.isPlaying).isEqualTo(false)
- Truth.assertThat(it.isEnded).isEqualTo(false)
- Truth.assertThat(it.currentPosition).isEqualTo(2000)
- Truth.assertThat(it.duration).isEqualTo(FAKE_TOTAL_DURATION_MS)
+ assertThat(it.isReady).isTrue()
+ assertThat(it.isPlaying).isFalse()
+ assertThat(it.isEnded).isFalse()
+ assertThat(it.currentPosition).isEqualTo(2000)
+ assertThat(it.duration).isEqualTo(FAKE_TOTAL_DURATION_MS)
}
}
}
@@ -296,11 +296,11 @@ private const val MXC_URI = "mxc://matrix.org/1234567890abcdefg"
private suspend fun TurbineTestContext.matchInitialState() {
awaitItem().let {
- Truth.assertThat(it.isReady).isEqualTo(false)
- Truth.assertThat(it.isPlaying).isEqualTo(false)
- Truth.assertThat(it.isEnded).isEqualTo(false)
- Truth.assertThat(it.currentPosition).isEqualTo(0)
- Truth.assertThat(it.duration).isEqualTo(null)
+ assertThat(it.isReady).isFalse()
+ assertThat(it.isPlaying).isFalse()
+ assertThat(it.isEnded).isFalse()
+ assertThat(it.currentPosition).isEqualTo(0)
+ assertThat(it.duration).isNull()
}
}
@@ -308,10 +308,10 @@ private suspend fun TurbineTestContext.matchReadyState
fakeTotalDurationMs: Long = FAKE_TOTAL_DURATION_MS,
) {
awaitItem().let {
- Truth.assertThat(it.isReady).isEqualTo(true)
- Truth.assertThat(it.isPlaying).isEqualTo(false)
- Truth.assertThat(it.isEnded).isEqualTo(false)
- Truth.assertThat(it.currentPosition).isEqualTo(0)
- Truth.assertThat(it.duration).isEqualTo(fakeTotalDurationMs)
+ assertThat(it.isReady).isTrue()
+ assertThat(it.isPlaying).isFalse()
+ assertThat(it.isEnded).isFalse()
+ assertThat(it.currentPosition).isEqualTo(0)
+ assertThat(it.duration).isEqualTo(fakeTotalDurationMs)
}
}
diff --git a/features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/voicemessages/timeline/RedactedVoiceMessageManagerTest.kt b/features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/voicemessages/timeline/RedactedVoiceMessageManagerTest.kt
index 3a003e23a9..00eb7141c3 100644
--- a/features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/voicemessages/timeline/RedactedVoiceMessageManagerTest.kt
+++ b/features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/voicemessages/timeline/RedactedVoiceMessageManagerTest.kt
@@ -16,7 +16,7 @@
package io.element.android.features.messages.impl.voicemessages.timeline
-import com.google.common.truth.Truth
+import com.google.common.truth.Truth.assertThat
import io.element.android.libraries.core.mimetype.MimeTypes
import io.element.android.libraries.matrix.api.core.EventId
import io.element.android.libraries.matrix.api.timeline.MatrixTimelineItem
@@ -44,13 +44,13 @@ class RedactedVoiceMessageManagerTest {
}
val manager = aDefaultRedactedVoiceMessageManager(mediaPlayer = mediaPlayer)
- Truth.assertThat(mediaPlayer.state.value.mediaId).isEqualTo(AN_EVENT_ID.value)
- Truth.assertThat(mediaPlayer.state.value.isPlaying).isTrue()
+ assertThat(mediaPlayer.state.value.mediaId).isEqualTo(AN_EVENT_ID.value)
+ assertThat(mediaPlayer.state.value.isPlaying).isTrue()
manager.onEachMatrixTimelineItem(aRedactedMatrixTimeline(AN_EVENT_ID_2))
- Truth.assertThat(mediaPlayer.state.value.mediaId).isEqualTo(AN_EVENT_ID.value)
- Truth.assertThat(mediaPlayer.state.value.isPlaying).isTrue()
+ assertThat(mediaPlayer.state.value.mediaId).isEqualTo(AN_EVENT_ID.value)
+ assertThat(mediaPlayer.state.value.isPlaying).isTrue()
}
@Test
@@ -61,13 +61,13 @@ class RedactedVoiceMessageManagerTest {
}
val manager = aDefaultRedactedVoiceMessageManager(mediaPlayer = mediaPlayer)
- Truth.assertThat(mediaPlayer.state.value.mediaId).isEqualTo(AN_EVENT_ID.value)
- Truth.assertThat(mediaPlayer.state.value.isPlaying).isTrue()
+ assertThat(mediaPlayer.state.value.mediaId).isEqualTo(AN_EVENT_ID.value)
+ assertThat(mediaPlayer.state.value.isPlaying).isTrue()
manager.onEachMatrixTimelineItem(aRedactedMatrixTimeline(AN_EVENT_ID))
- Truth.assertThat(mediaPlayer.state.value.mediaId).isEqualTo(AN_EVENT_ID.value)
- Truth.assertThat(mediaPlayer.state.value.isPlaying).isFalse()
+ assertThat(mediaPlayer.state.value.mediaId).isEqualTo(AN_EVENT_ID.value)
+ assertThat(mediaPlayer.state.value.isPlaying).isFalse()
}
}
diff --git a/features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/voicemessages/timeline/VoiceMessagePresenterTest.kt b/features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/voicemessages/timeline/VoiceMessagePresenterTest.kt
index 9d885016d8..00b0874696 100644
--- a/features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/voicemessages/timeline/VoiceMessagePresenterTest.kt
+++ b/features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/voicemessages/timeline/VoiceMessagePresenterTest.kt
@@ -19,7 +19,7 @@ package io.element.android.features.messages.impl.voicemessages.timeline
import app.cash.molecule.RecompositionMode
import app.cash.molecule.moleculeFlow
import app.cash.turbine.test
-import com.google.common.truth.Truth
+import com.google.common.truth.Truth.assertThat
import io.element.android.features.messages.impl.timeline.model.event.TimelineItemVoiceContent
import io.element.android.features.messages.impl.timeline.model.event.aTimelineItemVoiceContent
import io.element.android.features.messages.impl.voicemessages.VoiceMessageException
@@ -39,9 +39,9 @@ class VoiceMessagePresenterTest {
presenter.present()
}.test {
awaitItem().let {
- Truth.assertThat(it.button).isEqualTo(VoiceMessageState.Button.Play)
- Truth.assertThat(it.progress).isEqualTo(0f)
- Truth.assertThat(it.time).isEqualTo("1:01")
+ assertThat(it.button).isEqualTo(VoiceMessageState.Button.Play)
+ assertThat(it.progress).isEqualTo(0f)
+ assertThat(it.time).isEqualTo("1:01")
}
}
}
@@ -56,27 +56,27 @@ class VoiceMessagePresenterTest {
presenter.present()
}.test {
val initialState = awaitItem().also {
- Truth.assertThat(it.button).isEqualTo(VoiceMessageState.Button.Play)
- Truth.assertThat(it.progress).isEqualTo(0f)
- Truth.assertThat(it.time).isEqualTo("0:02")
+ assertThat(it.button).isEqualTo(VoiceMessageState.Button.Play)
+ assertThat(it.progress).isEqualTo(0f)
+ assertThat(it.time).isEqualTo("0:02")
}
initialState.eventSink(VoiceMessageEvents.PlayPause)
awaitItem().also {
- Truth.assertThat(it.button).isEqualTo(VoiceMessageState.Button.Downloading)
- Truth.assertThat(it.progress).isEqualTo(0f)
- Truth.assertThat(it.time).isEqualTo("0:02")
+ assertThat(it.button).isEqualTo(VoiceMessageState.Button.Downloading)
+ assertThat(it.progress).isEqualTo(0f)
+ assertThat(it.time).isEqualTo("0:02")
}
awaitItem().also {
- Truth.assertThat(it.button).isEqualTo(VoiceMessageState.Button.Downloading)
- Truth.assertThat(it.progress).isEqualTo(0f)
- Truth.assertThat(it.time).isEqualTo("0:00")
+ assertThat(it.button).isEqualTo(VoiceMessageState.Button.Downloading)
+ assertThat(it.progress).isEqualTo(0f)
+ assertThat(it.time).isEqualTo("0:00")
}
awaitItem().also {
- Truth.assertThat(it.button).isEqualTo(VoiceMessageState.Button.Pause)
- Truth.assertThat(it.progress).isEqualTo(0.5f)
- Truth.assertThat(it.time).isEqualTo("0:01")
+ assertThat(it.button).isEqualTo(VoiceMessageState.Button.Pause)
+ assertThat(it.progress).isEqualTo(0.5f)
+ assertThat(it.time).isEqualTo("0:01")
}
}
}
@@ -94,25 +94,25 @@ class VoiceMessagePresenterTest {
presenter.present()
}.test {
val initialState = awaitItem().also {
- Truth.assertThat(it.button).isEqualTo(VoiceMessageState.Button.Play)
- Truth.assertThat(it.progress).isEqualTo(0f)
- Truth.assertThat(it.time).isEqualTo("0:02")
+ assertThat(it.button).isEqualTo(VoiceMessageState.Button.Play)
+ assertThat(it.progress).isEqualTo(0f)
+ assertThat(it.time).isEqualTo("0:02")
}
initialState.eventSink(VoiceMessageEvents.PlayPause)
awaitItem().also {
- Truth.assertThat(it.button).isEqualTo(VoiceMessageState.Button.Downloading)
- Truth.assertThat(it.progress).isEqualTo(0f)
- Truth.assertThat(it.time).isEqualTo("0:02")
+ assertThat(it.button).isEqualTo(VoiceMessageState.Button.Downloading)
+ assertThat(it.progress).isEqualTo(0f)
+ assertThat(it.time).isEqualTo("0:02")
}
awaitItem().also {
- Truth.assertThat(it.button).isEqualTo(VoiceMessageState.Button.Retry)
- Truth.assertThat(it.progress).isEqualTo(0f)
- Truth.assertThat(it.time).isEqualTo("0:02")
+ assertThat(it.button).isEqualTo(VoiceMessageState.Button.Retry)
+ assertThat(it.progress).isEqualTo(0f)
+ assertThat(it.time).isEqualTo("0:02")
}
analyticsService.trackedErrors.first().also {
- Truth.assertThat(it).apply {
+ assertThat(it).apply {
isInstanceOf(VoiceMessageException.PlayMessageError::class.java)
hasMessageThat().isEqualTo("Error while trying to play voice message")
}
@@ -130,25 +130,25 @@ class VoiceMessagePresenterTest {
presenter.present()
}.test {
val initialState = awaitItem().also {
- Truth.assertThat(it.button).isEqualTo(VoiceMessageState.Button.Play)
- Truth.assertThat(it.progress).isEqualTo(0f)
- Truth.assertThat(it.time).isEqualTo("0:02")
+ assertThat(it.button).isEqualTo(VoiceMessageState.Button.Play)
+ assertThat(it.progress).isEqualTo(0f)
+ assertThat(it.time).isEqualTo("0:02")
}
initialState.eventSink(VoiceMessageEvents.PlayPause)
skipItems(2) // skip downloading states
val playingState = awaitItem().also {
- Truth.assertThat(it.button).isEqualTo(VoiceMessageState.Button.Pause)
- Truth.assertThat(it.progress).isEqualTo(0.5f)
- Truth.assertThat(it.time).isEqualTo("0:01")
+ assertThat(it.button).isEqualTo(VoiceMessageState.Button.Pause)
+ assertThat(it.progress).isEqualTo(0.5f)
+ assertThat(it.time).isEqualTo("0:01")
}
playingState.eventSink(VoiceMessageEvents.PlayPause)
awaitItem().also {
- Truth.assertThat(it.button).isEqualTo(VoiceMessageState.Button.Play)
- Truth.assertThat(it.progress).isEqualTo(0.5f)
- Truth.assertThat(it.time).isEqualTo("0:01")
+ assertThat(it.button).isEqualTo(VoiceMessageState.Button.Play)
+ assertThat(it.progress).isEqualTo(0.5f)
+ assertThat(it.time).isEqualTo("0:01")
}
}
}
@@ -162,9 +162,9 @@ class VoiceMessagePresenterTest {
presenter.present()
}.test {
awaitItem().also {
- Truth.assertThat(it.button).isEqualTo(VoiceMessageState.Button.Disabled)
- Truth.assertThat(it.progress).isEqualTo(0f)
- Truth.assertThat(it.time).isEqualTo("1:01")
+ assertThat(it.button).isEqualTo(VoiceMessageState.Button.Disabled)
+ assertThat(it.progress).isEqualTo(0f)
+ assertThat(it.time).isEqualTo("1:01")
}
}
}
@@ -179,17 +179,17 @@ class VoiceMessagePresenterTest {
presenter.present()
}.test {
val initialState = awaitItem().also {
- Truth.assertThat(it.button).isEqualTo(VoiceMessageState.Button.Play)
- Truth.assertThat(it.progress).isEqualTo(0f)
- Truth.assertThat(it.time).isEqualTo("0:10")
+ assertThat(it.button).isEqualTo(VoiceMessageState.Button.Play)
+ assertThat(it.progress).isEqualTo(0f)
+ assertThat(it.time).isEqualTo("0:10")
}
initialState.eventSink(VoiceMessageEvents.Seek(0.5f))
awaitItem().also {
- Truth.assertThat(it.button).isEqualTo(VoiceMessageState.Button.Play)
- Truth.assertThat(it.progress).isEqualTo(0.5f)
- Truth.assertThat(it.time).isEqualTo("0:05")
+ assertThat(it.button).isEqualTo(VoiceMessageState.Button.Play)
+ assertThat(it.progress).isEqualTo(0.5f)
+ assertThat(it.time).isEqualTo("0:05")
}
}
}
@@ -203,9 +203,9 @@ class VoiceMessagePresenterTest {
presenter.present()
}.test {
val initialState = awaitItem().also {
- Truth.assertThat(it.button).isEqualTo(VoiceMessageState.Button.Play)
- Truth.assertThat(it.progress).isEqualTo(0f)
- Truth.assertThat(it.time).isEqualTo("0:10")
+ assertThat(it.button).isEqualTo(VoiceMessageState.Button.Play)
+ assertThat(it.progress).isEqualTo(0f)
+ assertThat(it.time).isEqualTo("0:10")
}
initialState.eventSink(VoiceMessageEvents.PlayPause)
@@ -213,17 +213,17 @@ class VoiceMessagePresenterTest {
skipItems(2) // skip downloading states
awaitItem().also {
- Truth.assertThat(it.button).isEqualTo(VoiceMessageState.Button.Pause)
- Truth.assertThat(it.progress).isEqualTo(0.1f)
- Truth.assertThat(it.time).isEqualTo("0:01")
+ assertThat(it.button).isEqualTo(VoiceMessageState.Button.Pause)
+ assertThat(it.progress).isEqualTo(0.1f)
+ assertThat(it.time).isEqualTo("0:01")
}
initialState.eventSink(VoiceMessageEvents.Seek(0.5f))
awaitItem().also {
- Truth.assertThat(it.button).isEqualTo(VoiceMessageState.Button.Pause)
- Truth.assertThat(it.progress).isEqualTo(0.5f)
- Truth.assertThat(it.time).isEqualTo("0:05")
+ assertThat(it.button).isEqualTo(VoiceMessageState.Button.Pause)
+ assertThat(it.progress).isEqualTo(0.5f)
+ assertThat(it.time).isEqualTo("0:05")
}
}
}
diff --git a/features/onboarding/impl/src/main/res/values-hu/translations.xml b/features/onboarding/impl/src/main/res/values-hu/translations.xml
new file mode 100644
index 0000000000..8acd47c566
--- /dev/null
+++ b/features/onboarding/impl/src/main/res/values-hu/translations.xml
@@ -0,0 +1,9 @@
+
+
+ "Kézi bejelentkezés"
+ "Bejelentkezés QR-kóddal"
+ "Fiók létrehozása"
+ "Üdvözöljük a valaha volt leggyorsabb Elementben. Felturbózva, a sebesség és az egyszerűség érdekében."
+ "Üdvözli az %1$s. Felturbózva, a sebesség és az egyszerűség jegyében."
+ "Legyen elemében"
+
diff --git a/features/onboarding/impl/src/main/res/values-in/translations.xml b/features/onboarding/impl/src/main/res/values-in/translations.xml
new file mode 100644
index 0000000000..06946a3cd8
--- /dev/null
+++ b/features/onboarding/impl/src/main/res/values-in/translations.xml
@@ -0,0 +1,9 @@
+
+
+ "Masuk secara manual"
+ "Masuk dengan kode QR"
+ "Buat akun"
+ "Selamat datang di Element tercepat yang pernah ada. Berdaya besar untuk kecepatan dan kesederhanaan."
+ "Selamat datang di %1$s. Berdaya penuh, untuk kecepatan dan kesederhanaan."
+ "Berada di elemen Anda"
+
diff --git a/features/poll/impl/src/main/res/values-de/translations.xml b/features/poll/impl/src/main/res/values-de/translations.xml
index 30b16ec585..c340f85258 100644
--- a/features/poll/impl/src/main/res/values-de/translations.xml
+++ b/features/poll/impl/src/main/res/values-de/translations.xml
@@ -4,7 +4,11 @@
"Ergebnisse erst nach Ende der Umfrage anzeigen"
"Anonyme Umfrage"
"Option %1$d"
+ "Deine Änderungen wurden nicht gespeichert. Bist du sicher, dass du zurückgehen willst?"
"Frage oder Thema"
"Worum geht es bei der Umfrage?"
"Umfrage erstellen"
+ "Bist du dir sicher, dass du diese Umfrage löschen möchtest?"
+ "Umfrage löschen"
+ "Umfrage bearbeiten"
diff --git a/features/poll/impl/src/main/res/values-fr/translations.xml b/features/poll/impl/src/main/res/values-fr/translations.xml
index e323fe5711..8e371bf1d8 100644
--- a/features/poll/impl/src/main/res/values-fr/translations.xml
+++ b/features/poll/impl/src/main/res/values-fr/translations.xml
@@ -4,7 +4,11 @@
"Afficher les résultats uniquement après la fin du sondage"
"Masquer les votes"
"Option %1$d"
+ "Vos modifications n’ont pas été enregistrées. Êtes-vous certain de vouloir quitter?"
"Question ou sujet"
"Quel est le sujet du sondage ?"
"Créer un sondage"
+ "Êtes-vous certain de vouloir supprimer ce sondage?"
+ "Supprimer le sondage"
+ "Modifier le sondage"
diff --git a/features/poll/impl/src/main/res/values-hu/translations.xml b/features/poll/impl/src/main/res/values-hu/translations.xml
new file mode 100644
index 0000000000..b607c49e23
--- /dev/null
+++ b/features/poll/impl/src/main/res/values-hu/translations.xml
@@ -0,0 +1,14 @@
+
+
+ "Lehetőség hozzáadása"
+ "Eredmények megjelenítése csak a szavazás befejezése után"
+ "Szavazatok elrejtése"
+ "%1$d. lehetőség"
+ "A módosítások nem lettek mentve. Biztos, hogy vissza akar lépni?"
+ "Kérdés vagy téma"
+ "Miről szól ez a szavazás?"
+ "Szavazás létrehozása"
+ "Biztos, hogy törli ezt a szavazást?"
+ "Szavazás törlése"
+ "Szavazás szerkesztése"
+
diff --git a/features/poll/impl/src/main/res/values-in/translations.xml b/features/poll/impl/src/main/res/values-in/translations.xml
new file mode 100644
index 0000000000..b8982d9c13
--- /dev/null
+++ b/features/poll/impl/src/main/res/values-in/translations.xml
@@ -0,0 +1,14 @@
+
+
+ "Tambahkan opsi"
+ "Tampilkan hasil hanya setelah pemungutan suara berakhir"
+ "Pemungutan suara anonim"
+ "Opsi %1$d"
+ "Perubahan Anda belum disimpan. Apakah Anda yakin ingin kembali?"
+ "Pertanyaan atau topik"
+ "Tentang apa pemungutan suara ini?"
+ "Buat pemungutan suara"
+ "Apakah Anda yakin ingin menghapus pemungutan suara ini?"
+ "Hapus pemungutan suara"
+ "Sunting pemungutan suara"
+
diff --git a/features/poll/impl/src/test/kotlin/io/element/android/features/poll/impl/create/CreatePollPresenterTest.kt b/features/poll/impl/src/test/kotlin/io/element/android/features/poll/impl/create/CreatePollPresenterTest.kt
index 114e7cb48f..5ee32efeb2 100644
--- a/features/poll/impl/src/test/kotlin/io/element/android/features/poll/impl/create/CreatePollPresenterTest.kt
+++ b/features/poll/impl/src/test/kotlin/io/element/android/features/poll/impl/create/CreatePollPresenterTest.kt
@@ -20,7 +20,7 @@ import app.cash.molecule.RecompositionMode
import app.cash.molecule.moleculeFlow
import app.cash.turbine.TurbineTestContext
import app.cash.turbine.test
-import com.google.common.truth.Truth
+import com.google.common.truth.Truth.assertThat
import im.vector.app.features.analytics.plan.Composer
import im.vector.app.features.analytics.plan.PollCreation
import io.element.android.features.messages.test.FakeMessageComposerContext
@@ -88,8 +88,8 @@ class CreatePollPresenterTest {
presenter.present()
}.test {
awaitDefaultItem()
- Truth.assertThat(fakeAnalyticsService.trackedErrors.filterIsInstance()).isNotEmpty()
- Truth.assertThat(navUpInvocationsCount).isEqualTo(1)
+ assertThat(fakeAnalyticsService.trackedErrors.filterIsInstance()).isNotEmpty()
+ assertThat(navUpInvocationsCount).isEqualTo(1)
}
}
@@ -100,19 +100,19 @@ class CreatePollPresenterTest {
presenter.present()
}.test {
val initial = awaitItem()
- Truth.assertThat(initial.canSave).isFalse()
+ assertThat(initial.canSave).isFalse()
initial.eventSink(CreatePollEvents.SetQuestion("A question?"))
val questionSet = awaitItem()
- Truth.assertThat(questionSet.canSave).isFalse()
+ assertThat(questionSet.canSave).isFalse()
questionSet.eventSink(CreatePollEvents.SetAnswer(0, "Answer 1"))
val answer1Set = awaitItem()
- Truth.assertThat(answer1Set.canSave).isFalse()
+ assertThat(answer1Set.canSave).isFalse()
answer1Set.eventSink(CreatePollEvents.SetAnswer(1, "Answer 2"))
val answer2Set = awaitItem()
- Truth.assertThat(answer2Set.canSave).isTrue()
+ assertThat(answer2Set.canSave).isTrue()
}
}
@@ -129,8 +129,8 @@ class CreatePollPresenterTest {
skipItems(3)
initial.eventSink(CreatePollEvents.Save)
delay(1) // Wait for the coroutine to finish
- Truth.assertThat(fakeMatrixRoom.createPollInvocations.size).isEqualTo(1)
- Truth.assertThat(fakeMatrixRoom.createPollInvocations.last()).isEqualTo(
+ assertThat(fakeMatrixRoom.createPollInvocations.size).isEqualTo(1)
+ assertThat(fakeMatrixRoom.createPollInvocations.last()).isEqualTo(
SavePollInvocation(
question = "A question?",
answers = listOf("Answer 1", "Answer 2"),
@@ -138,8 +138,8 @@ class CreatePollPresenterTest {
pollKind = PollKind.Disclosed
)
)
- Truth.assertThat(fakeAnalyticsService.capturedEvents.size).isEqualTo(2)
- Truth.assertThat(fakeAnalyticsService.capturedEvents[0]).isEqualTo(
+ assertThat(fakeAnalyticsService.capturedEvents.size).isEqualTo(2)
+ assertThat(fakeAnalyticsService.capturedEvents[0]).isEqualTo(
Composer(
inThread = false,
isEditing = false,
@@ -147,7 +147,7 @@ class CreatePollPresenterTest {
messageType = Composer.MessageType.Poll,
)
)
- Truth.assertThat(fakeAnalyticsService.capturedEvents[1]).isEqualTo(
+ assertThat(fakeAnalyticsService.capturedEvents[1]).isEqualTo(
PollCreation(
action = PollCreation.Action.Create,
isUndisclosed = false,
@@ -170,10 +170,10 @@ class CreatePollPresenterTest {
awaitItem().eventSink(CreatePollEvents.SetAnswer(1, "Answer 2"))
awaitItem().eventSink(CreatePollEvents.Save)
delay(1) // Wait for the coroutine to finish
- Truth.assertThat(fakeMatrixRoom.createPollInvocations).hasSize(1)
- Truth.assertThat(fakeAnalyticsService.capturedEvents).isEmpty()
- Truth.assertThat(fakeAnalyticsService.trackedErrors).hasSize(1)
- Truth.assertThat(fakeAnalyticsService.trackedErrors).containsExactly(
+ assertThat(fakeMatrixRoom.createPollInvocations).hasSize(1)
+ assertThat(fakeAnalyticsService.capturedEvents).isEmpty()
+ assertThat(fakeAnalyticsService.trackedErrors).hasSize(1)
+ assertThat(fakeAnalyticsService.trackedErrors).containsExactly(
CreatePollException.SavePollFailed("Failed to create poll", error)
)
}
@@ -203,8 +203,8 @@ class CreatePollPresenterTest {
eventSink(CreatePollEvents.Save)
}
delay(1) // Wait for the coroutine to finish
- Truth.assertThat(fakeMatrixRoom.editPollInvocations.size).isEqualTo(1)
- Truth.assertThat(fakeMatrixRoom.editPollInvocations.last()).isEqualTo(
+ assertThat(fakeMatrixRoom.editPollInvocations.size).isEqualTo(1)
+ assertThat(fakeMatrixRoom.editPollInvocations.last()).isEqualTo(
SavePollInvocation(
question = "Changed question",
answers = listOf("Changed answer 1", "Changed answer 2", "Maybe"),
@@ -212,8 +212,8 @@ class CreatePollPresenterTest {
pollKind = PollKind.Disclosed
)
)
- Truth.assertThat(fakeAnalyticsService.capturedEvents.size).isEqualTo(2)
- Truth.assertThat(fakeAnalyticsService.capturedEvents[0]).isEqualTo(
+ assertThat(fakeAnalyticsService.capturedEvents.size).isEqualTo(2)
+ assertThat(fakeAnalyticsService.capturedEvents[0]).isEqualTo(
Composer(
inThread = false,
isEditing = true,
@@ -221,7 +221,7 @@ class CreatePollPresenterTest {
messageType = Composer.MessageType.Poll,
)
)
- Truth.assertThat(fakeAnalyticsService.capturedEvents[1]).isEqualTo(
+ assertThat(fakeAnalyticsService.capturedEvents[1]).isEqualTo(
PollCreation(
action = PollCreation.Action.Edit,
isUndisclosed = false,
@@ -243,10 +243,10 @@ class CreatePollPresenterTest {
awaitPollLoaded().eventSink(CreatePollEvents.SetAnswer(0, "A"))
awaitPollLoaded(newAnswer1 = "A").eventSink(CreatePollEvents.Save)
delay(1) // Wait for the coroutine to finish
- Truth.assertThat(fakeMatrixRoom.editPollInvocations).hasSize(1)
- Truth.assertThat(fakeAnalyticsService.capturedEvents).isEmpty()
- Truth.assertThat(fakeAnalyticsService.trackedErrors).hasSize(1)
- Truth.assertThat(fakeAnalyticsService.trackedErrors).containsExactly(
+ assertThat(fakeMatrixRoom.editPollInvocations).hasSize(1)
+ assertThat(fakeAnalyticsService.capturedEvents).isEmpty()
+ assertThat(fakeAnalyticsService.trackedErrors).hasSize(1)
+ assertThat(fakeAnalyticsService.trackedErrors).containsExactly(
CreatePollException.SavePollFailed("Failed to edit poll", error)
)
}
@@ -259,16 +259,16 @@ class CreatePollPresenterTest {
presenter.present()
}.test {
val initial = awaitItem()
- Truth.assertThat(initial.answers.size).isEqualTo(2)
+ assertThat(initial.answers.size).isEqualTo(2)
initial.eventSink(CreatePollEvents.AddAnswer)
val answerAdded = awaitItem()
- Truth.assertThat(answerAdded.answers.size).isEqualTo(3)
- Truth.assertThat(answerAdded.answers[2].text).isEmpty()
+ assertThat(answerAdded.answers.size).isEqualTo(3)
+ assertThat(answerAdded.answers[2].text).isEmpty()
initial.eventSink(CreatePollEvents.RemoveAnswer(2))
val answerRemoved = awaitItem()
- Truth.assertThat(answerRemoved.answers.size).isEqualTo(2)
+ assertThat(answerRemoved.answers.size).isEqualTo(2)
}
}
@@ -281,7 +281,7 @@ class CreatePollPresenterTest {
val initial = awaitItem()
initial.eventSink(CreatePollEvents.SetQuestion("A question?"))
val questionSet = awaitItem()
- Truth.assertThat(questionSet.question).isEqualTo("A question?")
+ assertThat(questionSet.question).isEqualTo("A question?")
}
}
@@ -294,7 +294,7 @@ class CreatePollPresenterTest {
val initial = awaitItem()
initial.eventSink(CreatePollEvents.SetAnswer(0, "This is answer 1"))
val answerSet = awaitItem()
- Truth.assertThat(answerSet.answers.first().text).isEqualTo("This is answer 1")
+ assertThat(answerSet.answers.first().text).isEqualTo("This is answer 1")
}
}
@@ -307,7 +307,7 @@ class CreatePollPresenterTest {
val initial = awaitItem()
initial.eventSink(CreatePollEvents.SetPollKind(PollKind.Undisclosed))
val kindSet = awaitItem()
- Truth.assertThat(kindSet.pollKind).isEqualTo(PollKind.Undisclosed)
+ assertThat(kindSet.pollKind).isEqualTo(PollKind.Undisclosed)
}
}
@@ -318,13 +318,13 @@ class CreatePollPresenterTest {
presenter.present()
}.test {
val initial = awaitItem()
- Truth.assertThat(initial.canAddAnswer).isTrue()
+ assertThat(initial.canAddAnswer).isTrue()
repeat(17) {
initial.eventSink(CreatePollEvents.AddAnswer)
- Truth.assertThat(awaitItem().canAddAnswer).isTrue()
+ assertThat(awaitItem().canAddAnswer).isTrue()
}
initial.eventSink(CreatePollEvents.AddAnswer)
- Truth.assertThat(awaitItem().canAddAnswer).isFalse()
+ assertThat(awaitItem().canAddAnswer).isFalse()
}
}
@@ -335,9 +335,9 @@ class CreatePollPresenterTest {
presenter.present()
}.test {
val initial = awaitItem()
- Truth.assertThat(initial.answers.all { it.canDelete }).isFalse()
+ assertThat(initial.answers.all { it.canDelete }).isFalse()
initial.eventSink(CreatePollEvents.AddAnswer)
- Truth.assertThat(awaitItem().answers.all { it.canDelete }).isTrue()
+ assertThat(awaitItem().answers.all { it.canDelete }).isTrue()
}
}
@@ -349,7 +349,7 @@ class CreatePollPresenterTest {
}.test {
val initial = awaitItem()
initial.eventSink(CreatePollEvents.SetAnswer(0, "A".repeat(241)))
- Truth.assertThat(awaitItem().answers.first().text.length).isEqualTo(240)
+ assertThat(awaitItem().answers.first().text.length).isEqualTo(240)
}
}
@@ -360,9 +360,9 @@ class CreatePollPresenterTest {
presenter.present()
}.test {
val initial = awaitItem()
- Truth.assertThat(navUpInvocationsCount).isEqualTo(0)
+ assertThat(navUpInvocationsCount).isEqualTo(0)
initial.eventSink(CreatePollEvents.NavBack)
- Truth.assertThat(navUpInvocationsCount).isEqualTo(1)
+ assertThat(navUpInvocationsCount).isEqualTo(1)
}
}
@@ -373,10 +373,10 @@ class CreatePollPresenterTest {
presenter.present()
}.test {
val initial = awaitItem()
- Truth.assertThat(navUpInvocationsCount).isEqualTo(0)
- Truth.assertThat(initial.showBackConfirmation).isFalse()
+ assertThat(navUpInvocationsCount).isEqualTo(0)
+ assertThat(initial.showBackConfirmation).isFalse()
initial.eventSink(CreatePollEvents.ConfirmNavBack)
- Truth.assertThat(navUpInvocationsCount).isEqualTo(1)
+ assertThat(navUpInvocationsCount).isEqualTo(1)
}
}
@@ -388,12 +388,12 @@ class CreatePollPresenterTest {
}.test {
val initial = awaitItem()
initial.eventSink(CreatePollEvents.SetQuestion("Non blank"))
- Truth.assertThat(awaitItem().showBackConfirmation).isFalse()
+ assertThat(awaitItem().showBackConfirmation).isFalse()
initial.eventSink(CreatePollEvents.ConfirmNavBack)
- Truth.assertThat(awaitItem().showBackConfirmation).isTrue()
+ assertThat(awaitItem().showBackConfirmation).isTrue()
initial.eventSink(CreatePollEvents.HideConfirmation)
- Truth.assertThat(awaitItem().showBackConfirmation).isFalse()
- Truth.assertThat(navUpInvocationsCount).isEqualTo(0)
+ assertThat(awaitItem().showBackConfirmation).isFalse()
+ assertThat(navUpInvocationsCount).isEqualTo(0)
}
}
@@ -405,10 +405,10 @@ class CreatePollPresenterTest {
}.test {
awaitDefaultItem()
val loaded = awaitPollLoaded()
- Truth.assertThat(navUpInvocationsCount).isEqualTo(0)
- Truth.assertThat(loaded.showBackConfirmation).isFalse()
+ assertThat(navUpInvocationsCount).isEqualTo(0)
+ assertThat(loaded.showBackConfirmation).isFalse()
loaded.eventSink(CreatePollEvents.ConfirmNavBack)
- Truth.assertThat(navUpInvocationsCount).isEqualTo(1)
+ assertThat(navUpInvocationsCount).isEqualTo(1)
}
}
@@ -421,12 +421,12 @@ class CreatePollPresenterTest {
awaitDefaultItem()
val loaded = awaitPollLoaded()
loaded.eventSink(CreatePollEvents.SetQuestion("CHANGED"))
- Truth.assertThat(awaitItem().showBackConfirmation).isFalse()
+ assertThat(awaitItem().showBackConfirmation).isFalse()
loaded.eventSink(CreatePollEvents.ConfirmNavBack)
- Truth.assertThat(awaitItem().showBackConfirmation).isTrue()
+ assertThat(awaitItem().showBackConfirmation).isTrue()
loaded.eventSink(CreatePollEvents.HideConfirmation)
- Truth.assertThat(awaitItem().showBackConfirmation).isFalse()
- Truth.assertThat(navUpInvocationsCount).isEqualTo(0)
+ assertThat(awaitItem().showBackConfirmation).isFalse()
+ assertThat(navUpInvocationsCount).isEqualTo(0)
}
}
@@ -439,7 +439,7 @@ class CreatePollPresenterTest {
awaitDefaultItem()
awaitPollLoaded().eventSink(CreatePollEvents.Delete(confirmed = false))
awaitDeleteConfirmation()
- Truth.assertThat(fakeMatrixRoom.redactEventEventIdParam).isNull()
+ assertThat(fakeMatrixRoom.redactEventEventIdParam).isNull()
}
}
@@ -451,12 +451,12 @@ class CreatePollPresenterTest {
}.test {
awaitDefaultItem()
awaitPollLoaded().eventSink(CreatePollEvents.Delete(confirmed = false))
- Truth.assertThat(fakeMatrixRoom.redactEventEventIdParam).isNull()
+ assertThat(fakeMatrixRoom.redactEventEventIdParam).isNull()
awaitDeleteConfirmation().eventSink(CreatePollEvents.HideConfirmation)
awaitPollLoaded().apply {
- Truth.assertThat(showDeleteConfirmation).isFalse()
+ assertThat(showDeleteConfirmation).isFalse()
}
- Truth.assertThat(fakeMatrixRoom.redactEventEventIdParam).isNull()
+ assertThat(fakeMatrixRoom.redactEventEventIdParam).isNull()
}
}
@@ -468,29 +468,29 @@ class CreatePollPresenterTest {
}.test {
awaitDefaultItem()
awaitPollLoaded().eventSink(CreatePollEvents.Delete(confirmed = false))
- Truth.assertThat(fakeMatrixRoom.redactEventEventIdParam).isNull()
+ assertThat(fakeMatrixRoom.redactEventEventIdParam).isNull()
awaitDeleteConfirmation().eventSink(CreatePollEvents.Delete(confirmed = true))
awaitPollLoaded().apply {
- Truth.assertThat(showDeleteConfirmation).isFalse()
+ assertThat(showDeleteConfirmation).isFalse()
}
- Truth.assertThat(fakeMatrixRoom.redactEventEventIdParam).isEqualTo(pollEventId)
+ assertThat(fakeMatrixRoom.redactEventEventIdParam).isEqualTo(pollEventId)
}
}
private suspend fun TurbineTestContext.awaitDefaultItem() =
awaitItem().apply {
- Truth.assertThat(canSave).isFalse()
- Truth.assertThat(canAddAnswer).isTrue()
- Truth.assertThat(question).isEmpty()
- Truth.assertThat(answers).isEqualTo(listOf(Answer("", false), Answer("", false)))
- Truth.assertThat(pollKind).isEqualTo(PollKind.Disclosed)
- Truth.assertThat(showBackConfirmation).isFalse()
- Truth.assertThat(showDeleteConfirmation).isFalse()
+ assertThat(canSave).isFalse()
+ assertThat(canAddAnswer).isTrue()
+ assertThat(question).isEmpty()
+ assertThat(answers).isEqualTo(listOf(Answer("", false), Answer("", false)))
+ assertThat(pollKind).isEqualTo(PollKind.Disclosed)
+ assertThat(showBackConfirmation).isFalse()
+ assertThat(showDeleteConfirmation).isFalse()
}
private suspend fun TurbineTestContext.awaitDeleteConfirmation() =
awaitItem().apply {
- Truth.assertThat(showDeleteConfirmation).isTrue()
+ assertThat(showDeleteConfirmation).isTrue()
}
private suspend fun TurbineTestContext.awaitPollLoaded(
@@ -499,14 +499,14 @@ class CreatePollPresenterTest {
newAnswer2: String? = null,
) =
awaitItem().apply {
- Truth.assertThat(canSave).isTrue()
- Truth.assertThat(canAddAnswer).isTrue()
- Truth.assertThat(question).isEqualTo(newQuestion ?: existingPoll.question)
- Truth.assertThat(answers).isEqualTo(existingPoll.expectedAnswersState().toMutableList().apply {
+ assertThat(canSave).isTrue()
+ assertThat(canAddAnswer).isTrue()
+ assertThat(question).isEqualTo(newQuestion ?: existingPoll.question)
+ assertThat(answers).isEqualTo(existingPoll.expectedAnswersState().toMutableList().apply {
newAnswer1?.let { this[0] = Answer(it, true) }
newAnswer2?.let { this[1] = Answer(it, true) }
})
- Truth.assertThat(pollKind).isEqualTo(existingPoll.kind)
+ assertThat(pollKind).isEqualTo(existingPoll.kind)
}
private fun createCreatePollPresenter(
diff --git a/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/notifications/NotificationSettingsEvents.kt b/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/notifications/NotificationSettingsEvents.kt
index 9e87675b3a..f38c211b67 100644
--- a/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/notifications/NotificationSettingsEvents.kt
+++ b/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/notifications/NotificationSettingsEvents.kt
@@ -17,11 +17,11 @@
package io.element.android.features.preferences.impl.notifications
sealed interface NotificationSettingsEvents {
-
data object RefreshSystemNotificationsEnabled : NotificationSettingsEvents
data class SetNotificationsEnabled(val enabled: Boolean) : NotificationSettingsEvents
data class SetAtRoomNotificationsEnabled(val enabled: Boolean) : NotificationSettingsEvents
data class SetCallNotificationsEnabled(val enabled: Boolean) : NotificationSettingsEvents
+ data class SetInviteForMeNotificationsEnabled(val enabled: Boolean) : NotificationSettingsEvents
data object FixConfigurationMismatch : NotificationSettingsEvents
data object ClearConfigurationMismatchError : NotificationSettingsEvents
data object ClearNotificationChangeError : NotificationSettingsEvents
diff --git a/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/notifications/NotificationSettingsPresenter.kt b/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/notifications/NotificationSettingsPresenter.kt
index 689cca8f66..6252be1e5c 100644
--- a/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/notifications/NotificationSettingsPresenter.kt
+++ b/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/notifications/NotificationSettingsPresenter.kt
@@ -76,6 +76,9 @@ class NotificationSettingsPresenter @Inject constructor(
is NotificationSettingsEvents.SetCallNotificationsEnabled -> {
localCoroutineScope.setCallNotificationsEnabled(event.enabled, changeNotificationSettingAction)
}
+ is NotificationSettingsEvents.SetInviteForMeNotificationsEnabled -> {
+ localCoroutineScope.setInviteForMeNotificationsEnabled(event.enabled, changeNotificationSettingAction)
+ }
is NotificationSettingsEvents.SetNotificationsEnabled -> localCoroutineScope.setNotificationsEnabled(userPushStore, event.enabled)
NotificationSettingsEvents.ClearConfigurationMismatchError -> {
matrixSettings.value = NotificationSettingsState.MatrixSettings.Invalid(fixFailed = false)
@@ -123,10 +126,12 @@ class NotificationSettingsPresenter @Inject constructor(
val callNotificationsEnabled = notificationSettingsService.isCallEnabled().getOrThrow()
val atRoomNotificationsEnabled = notificationSettingsService.isRoomMentionEnabled().getOrThrow()
+ val inviteForMeNotificationsEnabled = notificationSettingsService.isInviteForMeEnabled().getOrThrow()
target.value = NotificationSettingsState.MatrixSettings.Valid(
atRoomNotificationsEnabled = atRoomNotificationsEnabled,
callNotificationsEnabled = callNotificationsEnabled,
+ inviteForMeNotificationsEnabled = inviteForMeNotificationsEnabled,
defaultGroupNotificationMode = encryptedGroupDefaultMode,
defaultOneToOneNotificationMode = encryptedOneToOneDefaultMode,
)
@@ -175,6 +180,12 @@ class NotificationSettingsPresenter @Inject constructor(
}.runCatchingUpdatingState(action)
}
+ private fun CoroutineScope.setInviteForMeNotificationsEnabled(enabled: Boolean, action: MutableState>) = launch {
+ suspend {
+ notificationSettingsService.setInviteForMeEnabled(enabled).getOrThrow()
+ }.runCatchingUpdatingState(action)
+ }
+
private fun CoroutineScope.setNotificationsEnabled(userPushStore: UserPushStore, enabled: Boolean) = launch {
userPushStore.setNotificationEnabledForDevice(enabled)
}
diff --git a/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/notifications/NotificationSettingsState.kt b/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/notifications/NotificationSettingsState.kt
index 2b0faa110c..581f0e8475 100644
--- a/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/notifications/NotificationSettingsState.kt
+++ b/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/notifications/NotificationSettingsState.kt
@@ -32,6 +32,7 @@ data class NotificationSettingsState(
data class Valid(
val atRoomNotificationsEnabled: Boolean,
val callNotificationsEnabled: Boolean,
+ val inviteForMeNotificationsEnabled: Boolean,
val defaultGroupNotificationMode: RoomNotificationMode?,
val defaultOneToOneNotificationMode: RoomNotificationMode?,
) : MatrixSettings
diff --git a/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/notifications/NotificationSettingsStateProvider.kt b/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/notifications/NotificationSettingsStateProvider.kt
index 9336857585..f121a2fe60 100644
--- a/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/notifications/NotificationSettingsStateProvider.kt
+++ b/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/notifications/NotificationSettingsStateProvider.kt
@@ -35,6 +35,7 @@ fun aNotificationSettingsState(
matrixSettings = NotificationSettingsState.MatrixSettings.Valid(
atRoomNotificationsEnabled = true,
callNotificationsEnabled = true,
+ inviteForMeNotificationsEnabled = true,
defaultGroupNotificationMode = RoomNotificationMode.MENTIONS_AND_KEYWORDS_ONLY,
defaultOneToOneNotificationMode = RoomNotificationMode.ALL_MESSAGES,
),
diff --git a/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/notifications/NotificationSettingsView.kt b/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/notifications/NotificationSettingsView.kt
index c2c52a07c9..f1066b2e9d 100644
--- a/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/notifications/NotificationSettingsView.kt
+++ b/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/notifications/NotificationSettingsView.kt
@@ -77,6 +77,7 @@ fun NotificationSettingsView(
onMentionNotificationsChanged = { state.eventSink(NotificationSettingsEvents.SetAtRoomNotificationsEnabled(it)) },
// TODO We are removing the call notification toggle until support for call notifications has been added
// onCallsNotificationsChanged = { state.eventSink(NotificationSettingsEvents.SetCallNotificationsEnabled(it)) },
+ onInviteForMeNotificationsChanged = { state.eventSink(NotificationSettingsEvents.SetInviteForMeNotificationsEnabled(it)) },
)
}
AsyncView(
@@ -98,6 +99,7 @@ private fun NotificationSettingsContentView(
onMentionNotificationsChanged: (Boolean) -> Unit,
// TODO We are removing the call notification toggle until support for call notifications has been added
// onCallsNotificationsChanged: (Boolean) -> Unit,
+ onInviteForMeNotificationsChanged: (Boolean) -> Unit,
modifier: Modifier = Modifier,
) {
val context = LocalContext.current
@@ -147,8 +149,8 @@ private fun NotificationSettingsContentView(
onCheckedChange = onMentionNotificationsChanged
)
}
- // TODO We are removing the call notification toggle until support for call notifications has been added
-// PreferenceCategory(title = stringResource(id = CommonStrings.screen_notification_settings_additional_settings_section_title)) {
+ PreferenceCategory(title = stringResource(id = R.string.screen_notification_settings_additional_settings_section_title)) {
+ // TODO We are removing the call notification toggle until support for call notifications has been added
// PreferenceSwitch(
// modifier = Modifier,
// title = stringResource(id = CommonStrings.screen_notification_settings_calls_label),
@@ -156,7 +158,14 @@ private fun NotificationSettingsContentView(
// switchAlignment = Alignment.Top,
// onCheckedChange = onCallsNotificationsChanged
// )
-// }
+ PreferenceSwitch(
+ modifier = Modifier,
+ title = stringResource(id = R.string.screen_notification_settings_invite_for_me_label),
+ isChecked = matrixSettings.inviteForMeNotificationsEnabled,
+ switchAlignment = Alignment.Top,
+ onCheckedChange = onInviteForMeNotificationsChanged
+ )
+ }
}
}
diff --git a/features/preferences/impl/src/main/res/values-cs/translations.xml b/features/preferences/impl/src/main/res/values-cs/translations.xml
index a8f8af56ed..76d764c131 100644
--- a/features/preferences/impl/src/main/res/values-cs/translations.xml
+++ b/features/preferences/impl/src/main/res/values-cs/translations.xml
@@ -31,6 +31,7 @@ Pokud budete pokračovat, některá nastavení se mohou změnit."
"Povolit oznámení na tomto zařízení"
"Konfigurace nebyla opravena, zkuste to prosím znovu."
"Skupinové chaty"
+ "Pozvánky"
"Váš domovský server tuto možnost v zašifrovaných místnostech nepodporuje, v některých místnostech nemusíte být upozorněni."
"Zmínky"
"Vše"
diff --git a/features/preferences/impl/src/main/res/values-de/translations.xml b/features/preferences/impl/src/main/res/values-de/translations.xml
index 4287d4d7c8..cacc15a633 100644
--- a/features/preferences/impl/src/main/res/values-de/translations.xml
+++ b/features/preferences/impl/src/main/res/values-de/translations.xml
@@ -1,7 +1,12 @@
+ "Benutzerdefinierte Element-Aufruf-Basis-URL"
+ "Lege eine eigene Basis-URL für Element Call fest."
+ "Ungültige URL, bitte stelle sicher, dass du das Protokoll (http/https) und die richtige Adresse angibst."
"Entwickler-Modus"
+ "Aktivieren, um Zugriff auf Features und Funktionen für Entwickler zu aktivieren."
"Deaktiviere den Rich-Text-Editor, um Markdown manuell einzugeben."
+ "Option aktiveren, um Nachrichtenquelle in der Zeitleiste anzuzeigen."
"Anzeigename"
"Dein Anzeigename"
"Ein unbekannter Fehler ist aufgetreten und die Informationen konnten nicht geändert werden."
@@ -22,6 +27,7 @@
"Benachrichtigungen auf diesem Gerät aktivieren"
"Die Konfiguration wurde nicht korrigiert, bitte versuche es erneut."
"Gruppenchats"
+ "Dein Homeserver unterstützt diese Option in verschlüsselten Räumen nicht. In einigen Räumen wirst du möglicherweise nicht benachrichtigt."
"Erwähnungen"
"Alle"
"Erwähnungen"
diff --git a/features/preferences/impl/src/main/res/values-fr/translations.xml b/features/preferences/impl/src/main/res/values-fr/translations.xml
index aca213c957..dc5e6ff790 100644
--- a/features/preferences/impl/src/main/res/values-fr/translations.xml
+++ b/features/preferences/impl/src/main/res/values-fr/translations.xml
@@ -6,6 +6,7 @@
"Mode développeur"
"Activer pour pouvoir accéder aux fonctionnalités destinées aux développeurs."
"Désactivez l’éditeur de texte enrichi pour saisir manuellement du Markdown."
+ "Activer cette option pour pouvoir voir la source des messages dans la discussion."
"Pseudonyme"
"Votre pseudonyme"
"Une erreur inconnue s’est produite et les informations n’ont pas pu être modifiées."
@@ -30,6 +31,7 @@ Si vous continuez, il est possible que certains de vos paramètres soient modifi
"Activer les notifications sur cet appareil"
"La configuration n’a pas été corrigée, veuillez réessayer."
"Discussions de groupe"
+ "Invitations"
"Votre serveur d’accueil ne supporte pas cette option pour les salons chiffrés, vous pourriez ne pas être notifié(e) dans certains salons."
"Mentions"
"Tous"
diff --git a/features/preferences/impl/src/main/res/values-hu/translations.xml b/features/preferences/impl/src/main/res/values-hu/translations.xml
new file mode 100644
index 0000000000..5529ef2175
--- /dev/null
+++ b/features/preferences/impl/src/main/res/values-hu/translations.xml
@@ -0,0 +1,42 @@
+
+
+ "Egyéni Element Call alapwebcím"
+ "Egyéni alapwebcím beállítása az Element Callhoz."
+ "Érvénytelen webcím, győződjön meg arról, hogy szerepel benne a protokoll (http/https), és hogy helyes a cím."
+ "Fejlesztői mód"
+ "Engedélyezze, hogy elérje a fejlesztőknek szánt funkciókat."
+ "A formázott szöveges szerkesztő letiltása, hogy kézzel írhasson Markdownt."
+ "Engedélyezze a beállítást az üzenet forrásának megjelenítéséhez az idővonalon."
+ "Megjelenítendő név"
+ "Saját megjelenítendő név"
+ "Ismeretlen hiba történt, és az információ módosítása nem sikerült."
+ "Nem sikerült frissíteni a profilt"
+ "Profil szerkesztése"
+ "Profil frissítése…"
+ "További beállítások"
+ "Hang- és videóhívások"
+ "Konfigurációs eltérés"
+ "Egyszerűsítettük az értesítési beállításokat, hogy könnyebben megtalálhatók legyenek a lehetőségek. A korábban kiválasztott egyéni beállítások némelyike nem jelenik meg itt, de továbbra is aktív.
+
+Ha folytatja, egyes beállítások megváltozhatnak."
+ "Közvetlen csevegések"
+ "Egyéni beállítás csevegésenként"
+ "Hiba történt az értesítési beállítás frissítésekor."
+ "Összes üzenet"
+ "Csak említések és kulcsszavak"
+ "Közvetlen csevegéseknél értesítés ezekről:"
+ "Csoportos csevegésekben értesítés ezekről:"
+ "Értesítések engedélyezése ezen az eszközön"
+ "A konfiguráció nem lett kijavítva, próbálja újra."
+ "Csoportos csevegések"
+ "A Matrix-kiszolgálója nem támogatja ezt a beállítást a titkosított szobákban, előfordulhat, hogy egyes szobákban nem kap értesítést."
+ "Említések"
+ "Összes"
+ "Említések"
+ "Értesítés ezekről:"
+ "Értesítés a @room említésekor"
+ "Az értesítések fogadásához kérjük, módosítsa a %1$s."
+ "rendszerbeállításokat"
+ "A rendszerértesítések ki vannak kapcsolva"
+ "Értesítések"
+
diff --git a/features/preferences/impl/src/main/res/values-in/translations.xml b/features/preferences/impl/src/main/res/values-in/translations.xml
new file mode 100644
index 0000000000..f33bf54cfb
--- /dev/null
+++ b/features/preferences/impl/src/main/res/values-in/translations.xml
@@ -0,0 +1,45 @@
+
+
+ "URL dasar Element Call khusus"
+ "Tetapkan URL dasar khusus untuk Element Call."
+ "URL tidak valid, pastikan Anda menyertakan protokol (http/https) dan alamat yang benar."
+ "Mode pengembang"
+ "Aktifkan untuk mengakses fitur dan fungsi untuk para pengembang."
+ "Nonaktifkan penyunting teks kaya untuk mengetik Markdown secara manual."
+ "Aktifkan opsi untuk melihat sumber pesan dalam lini masa."
+ "Nama tampilan"
+ "Nama tampilan Anda"
+ "Terjadi kesalahan yang tidak diketahui dan informasi tidak dapat diubah."
+ "Tidak dapat memperbarui profil"
+ "Sunting profil"
+ "Memperbarui profil…"
+ "Pengaturan tambahan"
+ "Panggilan audio dan video"
+ "Ketidakcocokan pengaturan"
+ "Kami telah menyederhanakan Pengaturan Pemberitahuan untuk membuat opsi lebih mudah ditemukan.
+
+Beberapa pengaturan khusus yang Anda pilih di masa lalu tidak ditampilkan di sini, tetapi masih aktif.
+
+Jika Anda melanjutkan, beberapa pengaturan Anda dapat berubah."
+ "Obrolan langsung"
+ "Pengaturan khusus per obrolan"
+ "Terjadi kesalahan saat memperbarui pengaturan pemberitahuan."
+ "Semua pesan"
+ "Sebutan dan Kata Kunci saja"
+ "Di obrolan langsung, beri tahu saya tentang"
+ "Di obrolan grup, beri tahu tentang"
+ "Aktifkan pemberitahuan di perangkat ini"
+ "Pengaturan belum diperbaiki, silakan coba lagi."
+ "Obrolan grup"
+ "Undangan"
+ "Homeserver Anda tidak mendukung opsi ini dalam ruangan terenkripsi, Anda mungkin tidak diberi tahu dalam beberapa ruangan."
+ "Sebutan"
+ "Semua"
+ "Sebutan"
+ "Beri tahu saya tentang"
+ "Beri tahu saya pada @room"
+ "Untuk menerima pemberitahuan, silakan ubah %1$s Anda."
+ "pengaturan sistem"
+ "Pemberitahuan sistem dimatikan"
+ "Notifikasi"
+
diff --git a/features/preferences/impl/src/main/res/values-ru/translations.xml b/features/preferences/impl/src/main/res/values-ru/translations.xml
index 4a008eab47..bbf5f426ea 100644
--- a/features/preferences/impl/src/main/res/values-ru/translations.xml
+++ b/features/preferences/impl/src/main/res/values-ru/translations.xml
@@ -29,6 +29,7 @@
"Включить уведомления на данном устройстве"
"Конфигурация не была исправлена, попробуйте еще раз."
"Групповые чаты"
+ "Приглашения"
"Ваш домашний сервер не поддерживает эту опцию в зашифрованных комнатах, в некоторых комнатах вы можете не получать уведомления."
"Упоминания"
"Все"
diff --git a/features/preferences/impl/src/main/res/values-sk/translations.xml b/features/preferences/impl/src/main/res/values-sk/translations.xml
index 0464bf8bee..8171748e1d 100644
--- a/features/preferences/impl/src/main/res/values-sk/translations.xml
+++ b/features/preferences/impl/src/main/res/values-sk/translations.xml
@@ -31,6 +31,7 @@ Ak budete pokračovať, niektoré z vašich nastavení sa môžu zmeniť.""Povoliť oznámenia na tomto zariadení"
"Konfigurácia nebola opravená, skúste to prosím znova."
"Skupinové rozhovory"
+ "Pozvánky"
"Váš domovský server nepodporuje túto možnosť v šifrovaných miestnostiach, v niektorých miestnostiach nemusíte dostať upozornenie."
"Zmienky"
"Všetky"
diff --git a/features/preferences/impl/src/test/kotlin/io/element/android/features/preferences/impl/notifications/EditDefaultNotificationSettingsPresenterTests.kt b/features/preferences/impl/src/test/kotlin/io/element/android/features/preferences/impl/notifications/EditDefaultNotificationSettingsPresenterTests.kt
index f4cc7c80e9..3765d5dbb9 100644
--- a/features/preferences/impl/src/test/kotlin/io/element/android/features/preferences/impl/notifications/EditDefaultNotificationSettingsPresenterTests.kt
+++ b/features/preferences/impl/src/test/kotlin/io/element/android/features/preferences/impl/notifications/EditDefaultNotificationSettingsPresenterTests.kt
@@ -19,7 +19,7 @@ package io.element.android.features.preferences.impl.notifications
import app.cash.molecule.RecompositionMode
import app.cash.molecule.moleculeFlow
import app.cash.turbine.test
-import com.google.common.truth.Truth
+import com.google.common.truth.Truth.assertThat
import io.element.android.features.preferences.impl.notifications.edit.EditDefaultNotificationSettingPresenter
import io.element.android.features.preferences.impl.notifications.edit.EditDefaultNotificationSettingStateEvents
import io.element.android.libraries.matrix.api.room.RoomNotificationMode
@@ -44,13 +44,13 @@ class EditDefaultNotificationSettingsPresenterTests {
presenter.present()
}.test {
val initialState = awaitItem()
- Truth.assertThat(initialState.mode).isNull()
- Truth.assertThat(initialState.isOneToOne).isFalse()
+ assertThat(initialState.mode).isNull()
+ assertThat(initialState.isOneToOne).isFalse()
val loadedState = consumeItemsUntilPredicate {
it.mode == RoomNotificationMode.MENTIONS_AND_KEYWORDS_ONLY
}.last()
- Truth.assertThat(loadedState.mode).isEqualTo(RoomNotificationMode.MENTIONS_AND_KEYWORDS_ONLY)
+ assertThat(loadedState.mode).isEqualTo(RoomNotificationMode.MENTIONS_AND_KEYWORDS_ONLY)
}
}
@@ -73,7 +73,7 @@ class EditDefaultNotificationSettingsPresenterTests {
val loadedState = consumeItemsUntilPredicate { state ->
state.roomsWithUserDefinedMode.any { it.details.notificationMode == RoomNotificationMode.ALL_MESSAGES }
}.last()
- Truth.assertThat(loadedState.roomsWithUserDefinedMode.any { it.details.notificationMode == RoomNotificationMode.ALL_MESSAGES }).isTrue()
+ assertThat(loadedState.roomsWithUserDefinedMode.any { it.details.notificationMode == RoomNotificationMode.ALL_MESSAGES }).isTrue()
}
}
@@ -87,7 +87,7 @@ class EditDefaultNotificationSettingsPresenterTests {
val loadedState = consumeItemsUntilPredicate {
it.mode == RoomNotificationMode.ALL_MESSAGES
}.last()
- Truth.assertThat(loadedState.mode).isEqualTo(RoomNotificationMode.ALL_MESSAGES)
+ assertThat(loadedState.mode).isEqualTo(RoomNotificationMode.ALL_MESSAGES)
}
}
@@ -103,12 +103,12 @@ class EditDefaultNotificationSettingsPresenterTests {
val errorState = consumeItemsUntilPredicate {
it.changeNotificationSettingAction.isFailure()
}.last()
- Truth.assertThat(errorState.changeNotificationSettingAction.isFailure()).isTrue()
+ assertThat(errorState.changeNotificationSettingAction.isFailure()).isTrue()
errorState.eventSink(EditDefaultNotificationSettingStateEvents.ClearError)
val clearErrorState = consumeItemsUntilPredicate {
it.changeNotificationSettingAction.isUninitialized()
}.last()
- Truth.assertThat(clearErrorState.changeNotificationSettingAction.isUninitialized()).isTrue()
+ assertThat(clearErrorState.changeNotificationSettingAction.isUninitialized()).isTrue()
}
}
diff --git a/features/preferences/impl/src/test/kotlin/io/element/android/features/preferences/impl/notifications/NotificationSettingsPresenterTests.kt b/features/preferences/impl/src/test/kotlin/io/element/android/features/preferences/impl/notifications/NotificationSettingsPresenterTests.kt
index c3d6f51256..96eca14746 100644
--- a/features/preferences/impl/src/test/kotlin/io/element/android/features/preferences/impl/notifications/NotificationSettingsPresenterTests.kt
+++ b/features/preferences/impl/src/test/kotlin/io/element/android/features/preferences/impl/notifications/NotificationSettingsPresenterTests.kt
@@ -20,7 +20,7 @@ import app.cash.molecule.RecompositionMode
import app.cash.molecule.moleculeFlow
import app.cash.turbine.test
import com.element.android.libraries.pushstore.test.userpushstore.FakeUserPushStoreFactory
-import com.google.common.truth.Truth
+import com.google.common.truth.Truth.assertThat
import io.element.android.libraries.matrix.api.room.RoomNotificationMode
import io.element.android.libraries.matrix.test.A_THROWABLE
import io.element.android.libraries.matrix.test.FakeMatrixClient
@@ -38,20 +38,20 @@ class NotificationSettingsPresenterTests {
presenter.present()
}.test {
val initialState = awaitItem()
- Truth.assertThat(initialState.appSettings.appNotificationsEnabled).isFalse()
- Truth.assertThat(initialState.appSettings.systemNotificationsEnabled).isTrue()
- Truth.assertThat(initialState.matrixSettings).isEqualTo(NotificationSettingsState.MatrixSettings.Uninitialized)
-
+ assertThat(initialState.appSettings.appNotificationsEnabled).isFalse()
+ assertThat(initialState.appSettings.systemNotificationsEnabled).isTrue()
+ assertThat(initialState.matrixSettings).isEqualTo(NotificationSettingsState.MatrixSettings.Uninitialized)
val loadedState = consumeItemsUntilPredicate {
it.matrixSettings is NotificationSettingsState.MatrixSettings.Valid
}.last()
- Truth.assertThat(loadedState.appSettings.appNotificationsEnabled).isTrue()
- Truth.assertThat(loadedState.appSettings.systemNotificationsEnabled).isTrue()
+ assertThat(loadedState.appSettings.appNotificationsEnabled).isTrue()
+ assertThat(loadedState.appSettings.systemNotificationsEnabled).isTrue()
val valid = loadedState.matrixSettings as? NotificationSettingsState.MatrixSettings.Valid
- Truth.assertThat(valid?.atRoomNotificationsEnabled).isFalse()
- Truth.assertThat(valid?.callNotificationsEnabled).isFalse()
- Truth.assertThat(valid?.defaultGroupNotificationMode).isEqualTo(RoomNotificationMode.MENTIONS_AND_KEYWORDS_ONLY)
- Truth.assertThat(valid?.defaultOneToOneNotificationMode).isEqualTo(RoomNotificationMode.ALL_MESSAGES)
+ assertThat(valid?.atRoomNotificationsEnabled).isFalse()
+ assertThat(valid?.callNotificationsEnabled).isFalse()
+ assertThat(valid?.inviteForMeNotificationsEnabled).isFalse()
+ assertThat(valid?.defaultGroupNotificationMode).isEqualTo(RoomNotificationMode.MENTIONS_AND_KEYWORDS_ONLY)
+ assertThat(valid?.defaultOneToOneNotificationMode).isEqualTo(RoomNotificationMode.ALL_MESSAGES)
cancelAndIgnoreRemainingEvents()
}
}
@@ -63,7 +63,6 @@ class NotificationSettingsPresenterTests {
moleculeFlow(RecompositionMode.Immediate) {
presenter.present()
}.test {
-
notificationSettingsService.setDefaultRoomNotificationMode(isEncrypted = true, isOneToOne = false, mode = RoomNotificationMode.ALL_MESSAGES)
notificationSettingsService.setDefaultRoomNotificationMode(isEncrypted = false, isOneToOne = false, mode = RoomNotificationMode.ALL_MESSAGES)
val updatedState = consumeItemsUntilPredicate {
@@ -71,7 +70,7 @@ class NotificationSettingsPresenterTests {
?.defaultGroupNotificationMode == RoomNotificationMode.ALL_MESSAGES
}.last()
val valid = updatedState.matrixSettings as? NotificationSettingsState.MatrixSettings.Valid
- Truth.assertThat(valid?.defaultGroupNotificationMode).isEqualTo(RoomNotificationMode.ALL_MESSAGES)
+ assertThat(valid?.defaultGroupNotificationMode).isEqualTo(RoomNotificationMode.ALL_MESSAGES)
}
}
@@ -82,7 +81,6 @@ class NotificationSettingsPresenterTests {
moleculeFlow(RecompositionMode.Immediate) {
presenter.present()
}.test {
-
notificationSettingsService.setDefaultRoomNotificationMode(
isEncrypted = true,
isOneToOne = false,
@@ -96,7 +94,7 @@ class NotificationSettingsPresenterTests {
val updatedState = consumeItemsUntilPredicate {
it.matrixSettings is NotificationSettingsState.MatrixSettings.Invalid
}.last()
- Truth.assertThat(updatedState.matrixSettings).isEqualTo(NotificationSettingsState.MatrixSettings.Invalid(fixFailed = false))
+ assertThat(updatedState.matrixSettings).isEqualTo(NotificationSettingsState.MatrixSettings.Invalid(fixFailed = false))
}
}
@@ -118,9 +116,8 @@ class NotificationSettingsPresenterTests {
val fixedState = consumeItemsUntilPredicate(timeout = 2000.milliseconds) {
it.matrixSettings is NotificationSettingsState.MatrixSettings.Valid
}.last()
-
val fixedMatrixState = fixedState.matrixSettings as? NotificationSettingsState.MatrixSettings.Valid
- Truth.assertThat(fixedMatrixState?.defaultGroupNotificationMode).isEqualTo(RoomNotificationMode.ALL_MESSAGES)
+ assertThat(fixedMatrixState?.defaultGroupNotificationMode).isEqualTo(RoomNotificationMode.ALL_MESSAGES)
}
}
@@ -133,13 +130,12 @@ class NotificationSettingsPresenterTests {
val loadedState = consumeItemsUntilPredicate {
it.matrixSettings is NotificationSettingsState.MatrixSettings.Valid
}.last()
- Truth.assertThat(loadedState.appSettings.appNotificationsEnabled).isTrue()
-
+ assertThat(loadedState.appSettings.appNotificationsEnabled).isTrue()
loadedState.eventSink(NotificationSettingsEvents.SetNotificationsEnabled(false))
val updatedState = consumeItemsUntilPredicate {
!it.appSettings.appNotificationsEnabled
}.last()
- Truth.assertThat(updatedState.appSettings.appNotificationsEnabled).isFalse()
+ assertThat(updatedState.appSettings.appNotificationsEnabled).isFalse()
cancelAndIgnoreRemainingEvents()
}
}
@@ -154,14 +150,34 @@ class NotificationSettingsPresenterTests {
(it.matrixSettings as? NotificationSettingsState.MatrixSettings.Valid)?.callNotificationsEnabled == false
}.last()
val validMatrixState = loadedState.matrixSettings as? NotificationSettingsState.MatrixSettings.Valid
- Truth.assertThat(validMatrixState?.callNotificationsEnabled).isFalse()
-
+ assertThat(validMatrixState?.callNotificationsEnabled).isFalse()
loadedState.eventSink(NotificationSettingsEvents.SetCallNotificationsEnabled(true))
val updatedState = consumeItemsUntilPredicate {
(it.matrixSettings as? NotificationSettingsState.MatrixSettings.Valid)?.callNotificationsEnabled == true
}.last()
val updatedMatrixState = updatedState.matrixSettings as? NotificationSettingsState.MatrixSettings.Valid
- Truth.assertThat(updatedMatrixState?.callNotificationsEnabled).isTrue()
+ assertThat(updatedMatrixState?.callNotificationsEnabled).isTrue()
+ cancelAndIgnoreRemainingEvents()
+ }
+ }
+
+ @Test
+ fun `present - set invite for me notifications enabled`() = runTest {
+ val presenter = createNotificationSettingsPresenter()
+ moleculeFlow(RecompositionMode.Immediate) {
+ presenter.present()
+ }.test {
+ val loadedState = consumeItemsUntilPredicate {
+ (it.matrixSettings as? NotificationSettingsState.MatrixSettings.Valid)?.inviteForMeNotificationsEnabled == false
+ }.last()
+ val validMatrixState = loadedState.matrixSettings as? NotificationSettingsState.MatrixSettings.Valid
+ assertThat(validMatrixState?.inviteForMeNotificationsEnabled).isFalse()
+ loadedState.eventSink(NotificationSettingsEvents.SetInviteForMeNotificationsEnabled(true))
+ val updatedState = consumeItemsUntilPredicate {
+ (it.matrixSettings as? NotificationSettingsState.MatrixSettings.Valid)?.inviteForMeNotificationsEnabled == true
+ }.last()
+ val updatedMatrixState = updatedState.matrixSettings as? NotificationSettingsState.MatrixSettings.Valid
+ assertThat(updatedMatrixState?.inviteForMeNotificationsEnabled).isTrue()
cancelAndIgnoreRemainingEvents()
}
}
@@ -176,14 +192,13 @@ class NotificationSettingsPresenterTests {
(it.matrixSettings as? NotificationSettingsState.MatrixSettings.Valid)?.atRoomNotificationsEnabled == false
}.last()
val validMatrixState = loadedState.matrixSettings as? NotificationSettingsState.MatrixSettings.Valid
- Truth.assertThat(validMatrixState?.atRoomNotificationsEnabled).isFalse()
-
+ assertThat(validMatrixState?.atRoomNotificationsEnabled).isFalse()
loadedState.eventSink(NotificationSettingsEvents.SetAtRoomNotificationsEnabled(true))
val updatedState = consumeItemsUntilPredicate {
(it.matrixSettings as? NotificationSettingsState.MatrixSettings.Valid)?.atRoomNotificationsEnabled == true
}.last()
val updatedMatrixState = updatedState.matrixSettings as? NotificationSettingsState.MatrixSettings.Valid
- Truth.assertThat(updatedMatrixState?.atRoomNotificationsEnabled).isTrue()
+ assertThat(updatedMatrixState?.atRoomNotificationsEnabled).isTrue()
cancelAndIgnoreRemainingEvents()
}
}
@@ -200,19 +215,17 @@ class NotificationSettingsPresenterTests {
(it.matrixSettings as? NotificationSettingsState.MatrixSettings.Valid)?.atRoomNotificationsEnabled == false
}.last()
val validMatrixState = loadedState.matrixSettings as? NotificationSettingsState.MatrixSettings.Valid
- Truth.assertThat(validMatrixState?.atRoomNotificationsEnabled).isFalse()
-
+ assertThat(validMatrixState?.atRoomNotificationsEnabled).isFalse()
loadedState.eventSink(NotificationSettingsEvents.SetAtRoomNotificationsEnabled(true))
val errorState = consumeItemsUntilPredicate {
it.changeNotificationSettingAction.isFailure()
}.last()
- Truth.assertThat(errorState.changeNotificationSettingAction.isFailure()).isTrue()
+ assertThat(errorState.changeNotificationSettingAction.isFailure()).isTrue()
errorState.eventSink(NotificationSettingsEvents.ClearNotificationChangeError)
-
val clearErrorState = consumeItemsUntilPredicate {
it.changeNotificationSettingAction.isUninitialized()
}.last()
- Truth.assertThat(clearErrorState.changeNotificationSettingAction.isUninitialized()).isTrue()
+ assertThat(clearErrorState.changeNotificationSettingAction.isUninitialized()).isTrue()
cancelAndIgnoreRemainingEvents()
}
}
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 4adea8e59c..f914c21100 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
@@ -73,8 +73,8 @@ class PreferencesRootPresenterTest {
avatarUrl = AN_AVATAR_URL
)
)
- assertThat(loadedState.showDeveloperSettings).isEqualTo(true)
- assertThat(loadedState.showAnalyticsSettings).isEqualTo(false)
+ assertThat(loadedState.showDeveloperSettings).isTrue()
+ assertThat(loadedState.showAnalyticsSettings).isFalse()
assertThat(loadedState.accountManagementUrl).isNull()
assertThat(loadedState.devicesManagementUrl).isNull()
}
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 38992f25f5..d50ce28778 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
@@ -47,4 +47,9 @@ interface BugReporter {
* Provide the log directory.
*/
fun logDirectory(): File
+
+ /**
+ * Set the current tracing filter.
+ */
+ fun setCurrentTracingFilter(tracingFilter: String)
}
diff --git a/features/rageshake/api/src/main/res/values-de/translations.xml b/features/rageshake/api/src/main/res/values-de/translations.xml
index 6a22b4a72c..46d2be277e 100644
--- a/features/rageshake/api/src/main/res/values-de/translations.xml
+++ b/features/rageshake/api/src/main/res/values-de/translations.xml
@@ -1,6 +1,7 @@
"%1$s ist bei der letzten Nutzung abgestürzt. Möchtest du einen Absturzbericht mit uns teilen?"
+ "Du scheinst das Telefon aus Frustration zu schütteln. Möchtest du den Bildschirm für den Fehlerbericht öffnen?"
"Rageshake"
"Erkennungsschwelle"
diff --git a/features/rageshake/api/src/main/res/values-hu/translations.xml b/features/rageshake/api/src/main/res/values-hu/translations.xml
new file mode 100644
index 0000000000..559594ed05
--- /dev/null
+++ b/features/rageshake/api/src/main/res/values-hu/translations.xml
@@ -0,0 +1,7 @@
+
+
+ "Az %1$s összeomlott a legutóbbi használata óta. Megosztja velünk az összeomlás-jelentést?"
+ "Úgy tűnik, mintha mérgében a telefont rázná. Megnyitja a hibajelentési képernyőt?"
+ "Ideges rázás"
+ "Észlelési küszöb"
+
diff --git a/features/rageshake/api/src/main/res/values-in/translations.xml b/features/rageshake/api/src/main/res/values-in/translations.xml
new file mode 100644
index 0000000000..270f62364b
--- /dev/null
+++ b/features/rageshake/api/src/main/res/values-in/translations.xml
@@ -0,0 +1,7 @@
+
+
+ "%1$s mengalami kemogokan saat terakhir kali digunakan. Apakah Anda ingin berbagi laporan kerusakan dengan kami?"
+ "Anda tampaknya mengguncang telepon karena frustrasi. Apakah Anda ingin membuka layar laporan kutu?"
+ "Rageshake"
+ "Ambang batas deteksi"
+
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 e848082e91..a4d06564a8 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
@@ -136,7 +136,7 @@ class VectorFileLogger(
*
* @return The list of files with logs.
*/
- fun getLogFiles(): List {
+ private fun getLogFiles(): List {
return tryOrNull(
onError = { Timber.e(it, "## getLogFiles() failed") }
) {
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 3bd7405f52..5acf5b4103 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
@@ -35,6 +35,7 @@ import io.element.android.libraries.core.meta.BuildMeta
import io.element.android.libraries.core.mimetype.MimeTypes
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.network.useragent.UserAgentProvider
import io.element.android.libraries.sessionstorage.api.SessionStore
import io.element.android.services.toolbox.api.systemclock.SystemClock
@@ -63,6 +64,7 @@ import javax.inject.Provider
/**
* BugReporter creates and sends the bug reports.
*/
+@SingleIn(AppScope::class)
@ContributesBinding(AppScope::class)
class DefaultBugReporter @Inject constructor(
@ApplicationContext private val context: Context,
@@ -86,10 +88,10 @@ class DefaultBugReporter @Inject constructor(
// the pending bug report call
private var bugReportCall: Call? = null
-
// boolean to cancel the bug report
private val isCancelled = false
private val logcatCommandDebug = arrayOf("logcat", "-d", "-v", "threadtime", "*:*")
+ private var currentTracingFilter: String? = null
override suspend fun sendBugReport(
withDevicesLogs: Boolean,
@@ -153,6 +155,9 @@ class DefaultBugReporter @Inject constructor(
.addFormDataPart("device_id", deviceId)
.addFormDataPart("device", Build.MODEL.trim())
.addFormDataPart("locale", Locale.getDefault().toString())
+ currentTracingFilter?.let {
+ builder.addFormDataPart("tracing_filter", it)
+ }
// add the gzipped files, don't cancel the whole upload if only some file failed to upload
var uploadedSomeLogs = false
@@ -323,6 +328,10 @@ class DefaultBugReporter @Inject constructor(
}
}
+ override fun setCurrentTracingFilter(tracingFilter: String) {
+ currentTracingFilter = tracingFilter
+ }
+
/**
* @return the files on the log directory.
*/
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 68951d81f8..95e8c0228b 100644
--- a/features/rageshake/impl/src/main/res/values-de/translations.xml
+++ b/features/rageshake/impl/src/main/res/values-de/translations.xml
@@ -4,7 +4,7 @@
"Sie können mich kontaktieren, wenn Sie weitere Fragen haben."
"Kontaktieren Sie mich"
"Bildschirmfoto bearbeiten"
- "Bitte beschreibe den Fehler. Was hast du getan? Was hast du erwartet, was passiert? Was ist tatsächlich passiert. Bitte gehe so detailliert wie möglich vor."
+ "Bitte beschreibe den Fehler. Was hast du getan? Was hast du erwartet, was passiert? Was ist tatsächlich passiert? Bitte gehe so detailliert wie möglich vor."
"Beschreibe den Fehler…"
"Wenn möglich, verfasse die Beschreibung bitte auf Englisch."
"Absturzprotokolle senden"
diff --git a/features/rageshake/impl/src/main/res/values-hu/translations.xml b/features/rageshake/impl/src/main/res/values-hu/translations.xml
new file mode 100644
index 0000000000..bc09e541ab
--- /dev/null
+++ b/features/rageshake/impl/src/main/res/values-hu/translations.xml
@@ -0,0 +1,15 @@
+
+
+ "Képernyőkép mellékelése"
+ "Felveheti velem a kapcsolatot, ha bármilyen további kérdése van."
+ "Kapcsolat"
+ "Képernyőkép szerkesztése"
+ "Írja le a hibát. Mit csinált? Mire számított, hogy mi fog történni? Mi történt valójában? Fogalmazzon a lehető legrészletesebben."
+ "Írja le a problémát…"
+ "Ha lehetséges, a leírást angolul írja meg."
+ "Összeomlásnaplók küldése"
+ "Naplók engedélyezése"
+ "Képernyőkép küldése"
+ "A naplók szerepelni fognak az üzenetben, hogy megbizonyosodhassunk arról, hogy minden megfelelően működik-e. Ha naplók nélkül szeretné elküldeni az üzenetet, akkor kapcsolja ki ezt a beállítást."
+ "Az %1$s összeomlott a legutóbbi használata óta. Megosztja velünk az összeomlás-jelentést?"
+
diff --git a/features/rageshake/impl/src/main/res/values-in/translations.xml b/features/rageshake/impl/src/main/res/values-in/translations.xml
new file mode 100644
index 0000000000..14c1defea9
--- /dev/null
+++ b/features/rageshake/impl/src/main/res/values-in/translations.xml
@@ -0,0 +1,15 @@
+
+
+ "Lampirkan tangkapan layar"
+ "Anda dapat menghubungi saya jika Anda memiliki pertanyaan lebih lanjut."
+ "Hubungi saya"
+ "Sunting tangkapan layar"
+ "Silakan jelaskan masalah tersebut. Apa yang Anda lakukan? Apa yang Anda harapkan untuk terjadi? Apa yang sebenarnya terjadi? Jelaskan sedetail mungkin."
+ "Jelaskan masalah tersebut…"
+ "Jika memungkinkan, silakan tulis deskripsi dalam bahasa Inggris."
+ "Kirim log kerusakan"
+ "Izinkan log"
+ "Kirim tangkapan layar"
+ "Log akan disertakan dengan pesan Anda untuk memastikan bahwa semuanya berfungsi dengan baik. Untuk mengirimkan pesan Anda tanpa log, matikan pengaturan ini."
+ "%1$s mengalami kemogokan saat terakhir kali digunakan. Apakah Anda ingin berbagi laporan kerusakan dengan kami?"
+
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 00343f8f6e..2cd9e61398 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
@@ -59,6 +59,10 @@ class FakeBugReporter(val mode: FakeBugReporterMode = FakeBugReporterMode.Succes
override fun logDirectory(): File {
return File("fake")
}
+
+ override fun setCurrentTracingFilter(tracingFilter: String) {
+ // No op
+ }
}
enum class FakeBugReporterMode {
diff --git a/features/rageshake/impl/src/test/kotlin/io/element/android/features/rageshake/impl/logs/VectorFileLoggerTest.kt b/features/rageshake/impl/src/test/kotlin/io/element/android/features/rageshake/impl/logs/VectorFileLoggerTest.kt
new file mode 100644
index 0000000000..26e29e1786
--- /dev/null
+++ b/features/rageshake/impl/src/test/kotlin/io/element/android/features/rageshake/impl/logs/VectorFileLoggerTest.kt
@@ -0,0 +1,58 @@
+/*
+ * 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.rageshake.impl.logs
+
+import com.google.common.truth.Truth.assertThat
+import io.element.android.libraries.matrix.test.A_THROWABLE
+import io.element.android.tests.testutils.testCoroutineDispatchers
+import kotlinx.coroutines.test.TestScope
+import kotlinx.coroutines.test.runTest
+import org.junit.Test
+import org.junit.runner.RunWith
+import org.robolectric.RobolectricTestRunner
+import org.robolectric.RuntimeEnvironment
+
+@RunWith(RobolectricTestRunner::class)
+class VectorFileLoggerTest {
+ @Test
+ fun `init VectorFileLogger log debug`() = runTest {
+ val sut = createVectorFileLogger()
+ sut.d("A debug log")
+ }
+
+ @Test
+ fun `init VectorFileLogger log error`() = runTest {
+ val sut = createVectorFileLogger()
+ sut.e(A_THROWABLE, "A debug log")
+ }
+
+ @Test
+ fun `reset VectorFileLogger`() = runTest {
+ val sut = createVectorFileLogger()
+ sut.reset()
+ }
+
+ @Test
+ fun `check getFromTimber`() {
+ assertThat(VectorFileLogger.getFromTimber()).isNull()
+ }
+
+ private fun TestScope.createVectorFileLogger() = VectorFileLogger(
+ context = RuntimeEnvironment.getApplication(),
+ dispatcher = testCoroutineDispatchers().io,
+ )
+}
diff --git a/features/roomdetails/api/src/main/kotlin/io/element/android/features/roomdetails/api/RoomDetailsEntryPoint.kt b/features/roomdetails/api/src/main/kotlin/io/element/android/features/roomdetails/api/RoomDetailsEntryPoint.kt
index 0aaac324da..bd1a414294 100644
--- a/features/roomdetails/api/src/main/kotlin/io/element/android/features/roomdetails/api/RoomDetailsEntryPoint.kt
+++ b/features/roomdetails/api/src/main/kotlin/io/element/android/features/roomdetails/api/RoomDetailsEntryPoint.kt
@@ -22,6 +22,7 @@ import com.bumble.appyx.core.node.Node
import com.bumble.appyx.core.plugin.Plugin
import io.element.android.libraries.architecture.FeatureEntryPoint
import io.element.android.libraries.architecture.NodeInputs
+import io.element.android.libraries.matrix.api.core.RoomId
import io.element.android.libraries.matrix.api.core.UserId
import kotlinx.parcelize.Parcelize
@@ -42,6 +43,7 @@ interface RoomDetailsEntryPoint : FeatureEntryPoint {
interface Callback : Plugin {
fun onOpenGlobalNotificationSettings()
+ fun onOpenRoom(roomId: RoomId)
}
interface NodeBuilder {
diff --git a/features/roomdetails/impl/build.gradle.kts b/features/roomdetails/impl/build.gradle.kts
index 5f389bcfe9..0f1a139f40 100644
--- a/features/roomdetails/impl/build.gradle.kts
+++ b/features/roomdetails/impl/build.gradle.kts
@@ -51,6 +51,7 @@ dependencies {
api(projects.services.apperror.api)
implementation(libs.coil.compose)
implementation(projects.features.leaveroom.api)
+ implementation(projects.features.createroom.api)
implementation(projects.services.analytics.api)
implementation(projects.features.poll.api)
@@ -68,6 +69,7 @@ dependencies {
testImplementation(projects.libraries.featureflag.test)
testImplementation(projects.tests.testutils)
testImplementation(projects.features.leaveroom.test)
+ testImplementation(projects.features.createroom.test)
ksp(libs.showkase.processor)
}
diff --git a/features/roomdetails/impl/src/main/kotlin/io/element/android/features/roomdetails/impl/RoomDetailsFlowNode.kt b/features/roomdetails/impl/src/main/kotlin/io/element/android/features/roomdetails/impl/RoomDetailsFlowNode.kt
index 2e58ccfe4e..47c8878825 100644
--- a/features/roomdetails/impl/src/main/kotlin/io/element/android/features/roomdetails/impl/RoomDetailsFlowNode.kt
+++ b/features/roomdetails/impl/src/main/kotlin/io/element/android/features/roomdetails/impl/RoomDetailsFlowNode.kt
@@ -42,6 +42,7 @@ import io.element.android.libraries.architecture.animation.rememberDefaultTransi
import io.element.android.libraries.architecture.createNode
import io.element.android.libraries.core.mimetype.MimeTypes
import io.element.android.libraries.di.RoomScope
+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.media.MediaSource
import io.element.android.libraries.mediaviewer.api.local.MediaInfo
@@ -161,6 +162,10 @@ class RoomDetailsFlowNode @AssistedInject constructor(
override fun openAvatarPreview(username: String, avatarUrl: String) {
backstack.push(NavTarget.MemberAvatarPreview(username, avatarUrl))
}
+
+ override fun onStartDM(roomId: RoomId) {
+ plugins().forEach { it.onOpenRoom(roomId) }
+ }
}
val plugins = listOf(RoomMemberDetailsNode.RoomMemberDetailsInput(navTarget.roomMemberId), callback)
createNode(buildContext, plugins)
diff --git a/features/roomdetails/impl/src/main/kotlin/io/element/android/features/roomdetails/impl/blockuser/BlockUserSection.kt b/features/roomdetails/impl/src/main/kotlin/io/element/android/features/roomdetails/impl/blockuser/BlockUserSection.kt
index 532e1a8a25..b99319812b 100644
--- a/features/roomdetails/impl/src/main/kotlin/io/element/android/features/roomdetails/impl/blockuser/BlockUserSection.kt
+++ b/features/roomdetails/impl/src/main/kotlin/io/element/android/features/roomdetails/impl/blockuser/BlockUserSection.kt
@@ -85,6 +85,7 @@ private fun PreferenceBlockUser(
leadingContent = ListItemContent.Icon(IconSource.Vector(CompoundIcons.Block)),
onClick = { if (!isLoading) eventSink(RoomMemberDetailsEvents.UnblockUser(needsConfirmation = true)) },
trailingContent = if (isLoading) ListItemContent.Custom(loadingCurrentValue) else null,
+ style = ListItemStyle.Primary,
modifier = modifier,
)
} else {
diff --git a/features/roomdetails/impl/src/main/kotlin/io/element/android/features/roomdetails/impl/di/RoomMemberModule.kt b/features/roomdetails/impl/src/main/kotlin/io/element/android/features/roomdetails/impl/di/RoomMemberModule.kt
index ca462c6507..c65b63432e 100644
--- a/features/roomdetails/impl/src/main/kotlin/io/element/android/features/roomdetails/impl/di/RoomMemberModule.kt
+++ b/features/roomdetails/impl/src/main/kotlin/io/element/android/features/roomdetails/impl/di/RoomMemberModule.kt
@@ -19,6 +19,7 @@ package io.element.android.features.roomdetails.impl.di
import com.squareup.anvil.annotations.ContributesTo
import dagger.Module
import dagger.Provides
+import io.element.android.features.createroom.api.StartDMAction
import io.element.android.features.roomdetails.impl.members.details.RoomMemberDetailsPresenter
import io.element.android.libraries.di.RoomScope
import io.element.android.libraries.matrix.api.MatrixClient
@@ -33,10 +34,11 @@ object RoomMemberModule {
fun provideRoomMemberDetailsPresenterFactory(
matrixClient: MatrixClient,
room: MatrixRoom,
+ startDMAction: StartDMAction,
): RoomMemberDetailsPresenter.Factory {
return object : RoomMemberDetailsPresenter.Factory {
override fun create(roomMemberId: UserId): RoomMemberDetailsPresenter {
- return RoomMemberDetailsPresenter(matrixClient, room, roomMemberId)
+ return RoomMemberDetailsPresenter(roomMemberId, matrixClient, room, startDMAction)
}
}
}
diff --git a/features/roomdetails/impl/src/main/kotlin/io/element/android/features/roomdetails/impl/members/details/RoomMemberDetailsEvents.kt b/features/roomdetails/impl/src/main/kotlin/io/element/android/features/roomdetails/impl/members/details/RoomMemberDetailsEvents.kt
index 05688c6cf7..75c66f26e2 100644
--- a/features/roomdetails/impl/src/main/kotlin/io/element/android/features/roomdetails/impl/members/details/RoomMemberDetailsEvents.kt
+++ b/features/roomdetails/impl/src/main/kotlin/io/element/android/features/roomdetails/impl/members/details/RoomMemberDetailsEvents.kt
@@ -17,6 +17,8 @@
package io.element.android.features.roomdetails.impl.members.details
sealed interface RoomMemberDetailsEvents {
+ data object StartDM : RoomMemberDetailsEvents
+ data object ClearStartDMState : RoomMemberDetailsEvents
data class BlockUser(val needsConfirmation: Boolean = false) : RoomMemberDetailsEvents
data class UnblockUser(val needsConfirmation: Boolean = false) : RoomMemberDetailsEvents
data object ClearBlockUserError : RoomMemberDetailsEvents
diff --git a/features/roomdetails/impl/src/main/kotlin/io/element/android/features/roomdetails/impl/members/details/RoomMemberDetailsNode.kt b/features/roomdetails/impl/src/main/kotlin/io/element/android/features/roomdetails/impl/members/details/RoomMemberDetailsNode.kt
index 8d20ddaf77..3037136f63 100644
--- a/features/roomdetails/impl/src/main/kotlin/io/element/android/features/roomdetails/impl/members/details/RoomMemberDetailsNode.kt
+++ b/features/roomdetails/impl/src/main/kotlin/io/element/android/features/roomdetails/impl/members/details/RoomMemberDetailsNode.kt
@@ -17,6 +17,7 @@
package io.element.android.features.roomdetails.impl.members.details
import androidx.compose.runtime.Composable
+import androidx.compose.runtime.LaunchedEffect
import androidx.compose.ui.Modifier
import androidx.compose.ui.platform.LocalContext
import com.bumble.appyx.core.lifecycle.subscribe
@@ -29,9 +30,11 @@ import im.vector.app.features.analytics.plan.MobileScreen
import io.element.android.anvilannotations.ContributesNode
import io.element.android.features.roomdetails.impl.R
import io.element.android.libraries.androidutils.system.startSharePlainTextIntent
+import io.element.android.libraries.architecture.Async
import io.element.android.libraries.architecture.NodeInputs
import io.element.android.libraries.architecture.inputs
import io.element.android.libraries.di.RoomScope
+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.permalink.PermalinkBuilder
import io.element.android.services.analytics.api.AnalyticsService
@@ -46,8 +49,9 @@ class RoomMemberDetailsNode @AssistedInject constructor(
presenterFactory: RoomMemberDetailsPresenter.Factory,
) : Node(buildContext, plugins = plugins) {
- interface Callback: NodeInputs {
+ interface Callback : NodeInputs {
fun openAvatarPreview(username: String, avatarUrl: String)
+ fun onStartDM(roomId: RoomId)
}
data class RoomMemberDetailsInput(
@@ -84,12 +88,23 @@ class RoomMemberDetailsNode @AssistedInject constructor(
}
}
+ fun onStartDM(roomId: RoomId) {
+ callback.onStartDM(roomId)
+ }
+
val state = presenter.present()
+
+ LaunchedEffect(state.startDmActionState) {
+ if (state.startDmActionState is Async.Success) {
+ onStartDM(state.startDmActionState.data)
+ }
+ }
RoomMemberDetailsView(
state = state,
modifier = modifier,
goBack = this::navigateUp,
onShareUser = ::onShareUser,
+ onDMStarted = ::onStartDM,
openAvatarPreview = callback::openAvatarPreview,
)
}
diff --git a/features/roomdetails/impl/src/main/kotlin/io/element/android/features/roomdetails/impl/members/details/RoomMemberDetailsPresenter.kt b/features/roomdetails/impl/src/main/kotlin/io/element/android/features/roomdetails/impl/members/details/RoomMemberDetailsPresenter.kt
index 3be83a2fef..e82b5f0cb5 100644
--- a/features/roomdetails/impl/src/main/kotlin/io/element/android/features/roomdetails/impl/members/details/RoomMemberDetailsPresenter.kt
+++ b/features/roomdetails/impl/src/main/kotlin/io/element/android/features/roomdetails/impl/members/details/RoomMemberDetailsPresenter.kt
@@ -27,11 +27,13 @@ import androidx.compose.runtime.rememberCoroutineScope
import androidx.compose.runtime.setValue
import dagger.assisted.Assisted
import dagger.assisted.AssistedInject
+import io.element.android.features.createroom.api.StartDMAction
import io.element.android.features.roomdetails.impl.members.details.RoomMemberDetailsState.ConfirmationDialog
import io.element.android.libraries.architecture.Async
import io.element.android.libraries.architecture.Presenter
import io.element.android.libraries.core.bool.orFalse
import io.element.android.libraries.matrix.api.MatrixClient
+import io.element.android.libraries.matrix.api.core.RoomId
import io.element.android.libraries.matrix.api.core.UserId
import io.element.android.libraries.matrix.api.room.MatrixRoom
import io.element.android.libraries.matrix.ui.room.getRoomMemberAsState
@@ -39,9 +41,10 @@ import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.launch
class RoomMemberDetailsPresenter @AssistedInject constructor(
+ @Assisted private val roomMemberId: UserId,
private val client: MatrixClient,
private val room: MatrixRoom,
- @Assisted private val roomMemberId: UserId,
+ private val startDMAction: StartDMAction,
) : Presenter {
interface Factory {
@@ -53,6 +56,7 @@ class RoomMemberDetailsPresenter @AssistedInject constructor(
val coroutineScope = rememberCoroutineScope()
var confirmationDialog by remember { mutableStateOf(null) }
val roomMember by room.getRoomMemberAsState(roomMemberId)
+ val startDmActionState: MutableState> = remember { mutableStateOf(Async.Uninitialized) }
// the room member is not really live...
val isBlocked: MutableState> = remember(roomMember) {
val isIgnored = roomMember?.isIgnored
@@ -88,6 +92,14 @@ class RoomMemberDetailsPresenter @AssistedInject constructor(
RoomMemberDetailsEvents.ClearBlockUserError -> {
isBlocked.value = Async.Success(isBlocked.value.dataOrNull().orFalse())
}
+ RoomMemberDetailsEvents.StartDM -> {
+ coroutineScope.launch {
+ startDMAction.execute(roomMemberId, startDmActionState)
+ }
+ }
+ RoomMemberDetailsEvents.ClearStartDMState -> {
+ startDmActionState.value = Async.Uninitialized
+ }
}
}
@@ -108,6 +120,7 @@ class RoomMemberDetailsPresenter @AssistedInject constructor(
userName = userName,
avatarUrl = userAvatar,
isBlocked = isBlocked.value,
+ startDmActionState = startDmActionState.value,
displayConfirmationDialog = confirmationDialog,
isCurrentUser = client.isMe(roomMember?.userId),
eventSink = ::handleEvents
diff --git a/features/roomdetails/impl/src/main/kotlin/io/element/android/features/roomdetails/impl/members/details/RoomMemberDetailsState.kt b/features/roomdetails/impl/src/main/kotlin/io/element/android/features/roomdetails/impl/members/details/RoomMemberDetailsState.kt
index 957db2233e..ee9cfe388f 100644
--- a/features/roomdetails/impl/src/main/kotlin/io/element/android/features/roomdetails/impl/members/details/RoomMemberDetailsState.kt
+++ b/features/roomdetails/impl/src/main/kotlin/io/element/android/features/roomdetails/impl/members/details/RoomMemberDetailsState.kt
@@ -17,12 +17,14 @@
package io.element.android.features.roomdetails.impl.members.details
import io.element.android.libraries.architecture.Async
+import io.element.android.libraries.matrix.api.core.RoomId
data class RoomMemberDetailsState(
val userId: String,
val userName: String?,
val avatarUrl: String?,
val isBlocked: Async,
+ val startDmActionState: Async,
val displayConfirmationDialog: ConfirmationDialog?,
val isCurrentUser: Boolean,
val eventSink: (RoomMemberDetailsEvents) -> Unit
diff --git a/features/roomdetails/impl/src/main/kotlin/io/element/android/features/roomdetails/impl/members/details/RoomMemberDetailsStateProvider.kt b/features/roomdetails/impl/src/main/kotlin/io/element/android/features/roomdetails/impl/members/details/RoomMemberDetailsStateProvider.kt
index b14b0e3634..c5710986a6 100644
--- a/features/roomdetails/impl/src/main/kotlin/io/element/android/features/roomdetails/impl/members/details/RoomMemberDetailsStateProvider.kt
+++ b/features/roomdetails/impl/src/main/kotlin/io/element/android/features/roomdetails/impl/members/details/RoomMemberDetailsStateProvider.kt
@@ -28,6 +28,7 @@ open class RoomMemberDetailsStateProvider : PreviewParameterProvider Unit,
+ onDMStarted: (RoomId) -> Unit,
goBack: () -> Unit,
openAvatarPreview: (username: String, url: String) -> Unit,
modifier: Modifier = Modifier,
@@ -71,31 +83,36 @@ fun RoomMemberDetailsView(
Spacer(modifier = Modifier.height(26.dp))
- // TODO implement send DM
- // SendMessageSection(onSendMessage = {
- // ...
- // })
-
if (!state.isCurrentUser) {
+ StartDMSection(onStartDMClicked = { state.eventSink(RoomMemberDetailsEvents.StartDM) })
BlockUserSection(state)
BlockUserDialogs(state)
}
+ AsyncView(
+ async = state.startDmActionState,
+ progressText = stringResource(CommonStrings.common_starting_chat),
+ onSuccess = onDMStarted,
+ errorMessage = { stringResource(R.string.screen_start_chat_error_starting_chat) },
+ onRetry = { state.eventSink(RoomMemberDetailsEvents.StartDM) },
+ onErrorDismiss = { state.eventSink(RoomMemberDetailsEvents.ClearStartDMState) },
+ )
}
}
}
-/*
@Composable
-private fun SendMessageSection(onSendMessage: () -> Unit, modifier: Modifier = Modifier) {
- PreferenceCategory(modifier = modifier) {
- PreferenceText(
- title = stringResource(CommonStrings.action_send_message),
- icon = Icons.Outlined.ChatBubbleOutline,
- onClick = onSendMessage,
- )
- }
+private fun StartDMSection(
+ onStartDMClicked: () -> Unit,
+ modifier: Modifier = Modifier
+) {
+ ListItem(
+ headlineContent = { Text(stringResource(CommonStrings.common_direct_chat)) },
+ leadingContent = ListItemContent.Icon(IconSource.Vector(CompoundIcons.Chat)),
+ style = ListItemStyle.Primary,
+ onClick = onStartDMClicked,
+ modifier = modifier,
+ )
}
- */
@PreviewWithLargeHeight
@Composable
@@ -113,6 +130,7 @@ private fun ContentToPreview(state: RoomMemberDetailsState) {
state = state,
onShareUser = {},
goBack = {},
+ onDMStarted = {},
openAvatarPreview = { _, _ -> }
)
}
diff --git a/features/roomdetails/impl/src/main/kotlin/io/element/android/features/roomdetails/impl/members/details/RoomMemberHeaderSection.kt b/features/roomdetails/impl/src/main/kotlin/io/element/android/features/roomdetails/impl/members/details/RoomMemberHeaderSection.kt
index 5025f37b65..a5cc975b48 100644
--- a/features/roomdetails/impl/src/main/kotlin/io/element/android/features/roomdetails/impl/members/details/RoomMemberHeaderSection.kt
+++ b/features/roomdetails/impl/src/main/kotlin/io/element/android/features/roomdetails/impl/members/details/RoomMemberHeaderSection.kt
@@ -29,13 +29,14 @@ import androidx.compose.material3.MaterialTheme
import androidx.compose.runtime.Composable
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
+import androidx.compose.ui.draw.clipToBounds
import androidx.compose.ui.text.style.TextAlign
import androidx.compose.ui.unit.dp
+import io.element.android.compound.theme.ElementTheme
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.theme.components.Text
-import io.element.android.compound.theme.ElementTheme
@Composable
fun RoomMemberHeaderSection(
@@ -56,7 +57,11 @@ fun RoomMemberHeaderSection(
}
Spacer(modifier = Modifier.height(24.dp))
if (userName != null) {
- Text(text = userName, style = ElementTheme.typography.fontHeadingLgBold)
+ Text(
+ modifier = Modifier.clipToBounds(),
+ text = userName,
+ style = ElementTheme.typography.fontHeadingLgBold,
+ )
Spacer(modifier = Modifier.height(6.dp))
}
Text(
diff --git a/features/roomdetails/impl/src/main/res/values-cs/translations.xml b/features/roomdetails/impl/src/main/res/values-cs/translations.xml
index 0bddcdf7cd..9fb44a01e6 100644
--- a/features/roomdetails/impl/src/main/res/values-cs/translations.xml
+++ b/features/roomdetails/impl/src/main/res/values-cs/translations.xml
@@ -39,6 +39,7 @@
"Váš domovský server tuto možnost nepodporuje v šifrovaných místnostech, v této místnosti nebudete dostávat upozornění."
"Všechny zprávy"
"V této místnosti mě upozornit na"
+ "Při pokusu o zahájení chatu došlo k chybě"
"Zablokovat"
"Blokovaní uživatelé vám nebudou moci posílat zprávy a všechny jejich zprávy budou skryty. Můžete je kdykoli odblokovat."
"Zablokovat uživatele"
diff --git a/features/roomdetails/impl/src/main/res/values-de/translations.xml b/features/roomdetails/impl/src/main/res/values-de/translations.xml
index 9589c06a1e..4a0bc27207 100644
--- a/features/roomdetails/impl/src/main/res/values-de/translations.xml
+++ b/features/roomdetails/impl/src/main/res/values-de/translations.xml
@@ -35,8 +35,10 @@
"Beim Laden der Benachrichtigungseinstellungen ist ein Fehler aufgetreten."
"Fehler beim Wiederherstellen des Standardmodus. Bitte versuche es erneut."
"Fehler beim Einstellen des Modus. Bitte versuche es erneut."
+ "Dein Homeserver unterstützt diese Option in verschlüsselten Räumen nicht. Du wirst in diesem Raum nicht benachrichtigt."
"Alle Nachrichten"
"Benachrichtige mich in diesem Raum bei"
+ "Beim Versuch, einen Chat zu starten, ist ein Fehler aufgetreten"
"Sperren"
"Gesperrte Benutzer können dir keine Nachrichten senden und alle ihre Nachrichten werden ausgeblendet. Du kannst sie jederzeit entsperren."
"Benutzer sperren"
diff --git a/features/roomdetails/impl/src/main/res/values-es/translations.xml b/features/roomdetails/impl/src/main/res/values-es/translations.xml
index 620f974340..60353e3185 100644
--- a/features/roomdetails/impl/src/main/res/values-es/translations.xml
+++ b/features/roomdetails/impl/src/main/res/values-es/translations.xml
@@ -8,6 +8,7 @@
"Cifrado de mensajes activado"
"Invitar a otras personas"
"Compartir sala"
+ "Se ha producido un error al intentar iniciar un chat"
"Bloquear"
"Los usuarios bloqueados no podrán enviarte mensajes y se ocultarán todos sus mensajes. Puede revertir esta acción en cualquier momento."
"Bloquear usuario"
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 dd35f40252..9b0e1c59e5 100644
--- a/features/roomdetails/impl/src/main/res/values-fr/translations.xml
+++ b/features/roomdetails/impl/src/main/res/values-fr/translations.xml
@@ -38,6 +38,7 @@
"Votre serveur d’accueil ne supporte pas cette option pour les salons chiffrés, vous ne serez pas notifié(e) dans ce salon."
"Tous les messages"
"Dans ce salon, prévenez-moi pour"
+ "Une erreur s’est produite lors de la tentative de création de la discussion"
"Bloquer"
"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"
diff --git a/features/roomdetails/impl/src/main/res/values-hu/translations.xml b/features/roomdetails/impl/src/main/res/values-hu/translations.xml
new file mode 100644
index 0000000000..8144c35de7
--- /dev/null
+++ b/features/roomdetails/impl/src/main/res/values-hu/translations.xml
@@ -0,0 +1,48 @@
+
+
+ "Hiba történt az értesítési beállítás frissítésekor."
+ "Téma hozzáadása"
+ "Már tag"
+ "Már meghívták"
+ "Szoba szerkesztése"
+ "Ismeretlen hiba történt, és az információkat nem lehetett megváltoztatni."
+ "Nem sikerült frissíteni a szobát"
+ "Az üzeneteket kulcsok védik. Csak Ön és a címzett rendelkezik a feloldásukhoz szükséges egyedi kulcsokkal."
+ "Az üzenettitkosítás engedélyezve"
+ "Hiba történt az értesítési beállítások betöltésekor."
+ "Nem sikerült elnémítani ezt a szobát, próbálja újra."
+ "Nem sikerült feloldani a szoba némítását, próbálja újra."
+ "Emberek meghívása"
+ "Egyéni"
+ "Alapértelmezett"
+ "Értesítések"
+ "Szoba neve"
+ "Szoba megosztása"
+ "Szoba frissítése…"
+ "Függőben"
+ "Szoba tagjai"
+ "Egyéni beállítás engedélyezése"
+ "Ennek bekapcsolása felülírja az alapértelmezett beállítást"
+ "Értesítések kérése ebben a csevegésben ezekről:"
+ "Megváltoztathatja a %1$s."
+ "globális beállításokban"
+ "Alapértelmezett beállítás"
+ "Egyéni beállítás eltávolítása"
+ "Hiba történt az értesítési beállítások betöltésekor."
+ "Nem sikerült visszaállítani az alapértelmezett módot, próbálja újra."
+ "Nem sikerült a mód beállítása, próbálja újra."
+ "A Matrix-kiszolgálója nem támogatja ezt a beállítást a titkosított szobákban, egyes szobákban nem fog értesítéseket kapni."
+ "Összes üzenet"
+ "Ebben a szobában, értesítés ezekről:"
+ "Hiba történt a csevegés indításakor"
+ "Letiltás"
+ "A letiltott felhasználók nem fognak tudni üzeneteket küldeni, és az összes üzenetük rejtve lesz. Bármikor feloldhatja a letiltásukat."
+ "Felhasználó letiltása"
+ "Letiltás feloldása"
+ "Újra láthatja az összes üzenetét."
+ "Felhasználó kitiltásának feloldása"
+ "Szoba elhagyása"
+ "Biztonság"
+ "Téma"
+ "Csak említések és kulcsszavak"
+
diff --git a/features/roomdetails/impl/src/main/res/values-in/translations.xml b/features/roomdetails/impl/src/main/res/values-in/translations.xml
new file mode 100644
index 0000000000..b24da2c1a1
--- /dev/null
+++ b/features/roomdetails/impl/src/main/res/values-in/translations.xml
@@ -0,0 +1,51 @@
+
+
+
+ - "%1$d orang"
+
+ "Terjadi kesalahan saat memperbarui pengaturan pemberitahuan."
+ "Tambahkan topik"
+ "Sudah menjadi anggota"
+ "Sudah diundang"
+ "Sunting Ruangan"
+ "Terjadi kesalahan yang tidak diketahui dan informasinya tidak dapat diubah."
+ "Tidak dapat memperbarui ruangan"
+ "Pesan diamankan dengan kunci. Hanya Anda dan penerima yang memiliki kunci unik untuk membukanya."
+ "Enkripsi pesan diaktifkan"
+ "Terjadi kesalahan saat memuat pengaturan notifikasi."
+ "Gagal membisukan ruangan ini, silakan coba lagi."
+ "Gagal membunyikan ruangan ini, silakan coba lagi."
+ "Undang seseorang"
+ "Khusus"
+ "Bawaan"
+ "Pemberitahuan"
+ "Nama ruangan"
+ "Bagikan ruangan"
+ "Memperbarui ruangan…"
+ "Tertunda"
+ "Anggota ruangan"
+ "Izinkan pengaturan khusus"
+ "Mengaktifkan ini akan mengganti pengaturan bawaan Anda"
+ "Beri tahu saya di obrolan ini tentang"
+ "Anda dapat mengubahnya di %1$s Anda."
+ "pengaturan global"
+ "Pengaturan bawaan"
+ "Hapus pengaturan khusus"
+ "Terjadi kesalahan saat memuat pengaturan pemberitahuan."
+ "Gagal memulihkan mode bawaan, silakan coba lagi."
+ "Gagal mengatur mode, silakan coba lagi."
+ "Homeserver Anda tidak mendukung opsi ini dalam ruangan terenkripsi, Anda tidak akan diberi tahu dalam ruangan ini."
+ "Semua pesan"
+ "Di ruangan ini, beri tahu saya tentang"
+ "Terjadi kesalahan saat mencoba memulai obrolan"
+ "Blokir"
+ "Pengguna yang diblokir tidak akan dapat mengirim Anda pesan dan semua pesan mereka akan disembunyikan. Anda dapat membuka blokirnya kapan saja."
+ "Blokir pengguna"
+ "Buka blokir"
+ "Anda akan dapat melihat semua pesan dari mereka lagi."
+ "Buka blokir pengguna"
+ "Tinggalkan ruangan"
+ "Keamanan"
+ "Topik"
+ "Sebutan dan Kata Kunci saja"
+
diff --git a/features/roomdetails/impl/src/main/res/values-it/translations.xml b/features/roomdetails/impl/src/main/res/values-it/translations.xml
index c00fb14bc1..3217efe862 100644
--- a/features/roomdetails/impl/src/main/res/values-it/translations.xml
+++ b/features/roomdetails/impl/src/main/res/values-it/translations.xml
@@ -8,6 +8,7 @@
"Crittografia messaggi abilitata"
"Invita persone"
"Condividi stanza"
+ "Si è verificato un errore durante il tentativo di avviare una chat"
"Blocca"
"Gli utenti bloccati non saranno in grado di inviarti nuovi messaggi e tutti quelli già esistenti saranno nascosti. Potrai annullare questa azione in qualsiasi momento."
"Blocca utente"
diff --git a/features/roomdetails/impl/src/main/res/values-ro/translations.xml b/features/roomdetails/impl/src/main/res/values-ro/translations.xml
index 1a78709241..be6217d5e9 100644
--- a/features/roomdetails/impl/src/main/res/values-ro/translations.xml
+++ b/features/roomdetails/impl/src/main/res/values-ro/translations.xml
@@ -37,6 +37,7 @@
"Nu s-a reușit setarea modului, vă rugăm să încercați din nou."
"Toate mesajele"
"În această cameră, anunțați-mă pentru"
+ "A apărut o eroare la încercarea începerii conversației"
"Blocați"
"Utilizatorii blocați nu vă vor putea trimite mesaje și toate mesajele lor vor fi ascunse. Puteți anula această acțiune oricând."
"Blocați utilizatorul"
diff --git a/features/roomdetails/impl/src/main/res/values-ru/translations.xml b/features/roomdetails/impl/src/main/res/values-ru/translations.xml
index 7d3eae6fff..a83b6828d1 100644
--- a/features/roomdetails/impl/src/main/res/values-ru/translations.xml
+++ b/features/roomdetails/impl/src/main/res/values-ru/translations.xml
@@ -39,6 +39,7 @@
"Ваш домашний сервер не поддерживает эту опцию в зашифрованных комнатах, вы не будете получать уведомления в этой комнате."
"Все сообщения"
"В этой комнате уведомить меня о"
+ "Произошла ошибка при попытке открытия комнаты"
"Заблокировать"
"Заблокированные пользователи не смогут отправлять вам сообщения, а все их сообщения будут скрыты. Вы можете разблокировать их в любое время."
"Заблокировать пользователя"
diff --git a/features/roomdetails/impl/src/main/res/values-sk/translations.xml b/features/roomdetails/impl/src/main/res/values-sk/translations.xml
index c7e422b920..c2f40781aa 100644
--- a/features/roomdetails/impl/src/main/res/values-sk/translations.xml
+++ b/features/roomdetails/impl/src/main/res/values-sk/translations.xml
@@ -39,6 +39,7 @@
"Váš domovský server nepodporuje túto možnosť v šifrovaných miestnostiach, v tejto miestnosti nedostanete upozornenie."
"Všetky správy"
"V tejto miestnosti ma upozorniť na"
+ "Pri pokuse o spustenie konverzácie sa vyskytla chyba"
"Zablokovať"
"Blokovaní používatelia vám nebudú môcť posielať správy a všetky ich správy budú skryté. Môžete ich kedykoľvek odblokovať."
"Zablokovať používateľa"
diff --git a/features/roomdetails/impl/src/main/res/values/localazy.xml b/features/roomdetails/impl/src/main/res/values/localazy.xml
index f8bf5ddf6f..dd324d9576 100644
--- a/features/roomdetails/impl/src/main/res/values/localazy.xml
+++ b/features/roomdetails/impl/src/main/res/values/localazy.xml
@@ -39,6 +39,7 @@
"Your homeserver does not support this option in encrypted rooms, you won\'t get notified in this room."
"All messages"
"In this room, notify me for"
+ "An error occurred when trying to start a chat"
"Block"
"Blocked users won\'t be able to send you messages and all their messages will be hidden. You can unblock them anytime."
"Block user"
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 f7a74ddcc0..6ffba16377 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
@@ -20,6 +20,7 @@ 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.createroom.test.FakeStartDMAction
import io.element.android.features.leaveroom.api.LeaveRoomEvent
import io.element.android.features.leaveroom.api.LeaveRoomPresenter
import io.element.android.features.leaveroom.fake.FakeLeaveRoomPresenter
@@ -45,11 +46,12 @@ import io.element.android.libraries.matrix.test.A_USER_ID_2
import io.element.android.libraries.matrix.test.FakeMatrixClient
import io.element.android.libraries.matrix.test.notificationsettings.FakeNotificationSettingsService
import io.element.android.libraries.matrix.test.room.FakeMatrixRoom
+import io.element.android.tests.testutils.WarmUpRule
import io.element.android.tests.testutils.consumeItemsUntilPredicate
import io.element.android.tests.testutils.testCoroutineDispatchers
-import io.element.android.tests.testutils.WarmUpRule
import kotlinx.collections.immutable.persistentListOf
import kotlinx.coroutines.ExperimentalCoroutinesApi
+import kotlinx.coroutines.test.TestScope
import kotlinx.coroutines.test.runTest
import org.junit.Rule
import org.junit.Test
@@ -61,16 +63,16 @@ class RoomDetailsPresenterTests {
@get:Rule
val warmUpRule = WarmUpRule()
- private fun createRoomDetailsPresenter(
+ private fun TestScope.createRoomDetailsPresenter(
room: MatrixRoom,
leaveRoomPresenter: LeaveRoomPresenter = FakeLeaveRoomPresenter(),
- dispatchers: CoroutineDispatchers,
+ dispatchers: CoroutineDispatchers = testCoroutineDispatchers(),
notificationSettingsService: FakeNotificationSettingsService = FakeNotificationSettingsService()
): RoomDetailsPresenter {
val matrixClient = FakeMatrixClient(notificationSettingsService = notificationSettingsService)
val roomMemberDetailsPresenterFactory = object : RoomMemberDetailsPresenter.Factory {
override fun create(roomMemberId: UserId): RoomMemberDetailsPresenter {
- return RoomMemberDetailsPresenter(matrixClient, room, roomMemberId)
+ return RoomMemberDetailsPresenter(roomMemberId, matrixClient, room, FakeStartDMAction())
}
}
val featureFlagService = FakeFeatureFlagService(
@@ -90,7 +92,7 @@ class RoomDetailsPresenterTests {
@Test
fun `present - initial state is created from room info`() = runTest {
val room = aMatrixRoom()
- val presenter = createRoomDetailsPresenter(room, dispatchers = testCoroutineDispatchers())
+ val presenter = createRoomDetailsPresenter(room)
moleculeFlow(RecompositionMode.Immediate) {
presenter.present()
}.test {
@@ -109,7 +111,7 @@ class RoomDetailsPresenterTests {
@Test
fun `present - initial state with no room name`() = runTest {
val room = aMatrixRoom(name = null)
- val presenter = createRoomDetailsPresenter(room, dispatchers = testCoroutineDispatchers())
+ val presenter = createRoomDetailsPresenter(room)
moleculeFlow(RecompositionMode.Immediate) {
presenter.present()
}.test {
@@ -131,7 +133,7 @@ class RoomDetailsPresenterTests {
val roomMembers = persistentListOf(myRoomMember, otherRoomMember)
givenRoomMembersState(MatrixRoomMembersState.Ready(roomMembers))
}
- val presenter = createRoomDetailsPresenter(room, dispatchers = testCoroutineDispatchers())
+ val presenter = createRoomDetailsPresenter(room)
moleculeFlow(RecompositionMode.Immediate) {
presenter.present()
}.test {
@@ -165,7 +167,7 @@ class RoomDetailsPresenterTests {
val room = aMatrixRoom().apply {
givenCanInviteResult(Result.success(false))
}
- val presenter = createRoomDetailsPresenter(room, dispatchers = testCoroutineDispatchers())
+ val presenter = createRoomDetailsPresenter(room)
moleculeFlow(RecompositionMode.Immediate) {
presenter.present()
}.test {
@@ -180,7 +182,7 @@ class RoomDetailsPresenterTests {
val room = aMatrixRoom().apply {
givenCanInviteResult(Result.failure(Throwable("Whoops")))
}
- val presenter = createRoomDetailsPresenter(room, dispatchers = testCoroutineDispatchers())
+ val presenter = createRoomDetailsPresenter(room)
moleculeFlow(RecompositionMode.Immediate) {
presenter.present()
}.test {
@@ -198,7 +200,7 @@ class RoomDetailsPresenterTests {
givenCanSendStateResult(StateEventType.ROOM_AVATAR, Result.failure(Throwable("Whelp")))
givenCanInviteResult(Result.success(false))
}
- val presenter = createRoomDetailsPresenter(room, dispatchers = testCoroutineDispatchers())
+ val presenter = createRoomDetailsPresenter(room)
moleculeFlow(RecompositionMode.Immediate) {
presenter.present()
}.test {
@@ -227,7 +229,7 @@ class RoomDetailsPresenterTests {
givenCanSendStateResult(StateEventType.ROOM_AVATAR, Result.success(true))
givenCanInviteResult(Result.success(false))
}
- val presenter = createRoomDetailsPresenter(room, dispatchers = testCoroutineDispatchers())
+ val presenter = createRoomDetailsPresenter(room)
moleculeFlow(RecompositionMode.Immediate) {
presenter.present()
}.test {
@@ -242,6 +244,7 @@ class RoomDetailsPresenterTests {
cancelAndIgnoreRemainingEvents()
}
}
+
@Test
fun `present - initial state when in a DM with no topic`() = runTest {
val myRoomMember = aRoomMember(A_SESSION_ID)
@@ -256,7 +259,7 @@ class RoomDetailsPresenterTests {
givenCanSendStateResult(StateEventType.ROOM_TOPIC, Result.success(true))
}
- val presenter = createRoomDetailsPresenter(room, dispatchers = testCoroutineDispatchers())
+ val presenter = createRoomDetailsPresenter(room)
moleculeFlow(RecompositionMode.Immediate) {
presenter.present()
}.test {
@@ -277,7 +280,7 @@ class RoomDetailsPresenterTests {
givenCanSendStateResult(StateEventType.ROOM_AVATAR, Result.success(true))
givenCanInviteResult(Result.success(false))
}
- val presenter = createRoomDetailsPresenter(room, dispatchers = testCoroutineDispatchers())
+ val presenter = createRoomDetailsPresenter(room)
moleculeFlow(RecompositionMode.Immediate) {
presenter.present()
}.test {
@@ -298,7 +301,7 @@ class RoomDetailsPresenterTests {
givenCanSendStateResult(StateEventType.ROOM_AVATAR, Result.success(false))
givenCanInviteResult(Result.success(false))
}
- val presenter = createRoomDetailsPresenter(room, dispatchers = testCoroutineDispatchers())
+ val presenter = createRoomDetailsPresenter(room)
moleculeFlow(RecompositionMode.Immediate) {
presenter.present()
}.test {
@@ -316,7 +319,7 @@ class RoomDetailsPresenterTests {
givenCanInviteResult(Result.success(false))
}
- val presenter = createRoomDetailsPresenter(room, dispatchers = testCoroutineDispatchers())
+ val presenter = createRoomDetailsPresenter(room)
moleculeFlow(RecompositionMode.Immediate) {
presenter.present()
}.test {
@@ -334,7 +337,7 @@ class RoomDetailsPresenterTests {
givenCanInviteResult(Result.success(false))
}
- val presenter = createRoomDetailsPresenter(room, dispatchers = testCoroutineDispatchers())
+ val presenter = createRoomDetailsPresenter(room)
moleculeFlow(RecompositionMode.Immediate) {
presenter.present()
}.test {
@@ -352,7 +355,11 @@ class RoomDetailsPresenterTests {
fun `present - leave room event is passed on to leave room presenter`() = runTest {
val leaveRoomPresenter = FakeLeaveRoomPresenter()
val room = aMatrixRoom()
- val presenter = createRoomDetailsPresenter(room, leaveRoomPresenter, testCoroutineDispatchers())
+ val presenter = createRoomDetailsPresenter(
+ room = room,
+ leaveRoomPresenter = leaveRoomPresenter,
+ dispatchers = testCoroutineDispatchers()
+ )
moleculeFlow(RecompositionMode.Immediate) {
presenter.present()
}.test {
@@ -369,14 +376,18 @@ class RoomDetailsPresenterTests {
val leaveRoomPresenter = FakeLeaveRoomPresenter()
val notificationSettingsService = FakeNotificationSettingsService()
val room = aMatrixRoom(notificationSettingsService = notificationSettingsService)
- val presenter = createRoomDetailsPresenter(room, leaveRoomPresenter, testCoroutineDispatchers(), notificationSettingsService)
+ val presenter = createRoomDetailsPresenter(
+ room = room,
+ leaveRoomPresenter = leaveRoomPresenter,
+ notificationSettingsService = notificationSettingsService,
+ )
moleculeFlow(RecompositionMode.Immediate) {
presenter.present()
}.test {
notificationSettingsService.setRoomNotificationMode(room.roomId, RoomNotificationMode.MENTIONS_AND_KEYWORDS_ONLY)
val updatedState = consumeItemsUntilPredicate {
- it.roomNotificationSettings?.mode == RoomNotificationMode.MENTIONS_AND_KEYWORDS_ONLY
+ it.roomNotificationSettings?.mode == RoomNotificationMode.MENTIONS_AND_KEYWORDS_ONLY
}.last()
assertThat(updatedState.roomNotificationSettings?.mode).isEqualTo(RoomNotificationMode.MENTIONS_AND_KEYWORDS_ONLY)
cancelAndIgnoreRemainingEvents()
@@ -385,16 +396,15 @@ class RoomDetailsPresenterTests {
@Test
fun `present - mute room notifications`() = runTest {
- val leaveRoomPresenter = FakeLeaveRoomPresenter()
val notificationSettingsService = FakeNotificationSettingsService(initialRoomMode = RoomNotificationMode.MENTIONS_AND_KEYWORDS_ONLY)
val room = aMatrixRoom(notificationSettingsService = notificationSettingsService)
- val presenter = createRoomDetailsPresenter(room, leaveRoomPresenter, testCoroutineDispatchers(), notificationSettingsService)
+ val presenter = createRoomDetailsPresenter(room = room, notificationSettingsService = notificationSettingsService)
moleculeFlow(RecompositionMode.Immediate) {
presenter.present()
}.test {
awaitItem().eventSink(RoomDetailsEvent.MuteNotification)
val updatedState = consumeItemsUntilPredicate(timeout = 250.milliseconds) {
- it.roomNotificationSettings?.mode == RoomNotificationMode.MUTE
+ it.roomNotificationSettings?.mode == RoomNotificationMode.MUTE
}.last()
assertThat(updatedState.roomNotificationSettings?.mode).isEqualTo(RoomNotificationMode.MUTE)
cancelAndIgnoreRemainingEvents()
@@ -403,19 +413,18 @@ class RoomDetailsPresenterTests {
@Test
fun `present - unmute room notifications`() = runTest {
- val leaveRoomPresenter = FakeLeaveRoomPresenter()
val notificationSettingsService = FakeNotificationSettingsService(
initialRoomMode = RoomNotificationMode.MENTIONS_AND_KEYWORDS_ONLY,
initialEncryptedGroupDefaultMode = RoomNotificationMode.ALL_MESSAGES
)
val room = aMatrixRoom(notificationSettingsService = notificationSettingsService)
- val presenter = createRoomDetailsPresenter(room, leaveRoomPresenter, testCoroutineDispatchers(), notificationSettingsService)
+ val presenter = createRoomDetailsPresenter(room = room, notificationSettingsService = notificationSettingsService)
moleculeFlow(RecompositionMode.Immediate) {
presenter.present()
}.test {
awaitItem().eventSink(RoomDetailsEvent.UnmuteNotification)
val updatedState = consumeItemsUntilPredicate {
- it.roomNotificationSettings?.mode == RoomNotificationMode.ALL_MESSAGES
+ it.roomNotificationSettings?.mode == RoomNotificationMode.ALL_MESSAGES
}.last()
assertThat(updatedState.roomNotificationSettings?.mode).isEqualTo(RoomNotificationMode.ALL_MESSAGES)
cancelAndIgnoreRemainingEvents()
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 eb89c40a24..2c1b399da8 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
@@ -107,7 +107,7 @@ class RoomDetailsEditPresenterTest {
AvatarAction.TakePhoto,
AvatarAction.Remove
)
- assertThat(initialState.saveButtonEnabled).isEqualTo(false)
+ assertThat(initialState.saveButtonEnabled).isFalse()
assertThat(initialState.saveAction).isInstanceOf(Async.Uninitialized::class.java)
}
}
@@ -299,42 +299,42 @@ class RoomDetailsEditPresenterTest {
presenter.present()
}.test {
val initialState = awaitItem()
- assertThat(initialState.saveButtonEnabled).isEqualTo(false)
+ assertThat(initialState.saveButtonEnabled).isFalse()
// Once a change is made, the save button is enabled
initialState.eventSink(RoomDetailsEditEvents.UpdateRoomName("Name II"))
awaitItem().apply {
- assertThat(saveButtonEnabled).isEqualTo(true)
+ assertThat(saveButtonEnabled).isTrue()
}
// If it's reverted then the save disables again
initialState.eventSink(RoomDetailsEditEvents.UpdateRoomName("Name"))
awaitItem().apply {
- assertThat(saveButtonEnabled).isEqualTo(false)
+ assertThat(saveButtonEnabled).isFalse()
}
// Make a change...
initialState.eventSink(RoomDetailsEditEvents.UpdateRoomTopic("Another topic"))
awaitItem().apply {
- assertThat(saveButtonEnabled).isEqualTo(true)
+ assertThat(saveButtonEnabled).isTrue()
}
// Revert it...
initialState.eventSink(RoomDetailsEditEvents.UpdateRoomTopic("My topic"))
awaitItem().apply {
- assertThat(saveButtonEnabled).isEqualTo(false)
+ assertThat(saveButtonEnabled).isFalse()
}
// Make a change...
initialState.eventSink(RoomDetailsEditEvents.HandleAvatarAction(AvatarAction.Remove))
awaitItem().apply {
- assertThat(saveButtonEnabled).isEqualTo(true)
+ assertThat(saveButtonEnabled).isTrue()
}
// Revert it...
initialState.eventSink(RoomDetailsEditEvents.HandleAvatarAction(AvatarAction.ChoosePhoto))
awaitItem().apply {
- assertThat(saveButtonEnabled).isEqualTo(false)
+ assertThat(saveButtonEnabled).isFalse()
}
}
}
@@ -351,42 +351,42 @@ class RoomDetailsEditPresenterTest {
presenter.present()
}.test {
val initialState = awaitItem()
- assertThat(initialState.saveButtonEnabled).isEqualTo(false)
+ assertThat(initialState.saveButtonEnabled).isFalse()
// Once a change is made, the save button is enabled
initialState.eventSink(RoomDetailsEditEvents.UpdateRoomName("Name II"))
awaitItem().apply {
- assertThat(saveButtonEnabled).isEqualTo(true)
+ assertThat(saveButtonEnabled).isTrue()
}
// If it's reverted then the save disables again
initialState.eventSink(RoomDetailsEditEvents.UpdateRoomName("fallback"))
awaitItem().apply {
- assertThat(saveButtonEnabled).isEqualTo(false)
+ assertThat(saveButtonEnabled).isFalse()
}
// Make a change...
initialState.eventSink(RoomDetailsEditEvents.UpdateRoomTopic("Another topic"))
awaitItem().apply {
- assertThat(saveButtonEnabled).isEqualTo(true)
+ assertThat(saveButtonEnabled).isTrue()
}
// Revert it...
initialState.eventSink(RoomDetailsEditEvents.UpdateRoomTopic(""))
awaitItem().apply {
- assertThat(saveButtonEnabled).isEqualTo(false)
+ assertThat(saveButtonEnabled).isFalse()
}
// Make a change...
initialState.eventSink(RoomDetailsEditEvents.HandleAvatarAction(AvatarAction.ChoosePhoto))
awaitItem().apply {
- assertThat(saveButtonEnabled).isEqualTo(true)
+ assertThat(saveButtonEnabled).isTrue()
}
// Revert it...
initialState.eventSink(RoomDetailsEditEvents.HandleAvatarAction(AvatarAction.Remove))
awaitItem().apply {
- assertThat(saveButtonEnabled).isEqualTo(false)
+ assertThat(saveButtonEnabled).isFalse()
}
}
}
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 c7e4c6d8b5..097919a5e1 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
@@ -19,7 +19,7 @@ package io.element.android.features.roomdetails.members
import app.cash.molecule.RecompositionMode
import app.cash.molecule.moleculeFlow
import app.cash.turbine.test
-import com.google.common.truth.Truth
+import com.google.common.truth.Truth.assertThat
import io.element.android.features.roomdetails.impl.members.RoomMemberListDataSource
import io.element.android.features.roomdetails.impl.members.RoomMemberListEvents
import io.element.android.features.roomdetails.impl.members.RoomMemberListPresenter
@@ -53,14 +53,14 @@ class RoomMemberListPresenterTests {
presenter.present()
}.test {
val initialState = awaitItem()
- Truth.assertThat(initialState.roomMembers).isInstanceOf(Async.Loading::class.java)
- Truth.assertThat(initialState.searchQuery).isEmpty()
- Truth.assertThat(initialState.searchResults).isInstanceOf(SearchBarResultState.NotSearching::class.java)
- Truth.assertThat(initialState.isSearchActive).isFalse()
+ assertThat(initialState.roomMembers).isInstanceOf(Async.Loading::class.java)
+ assertThat(initialState.searchQuery).isEmpty()
+ assertThat(initialState.searchResults).isInstanceOf(SearchBarResultState.NotSearching::class.java)
+ 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()))
- Truth.assertThat((loadedState.roomMembers as Async.Success).data.joined).isNotEmpty()
+ assertThat(loadedState.roomMembers).isInstanceOf(Async.Success::class.java)
+ assertThat((loadedState.roomMembers as Async.Success).data.invited).isEqualTo(listOf(aVictor(), aWalter()))
+ assertThat((loadedState.roomMembers as Async.Success).data.joined).isNotEmpty()
}
}
@@ -74,7 +74,7 @@ class RoomMemberListPresenterTests {
val loadedState = awaitItem()
loadedState.eventSink(RoomMemberListEvents.OnSearchActiveChanged(true))
val searchActiveState = awaitItem()
- Truth.assertThat(searchActiveState.isSearchActive).isTrue()
+ assertThat(searchActiveState.isSearchActive).isTrue()
}
}
@@ -90,9 +90,9 @@ class RoomMemberListPresenterTests {
val searchActiveState = awaitItem()
searchActiveState.eventSink(RoomMemberListEvents.UpdateSearchQuery("something"))
val searchQueryUpdatedState = awaitItem()
- Truth.assertThat(searchQueryUpdatedState.searchQuery).isEqualTo("something")
+ assertThat(searchQueryUpdatedState.searchQuery).isEqualTo("something")
val searchSearchResultDelivered = awaitItem()
- Truth.assertThat(searchSearchResultDelivered.searchResults).isInstanceOf(SearchBarResultState.NoResults::class.java)
+ assertThat(searchSearchResultDelivered.searchResults).isInstanceOf(SearchBarResultState.NoResults::class.java)
}
}
@@ -108,10 +108,10 @@ class RoomMemberListPresenterTests {
val searchActiveState = awaitItem()
searchActiveState.eventSink(RoomMemberListEvents.UpdateSearchQuery("Alice"))
val searchQueryUpdatedState = awaitItem()
- Truth.assertThat(searchQueryUpdatedState.searchQuery).isEqualTo("Alice")
+ assertThat(searchQueryUpdatedState.searchQuery).isEqualTo("Alice")
val searchSearchResultDelivered = awaitItem()
- Truth.assertThat(searchSearchResultDelivered.searchResults).isInstanceOf(SearchBarResultState.Results::class.java)
- Truth.assertThat((searchSearchResultDelivered.searchResults as SearchBarResultState.Results).results.joined.first().displayName)
+ assertThat(searchSearchResultDelivered.searchResults).isInstanceOf(SearchBarResultState.Results::class.java)
+ assertThat((searchSearchResultDelivered.searchResults as SearchBarResultState.Results).results.joined.first().displayName)
.isEqualTo("Alice")
}
}
@@ -128,7 +128,7 @@ class RoomMemberListPresenterTests {
}.test {
skipItems(1)
val loadedState = awaitItem()
- Truth.assertThat(loadedState.canInvite).isTrue()
+ assertThat(loadedState.canInvite).isTrue()
}
}
@@ -144,7 +144,7 @@ class RoomMemberListPresenterTests {
}.test {
skipItems(1)
val loadedState = awaitItem()
- Truth.assertThat(loadedState.canInvite).isFalse()
+ assertThat(loadedState.canInvite).isFalse()
}
}
@@ -160,7 +160,7 @@ class RoomMemberListPresenterTests {
}.test {
skipItems(1)
val loadedState = awaitItem()
- Truth.assertThat(loadedState.canInvite).isFalse()
+ assertThat(loadedState.canInvite).isFalse()
}
}
}
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 0921efe0ca..ac429e262d 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
@@ -19,14 +19,21 @@ package io.element.android.features.roomdetails.members.details
import app.cash.molecule.RecompositionMode
import app.cash.molecule.moleculeFlow
import app.cash.turbine.test
-import com.google.common.truth.Truth
+import com.google.common.truth.Truth.assertThat
+import io.element.android.features.createroom.api.StartDMAction
+import io.element.android.features.createroom.test.FakeStartDMAction
import io.element.android.features.roomdetails.aMatrixRoom
import io.element.android.features.roomdetails.impl.members.aRoomMember
import io.element.android.features.roomdetails.impl.members.details.RoomMemberDetailsEvents
import io.element.android.features.roomdetails.impl.members.details.RoomMemberDetailsPresenter
import io.element.android.features.roomdetails.impl.members.details.RoomMemberDetailsState
import io.element.android.libraries.architecture.Async
+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.MatrixRoom
import io.element.android.libraries.matrix.api.room.MatrixRoomMembersState
+import io.element.android.libraries.matrix.api.room.RoomMember
+import io.element.android.libraries.matrix.test.A_ROOM_ID
import io.element.android.libraries.matrix.test.A_THROWABLE
import io.element.android.libraries.matrix.test.FakeMatrixClient
import io.element.android.tests.testutils.WarmUpRule
@@ -50,19 +57,22 @@ class RoomMemberDetailsPresenterTests {
givenUserAvatarUrlResult(Result.success("A custom avatar"))
givenRoomMembersState(MatrixRoomMembersState.Ready(persistentListOf(roomMember)))
}
- val presenter = RoomMemberDetailsPresenter(FakeMatrixClient(), room, roomMember.userId)
+ val presenter = createRoomMemberDetailsPresenter(
+ room = room,
+ roomMember = roomMember
+ )
moleculeFlow(RecompositionMode.Immediate) {
presenter.present()
}.test {
val initialState = awaitItem()
- Truth.assertThat(initialState.userId).isEqualTo(roomMember.userId.value)
- Truth.assertThat(initialState.userName).isEqualTo(roomMember.displayName)
- Truth.assertThat(initialState.avatarUrl).isEqualTo(roomMember.avatarUrl)
- Truth.assertThat(initialState.isBlocked).isEqualTo(Async.Success(roomMember.isIgnored))
+ assertThat(initialState.userId).isEqualTo(roomMember.userId.value)
+ assertThat(initialState.userName).isEqualTo(roomMember.displayName)
+ assertThat(initialState.avatarUrl).isEqualTo(roomMember.avatarUrl)
+ assertThat(initialState.isBlocked).isEqualTo(Async.Success(roomMember.isIgnored))
skipItems(1)
val loadedState = awaitItem()
- Truth.assertThat(loadedState.userName).isEqualTo("A custom name")
- Truth.assertThat(loadedState.avatarUrl).isEqualTo("A custom avatar")
+ assertThat(loadedState.userName).isEqualTo("A custom name")
+ assertThat(loadedState.avatarUrl).isEqualTo("A custom avatar")
}
}
@@ -74,13 +84,16 @@ class RoomMemberDetailsPresenterTests {
givenUserAvatarUrlResult(Result.failure(Throwable()))
givenRoomMembersState(MatrixRoomMembersState.Ready(persistentListOf(roomMember)))
}
- val presenter = RoomMemberDetailsPresenter(FakeMatrixClient(), room, roomMember.userId)
+ val presenter = createRoomMemberDetailsPresenter(
+ room = room,
+ roomMember = roomMember
+ )
moleculeFlow(RecompositionMode.Immediate) {
presenter.present()
}.test {
val initialState = awaitItem()
- Truth.assertThat(initialState.userName).isEqualTo(roomMember.displayName)
- Truth.assertThat(initialState.avatarUrl).isEqualTo(roomMember.avatarUrl)
+ assertThat(initialState.userName).isEqualTo(roomMember.displayName)
+ assertThat(initialState.avatarUrl).isEqualTo(roomMember.avatarUrl)
ensureAllEventsConsumed()
}
@@ -94,13 +107,16 @@ class RoomMemberDetailsPresenterTests {
givenUserAvatarUrlResult(Result.success(null))
givenRoomMembersState(MatrixRoomMembersState.Ready(persistentListOf(roomMember)))
}
- val presenter = RoomMemberDetailsPresenter(FakeMatrixClient(), room, roomMember.userId)
+ val presenter = createRoomMemberDetailsPresenter(
+ room = room,
+ roomMember = roomMember
+ )
moleculeFlow(RecompositionMode.Immediate) {
presenter.present()
}.test {
val initialState = awaitItem()
- Truth.assertThat(initialState.userName).isEqualTo(roomMember.displayName)
- Truth.assertThat(initialState.avatarUrl).isEqualTo(roomMember.avatarUrl)
+ assertThat(initialState.userName).isEqualTo(roomMember.displayName)
+ assertThat(initialState.avatarUrl).isEqualTo(roomMember.avatarUrl)
ensureAllEventsConsumed()
}
@@ -108,9 +124,7 @@ class RoomMemberDetailsPresenterTests {
@Test
fun `present - BlockUser needing confirmation displays confirmation dialog`() = runTest {
- val room = aMatrixRoom()
- val roomMember = aRoomMember()
- val presenter = RoomMemberDetailsPresenter(FakeMatrixClient(), room, roomMember.userId)
+ val presenter = createRoomMemberDetailsPresenter()
moleculeFlow(RecompositionMode.Immediate) {
presenter.present()
}.test {
@@ -118,10 +132,10 @@ class RoomMemberDetailsPresenterTests {
initialState.eventSink(RoomMemberDetailsEvents.BlockUser(needsConfirmation = true))
val dialogState = awaitItem()
- Truth.assertThat(dialogState.displayConfirmationDialog).isEqualTo(RoomMemberDetailsState.ConfirmationDialog.Block)
+ assertThat(dialogState.displayConfirmationDialog).isEqualTo(RoomMemberDetailsState.ConfirmationDialog.Block)
dialogState.eventSink(RoomMemberDetailsEvents.ClearConfirmationDialog)
- Truth.assertThat(awaitItem().displayConfirmationDialog).isNull()
+ assertThat(awaitItem().displayConfirmationDialog).isNull()
ensureAllEventsConsumed()
}
@@ -129,49 +143,43 @@ class RoomMemberDetailsPresenterTests {
@Test
fun `present - BlockUser and UnblockUser without confirmation change the 'blocked' state`() = runTest {
- val room = aMatrixRoom()
- val roomMember = aRoomMember()
- val presenter = RoomMemberDetailsPresenter(FakeMatrixClient(), room, roomMember.userId)
+ val presenter = createRoomMemberDetailsPresenter()
moleculeFlow(RecompositionMode.Immediate) {
presenter.present()
}.test {
val initialState = awaitItem()
initialState.eventSink(RoomMemberDetailsEvents.BlockUser(needsConfirmation = false))
- Truth.assertThat(awaitItem().isBlocked.isLoading()).isTrue()
- Truth.assertThat(awaitItem().isBlocked.dataOrNull()).isTrue()
+ assertThat(awaitItem().isBlocked.isLoading()).isTrue()
+ assertThat(awaitItem().isBlocked.dataOrNull()).isTrue()
initialState.eventSink(RoomMemberDetailsEvents.UnblockUser(needsConfirmation = false))
- Truth.assertThat(awaitItem().isBlocked.isLoading()).isTrue()
- Truth.assertThat(awaitItem().isBlocked.dataOrNull()).isFalse()
+ assertThat(awaitItem().isBlocked.isLoading()).isTrue()
+ assertThat(awaitItem().isBlocked.dataOrNull()).isFalse()
}
}
@Test
fun `present - BlockUser with error`() = runTest {
- val room = aMatrixRoom()
- val roomMember = aRoomMember()
val matrixClient = FakeMatrixClient()
matrixClient.givenIgnoreUserResult(Result.failure(A_THROWABLE))
- val presenter = RoomMemberDetailsPresenter(matrixClient, room, roomMember.userId)
+ val presenter = createRoomMemberDetailsPresenter(client = matrixClient)
moleculeFlow(RecompositionMode.Immediate) {
presenter.present()
}.test {
val initialState = awaitItem()
initialState.eventSink(RoomMemberDetailsEvents.BlockUser(needsConfirmation = false))
- Truth.assertThat(awaitItem().isBlocked.isLoading()).isTrue()
+ assertThat(awaitItem().isBlocked.isLoading()).isTrue()
val errorState = awaitItem()
- Truth.assertThat(errorState.isBlocked.errorOrNull()).isEqualTo(A_THROWABLE)
+ assertThat(errorState.isBlocked.errorOrNull()).isEqualTo(A_THROWABLE)
// Clear error
initialState.eventSink(RoomMemberDetailsEvents.ClearBlockUserError)
- Truth.assertThat(awaitItem().isBlocked).isEqualTo(Async.Success(false))
+ assertThat(awaitItem().isBlocked).isEqualTo(Async.Success(false))
}
}
@Test
fun `present - UnblockUser needing confirmation displays confirmation dialog`() = runTest {
- val room = aMatrixRoom()
- val roomMember = aRoomMember()
- val presenter = RoomMemberDetailsPresenter(FakeMatrixClient(), room, roomMember.userId)
+ val presenter = createRoomMemberDetailsPresenter()
moleculeFlow(RecompositionMode.Immediate) {
presenter.present()
}.test {
@@ -179,12 +187,60 @@ class RoomMemberDetailsPresenterTests {
initialState.eventSink(RoomMemberDetailsEvents.UnblockUser(needsConfirmation = true))
val dialogState = awaitItem()
- Truth.assertThat(dialogState.displayConfirmationDialog).isEqualTo(RoomMemberDetailsState.ConfirmationDialog.Unblock)
+ assertThat(dialogState.displayConfirmationDialog).isEqualTo(RoomMemberDetailsState.ConfirmationDialog.Unblock)
dialogState.eventSink(RoomMemberDetailsEvents.ClearConfirmationDialog)
- Truth.assertThat(awaitItem().displayConfirmationDialog).isNull()
+ assertThat(awaitItem().displayConfirmationDialog).isNull()
ensureAllEventsConsumed()
}
}
+
+ @Test
+ fun `present - start DM action complete scenario`() = runTest {
+ val startDMAction = FakeStartDMAction()
+ val presenter = createRoomMemberDetailsPresenter(startDMAction = startDMAction)
+ moleculeFlow(RecompositionMode.Immediate) {
+ presenter.present()
+ }.test {
+ val initialState = awaitItem()
+ assertThat(initialState.startDmActionState).isInstanceOf(Async.Uninitialized::class.java)
+ val startDMSuccessResult = Async.Success(A_ROOM_ID)
+ val startDMFailureResult = Async.Failure(A_THROWABLE)
+
+ // Failure
+ startDMAction.givenExecuteResult(startDMFailureResult)
+ initialState.eventSink(RoomMemberDetailsEvents.StartDM)
+ assertThat(awaitItem().startDmActionState).isInstanceOf(Async.Loading::class.java)
+ awaitItem().also { state ->
+ assertThat(state.startDmActionState).isEqualTo(startDMFailureResult)
+ state.eventSink(RoomMemberDetailsEvents.ClearStartDMState)
+ }
+
+ // Success
+ startDMAction.givenExecuteResult(startDMSuccessResult)
+ awaitItem().also { state ->
+ assertThat(state.startDmActionState).isEqualTo(Async.Uninitialized)
+ state.eventSink(RoomMemberDetailsEvents.StartDM)
+ }
+ assertThat(awaitItem().startDmActionState).isInstanceOf(Async.Loading::class.java)
+ awaitItem().also { state ->
+ assertThat(state.startDmActionState).isEqualTo(startDMSuccessResult)
+ }
+ }
+ }
+
+ private fun createRoomMemberDetailsPresenter(
+ client: MatrixClient = FakeMatrixClient(),
+ room: MatrixRoom = aMatrixRoom(),
+ roomMember: RoomMember = aRoomMember(),
+ startDMAction: StartDMAction = FakeStartDMAction()
+ ): RoomMemberDetailsPresenter {
+ return RoomMemberDetailsPresenter(
+ roomMemberId = roomMember.userId,
+ client = client,
+ room = room,
+ startDMAction = startDMAction
+ )
+ }
}
diff --git a/features/roomdetails/impl/src/test/kotlin/io/element/android/features/roomdetails/notificationsettings/RoomNotificationSettingsPresenterTests.kt b/features/roomdetails/impl/src/test/kotlin/io/element/android/features/roomdetails/notificationsettings/RoomNotificationSettingsPresenterTests.kt
index c4134462f7..efd8ba3731 100644
--- a/features/roomdetails/impl/src/test/kotlin/io/element/android/features/roomdetails/notificationsettings/RoomNotificationSettingsPresenterTests.kt
+++ b/features/roomdetails/impl/src/test/kotlin/io/element/android/features/roomdetails/notificationsettings/RoomNotificationSettingsPresenterTests.kt
@@ -19,7 +19,7 @@ package io.element.android.features.roomdetails.notificationsettings
import app.cash.molecule.RecompositionMode
import app.cash.molecule.moleculeFlow
import app.cash.turbine.test
-import com.google.common.truth.Truth
+import com.google.common.truth.Truth.assertThat
import io.element.android.features.roomdetails.aMatrixRoom
import io.element.android.features.roomdetails.impl.notificationsettings.RoomNotificationSettingsEvents
import io.element.android.features.roomdetails.impl.notificationsettings.RoomNotificationSettingsPresenter
@@ -39,8 +39,8 @@ class RoomNotificationSettingsPresenterTests {
presenter.present()
}.test {
val initialState = awaitItem()
- Truth.assertThat(initialState.roomNotificationSettings.dataOrNull()).isNull()
- Truth.assertThat(initialState.defaultRoomNotificationMode).isNull()
+ assertThat(initialState.roomNotificationSettings.dataOrNull()).isNull()
+ assertThat(initialState.defaultRoomNotificationMode).isNull()
cancelAndIgnoreRemainingEvents()
}
}
@@ -55,7 +55,7 @@ class RoomNotificationSettingsPresenterTests {
val updatedState = consumeItemsUntilPredicate {
it.roomNotificationSettings.dataOrNull()?.mode == RoomNotificationMode.MENTIONS_AND_KEYWORDS_ONLY
}.last()
- Truth.assertThat(updatedState.roomNotificationSettings.dataOrNull()?.mode).isEqualTo(RoomNotificationMode.MENTIONS_AND_KEYWORDS_ONLY)
+ assertThat(updatedState.roomNotificationSettings.dataOrNull()?.mode).isEqualTo(RoomNotificationMode.MENTIONS_AND_KEYWORDS_ONLY)
cancelAndIgnoreRemainingEvents()
}
}
@@ -71,7 +71,7 @@ class RoomNotificationSettingsPresenterTests {
val updatedState = consumeItemsUntilPredicate {
it.roomNotificationSettings.dataOrNull()?.mode == RoomNotificationMode.MENTIONS_AND_KEYWORDS_ONLY
}.last()
- Truth.assertThat(updatedState.roomNotificationSettings.dataOrNull()?.mode).isEqualTo(RoomNotificationMode.MENTIONS_AND_KEYWORDS_ONLY)
+ assertThat(updatedState.roomNotificationSettings.dataOrNull()?.mode).isEqualTo(RoomNotificationMode.MENTIONS_AND_KEYWORDS_ONLY)
}
}
@@ -89,16 +89,16 @@ class RoomNotificationSettingsPresenterTests {
it.setNotificationSettingAction.isFailure()
}.last()
- Truth.assertThat(failedState.roomNotificationSettings.dataOrNull()?.isDefault).isTrue()
- Truth.assertThat(failedState.pendingSetDefault).isNull()
- Truth.assertThat(failedState.setNotificationSettingAction.isFailure()).isTrue()
+ assertThat(failedState.roomNotificationSettings.dataOrNull()?.isDefault).isTrue()
+ assertThat(failedState.pendingSetDefault).isNull()
+ assertThat(failedState.setNotificationSettingAction.isFailure()).isTrue()
failedState.eventSink(RoomNotificationSettingsEvents.ClearSetNotificationError)
val errorClearedState = consumeItemsUntilPredicate {
it.setNotificationSettingAction.isUninitialized()
}.last()
- Truth.assertThat(errorClearedState.setNotificationSettingAction.isUninitialized()).isTrue()
+ assertThat(errorClearedState.setNotificationSettingAction.isUninitialized()).isTrue()
}
}
@@ -114,7 +114,7 @@ class RoomNotificationSettingsPresenterTests {
val defaultState = consumeItemsUntilPredicate {
it.roomNotificationSettings.dataOrNull()?.isDefault == false
}.last()
- Truth.assertThat(defaultState.roomNotificationSettings.dataOrNull()?.isDefault).isFalse()
+ assertThat(defaultState.roomNotificationSettings.dataOrNull()?.isDefault).isFalse()
}
}
@@ -130,7 +130,7 @@ class RoomNotificationSettingsPresenterTests {
val defaultState = consumeItemsUntilPredicate {
it.roomNotificationSettings.dataOrNull()?.mode == RoomNotificationMode.MENTIONS_AND_KEYWORDS_ONLY
}.last()
- Truth.assertThat(defaultState.roomNotificationSettings.dataOrNull()?.mode).isEqualTo(RoomNotificationMode.MENTIONS_AND_KEYWORDS_ONLY)
+ assertThat(defaultState.roomNotificationSettings.dataOrNull()?.mode).isEqualTo(RoomNotificationMode.MENTIONS_AND_KEYWORDS_ONLY)
cancelAndIgnoreRemainingEvents()
}
}
@@ -149,13 +149,13 @@ class RoomNotificationSettingsPresenterTests {
val failedState = consumeItemsUntilPredicate {
it.restoreDefaultAction.isFailure()
}.last()
- Truth.assertThat(failedState.restoreDefaultAction.isFailure()).isTrue()
+ assertThat(failedState.restoreDefaultAction.isFailure()).isTrue()
failedState.eventSink(RoomNotificationSettingsEvents.ClearRestoreDefaultError)
val errorClearedState = consumeItemsUntilPredicate {
it.restoreDefaultAction.isUninitialized()
}.last()
- Truth.assertThat(errorClearedState.restoreDefaultAction.isUninitialized()).isTrue()
+ assertThat(errorClearedState.restoreDefaultAction.isUninitialized()).isTrue()
cancelAndIgnoreRemainingEvents()
}
}
diff --git a/features/roomlist/impl/src/main/res/values-de/translations.xml b/features/roomlist/impl/src/main/res/values-de/translations.xml
index 3e511f67bd..3daa701b8d 100644
--- a/features/roomlist/impl/src/main/res/values-de/translations.xml
+++ b/features/roomlist/impl/src/main/res/values-de/translations.xml
@@ -1,5 +1,6 @@
+ "Dein Chat-Backup ist derzeit nicht synchronisiert. Du musst deinen Wiederherstellungsschlüssel bestätigen, um Zugriff auf dein Chat-Backup zu erhalten."
"Eine neue Unterhaltung oder einen neuen Raum erstellen"
"Beginne, indem du jemandem eine Nachricht sendest."
"Noch keine Chats."
diff --git a/features/roomlist/impl/src/main/res/values-hu/translations.xml b/features/roomlist/impl/src/main/res/values-hu/translations.xml
new file mode 100644
index 0000000000..cd5dced50a
--- /dev/null
+++ b/features/roomlist/impl/src/main/res/values-hu/translations.xml
@@ -0,0 +1,11 @@
+
+
+ "A csevegés biztonsági mentés nincs szinkronban. Meg kell erősítenie a helyreállítási kulcsát, hogy továbbra is hozzáférjen a csevegés biztonsági mentéséhez."
+ "Helyreállítási kulcs megerősítése"
+ "Új beszélgetés vagy szoba létrehozása"
+ "Kezdje azzal, hogy üzenetet küld valakinek."
+ "Még nincsenek csevegések."
+ "Összes csevegés"
+ "Úgy tűnik, hogy új eszközt használ. Ellenőrizze egy másik eszközzel, hogy a továbbiakban elérje a titkosított üzeneteket."
+ "Ellenőrizze, hogy Ön az"
+
diff --git a/features/roomlist/impl/src/main/res/values-in/translations.xml b/features/roomlist/impl/src/main/res/values-in/translations.xml
new file mode 100644
index 0000000000..58994e4772
--- /dev/null
+++ b/features/roomlist/impl/src/main/res/values-in/translations.xml
@@ -0,0 +1,11 @@
+
+
+ "Cadangan percakapan Anda saat ini tidak tersinkron. Anda perlu mengonfirmasi kunci pemulihan Anda untuk tetap memiliki akses ke cadangan percakapan Anda."
+ "Konfirmasi kunci pemulihan Anda"
+ "Buat percakapan atau ruangan baru"
+ "Mulailah dengan mengirim pesan kepada seseorang."
+ "Belum ada obrolan."
+ "Semua Obrolan"
+ "Sepertinya Anda menggunakan perangkat baru. Verifikasi dengan perangkat lain untuk mengakses pesan terenkripsi Anda selanjutnya."
+ "Verifikasi bahwa ini Anda"
+
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 2ac418e098..bf7c085ac7 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
@@ -19,7 +19,7 @@ package io.element.android.features.roomlist.impl
import app.cash.molecule.RecompositionMode
import app.cash.molecule.moleculeFlow
import app.cash.turbine.test
-import com.google.common.truth.Truth
+import com.google.common.truth.Truth.assertThat
import io.element.android.features.leaveroom.api.LeaveRoomEvent
import io.element.android.features.leaveroom.api.LeaveRoomPresenter
import io.element.android.features.leaveroom.fake.FakeLeaveRoomPresenter
@@ -83,13 +83,13 @@ class RoomListPresenterTests {
presenter.present()
}.test {
val initialState = awaitItem()
- Truth.assertThat(initialState.matrixUser).isNull()
+ assertThat(initialState.matrixUser).isNull()
val withUserState = awaitItem()
- Truth.assertThat(withUserState.matrixUser).isNotNull()
- Truth.assertThat(withUserState.matrixUser!!.userId).isEqualTo(A_USER_ID)
- Truth.assertThat(withUserState.matrixUser!!.displayName).isEqualTo(A_USER_NAME)
- Truth.assertThat(withUserState.matrixUser!!.avatarUrl).isEqualTo(AN_AVATAR_URL)
- Truth.assertThat(withUserState.showAvatarIndicator).isFalse()
+ assertThat(withUserState.matrixUser).isNotNull()
+ assertThat(withUserState.matrixUser!!.userId).isEqualTo(A_USER_ID)
+ assertThat(withUserState.matrixUser!!.displayName).isEqualTo(A_USER_NAME)
+ assertThat(withUserState.matrixUser!!.avatarUrl).isEqualTo(AN_AVATAR_URL)
+ assertThat(withUserState.showAvatarIndicator).isFalse()
scope.cancel()
}
}
@@ -109,12 +109,12 @@ class RoomListPresenterTests {
}.test {
skipItems(1)
val initialState = awaitItem()
- Truth.assertThat(initialState.showAvatarIndicator).isFalse()
+ assertThat(initialState.showAvatarIndicator).isFalse()
sessionVerificationService.givenCanVerifySession(false)
- Truth.assertThat(awaitItem().showAvatarIndicator).isFalse()
+ assertThat(awaitItem().showAvatarIndicator).isFalse()
encryptionService.emitBackupState(BackupState.UNKNOWN)
val finalState = awaitItem()
- Truth.assertThat(finalState.showAvatarIndicator).isTrue()
+ assertThat(finalState.showAvatarIndicator).isTrue()
scope.cancel()
}
}
@@ -131,9 +131,9 @@ class RoomListPresenterTests {
presenter.present()
}.test {
val initialState = awaitItem()
- Truth.assertThat(initialState.matrixUser).isNull()
+ assertThat(initialState.matrixUser).isNull()
val withUserState = awaitItem()
- Truth.assertThat(withUserState.matrixUser).isNotNull()
+ assertThat(withUserState.matrixUser).isNotNull()
scope.cancel()
}
}
@@ -147,10 +147,10 @@ class RoomListPresenterTests {
}.test {
skipItems(1)
val withUserState = awaitItem()
- Truth.assertThat(withUserState.filter).isEqualTo("")
+ assertThat(withUserState.filter).isEqualTo("")
withUserState.eventSink.invoke(RoomListEvents.UpdateFilter("t"))
val withFilterState = awaitItem()
- Truth.assertThat(withFilterState.filter).isEqualTo("t")
+ assertThat(withFilterState.filter).isEqualTo("t")
cancelAndIgnoreRemainingEvents()
scope.cancel()
}
@@ -169,12 +169,12 @@ class RoomListPresenterTests {
}.test {
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()
+ assertThat(initialState.roomList.size).isEqualTo(16)
+ assertThat(initialState.roomList.all { it.isPlaceholder }).isTrue()
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())
+ assertThat(withRoomState.roomList.size).isEqualTo(1)
+ assertThat(withRoomState.roomList.first())
.isEqualTo(aRoomListRoomSummary)
scope.cancel()
}
@@ -196,15 +196,15 @@ class RoomListPresenterTests {
// Test filtering with result
loadedState.eventSink.invoke(RoomListEvents.UpdateFilter(A_ROOM_NAME.substring(0, 3)))
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())
+ assertThat(withFilteredRoomState.filter).isEqualTo(A_ROOM_NAME.substring(0, 3))
+ assertThat(withFilteredRoomState.filteredRoomList.size).isEqualTo(1)
+ assertThat(withFilteredRoomState.filteredRoomList.first())
.isEqualTo(aRoomListRoomSummary)
// Test filtering without result
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()
+ assertThat(withNotFilteredRoomState.filter).isEqualTo("tada")
+ assertThat(withNotFilteredRoomState.filteredRoomList).isEmpty()
scope.cancel()
}
}
@@ -223,28 +223,28 @@ class RoomListPresenterTests {
roomListService.postAllRooms(listOf(aRoomSummaryFilled()))
val loadedState = awaitItem()
// check initial value
- Truth.assertThat(roomListService.latestSlidingSyncRange).isNull()
+ assertThat(roomListService.latestSlidingSyncRange).isNull()
// Test empty range
loadedState.eventSink.invoke(RoomListEvents.UpdateVisibleRange(IntRange(1, 0)))
- Truth.assertThat(roomListService.latestSlidingSyncRange).isNull()
+ 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(roomListService.latestSlidingSyncRange)
+ assertThat(roomListService.latestSlidingSyncRange)
.isEqualTo(IntRange(0, 20))
loadedState.eventSink.invoke(RoomListEvents.UpdateVisibleRange(IntRange(0, 1)))
- Truth.assertThat(roomListService.latestSlidingSyncRange)
+ assertThat(roomListService.latestSlidingSyncRange)
.isEqualTo(IntRange(0, 21))
loadedState.eventSink.invoke(RoomListEvents.UpdateVisibleRange(IntRange(19, 29)))
- Truth.assertThat(roomListService.latestSlidingSyncRange)
+ assertThat(roomListService.latestSlidingSyncRange)
.isEqualTo(IntRange(0, 49))
loadedState.eventSink.invoke(RoomListEvents.UpdateVisibleRange(IntRange(49, 59)))
- Truth.assertThat(roomListService.latestSlidingSyncRange)
+ assertThat(roomListService.latestSlidingSyncRange)
.isEqualTo(IntRange(29, 79))
loadedState.eventSink.invoke(RoomListEvents.UpdateVisibleRange(IntRange(149, 159)))
- Truth.assertThat(roomListService.latestSlidingSyncRange)
+ assertThat(roomListService.latestSlidingSyncRange)
.isEqualTo(IntRange(129, 179))
loadedState.eventSink.invoke(RoomListEvents.UpdateVisibleRange(IntRange(149, 259)))
- Truth.assertThat(roomListService.latestSlidingSyncRange)
+ assertThat(roomListService.latestSlidingSyncRange)
.isEqualTo(IntRange(129, 279))
cancelAndIgnoreRemainingEvents()
scope.cancel()
@@ -270,10 +270,10 @@ class RoomListPresenterTests {
presenter.present()
}.test {
val eventSink = awaitItem().eventSink
- Truth.assertThat(awaitItem().displayVerificationPrompt).isTrue()
+ assertThat(awaitItem().displayVerificationPrompt).isTrue()
eventSink(RoomListEvents.DismissRequestVerificationPrompt)
- Truth.assertThat(awaitItem().displayVerificationPrompt).isFalse()
+ assertThat(awaitItem().displayVerificationPrompt).isFalse()
scope.cancel()
}
}
@@ -288,16 +288,16 @@ class RoomListPresenterTests {
presenter.present()
}.test {
skipItems(1)
- Truth.assertThat(awaitItem().invitesState).isEqualTo(InvitesState.NoInvites)
+ assertThat(awaitItem().invitesState).isEqualTo(InvitesState.NoInvites)
inviteStateFlow.value = InvitesState.SeenInvites
- Truth.assertThat(awaitItem().invitesState).isEqualTo(InvitesState.SeenInvites)
+ assertThat(awaitItem().invitesState).isEqualTo(InvitesState.SeenInvites)
inviteStateFlow.value = InvitesState.NewInvites
- Truth.assertThat(awaitItem().invitesState).isEqualTo(InvitesState.NewInvites)
+ assertThat(awaitItem().invitesState).isEqualTo(InvitesState.NewInvites)
inviteStateFlow.value = InvitesState.NoInvites
- Truth.assertThat(awaitItem().invitesState).isEqualTo(InvitesState.NoInvites)
+ assertThat(awaitItem().invitesState).isEqualTo(InvitesState.NoInvites)
scope.cancel()
}
}
@@ -316,7 +316,7 @@ class RoomListPresenterTests {
initialState.eventSink(RoomListEvents.ShowContextMenu(summary))
val shownState = awaitItem()
- Truth.assertThat(shownState.contextMenu)
+ assertThat(shownState.contextMenu)
.isEqualTo(RoomListState.ContextMenu.Shown(summary.roomId, summary.name))
scope.cancel()
}
@@ -336,12 +336,12 @@ class RoomListPresenterTests {
initialState.eventSink(RoomListEvents.ShowContextMenu(summary))
val shownState = awaitItem()
- Truth.assertThat(shownState.contextMenu)
+ assertThat(shownState.contextMenu)
.isEqualTo(RoomListState.ContextMenu.Shown(summary.roomId, summary.name))
shownState.eventSink(RoomListEvents.HideContextMenu)
val hiddenState = awaitItem()
- Truth.assertThat(hiddenState.contextMenu).isEqualTo(RoomListState.ContextMenu.Hidden)
+ assertThat(hiddenState.contextMenu).isEqualTo(RoomListState.ContextMenu.Hidden)
scope.cancel()
}
}
@@ -356,7 +356,7 @@ class RoomListPresenterTests {
}.test {
val initialState = awaitItem()
initialState.eventSink(RoomListEvents.LeaveRoom(A_ROOM_ID))
- Truth.assertThat(leaveRoomPresenter.events).containsExactly(LeaveRoomEvent.ShowConfirmation(A_ROOM_ID))
+ assertThat(leaveRoomPresenter.events).containsExactly(LeaveRoomEvent.ShowConfirmation(A_ROOM_ID))
cancelAndIgnoreRemainingEvents()
scope.cancel()
}
@@ -384,7 +384,7 @@ class RoomListPresenterTests {
}.last()
val room = updatedState.roomList.find { it.id == A_ROOM_ID.value }
- Truth.assertThat(room?.notificationMode).isEqualTo(userDefinedMode)
+ assertThat(room?.notificationMode).isEqualTo(userDefinedMode)
cancelAndIgnoreRemainingEvents()
scope.cancel()
}
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 ce7bf685a8..fc41e48b53 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
@@ -19,7 +19,7 @@ package io.element.android.features.roomlist.impl.datasource
import app.cash.molecule.RecompositionMode
import app.cash.molecule.moleculeFlow
import app.cash.turbine.test
-import com.google.common.truth.Truth
+import com.google.common.truth.Truth.assertThat
import io.element.android.features.invitelist.test.FakeSeenInvitesStore
import io.element.android.features.roomlist.impl.InvitesState
import io.element.android.libraries.matrix.test.A_ROOM_ID
@@ -43,7 +43,7 @@ internal class DefaultInviteStateDataSourceTest {
moleculeFlow(RecompositionMode.Immediate) {
dataSource.inviteState()
}.test {
- Truth.assertThat(awaitItem()).isEqualTo(InvitesState.NoInvites)
+ assertThat(awaitItem()).isEqualTo(InvitesState.NoInvites)
}
}
@@ -59,7 +59,7 @@ internal class DefaultInviteStateDataSourceTest {
dataSource.inviteState()
}.test {
skipItems(1)
- Truth.assertThat(awaitItem()).isEqualTo(InvitesState.NewInvites)
+ assertThat(awaitItem()).isEqualTo(InvitesState.NewInvites)
}
}
@@ -76,7 +76,7 @@ internal class DefaultInviteStateDataSourceTest {
dataSource.inviteState()
}.test {
skipItems(1)
- Truth.assertThat(awaitItem()).isEqualTo(InvitesState.NewInvites)
+ assertThat(awaitItem()).isEqualTo(InvitesState.NewInvites)
}
}
@@ -94,7 +94,7 @@ internal class DefaultInviteStateDataSourceTest {
}.test {
skipItems(1)
- Truth.assertThat(awaitItem()).isEqualTo(InvitesState.SeenInvites)
+ assertThat(awaitItem()).isEqualTo(InvitesState.SeenInvites)
}
}
@@ -109,27 +109,27 @@ internal class DefaultInviteStateDataSourceTest {
dataSource.inviteState()
}.test {
// Initially there are no invites
- Truth.assertThat(awaitItem()).isEqualTo(InvitesState.NoInvites)
+ assertThat(awaitItem()).isEqualTo(InvitesState.NoInvites)
// When a single invite is received, state should be NewInvites
roomListService.postInviteRooms(listOf(aRoomSummaryFilled(roomId = A_ROOM_ID)))
skipItems(1)
- Truth.assertThat(awaitItem()).isEqualTo(InvitesState.NewInvites)
+ assertThat(awaitItem()).isEqualTo(InvitesState.NewInvites)
// If that invite is marked as seen, then the state becomes SeenInvites
seenStore.publishRoomIds(setOf(A_ROOM_ID))
skipItems(1)
- Truth.assertThat(awaitItem()).isEqualTo(InvitesState.SeenInvites)
+ assertThat(awaitItem()).isEqualTo(InvitesState.SeenInvites)
// Another new invite resets it to NewInvites
roomListService.postInviteRooms(listOf(aRoomSummaryFilled(roomId = A_ROOM_ID), aRoomSummaryFilled(roomId = A_ROOM_ID_2)))
skipItems(1)
- Truth.assertThat(awaitItem()).isEqualTo(InvitesState.NewInvites)
+ assertThat(awaitItem()).isEqualTo(InvitesState.NewInvites)
// All of the invites going away reverts to NoInvites
roomListService.postInviteRooms(emptyList())
skipItems(1)
- Truth.assertThat(awaitItem()).isEqualTo(InvitesState.NoInvites)
+ assertThat(awaitItem()).isEqualTo(InvitesState.NoInvites)
}
}
}
diff --git a/features/securebackup/impl/src/main/kotlin/io/element/android/features/securebackup/impl/enter/SecureBackupEnterRecoveryKeyPresenter.kt b/features/securebackup/impl/src/main/kotlin/io/element/android/features/securebackup/impl/enter/SecureBackupEnterRecoveryKeyPresenter.kt
index bec4dd9217..9207dbef79 100644
--- a/features/securebackup/impl/src/main/kotlin/io/element/android/features/securebackup/impl/enter/SecureBackupEnterRecoveryKeyPresenter.kt
+++ b/features/securebackup/impl/src/main/kotlin/io/element/android/features/securebackup/impl/enter/SecureBackupEnterRecoveryKeyPresenter.kt
@@ -89,7 +89,7 @@ class SecureBackupEnterRecoveryKeyPresenter @Inject constructor(
action: MutableState>
) = launch {
suspend {
- encryptionService.fixRecoveryIssues(recoveryKey).getOrThrow()
+ encryptionService.recover(recoveryKey).getOrThrow()
}.runCatchingUpdatingState(action)
}
}
diff --git a/features/securebackup/impl/src/main/res/values-de/translations.xml b/features/securebackup/impl/src/main/res/values-de/translations.xml
new file mode 100644
index 0000000000..70c5fecfc1
--- /dev/null
+++ b/features/securebackup/impl/src/main/res/values-de/translations.xml
@@ -0,0 +1,32 @@
+
+
+ "Backup deaktivieren"
+ "Backup aktivieren"
+ "Das Backup stellt sicher, dass du deinen Nachrichtenverlauf nicht verlierst. %1$s."
+ "Backup"
+ "Dein Chat-Backup ist derzeit nicht synchronisiert."
+ "Wiederherstellung einrichten"
+ "Erhalte Zugriff auf deine verschlüsselten Nachrichten, wenn du alle deine Geräte verlierst oder von %1$s überall abgemeldet bist."
+ "Ausschalten"
+ "Du verlierst deine verschlüsselten Nachrichten, wenn du auf allen Geräten abgemeldet bist."
+ "Bist du sicher, dass du das Backup ausschalten willst?"
+ "Wenn du das Backup ausschaltest, wird dein aktuelles Backup des Verschlüsselungsschlüssels entfernt und andere Sicherheitsfunktionen werden deaktiviert. In diesem Fall wirst du:"
+ "Kein verschlüsselter Nachrichtenverlauf auf neuen Geräten"
+ "Du verlierst den Zugriff auf deine verschlüsselten Nachrichten, wenn du dich überall von %1$s abmeldest"
+ "Bist du sicher, dass du das Backup ausschalten willst?"
+ "Besorge dir einen neuen Wiederherstellungsschlüssel, wenn du deinen alten verloren hast. Nachdem du deinen Wiederherstellungsschlüssel geändert hast, funktioniert dein alter Schlüssel nicht mehr."
+ "Stelle sicher, dass du deinen Wiederherstellungsschlüssel an einem sicheren Ort aufbewahren kannst"
+ "Gib deinen Wiederherstellungsschlüssel ein, um den Zugriff auf dein Chat-Backup zu bestätigen."
+ "Bitte versuche es noch einmal, um den Zugriff auf dein Chat-Backup zu bestätigen."
+ "Gib den 48-stelligen Code ein."
+ "Eingeben…"
+ "Generieren…"
+ "Notiere dir deinen Wiederherstellungsschlüssel an einem sicheren Ort oder speichere ihn in einem Passwort-Manager."
+ "Tippe, um den Wiederherstellungsschlüssel zu kopieren"
+ "Nach diesem Schritt kannst du nicht mehr auf deinen neuen Wiederherstellungsschlüssel zugreifen."
+ "Hast du deinen Wiederherstellungsschlüssel gespeichert?"
+ "Dein Chat-Backup ist durch einen Wiederherstellungsschlüssel geschützt. Wenn du nach der Einrichtung einen neuen Wiederherstellungsschlüssel brauchst, kannst du ihn über die Option \"Wiederherstellungsschlüssel ändern\" neu erstellen."
+ "Stelle sicher, dass du deinen Wiederherstellungsschlüssel an einem sicheren Ort aufbewahren kannst"
+ "Einrichtung der Wiederherstellung erfolgreich"
+ "Wiederherstellung einrichten"
+
diff --git a/features/securebackup/impl/src/main/res/values-hu/translations.xml b/features/securebackup/impl/src/main/res/values-hu/translations.xml
new file mode 100644
index 0000000000..0eff260322
--- /dev/null
+++ b/features/securebackup/impl/src/main/res/values-hu/translations.xml
@@ -0,0 +1,44 @@
+
+
+ "Biztonsági mentés kikapcsolása"
+ "Biztonsági mentés bekapcsolása"
+ "A biztonsági mentés biztosítja, hogy ne veszítse el az üzenetelőzményeit. %1$s."
+ "Biztonsági mentés"
+ "Helyreállítási kulcs módosítása"
+ "Helyreállítási kulcs megerősítése"
+ "A csevegéselőzményei nincsenek szinkronban."
+ "Helyreállítás beállítása"
+ "Szerezzen hozzáférést a titkosított üzeneteihez, ha elvesztette az összes eszközét, vagy ha mindenütt kijelentkezett az %1$sből."
+ "Kikapcsolás"
+ "Ha kijelentkezik az összes eszközéről, akkor elveszti a titkosított üzeneteit."
+ "Biztos, hogy kikapcsolja a biztonsági mentéseket?"
+ "A biztonsági mentés kikapcsolása eltávolítja a jelenlegi titkosítási kulcsának mentését, és kikapcsol más biztonsági funkciókat is. Ebben az esetben:"
+ "Nem lesznek meg a titkosított üzenetelőzményei az új eszközein"
+ "Elveszti a titkosított üzenetei hozzáférését, ha mindenhol kilép az %1$sből"
+ "Biztos, hogy kikapcsolja a biztonsági mentéseket?"
+ "Szerezzen új helyreállítási kulcsot, ha elvesztette a meglévőt. A helyreállítása kulcsa módosítása után a régi már nem fog működni."
+ "Új helyreállítási kulcs előállítása"
+ "Gondoskodjon arról, hogy biztonságos helyen tárolja a helyreállítási kulcsát"
+ "Helyreállítási kulcs lecserélve"
+ "Módosítja a helyreállítási kulcsot?"
+ "Adja meg a helyreállítási kulcsát, hogy megerősítse a csevegések biztonsági mentéséhez való hozzáférését."
+ "Próbálja meg újra megerősíteni a csevegés biztonsági mentéséhez való hozzáférését."
+ "Helytelen helyreállítási kulcs"
+ "Adja meg a 48 karakteres kódot."
+ "Megadás…"
+ "Helyreállítási kulcs megerősítve"
+ "Erősítse meg a helyreállítási kulcsát"
+ "Helyreállítási kulcs másolva"
+ "Előállítás…"
+ "Helyreállítási kulcs mentése"
+ "Írja le a helyreállítási kulcsát valami biztonságos helyre, vagy mentse egy jelszókezelőbe."
+ "Koppintson a helyreállítási kulcs másolásához"
+ "Mentse el a helyreállítási kulcsát"
+ "Ezután a lépés után nem fog tudni hozzáférni az új helyreállítási kulcsához."
+ "Mentette a helyreállítási kulcsát?"
+ "A csevegései biztonsági mentését a helyreállítási kulcsa védi. Ha új helyreállítási kulcsra van szüksége a beállítás után, akkor a „Helyreállítási kulcs módosítása” választásával újból létrehozhat egyet."
+ "Helyreállítási kulcs előállítása"
+ "Gondoskodjon arról, hogy biztonságos helyen tárolja a helyreállítási kulcsát"
+ "A helyreállítás beállítása sikeres"
+ "Helyreállítás beállítása"
+
diff --git a/features/securebackup/impl/src/main/res/values-in/translations.xml b/features/securebackup/impl/src/main/res/values-in/translations.xml
new file mode 100644
index 0000000000..c7712832d2
--- /dev/null
+++ b/features/securebackup/impl/src/main/res/values-in/translations.xml
@@ -0,0 +1,44 @@
+
+
+ "Matikan pencadangan"
+ "Nyalakan pencadangan"
+ "Pencadangan memastikan bahwa Anda tidak akan kehilangan riwayat pesan Anda. %1$s."
+ "Pencadangan"
+ "Ubah kunci pemulihan"
+ "Konfirmasi kunci pemulihan"
+ "Pencadangan percakapan Anda saat ini tidak tersinkron."
+ "Siapkan pemulihan"
+ "Dapatkan akses ke pesan terenkripsi Anda jika Anda kehilangan semua perangkat Anda atau keluar dari %1$s di mana pun."
+ "Matikan"
+ "Anda akan kehilangan pesan terenkripsi jika Anda keluar dari semua perangkat."
+ "Apakah Anda yakin ingin mematikan pencadangan?"
+ "Mematikan pencadangan akan menghapus pencadangan kunci terenkripsi saat ini dan mematikan fitur keamanan lainnya. Dalam hal ini, Anda akan:"
+ "Tidak memiliki riwayat pesan terenkripsi di perangkat baru"
+ "Kehilangan akses ke pesan terenkripsi Anda jika keluar dari %1$s di mana pun"
+ "Apakah Anda yakin ingin mematikan pencadangan?"
+ "Dapatkan kunci pemulihan yang baru jika Anda kehilangan kunci pemulihan saat ini. Setelah mengganti kunci pemulihan Anda, yang lama tidak akan bekerja lagi."
+ "Buat kunci pemulihan baru"
+ "Pastikan Anda dapat menyimpan kunci pemulihan Anda di tempat yang aman"
+ "Kunci pemulihan diganti"
+ "Ubah kunci pemulihan?"
+ "Masukkan kunci pemulihan Anda untuk mengonfirmasi akses ke cadangan percakapan Anda."
+ "Silakan coba lagi untuk mengonfirmasi akses ke cadangan percakapan Anda."
+ "Kunci pemulihan salah"
+ "Masukkan kode 48 karakter."
+ "Masukkan…"
+ "Kunci pemulihan dikonfirmasi"
+ "Konfirmasi kunci pemulihan Anda"
+ "Kunci pemulihan disalin"
+ "Membuat…"
+ "Simpan kunci pemulihan"
+ "Tuliskan kunci pemulihan Anda di tempat yang aman atau simpan di pengelola kata sandi."
+ "Ketuk untuk menyalin kunci pemulihan"
+ "Simpan kunci pemulihan Anda"
+ "Anda tidak akan dapat mengakses kunci pemulihan Anda setelah langkah ini."
+ "Apakah Anda sudah menyimpan kunci pemulihan Anda?"
+ "Pencadangan percakapan Anda sedang dilindungi oleh sebuah kunci pemulihan. Jika Anda perlu kunci pemulihan yang baru setelah penyiapan, Anda dapat membuat ulang dengan memilih \'Ubah kunci pemulihan\'."
+ "Buat kunci pemulihan Anda"
+ "Pastikan Anda dapat menyimpan kunci pemulihan Anda di tempat yang aman"
+ "Penyiapan pemulihan berhasil"
+ "Siapkan pemulihan"
+
diff --git a/features/securebackup/impl/src/test/kotlin/io/element/android/features/securebackup/impl/enter/SecureBackupEnterRecoveryKeyPresenterTest.kt b/features/securebackup/impl/src/test/kotlin/io/element/android/features/securebackup/impl/enter/SecureBackupEnterRecoveryKeyPresenterTest.kt
index d34f869f6e..862cbbde72 100644
--- a/features/securebackup/impl/src/test/kotlin/io/element/android/features/securebackup/impl/enter/SecureBackupEnterRecoveryKeyPresenterTest.kt
+++ b/features/securebackup/impl/src/test/kotlin/io/element/android/features/securebackup/impl/enter/SecureBackupEnterRecoveryKeyPresenterTest.kt
@@ -73,7 +73,7 @@ class SecureBackupEnterRecoveryKeyPresenterTest {
inProgress = false,
)
)
- encryptionService.givenFixRecoveryIssuesFailure(AN_EXCEPTION)
+ encryptionService.givenRecoverFailure(AN_EXCEPTION)
withRecoveryKeyState.eventSink(SecureBackupEnterRecoveryKeyEvents.Submit)
val loadingState = awaitItem()
assertThat(loadingState.submitAction).isEqualTo(Async.Loading())
@@ -85,7 +85,7 @@ class SecureBackupEnterRecoveryKeyPresenterTest {
val clearedState = awaitItem()
assertThat(clearedState.submitAction).isEqualTo(Async.Uninitialized)
assertThat(clearedState.isSubmitEnabled).isTrue()
- encryptionService.givenFixRecoveryIssuesFailure(null)
+ encryptionService.givenRecoverFailure(null)
clearedState.eventSink(SecureBackupEnterRecoveryKeyEvents.Submit)
val loadingState2 = awaitItem()
assertThat(loadingState2.submitAction).isEqualTo(Async.Loading())
diff --git a/features/signedout/impl/src/main/res/values-de/translations.xml b/features/signedout/impl/src/main/res/values-de/translations.xml
new file mode 100644
index 0000000000..08e0305f8e
--- /dev/null
+++ b/features/signedout/impl/src/main/res/values-de/translations.xml
@@ -0,0 +1,8 @@
+
+
+ "Du hast dein Passwort in einer anderen Sitzung geändert"
+ "Du hast die Sitzung aus einer anderen Sitzung gelöscht"
+ "Der Administrator deines Servers hat deinen Zugang ungültig gemacht"
+ "Möglicherweise wurdest du aus einem der unten aufgeführten Gründe abgemeldet. Bitte melde dich erneut an, um %s weiter zu nutzen."
+ "Du bist abgemeldet"
+
diff --git a/features/signedout/impl/src/main/res/values-hu/translations.xml b/features/signedout/impl/src/main/res/values-hu/translations.xml
new file mode 100644
index 0000000000..a73cdbb734
--- /dev/null
+++ b/features/signedout/impl/src/main/res/values-hu/translations.xml
@@ -0,0 +1,7 @@
+
+
+ "Megváltoztatta a jelszavát egy másik munkamenetben"
+ "Törölte a munkamenetet egy másik munkamenetből"
+ "A kiszolgáló rendszergazdája érvénytelenítette a hozzáférését"
+ "Kijelentkezett"
+
diff --git a/features/signedout/impl/src/main/res/values-in/translations.xml b/features/signedout/impl/src/main/res/values-in/translations.xml
new file mode 100644
index 0000000000..7feb4b4edb
--- /dev/null
+++ b/features/signedout/impl/src/main/res/values-in/translations.xml
@@ -0,0 +1,8 @@
+
+
+ "Anda telah mengubah kata sandi Anda di sesi yang lain"
+ "Anda telah menghapus sesi dari sesi lain"
+ "Administrator homeserver Anda telah membatalkan akses Anda"
+ "Anda mungkin dikeluarkan karena alasan berikut. Silakan masuk lagi untuk melanjutkan menggunakan %s."
+ "Anda telah keluar"
+
diff --git a/features/verifysession/impl/src/main/kotlin/io/element/android/features/verifysession/impl/VerifySelfSessionPresenter.kt b/features/verifysession/impl/src/main/kotlin/io/element/android/features/verifysession/impl/VerifySelfSessionPresenter.kt
index 689ff3a154..89751ca604 100644
--- a/features/verifysession/impl/src/main/kotlin/io/element/android/features/verifysession/impl/VerifySelfSessionPresenter.kt
+++ b/features/verifysession/impl/src/main/kotlin/io/element/android/features/verifysession/impl/VerifySelfSessionPresenter.kt
@@ -97,7 +97,7 @@ class VerifySelfSessionPresenter @Inject constructor(
is StateMachineState.Verifying.Replying -> Async.Loading()
else -> Async.Uninitialized
}
- VerifySelfSessionState.VerificationStep.Verifying(machineState.emojis, async)
+ VerifySelfSessionState.VerificationStep.Verifying(machineState.data, async)
}
StateMachineState.Completed -> {
@@ -116,7 +116,7 @@ class VerifySelfSessionPresenter @Inject constructor(
stateMachine.dispatch(VerifySelfSessionStateMachine.Event.DidStartSasVerification)
}
is VerificationFlowState.ReceivedVerificationData -> {
- stateMachine.dispatch(VerifySelfSessionStateMachine.Event.DidReceiveChallenge(verificationAttemptState.emoji))
+ stateMachine.dispatch(VerifySelfSessionStateMachine.Event.DidReceiveChallenge(verificationAttemptState.data))
}
VerificationFlowState.Finished -> {
stateMachine.dispatch(VerifySelfSessionStateMachine.Event.DidAcceptChallenge)
diff --git a/features/verifysession/impl/src/main/kotlin/io/element/android/features/verifysession/impl/VerifySelfSessionState.kt b/features/verifysession/impl/src/main/kotlin/io/element/android/features/verifysession/impl/VerifySelfSessionState.kt
index 248e3aec10..f3afd3b7b9 100644
--- a/features/verifysession/impl/src/main/kotlin/io/element/android/features/verifysession/impl/VerifySelfSessionState.kt
+++ b/features/verifysession/impl/src/main/kotlin/io/element/android/features/verifysession/impl/VerifySelfSessionState.kt
@@ -19,7 +19,7 @@ package io.element.android.features.verifysession.impl
import androidx.compose.runtime.Immutable
import androidx.compose.runtime.Stable
import io.element.android.libraries.architecture.Async
-import io.element.android.libraries.matrix.api.verification.VerificationEmoji
+import io.element.android.libraries.matrix.api.verification.SessionVerificationData
@Immutable
data class VerifySelfSessionState(
@@ -33,7 +33,7 @@ data class VerifySelfSessionState(
data object Canceled : VerificationStep
data object AwaitingOtherDeviceResponse : VerificationStep
data object Ready : VerificationStep
- data class Verifying(val emojiList: List, val state: Async) : VerificationStep
+ data class Verifying(val data: SessionVerificationData, val state: Async) : VerificationStep
data object Completed : VerificationStep
}
}
diff --git a/features/verifysession/impl/src/main/kotlin/io/element/android/features/verifysession/impl/VerifySelfSessionStateMachine.kt b/features/verifysession/impl/src/main/kotlin/io/element/android/features/verifysession/impl/VerifySelfSessionStateMachine.kt
index ad48294e92..52bd38bfbd 100644
--- a/features/verifysession/impl/src/main/kotlin/io/element/android/features/verifysession/impl/VerifySelfSessionStateMachine.kt
+++ b/features/verifysession/impl/src/main/kotlin/io/element/android/features/verifysession/impl/VerifySelfSessionStateMachine.kt
@@ -20,8 +20,8 @@
package io.element.android.features.verifysession.impl
import com.freeletics.flowredux.dsl.FlowReduxStateMachine
+import io.element.android.libraries.matrix.api.verification.SessionVerificationData
import io.element.android.libraries.matrix.api.verification.SessionVerificationService
-import io.element.android.libraries.matrix.api.verification.VerificationEmoji
import kotlinx.coroutines.ExperimentalCoroutinesApi
import javax.inject.Inject
import com.freeletics.flowredux.dsl.State as MachineState
@@ -70,15 +70,15 @@ class VerifySelfSessionStateMachine @Inject constructor(
}
inState {
on { event: Event.DidReceiveChallenge, state: MachineState ->
- state.override { State.Verifying.ChallengeReceived(event.emojis) }
+ state.override { State.Verifying.ChallengeReceived(event.data) }
}
}
inState {
on { _: Event.AcceptChallenge, state: MachineState ->
- state.override { State.Verifying.Replying(state.snapshot.emojis, accept = true) }
+ state.override { State.Verifying.Replying(state.snapshot.data, accept = true) }
}
on { _: Event.DeclineChallenge, state: MachineState ->
- state.override { State.Verifying.Replying(state.snapshot.emojis, accept = false) }
+ state.override { State.Verifying.Replying(state.snapshot.data, accept = false) }
}
}
inState {
@@ -139,12 +139,12 @@ class VerifySelfSessionStateMachine @Inject constructor(
/** A SaS verification flow has been started. */
data object SasVerificationStarted : State
- sealed class Verifying(open val emojis: List) : State {
+ sealed class Verifying(open val data: SessionVerificationData) : State {
/** Verification accepted and emojis received. */
- data class ChallengeReceived(override val emojis: List) : Verifying(emojis)
+ data class ChallengeReceived(override val data: SessionVerificationData) : Verifying(data)
/** Replying to a verification challenge. */
- data class Replying(override val emojis: List, val accept: Boolean) : Verifying(emojis)
+ data class Replying(override val data: SessionVerificationData, val accept: Boolean) : Verifying(data)
}
/** The verification is being canceled. */
@@ -170,8 +170,8 @@ class VerifySelfSessionStateMachine @Inject constructor(
/** Started a SaS verification flow. */
data object DidStartSasVerification : Event
- /** Has received emojis. */
- data class DidReceiveChallenge(val emojis: List) : Event
+ /** Has received data. */
+ data class DidReceiveChallenge(val data: SessionVerificationData) : Event
/** Emojis match. */
data object AcceptChallenge : Event
diff --git a/features/verifysession/impl/src/main/kotlin/io/element/android/features/verifysession/impl/VerifySelfSessionStateProvider.kt b/features/verifysession/impl/src/main/kotlin/io/element/android/features/verifysession/impl/VerifySelfSessionStateProvider.kt
index 54a59dee01..9115b8b444 100644
--- a/features/verifysession/impl/src/main/kotlin/io/element/android/features/verifysession/impl/VerifySelfSessionStateProvider.kt
+++ b/features/verifysession/impl/src/main/kotlin/io/element/android/features/verifysession/impl/VerifySelfSessionStateProvider.kt
@@ -18,6 +18,7 @@ package io.element.android.features.verifysession.impl
import androidx.compose.ui.tooling.preview.PreviewParameterProvider
import io.element.android.libraries.architecture.Async
+import io.element.android.libraries.matrix.api.verification.SessionVerificationData
import io.element.android.libraries.matrix.api.verification.VerificationEmoji
open class VerifySelfSessionStateProvider : PreviewParameterProvider {
@@ -28,10 +29,10 @@ open class VerifySelfSessionStateProvider : PreviewParameterProvider = aVerificationEmojiList(),
+): SessionVerificationData {
+ return SessionVerificationData.Emojis(emojiList)
+}
+
+private fun aDecimalsSessionVerificationData(
+ decimals: List = listOf(123, 456, 789),
+): SessionVerificationData {
+ return SessionVerificationData.Decimals(decimals)
+}
+
+private fun aVerifySelfSessionState() = VerifySelfSessionState(
verificationFlowStep = VerifySelfSessionState.VerificationStep.Initial,
eventSink = {},
)
-fun aVerificationEmojiList() = listOf(
- VerificationEmoji("🍕", "Pizza"),
- VerificationEmoji("🚀", "Rocket"),
- VerificationEmoji("🚀", "Rocket"),
- VerificationEmoji("🗺️", "Map"),
- VerificationEmoji("🎳", "Bowling"),
- VerificationEmoji("🎳", "Bowling"),
- VerificationEmoji("📌", "Pin"),
+private fun aVerificationEmojiList() = listOf(
+ VerificationEmoji(number = 27, emoji = "🍕", description = "Pizza"),
+ VerificationEmoji(number = 54, emoji = "🚀", description = "Rocket"),
+ VerificationEmoji(number = 54, emoji = "🚀", description = "Rocket"),
+ VerificationEmoji(number = 42, emoji = "📕", description = "Book"),
+ VerificationEmoji(number = 48, emoji = "🔨", description = "Hammer"),
+ VerificationEmoji(number = 48, emoji = "🔨", description = "Hammer"),
+ VerificationEmoji(number = 63, emoji = "📌", description = "Pin"),
)
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 df29cc653e..a132431812 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
@@ -17,6 +17,7 @@
package io.element.android.features.verifysession.impl
import androidx.activity.compose.BackHandler
+import androidx.compose.foundation.Image
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Row
@@ -25,6 +26,7 @@ import androidx.compose.foundation.layout.fillMaxHeight
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.material3.MaterialTheme
import androidx.compose.runtime.Composable
@@ -33,11 +35,14 @@ import androidx.compose.runtime.getValue
import androidx.compose.runtime.remember
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
+import androidx.compose.ui.res.painterResource
import androidx.compose.ui.res.stringResource
+import androidx.compose.ui.text.style.TextAlign
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.compound.theme.ElementTheme
+import io.element.android.features.verifysession.impl.emoji.toEmojiResource
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
@@ -48,8 +53,8 @@ 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.SessionVerificationData
import io.element.android.libraries.matrix.api.verification.VerificationEmoji
-import io.element.android.compound.theme.ElementTheme
import io.element.android.libraries.ui.strings.CommonStrings
import io.element.android.features.verifysession.impl.VerifySelfSessionState.VerificationStep as FlowStep
@@ -100,14 +105,23 @@ private fun HeaderContent(verificationFlowStep: FlowStep, modifier: Modifier = M
FlowStep.Initial -> R.string.screen_session_verification_open_existing_session_title
FlowStep.Canceled -> CommonStrings.common_verification_cancelled
FlowStep.AwaitingOtherDeviceResponse -> R.string.screen_session_verification_waiting_to_accept_title
- FlowStep.Ready, is FlowStep.Verifying, FlowStep.Completed -> R.string.screen_session_verification_compare_emojis_title
+ FlowStep.Ready,
+ FlowStep.Completed -> R.string.screen_session_verification_compare_emojis_title
+ is FlowStep.Verifying -> when (verificationFlowStep.data) {
+ is SessionVerificationData.Decimals -> R.string.screen_session_verification_compare_numbers_title
+ is SessionVerificationData.Emojis -> R.string.screen_session_verification_compare_emojis_title
+ }
}
val subtitleTextId = when (verificationFlowStep) {
FlowStep.Initial -> R.string.screen_session_verification_open_existing_session_subtitle
FlowStep.Canceled -> R.string.screen_session_verification_cancelled_subtitle
FlowStep.AwaitingOtherDeviceResponse -> R.string.screen_session_verification_waiting_to_accept_subtitle
- is FlowStep.Verifying, FlowStep.Completed -> R.string.screen_session_verification_compare_emojis_subtitle
FlowStep.Ready -> R.string.screen_session_verification_ready_subtitle
+ FlowStep.Completed -> R.string.screen_session_verification_compare_emojis_subtitle
+ is FlowStep.Verifying -> when (verificationFlowStep.data) {
+ is SessionVerificationData.Decimals -> R.string.screen_session_verification_compare_numbers_subtitle
+ is SessionVerificationData.Emojis -> R.string.screen_session_verification_compare_emojis_subtitle
+ }
}
IconTitleSubtitleMolecule(
@@ -138,17 +152,30 @@ private fun ContentWaiting(modifier: Modifier = Modifier) {
@Composable
private fun ContentVerifying(verificationFlowStep: FlowStep.Verifying, modifier: Modifier = Modifier) {
- // We want each row to have up to 4 emojis
- val rows = verificationFlowStep.emojiList.chunked(4)
- Column(modifier = modifier.fillMaxWidth()) {
- for ((rowIndex, emojis) in rows.withIndex()) {
- // Vertical spacing between rows
- if (rowIndex > 0) {
- Spacer(modifier = Modifier.height(40.dp))
- }
- Row(modifier = Modifier.fillMaxWidth(), horizontalArrangement = Arrangement.SpaceEvenly) {
- for (emoji in emojis) {
- EmojiItemView(emoji = emoji, modifier = Modifier.widthIn(max = 60.dp))
+ when (verificationFlowStep.data) {
+ is SessionVerificationData.Decimals -> {
+ val text = verificationFlowStep.data.decimals.joinToString(separator = " - ") { it.toString() }
+ Text(
+ modifier = modifier.fillMaxWidth(),
+ text = text,
+ style = ElementTheme.typography.fontHeadingLgBold,
+ color = MaterialTheme.colorScheme.primary,
+ textAlign = TextAlign.Center,
+ )
+ }
+ is SessionVerificationData.Emojis -> {
+ // We want each row to have up to 4 emojis
+ val rows = verificationFlowStep.data.emojis.chunked(4)
+ Column(
+ modifier = modifier.fillMaxWidth(),
+ verticalArrangement = Arrangement.spacedBy(40.dp),
+ ) {
+ rows.forEach { emojis ->
+ Row(modifier = Modifier.fillMaxWidth(), horizontalArrangement = Arrangement.SpaceEvenly) {
+ for (emoji in emojis) {
+ EmojiItemView(emoji = emoji, modifier = Modifier.widthIn(max = 60.dp))
+ }
+ }
}
}
}
@@ -157,14 +184,16 @@ private fun ContentVerifying(verificationFlowStep: FlowStep.Verifying, modifier:
@Composable
private fun EmojiItemView(emoji: VerificationEmoji, modifier: Modifier = Modifier) {
+ val emojiResource = emoji.number.toEmojiResource()
Column(horizontalAlignment = Alignment.CenterHorizontally, modifier = modifier) {
- Text(
- text = emoji.code,
- style = ElementTheme.typography.fontBodyMdRegular.copy(fontSize = 34.sp),
+ Image(
+ modifier = Modifier.size(48.dp),
+ painter = painterResource(id = emojiResource.drawableRes),
+ contentDescription = null,
)
Spacer(modifier = Modifier.height(16.dp))
Text(
- emoji.name,
+ text = stringResource(id = emojiResource.nameRes),
style = ElementTheme.typography.fontBodyMdRegular,
color = MaterialTheme.colorScheme.secondary,
maxLines = 1,
diff --git a/features/verifysession/impl/src/main/kotlin/io/element/android/features/verifysession/impl/emoji/EmojiResource.kt b/features/verifysession/impl/src/main/kotlin/io/element/android/features/verifysession/impl/emoji/EmojiResource.kt
new file mode 100644
index 0000000000..e57239d5f2
--- /dev/null
+++ b/features/verifysession/impl/src/main/kotlin/io/element/android/features/verifysession/impl/emoji/EmojiResource.kt
@@ -0,0 +1,94 @@
+/*
+ * 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.verifysession.impl.emoji
+
+import androidx.annotation.DrawableRes
+import androidx.annotation.StringRes
+import io.element.android.features.verifysession.impl.R
+
+internal data class EmojiResource(
+ @DrawableRes val drawableRes: Int,
+ @StringRes val nameRes: Int
+)
+
+internal fun Int.toEmojiResource(): EmojiResource {
+ return when (this % 64) {
+ 0 -> EmojiResource(R.drawable.ic_verification_00, R.string.verification_emoji_00)
+ 1 -> EmojiResource(R.drawable.ic_verification_01, R.string.verification_emoji_01)
+ 2 -> EmojiResource(R.drawable.ic_verification_02, R.string.verification_emoji_02)
+ 3 -> EmojiResource(R.drawable.ic_verification_03, R.string.verification_emoji_03)
+ 4 -> EmojiResource(R.drawable.ic_verification_04, R.string.verification_emoji_04)
+ 5 -> EmojiResource(R.drawable.ic_verification_05, R.string.verification_emoji_05)
+ 6 -> EmojiResource(R.drawable.ic_verification_06, R.string.verification_emoji_06)
+ 7 -> EmojiResource(R.drawable.ic_verification_07, R.string.verification_emoji_07)
+ 8 -> EmojiResource(R.drawable.ic_verification_08, R.string.verification_emoji_08)
+ 9 -> EmojiResource(R.drawable.ic_verification_09, R.string.verification_emoji_09)
+ 10 -> EmojiResource(R.drawable.ic_verification_10, R.string.verification_emoji_10)
+ 11 -> EmojiResource(R.drawable.ic_verification_11, R.string.verification_emoji_11)
+ 12 -> EmojiResource(R.drawable.ic_verification_12, R.string.verification_emoji_12)
+ 13 -> EmojiResource(R.drawable.ic_verification_13, R.string.verification_emoji_13)
+ 14 -> EmojiResource(R.drawable.ic_verification_14, R.string.verification_emoji_14)
+ 15 -> EmojiResource(R.drawable.ic_verification_15, R.string.verification_emoji_15)
+ 16 -> EmojiResource(R.drawable.ic_verification_16, R.string.verification_emoji_16)
+ 17 -> EmojiResource(R.drawable.ic_verification_17, R.string.verification_emoji_17)
+ 18 -> EmojiResource(R.drawable.ic_verification_18, R.string.verification_emoji_18)
+ 19 -> EmojiResource(R.drawable.ic_verification_19, R.string.verification_emoji_19)
+ 20 -> EmojiResource(R.drawable.ic_verification_20, R.string.verification_emoji_20)
+ 21 -> EmojiResource(R.drawable.ic_verification_21, R.string.verification_emoji_21)
+ 22 -> EmojiResource(R.drawable.ic_verification_22, R.string.verification_emoji_22)
+ 23 -> EmojiResource(R.drawable.ic_verification_23, R.string.verification_emoji_23)
+ 24 -> EmojiResource(R.drawable.ic_verification_24, R.string.verification_emoji_24)
+ 25 -> EmojiResource(R.drawable.ic_verification_25, R.string.verification_emoji_25)
+ 26 -> EmojiResource(R.drawable.ic_verification_26, R.string.verification_emoji_26)
+ 27 -> EmojiResource(R.drawable.ic_verification_27, R.string.verification_emoji_27)
+ 28 -> EmojiResource(R.drawable.ic_verification_28, R.string.verification_emoji_28)
+ 29 -> EmojiResource(R.drawable.ic_verification_29, R.string.verification_emoji_29)
+ 30 -> EmojiResource(R.drawable.ic_verification_30, R.string.verification_emoji_30)
+ 31 -> EmojiResource(R.drawable.ic_verification_31, R.string.verification_emoji_31)
+ 32 -> EmojiResource(R.drawable.ic_verification_32, R.string.verification_emoji_32)
+ 33 -> EmojiResource(R.drawable.ic_verification_33, R.string.verification_emoji_33)
+ 34 -> EmojiResource(R.drawable.ic_verification_34, R.string.verification_emoji_34)
+ 35 -> EmojiResource(R.drawable.ic_verification_35, R.string.verification_emoji_35)
+ 36 -> EmojiResource(R.drawable.ic_verification_36, R.string.verification_emoji_36)
+ 37 -> EmojiResource(R.drawable.ic_verification_37, R.string.verification_emoji_37)
+ 38 -> EmojiResource(R.drawable.ic_verification_38, R.string.verification_emoji_38)
+ 39 -> EmojiResource(R.drawable.ic_verification_39, R.string.verification_emoji_39)
+ 40 -> EmojiResource(R.drawable.ic_verification_40, R.string.verification_emoji_40)
+ 41 -> EmojiResource(R.drawable.ic_verification_41, R.string.verification_emoji_41)
+ 42 -> EmojiResource(R.drawable.ic_verification_42, R.string.verification_emoji_42)
+ 43 -> EmojiResource(R.drawable.ic_verification_43, R.string.verification_emoji_43)
+ 44 -> EmojiResource(R.drawable.ic_verification_44, R.string.verification_emoji_44)
+ 45 -> EmojiResource(R.drawable.ic_verification_45, R.string.verification_emoji_45)
+ 46 -> EmojiResource(R.drawable.ic_verification_46, R.string.verification_emoji_46)
+ 47 -> EmojiResource(R.drawable.ic_verification_47, R.string.verification_emoji_47)
+ 48 -> EmojiResource(R.drawable.ic_verification_48, R.string.verification_emoji_48)
+ 49 -> EmojiResource(R.drawable.ic_verification_49, R.string.verification_emoji_49)
+ 50 -> EmojiResource(R.drawable.ic_verification_50, R.string.verification_emoji_50)
+ 51 -> EmojiResource(R.drawable.ic_verification_51, R.string.verification_emoji_51)
+ 52 -> EmojiResource(R.drawable.ic_verification_52, R.string.verification_emoji_52)
+ 53 -> EmojiResource(R.drawable.ic_verification_53, R.string.verification_emoji_53)
+ 54 -> EmojiResource(R.drawable.ic_verification_54, R.string.verification_emoji_54)
+ 55 -> EmojiResource(R.drawable.ic_verification_55, R.string.verification_emoji_55)
+ 56 -> EmojiResource(R.drawable.ic_verification_56, R.string.verification_emoji_56)
+ 57 -> EmojiResource(R.drawable.ic_verification_57, R.string.verification_emoji_57)
+ 58 -> EmojiResource(R.drawable.ic_verification_58, R.string.verification_emoji_58)
+ 59 -> EmojiResource(R.drawable.ic_verification_59, R.string.verification_emoji_59)
+ 60 -> EmojiResource(R.drawable.ic_verification_60, R.string.verification_emoji_60)
+ 61 -> EmojiResource(R.drawable.ic_verification_61, R.string.verification_emoji_61)
+ 62 -> EmojiResource(R.drawable.ic_verification_62, R.string.verification_emoji_62)
+ /* 63 */ else -> EmojiResource(R.drawable.ic_verification_63, R.string.verification_emoji_63)
+ }
+}
diff --git a/features/verifysession/impl/src/main/kotlin/io/element/android/features/verifysession/impl/emoji/SasEmojisPreview.kt b/features/verifysession/impl/src/main/kotlin/io/element/android/features/verifysession/impl/emoji/SasEmojisPreview.kt
new file mode 100644
index 0000000000..0508aa66c3
--- /dev/null
+++ b/features/verifysession/impl/src/main/kotlin/io/element/android/features/verifysession/impl/emoji/SasEmojisPreview.kt
@@ -0,0 +1,75 @@
+/*
+ * 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.verifysession.impl.emoji
+
+import androidx.compose.foundation.Image
+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.foundation.layout.size
+import androidx.compose.runtime.Composable
+import androidx.compose.ui.Alignment
+import androidx.compose.ui.Modifier
+import androidx.compose.ui.res.painterResource
+import androidx.compose.ui.res.stringResource
+import androidx.compose.ui.text.style.TextOverflow
+import androidx.compose.ui.unit.dp
+import androidx.compose.ui.unit.sp
+import io.element.android.compound.theme.ElementTheme
+import io.element.android.libraries.designsystem.preview.ElementPreview
+import io.element.android.libraries.designsystem.preview.PreviewsDayNight
+import io.element.android.libraries.designsystem.theme.components.Text
+
+@Composable
+@PreviewsDayNight
+internal fun SasEmojisPreview() = ElementPreview {
+ Column(
+ modifier = Modifier.padding(8.dp),
+ verticalArrangement = Arrangement.spacedBy(2.dp),
+ ) {
+ List(64) { it to it.toEmojiResource() }
+ .chunked(8)
+ .forEach {
+ Row(
+ horizontalArrangement = Arrangement.spacedBy(2.dp),
+ ) {
+ it.forEach { emoji ->
+ Column(
+ modifier = Modifier.weight(1f),
+ horizontalAlignment = Alignment.CenterHorizontally,
+ ) {
+ Image(
+ painter = painterResource(id = emoji.second.drawableRes),
+ contentDescription = null,
+ modifier = Modifier
+ .size(32.dp)
+ )
+ Text(
+ text = emoji.first.toString() + ":" + stringResource(id = emoji.second.nameRes),
+ maxLines = 1,
+ overflow = TextOverflow.Ellipsis,
+ style = ElementTheme.typography.fontBodySmRegular.copy(
+ fontSize = 8.sp
+ )
+ )
+ }
+ }
+ }
+ }
+ }
+}
diff --git a/features/verifysession/impl/src/main/res/drawable/ic_verification_00.xml b/features/verifysession/impl/src/main/res/drawable/ic_verification_00.xml
new file mode 100644
index 0000000000..8346a5ebee
--- /dev/null
+++ b/features/verifysession/impl/src/main/res/drawable/ic_verification_00.xml
@@ -0,0 +1,45 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/features/verifysession/impl/src/main/res/drawable/ic_verification_01.xml b/features/verifysession/impl/src/main/res/drawable/ic_verification_01.xml
new file mode 100644
index 0000000000..b34cf63d98
--- /dev/null
+++ b/features/verifysession/impl/src/main/res/drawable/ic_verification_01.xml
@@ -0,0 +1,36 @@
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/features/verifysession/impl/src/main/res/drawable/ic_verification_02.xml b/features/verifysession/impl/src/main/res/drawable/ic_verification_02.xml
new file mode 100644
index 0000000000..b97a508fc2
--- /dev/null
+++ b/features/verifysession/impl/src/main/res/drawable/ic_verification_02.xml
@@ -0,0 +1,54 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/features/verifysession/impl/src/main/res/drawable/ic_verification_03.xml b/features/verifysession/impl/src/main/res/drawable/ic_verification_03.xml
new file mode 100644
index 0000000000..bedf0f6f46
--- /dev/null
+++ b/features/verifysession/impl/src/main/res/drawable/ic_verification_03.xml
@@ -0,0 +1,33 @@
+
+
+
+
+
+
+
+
+
+
+
diff --git a/features/verifysession/impl/src/main/res/drawable/ic_verification_04.xml b/features/verifysession/impl/src/main/res/drawable/ic_verification_04.xml
new file mode 100644
index 0000000000..19cef5d339
--- /dev/null
+++ b/features/verifysession/impl/src/main/res/drawable/ic_verification_04.xml
@@ -0,0 +1,30 @@
+
+
+
+
+
+
+
+
+
+
diff --git a/features/verifysession/impl/src/main/res/drawable/ic_verification_05.xml b/features/verifysession/impl/src/main/res/drawable/ic_verification_05.xml
new file mode 100644
index 0000000000..c31bd06c52
--- /dev/null
+++ b/features/verifysession/impl/src/main/res/drawable/ic_verification_05.xml
@@ -0,0 +1,21 @@
+
+
+
+
+
+
+
diff --git a/features/verifysession/impl/src/main/res/drawable/ic_verification_06.xml b/features/verifysession/impl/src/main/res/drawable/ic_verification_06.xml
new file mode 100644
index 0000000000..d0a2de42cb
--- /dev/null
+++ b/features/verifysession/impl/src/main/res/drawable/ic_verification_06.xml
@@ -0,0 +1,15 @@
+
+
+
+
+
diff --git a/features/verifysession/impl/src/main/res/drawable/ic_verification_07.xml b/features/verifysession/impl/src/main/res/drawable/ic_verification_07.xml
new file mode 100644
index 0000000000..c8ff75c999
--- /dev/null
+++ b/features/verifysession/impl/src/main/res/drawable/ic_verification_07.xml
@@ -0,0 +1,27 @@
+
+
+
+
+
+
+
+
+
diff --git a/features/verifysession/impl/src/main/res/drawable/ic_verification_08.xml b/features/verifysession/impl/src/main/res/drawable/ic_verification_08.xml
new file mode 100644
index 0000000000..ab1e718c44
--- /dev/null
+++ b/features/verifysession/impl/src/main/res/drawable/ic_verification_08.xml
@@ -0,0 +1,42 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/features/verifysession/impl/src/main/res/drawable/ic_verification_09.xml b/features/verifysession/impl/src/main/res/drawable/ic_verification_09.xml
new file mode 100644
index 0000000000..cb7ad563f0
--- /dev/null
+++ b/features/verifysession/impl/src/main/res/drawable/ic_verification_09.xml
@@ -0,0 +1,18 @@
+
+
+
+
+
+
diff --git a/features/verifysession/impl/src/main/res/drawable/ic_verification_10.xml b/features/verifysession/impl/src/main/res/drawable/ic_verification_10.xml
new file mode 100644
index 0000000000..fb2e05760f
--- /dev/null
+++ b/features/verifysession/impl/src/main/res/drawable/ic_verification_10.xml
@@ -0,0 +1,21 @@
+
+
+
+
+
+
+
diff --git a/features/verifysession/impl/src/main/res/drawable/ic_verification_11.xml b/features/verifysession/impl/src/main/res/drawable/ic_verification_11.xml
new file mode 100644
index 0000000000..1cedc1b6ad
--- /dev/null
+++ b/features/verifysession/impl/src/main/res/drawable/ic_verification_11.xml
@@ -0,0 +1,21 @@
+
+
+
+
+
+
+
diff --git a/features/verifysession/impl/src/main/res/drawable/ic_verification_12.xml b/features/verifysession/impl/src/main/res/drawable/ic_verification_12.xml
new file mode 100644
index 0000000000..30907f2496
--- /dev/null
+++ b/features/verifysession/impl/src/main/res/drawable/ic_verification_12.xml
@@ -0,0 +1,24 @@
+
+
+
+
+
+
+
+
diff --git a/features/verifysession/impl/src/main/res/drawable/ic_verification_13.xml b/features/verifysession/impl/src/main/res/drawable/ic_verification_13.xml
new file mode 100644
index 0000000000..054760f3b8
--- /dev/null
+++ b/features/verifysession/impl/src/main/res/drawable/ic_verification_13.xml
@@ -0,0 +1,24 @@
+
+
+
+
+
+
+
+
diff --git a/features/verifysession/impl/src/main/res/drawable/ic_verification_14.xml b/features/verifysession/impl/src/main/res/drawable/ic_verification_14.xml
new file mode 100644
index 0000000000..d4b557a7ed
--- /dev/null
+++ b/features/verifysession/impl/src/main/res/drawable/ic_verification_14.xml
@@ -0,0 +1,39 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/features/verifysession/impl/src/main/res/drawable/ic_verification_15.xml b/features/verifysession/impl/src/main/res/drawable/ic_verification_15.xml
new file mode 100644
index 0000000000..8a91221a80
--- /dev/null
+++ b/features/verifysession/impl/src/main/res/drawable/ic_verification_15.xml
@@ -0,0 +1,15 @@
+
+
+
+
+
diff --git a/features/verifysession/impl/src/main/res/drawable/ic_verification_16.xml b/features/verifysession/impl/src/main/res/drawable/ic_verification_16.xml
new file mode 100644
index 0000000000..c5acc19a72
--- /dev/null
+++ b/features/verifysession/impl/src/main/res/drawable/ic_verification_16.xml
@@ -0,0 +1,54 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/features/verifysession/impl/src/main/res/drawable/ic_verification_17.xml b/features/verifysession/impl/src/main/res/drawable/ic_verification_17.xml
new file mode 100644
index 0000000000..ce8aff0657
--- /dev/null
+++ b/features/verifysession/impl/src/main/res/drawable/ic_verification_17.xml
@@ -0,0 +1,51 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/features/verifysession/impl/src/main/res/drawable/ic_verification_18.xml b/features/verifysession/impl/src/main/res/drawable/ic_verification_18.xml
new file mode 100644
index 0000000000..72f7036856
--- /dev/null
+++ b/features/verifysession/impl/src/main/res/drawable/ic_verification_18.xml
@@ -0,0 +1,24 @@
+
+
+
+
+
+
+
+
diff --git a/features/verifysession/impl/src/main/res/drawable/ic_verification_19.xml b/features/verifysession/impl/src/main/res/drawable/ic_verification_19.xml
new file mode 100644
index 0000000000..2a07829cb3
--- /dev/null
+++ b/features/verifysession/impl/src/main/res/drawable/ic_verification_19.xml
@@ -0,0 +1,15 @@
+
+
+
+
+
diff --git a/features/verifysession/impl/src/main/res/drawable/ic_verification_20.xml b/features/verifysession/impl/src/main/res/drawable/ic_verification_20.xml
new file mode 100644
index 0000000000..3f5abe6ae3
--- /dev/null
+++ b/features/verifysession/impl/src/main/res/drawable/ic_verification_20.xml
@@ -0,0 +1,12 @@
+
+
+
+
diff --git a/features/verifysession/impl/src/main/res/drawable/ic_verification_21.xml b/features/verifysession/impl/src/main/res/drawable/ic_verification_21.xml
new file mode 100644
index 0000000000..d390bd6e87
--- /dev/null
+++ b/features/verifysession/impl/src/main/res/drawable/ic_verification_21.xml
@@ -0,0 +1,12 @@
+
+
+
+
diff --git a/features/verifysession/impl/src/main/res/drawable/ic_verification_22.xml b/features/verifysession/impl/src/main/res/drawable/ic_verification_22.xml
new file mode 100644
index 0000000000..ebf42039b1
--- /dev/null
+++ b/features/verifysession/impl/src/main/res/drawable/ic_verification_22.xml
@@ -0,0 +1,12 @@
+
+
+
+
diff --git a/features/verifysession/impl/src/main/res/drawable/ic_verification_23.xml b/features/verifysession/impl/src/main/res/drawable/ic_verification_23.xml
new file mode 100644
index 0000000000..cdd3cb1b9f
--- /dev/null
+++ b/features/verifysession/impl/src/main/res/drawable/ic_verification_23.xml
@@ -0,0 +1,36 @@
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/features/verifysession/impl/src/main/res/drawable/ic_verification_24.xml b/features/verifysession/impl/src/main/res/drawable/ic_verification_24.xml
new file mode 100644
index 0000000000..54e0f9a3c0
--- /dev/null
+++ b/features/verifysession/impl/src/main/res/drawable/ic_verification_24.xml
@@ -0,0 +1,15 @@
+
+
+
+
+
diff --git a/features/verifysession/impl/src/main/res/drawable/ic_verification_25.xml b/features/verifysession/impl/src/main/res/drawable/ic_verification_25.xml
new file mode 100644
index 0000000000..0eeb290d9d
--- /dev/null
+++ b/features/verifysession/impl/src/main/res/drawable/ic_verification_25.xml
@@ -0,0 +1,15 @@
+
+
+
+
+
diff --git a/features/verifysession/impl/src/main/res/drawable/ic_verification_26.xml b/features/verifysession/impl/src/main/res/drawable/ic_verification_26.xml
new file mode 100644
index 0000000000..d863d03c2a
--- /dev/null
+++ b/features/verifysession/impl/src/main/res/drawable/ic_verification_26.xml
@@ -0,0 +1,18 @@
+
+
+
+
+
+
diff --git a/features/verifysession/impl/src/main/res/drawable/ic_verification_27.xml b/features/verifysession/impl/src/main/res/drawable/ic_verification_27.xml
new file mode 100644
index 0000000000..a514aeb3d6
--- /dev/null
+++ b/features/verifysession/impl/src/main/res/drawable/ic_verification_27.xml
@@ -0,0 +1,21 @@
+
+
+
+
+
+
+
diff --git a/features/verifysession/impl/src/main/res/drawable/ic_verification_28.xml b/features/verifysession/impl/src/main/res/drawable/ic_verification_28.xml
new file mode 100644
index 0000000000..9ebb3c0904
--- /dev/null
+++ b/features/verifysession/impl/src/main/res/drawable/ic_verification_28.xml
@@ -0,0 +1,42 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/features/verifysession/impl/src/main/res/drawable/ic_verification_29.xml b/features/verifysession/impl/src/main/res/drawable/ic_verification_29.xml
new file mode 100644
index 0000000000..d37bcc33d1
--- /dev/null
+++ b/features/verifysession/impl/src/main/res/drawable/ic_verification_29.xml
@@ -0,0 +1,9 @@
+
+
+
diff --git a/features/verifysession/impl/src/main/res/drawable/ic_verification_30.xml b/features/verifysession/impl/src/main/res/drawable/ic_verification_30.xml
new file mode 100644
index 0000000000..28c2394b99
--- /dev/null
+++ b/features/verifysession/impl/src/main/res/drawable/ic_verification_30.xml
@@ -0,0 +1,21 @@
+
+
+
+
+
+
+
diff --git a/features/verifysession/impl/src/main/res/drawable/ic_verification_31.xml b/features/verifysession/impl/src/main/res/drawable/ic_verification_31.xml
new file mode 100644
index 0000000000..a53cfe99c0
--- /dev/null
+++ b/features/verifysession/impl/src/main/res/drawable/ic_verification_31.xml
@@ -0,0 +1,48 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/features/verifysession/impl/src/main/res/drawable/ic_verification_32.xml b/features/verifysession/impl/src/main/res/drawable/ic_verification_32.xml
new file mode 100644
index 0000000000..15f980bdb1
--- /dev/null
+++ b/features/verifysession/impl/src/main/res/drawable/ic_verification_32.xml
@@ -0,0 +1,15 @@
+
+
+
+
+
diff --git a/features/verifysession/impl/src/main/res/drawable/ic_verification_33.xml b/features/verifysession/impl/src/main/res/drawable/ic_verification_33.xml
new file mode 100644
index 0000000000..8913d1ffd7
--- /dev/null
+++ b/features/verifysession/impl/src/main/res/drawable/ic_verification_33.xml
@@ -0,0 +1,12 @@
+
+
+
+
diff --git a/features/verifysession/impl/src/main/res/drawable/ic_verification_34.xml b/features/verifysession/impl/src/main/res/drawable/ic_verification_34.xml
new file mode 100644
index 0000000000..ba3c4313a3
--- /dev/null
+++ b/features/verifysession/impl/src/main/res/drawable/ic_verification_34.xml
@@ -0,0 +1,9 @@
+
+
+
diff --git a/features/verifysession/impl/src/main/res/drawable/ic_verification_35.xml b/features/verifysession/impl/src/main/res/drawable/ic_verification_35.xml
new file mode 100644
index 0000000000..4f7bc1a24f
--- /dev/null
+++ b/features/verifysession/impl/src/main/res/drawable/ic_verification_35.xml
@@ -0,0 +1,42 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/features/verifysession/impl/src/main/res/drawable/ic_verification_36.xml b/features/verifysession/impl/src/main/res/drawable/ic_verification_36.xml
new file mode 100644
index 0000000000..9761204ab6
--- /dev/null
+++ b/features/verifysession/impl/src/main/res/drawable/ic_verification_36.xml
@@ -0,0 +1,12 @@
+
+
+
+
diff --git a/features/verifysession/impl/src/main/res/drawable/ic_verification_37.xml b/features/verifysession/impl/src/main/res/drawable/ic_verification_37.xml
new file mode 100644
index 0000000000..ac1267cd3b
--- /dev/null
+++ b/features/verifysession/impl/src/main/res/drawable/ic_verification_37.xml
@@ -0,0 +1,18 @@
+
+
+
+
+
+
diff --git a/features/verifysession/impl/src/main/res/drawable/ic_verification_38.xml b/features/verifysession/impl/src/main/res/drawable/ic_verification_38.xml
new file mode 100644
index 0000000000..8bb37a35bb
--- /dev/null
+++ b/features/verifysession/impl/src/main/res/drawable/ic_verification_38.xml
@@ -0,0 +1,15 @@
+
+
+
+
+
diff --git a/features/verifysession/impl/src/main/res/drawable/ic_verification_39.xml b/features/verifysession/impl/src/main/res/drawable/ic_verification_39.xml
new file mode 100644
index 0000000000..48d7150c36
--- /dev/null
+++ b/features/verifysession/impl/src/main/res/drawable/ic_verification_39.xml
@@ -0,0 +1,27 @@
+
+
+
+
+
+
+
+
+
diff --git a/features/verifysession/impl/src/main/res/drawable/ic_verification_40.xml b/features/verifysession/impl/src/main/res/drawable/ic_verification_40.xml
new file mode 100644
index 0000000000..d18c6e860a
--- /dev/null
+++ b/features/verifysession/impl/src/main/res/drawable/ic_verification_40.xml
@@ -0,0 +1,21 @@
+
+
+
+
+
+
+
diff --git a/features/verifysession/impl/src/main/res/drawable/ic_verification_41.xml b/features/verifysession/impl/src/main/res/drawable/ic_verification_41.xml
new file mode 100644
index 0000000000..18f3149500
--- /dev/null
+++ b/features/verifysession/impl/src/main/res/drawable/ic_verification_41.xml
@@ -0,0 +1,21 @@
+
+
+
+
+
+
+
diff --git a/features/verifysession/impl/src/main/res/drawable/ic_verification_42.xml b/features/verifysession/impl/src/main/res/drawable/ic_verification_42.xml
new file mode 100644
index 0000000000..8e3ecc00c0
--- /dev/null
+++ b/features/verifysession/impl/src/main/res/drawable/ic_verification_42.xml
@@ -0,0 +1,24 @@
+
+
+
+
+
+
+
+
diff --git a/features/verifysession/impl/src/main/res/drawable/ic_verification_43.xml b/features/verifysession/impl/src/main/res/drawable/ic_verification_43.xml
new file mode 100644
index 0000000000..3b9f51fca5
--- /dev/null
+++ b/features/verifysession/impl/src/main/res/drawable/ic_verification_43.xml
@@ -0,0 +1,24 @@
+
+
+
+
+
+
+
+
diff --git a/features/verifysession/impl/src/main/res/drawable/ic_verification_44.xml b/features/verifysession/impl/src/main/res/drawable/ic_verification_44.xml
new file mode 100644
index 0000000000..e8f89859d6
--- /dev/null
+++ b/features/verifysession/impl/src/main/res/drawable/ic_verification_44.xml
@@ -0,0 +1,9 @@
+
+
+
diff --git a/features/verifysession/impl/src/main/res/drawable/ic_verification_45.xml b/features/verifysession/impl/src/main/res/drawable/ic_verification_45.xml
new file mode 100644
index 0000000000..98e68c2071
--- /dev/null
+++ b/features/verifysession/impl/src/main/res/drawable/ic_verification_45.xml
@@ -0,0 +1,21 @@
+
+
+
+
+
+
+
diff --git a/features/verifysession/impl/src/main/res/drawable/ic_verification_46.xml b/features/verifysession/impl/src/main/res/drawable/ic_verification_46.xml
new file mode 100644
index 0000000000..de3979434f
--- /dev/null
+++ b/features/verifysession/impl/src/main/res/drawable/ic_verification_46.xml
@@ -0,0 +1,12 @@
+
+
+
+
diff --git a/features/verifysession/impl/src/main/res/drawable/ic_verification_47.xml b/features/verifysession/impl/src/main/res/drawable/ic_verification_47.xml
new file mode 100644
index 0000000000..4cd1d033f7
--- /dev/null
+++ b/features/verifysession/impl/src/main/res/drawable/ic_verification_47.xml
@@ -0,0 +1,9 @@
+
+
+
diff --git a/features/verifysession/impl/src/main/res/drawable/ic_verification_48.xml b/features/verifysession/impl/src/main/res/drawable/ic_verification_48.xml
new file mode 100644
index 0000000000..7b70654d52
--- /dev/null
+++ b/features/verifysession/impl/src/main/res/drawable/ic_verification_48.xml
@@ -0,0 +1,12 @@
+
+
+
+
diff --git a/features/verifysession/impl/src/main/res/drawable/ic_verification_49.xml b/features/verifysession/impl/src/main/res/drawable/ic_verification_49.xml
new file mode 100644
index 0000000000..7beda09c4e
--- /dev/null
+++ b/features/verifysession/impl/src/main/res/drawable/ic_verification_49.xml
@@ -0,0 +1,15 @@
+
+
+
+
+
diff --git a/features/verifysession/impl/src/main/res/drawable/ic_verification_50.xml b/features/verifysession/impl/src/main/res/drawable/ic_verification_50.xml
new file mode 100644
index 0000000000..250388dc4a
--- /dev/null
+++ b/features/verifysession/impl/src/main/res/drawable/ic_verification_50.xml
@@ -0,0 +1,24 @@
+
+
+
+
+
+
+
+
diff --git a/features/verifysession/impl/src/main/res/drawable/ic_verification_51.xml b/features/verifysession/impl/src/main/res/drawable/ic_verification_51.xml
new file mode 100644
index 0000000000..e317ce1642
--- /dev/null
+++ b/features/verifysession/impl/src/main/res/drawable/ic_verification_51.xml
@@ -0,0 +1,72 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/features/verifysession/impl/src/main/res/drawable/ic_verification_52.xml b/features/verifysession/impl/src/main/res/drawable/ic_verification_52.xml
new file mode 100644
index 0000000000..1427e793c5
--- /dev/null
+++ b/features/verifysession/impl/src/main/res/drawable/ic_verification_52.xml
@@ -0,0 +1,27 @@
+
+
+
+
+
+
+
+
+
diff --git a/features/verifysession/impl/src/main/res/drawable/ic_verification_53.xml b/features/verifysession/impl/src/main/res/drawable/ic_verification_53.xml
new file mode 100644
index 0000000000..72026cd7a0
--- /dev/null
+++ b/features/verifysession/impl/src/main/res/drawable/ic_verification_53.xml
@@ -0,0 +1,18 @@
+
+
+
+
+
+
diff --git a/features/verifysession/impl/src/main/res/drawable/ic_verification_54.xml b/features/verifysession/impl/src/main/res/drawable/ic_verification_54.xml
new file mode 100644
index 0000000000..4097ed9030
--- /dev/null
+++ b/features/verifysession/impl/src/main/res/drawable/ic_verification_54.xml
@@ -0,0 +1,24 @@
+
+
+
+
+
+
+
+
diff --git a/features/verifysession/impl/src/main/res/drawable/ic_verification_55.xml b/features/verifysession/impl/src/main/res/drawable/ic_verification_55.xml
new file mode 100644
index 0000000000..631da7320d
--- /dev/null
+++ b/features/verifysession/impl/src/main/res/drawable/ic_verification_55.xml
@@ -0,0 +1,18 @@
+
+
+
+
+
+
diff --git a/features/verifysession/impl/src/main/res/drawable/ic_verification_56.xml b/features/verifysession/impl/src/main/res/drawable/ic_verification_56.xml
new file mode 100644
index 0000000000..b12c6d245b
--- /dev/null
+++ b/features/verifysession/impl/src/main/res/drawable/ic_verification_56.xml
@@ -0,0 +1,15 @@
+
+
+
+
+
diff --git a/features/verifysession/impl/src/main/res/drawable/ic_verification_57.xml b/features/verifysession/impl/src/main/res/drawable/ic_verification_57.xml
new file mode 100644
index 0000000000..2622fbe416
--- /dev/null
+++ b/features/verifysession/impl/src/main/res/drawable/ic_verification_57.xml
@@ -0,0 +1,51 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/features/verifysession/impl/src/main/res/drawable/ic_verification_58.xml b/features/verifysession/impl/src/main/res/drawable/ic_verification_58.xml
new file mode 100644
index 0000000000..84f95a8592
--- /dev/null
+++ b/features/verifysession/impl/src/main/res/drawable/ic_verification_58.xml
@@ -0,0 +1,21 @@
+
+
+
+
+
+
+
diff --git a/features/verifysession/impl/src/main/res/drawable/ic_verification_59.xml b/features/verifysession/impl/src/main/res/drawable/ic_verification_59.xml
new file mode 100644
index 0000000000..2f29828bcf
--- /dev/null
+++ b/features/verifysession/impl/src/main/res/drawable/ic_verification_59.xml
@@ -0,0 +1,15 @@
+
+
+
+
+
diff --git a/features/verifysession/impl/src/main/res/drawable/ic_verification_60.xml b/features/verifysession/impl/src/main/res/drawable/ic_verification_60.xml
new file mode 100644
index 0000000000..b89d033b9e
--- /dev/null
+++ b/features/verifysession/impl/src/main/res/drawable/ic_verification_60.xml
@@ -0,0 +1,12 @@
+
+
+
+
diff --git a/features/verifysession/impl/src/main/res/drawable/ic_verification_61.xml b/features/verifysession/impl/src/main/res/drawable/ic_verification_61.xml
new file mode 100644
index 0000000000..cbc43e7601
--- /dev/null
+++ b/features/verifysession/impl/src/main/res/drawable/ic_verification_61.xml
@@ -0,0 +1,15 @@
+
+
+
+
+
diff --git a/features/verifysession/impl/src/main/res/drawable/ic_verification_62.xml b/features/verifysession/impl/src/main/res/drawable/ic_verification_62.xml
new file mode 100644
index 0000000000..9320766492
--- /dev/null
+++ b/features/verifysession/impl/src/main/res/drawable/ic_verification_62.xml
@@ -0,0 +1,12 @@
+
+
+
+
diff --git a/features/verifysession/impl/src/main/res/drawable/ic_verification_63.xml b/features/verifysession/impl/src/main/res/drawable/ic_verification_63.xml
new file mode 100644
index 0000000000..f10e4606a9
--- /dev/null
+++ b/features/verifysession/impl/src/main/res/drawable/ic_verification_63.xml
@@ -0,0 +1,18 @@
+
+
+
+
+
+
diff --git a/features/verifysession/impl/src/main/res/values-ar/strings_sas.xml b/features/verifysession/impl/src/main/res/values-ar/strings_sas.xml
new file mode 100644
index 0000000000..7bab8eec98
--- /dev/null
+++ b/features/verifysession/impl/src/main/res/values-ar/strings_sas.xml
@@ -0,0 +1,68 @@
+
+
+
+ كلب
+ هِرَّة
+ أَسَد
+ حِصَان
+ حصان وحيد القرن
+ خِنزِير
+ فِيل
+ أَرنَب
+ باندَا
+ دِيك
+ بطريق
+ سُلحفاة
+ سَمَكة
+ أُخطُبُوط
+ فَرَاشَة
+ زَهرَة
+ شَجَرَة
+ صبار
+ فُطر
+ كُرَةٌ أرضِيَّة
+ قَمَر
+ سَحابَة
+ نار
+ مَوزَة
+ تُفَّاحَة
+ فَراوِلَة
+ ذُرَة
+ بِيتزا
+ كَعكَة
+ قَلب
+ اِبتِسَامَة
+ رُوبُوت
+ قُبَّعَة
+ نَظَّارَة
+ مِفتَاحُ رَبط
+ سانتا
+ رَفعُ إِبهَام
+ مِظَلَّة
+ سَاعَةٌ رَملِيَّة
+ سَاعَة
+ هَدِيَّة
+ مِصبَاح
+ كِتَاب
+ قَلَمُ رَصاص
+ مِشبَكُ وَرَق
+ مِقَصّ
+ قُفل
+ مِفتَاح
+ مِطرَقَة
+ تِلِفُون
+ عَلَم
+ قِطَار
+ دَرّاجَة
+ طَائِرة
+ صَارُوخ
+ كَأسُ النَّصر
+ كُرَة
+ غيتار
+ بُوق
+ جَرَس
+ مِرسَاة
+ سَمّاعَة رَأس
+ مُجَلَّد
+ دَبُّوس
+
diff --git a/features/verifysession/impl/src/main/res/values-bg/strings_sas.xml b/features/verifysession/impl/src/main/res/values-bg/strings_sas.xml
new file mode 100644
index 0000000000..cae262847f
--- /dev/null
+++ b/features/verifysession/impl/src/main/res/values-bg/strings_sas.xml
@@ -0,0 +1,68 @@
+
+
+
+ Куче
+ Котка
+ Лъв
+ Кон
+ Еднорог
+ Прасе
+ Слон
+ Заек
+ Панда
+ Петел
+ Пингвин
+ Костенурка
+ Риба
+ Октопод
+ Пеперуда
+ Цвете
+ Дърво
+ Кактус
+ Гъба
+ Глобус
+ Луна
+ Облак
+ Огън
+ Банан
+ Ябълка
+ Ягода
+ Царевица
+ Пица
+ Торта
+ Сърце
+ Усмивка
+ Робот
+ Шапка
+ Очила
+ Гаечен ключ
+ Дядо Коледа
+ Палец нагоре
+ Чадър
+ Пясъчен часовник
+ Часовник
+ Подарък
+ Лампа
+ Книга
+ Молив
+ Кламер
+ Ножици
+ Катинар
+ Ключ
+ Чук
+ Телефон
+ Флаг
+ Влак
+ Колело
+ Самолет
+ Ракета
+ Трофей
+ Топка
+ Китара
+ Тромпет
+ Звънец
+ Котва
+ Слушалки
+ Папка
+ Кабърче
+
diff --git a/features/verifysession/impl/src/main/res/values-ca/strings_sas.xml b/features/verifysession/impl/src/main/res/values-ca/strings_sas.xml
new file mode 100644
index 0000000000..07201480a8
--- /dev/null
+++ b/features/verifysession/impl/src/main/res/values-ca/strings_sas.xml
@@ -0,0 +1,68 @@
+
+
+
+ Gos
+ Gat
+ Lleó
+ Cavall
+ Unicorn
+ Porc
+ Elefant
+ Conill
+ Panda
+ Gall
+ Pingüí
+ Tortuga
+ Peix
+ Pop
+ Papallona
+ Flor
+ Arbre
+ Cactus
+ Bolet
+ Globus terraqüi
+ Lluna
+ Núvol
+ Foc
+ Plàtan
+ Poma
+ Maduixa
+ Blat de moro
+ Pizza
+ Pastís
+ Cor
+ Somrient
+ Robot
+ Barret
+ Ulleres
+ Clau anglesa
+ Pare Noél
+ Polzes amunt
+ Paraigües
+ Rellotge de sorra
+ Rellotge
+ Regal
+ Bombeta
+ Llibre
+ Llapis
+ Clip
+ Tisores
+ Cadenat
+ Clau
+ Martell
+ Telèfon
+ Bandera
+ Tren
+ Bicicleta
+ Avió
+ Coet
+ Trofeu
+ Pilota
+ Guitarra
+ Trompeta
+ Campana
+ Àncora
+ Auriculars
+ Carpeta
+ Xinxeta
+
diff --git a/features/verifysession/impl/src/main/res/values-cs/strings_sas.xml b/features/verifysession/impl/src/main/res/values-cs/strings_sas.xml
new file mode 100644
index 0000000000..6f0eaa0703
--- /dev/null
+++ b/features/verifysession/impl/src/main/res/values-cs/strings_sas.xml
@@ -0,0 +1,68 @@
+
+
+
+ Pes
+ Kočka
+ Lev
+ Kůň
+ Jednorožec
+ Prase
+ Slon
+ Králík
+ Panda
+ Kohout
+ Tučňák
+ Želva
+ Ryba
+ Chobotnice
+ Motýl
+ Květina
+ Strom
+ Kaktus
+ Houba
+ Zeměkoule
+ Měsíc
+ Mrak
+ Oheň
+ Banán
+ Jablko
+ Jahoda
+ Kukuřice
+ Pizza
+ Dort
+ Srdce
+ Smajlík
+ Robot
+ Klobouk
+ Brýle
+ Klíč
+ Mikuláš
+ Palec nahoru
+ Deštník
+ Přesýpací hodiny
+ Hodiny
+ Dárek
+ Žárovka
+ Kniha
+ Tužka
+ Sponka
+ Nůžky
+ Zámek
+ Klíč ke dveřím
+ Kladivo
+ Telefon
+ Vlajka
+ Vlak
+ Kolo
+ Letadlo
+ Raketa
+ Pohár
+ Míč
+ Kytara
+ Trumpeta
+ Zvonek
+ Kotva
+ Sluchátka
+ Složka
+ Špendlík
+
diff --git a/features/verifysession/impl/src/main/res/values-de/strings_sas.xml b/features/verifysession/impl/src/main/res/values-de/strings_sas.xml
new file mode 100644
index 0000000000..fc81895816
--- /dev/null
+++ b/features/verifysession/impl/src/main/res/values-de/strings_sas.xml
@@ -0,0 +1,68 @@
+
+
+
+ Hund
+ Katze
+ Löwe
+ Pferd
+ Einhorn
+ Schwein
+ Elefant
+ Hase
+ Panda
+ Hahn
+ Pinguin
+ Schildkröte
+ Fisch
+ Oktopus
+ Schmetterling
+ Blume
+ Baum
+ Kaktus
+ Pilz
+ Globus
+ Mond
+ Wolke
+ Feuer
+ Banane
+ Apfel
+ Erdbeere
+ Mais
+ Pizza
+ Kuchen
+ Herz
+ Lächeln
+ Roboter
+ Hut
+ Brille
+ Schraubenschlüssel
+ Weihnachtsmann
+ Daumen Hoch
+ Regenschirm
+ Sanduhr
+ Uhr
+ Geschenk
+ Glühbirne
+ Buch
+ Bleistift
+ Büroklammer
+ Schere
+ Schloss
+ Schlüssel
+ Hammer
+ Telefon
+ Flagge
+ Zug
+ Fahrrad
+ Flugzeug
+ Rakete
+ Pokal
+ Ball
+ Gitarre
+ Trompete
+ Glocke
+ Anker
+ Kopfhörer
+ Ordner
+ Stecknadel
+
diff --git a/features/verifysession/impl/src/main/res/values-de/translations.xml b/features/verifysession/impl/src/main/res/values-de/translations.xml
index 7ac1ddce6f..d3d225969b 100644
--- a/features/verifysession/impl/src/main/res/values-de/translations.xml
+++ b/features/verifysession/impl/src/main/res/values-de/translations.xml
@@ -9,6 +9,7 @@
"Verifizierung wiederholen"
"Ich bin bereit"
"Warten auf eine Übereinstimmung"
+ "Vergleiche eine spezielle Reihe von Emojis."
"Vergleiche die einzelnen Emojis und stelle sicher, dass sie in der gleichen Reihenfolge erscheinen."
"Sie stimmen nicht überein"
"Sie stimmen überein"
diff --git a/features/verifysession/impl/src/main/res/values-eo/strings_sas.xml b/features/verifysession/impl/src/main/res/values-eo/strings_sas.xml
new file mode 100644
index 0000000000..d9efa50fb7
--- /dev/null
+++ b/features/verifysession/impl/src/main/res/values-eo/strings_sas.xml
@@ -0,0 +1,68 @@
+
+
+
+ Hundo
+ Kato
+ Leono
+ Ĉevalo
+ Unukorno
+ Porko
+ Elefanto
+ Kuniklo
+ Pando
+ Virkoko
+ Pingveno
+ Testudo
+ Fiŝo
+ Polpo
+ Papilio
+ Floro
+ Arbo
+ Kakto
+ Fungo
+ Globo
+ Luno
+ Nubo
+ Fajro
+ Banano
+ Pomo
+ Frago
+ Maizo
+ Pico
+ Torto
+ Koro
+ Rideto
+ Roboto
+ Ĉapelo
+ Okulvitroj
+ Ŝraŭbŝlosilo
+ Kristnaska viro
+ Dikfingro supren
+ Ombrelo
+ Sablohorloĝo
+ Horloĝo
+ Donaco
+ Lampo
+ Libro
+ Krajono
+ Paperkuntenilo
+ Tondilo
+ Seruro
+ Ŝlosilo
+ Martelo
+ Telefono
+ Flago
+ Vagonaro
+ Biciklo
+ Aviadilo
+ Raketo
+ Trofeo
+ Pilko
+ Gitaro
+ Trumpeto
+ Sonorilo
+ Ankro
+ Kapaŭdilo
+ Dosierujo
+ Pinglo
+
diff --git a/features/verifysession/impl/src/main/res/values-es/strings_sas.xml b/features/verifysession/impl/src/main/res/values-es/strings_sas.xml
new file mode 100644
index 0000000000..cc78a46ec3
--- /dev/null
+++ b/features/verifysession/impl/src/main/res/values-es/strings_sas.xml
@@ -0,0 +1,68 @@
+
+
+
+ Perro
+ Gato
+ León
+ Caballo
+ Unicornio
+ Cerdo
+ Elefante
+ Conejo
+ Panda
+ Gallo
+ Pingüino
+ Tortuga
+ Pez
+ Pulpo
+ Mariposa
+ Flor
+ Árbol
+ Cactus
+ Seta
+ Globo
+ Luna
+ Nube
+ Fuego
+ Plátano
+ Manzana
+ Fresa
+ Maíz
+ Pizza
+ Tarta
+ Corazón
+ Emoticono
+ Robot
+ Sombrero
+ Gafas
+ Llave inglesa
+ Papá Noel
+ Pulgar arriba
+ Paraguas
+ Reloj de arena
+ Reloj
+ Regalo
+ Bombilla
+ Libro
+ Lápiz
+ Clip
+ Tijeras
+ Candado
+ Llave
+ Martillo
+ Teléfono
+ Bandera
+ Tren
+ Bicicleta
+ Avión
+ Cohete
+ Trofeo
+ Bola
+ Guitarra
+ Trompeta
+ Campana
+ Ancla
+ Cascos
+ Carpeta
+ Alfiler
+
diff --git a/features/verifysession/impl/src/main/res/values-et/strings_sas.xml b/features/verifysession/impl/src/main/res/values-et/strings_sas.xml
new file mode 100644
index 0000000000..1223b67104
--- /dev/null
+++ b/features/verifysession/impl/src/main/res/values-et/strings_sas.xml
@@ -0,0 +1,68 @@
+
+
+
+ Koer
+ Kass
+ Lõvi
+ Hobune
+ Ükssarvik
+ Siga
+ Elevant
+ Jänes
+ Panda
+ Kukk
+ Pingviin
+ Kilpkonn
+ Kala
+ Kaheksajalg
+ Liblikas
+ Lill
+ Puu
+ Kaktus
+ Seen
+ Maakera
+ Kuu
+ Pilv
+ Tuli
+ Banaan
+ Õun
+ Maasikas
+ Mais
+ Pitsa
+ Kook
+ Süda
+ Smaili
+ Robot
+ Kübar
+ Prillid
+ Mutrivõti
+ Jõuluvana
+ Pöidlad püsti
+ Vihmavari
+ Liivakell
+ Kell
+ Kingitus
+ Lambipirn
+ Raamat
+ Pliiats
+ Kirjaklamber
+ Käärid
+ Lukk
+ Võti
+ Haamer
+ Telefon
+ Lipp
+ Rong
+ Jalgratas
+ Lennuk
+ Rakett
+ Auhind
+ Pall
+ Kitarr
+ Trompet
+ Kelluke
+ Ankur
+ Kõrvaklapid
+ Kaust
+ Nööpnõel
+
diff --git a/features/verifysession/impl/src/main/res/values-fa/strings_sas.xml b/features/verifysession/impl/src/main/res/values-fa/strings_sas.xml
new file mode 100644
index 0000000000..42efb247bb
--- /dev/null
+++ b/features/verifysession/impl/src/main/res/values-fa/strings_sas.xml
@@ -0,0 +1,68 @@
+
+
+
+ سگ
+ گربه
+ شیر
+ اسب
+ تک شاخ
+ خوک
+ فیل
+ خرگوش
+ پاندا
+ خروس
+ پنگوئن
+ لاکپشت
+ ماهی
+ اختاپوس
+ پروانه
+ گل
+ درخت
+ کاکتوس
+ قارچ
+ زمین
+ ماه
+ ابر
+ آتش
+ موز
+ سیب
+ توت فرنگی
+ ذرت
+ پیتزا
+ کیک
+ قلب
+ خنده
+ ربات
+ کلاه
+ عینک
+ آچار
+ بابا نوئل
+ لایک
+ چتر
+ ساعت شنی
+ ساعت
+ هدیه
+ لامپ
+ کتاب
+ مداد
+ گیره کاغذ
+ قیچی
+ قفل
+ کلید
+ چکش
+ تلفن
+ پرچم
+ قطار
+ دوچرخه
+ هواپیما
+ موشک
+ جام
+ توپ
+ گیتار
+ شیپور
+ زنگ
+ لنگر
+ هدفون
+ پوشه
+ سنجاق
+
diff --git a/features/verifysession/impl/src/main/res/values-fi/strings_sas.xml b/features/verifysession/impl/src/main/res/values-fi/strings_sas.xml
new file mode 100644
index 0000000000..c51447706e
--- /dev/null
+++ b/features/verifysession/impl/src/main/res/values-fi/strings_sas.xml
@@ -0,0 +1,68 @@
+
+
+
+ Koira
+ Kissa
+ Leijona
+ Hevonen
+ Yksisarvinen
+ Sika
+ Norsu
+ Kani
+ Panda
+ Kukko
+ Pingviini
+ Kilpikonna
+ Kala
+ Tursas
+ Perhonen
+ Kukka
+ Puu
+ Kaktus
+ Sieni
+ Maapallo
+ Kuu
+ Pilvi
+ Tuli
+ Banaani
+ Omena
+ Mansikka
+ Maissi
+ Pizza
+ Kakku
+ Sydän
+ Hymynaama
+ Robotti
+ Hattu
+ Silmälasit
+ Kiintoavain
+ Joulupukki
+ Peukalo ylös
+ Sateenvarjo
+ Tiimalasi
+ Pöytäkello
+ Lahja
+ Hehkulamppu
+ Kirja
+ Lyijykynä
+ Paperiliitin
+ Sakset
+ Lukko
+ Avain
+ Vasara
+ Puhelin
+ Lippu
+ Juna
+ Polkupyörä
+ Lentokone
+ Raketti
+ Palkinto
+ Pallo
+ Kitara
+ Trumpetti
+ Soittokello
+ Ankkuri
+ Kuulokkeet
+ Kansio
+ Nuppineula
+
diff --git a/features/verifysession/impl/src/main/res/values-fr/strings_sas.xml b/features/verifysession/impl/src/main/res/values-fr/strings_sas.xml
new file mode 100644
index 0000000000..3edd4b26fb
--- /dev/null
+++ b/features/verifysession/impl/src/main/res/values-fr/strings_sas.xml
@@ -0,0 +1,68 @@
+
+
+
+ Chien
+ Chat
+ Lion
+ Cheval
+ Licorne
+ Cochon
+ Éléphant
+ Lapin
+ Panda
+ Coq
+ Manchot
+ Tortue
+ Poisson
+ Poulpe
+ Papillon
+ Fleur
+ Arbre
+ Cactus
+ Champignon
+ Globe
+ Lune
+ Nuage
+ Feu
+ Banane
+ Pomme
+ Fraise
+ Maïs
+ Pizza
+ Gâteau
+ Cœur
+ Sourire
+ Robot
+ Chapeau
+ Lunettes
+ Clé à molette
+ Père Noël
+ Pouce en l’air
+ Parapluie
+ Sablier
+ Réveil
+ Cadeau
+ Ampoule
+ Livre
+ Crayon
+ Trombone
+ Ciseaux
+ Cadenas
+ Clé
+ Marteau
+ Téléphone
+ Drapeau
+ Train
+ Vélo
+ Avion
+ Fusée
+ Trophée
+ Ballon
+ Guitare
+ Trompette
+ Cloche
+ Ancre
+ Casque audio
+ Dossier
+ Punaise
+
diff --git a/features/verifysession/impl/src/main/res/values-fr/translations.xml b/features/verifysession/impl/src/main/res/values-fr/translations.xml
index 1ad0ffca42..8473d7d6bd 100644
--- a/features/verifysession/impl/src/main/res/values-fr/translations.xml
+++ b/features/verifysession/impl/src/main/res/values-fr/translations.xml
@@ -3,6 +3,8 @@
"Quelque chose ne va pas. Soit la demande a expiré, soit elle a été refusée."
"Confirmez que les emojis ci-dessous correspondent à ceux affichés sur votre autre session."
"Comparez les émojis"
+ "Confirmez que les nombres ci-dessous correspondent à ceux affichés sur votre autre session."
+ "Comparez les nombres"
"Votre nouvelle session est désormais vérifiée. Elle a accès à vos messages chiffrés et les autres utilisateurs la verront identifiée comme fiable."
"Prouvez qu’il s’agit bien de vous pour accéder à l’historique de vos messages chiffrés."
"Ouvrir une session existante"
diff --git a/features/verifysession/impl/src/main/res/values-hr/strings_sas.xml b/features/verifysession/impl/src/main/res/values-hr/strings_sas.xml
new file mode 100644
index 0000000000..22f3e62ae2
--- /dev/null
+++ b/features/verifysession/impl/src/main/res/values-hr/strings_sas.xml
@@ -0,0 +1,68 @@
+
+
+
+ pas
+ mačka
+ lav
+ konj
+ jednorog
+ svinja
+ slon
+ zec
+ panda
+ kokot
+ pingvin
+ kornjača
+ riba
+ hobotnica
+ leptir
+ svijet
+ drvo
+ kaktus
+ gljiva
+ Globus
+ mjesec
+ oblak
+ vatra
+ banana
+ jabuka
+ jagoda
+ kukuruza
+ pizza
+ torta
+ srca
+ smajlića
+ robot
+ kapa
+ naočale
+ ključ
+ deda Mraz
+ palac gore
+ kišobran
+ pješčani sat
+ sat
+ poklon
+ žarulja
+ knjiga
+ olovka
+ spajalica
+ škare
+ zaključati
+ ključ
+ čekić
+ telefon
+ zastava
+ vlak
+ bicikl
+ avion
+ raketa
+ trofej
+ lopta
+ gitara
+ truba
+ zvono
+ sidro
+ slušalice
+ mapu
+ pribadača
+
diff --git a/features/verifysession/impl/src/main/res/values-hu/strings_sas.xml b/features/verifysession/impl/src/main/res/values-hu/strings_sas.xml
new file mode 100644
index 0000000000..8137042078
--- /dev/null
+++ b/features/verifysession/impl/src/main/res/values-hu/strings_sas.xml
@@ -0,0 +1,68 @@
+
+
+
+ Kutya
+ Macska
+ Oroszlán
+ Ló
+ Egyszarvú
+ Malac
+ Elefánt
+ Nyúl
+ Panda
+ Kakas
+ Pingvin
+ Teknős
+ Hal
+ Polip
+ Pillangó
+ Virág
+ Fa
+ Kaktusz
+ Gomba
+ Földgömb
+ Hold
+ Felhő
+ Tűz
+ Banán
+ Alma
+ Eper
+ Kukorica
+ Pizza
+ Süti
+ Szív
+ Mosoly
+ Robot
+ Kalap
+ Szemüveg
+ Csavarkulcs
+ Télapó
+ Hüvelykujj fel
+ Esernyő
+ Homokóra
+ Óra
+ Ajándék
+ Égő
+ Könyv
+ Ceruza
+ Gémkapocs
+ Olló
+ Lakat
+ Kulcs
+ Kalapács
+ Telefon
+ Zászló
+ Vonat
+ Kerékpár
+ Repülő
+ Rakáta
+ Trófea
+ Labda
+ Gitár
+ Trombita
+ Harang
+ Horgony
+ Fejhallgató
+ Mappa
+ Rajszeg
+
diff --git a/features/verifysession/impl/src/main/res/values-hu/translations.xml b/features/verifysession/impl/src/main/res/values-hu/translations.xml
new file mode 100644
index 0000000000..4be493dcaf
--- /dev/null
+++ b/features/verifysession/impl/src/main/res/values-hu/translations.xml
@@ -0,0 +1,18 @@
+
+
+ "Valami hibásnak tűnik. A kérés vagy időtúllépésre futott, vagy elutasították."
+ "Erősítse meg, hogy a lenti emodzsik egyeznek-e a másik munkamenetben megjelenítettekkel."
+ "Emodzsik összehasonlítása"
+ "Az új munkamenete most már ellenőrizve van. Eléri a titkosított üzeneteit, és a többi felhasználó is megbízhatónak fogja látni."
+ "Bizonyítsa, hogy valóban Ön az, hogy elérje a titkosított üzeneteinek előzményeit."
+ "Meglévő munkamenet megnyitása"
+ "Ellenőrzés újrapróbálása"
+ "Kész vagyok"
+ "Várakozás az egyezésre"
+ "Egyedi emodzsik összehasonlítása."
+ "Hasonlítsa össze az egyedi emodzsikat, meggyőződve arról, hogy azonos a sorrendjük."
+ "Nem egyeznek"
+ "Megegyeznek"
+ "A folytatáshoz fogadja el az ellenőrzési folyamat indítási kérését a másik munkamenetében."
+ "Várakozás a kérés elfogadására"
+
diff --git a/features/verifysession/impl/src/main/res/values-in/strings_sas.xml b/features/verifysession/impl/src/main/res/values-in/strings_sas.xml
new file mode 100644
index 0000000000..1b283a7438
--- /dev/null
+++ b/features/verifysession/impl/src/main/res/values-in/strings_sas.xml
@@ -0,0 +1,68 @@
+
+
+
+ Anjing
+ Kucing
+ Singa
+ Kuda
+ Unicorn
+ Babi
+ Gajah
+ Kelinci
+ Panda
+ Ayam
+ Penguin
+ Kura-Kura
+ Ikan
+ Gurita
+ Kupu-Kupu
+ Bunga
+ Pohon
+ Kaktus
+ Jamur
+ Bola Dunia
+ Bulan
+ Awan
+ Api
+ Pisang
+ Apel
+ Stroberi
+ Jagung
+ Pizza
+ Kue
+ Hati
+ Senyuman
+ Robot
+ Topi
+ Kacamata
+ Kunci Bengkel
+ Santa
+ Jempol
+ Payung
+ Jam Pasir
+ Jam
+ Kado
+ Bohlam Lampu
+ Buku
+ Pensil
+ Klip Kertas
+ Gunting
+ Gembok
+ Kunci
+ Palu
+ Telepon
+ Bendera
+ Kereta Api
+ Sepeda
+ Pesawat
+ Roket
+ Piala
+ Bola
+ Gitar
+ Terompet
+ Lonceng
+ Jangkar
+ Headphone
+ Map
+ Pin
+
diff --git a/features/verifysession/impl/src/main/res/values-in/translations.xml b/features/verifysession/impl/src/main/res/values-in/translations.xml
new file mode 100644
index 0000000000..0c0a7dad4d
--- /dev/null
+++ b/features/verifysession/impl/src/main/res/values-in/translations.xml
@@ -0,0 +1,18 @@
+
+
+ "Sepertinya ada yang tidak beres. Entah permintaan sudah habis masa berlakunya atau permintaan ditolak."
+ "Konfirmasikan bahwa emoji di bawah ini sesuai dengan yang ditampilkan pada sesi Anda yang lain."
+ "Bandingkan emoji"
+ "Sesi baru Anda sekarang diverifikasi. Ini memiliki akses ke pesan terenkripsi Anda, dan pengguna lain akan melihatnya sebagai tepercaya."
+ "Buktikan bahwa ini memang Anda untuk mengakses riwayat pesan terenkripsi Anda."
+ "Buka sesi yang sudah ada"
+ "Verifikasi ulang"
+ "Saya siap"
+ "Menunggu untuk mencocokkan"
+ "Bandingkan satu set emoji yang unik."
+ "Bandingkan emoji unik, dan pastikan emoji tersebut muncul dalam urutan yang sama."
+ "Mereka tidak cocok"
+ "Mereka cocok"
+ "Terima permintaan untuk memulai proses verifikasi di sesi Anda yang lain untuk melanjutkan."
+ "Menunggu untuk menerima permintaan"
+
diff --git a/features/verifysession/impl/src/main/res/values-it/strings_sas.xml b/features/verifysession/impl/src/main/res/values-it/strings_sas.xml
new file mode 100644
index 0000000000..d0dca4b835
--- /dev/null
+++ b/features/verifysession/impl/src/main/res/values-it/strings_sas.xml
@@ -0,0 +1,68 @@
+
+
+
+ Cane
+ Gatto
+ Leone
+ Cavallo
+ Unicorno
+ Maiale
+ Elefante
+ Coniglio
+ Panda
+ Gallo
+ Pinguino
+ Tartaruga
+ Pesce
+ Polpo
+ Farfalla
+ Fiore
+ Albero
+ Cactus
+ Fungo
+ Globo
+ Luna
+ Nuvola
+ Fuoco
+ Banana
+ Mela
+ Fragola
+ Mais
+ Pizza
+ Torta
+ Cuore
+ Faccina sorridente
+ Robot
+ Cappello
+ Occhiali
+ Chiave inglese
+ Babbo Natale
+ Pollice alzato
+ Ombrello
+ Clessidra
+ Orologio
+ Regalo
+ Lampadina
+ Libro
+ Matita
+ Graffetta
+ Forbici
+ Lucchetto
+ Chiave
+ Martello
+ Telefono
+ Bandiera
+ Treno
+ Bicicletta
+ Aeroplano
+ Razzo
+ Trofeo
+ Palla
+ Chitarra
+ Trombetta
+ Campana
+ Ancora
+ Cuffie
+ Cartella
+ Puntina
+
diff --git a/features/verifysession/impl/src/main/res/values-ja/strings_sas.xml b/features/verifysession/impl/src/main/res/values-ja/strings_sas.xml
new file mode 100644
index 0000000000..9791b688fe
--- /dev/null
+++ b/features/verifysession/impl/src/main/res/values-ja/strings_sas.xml
@@ -0,0 +1,68 @@
+
+
+
+ 犬
+ 猫
+ ライオン
+ 馬
+ ユニコーン
+ ブタ
+ ゾウ
+ うさぎ
+ パンダ
+ ニワトリ
+ ペンギン
+ 亀
+ 魚
+ たこ
+ ちょうちょ
+ 花
+ 木
+ サボテン
+ きのこ
+ 地球
+ 月
+ 雲
+ 炎
+ バナナ
+ リンゴ
+ いちご
+ とうもろこし
+ ピザ
+ ケーキ
+ ハート
+ スマイル
+ ロボット
+ 帽子
+ めがね
+ スパナ
+ サンタ
+ いいね
+ 傘
+ 砂時計
+ 時計
+ ギフト
+ 電球
+ 本
+ 鉛筆
+ クリップ
+ はさみ
+ 錠前
+ 鍵
+ 金槌
+ 電話機
+ 旗
+ 電車
+ 自転車
+ 飛行機
+ ロケット
+ トロフィー
+ ボール
+ ギター
+ トランペット
+ ベル
+ いかり
+ ヘッドホン
+ フォルダー
+ ピン
+
diff --git a/features/verifysession/impl/src/main/res/values-nb-rNO/strings_sas.xml b/features/verifysession/impl/src/main/res/values-nb-rNO/strings_sas.xml
new file mode 100644
index 0000000000..48c830a22e
--- /dev/null
+++ b/features/verifysession/impl/src/main/res/values-nb-rNO/strings_sas.xml
@@ -0,0 +1,68 @@
+
+
+
+ Hund
+ Katt
+ Løve
+ Hest
+ Enhjørning
+ Gris
+ Elefant
+ Kanin
+ Panda
+ Hane
+ Pingvin
+ Skilpadde
+ Fisk
+ Blekksprut
+ Sommerfugl
+ Blomst
+ Tre
+ Kaktus
+ Sopp
+ Globus
+ Måne
+ Sky
+ Flamme
+ Banan
+ Eple
+ Jordbær
+ Mais
+ Pizza
+ Kake
+ Hjerte
+ Smilefjes
+ Robot
+ Hatt
+ Briller
+ Fastnøkkel
+ Julenisse
+ Tommel Opp
+ Paraply
+ Timeglass
+ Klokke
+ Gave
+ Lyspære
+ Bok
+ Blyant
+ BInders
+ Saks
+ Lås
+ Nøkkel
+ Hammer
+ Telefon
+ Flagg
+ Tog
+ Sykkel
+ Fly
+ Rakett
+ Pokal
+ Ball
+ Gitar
+ Trompet
+ Bjelle
+ Anker
+ Hodetelefoner
+ Mappe
+ Tegnestift
+
diff --git a/features/verifysession/impl/src/main/res/values-nl/strings_sas.xml b/features/verifysession/impl/src/main/res/values-nl/strings_sas.xml
new file mode 100644
index 0000000000..24a889f58a
--- /dev/null
+++ b/features/verifysession/impl/src/main/res/values-nl/strings_sas.xml
@@ -0,0 +1,68 @@
+
+
+
+ Hond
+ Kat
+ Leeuw
+ Paard
+ Eenhoorn
+ Varken
+ Olifant
+ Konijn
+ Panda
+ Haan
+ Pinguïn
+ Schildpad
+ Vis
+ Octopus
+ Vlinder
+ Bloem
+ Boom
+ Cactus
+ Paddenstoel
+ Wereldbol
+ Maan
+ Wolk
+ Vuur
+ Banaan
+ Appel
+ Aardbei
+ Maïs
+ Pizza
+ Taart
+ Hart
+ Smiley
+ Robot
+ Hoed
+ Bril
+ Moersleutel
+ Kerstman
+ Duim omhoog
+ Paraplu
+ Zandloper
+ Wekker
+ Geschenk
+ Gloeilamp
+ Boek
+ Potlood
+ Papierklemmetje
+ Schaar
+ Slot
+ Sleutel
+ Hamer
+ Telefoon
+ Vlag
+ Trein
+ Fiets
+ Vliegtuig
+ Raket
+ Trofee
+ Bal
+ Gitaar
+ Trompet
+ Bel
+ Anker
+ Koptelefoon
+ Map
+ Duimspijker
+
diff --git a/features/verifysession/impl/src/main/res/values-pt-rBR/strings_sas.xml b/features/verifysession/impl/src/main/res/values-pt-rBR/strings_sas.xml
new file mode 100644
index 0000000000..34add983e2
--- /dev/null
+++ b/features/verifysession/impl/src/main/res/values-pt-rBR/strings_sas.xml
@@ -0,0 +1,68 @@
+
+
+
+ Cachorro
+ Gato
+ Leão
+ Cavalo
+ Unicórnio
+ Porco
+ Elefante
+ Coelho
+ Panda
+ Galo
+ Pinguim
+ Tartaruga
+ Peixe
+ Polvo
+ Borboleta
+ Flor
+ Árvore
+ Cacto
+ Cogumelo
+ Globo
+ Lua
+ Nuvem
+ Fogo
+ Banana
+ Maçã
+ Morango
+ Milho
+ Pizza
+ Bolo
+ Coração
+ Sorriso
+ Robô
+ Chapéu
+ Óculos
+ Chave inglesa
+ Papai-noel
+ Joinha
+ Guarda-chuva
+ Ampulheta
+ Relógio
+ Presente
+ Lâmpada
+ Livro
+ Lápis
+ Clipe de papel
+ Tesoura
+ Cadeado
+ Chave
+ Martelo
+ Telefone
+ Bandeira
+ Trem
+ Bicicleta
+ Avião
+ Foguete
+ Troféu
+ Bola
+ Guitarra
+ Trombeta
+ Sino
+ Âncora
+ Fones de ouvido
+ Pasta
+ Alfinete
+
diff --git a/features/verifysession/impl/src/main/res/values-pt/strings_sas.xml b/features/verifysession/impl/src/main/res/values-pt/strings_sas.xml
new file mode 100644
index 0000000000..c422b2a9c7
--- /dev/null
+++ b/features/verifysession/impl/src/main/res/values-pt/strings_sas.xml
@@ -0,0 +1,68 @@
+
+
+
+ Cão
+ Gato
+ Leão
+ Cavalo
+ Unicórnio
+ Porco
+ Elefante
+ Coelho
+ Panda
+ Galo
+ Pinguim
+ Tartaruga
+ Peixe
+ Polvo
+ Borboleta
+ Flor
+ Árvore
+ Cato
+ Cogumelo
+ Globo
+ Lua
+ Nuvem
+ Fogo
+ Banana
+ Maçã
+ Morango
+ Milho
+ Piza
+ Bolo
+ Coração
+ Sorriso
+ Robô
+ Chapéu
+ Óculos
+ Chave inglesa
+ Pai Natal
+ Polegar para cima
+ Guarda-chuva
+ Ampulheta
+ Relógio
+ Presente
+ Lâmpada
+ Livro
+ Lápis
+ Clipe
+ Tesoura
+ Cadeado
+ Chave
+ Martelo
+ Telefone
+ Bandeira
+ Comboio
+ Bicicleta
+ Avião
+ Foguetão
+ Troféu
+ Bola
+ Guitarra
+ Trompete
+ Sino
+ Âncora
+ Fones
+ Pasta
+ Pionés
+
diff --git a/features/verifysession/impl/src/main/res/values-ru/strings_sas.xml b/features/verifysession/impl/src/main/res/values-ru/strings_sas.xml
new file mode 100644
index 0000000000..9a26caf62e
--- /dev/null
+++ b/features/verifysession/impl/src/main/res/values-ru/strings_sas.xml
@@ -0,0 +1,68 @@
+
+
+
+ Собака
+ Кошка
+ Лев
+ Лошадь
+ Единорог
+ Свинья
+ Слон
+ Кролик
+ Панда
+ Петух
+ Пингвин
+ Черепаха
+ Рыба
+ Осьминог
+ Бабочка
+ Цветок
+ Дерево
+ Кактус
+ Гриб
+ Глобус
+ Луна
+ Облако
+ Огонь
+ Банан
+ Яблоко
+ Клубника
+ Кукуруза
+ Пицца
+ Торт
+ Сердце
+ Улыбка
+ Робот
+ Шляпа
+ Очки
+ Ключ
+ Санта
+ Большой палец вверх
+ Зонт
+ Песочные часы
+ Часы
+ Подарок
+ Лампочка
+ Книга
+ Карандаш
+ Скрепка
+ Ножницы
+ Замок
+ Ключ
+ Молоток
+ Телефон
+ Флаг
+ Поезд
+ Велосипед
+ Самолет
+ Ракета
+ Кубок
+ Мяч
+ Гитара
+ Труба
+ Колокол
+ Якорь
+ Наушники
+ Папка
+ Булавка
+
diff --git a/features/verifysession/impl/src/main/res/values-si/strings_sas.xml b/features/verifysession/impl/src/main/res/values-si/strings_sas.xml
new file mode 100644
index 0000000000..67d0775281
--- /dev/null
+++ b/features/verifysession/impl/src/main/res/values-si/strings_sas.xml
@@ -0,0 +1,8 @@
+
+
+
+ බල්ලා
+ පූසා
+ සිංහයා
+ අශ්වයා
+
diff --git a/features/verifysession/impl/src/main/res/values-sk/strings_sas.xml b/features/verifysession/impl/src/main/res/values-sk/strings_sas.xml
new file mode 100644
index 0000000000..5e1eba9569
--- /dev/null
+++ b/features/verifysession/impl/src/main/res/values-sk/strings_sas.xml
@@ -0,0 +1,68 @@
+
+
+
+ Pes
+ Mačka
+ Lev
+ Kôň
+ Jednorožec
+ Prasa
+ Slon
+ Zajac
+ Panda
+ Kohút
+ Tučniak
+ Korytnačka
+ Ryba
+ Chobotnica
+ Motýľ
+ Kvet
+ Strom
+ Kaktus
+ Huba
+ Zemeguľa
+ Mesiac
+ Oblak
+ Oheň
+ Banán
+ Jablko
+ Jahoda
+ Kukurica
+ Pizza
+ Torta
+ Srdce
+ Smajlík
+ Robot
+ Klobúk
+ Okuliare
+ Vidlicový kľúč
+ Mikuláš
+ Palec nahor
+ Dáždnik
+ Presýpacie hodiny
+ Budík
+ Darček
+ Žiarovka
+ Kniha
+ Ceruzka
+ Kancelárska sponka
+ Nožnice
+ Zámka
+ Kľúč
+ Kladivo
+ Telefón
+ Zástava
+ Vlak
+ Bicykel
+ Lietadlo
+ Raketa
+ Trofej
+ Lopta
+ Gitara
+ Trúbka
+ Zvonec
+ Kotva
+ Slúchadlá
+ Fascikel
+ Špendlík
+
diff --git a/features/verifysession/impl/src/main/res/values-sk/translations.xml b/features/verifysession/impl/src/main/res/values-sk/translations.xml
index 4b13701466..5d7920d740 100644
--- a/features/verifysession/impl/src/main/res/values-sk/translations.xml
+++ b/features/verifysession/impl/src/main/res/values-sk/translations.xml
@@ -3,6 +3,8 @@
"Zdá sa, že niečo nie je v poriadku. Časový limit žiadosti vypršal alebo bola žiadosť zamietnutá."
"Skontrolujte, či sa emotikony uvedené nižšie zhodujú s emotikonmi zobrazenými vo vašej druhej relácii."
"Porovnajte emotikony"
+ "Skontrolujte, či sa nižšie uvedené čísla zhodujú s číslami zobrazenými na vašej druhej relácii."
+ "Porovnať čísla"
"Vaša nová relácia je teraz overená. Má prístup k vašim zašifrovaným správam a ostatní používatelia ju budú vidieť ako dôveryhodnú."
"Dokážte, že ste to vy, aby ste získali prístup k histórii vašich zašifrovaných správ."
"Otvoriť existujúcu reláciu"
diff --git a/features/verifysession/impl/src/main/res/values-sq/strings_sas.xml b/features/verifysession/impl/src/main/res/values-sq/strings_sas.xml
new file mode 100644
index 0000000000..b305c9788f
--- /dev/null
+++ b/features/verifysession/impl/src/main/res/values-sq/strings_sas.xml
@@ -0,0 +1,67 @@
+
+
+
+ Qen
+ Mace
+ Luan
+ Kalë
+ Njëbrirësh
+ Derr
+ Elefant
+ Lepur
+ Panda
+ Këndes
+ Pinguin
+ Breshkë
+ Peshk
+ Oktapod
+ Flutur
+ Lule
+ Pemë
+ Kaktus
+ Kërpudhë
+ Rruzull
+ Hënë
+ Re
+ Zjarr
+ Banane
+ Mollë
+ Luleshtrydhe
+ Misër
+ Picë
+ Tortë
+ Zemër
+ Emotikon
+ Robot
+ Kapë
+ Syze
+ Çelës
+ Babagjyshi i Vitit të Ri
+ Ombrellë
+ Klepsidër
+ Sahat
+ Dhuratë
+ Llambë
+ Libër
+ Laps
+ Kapëse
+ Gërshërë
+ Dry
+ Çelës
+ Çekiç
+ Telefon
+ Flamur
+ Tren
+ Biçikletë
+ Avion
+ Raketë
+ Trofe
+ Top
+ Kitarë
+ Trombë
+ Kambanë
+ Spirancë
+ Kufje
+ Dosje
+ Karficë
+
diff --git a/features/verifysession/impl/src/main/res/values-sr/strings_sas.xml b/features/verifysession/impl/src/main/res/values-sr/strings_sas.xml
new file mode 100644
index 0000000000..f9e1c9d201
--- /dev/null
+++ b/features/verifysession/impl/src/main/res/values-sr/strings_sas.xml
@@ -0,0 +1,68 @@
+
+
+
+ пас
+ мачка
+ лав
+ коњ
+ једнорог
+ прасе
+ слон
+ зец
+ панда
+ петао
+ пингвин
+ корњача
+ риба
+ октопод
+ лептир
+ цвет
+ дрво
+ кактус
+ печурка
+ глобус
+ месец
+ облак
+ ватра
+ банана
+ јабука
+ јагода
+ кукуруз
+ пица
+ торта
+ срце
+ смајли
+ робот
+ шешир
+ наочаре
+ кључ
+ деда Мраз
+ палчић горе
+ кишобран
+ пешчаник
+ сат
+ поклон
+ сијалица
+ књига
+ оловка
+ спајалица
+ маказе
+ катанац
+ кључ
+ чекић
+ телефон
+ застава
+ воз
+ бицикл
+ авион
+ ракета
+ пехар
+ лопта
+ гитара
+ труба
+ звоно
+ сидро
+ слушалице
+ фасцикла
+ чиода
+
diff --git a/features/verifysession/impl/src/main/res/values-sv/strings_sas.xml b/features/verifysession/impl/src/main/res/values-sv/strings_sas.xml
new file mode 100644
index 0000000000..02cf63c37f
--- /dev/null
+++ b/features/verifysession/impl/src/main/res/values-sv/strings_sas.xml
@@ -0,0 +1,68 @@
+
+
+
+ Hund
+ Katt
+ Lejon
+ Häst
+ Enhörning
+ Gris
+ Elefant
+ Kanin
+ Panda
+ Tupp
+ Pingvin
+ Sköldpadda
+ Fisk
+ Bläckfisk
+ Fjäril
+ Blomma
+ Träd
+ Kaktus
+ Svamp
+ Jordklot
+ Måne
+ Moln
+ Eld
+ Banan
+ Äpple
+ Jordgubbe
+ Majs
+ Pizza
+ Tårta
+ Hjärta
+ Smiley
+ Robot
+ Hatt
+ Glasögon
+ Skruvnyckel
+ Tomte
+ Tummen upp
+ Paraply
+ Timglas
+ Klocka
+ Present
+ Lampa
+ Bok
+ Penna
+ Gem
+ Sax
+ Lås
+ Nyckel
+ Hammare
+ Telefon
+ Flagga
+ Tåg
+ Cykel
+ Flygplan
+ Raket
+ Trofé
+ Boll
+ Gitarr
+ Trumpet
+ Bjällra
+ Ankare
+ Hörlurar
+ Mapp
+ Häftstift
+
diff --git a/features/verifysession/impl/src/main/res/values-szl/strings_sas.xml b/features/verifysession/impl/src/main/res/values-szl/strings_sas.xml
new file mode 100644
index 0000000000..9769ad73ce
--- /dev/null
+++ b/features/verifysession/impl/src/main/res/values-szl/strings_sas.xml
@@ -0,0 +1,4 @@
+
+
+
+
diff --git a/features/verifysession/impl/src/main/res/values-tzm/strings_sas.xml b/features/verifysession/impl/src/main/res/values-tzm/strings_sas.xml
new file mode 100644
index 0000000000..6d1567d6dd
--- /dev/null
+++ b/features/verifysession/impl/src/main/res/values-tzm/strings_sas.xml
@@ -0,0 +1,30 @@
+
+
+
+ Aydi
+ Amuc
+ Izem
+ Ayyis
+ Ilef
+ Ilu
+ Agnin
+ Ayaẓiḍ
+ Ifker
+ Aselm
+ Aseklu
+ Agursel
+ Ayyur
+ Timessi
+ Tabanant
+ Tadeffuyt
+ Ul
+ Aṛubu
+ Taraza
+ Adlis
+ Tasarut
+ Atilifun
+ Acenyal
+ Tcama
+ Agiṭaṛ
+ Asdaw
+
diff --git a/features/verifysession/impl/src/main/res/values-uk/strings_sas.xml b/features/verifysession/impl/src/main/res/values-uk/strings_sas.xml
new file mode 100644
index 0000000000..bfeaa3a6d1
--- /dev/null
+++ b/features/verifysession/impl/src/main/res/values-uk/strings_sas.xml
@@ -0,0 +1,68 @@
+
+
+
+ Пес
+ Кіт
+ Лев
+ Кінь
+ Єдиноріг
+ Свиня
+ Слон
+ Кріль
+ Панда
+ Когут
+ Пінгвін
+ Черепаха
+ Риба
+ Восьминіг
+ Метелик
+ Квітка
+ Дерево
+ Кактус
+ Гриб
+ Глобус
+ Місяць
+ Хмара
+ Вогонь
+ Банан
+ Яблуко
+ Полуниця
+ Кукурудза
+ Піца
+ Пиріг
+ Серце
+ Посмішка
+ Робот
+ Капелюх
+ Окуляри
+ Гайковий ключ
+ Санта Клаус
+ Великий палець вгору
+ Парасолька
+ Пісковий годинник
+ Годинник
+ Подарунок
+ Лампочка
+ Книга
+ Олівець
+ Спиначка
+ Ножиці
+ Замок
+ Ключ
+ Молоток
+ Телефон
+ Прапор
+ Потяг
+ Велосипед
+ Літак
+ Ракета
+ Приз
+ М\'яч
+ Гітара
+ Труба
+ Дзвін
+ Якір
+ Навушники
+ Тека
+ Кнопка
+
diff --git a/features/verifysession/impl/src/main/res/values-vi/strings_sas.xml b/features/verifysession/impl/src/main/res/values-vi/strings_sas.xml
new file mode 100644
index 0000000000..dbf7db0234
--- /dev/null
+++ b/features/verifysession/impl/src/main/res/values-vi/strings_sas.xml
@@ -0,0 +1,68 @@
+
+
+
+ Chó
+ Mèo
+ Sư tử
+ Ngựa
+ Kỳ lân
+ Heo
+ Voi
+ Thỏ
+ Gấu trúc
+ Gà trống
+ Chim cánh cụt
+ Rùa
+ Cá
+ Bạch tuộc
+ Bướm
+ Hoa
+ Cây
+ Xương rồng
+ Nấm
+ Địa cầu
+ Mặt trăng
+ Mây
+ Lửa
+ Chuối
+ Táo
+ Dâu tây
+ Bắp
+ Pizza
+ Bánh
+ Tim
+ Mặt cười
+ Rô-bô
+ Mũ
+ Kính mắt
+ Cờ-lê
+ ông già Nô-en
+ Thích
+ Cái ô
+ Đồng hồ cát
+ Đồng hồ
+ Quà tặng
+ Bóng đèn tròn
+ Sách
+ Viết chì
+ Kẹp giấy
+ Cái kéo
+ Ổ khóa
+ Chìa khóa
+ Búa
+ Điện thoại
+ Lá cờ
+ Xe lửa
+ Xe đạp
+ Máy bay
+ Tên lửa
+ Cúp
+ Banh
+ Ghi-ta
+ Kèn
+ Chuông
+ Mỏ neo
+ Tai nghe
+ Thư mục
+ Ghim
+
diff --git a/features/verifysession/impl/src/main/res/values-zh-rCN/strings_sas.xml b/features/verifysession/impl/src/main/res/values-zh-rCN/strings_sas.xml
new file mode 100644
index 0000000000..39c2ff1d37
--- /dev/null
+++ b/features/verifysession/impl/src/main/res/values-zh-rCN/strings_sas.xml
@@ -0,0 +1,68 @@
+
+
+
+ 狗
+ 猫
+ 狮子
+ 马
+ 独角兽
+ 猪
+ 大象
+ 兔子
+ 熊猫
+ 公鸡
+ 企鹅
+ 乌龟
+ 鱼
+ 章鱼
+ 蝴蝶
+ 花
+ 树
+ 仙人掌
+ 蘑菇
+ 地球
+ 月亮
+ 云
+ 火
+ 香蕉
+ 苹果
+ 草莓
+ 玉米
+ 披萨
+ 蛋糕
+ 心
+ 笑脸
+ 机器人
+ 帽子
+ 眼镜
+ 扳手
+ 圣诞老人
+ 赞
+ 伞
+ 沙漏
+ 时钟
+ 礼物
+ 灯泡
+ 书
+ 铅笔
+ 回形针
+ 剪刀
+ 锁
+ 钥匙
+ 锤子
+ 电话
+ 旗帜
+ 火车
+ 自行车
+ 飞机
+ 火箭
+ 奖杯
+ 球
+ 吉他
+ 喇叭
+ 铃铛
+ 锚
+ 耳机
+ 文件夹
+ 图钉
+
diff --git a/features/verifysession/impl/src/main/res/values-zh-rTW/strings_sas.xml b/features/verifysession/impl/src/main/res/values-zh-rTW/strings_sas.xml
new file mode 100644
index 0000000000..b7068b7f67
--- /dev/null
+++ b/features/verifysession/impl/src/main/res/values-zh-rTW/strings_sas.xml
@@ -0,0 +1,68 @@
+
+
+
+ 狗
+ 貓
+ 獅子
+ 馬
+ 獨角獸
+ 豬
+ 大象
+ 兔子
+ 熊貓
+ 公雞
+ 企鵝
+ 烏龜
+ 魚
+ 章魚
+ 蝴蝶
+ 花
+ 樹
+ 仙人掌
+ 蘑菇
+ 地球
+ 月亮
+ 雲朵
+ 火
+ 香蕉
+ 蘋果
+ 草莓
+ 玉米
+ 披薩
+ 蛋糕
+ 愛心
+ 笑臉
+ 機器人
+ 帽子
+ 眼鏡
+ 扳手
+ 聖誕老人
+ 讚
+ 雨傘
+ 沙漏
+ 時鐘
+ 禮物
+ 燈泡
+ 書
+ 鉛筆
+ 迴紋針
+ 剪刀
+ 鎖頭
+ 鑰匙
+ 鎚子
+ 電話
+ 旗幟
+ 火車
+ 腳踏車
+ 飛機
+ 火箭
+ 獎盃
+ 足球
+ 吉他
+ 喇叭
+ 鈴鐺
+ 船錨
+ 耳機
+ 資料夾
+ 圖釘
+
diff --git a/features/verifysession/impl/src/main/res/values/strings_sas.xml b/features/verifysession/impl/src/main/res/values/strings_sas.xml
new file mode 100644
index 0000000000..db6b545428
--- /dev/null
+++ b/features/verifysession/impl/src/main/res/values/strings_sas.xml
@@ -0,0 +1,68 @@
+
+
+
+ Dog
+ Cat
+ Lion
+ Horse
+ Unicorn
+ Pig
+ Elephant
+ Rabbit
+ Panda
+ Rooster
+ Penguin
+ Turtle
+ Fish
+ Octopus
+ Butterfly
+ Flower
+ Tree
+ Cactus
+ Mushroom
+ Globe
+ Moon
+ Cloud
+ Fire
+ Banana
+ Apple
+ Strawberry
+ Corn
+ Pizza
+ Cake
+ Heart
+ Smiley
+ Robot
+ Hat
+ Glasses
+ Spanner
+ Santa
+ Thumbs Up
+ Umbrella
+ Hourglass
+ Clock
+ Gift
+ Light Bulb
+ Book
+ Pencil
+ Paperclip
+ Scissors
+ Lock
+ Key
+ Hammer
+ Telephone
+ Flag
+ Train
+ Bicycle
+ Aeroplane
+ Rocket
+ Trophy
+ Ball
+ Guitar
+ Trumpet
+ Bell
+ Anchor
+ Headphones
+ Folder
+ Pin
+
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 8f8795ed78..c96866cb5a 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
@@ -23,11 +23,11 @@ import app.cash.turbine.test
import com.google.common.truth.Truth.assertThat
import io.element.android.features.verifysession.impl.VerifySelfSessionState.VerificationStep
import io.element.android.libraries.architecture.Async
+import io.element.android.libraries.matrix.api.verification.SessionVerificationData
import io.element.android.libraries.matrix.api.verification.VerificationEmoji
import io.element.android.libraries.matrix.api.verification.VerificationFlowState
import io.element.android.libraries.matrix.test.verification.FakeSessionVerificationService
import io.element.android.tests.testutils.WarmUpRule
-import kotlinx.collections.immutable.persistentListOf
import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.test.runTest
import org.junit.Rule
@@ -74,7 +74,7 @@ class VerifySelfSessionPresenterTests {
// Await for other device response:
assertThat(awaitItem().verificationFlowStep).isEqualTo(VerificationStep.AwaitingOtherDeviceResponse)
// ChallengeReceived:
- service.triggerReceiveVerificationData()
+ service.triggerReceiveVerificationData(SessionVerificationData.Emojis(emptyList()))
val verifyingState = awaitItem()
assertThat(verifyingState.verificationFlowStep).isInstanceOf(VerificationStep.Verifying::class.java)
}
@@ -133,7 +133,7 @@ class VerifySelfSessionPresenterTests {
presenter.present()
}.test {
requestVerificationAndAwaitVerifyingState(service)
- service.givenVerificationFlowState(VerificationFlowState.ReceivedVerificationData(persistentListOf()))
+ service.givenVerificationFlowState(VerificationFlowState.ReceivedVerificationData(SessionVerificationData.Emojis(emptyList())))
ensureAllEventsConsumed()
}
}
@@ -157,19 +157,25 @@ class VerifySelfSessionPresenterTests {
@Test
fun `present - When verification is approved, the flow completes if there is no error`() = runTest {
- val emojis = listOf(
- VerificationEmoji("😄", "Smile")
+ val emojis = listOf(
+ VerificationEmoji(number = 30, emoji = "😀", description = "Smiley")
)
- val service = FakeSessionVerificationService().apply {
- givenEmojiList(emojis)
- }
+ val service = FakeSessionVerificationService()
val presenter = createVerifySelfSessionPresenter(service)
moleculeFlow(RecompositionMode.Immediate) {
presenter.present()
}.test {
- val state = requestVerificationAndAwaitVerifyingState(service)
+ val state = requestVerificationAndAwaitVerifyingState(
+ service,
+ SessionVerificationData.Emojis(emojis)
+ )
state.eventSink(VerifySelfSessionViewEvents.ConfirmVerification)
- assertThat(awaitItem().verificationFlowStep).isEqualTo(VerificationStep.Verifying(emojis, Async.Loading()))
+ assertThat(awaitItem().verificationFlowStep).isEqualTo(
+ VerificationStep.Verifying(
+ SessionVerificationData.Emojis(emojis),
+ Async.Loading(),
+ )
+ )
assertThat(awaitItem().verificationFlowStep).isEqualTo(VerificationStep.Completed)
}
}
@@ -183,13 +189,19 @@ class VerifySelfSessionPresenterTests {
}.test {
val state = requestVerificationAndAwaitVerifyingState(service)
state.eventSink(VerifySelfSessionViewEvents.DeclineVerification)
- assertThat(awaitItem().verificationFlowStep).isEqualTo(VerificationStep.Verifying(emptyList(), Async.Loading()))
+ assertThat(awaitItem().verificationFlowStep).isEqualTo(
+ VerificationStep.Verifying(
+ SessionVerificationData.Emojis(emptyList()),
+ Async.Loading(),
+ )
+ )
assertThat(awaitItem().verificationFlowStep).isEqualTo(VerificationStep.Canceled)
}
}
private suspend fun ReceiveTurbine.requestVerificationAndAwaitVerifyingState(
- fakeService: FakeSessionVerificationService
+ fakeService: FakeSessionVerificationService,
+ sessionVerificationData: SessionVerificationData = SessionVerificationData.Emojis(emptyList()),
): VerifySelfSessionState {
var state = awaitItem()
assertThat(state.verificationFlowStep).isEqualTo(VerificationStep.Initial)
@@ -204,7 +216,7 @@ class VerifySelfSessionPresenterTests {
// Await for other device response (again):
state = awaitItem()
assertThat(state.verificationFlowStep).isEqualTo(VerificationStep.AwaitingOtherDeviceResponse)
- fakeService.triggerReceiveVerificationData()
+ fakeService.triggerReceiveVerificationData(sessionVerificationData)
// Finally, ChallengeReceived:
state = awaitItem()
assertThat(state.verificationFlowStep).isInstanceOf(VerificationStep.Verifying::class.java)
diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml
index f327a06ba0..1377b7c948 100644
--- a/gradle/libs.versions.toml
+++ b/gradle/libs.versions.toml
@@ -3,6 +3,8 @@
[versions]
# Project
+# Warning: version 8.2.0 is leading https://github.com/element-hq/element-x-android/issues/1971
+# which will only occurs in release mode, and so will not be detected by Maestro
android_gradle_plugin = "8.1.4"
kotlin = "1.9.20"
ksp = "1.9.20-1.0.14"
@@ -36,11 +38,11 @@ datetime = "0.4.1"
serialization_json = "1.6.1"
showkase = "1.0.2"
appyx = "1.4.0"
-sqldelight = "2.0.0"
-wysiwyg = "2.20.0"
+sqldelight = "2.0.1"
+wysiwyg = "2.21.0"
# DI
-dagger = "2.48.1"
+dagger = "2.49"
anvil = "2.4.8-1-8"
# Auto service
@@ -59,7 +61,7 @@ android_desugar = "com.android.tools:desugar_jdk_libs:2.0.4"
kotlin_gradle_plugin = { module = "org.jetbrains.kotlin:kotlin-gradle-plugin", version.ref = "kotlin" }
gms_google_services = "com.google.gms:google-services:4.4.0"
# https://firebase.google.com/docs/android/setup#available-libraries
-google_firebase_bom = "com.google.firebase:firebase-bom:32.6.0"
+google_firebase_bom = "com.google.firebase:firebase-bom:32.7.0"
firebase_appdistribution_gradle = { module = "com.google.firebase:firebase-appdistribution-gradle", version.ref = "firebaseAppDistribution" }
# AndroidX
@@ -86,7 +88,7 @@ androidx_activity_activity = { module = "androidx.activity:activity", version.re
androidx_activity_compose = { module = "androidx.activity:activity-compose", version.ref = "activity" }
androidx_startup = "androidx.startup:startup-runtime:1.1.1"
androidx_preference = "androidx.preference:preference:1.2.1"
-androidx_webkit = "androidx.webkit:webkit:1.8.0"
+androidx_webkit = "androidx.webkit:webkit:1.9.0"
androidx_compose_bom = { module = "androidx.compose:compose-bom", version.ref = "compose_bom" }
androidx_compose_material3 = "androidx.compose.material3:material3:1.2.0-alpha12"
@@ -147,7 +149,7 @@ jsoup = "org.jsoup:jsoup:1.17.1"
appyx_core = { module = "com.bumble.appyx:core", version.ref = "appyx" }
molecule-runtime = "app.cash.molecule:molecule-runtime:1.3.1"
timber = "com.jakewharton.timber:timber:5.0.1"
-matrix_sdk = "org.matrix.rustcomponents:sdk-android:0.1.72"
+matrix_sdk = "org.matrix.rustcomponents:sdk-android:0.1.76"
matrix_richtexteditor = { module = "io.element.android:wysiwyg", version.ref = "wysiwyg" }
matrix_richtexteditor_compose = { module = "io.element.android:wysiwyg-compose", version.ref = "wysiwyg" }
sqldelight-driver-android = { module = "app.cash.sqldelight:android-driver", version.ref = "sqldelight" }
@@ -157,18 +159,18 @@ sqlcipher = "net.zetetic:android-database-sqlcipher:4.5.4"
sqlite = "androidx.sqlite:sqlite-ktx:2.4.0"
unifiedpush = "com.github.UnifiedPush:android-connector:2.1.1"
otaliastudios_transcoder = "com.otaliastudios:transcoder:0.10.5"
-vanniktech_blurhash = "com.vanniktech:blurhash:0.1.0"
+vanniktech_blurhash = "com.vanniktech:blurhash:0.2.0"
telephoto_zoomableimage = "me.saket.telephoto:zoomable-image-coil:0.7.1"
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.2"
maplibre_annotation = "org.maplibre.gl:android-plugin-annotation-v9:2.0.2"
opusencoder = "io.element.android:opusencoder:1.1.0"
-kotlinpoet = "com.squareup:kotlinpoet:1.15.1"
+kotlinpoet = "com.squareup:kotlinpoet:1.15.3"
# Analytics
-posthog = "com.posthog.android:posthog:2.0.3"
-sentry = "io.sentry:sentry-android:6.34.0"
+posthog = "com.posthog:posthog-android:3.0.0"
+sentry = "io.sentry:sentry-android:7.0.0"
matrix_analytics_events = "com.github.matrix-org:matrix-analytics-events:aa14cbcdf81af2746d20a71779ec751f971e1d7f"
# Emojibase
@@ -207,10 +209,10 @@ 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 = "io.gitlab.arturbosch.detekt:1.23.4"
-ktlint = "org.jlleitschuh.gradle.ktlint:11.6.1"
+ktlint = "org.jlleitschuh.gradle.ktlint:12.0.3"
dependencygraph = "com.savvasdalkitsis.module-dependency-graph:0.12"
-dependencycheck = "org.owasp.dependencycheck:9.0.1"
-dependencyanalysis = "com.autonomousapps.dependency-analysis:1.26.0"
+dependencycheck = "org.owasp.dependencycheck:9.0.4"
+dependencyanalysis = "com.autonomousapps.dependency-analysis:1.27.0"
paparazzi = "app.cash.paparazzi:1.3.1"
kover = "org.jetbrains.kotlinx.kover:0.6.1"
sqldelight = { id = "app.cash.sqldelight", version.ref = "sqldelight" }
diff --git a/libraries/androidutils/build.gradle.kts b/libraries/androidutils/build.gradle.kts
index 87382a2c3e..94e6d92160 100644
--- a/libraries/androidutils/build.gradle.kts
+++ b/libraries/androidutils/build.gradle.kts
@@ -1,4 +1,3 @@
-
/*
* Copyright (c) 2023 New Vector Ltd
*
@@ -33,6 +32,7 @@ dependencies {
implementation(projects.libraries.di)
implementation(projects.libraries.core)
+ implementation(projects.services.toolbox.api)
implementation(libs.dagger)
implementation(libs.timber)
implementation(libs.androidx.corektx)
@@ -41,4 +41,12 @@ dependencies {
implementation(libs.androidx.exifinterface)
implementation(libs.androidx.security.crypto)
api(libs.androidx.browser)
+
+ testImplementation(projects.tests.testutils)
+ testImplementation(libs.test.junit)
+ testImplementation(libs.test.truth)
+ testImplementation(libs.test.robolectric)
+ testImplementation(libs.coroutines.core)
+ testImplementation(libs.coroutines.test)
+ testImplementation(projects.services.toolbox.test)
}
diff --git a/libraries/androidutils/src/main/kotlin/io/element/android/libraries/androidutils/filesize/AndroidFileSizeFormatter.kt b/libraries/androidutils/src/main/kotlin/io/element/android/libraries/androidutils/filesize/AndroidFileSizeFormatter.kt
index 9cd70febcc..abf55b581c 100644
--- a/libraries/androidutils/src/main/kotlin/io/element/android/libraries/androidutils/filesize/AndroidFileSizeFormatter.kt
+++ b/libraries/androidutils/src/main/kotlin/io/element/android/libraries/androidutils/filesize/AndroidFileSizeFormatter.kt
@@ -22,16 +22,18 @@ import android.text.format.Formatter
import com.squareup.anvil.annotations.ContributesBinding
import io.element.android.libraries.di.AppScope
import io.element.android.libraries.di.ApplicationContext
+import io.element.android.services.toolbox.api.sdk.BuildVersionSdkIntProvider
import javax.inject.Inject
@ContributesBinding(AppScope::class)
class AndroidFileSizeFormatter @Inject constructor(
@ApplicationContext private val context: Context,
- ) : FileSizeFormatter {
+ private val sdkIntProvider: BuildVersionSdkIntProvider,
+) : FileSizeFormatter {
override fun format(fileSize: Long, useShortFormat: Boolean): String {
// Since Android O, the system considers that 1kB = 1000 bytes instead of 1024 bytes.
// We want to avoid that.
- val normalizedSize = if (Build.VERSION.SDK_INT <= Build.VERSION_CODES.N) {
+ val normalizedSize = if (sdkIntProvider.get() <= Build.VERSION_CODES.N) {
fileSize
} else {
// First convert the size
diff --git a/libraries/androidutils/src/main/res/values-hu/translations.xml b/libraries/androidutils/src/main/res/values-hu/translations.xml
new file mode 100644
index 0000000000..dbbc088ed4
--- /dev/null
+++ b/libraries/androidutils/src/main/res/values-hu/translations.xml
@@ -0,0 +1,4 @@
+
+
+ "Nem található kompatibilis alkalmazás a művelet kezeléséhez."
+
diff --git a/libraries/androidutils/src/main/res/values-in/translations.xml b/libraries/androidutils/src/main/res/values-in/translations.xml
new file mode 100644
index 0000000000..b593b49812
--- /dev/null
+++ b/libraries/androidutils/src/main/res/values-in/translations.xml
@@ -0,0 +1,4 @@
+
+
+ "Tidak ada aplikasi yang kompatibel yang ditemukan untuk menangani tindakan ini."
+
diff --git a/libraries/androidutils/src/test/kotlin/io/element/android/libraries/androidutils/filesize/AndroidFileSizeFormatterTest.kt b/libraries/androidutils/src/test/kotlin/io/element/android/libraries/androidutils/filesize/AndroidFileSizeFormatterTest.kt
new file mode 100644
index 0000000000..4d83a2367a
--- /dev/null
+++ b/libraries/androidutils/src/test/kotlin/io/element/android/libraries/androidutils/filesize/AndroidFileSizeFormatterTest.kt
@@ -0,0 +1,71 @@
+/*
+ * 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.filesize
+
+import android.os.Build
+import com.google.common.truth.Truth.assertThat
+import io.element.android.services.toolbox.test.sdk.FakeBuildVersionSdkIntProvider
+import org.junit.Test
+import org.junit.runner.RunWith
+import org.robolectric.RobolectricTestRunner
+import org.robolectric.RuntimeEnvironment
+
+@RunWith(RobolectricTestRunner::class)
+class AndroidFileSizeFormatterTest {
+ @Test
+ fun `test api 24 long format`() {
+ val sut = createAndroidFileSizeFormatter(sdkLevel = Build.VERSION_CODES.N)
+ assertThat(sut.format(1, useShortFormat = false)).isEqualTo("1.00B")
+ assertThat(sut.format(1000, useShortFormat = false)).isEqualTo("0.98KB")
+ assertThat(sut.format(1024, useShortFormat = false)).isEqualTo("1.00KB")
+ assertThat(sut.format(1024 * 1024, useShortFormat = false)).isEqualTo("1.00MB")
+ assertThat(sut.format(1024 * 1024 * 1024, useShortFormat = false)).isEqualTo("1.00GB")
+ }
+
+ @Test
+ fun `test api 26 long format`() {
+ val sut = createAndroidFileSizeFormatter(sdkLevel = Build.VERSION_CODES.O)
+ assertThat(sut.format(1, useShortFormat = false)).isEqualTo("1.00B")
+ assertThat(sut.format(1000, useShortFormat = false)).isEqualTo("0.98KB")
+ assertThat(sut.format(1024 * 1024, useShortFormat = false)).isEqualTo("0.95MB")
+ assertThat(sut.format(1024 * 1024 * 1024, useShortFormat = false)).isEqualTo("0.93GB")
+ }
+
+ @Test
+ fun `test api 24 short format`() {
+ val sut = createAndroidFileSizeFormatter(sdkLevel = Build.VERSION_CODES.N)
+ assertThat(sut.format(1, useShortFormat = true)).isEqualTo("1.0B")
+ assertThat(sut.format(1000, useShortFormat = true)).isEqualTo("0.98KB")
+ assertThat(sut.format(1024, useShortFormat = true)).isEqualTo("1.0KB")
+ assertThat(sut.format(1024 * 1024, useShortFormat = true)).isEqualTo("1.0MB")
+ assertThat(sut.format(1024 * 1024 * 1024, useShortFormat = true)).isEqualTo("1.0GB")
+ }
+
+ @Test
+ fun `test api 26 short format`() {
+ val sut = createAndroidFileSizeFormatter(sdkLevel = Build.VERSION_CODES.O)
+ assertThat(sut.format(1, useShortFormat = true)).isEqualTo("1.0B")
+ assertThat(sut.format(1000, useShortFormat = true)).isEqualTo("0.98KB")
+ assertThat(sut.format(1024 * 1024, useShortFormat = true)).isEqualTo("0.95MB")
+ assertThat(sut.format(1024 * 1024 * 1024, useShortFormat = true)).isEqualTo("0.93GB")
+ }
+
+ private fun createAndroidFileSizeFormatter(sdkLevel: Int) = AndroidFileSizeFormatter(
+ context = RuntimeEnvironment.getApplication(),
+ sdkIntProvider = FakeBuildVersionSdkIntProvider(sdkInt = sdkLevel)
+ )
+}
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 2dcb19cc43..9475275e5d 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
@@ -25,7 +25,6 @@ import com.squareup.anvil.annotations.ContributesBinding
import io.element.android.libraries.di.SessionScope
import io.element.android.libraries.eventformatter.api.RoomLastMessageFormatter
import io.element.android.libraries.eventformatter.impl.mode.RenderingMode
-import io.element.android.libraries.matrix.api.MatrixClient
import io.element.android.libraries.matrix.api.timeline.item.event.AudioMessageType
import io.element.android.libraries.matrix.api.timeline.item.event.EmoteMessageType
import io.element.android.libraries.matrix.api.timeline.item.event.EventTimelineItem
@@ -58,14 +57,13 @@ import javax.inject.Inject
@ContributesBinding(SessionScope::class)
class DefaultRoomLastMessageFormatter @Inject constructor(
private val sp: StringProvider,
- private val matrixClient: MatrixClient,
private val roomMembershipContentFormatter: RoomMembershipContentFormatter,
private val profileChangeContentFormatter: ProfileChangeContentFormatter,
private val stateContentFormatter: StateContentFormatter,
) : RoomLastMessageFormatter {
override fun format(event: EventTimelineItem, isDmRoom: Boolean): CharSequence? {
- val isOutgoing = matrixClient.isMe(event.sender)
+ val isOutgoing = event.isOwn
val senderDisplayName = (event.senderProfile as? ProfileTimelineDetails.Ready)?.displayName ?: event.sender.value
return when (val content = event.content) {
is MessageContent -> processMessageContents(content, 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 2b729fb0d5..ce4e4aa860 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
@@ -21,7 +21,6 @@ import io.element.android.libraries.core.meta.BuildMeta
import io.element.android.libraries.di.SessionScope
import io.element.android.libraries.eventformatter.api.TimelineEventFormatter
import io.element.android.libraries.eventformatter.impl.mode.RenderingMode
-import io.element.android.libraries.matrix.api.MatrixClient
import io.element.android.libraries.matrix.api.timeline.item.event.EventTimelineItem
import io.element.android.libraries.matrix.api.timeline.item.event.FailedToParseMessageLikeContent
import io.element.android.libraries.matrix.api.timeline.item.event.FailedToParseStateContent
@@ -42,7 +41,6 @@ import javax.inject.Inject
@ContributesBinding(SessionScope::class)
class DefaultTimelineEventFormatter @Inject constructor(
private val sp: StringProvider,
- private val matrixClient: MatrixClient,
private val buildMeta: BuildMeta,
private val roomMembershipContentFormatter: RoomMembershipContentFormatter,
private val profileChangeContentFormatter: ProfileChangeContentFormatter,
@@ -50,7 +48,7 @@ class DefaultTimelineEventFormatter @Inject constructor(
) : TimelineEventFormatter {
override fun format(event: EventTimelineItem): CharSequence? {
- val isOutgoing = matrixClient.isMe(event.sender)
+ val isOutgoing = event.isOwn
val senderDisplayName = (event.senderProfile as? ProfileTimelineDetails.Ready)?.displayName ?: event.sender.value
return when (val content = event.content) {
is RoomMembershipContent -> {
diff --git a/libraries/eventformatter/impl/src/main/res/values-hu/translations.xml b/libraries/eventformatter/impl/src/main/res/values-hu/translations.xml
new file mode 100644
index 0000000000..dd38dcbbe4
--- /dev/null
+++ b/libraries/eventformatter/impl/src/main/res/values-hu/translations.xml
@@ -0,0 +1,57 @@
+
+
+ "(a profilkép is megváltozott)"
+ "%1$s megváltoztatta a profilképét"
+ "Megváltoztatta a profilképét"
+ "%1$s megváltoztatta a megjelenítendő nevét: %2$s → %3$s"
+ "Megváltoztatta a megjelenítendő nevét: %1$s → %2$s"
+ "%1$s eltávolította a megjelenítendő nevét (ez volt: %2$s)"
+ "Eltávolította a megjelenítendő nevét (ez volt: %1$s)"
+ "%1$s beállította a megjelenítendő nevét: %2$s"
+ "Beállította a megjelenítendő nevét: %1$s"
+ "%1$s megváltoztatta a szoba profilképét"
+ "Megváltoztatta a szoba profilképét"
+ "%1$s eltávolította a szoba profilképét"
+ "Eltávolítottad a szoba profilképét"
+ "%1$s kitiltotta: %2$s"
+ "Kitiltotta: %1$s"
+ "%1$s létrehozta a szobát"
+ "Létrehozta a szobát"
+ "%1$s meghívta: %2$s"
+ "%1$s elfogadta a meghívást"
+ "Elfogadta a meghívást"
+ "Meghívta: %1$s"
+ "%1$s meghívta"
+ "%1$s csatlakozott a szobához"
+ "Csatlakozott a szobához"
+ "%1$s kérte, hogy csatlakozhasson"
+ "%1$s engedélyezte, hogy %2$s csatlakozhasson"
+ "Engedélyezte, hogy %1$s csatlakozhasson"
+ "Kérte, hogy csatlakozhasson"
+ "%1$s elutasította %2$s kérését, hogy csatlakozhasson"
+ "Elutasította %1$s kérését, hogy csatlakozhasson"
+ "%1$s elutasította a kérését, hogy csatlakozhasson"
+ "%1$s már nem akar csatlakozni"
+ "Lemondta a csatlakozási kérését"
+ "%1$s elhagyta a szobát"
+ "Elhagyta a szobát"
+ "%1$s megváltoztatta a szoba nevét: %2$s"
+ "Megváltoztatta a szoba nevét: %1$s"
+ "%1$s eltávolította a szoba nevét"
+ "Eltávolította a szoba nevét"
+ "%1$s elutasította a meghívást"
+ "Elutasította a meghívást"
+ "%1$s eltávolította: %2$s"
+ "Eltávolította: %1$s"
+ "%1$s meghívót küldött %2$s számára, hogy csatlakozzon a szobához"
+ "Meghívót küldött %1$s számára, hogy csatlakozzon a szobához"
+ "%1$s visszavonta %2$s meghívását, hogy csatlakozzon a szobához"
+ "Visszavonta %1$s meghívását, hogy csatlakozzon a szobához"
+ "%1$s megváltoztatta a témát: %2$s"
+ "Megváltoztatta a témát: %1$s"
+ "%1$s eltávolította a szoba témáját"
+ "Eltávolította a szoba témáját"
+ "%1$s visszavonta %2$s kitiltását"
+ "Visszavonta %1$s kitiltását"
+ "%1$s ismeretlen változást hajtott végre a tagságában"
+
diff --git a/libraries/eventformatter/impl/src/main/res/values-in/translations.xml b/libraries/eventformatter/impl/src/main/res/values-in/translations.xml
new file mode 100644
index 0000000000..67ba9b03be
--- /dev/null
+++ b/libraries/eventformatter/impl/src/main/res/values-in/translations.xml
@@ -0,0 +1,57 @@
+
+
+ "(avatar juga diubah)"
+ "%1$s mengubah avatarnya"
+ "Anda mengubah avatar sendiri"
+ "%1$s mengubah nama tampilannya dari %2$s menjadi %3$s"
+ "Anda mengubah nama tampilan sendiri dari %1$s menjadi %2$s"
+ "%1$s menghapus nama tampilannya (sebelumnya %2$s)"
+ "Anda menghapus nama tampilan sendiri (sebelumnya %1$s)"
+ "%1$s menetapkan nama tampilannya menjadi %2$s"
+ "Anda menetapkan nama tampilan sendiri menjadi %1$s"
+ "%1$s mengubah avatar ruangan"
+ "Anda mengubah avatar ruangan"
+ "%1$s menghapus avatar ruangan"
+ "Anda menghapus avatar ruangan"
+ "%1$s memblokir %2$s"
+ "Anda memblokir %1$s"
+ "%1$s membuat ruangan"
+ "Anda membuat ruangan"
+ "%1$s mengundang %2$s"
+ "%1$s menerima undangan"
+ "Anda menerima undangan"
+ "Anda mengundang %1$s"
+ "%1$s mengundang Anda"
+ "%1$s bergabung ke ruangan"
+ "Anda bergabung ke ruangan"
+ "%1$s meminta untuk bergabung"
+ "%1$s memperbolehkan %2$s untuk bergabung"
+ "%1$s memperbolehkan Anda untuk bergabung"
+ "Anda meminta untuk bergabung"
+ "%1$s menolak permintaan %2$s untuk bergabung"
+ "Anda menolak permintaan %1$s untuk bergabung"
+ "%1$s menolak permintaan Anda untuk bergabung"
+ "%1$s tidak lagi tertarik untuk bergabung"
+ "Anda membatalkan permintaan sendiri untuk bergabung"
+ "%1$s meninggalkan ruangan"
+ "Anda keluar dari ruangan"
+ "%1$s mengubah nama ruangan menjadi: %2$s"
+ "Anda mengubah nama ruangan menjadi: %1$s"
+ "%1$s menghapus nama ruangan"
+ "Anda menghapus nama ruangan"
+ "%1$s menolak undangan"
+ "Anda menolak undangan"
+ "%1$s mengeluarkan %2$s"
+ "Anda mengeluarkan %1$s"
+ "%1$s mengirimkan undangan kepada %2$s untuk bergabung ke ruangan"
+ "Anda mengirimkan undangan kepada %1$s untuk bergabung ke ruangan"
+ "%1$s menghapus undangan kepada %2$s untuk bergabung ke ruangan"
+ "Anda menghapus undangan kepada %1$s untuk bergabung ke ruangan"
+ "%1$s mengubah topik menjadi: %2$s"
+ "Anda mengubah topik menjadi: %1$s"
+ "%1$s menghapus topik ruangan"
+ "Anda menghapus topik ruangan"
+ "%1$s membatalkan pemblokiran %2$s"
+ "Anda membatalkan pemblokiran %1$s"
+ "%1$s membuat perubahan keanggotaan yang tidak diketahui"
+
diff --git a/libraries/eventformatter/impl/src/test/kotlin/io/element/android/libraries/eventformatter/impl/DefaultRoomLastMessageFormatterTest.kt b/libraries/eventformatter/impl/src/test/kotlin/io/element/android/libraries/eventformatter/impl/DefaultRoomLastMessageFormatterTest.kt
index 8eed121568..6b7d52118d 100644
--- a/libraries/eventformatter/impl/src/test/kotlin/io/element/android/libraries/eventformatter/impl/DefaultRoomLastMessageFormatterTest.kt
+++ b/libraries/eventformatter/impl/src/test/kotlin/io/element/android/libraries/eventformatter/impl/DefaultRoomLastMessageFormatterTest.kt
@@ -18,7 +18,8 @@ package io.element.android.libraries.eventformatter.impl
import android.content.Context
import androidx.compose.ui.text.AnnotatedString
-import com.google.common.truth.Truth
+import com.google.common.truth.Truth.assertThat
+import com.google.common.truth.Truth.assertWithMessage
import io.element.android.libraries.matrix.api.core.UserId
import io.element.android.libraries.matrix.api.media.ImageInfo
import io.element.android.libraries.matrix.api.media.MediaSource
@@ -75,7 +76,6 @@ class DefaultRoomLastMessageFormatterTest {
val stringProvider = AndroidStringProvider(context.resources)
formatter = DefaultRoomLastMessageFormatter(
sp = AndroidStringProvider(context.resources),
- matrixClient = fakeMatrixClient,
roomMembershipContentFormatter = RoomMembershipContentFormatter(fakeMatrixClient, stringProvider),
profileChangeContentFormatter = ProfileChangeContentFormatter(stringProvider),
stateContentFormatter = StateContentFormatter(stringProvider)
@@ -91,10 +91,10 @@ class DefaultRoomLastMessageFormatterTest {
val message = createRoomEvent(false, senderName, RedactedContent)
val result = formatter.format(message, isDm)
if (isDm) {
- Truth.assertThat(result).isEqualTo(expected)
+ assertThat(result).isEqualTo(expected)
} else {
- Truth.assertThat(result).isInstanceOf(AnnotatedString::class.java)
- Truth.assertThat(result.toString()).isEqualTo("$senderName: $expected")
+ assertThat(result).isInstanceOf(AnnotatedString::class.java)
+ assertThat(result.toString()).isEqualTo("$senderName: $expected")
}
}
}
@@ -106,7 +106,7 @@ class DefaultRoomLastMessageFormatterTest {
val info = ImageInfo(null, null, null, null, null, null, null)
val message = createRoomEvent(false, null, StickerContent(body, info, "url"))
val result = formatter.format(message, false)
- Truth.assertThat(result).isEqualTo(body)
+ assertThat(result).isEqualTo(body)
}
@Test
@@ -118,10 +118,10 @@ class DefaultRoomLastMessageFormatterTest {
val message = createRoomEvent(false, senderName, UnableToDecryptContent(UnableToDecryptContent.Data.Unknown))
val result = formatter.format(message, isDm)
if (isDm) {
- Truth.assertThat(result).isEqualTo(expected)
+ assertThat(result).isEqualTo(expected)
} else {
- Truth.assertThat(result).isInstanceOf(AnnotatedString::class.java)
- Truth.assertThat(result.toString()).isEqualTo("$senderName: $expected")
+ assertThat(result).isInstanceOf(AnnotatedString::class.java)
+ assertThat(result.toString()).isEqualTo("$senderName: $expected")
}
}
}
@@ -140,10 +140,10 @@ class DefaultRoomLastMessageFormatterTest {
val message = createRoomEvent(false, senderName, type)
val result = formatter.format(message, isDm)
if (isDm) {
- Truth.assertWithMessage("$type was not properly handled").that(result).isEqualTo(expected)
+ assertWithMessage("$type was not properly handled").that(result).isEqualTo(expected)
} else {
- Truth.assertWithMessage("$type does not create an AnnotatedString").that(result).isInstanceOf(AnnotatedString::class.java)
- Truth.assertWithMessage("$type was not properly handled").that(result.toString()).isEqualTo("$senderName: $expected")
+ assertWithMessage("$type does not create an AnnotatedString").that(result).isInstanceOf(AnnotatedString::class.java)
+ assertWithMessage("$type was not properly handled").that(result.toString()).isEqualTo("$senderName: $expected")
}
}
}
@@ -203,7 +203,7 @@ class DefaultRoomLastMessageFormatterTest {
is NoticeMessageType,
is OtherMessageType -> body
}
- Truth.assertWithMessage("$type was not properly handled for DM").that(result).isEqualTo(expectedResult)
+ assertWithMessage("$type was not properly handled for DM").that(result).isEqualTo(expectedResult)
}
// Verify results of Room mode
@@ -233,11 +233,11 @@ class DefaultRoomLastMessageFormatterTest {
is OtherMessageType -> true
}
if (shouldCreateAnnotatedString) {
- Truth.assertWithMessage("$type doesn't produce an AnnotatedString")
+ assertWithMessage("$type doesn't produce an AnnotatedString")
.that(result)
.isInstanceOf(AnnotatedString::class.java)
}
- Truth.assertWithMessage("$type was not properly handled for room").that(string).isEqualTo(expectedResult)
+ assertWithMessage("$type was not properly handled for room").that(string).isEqualTo(expectedResult)
}
}
@@ -254,11 +254,11 @@ class DefaultRoomLastMessageFormatterTest {
val youJoinedRoomEvent = createRoomEvent(sentByYou = true, senderDisplayName = null, content = youContent)
val youJoinedRoom = formatter.format(youJoinedRoomEvent, false)
- Truth.assertThat(youJoinedRoom).isEqualTo("You joined the room")
+ assertThat(youJoinedRoom).isEqualTo("You joined the room")
val someoneJoinedRoomEvent = createRoomEvent(sentByYou = false, senderDisplayName = otherName, content = someoneContent)
val someoneJoinedRoom = formatter.format(someoneJoinedRoomEvent, false)
- Truth.assertThat(someoneJoinedRoom).isEqualTo("${someoneContent.userId} joined the room")
+ assertThat(someoneJoinedRoom).isEqualTo("${someoneContent.userId} joined the room")
}
@Test
@@ -270,11 +270,11 @@ class DefaultRoomLastMessageFormatterTest {
val youLeftRoomEvent = createRoomEvent(sentByYou = true, senderDisplayName = null, content = youContent)
val youLeftRoom = formatter.format(youLeftRoomEvent, false)
- Truth.assertThat(youLeftRoom).isEqualTo("You left the room")
+ assertThat(youLeftRoom).isEqualTo("You left the room")
val someoneLeftRoomEvent = createRoomEvent(sentByYou = false, senderDisplayName = otherName, content = someoneContent)
val someoneLeftRoom = formatter.format(someoneLeftRoomEvent, false)
- Truth.assertThat(someoneLeftRoom).isEqualTo("${someoneContent.userId} left the room")
+ assertThat(someoneLeftRoom).isEqualTo("${someoneContent.userId} left the room")
}
@Test
@@ -288,19 +288,19 @@ class DefaultRoomLastMessageFormatterTest {
val youBannedEvent = createRoomEvent(sentByYou = true, senderDisplayName = null, content = youContent)
val youBanned = formatter.format(youBannedEvent, false)
- Truth.assertThat(youBanned).isEqualTo("You banned ${youContent.userId}")
+ assertThat(youBanned).isEqualTo("You banned ${youContent.userId}")
val youKickBannedEvent = createRoomEvent(sentByYou = true, senderDisplayName = null, content = youKickedContent)
val youKickedBanned = formatter.format(youKickBannedEvent, false)
- Truth.assertThat(youKickedBanned).isEqualTo("You banned ${youContent.userId}")
+ assertThat(youKickedBanned).isEqualTo("You banned ${youContent.userId}")
val someoneBannedEvent = createRoomEvent(sentByYou = false, senderDisplayName = otherName, content = someoneContent)
val someoneBanned = formatter.format(someoneBannedEvent, false)
- Truth.assertThat(someoneBanned).isEqualTo("$otherName banned ${someoneContent.userId}")
+ assertThat(someoneBanned).isEqualTo("$otherName banned ${someoneContent.userId}")
val someoneKickBannedEvent = createRoomEvent(sentByYou = false, senderDisplayName = otherName, content = someoneKickedContent)
val someoneKickBanned = formatter.format(someoneKickBannedEvent, false)
- Truth.assertThat(someoneKickBanned).isEqualTo("$otherName banned ${someoneContent.userId}")
+ assertThat(someoneKickBanned).isEqualTo("$otherName banned ${someoneContent.userId}")
}
@Test
@@ -312,11 +312,11 @@ class DefaultRoomLastMessageFormatterTest {
val youUnbannedEvent = createRoomEvent(sentByYou = true, senderDisplayName = null, content = youContent)
val youUnbanned = formatter.format(youUnbannedEvent, false)
- Truth.assertThat(youUnbanned).isEqualTo("You unbanned ${youContent.userId}")
+ assertThat(youUnbanned).isEqualTo("You unbanned ${youContent.userId}")
val someoneUnbannedEvent = createRoomEvent(sentByYou = false, senderDisplayName = otherName, content = someoneContent)
val someoneUnbanned = formatter.format(someoneUnbannedEvent, false)
- Truth.assertThat(someoneUnbanned).isEqualTo("$otherName unbanned ${someoneContent.userId}")
+ assertThat(someoneUnbanned).isEqualTo("$otherName unbanned ${someoneContent.userId}")
}
@Test
@@ -328,11 +328,11 @@ class DefaultRoomLastMessageFormatterTest {
val youKickedEvent = createRoomEvent(sentByYou = true, senderDisplayName = null, content = youContent)
val youKicked = formatter.format(youKickedEvent, false)
- Truth.assertThat(youKicked).isEqualTo("You removed ${youContent.userId}")
+ assertThat(youKicked).isEqualTo("You removed ${youContent.userId}")
val someoneKickedEvent = createRoomEvent(sentByYou = false, senderDisplayName = otherName, content = someoneContent)
val someoneKicked = formatter.format(someoneKickedEvent, false)
- Truth.assertThat(someoneKicked).isEqualTo("$otherName removed ${someoneContent.userId}")
+ assertThat(someoneKicked).isEqualTo("$otherName removed ${someoneContent.userId}")
}
@Test
@@ -344,15 +344,15 @@ class DefaultRoomLastMessageFormatterTest {
val youWereInvitedEvent = createRoomEvent(sentByYou = false, senderDisplayName = otherName, content = youContent)
val youWereInvited = formatter.format(youWereInvitedEvent, false)
- Truth.assertThat(youWereInvited).isEqualTo("$otherName invited you")
+ assertThat(youWereInvited).isEqualTo("$otherName invited you")
val youInvitedEvent = createRoomEvent(sentByYou = true, senderDisplayName = null, content = someoneContent)
val youInvited = formatter.format(youInvitedEvent, false)
- Truth.assertThat(youInvited).isEqualTo("You invited ${someoneContent.userId}")
+ assertThat(youInvited).isEqualTo("You invited ${someoneContent.userId}")
val someoneInvitedEvent = createRoomEvent(sentByYou = false, senderDisplayName = otherName, content = someoneContent)
val someoneInvited = formatter.format(someoneInvitedEvent, false)
- Truth.assertThat(someoneInvited).isEqualTo("$otherName invited ${someoneContent.userId}")
+ assertThat(someoneInvited).isEqualTo("$otherName invited ${someoneContent.userId}")
}
@Test
@@ -364,11 +364,11 @@ class DefaultRoomLastMessageFormatterTest {
val youAcceptedInviteEvent = createRoomEvent(sentByYou = true, senderDisplayName = null, content = youContent)
val youAcceptedInvite = formatter.format(youAcceptedInviteEvent, false)
- Truth.assertThat(youAcceptedInvite).isEqualTo("You accepted the invite")
+ assertThat(youAcceptedInvite).isEqualTo("You accepted the invite")
val someoneAcceptedInviteEvent = createRoomEvent(sentByYou = false, senderDisplayName = otherName, content = someoneContent)
val someoneAcceptedInvite = formatter.format(someoneAcceptedInviteEvent, false)
- Truth.assertThat(someoneAcceptedInvite).isEqualTo("${someoneContent.userId} accepted the invite")
+ assertThat(someoneAcceptedInvite).isEqualTo("${someoneContent.userId} accepted the invite")
}
@Test
@@ -380,11 +380,11 @@ class DefaultRoomLastMessageFormatterTest {
val youRejectedInviteEvent = createRoomEvent(sentByYou = true, senderDisplayName = null, content = youContent)
val youRejectedInvite = formatter.format(youRejectedInviteEvent, false)
- Truth.assertThat(youRejectedInvite).isEqualTo("You rejected the invitation")
+ assertThat(youRejectedInvite).isEqualTo("You rejected the invitation")
val someoneRejectedInviteEvent = createRoomEvent(sentByYou = false, senderDisplayName = otherName, content = someoneContent)
val someoneRejectedInvite = formatter.format(someoneRejectedInviteEvent, false)
- Truth.assertThat(someoneRejectedInvite).isEqualTo("${someoneContent.userId} rejected the invitation")
+ assertThat(someoneRejectedInvite).isEqualTo("${someoneContent.userId} rejected the invitation")
}
@Test
@@ -395,11 +395,11 @@ class DefaultRoomLastMessageFormatterTest {
val youRevokedInviteEvent = createRoomEvent(sentByYou = true, senderDisplayName = null, content = someoneContent)
val youRevokedInvite = formatter.format(youRevokedInviteEvent, false)
- Truth.assertThat(youRevokedInvite).isEqualTo("You revoked the invitation for ${someoneContent.userId} to join the room")
+ assertThat(youRevokedInvite).isEqualTo("You revoked the invitation for ${someoneContent.userId} to join the room")
val someoneRevokedInviteEvent = createRoomEvent(sentByYou = false, senderDisplayName = otherName, content = someoneContent)
val someoneRevokedInvite = formatter.format(someoneRevokedInviteEvent, false)
- Truth.assertThat(someoneRevokedInvite).isEqualTo("$otherName revoked the invitation for ${someoneContent.userId} to join the room")
+ assertThat(someoneRevokedInvite).isEqualTo("$otherName revoked the invitation for ${someoneContent.userId} to join the room")
}
@Test
@@ -411,11 +411,11 @@ class DefaultRoomLastMessageFormatterTest {
val youKnockedEvent = createRoomEvent(sentByYou = true, senderDisplayName = null, content = youContent)
val youKnocked = formatter.format(youKnockedEvent, false)
- Truth.assertThat(youKnocked).isEqualTo("You requested to join")
+ assertThat(youKnocked).isEqualTo("You requested to join")
val someoneKnockedEvent = createRoomEvent(sentByYou = false, senderDisplayName = otherName, content = someoneContent)
val someoneKnocked = formatter.format(someoneKnockedEvent, false)
- Truth.assertThat(someoneKnocked).isEqualTo("${someoneContent.userId} requested to join")
+ assertThat(someoneKnocked).isEqualTo("${someoneContent.userId} requested to join")
}
@Test
@@ -426,11 +426,11 @@ class DefaultRoomLastMessageFormatterTest {
val youAcceptedKnockEvent = createRoomEvent(sentByYou = true, senderDisplayName = null, content = someoneContent)
val youAcceptedKnock = formatter.format(youAcceptedKnockEvent, false)
- Truth.assertThat(youAcceptedKnock).isEqualTo("${someoneContent.userId} allowed you to join")
+ assertThat(youAcceptedKnock).isEqualTo("${someoneContent.userId} allowed you to join")
val someoneAcceptedKnockEvent = createRoomEvent(sentByYou = false, senderDisplayName = otherName, content = someoneContent)
val someoneAcceptedKnock = formatter.format(someoneAcceptedKnockEvent, false)
- Truth.assertThat(someoneAcceptedKnock).isEqualTo("$otherName allowed ${someoneContent.userId} to join")
+ assertThat(someoneAcceptedKnock).isEqualTo("$otherName allowed ${someoneContent.userId} to join")
}
@Test
@@ -442,11 +442,11 @@ class DefaultRoomLastMessageFormatterTest {
val youRetractedKnockEvent = createRoomEvent(sentByYou = true, senderDisplayName = null, content = youContent)
val youRetractedKnock = formatter.format(youRetractedKnockEvent, false)
- Truth.assertThat(youRetractedKnock).isEqualTo("You cancelled your request to join")
+ assertThat(youRetractedKnock).isEqualTo("You cancelled your request to join")
val someoneRetractedKnockEvent = createRoomEvent(sentByYou = false, senderDisplayName = otherName, content = someoneContent)
val someoneRetractedKnock = formatter.format(someoneRetractedKnockEvent, false)
- Truth.assertThat(someoneRetractedKnock).isEqualTo("${someoneContent.userId} is no longer interested in joining")
+ assertThat(someoneRetractedKnock).isEqualTo("${someoneContent.userId} is no longer interested in joining")
}
@Test
@@ -458,15 +458,15 @@ class DefaultRoomLastMessageFormatterTest {
val youDeniedKnockEvent = createRoomEvent(sentByYou = true, senderDisplayName = null, content = someoneContent)
val youDeniedKnock = formatter.format(youDeniedKnockEvent, false)
- Truth.assertThat(youDeniedKnock).isEqualTo("You rejected ${someoneContent.userId}'s request to join")
+ assertThat(youDeniedKnock).isEqualTo("You rejected ${someoneContent.userId}'s request to join")
val someoneDeniedKnockEvent = createRoomEvent(sentByYou = false, senderDisplayName = otherName, content = someoneContent)
val someoneDeniedKnock = formatter.format(someoneDeniedKnockEvent, false)
- Truth.assertThat(someoneDeniedKnock).isEqualTo("$otherName rejected ${someoneContent.userId}'s request to join")
+ assertThat(someoneDeniedKnock).isEqualTo("$otherName rejected ${someoneContent.userId}'s request to join")
val someoneDeniedYourKnockEvent = createRoomEvent(sentByYou = false, senderDisplayName = otherName, content = youContent)
val someoneDeniedYourKnock = formatter.format(someoneDeniedYourKnockEvent, false)
- Truth.assertThat(someoneDeniedYourKnock).isEqualTo("$otherName rejected your request to join")
+ assertThat(someoneDeniedYourKnock).isEqualTo("$otherName rejected your request to join")
}
@Test
@@ -481,7 +481,7 @@ class DefaultRoomLastMessageFormatterTest {
change to result
}
val expected = otherChanges.map { it to null }
- Truth.assertThat(results).isEqualTo(expected)
+ assertThat(results).isEqualTo(expected)
}
// endregion
@@ -497,19 +497,19 @@ class DefaultRoomLastMessageFormatterTest {
val youChangedRoomAvatarEvent = createRoomEvent(sentByYou = true, senderDisplayName = null, content = changedContent)
val youChangedRoomAvatar = formatter.format(youChangedRoomAvatarEvent, false)
- Truth.assertThat(youChangedRoomAvatar).isEqualTo("You changed the room avatar")
+ assertThat(youChangedRoomAvatar).isEqualTo("You changed the room avatar")
val someoneChangedRoomAvatarEvent = createRoomEvent(sentByYou = false, senderDisplayName = otherName, content = changedContent)
val someoneChangedRoomAvatar = formatter.format(someoneChangedRoomAvatarEvent, false)
- Truth.assertThat(someoneChangedRoomAvatar).isEqualTo("$otherName changed the room avatar")
+ assertThat(someoneChangedRoomAvatar).isEqualTo("$otherName changed the room avatar")
val youRemovedRoomAvatarEvent = createRoomEvent(sentByYou = true, senderDisplayName = null, content = removedContent)
val youRemovedRoomAvatar = formatter.format(youRemovedRoomAvatarEvent, false)
- Truth.assertThat(youRemovedRoomAvatar).isEqualTo("You removed the room avatar")
+ assertThat(youRemovedRoomAvatar).isEqualTo("You removed the room avatar")
val someoneRemovedRoomAvatarEvent = createRoomEvent(sentByYou = false, senderDisplayName = otherName, content = removedContent)
val someoneRemovedRoomAvatar = formatter.format(someoneRemovedRoomAvatarEvent, false)
- Truth.assertThat(someoneRemovedRoomAvatar).isEqualTo("$otherName removed the room avatar")
+ assertThat(someoneRemovedRoomAvatar).isEqualTo("$otherName removed the room avatar")
}
@Test
@@ -520,11 +520,11 @@ class DefaultRoomLastMessageFormatterTest {
val youCreatedRoomMessage = createRoomEvent(sentByYou = true, senderDisplayName = null, content = content)
val youCreatedRoom = formatter.format(youCreatedRoomMessage, false)
- Truth.assertThat(youCreatedRoom).isEqualTo("You created the room")
+ assertThat(youCreatedRoom).isEqualTo("You created the room")
val someoneCreatedRoomEvent = createRoomEvent(sentByYou = false, senderDisplayName = otherName, content = content)
val someoneCreatedRoom = formatter.format(someoneCreatedRoomEvent, false)
- Truth.assertThat(someoneCreatedRoom).isEqualTo("$otherName created the room")
+ assertThat(someoneCreatedRoom).isEqualTo("$otherName created the room")
}
@Test
@@ -535,11 +535,11 @@ class DefaultRoomLastMessageFormatterTest {
val youCreatedRoomMessage = createRoomEvent(sentByYou = true, senderDisplayName = null, content = content)
val youCreatedRoom = formatter.format(youCreatedRoomMessage, false)
- Truth.assertThat(youCreatedRoom).isEqualTo("Encryption enabled")
+ assertThat(youCreatedRoom).isEqualTo("Encryption enabled")
val someoneCreatedRoomEvent = createRoomEvent(sentByYou = false, senderDisplayName = otherName, content = content)
val someoneCreatedRoom = formatter.format(someoneCreatedRoomEvent, false)
- Truth.assertThat(someoneCreatedRoom).isEqualTo("Encryption enabled")
+ assertThat(someoneCreatedRoom).isEqualTo("Encryption enabled")
}
@Test
@@ -552,19 +552,19 @@ class DefaultRoomLastMessageFormatterTest {
val youChangedRoomNameEvent = createRoomEvent(sentByYou = true, senderDisplayName = null, content = changedContent)
val youChangedRoomName = formatter.format(youChangedRoomNameEvent, false)
- Truth.assertThat(youChangedRoomName).isEqualTo("You changed the room name to: $newName")
+ assertThat(youChangedRoomName).isEqualTo("You changed the room name to: $newName")
val someoneChangedRoomNameEvent = createRoomEvent(sentByYou = false, senderDisplayName = otherName, content = changedContent)
val someoneChangedRoomName = formatter.format(someoneChangedRoomNameEvent, false)
- Truth.assertThat(someoneChangedRoomName).isEqualTo("$otherName changed the room name to: $newName")
+ assertThat(someoneChangedRoomName).isEqualTo("$otherName changed the room name to: $newName")
val youRemovedRoomNameEvent = createRoomEvent(sentByYou = true, senderDisplayName = null, content = removedContent)
val youRemovedRoomName = formatter.format(youRemovedRoomNameEvent, false)
- Truth.assertThat(youRemovedRoomName).isEqualTo("You removed the room name")
+ assertThat(youRemovedRoomName).isEqualTo("You removed the room name")
val someoneRemovedRoomNameEvent = createRoomEvent(sentByYou = false, senderDisplayName = otherName, content = removedContent)
val someoneRemovedRoomName = formatter.format(someoneRemovedRoomNameEvent, false)
- Truth.assertThat(someoneRemovedRoomName).isEqualTo("$otherName removed the room name")
+ assertThat(someoneRemovedRoomName).isEqualTo("$otherName removed the room name")
}
@Test
@@ -577,19 +577,19 @@ class DefaultRoomLastMessageFormatterTest {
val youInvitedSomeoneEvent = createRoomEvent(sentByYou = true, senderDisplayName = null, content = changedContent)
val youInvitedSomeone = formatter.format(youInvitedSomeoneEvent, false)
- Truth.assertThat(youInvitedSomeone).isEqualTo("You sent an invitation to $inviteeName to join the room")
+ assertThat(youInvitedSomeone).isEqualTo("You sent an invitation to $inviteeName to join the room")
val someoneInvitedSomeoneEvent = createRoomEvent(sentByYou = false, senderDisplayName = otherName, content = changedContent)
val someoneInvitedSomeone = formatter.format(someoneInvitedSomeoneEvent, false)
- Truth.assertThat(someoneInvitedSomeone).isEqualTo("$otherName sent an invitation to $inviteeName to join the room")
+ assertThat(someoneInvitedSomeone).isEqualTo("$otherName sent an invitation to $inviteeName to join the room")
val youInvitedNoOneEvent = createRoomEvent(sentByYou = true, senderDisplayName = null, content = removedContent)
val youInvitedNoOne = formatter.format(youInvitedNoOneEvent, false)
- Truth.assertThat(youInvitedNoOne).isNull()
+ assertThat(youInvitedNoOne).isNull()
val someoneInvitedNoOneEvent = createRoomEvent(sentByYou = false, senderDisplayName = otherName, content = removedContent)
val someoneInvitedNoOne = formatter.format(someoneInvitedNoOneEvent, false)
- Truth.assertThat(someoneInvitedNoOne).isNull()
+ assertThat(someoneInvitedNoOne).isNull()
}
@Test
@@ -602,19 +602,19 @@ class DefaultRoomLastMessageFormatterTest {
val youChangedRoomTopicEvent = createRoomEvent(sentByYou = true, senderDisplayName = null, content = changedContent)
val youChangedRoomTopic = formatter.format(youChangedRoomTopicEvent, false)
- Truth.assertThat(youChangedRoomTopic).isEqualTo("You changed the topic to: $roomTopic")
+ assertThat(youChangedRoomTopic).isEqualTo("You changed the topic to: $roomTopic")
val someoneChangedRoomTopicEvent = createRoomEvent(sentByYou = false, senderDisplayName = otherName, content = changedContent)
val someoneChangedRoomTopic = formatter.format(someoneChangedRoomTopicEvent, false)
- Truth.assertThat(someoneChangedRoomTopic).isEqualTo("$otherName changed the topic to: $roomTopic")
+ assertThat(someoneChangedRoomTopic).isEqualTo("$otherName changed the topic to: $roomTopic")
val youRemovedRoomTopicEvent = createRoomEvent(sentByYou = true, senderDisplayName = null, content = removedContent)
val youRemovedRoomTopic = formatter.format(youRemovedRoomTopicEvent, false)
- Truth.assertThat(youRemovedRoomTopic).isEqualTo("You removed the room topic")
+ assertThat(youRemovedRoomTopic).isEqualTo("You removed the room topic")
val someoneRemovedRoomTopicEvent = createRoomEvent(sentByYou = false, senderDisplayName = otherName, content = removedContent)
val someoneRemovedRoomTopic = formatter.format(someoneRemovedRoomTopicEvent, false)
- Truth.assertThat(someoneRemovedRoomTopic).isEqualTo("$otherName removed the room topic")
+ assertThat(someoneRemovedRoomTopic).isEqualTo("$otherName removed the room topic")
}
@Test
@@ -633,7 +633,7 @@ class DefaultRoomLastMessageFormatterTest {
state to result
}
val expected = otherStates.map { it to null }
- Truth.assertThat(results).isEqualTo(expected)
+ assertThat(results).isEqualTo(expected)
}
// endregion
@@ -652,35 +652,35 @@ class DefaultRoomLastMessageFormatterTest {
val youChangedAvatarEvent = createRoomEvent(sentByYou = true, senderDisplayName = null, content = changedContent)
val youChangedAvatar = formatter.format(youChangedAvatarEvent, false)
- Truth.assertThat(youChangedAvatar).isEqualTo("You changed your avatar")
+ assertThat(youChangedAvatar).isEqualTo("You changed your avatar")
val someoneChangeAvatarEvent = createRoomEvent(sentByYou = false, senderDisplayName = otherName, content = changedContent)
val someoneChangeAvatar = formatter.format(someoneChangeAvatarEvent, false)
- Truth.assertThat(someoneChangeAvatar).isEqualTo("$otherName changed their avatar")
+ assertThat(someoneChangeAvatar).isEqualTo("$otherName changed their avatar")
val youSetAvatarEvent = createRoomEvent(sentByYou = true, senderDisplayName = null, content = setContent)
val youSetAvatar = formatter.format(youSetAvatarEvent, false)
- Truth.assertThat(youSetAvatar).isEqualTo("You changed your avatar")
+ assertThat(youSetAvatar).isEqualTo("You changed your avatar")
val someoneSetAvatarEvent = createRoomEvent(sentByYou = false, senderDisplayName = otherName, content = setContent)
val someoneSetAvatar = formatter.format(someoneSetAvatarEvent, false)
- Truth.assertThat(someoneSetAvatar).isEqualTo("$otherName changed their avatar")
+ assertThat(someoneSetAvatar).isEqualTo("$otherName changed their avatar")
val youRemovedAvatarEvent = createRoomEvent(sentByYou = true, senderDisplayName = null, content = removedContent)
val youRemovedAvatar = formatter.format(youRemovedAvatarEvent, false)
- Truth.assertThat(youRemovedAvatar).isEqualTo("You changed your avatar")
+ assertThat(youRemovedAvatar).isEqualTo("You changed your avatar")
val someoneRemovedAvatarEvent = createRoomEvent(sentByYou = false, senderDisplayName = otherName, content = removedContent)
val someoneRemovedAvatar = formatter.format(someoneRemovedAvatarEvent, false)
- Truth.assertThat(someoneRemovedAvatar).isEqualTo("$otherName changed their avatar")
+ assertThat(someoneRemovedAvatar).isEqualTo("$otherName changed their avatar")
val unchangedEvent = createRoomEvent(sentByYou = true, senderDisplayName = otherName, content = sameContent)
val unchangedResult = formatter.format(unchangedEvent, false)
- Truth.assertThat(unchangedResult).isNull()
+ assertThat(unchangedResult).isNull()
val invalidEvent = createRoomEvent(sentByYou = true, senderDisplayName = otherName, content = invalidContent)
val invalidResult = formatter.format(invalidEvent, false)
- Truth.assertThat(invalidResult).isNull()
+ assertThat(invalidResult).isNull()
}
@Test
@@ -697,35 +697,35 @@ class DefaultRoomLastMessageFormatterTest {
val youChangedDisplayNameEvent = createRoomEvent(sentByYou = true, senderDisplayName = null, content = changedContent)
val youChangedDisplayName = formatter.format(youChangedDisplayNameEvent, false)
- Truth.assertThat(youChangedDisplayName).isEqualTo("You changed your display name from $oldDisplayName to $newDisplayName")
+ assertThat(youChangedDisplayName).isEqualTo("You changed your display name from $oldDisplayName to $newDisplayName")
val someoneChangedDisplayNameEvent = createRoomEvent(sentByYou = false, senderDisplayName = otherName, content = changedContent)
val someoneChangedDisplayName = formatter.format(someoneChangedDisplayNameEvent, false)
- Truth.assertThat(someoneChangedDisplayName).isEqualTo("$otherName changed their display name from $oldDisplayName to $newDisplayName")
+ assertThat(someoneChangedDisplayName).isEqualTo("$otherName changed their display name from $oldDisplayName to $newDisplayName")
val youSetDisplayNameEvent = createRoomEvent(sentByYou = true, senderDisplayName = null, content = setContent)
val youSetDisplayName = formatter.format(youSetDisplayNameEvent, false)
- Truth.assertThat(youSetDisplayName).isEqualTo("You set your display name to $newDisplayName")
+ assertThat(youSetDisplayName).isEqualTo("You set your display name to $newDisplayName")
val someoneSetDisplayNameEvent = createRoomEvent(sentByYou = false, senderDisplayName = otherName, content = setContent)
val someoneSetDisplayName = formatter.format(someoneSetDisplayNameEvent, false)
- Truth.assertThat(someoneSetDisplayName).isEqualTo("$otherName set their display name to $newDisplayName")
+ assertThat(someoneSetDisplayName).isEqualTo("$otherName set their display name to $newDisplayName")
val youRemovedDisplayNameEvent = createRoomEvent(sentByYou = true, senderDisplayName = null, content = removedContent)
val youRemovedDisplayName = formatter.format(youRemovedDisplayNameEvent, false)
- Truth.assertThat(youRemovedDisplayName).isEqualTo("You removed your display name (it was $oldDisplayName)")
+ assertThat(youRemovedDisplayName).isEqualTo("You removed your display name (it was $oldDisplayName)")
val someoneRemovedDisplayNameEvent = createRoomEvent(sentByYou = false, senderDisplayName = otherName, content = removedContent)
val someoneRemovedDisplayName = formatter.format(someoneRemovedDisplayNameEvent, false)
- Truth.assertThat(someoneRemovedDisplayName).isEqualTo("$otherName removed their display name (it was $oldDisplayName)")
+ assertThat(someoneRemovedDisplayName).isEqualTo("$otherName removed their display name (it was $oldDisplayName)")
val unchangedEvent = createRoomEvent(sentByYou = true, senderDisplayName = otherName, content = sameContent)
val unchangedResult = formatter.format(unchangedEvent, false)
- Truth.assertThat(unchangedResult).isNull()
+ assertThat(unchangedResult).isNull()
val invalidEvent = createRoomEvent(sentByYou = true, senderDisplayName = otherName, content = invalidContent)
val invalidResult = formatter.format(invalidEvent, false)
- Truth.assertThat(invalidResult).isNull()
+ assertThat(invalidResult).isNull()
}
@Test
@@ -754,15 +754,15 @@ class DefaultRoomLastMessageFormatterTest {
val youChangedBothEvent = createRoomEvent(sentByYou = true, senderDisplayName = null, content = changedContent)
val youChangedBoth = formatter.format(youChangedBothEvent, false)
- Truth.assertThat(youChangedBoth).isEqualTo("You changed your display name from $oldDisplayName to $newDisplayName\n(avatar was changed too)")
+ assertThat(youChangedBoth).isEqualTo("You changed your display name from $oldDisplayName to $newDisplayName\n(avatar was changed too)")
val invalidContentEvent = createRoomEvent(sentByYou = true, senderDisplayName = null, content = invalidContent)
val invalidMessage = formatter.format(invalidContentEvent, false)
- Truth.assertThat(invalidMessage).isNull()
+ assertThat(invalidMessage).isNull()
val sameContentEvent = createRoomEvent(sentByYou = true, senderDisplayName = null, content = sameContent)
val sameMessage = formatter.format(sameContentEvent, false)
- Truth.assertThat(sameMessage).isNull()
+ assertThat(sameMessage).isNull()
}
// endregion
@@ -775,10 +775,10 @@ class DefaultRoomLastMessageFormatterTest {
val pollContent = aPollContent()
val mineContentEvent = createRoomEvent(sentByYou = true, senderDisplayName = "Alice", content = pollContent)
- Truth.assertThat(formatter.format(mineContentEvent, true)).isEqualTo("Poll: Do you like polls?")
+ assertThat(formatter.format(mineContentEvent, true)).isEqualTo("Poll: Do you like polls?")
val contentEvent = createRoomEvent(sentByYou = false, senderDisplayName = "Bob", content = pollContent)
- Truth.assertThat(formatter.format(contentEvent, true)).isEqualTo("Poll: Do you like polls?")
+ assertThat(formatter.format(contentEvent, true)).isEqualTo("Poll: Do you like polls?")
}
@Test
@@ -787,10 +787,10 @@ class DefaultRoomLastMessageFormatterTest {
val pollContent = aPollContent()
val mineContentEvent = createRoomEvent(sentByYou = true, senderDisplayName = "Alice", content = pollContent)
- Truth.assertThat(formatter.format(mineContentEvent, false).toString()).isEqualTo("Alice: Poll: Do you like polls?")
+ assertThat(formatter.format(mineContentEvent, false).toString()).isEqualTo("Alice: Poll: Do you like polls?")
val contentEvent = createRoomEvent(sentByYou = false, senderDisplayName = "Bob", content = pollContent)
- Truth.assertThat(formatter.format(contentEvent, false).toString()).isEqualTo("Bob: Poll: Do you like polls?")
+ assertThat(formatter.format(contentEvent, false).toString()).isEqualTo("Bob: Poll: Do you like polls?")
}
// endregion
@@ -798,6 +798,11 @@ class DefaultRoomLastMessageFormatterTest {
private fun createRoomEvent(sentByYou: Boolean, senderDisplayName: String?, content: EventContent): EventTimelineItem {
val sender = if (sentByYou) A_USER_ID else UserId("@someone_else:domain")
val profile = ProfileTimelineDetails.Ready(senderDisplayName, false, null)
- return anEventTimelineItem(content = content, senderProfile = profile, sender = sender)
+ return anEventTimelineItem(
+ content = content,
+ senderProfile = profile,
+ sender = sender,
+ isOwn = sentByYou,
+ )
}
}
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 117005fd6f..fc2b605d47 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
@@ -37,7 +37,7 @@ class DefaultFeatureFlagServiceTest {
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.LocationSharing, true)
- assertThat(result).isEqualTo(false)
+ assertThat(result).isFalse()
}
@Test
@@ -45,7 +45,7 @@ class DefaultFeatureFlagServiceTest {
val featureFlagProvider = FakeMutableFeatureFlagProvider(0)
val featureFlagService = DefaultFeatureFlagService(setOf(featureFlagProvider))
val result = featureFlagService.setFeatureEnabled(FeatureFlags.LocationSharing, true)
- assertThat(result).isEqualTo(true)
+ assertThat(result).isTrue()
}
@Test
@@ -54,9 +54,9 @@ class DefaultFeatureFlagServiceTest {
val featureFlagService = DefaultFeatureFlagService(setOf(featureFlagProvider))
featureFlagService.setFeatureEnabled(FeatureFlags.LocationSharing, true)
featureFlagService.isFeatureEnabledFlow(FeatureFlags.LocationSharing).test {
- assertThat(awaitItem()).isEqualTo(true)
+ assertThat(awaitItem()).isTrue()
featureFlagService.setFeatureEnabled(FeatureFlags.LocationSharing, false)
- assertThat(awaitItem()).isEqualTo(false)
+ assertThat(awaitItem()).isFalse()
}
}
@@ -68,7 +68,7 @@ class DefaultFeatureFlagServiceTest {
lowPriorityFeatureFlagProvider.setFeatureEnabled(FeatureFlags.LocationSharing, false)
highPriorityFeatureFlagProvider.setFeatureEnabled(FeatureFlags.LocationSharing, true)
featureFlagService.isFeatureEnabledFlow(FeatureFlags.LocationSharing).test {
- assertThat(awaitItem()).isEqualTo(true)
+ assertThat(awaitItem()).isTrue()
}
}
}
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 f9ac0d84a5..dc452f1514 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
@@ -41,7 +41,7 @@ interface MatrixClient : Closeable {
val roomListService: RoomListService
val mediaLoader: MatrixMediaLoader
suspend fun getRoom(roomId: RoomId): MatrixRoom?
- suspend fun findDM(userId: UserId): MatrixRoom?
+ suspend fun findDM(userId: UserId): RoomId?
suspend fun ignoreUser(userId: UserId): Result
suspend fun unignoreUser(userId: UserId): Result
suspend fun createRoom(createRoomParams: CreateRoomParameters): Result
diff --git a/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/encryption/EncryptionService.kt b/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/encryption/EncryptionService.kt
index 534f5b68e2..522445b6c2 100644
--- a/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/encryption/EncryptionService.kt
+++ b/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/encryption/EncryptionService.kt
@@ -43,9 +43,9 @@ interface EncryptionService {
suspend fun doesBackupExistOnServer(): Result
/**
- * Note: accept bot recoveryKey and passphrase.
+ * Note: accept both recoveryKey and passphrase.
*/
- suspend fun fixRecoveryIssues(recoveryKey: String): Result
+ suspend fun recover(recoveryKey: String): Result
/**
* Wait for backup upload steady state.
diff --git a/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/encryption/RecoveryException.kt b/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/encryption/RecoveryException.kt
new file mode 100644
index 0000000000..fae2dad083
--- /dev/null
+++ b/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/encryption/RecoveryException.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.api.encryption
+
+import io.element.android.libraries.matrix.api.exception.ClientException
+
+sealed class RecoveryException(message: String) : Exception(message) {
+ class SecretStorage(message: String) : RecoveryException(message)
+ data object BackupExistsOnServer : RecoveryException("BackupExistsOnServer")
+ data class Client(val exception: ClientException) : RecoveryException(exception.message ?: "Unknown error")
+}
diff --git a/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/mxc/MxcTools.kt b/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/mxc/MxcTools.kt
new file mode 100644
index 0000000000..43a78d1d23
--- /dev/null
+++ b/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/mxc/MxcTools.kt
@@ -0,0 +1,42 @@
+/*
+ * 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.mxc
+
+import javax.inject.Inject
+
+class MxcTools @Inject constructor() {
+ /**
+ * Regex to match a Matrix Content (mxc://) URI.
+ *
+ * See: https://spec.matrix.org/v1.8/client-server-api/#matrix-content-mxc-uris
+ */
+ private val mxcRegex = Regex("""^mxc://([^/]+)/([^/]+)$""")
+
+ /**
+ * Sanitizes an mxcUri to be used as a relative file path.
+ *
+ * @param mxcUri the Matrix Content (mxc://) URI of the file.
+ * @return the relative file path as "/" or null if the mxcUri is invalid.
+ */
+ fun mxcUri2FilePath(mxcUri: String): String? = mxcRegex.matchEntire(mxcUri)?.let { match ->
+ buildString {
+ append(match.groupValues[1])
+ append("/")
+ append(match.groupValues[2])
+ }
+ }
+}
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 08f40c3376..8275b8ee5f 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
@@ -25,6 +25,7 @@ import io.element.android.libraries.matrix.api.timeline.item.event.MessageType
data class NotificationData(
val eventId: EventId,
val roomId: RoomId,
+ // mxc url
val senderAvatarUrl: String?,
val senderDisplayName: String?,
val roomAvatarUrl: String?,
@@ -34,8 +35,6 @@ data class NotificationData(
val isNoisy: Boolean,
val timestamp: Long,
val content: NotificationContent,
- // For images for instance
- val contentUrl: String?,
val hasMention: Boolean,
)
diff --git a/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/notificationsettings/NotificationSettingsService.kt b/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/notificationsettings/NotificationSettingsService.kt
index 71d46a2b8e..ca005e624a 100644
--- a/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/notificationsettings/NotificationSettingsService.kt
+++ b/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/notificationsettings/NotificationSettingsService.kt
@@ -38,5 +38,7 @@ interface NotificationSettingsService {
suspend fun setRoomMentionEnabled(enabled: Boolean): Result
suspend fun isCallEnabled(): Result
suspend fun setCallEnabled(enabled: Boolean): Result
+ suspend fun isInviteForMeEnabled(): Result
+ suspend fun setInviteForMeEnabled(enabled: Boolean): Result
suspend fun getRoomsWithUserDefinedRules(): Result>
}
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 a7cbdccfa2..ec1f49e4f8 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
@@ -132,7 +132,8 @@ interface MatrixRoom : Closeable {
suspend fun canUserTriggerRoomNotification(userId: UserId): Result
- suspend fun canUserJoinCall(userId: UserId): Result
+ suspend fun canUserJoinCall(userId: UserId): Result =
+ canUserSendState(userId, StateEventType.CALL_MEMBER)
suspend fun updateAvatar(mimeType: String, data: ByteArray): Result
diff --git a/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/room/StartDM.kt b/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/room/StartDM.kt
new file mode 100644
index 0000000000..7d0fd9a582
--- /dev/null
+++ b/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/room/StartDM.kt
@@ -0,0 +1,41 @@
+/*
+ * 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.room
+
+import io.element.android.libraries.matrix.api.MatrixClient
+import io.element.android.libraries.matrix.api.core.RoomId
+import io.element.android.libraries.matrix.api.core.UserId
+
+/**
+ * Try to find an existing DM with the given user, or create one if none exists.
+ */
+suspend fun MatrixClient.startDM(userId: UserId): StartDMResult {
+ val existingDM = findDM(userId)
+ return if (existingDM != null) {
+ StartDMResult.Success(existingDM, isNew = false)
+ } else {
+ createDM(userId).fold(
+ { StartDMResult.Success(it, isNew = true) },
+ { StartDMResult.Failure(it) }
+ )
+ }
+}
+
+sealed interface StartDMResult {
+ data class Success(val roomId: RoomId, val isNew: Boolean) : StartDMResult
+ data class Failure(val throwable: Throwable) : StartDMResult
+}
diff --git a/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/room/StateEventType.kt b/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/room/StateEventType.kt
index 50cde59b37..3cfacf4a23 100644
--- a/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/room/StateEventType.kt
+++ b/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/room/StateEventType.kt
@@ -20,6 +20,7 @@ enum class StateEventType {
POLICY_RULE_ROOM,
POLICY_RULE_SERVER,
POLICY_RULE_USER,
+ CALL_MEMBER,
ROOM_ALIASES,
ROOM_AVATAR,
ROOM_CANONICAL_ALIAS,
diff --git a/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/verification/SessionVerificationData.kt b/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/verification/SessionVerificationData.kt
new file mode 100644
index 0000000000..9368773ae8
--- /dev/null
+++ b/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/verification/SessionVerificationData.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.libraries.matrix.api.verification
+
+import androidx.compose.runtime.Immutable
+
+@Immutable
+sealed interface SessionVerificationData {
+ data class Emojis(
+ // 7 emojis
+ val emojis: List,
+ ) : SessionVerificationData
+
+ data class Decimals(
+ // 3 numbers
+ val decimals: List,
+ ) : SessionVerificationData
+}
+
+// https://spec.matrix.org/unstable/client-server-api/#sas-method-emoji
+data class VerificationEmoji(
+ val number: Int,
+ val emoji: String,
+ val description: String,
+)
diff --git a/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/verification/SessionVerificationService.kt b/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/verification/SessionVerificationService.kt
index 639b704823..db8fa1a939 100644
--- a/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/verification/SessionVerificationService.kt
+++ b/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/verification/SessionVerificationService.kt
@@ -17,7 +17,6 @@
package io.element.android.libraries.matrix.api.verification
import androidx.compose.runtime.Immutable
-import kotlinx.collections.immutable.ImmutableList
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.StateFlow
@@ -26,7 +25,7 @@ interface SessionVerificationService {
/**
* State of the current verification flow ([VerificationFlowState.Initial] if not started).
*/
- val verificationFlowState : StateFlow
+ val verificationFlowState: StateFlow
/**
* The internal service that checks verification can only run after the initial sync.
@@ -101,8 +100,8 @@ sealed interface VerificationFlowState {
/** Short Authentication String (SAS) verification started between the 2 devices. */
data object StartedSasVerification : VerificationFlowState
- /** Verification data for the SAS verification (emojis) received. */
- data class ReceivedVerificationData(val emoji: ImmutableList) : VerificationFlowState
+ /** Verification data for the SAS verification received. */
+ data class ReceivedVerificationData(val data: SessionVerificationData) : VerificationFlowState
/** Verification completed successfully. */
data object Finished : VerificationFlowState
diff --git a/libraries/matrix/api/src/test/kotlin/io/element/android/libraries/matrix/api/mxc/MxcToolsTest.kt b/libraries/matrix/api/src/test/kotlin/io/element/android/libraries/matrix/api/mxc/MxcToolsTest.kt
new file mode 100644
index 0000000000..652b5a6de6
--- /dev/null
+++ b/libraries/matrix/api/src/test/kotlin/io/element/android/libraries/matrix/api/mxc/MxcToolsTest.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.libraries.matrix.api.mxc
+
+import com.google.common.truth.Truth.assertThat
+import org.junit.Test
+
+class MxcToolsTest {
+ @Test
+ fun `mxcUri2FilePath returns extracted path`() {
+ val mxcTools = MxcTools()
+ val mxcUri = "mxc://server.org/abc123"
+ val filePath = mxcTools.mxcUri2FilePath(mxcUri)
+ assertThat(filePath).isEqualTo("server.org/abc123")
+ }
+
+ @Test
+ fun `mxcUri2FilePath returns null for invalid data`() {
+ val mxcTools = MxcTools()
+ assertThat(mxcTools.mxcUri2FilePath("")).isNull()
+ assertThat(mxcTools.mxcUri2FilePath("mxc://server.org")).isNull()
+ assertThat(mxcTools.mxcUri2FilePath("mxc://server.org/")).isNull()
+ assertThat(mxcTools.mxcUri2FilePath("m://server.org/abc123")).isNull()
+ }
+}
diff --git a/libraries/matrix/impl/build.gradle.kts b/libraries/matrix/impl/build.gradle.kts
index ef590c6889..41c84a0384 100644
--- a/libraries/matrix/impl/build.gradle.kts
+++ b/libraries/matrix/impl/build.gradle.kts
@@ -44,7 +44,7 @@ dependencies {
api(projects.libraries.matrix.api)
implementation(libs.dagger)
implementation(projects.libraries.core)
- implementation("net.java.dev.jna:jna:5.13.0@aar")
+ implementation("net.java.dev.jna:jna:5.14.0@aar")
implementation(libs.androidx.datastore.preferences)
implementation(libs.serialization.json)
implementation(libs.kotlinx.collections.immutable)
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 971e41414d..f7c157d2ba 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
@@ -91,7 +91,7 @@ import org.matrix.rustcomponents.sdk.RoomVisibility as RustRoomVisibility
import org.matrix.rustcomponents.sdk.SyncService as ClientSyncService
@OptIn(ExperimentalCoroutinesApi::class)
-class RustMatrixClient constructor(
+class RustMatrixClient(
private val client: Client,
private val syncService: ClientSyncService,
private val sessionStore: SessionStore,
@@ -119,10 +119,9 @@ class RustMatrixClient constructor(
.filterByPushRules()
.finish()
}
- private val notificationSettings = client.getNotificationSettings()
-
private val notificationService = RustNotificationService(sessionId, notificationClient, dispatchers, clock)
- private val notificationSettingsService = RustNotificationSettingsService(notificationSettings, dispatchers)
+ private val notificationSettingsService = RustNotificationSettingsService(client, dispatchers)
+ .apply { start() }
private val roomSyncSubscriber = RoomSyncSubscriber(innerRoomListService, dispatchers)
private val encryptionService = RustEncryptionService(
client = client,
@@ -241,9 +240,8 @@ class RustMatrixClient constructor(
}
}
- override suspend fun findDM(userId: UserId): MatrixRoom? {
- val roomId = client.getDmRoom(userId.value)?.use { RoomId(it.id()) }
- return roomId?.let { getRoom(it) }
+ override suspend fun findDM(userId: UserId): RoomId? {
+ return client.getDmRoom(userId.value)?.use { RoomId(it.id()) }
}
override suspend fun ignoreUser(userId: UserId): Result = withContext(sessionDispatcher) {
@@ -347,8 +345,7 @@ class RustMatrixClient constructor(
override fun close() {
sessionCoroutineScope.cancel()
clientDelegateTaskHandle?.cancelAndDestroy()
- notificationSettings.setDelegate(null)
- notificationSettings.destroy()
+ notificationSettingsService.destroy()
verificationService.destroy()
syncService.destroy()
innerRoomListService.destroy()
diff --git a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/encryption/RecoveryExceptionMapper.kt b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/encryption/RecoveryExceptionMapper.kt
new file mode 100644
index 0000000000..b21e035602
--- /dev/null
+++ b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/encryption/RecoveryExceptionMapper.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.libraries.matrix.impl.encryption
+
+import io.element.android.libraries.matrix.api.encryption.RecoveryException
+import io.element.android.libraries.matrix.api.exception.ClientException
+import io.element.android.libraries.matrix.impl.exception.mapClientException
+import org.matrix.rustcomponents.sdk.RecoveryException as RustRecoveryException
+
+fun Throwable.mapRecoveryException(): RecoveryException {
+ return when (this) {
+ is RustRecoveryException.SecretStorage -> RecoveryException.SecretStorage(
+ message = errorMessage
+ )
+ is RustRecoveryException.BackupExistsOnServer -> RecoveryException.BackupExistsOnServer
+ is RustRecoveryException.Client -> RecoveryException.Client(
+ source.mapClientException()
+ )
+ else -> RecoveryException.Client(
+ ClientException.Other("Unknown error")
+ )
+ }
+}
diff --git a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/encryption/RustEncryptionService.kt b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/encryption/RustEncryptionService.kt
index 10929f0494..8732645330 100644
--- a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/encryption/RustEncryptionService.kt
+++ b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/encryption/RustEncryptionService.kt
@@ -17,6 +17,7 @@
package io.element.android.libraries.matrix.impl.encryption
import io.element.android.libraries.core.coroutine.CoroutineDispatchers
+import io.element.android.libraries.core.extensions.mapFailure
import io.element.android.libraries.matrix.api.encryption.BackupState
import io.element.android.libraries.matrix.api.encryption.BackupUploadState
import io.element.android.libraries.matrix.api.encryption.EnableRecoveryProgress
@@ -110,6 +111,8 @@ internal class RustEncryptionService(
override suspend fun enableBackups(): Result = withContext(dispatchers.io) {
runCatching {
service.enableBackups()
+ }.mapFailure {
+ it.mapRecoveryException()
}
}
@@ -127,6 +130,8 @@ internal class RustEncryptionService(
)
// enableRecovery returns the encryption key, but we read it from the state flow
.let { }
+ }.mapFailure {
+ it.mapRecoveryException()
}
}
@@ -164,24 +169,32 @@ internal class RustEncryptionService(
override suspend fun disableRecovery(): Result = withContext(dispatchers.io) {
runCatching {
service.disableRecovery()
+ }.mapFailure {
+ it.mapRecoveryException()
}
}
override suspend fun isLastDevice(): Result = withContext(dispatchers.io) {
runCatching {
service.isLastDevice()
+ }.mapFailure {
+ it.mapRecoveryException()
}
}
override suspend fun resetRecoveryKey(): Result = withContext(dispatchers.io) {
runCatching {
service.resetRecoveryKey()
+ }.mapFailure {
+ it.mapRecoveryException()
}
}
- override suspend fun fixRecoveryIssues(recoveryKey: String): Result = withContext(dispatchers.io) {
+ override suspend fun recover(recoveryKey: String): Result = withContext(dispatchers.io) {
runCatching {
service.recover(recoveryKey)
+ }.mapFailure {
+ it.mapRecoveryException()
}
}
}
diff --git a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/encryption/SteadyStateExceptionMapper.kt b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/encryption/SteadyStateExceptionMapper.kt
index 0dfcee7196..7439f016d8 100644
--- a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/encryption/SteadyStateExceptionMapper.kt
+++ b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/encryption/SteadyStateExceptionMapper.kt
@@ -23,13 +23,13 @@ class SteadyStateExceptionMapper {
fun map(data: RustSteadyStateException): SteadyStateException {
return when (data) {
is RustSteadyStateException.BackupDisabled -> SteadyStateException.BackupDisabled(
- message = data.message
+ message = data.message.orEmpty()
)
is RustSteadyStateException.Connection -> SteadyStateException.Connection(
- message = data.message
+ message = data.message.orEmpty()
)
is RustSteadyStateException.Lagged -> SteadyStateException.Lagged(
- message = data.message
+ message = data.message.orEmpty()
)
}
}
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 9914a66c85..6285ba393f 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
@@ -52,7 +52,6 @@ class NotificationMapper(
isNoisy = item.isNoisy.orFalse(),
timestamp = item.timestamp() ?: clock.epochMillis(),
content = item.event.use { notificationContentMapper.map(it) },
- contentUrl = null,
hasMention = item.hasMention.orFalse(),
)
}
diff --git a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/notificationsettings/RustNotificationSettingsService.kt b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/notificationsettings/RustNotificationSettingsService.kt
index 42b2662a6d..6ddebfbe70 100644
--- a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/notificationsettings/RustNotificationSettingsService.kt
+++ b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/notificationsettings/RustNotificationSettingsService.kt
@@ -26,16 +26,16 @@ import kotlinx.coroutines.flow.MutableSharedFlow
import kotlinx.coroutines.flow.SharedFlow
import kotlinx.coroutines.flow.asSharedFlow
import kotlinx.coroutines.withContext
-import org.matrix.rustcomponents.sdk.NotificationSettings
+import org.matrix.rustcomponents.sdk.Client
import org.matrix.rustcomponents.sdk.NotificationSettingsDelegate
import org.matrix.rustcomponents.sdk.NotificationSettingsException
import timber.log.Timber
class RustNotificationSettingsService(
- private val notificationSettings: NotificationSettings,
+ client: Client,
private val dispatchers: CoroutineDispatchers,
) : NotificationSettingsService {
-
+ private val notificationSettings = client.getNotificationSettings()
private val _notificationSettingsChangeFlow = MutableSharedFlow(extraBufferCapacity = 1, onBufferOverflow = BufferOverflow.DROP_OLDEST)
override val notificationSettingsChangeFlow: SharedFlow = _notificationSettingsChangeFlow.asSharedFlow()
@@ -45,10 +45,15 @@ class RustNotificationSettingsService(
}
}
- init {
+ fun start() {
notificationSettings.setDelegate(notificationSettingsDelegate)
}
+ fun destroy() {
+ notificationSettings.setDelegate(null)
+ notificationSettings.destroy()
+ }
+
override suspend fun getRoomNotificationSettings(roomId: RoomId, isEncrypted: Boolean, isOneToOne: Boolean): Result =
runCatching {
notificationSettings.getRoomNotificationSettings(roomId.value, isEncrypted, isOneToOne).let(RoomNotificationSettingsMapper::map)
@@ -119,6 +124,18 @@ class RustNotificationSettingsService(
}
}
+ override suspend fun isInviteForMeEnabled(): Result = withContext(dispatchers.io) {
+ runCatching {
+ notificationSettings.isInviteForMeEnabled()
+ }
+ }
+
+ override suspend fun setInviteForMeEnabled(enabled: Boolean): Result = withContext(dispatchers.io) {
+ runCatching {
+ notificationSettings.setInviteForMeEnabled(enabled)
+ }
+ }
+
override suspend fun getRoomsWithUserDefinedRules(): Result> =
runCatching {
notificationSettings.getRoomsWithUserDefinedRules(enabled = true)
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 e509d05ad2..079f144130 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
@@ -360,12 +360,6 @@ class RustMatrixRoom(
}
}
- override suspend fun canUserJoinCall(userId: UserId): Result {
- return runCatching {
- innerRoom.canUserSendState(userId.value, StateEventType.ROOM_MEMBER_EVENT.map())
- }
- }
-
override suspend fun sendImage(file: File, thumbnailFile: File, imageInfo: ImageInfo, progressCallback: ProgressCallback?): Result {
return sendAttachment(listOf(file, thumbnailFile)) {
innerTimeline.sendImage(file.path, thumbnailFile.path, imageInfo.map(), progressCallback?.toProgressWatcher())
diff --git a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/room/StateEventType.kt b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/room/StateEventType.kt
index 2cd09e213c..fa2b731b61 100644
--- a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/room/StateEventType.kt
+++ b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/room/StateEventType.kt
@@ -23,6 +23,7 @@ fun StateEventType.map(): RustStateEventType = when (this) {
StateEventType.POLICY_RULE_ROOM -> RustStateEventType.POLICY_RULE_ROOM
StateEventType.POLICY_RULE_SERVER -> RustStateEventType.POLICY_RULE_SERVER
StateEventType.POLICY_RULE_USER -> RustStateEventType.POLICY_RULE_USER
+ StateEventType.CALL_MEMBER -> RustStateEventType.CALL_MEMBER
StateEventType.ROOM_ALIASES -> RustStateEventType.ROOM_ALIASES
StateEventType.ROOM_AVATAR -> RustStateEventType.ROOM_AVATAR
StateEventType.ROOM_CANONICAL_ALIAS -> RustStateEventType.ROOM_CANONICAL_ALIAS
@@ -47,6 +48,7 @@ fun RustStateEventType.map(): StateEventType = when (this) {
RustStateEventType.POLICY_RULE_ROOM -> StateEventType.POLICY_RULE_ROOM
RustStateEventType.POLICY_RULE_SERVER -> StateEventType.POLICY_RULE_SERVER
RustStateEventType.POLICY_RULE_USER -> StateEventType.POLICY_RULE_USER
+ RustStateEventType.CALL_MEMBER -> StateEventType.CALL_MEMBER
RustStateEventType.ROOM_ALIASES -> StateEventType.ROOM_ALIASES
RustStateEventType.ROOM_AVATAR -> StateEventType.ROOM_AVATAR
RustStateEventType.ROOM_CANONICAL_ALIAS -> StateEventType.ROOM_CANONICAL_ALIAS
diff --git a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/verification/RustSessionVerificationService.kt b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/verification/RustSessionVerificationService.kt
index 3d00c2d50e..0d705d6834 100644
--- a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/verification/RustSessionVerificationService.kt
+++ b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/verification/RustSessionVerificationService.kt
@@ -18,12 +18,12 @@ package io.element.android.libraries.matrix.impl.verification
import io.element.android.libraries.core.data.tryOrNull
import io.element.android.libraries.matrix.api.sync.SyncState
+import io.element.android.libraries.matrix.api.verification.SessionVerificationData
import io.element.android.libraries.matrix.api.verification.SessionVerificationService
import io.element.android.libraries.matrix.api.verification.SessionVerifiedStatus
import io.element.android.libraries.matrix.api.verification.VerificationEmoji
import io.element.android.libraries.matrix.api.verification.VerificationFlowState
import io.element.android.libraries.matrix.impl.sync.RustSyncService
-import kotlinx.collections.immutable.toImmutableList
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.StateFlow
@@ -33,7 +33,8 @@ import kotlinx.coroutines.launch
import org.matrix.rustcomponents.sdk.SessionVerificationController
import org.matrix.rustcomponents.sdk.SessionVerificationControllerDelegate
import org.matrix.rustcomponents.sdk.SessionVerificationControllerInterface
-import org.matrix.rustcomponents.sdk.SessionVerificationEmoji
+import org.matrix.rustcomponents.sdk.use
+import org.matrix.rustcomponents.sdk.SessionVerificationData as RustSessionVerificationData
class RustSessionVerificationService(
private val syncService: RustSyncService,
@@ -105,12 +106,8 @@ class RustSessionVerificationService(
updateVerificationStatus(isVerified = true)
}
- override fun didReceiveVerificationData(data: List) {
- val emojis = data.map { emoji ->
- emoji.use { VerificationEmoji(it.symbol(), it.description()) }
- }
- .toImmutableList()
- _verificationFlowState.value = VerificationFlowState.ReceivedVerificationData(emojis)
+ override fun didReceiveVerificationData(data: RustSessionVerificationData) {
+ _verificationFlowState.value = VerificationFlowState.ReceivedVerificationData(data.map())
}
// When the actual SAS verification starts
@@ -142,3 +139,28 @@ class RustSessionVerificationService(
_sessionVerifiedStatus.value = newValue
}
}
+
+private fun RustSessionVerificationData.map(): SessionVerificationData {
+ return use { sessionVerificationData ->
+ when (sessionVerificationData) {
+ is RustSessionVerificationData.Emojis -> {
+ SessionVerificationData.Emojis(
+ emojis = sessionVerificationData.emojis.mapIndexed { index, emoji ->
+ emoji.use { sessionVerificationEmoji ->
+ VerificationEmoji(
+ number = sessionVerificationData.indices[index].toInt(),
+ emoji = sessionVerificationEmoji.symbol(),
+ description = sessionVerificationEmoji.description(),
+ )
+ }
+ },
+ )
+ }
+ is RustSessionVerificationData.Decimals -> {
+ SessionVerificationData.Decimals(
+ decimals = sessionVerificationData.values.map { it.toInt() },
+ )
+ }
+ }
+ }
+}
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 e8228e806e..3977fbb133 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
@@ -39,7 +39,6 @@ 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.notificationsettings.FakeNotificationSettingsService
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.roomlist.FakeRoomListService
import io.element.android.libraries.matrix.test.sync.FakeSyncService
import io.element.android.libraries.matrix.test.verification.FakeSessionVerificationService
@@ -72,8 +71,7 @@ class FakeMatrixClient(
private var unignoreUserResult: Result = Result.success(Unit)
private var createRoomResult: Result = Result.success(A_ROOM_ID)
private var createDmResult: Result = Result.success(A_ROOM_ID)
- private var createDmFailure: Throwable? = null
- private var findDmResult: MatrixRoom? = FakeMatrixRoom()
+ private var findDmResult: RoomId? = A_ROOM_ID
private var logoutFailure: Throwable? = null
private val getRoomResults = mutableMapOf()
private val searchUserResults = mutableMapOf>()
@@ -87,7 +85,7 @@ class FakeMatrixClient(
return getRoomResults[roomId]
}
- override suspend fun findDM(userId: UserId): MatrixRoom? {
+ override suspend fun findDM(userId: UserId): RoomId? {
return findDmResult
}
@@ -99,14 +97,11 @@ class FakeMatrixClient(
return unignoreUserResult
}
- override suspend fun createRoom(createRoomParams: CreateRoomParameters): Result {
- delay(100)
+ override suspend fun createRoom(createRoomParams: CreateRoomParameters): Result = simulateLongTask {
return createRoomResult
}
- override suspend fun createDM(userId: UserId): Result {
- delay(100)
- createDmFailure?.let { throw it }
+ override suspend fun createDM(userId: UserId): Result = simulateLongTask {
return createDmResult
}
@@ -206,11 +201,7 @@ class FakeMatrixClient(
unignoreUserResult = result
}
- fun givenCreateDmError(failure: Throwable?) {
- createDmFailure = failure
- }
-
- fun givenFindDmResult(result: MatrixRoom?) {
+ fun givenFindDmResult(result: RoomId?) {
findDmResult = result
}
diff --git a/libraries/matrix/test/src/main/kotlin/io/element/android/libraries/matrix/test/encryption/FakeEncryptionService.kt b/libraries/matrix/test/src/main/kotlin/io/element/android/libraries/matrix/test/encryption/FakeEncryptionService.kt
index f8a2d411fe..44b9d734a5 100644
--- a/libraries/matrix/test/src/main/kotlin/io/element/android/libraries/matrix/test/encryption/FakeEncryptionService.kt
+++ b/libraries/matrix/test/src/main/kotlin/io/element/android/libraries/matrix/test/encryption/FakeEncryptionService.kt
@@ -33,7 +33,7 @@ class FakeEncryptionService : EncryptionService {
override val enableRecoveryProgressStateFlow: MutableStateFlow = MutableStateFlow(EnableRecoveryProgress.Starting)
private var waitForBackupUploadSteadyStateFlow: Flow = flowOf()
- private var fixRecoveryIssuesFailure: Exception? = null
+ private var recoverFailure: Exception? = null
private var doesBackupExistOnServerResult: Result = Result.success(true)
override suspend fun enableBackups(): Result = simulateLongTask {
@@ -44,8 +44,8 @@ class FakeEncryptionService : EncryptionService {
disableRecoveryFailure = exception
}
- fun givenFixRecoveryIssuesFailure(exception: Exception?) {
- fixRecoveryIssuesFailure = exception
+ fun givenRecoverFailure(exception: Exception?) {
+ recoverFailure = exception
}
override suspend fun disableRecovery(): Result = simulateLongTask {
@@ -61,8 +61,8 @@ class FakeEncryptionService : EncryptionService {
return doesBackupExistOnServerResult
}
- override suspend fun fixRecoveryIssues(recoveryKey: String): Result = simulateLongTask {
- fixRecoveryIssuesFailure?.let { return Result.failure(it) }
+ override suspend fun recover(recoveryKey: String): Result = simulateLongTask {
+ recoverFailure?.let { return Result.failure(it) }
return Result.success(Unit)
}
diff --git a/libraries/matrix/test/src/main/kotlin/io/element/android/libraries/matrix/test/notificationsettings/FakeNotificationSettingsService.kt b/libraries/matrix/test/src/main/kotlin/io/element/android/libraries/matrix/test/notificationsettings/FakeNotificationSettingsService.kt
index 039b855e7e..969acb9d25 100644
--- a/libraries/matrix/test/src/main/kotlin/io/element/android/libraries/matrix/test/notificationsettings/FakeNotificationSettingsService.kt
+++ b/libraries/matrix/test/src/main/kotlin/io/element/android/libraries/matrix/test/notificationsettings/FakeNotificationSettingsService.kt
@@ -41,6 +41,7 @@ class FakeNotificationSettingsService(
private var roomNotificationMode: RoomNotificationMode = initialRoomMode
private var roomNotificationModeIsDefault: Boolean = initialRoomModeIsDefault
private var callNotificationsEnabled = false
+ private var inviteNotificationsEnabled = false
private var atRoomNotificationsEnabled = false
private var setNotificationModeError: Throwable? = null
private var restoreDefaultNotificationModeError: Throwable? = null
@@ -52,7 +53,7 @@ class FakeNotificationSettingsService(
override suspend fun getRoomNotificationSettings(roomId: RoomId, isEncrypted: Boolean, isOneToOne: Boolean): Result {
return Result.success(
RoomNotificationSettings(
- mode = if(roomNotificationModeIsDefault) defaultEncryptedGroupRoomNotificationMode else roomNotificationMode,
+ mode = if (roomNotificationModeIsDefault) defaultEncryptedGroupRoomNotificationMode else roomNotificationMode,
isDefault = roomNotificationModeIsDefault
)
)
@@ -149,6 +150,15 @@ class FakeNotificationSettingsService(
return Result.success(Unit)
}
+ override suspend fun isInviteForMeEnabled(): Result {
+ return Result.success(inviteNotificationsEnabled)
+ }
+
+ override suspend fun setInviteForMeEnabled(enabled: Boolean): Result {
+ inviteNotificationsEnabled = enabled
+ return Result.success(Unit)
+ }
+
override suspend fun getRoomsWithUserDefinedRules(): Result> {
return Result.success(if (roomNotificationModeIsDefault) listOf() else listOf(A_ROOM_ID.value))
}
@@ -168,5 +178,4 @@ class FakeNotificationSettingsService(
fun givenSetDefaultNotificationModeError(throwable: Throwable?) {
setDefaultNotificationModeError = throwable
}
-
}
diff --git a/libraries/matrix/test/src/main/kotlin/io/element/android/libraries/matrix/test/verification/FakeSessionVerificationService.kt b/libraries/matrix/test/src/main/kotlin/io/element/android/libraries/matrix/test/verification/FakeSessionVerificationService.kt
index 34405f1e3d..4a7aa1c304 100644
--- a/libraries/matrix/test/src/main/kotlin/io/element/android/libraries/matrix/test/verification/FakeSessionVerificationService.kt
+++ b/libraries/matrix/test/src/main/kotlin/io/element/android/libraries/matrix/test/verification/FakeSessionVerificationService.kt
@@ -16,12 +16,10 @@
package io.element.android.libraries.matrix.test.verification
+import io.element.android.libraries.matrix.api.verification.SessionVerificationData
import io.element.android.libraries.matrix.api.verification.SessionVerificationService
-import io.element.android.libraries.matrix.api.verification.VerificationFlowState
import io.element.android.libraries.matrix.api.verification.SessionVerifiedStatus
-import io.element.android.libraries.matrix.api.verification.VerificationEmoji
-import kotlinx.collections.immutable.persistentListOf
-import kotlinx.collections.immutable.toPersistentList
+import io.element.android.libraries.matrix.api.verification.VerificationFlowState
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.StateFlow
@@ -31,10 +29,9 @@ class FakeSessionVerificationService : SessionVerificationService {
private val _sessionVerifiedStatus = MutableStateFlow(SessionVerifiedStatus.Unknown)
private var _verificationFlowState = MutableStateFlow(VerificationFlowState.Initial)
private var _canVerifySessionFlow = MutableStateFlow(true)
- private var emojiList = persistentListOf()
var shouldFail = false
- override val verificationFlowState: StateFlow =_verificationFlowState
+ override val verificationFlowState: StateFlow = _verificationFlowState
override val sessionVerifiedStatus: StateFlow = _sessionVerifiedStatus
override val canVerifySessionFlow: Flow = _canVerifySessionFlow
@@ -64,8 +61,8 @@ class FakeSessionVerificationService : SessionVerificationService {
}
}
- fun triggerReceiveVerificationData() {
- _verificationFlowState.value = VerificationFlowState.ReceivedVerificationData(emojiList)
+ fun triggerReceiveVerificationData(sessionVerificationData: SessionVerificationData) {
+ _verificationFlowState.value = VerificationFlowState.ReceivedVerificationData(sessionVerificationData)
}
override suspend fun startVerification() {
@@ -88,10 +85,6 @@ class FakeSessionVerificationService : SessionVerificationService {
_isReady.value = value
}
- fun givenEmojiList(emojis: List) {
- this.emojiList = emojis.toPersistentList()
- }
-
override suspend fun reset() {
_verificationFlowState.value = VerificationFlowState.Initial
}
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 9ff9f7d128..8a00be4663 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
@@ -25,6 +25,7 @@ import androidx.compose.foundation.layout.width
import androidx.compose.runtime.Composable
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
+import androidx.compose.ui.draw.clipToBounds
import androidx.compose.ui.text.style.TextOverflow
import androidx.compose.ui.tooling.preview.PreviewParameter
import androidx.compose.ui.unit.dp
@@ -80,6 +81,7 @@ private fun MatrixUserHeaderContent(
) {
// Name
Text(
+ modifier = Modifier.clipToBounds(),
text = matrixUser.getBestName(),
maxLines = 1,
style = ElementTheme.typography.fontHeadingSmMedium,
diff --git a/libraries/matrixui/src/main/kotlin/io/element/android/libraries/matrix/ui/components/SelectedUser.kt b/libraries/matrixui/src/main/kotlin/io/element/android/libraries/matrix/ui/components/SelectedUser.kt
index 650d4d521b..a3199369e2 100644
--- a/libraries/matrixui/src/main/kotlin/io/element/android/libraries/matrix/ui/components/SelectedUser.kt
+++ b/libraries/matrixui/src/main/kotlin/io/element/android/libraries/matrix/ui/components/SelectedUser.kt
@@ -31,6 +31,7 @@ import androidx.compose.runtime.remember
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.clip
+import androidx.compose.ui.draw.clipToBounds
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.text.style.TextOverflow
import androidx.compose.ui.unit.dp
@@ -62,6 +63,7 @@ fun SelectedUser(
) {
Avatar(matrixUser.getAvatarData(size = AvatarSize.SelectedUser))
Text(
+ modifier = Modifier.clipToBounds(),
text = matrixUser.getBestName(),
overflow = TextOverflow.Ellipsis,
maxLines = 1,
diff --git a/libraries/matrixui/src/main/kotlin/io/element/android/libraries/matrix/ui/components/UserRow.kt b/libraries/matrixui/src/main/kotlin/io/element/android/libraries/matrix/ui/components/UserRow.kt
index 8cd9b63735..f9eef6b990 100644
--- a/libraries/matrixui/src/main/kotlin/io/element/android/libraries/matrix/ui/components/UserRow.kt
+++ b/libraries/matrixui/src/main/kotlin/io/element/android/libraries/matrix/ui/components/UserRow.kt
@@ -25,12 +25,13 @@ import androidx.compose.material3.MaterialTheme
import androidx.compose.runtime.Composable
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
+import androidx.compose.ui.draw.clipToBounds
import androidx.compose.ui.text.style.TextOverflow
import androidx.compose.ui.unit.dp
+import io.element.android.compound.theme.ElementTheme
import io.element.android.libraries.designsystem.components.avatar.Avatar
import io.element.android.libraries.designsystem.components.avatar.AvatarData
import io.element.android.libraries.designsystem.theme.components.Text
-import io.element.android.compound.theme.ElementTheme
@Composable
internal fun UserRow(
@@ -55,6 +56,7 @@ internal fun UserRow(
) {
// Name
Text(
+ modifier = Modifier.clipToBounds(),
text = name,
maxLines = 1,
overflow = TextOverflow.Ellipsis,
diff --git a/libraries/matrixui/src/main/kotlin/io/element/android/libraries/matrix/ui/media/ImageLoaderFactories.kt b/libraries/matrixui/src/main/kotlin/io/element/android/libraries/matrix/ui/media/ImageLoaderFactories.kt
index c495558fd9..4c5309e2bd 100644
--- a/libraries/matrixui/src/main/kotlin/io/element/android/libraries/matrix/ui/media/ImageLoaderFactories.kt
+++ b/libraries/matrixui/src/main/kotlin/io/element/android/libraries/matrix/ui/media/ImageLoaderFactories.kt
@@ -28,8 +28,8 @@ import okhttp3.OkHttpClient
import javax.inject.Inject
import javax.inject.Provider
-class LoggedInImageLoaderFactory @Inject constructor(
- @ApplicationContext private val context: Context,
+class LoggedInImageLoaderFactory(
+ private val context: Context,
private val matrixClient: MatrixClient,
private val okHttpClient: Provider,
) : ImageLoaderFactory {
diff --git a/libraries/matrixui/src/main/kotlin/io/element/android/libraries/matrix/ui/media/ImageLoaderHolder.kt b/libraries/matrixui/src/main/kotlin/io/element/android/libraries/matrix/ui/media/ImageLoaderHolder.kt
new file mode 100644
index 0000000000..fc027d0e5c
--- /dev/null
+++ b/libraries/matrixui/src/main/kotlin/io/element/android/libraries/matrix/ui/media/ImageLoaderHolder.kt
@@ -0,0 +1,71 @@
+/*
+ * 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.ui.media
+
+import android.content.Context
+import coil.ImageLoader
+import com.squareup.anvil.annotations.ContributesBinding
+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.core.SessionId
+import io.element.android.libraries.sessionstorage.api.observer.SessionListener
+import io.element.android.libraries.sessionstorage.api.observer.SessionObserver
+import okhttp3.OkHttpClient
+import javax.inject.Inject
+import javax.inject.Provider
+
+interface ImageLoaderHolder {
+ fun get(client: MatrixClient): ImageLoader
+}
+
+@ContributesBinding(AppScope::class)
+@SingleIn(AppScope::class)
+class DefaultImageLoaderHolder @Inject constructor(
+ @ApplicationContext private val context: Context,
+ private val okHttpClient: Provider,
+ private val sessionObserver: SessionObserver,
+) : ImageLoaderHolder {
+ private val map = mutableMapOf()
+
+ init {
+ observeSessions()
+ }
+
+ private fun observeSessions() {
+ sessionObserver.addListener(object : SessionListener {
+ override suspend fun onSessionCreated(userId: String) = Unit
+
+ override suspend fun onSessionDeleted(userId: String) {
+ map.remove(SessionId(userId))
+ }
+ })
+ }
+
+ override fun get(client: MatrixClient): ImageLoader {
+ return synchronized(map) {
+ map.getOrPut(client.sessionId) {
+ LoggedInImageLoaderFactory(
+ context = context,
+ matrixClient = client,
+ okHttpClient = okHttpClient,
+ ).newImageLoader()
+ }
+ }
+ }
+}
diff --git a/libraries/mediapickers/impl/src/main/kotlin/io/element/android/libraries/mediapickers/impl/PickerProviderImpl.kt b/libraries/mediapickers/impl/src/main/kotlin/io/element/android/libraries/mediapickers/impl/PickerProviderImpl.kt
index 201fd9b069..f3c186a34f 100644
--- a/libraries/mediapickers/impl/src/main/kotlin/io/element/android/libraries/mediapickers/impl/PickerProviderImpl.kt
+++ b/libraries/mediapickers/impl/src/main/kotlin/io/element/android/libraries/mediapickers/impl/PickerProviderImpl.kt
@@ -37,7 +37,7 @@ import java.util.UUID
import javax.inject.Inject
@ContributesBinding(AppScope::class)
-class PickerProviderImpl constructor(private val isInTest: Boolean) : PickerProvider {
+class PickerProviderImpl(private val isInTest: Boolean) : PickerProvider {
@Inject
constructor(): this(false)
diff --git a/libraries/mediaupload/api/src/main/kotlin/io/element/android/libraries/mediaupload/api/MediaPreProcessor.kt b/libraries/mediaupload/api/src/main/kotlin/io/element/android/libraries/mediaupload/api/MediaPreProcessor.kt
index 31c6a813ff..9a48b50aca 100644
--- a/libraries/mediaupload/api/src/main/kotlin/io/element/android/libraries/mediaupload/api/MediaPreProcessor.kt
+++ b/libraries/mediaupload/api/src/main/kotlin/io/element/android/libraries/mediaupload/api/MediaPreProcessor.kt
@@ -31,6 +31,6 @@ interface MediaPreProcessor {
compressIfPossible: Boolean
): Result
- data class Failure(override val cause: Throwable?) : RuntimeException(cause)
+ data class Failure(override val cause: Throwable?) : Exception(cause)
}
diff --git a/libraries/mediaupload/impl/build.gradle.kts b/libraries/mediaupload/impl/build.gradle.kts
index a23ab14b74..c65b6b01a6 100644
--- a/libraries/mediaupload/impl/build.gradle.kts
+++ b/libraries/mediaupload/impl/build.gradle.kts
@@ -27,6 +27,12 @@ android {
generateDaggerFactories.set(true)
}
+ testOptions {
+ unitTests {
+ isIncludeAndroidResources = true
+ }
+ }
+
dependencies {
implementation(projects.anvilannotations)
anvil(projects.anvilcodegen)
@@ -37,6 +43,7 @@ android {
implementation(projects.libraries.core)
implementation(projects.libraries.di)
implementation(projects.libraries.matrix.api)
+ implementation(projects.services.toolbox.api)
implementation(libs.inject)
implementation(libs.androidx.exifinterface)
implementation(libs.coroutines.core)
@@ -44,7 +51,10 @@ android {
implementation(libs.vanniktech.blurhash)
testImplementation(libs.test.junit)
+ testImplementation(libs.test.robolectric)
testImplementation(libs.coroutines.test)
testImplementation(libs.test.truth)
+ testImplementation(projects.tests.testutils)
+ testImplementation(projects.services.toolbox.test)
}
}
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 d936b3a5bf..9f93818576 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
@@ -24,8 +24,8 @@ import io.element.android.libraries.androidutils.bitmap.calculateInSampleSize
import io.element.android.libraries.androidutils.bitmap.resizeToMax
import io.element.android.libraries.androidutils.bitmap.rotateToMetadataOrientation
import io.element.android.libraries.androidutils.file.createTmpFile
+import io.element.android.libraries.core.coroutine.CoroutineDispatchers
import io.element.android.libraries.di.ApplicationContext
-import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.withContext
import java.io.File
import java.io.InputStream
@@ -33,8 +33,8 @@ import javax.inject.Inject
class ImageCompressor @Inject constructor(
@ApplicationContext private val context: Context,
+ private val dispatchers: CoroutineDispatchers,
) {
-
/**
* Decodes the [inputStream] into a [Bitmap] and applies the needed transformations (rotation, scale) based on [resizeMode], then writes it into a
* temporary file using the passed [format], [orientation] and [desiredQuality].
@@ -46,7 +46,7 @@ class ImageCompressor @Inject constructor(
format: Bitmap.CompressFormat = Bitmap.CompressFormat.JPEG,
orientation: Int = ExifInterface.ORIENTATION_UNDEFINED,
desiredQuality: Int = 80,
- ): Result = withContext(Dispatchers.IO) {
+ ): Result = withContext(dispatchers.io) {
runCatching {
val compressedBitmap = compressToBitmap(inputStreamProvider, resizeMode, orientation).getOrThrow()
// Encode bitmap to the destination temporary file
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 2cee2566d1..40a75b6428 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
@@ -32,6 +32,7 @@ import io.element.android.libraries.androidutils.media.runAndRelease
import io.element.android.libraries.core.mimetype.MimeTypes
import io.element.android.libraries.di.ApplicationContext
import io.element.android.libraries.matrix.api.media.ThumbnailInfo
+import io.element.android.services.toolbox.api.sdk.BuildVersionSdkIntProvider
import kotlinx.coroutines.suspendCancellableCoroutine
import java.io.File
import javax.inject.Inject
@@ -56,13 +57,14 @@ private const val VIDEO_THUMB_FRAME = 0L
class ThumbnailFactory @Inject constructor(
@ApplicationContext private val context: Context,
+ private val sdkIntProvider: BuildVersionSdkIntProvider
) {
@SuppressLint("NewApi")
suspend fun createImageThumbnail(file: File): ThumbnailResult {
return createThumbnail { cancellationSignal ->
// This API works correctly with GIF
- if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
+ if (sdkIntProvider.isAtLeast(Build.VERSION_CODES.Q)) {
ThumbnailUtils.createImageThumbnail(
file,
Size(THUMB_MAX_WIDTH, THUMB_MAX_HEIGHT),
diff --git a/libraries/mediaupload/impl/src/test/assets/animated_gif.gif b/libraries/mediaupload/impl/src/test/assets/animated_gif.gif
new file mode 100644
index 0000000000..8fd2ce1550
--- /dev/null
+++ b/libraries/mediaupload/impl/src/test/assets/animated_gif.gif
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:6831610b21668c49e31732f9005177e959277233d3cab758910e061294f91d79
+size 687979
diff --git a/libraries/mediaupload/impl/src/test/assets/image.png b/libraries/mediaupload/impl/src/test/assets/image.png
new file mode 100644
index 0000000000..b0946f7ba8
--- /dev/null
+++ b/libraries/mediaupload/impl/src/test/assets/image.png
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:a980f7b74cb9edc323919db8652798da4b3dcf865fc7b6a1eb1110096b7bfb4f
+size 1856786
diff --git a/libraries/mediaupload/impl/src/test/assets/sample3s.mp3 b/libraries/mediaupload/impl/src/test/assets/sample3s.mp3
new file mode 100644
index 0000000000..cb4db9c9d8
--- /dev/null
+++ b/libraries/mediaupload/impl/src/test/assets/sample3s.mp3
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:0244590f2b4bcb62352b574e78bea940e8d89cfa69823b5208ef4c43e0abcb44
+size 52079
diff --git a/libraries/mediaupload/impl/src/test/assets/text.txt b/libraries/mediaupload/impl/src/test/assets/text.txt
new file mode 100644
index 0000000000..d45ec4338b
--- /dev/null
+++ b/libraries/mediaupload/impl/src/test/assets/text.txt
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:0ba904eae8773b70c75333db4de2f3ac45a8ad4ddba1b242f0b3cfc199391dd8
+size 13
diff --git a/libraries/mediaupload/impl/src/test/assets/video.mp4 b/libraries/mediaupload/impl/src/test/assets/video.mp4
new file mode 100644
index 0000000000..4d57318b1d
--- /dev/null
+++ b/libraries/mediaupload/impl/src/test/assets/video.mp4
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:fb58436524db95bd0c10b2c3023c2eb7b87404a2eab8987939f051647eb859d3
+size 1673712
diff --git a/libraries/mediaupload/impl/src/test/kotlin/io/element/android/libraries/mediaupload/AndroidMediaPreProcessorTest.kt b/libraries/mediaupload/impl/src/test/kotlin/io/element/android/libraries/mediaupload/AndroidMediaPreProcessorTest.kt
new file mode 100644
index 0000000000..3d745b3ec3
--- /dev/null
+++ b/libraries/mediaupload/impl/src/test/kotlin/io/element/android/libraries/mediaupload/AndroidMediaPreProcessorTest.kt
@@ -0,0 +1,347 @@
+/*
+ * 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.mediaupload
+
+import android.content.Context
+import android.os.Build
+import androidx.core.net.toUri
+import androidx.test.platform.app.InstrumentationRegistry
+import com.google.common.truth.Truth.assertThat
+import io.element.android.libraries.core.mimetype.MimeTypes
+import io.element.android.libraries.matrix.api.media.AudioInfo
+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.ThumbnailInfo
+import io.element.android.libraries.matrix.api.media.VideoInfo
+import io.element.android.libraries.mediaupload.api.MediaPreProcessor
+import io.element.android.libraries.mediaupload.api.MediaUploadInfo
+import io.element.android.services.toolbox.test.sdk.FakeBuildVersionSdkIntProvider
+import io.element.android.tests.testutils.testCoroutineDispatchers
+import kotlinx.coroutines.test.TestScope
+import kotlinx.coroutines.test.runTest
+import org.junit.Ignore
+import org.junit.Test
+import org.junit.runner.RunWith
+import org.robolectric.RobolectricTestRunner
+import java.io.File
+import java.io.FileNotFoundException
+import java.io.IOException
+import kotlin.time.Duration
+
+@RunWith(RobolectricTestRunner::class)
+class AndroidMediaPreProcessorTest {
+ @Test
+ fun `test processing image`() = runTest {
+ val context = InstrumentationRegistry.getInstrumentation().context
+ val sut = createAndroidMediaPreProcessor(context)
+ val file = getFileFromAssets(context, "image.png")
+ val result = sut.process(
+ uri = file.toUri(),
+ mimeType = MimeTypes.Png,
+ deleteOriginal = false,
+ compressIfPossible = true,
+ )
+ // This is failing for now
+ val error = result.exceptionOrNull()
+ assertThat(error).isInstanceOf(MediaPreProcessor.Failure::class.java)
+ assertThat(error?.cause).isInstanceOf(NullPointerException::class.java)
+ /*
+ val data = result.getOrThrow()
+ assertThat(data.file.path).endsWith("image.png")
+ val info = data as MediaUploadInfo.Image
+ assertThat(info.thumbnailFile).isNull() // TODO Check this
+ assertThat(info.imageInfo).isEqualTo(
+ ImageInfo(
+ height = 1_178,
+ width = 1_818,
+ mimetype = MimeTypes.Png,
+ size = 114_867,
+ thumbnailInfo = null,
+ thumbnailSource = null,
+ blurhash = null,
+ )
+ )
+ assertThat(file.exists()).isTrue()
+ */
+ }
+
+ @Test
+ fun `test processing image api Q`() = runTest {
+ val context = InstrumentationRegistry.getInstrumentation().context
+ val sut = createAndroidMediaPreProcessor(context, sdkIntVersion = Build.VERSION_CODES.Q)
+ val file = getFileFromAssets(context, "image.png")
+ val result = sut.process(
+ uri = file.toUri(),
+ mimeType = MimeTypes.Png,
+ deleteOriginal = false,
+ compressIfPossible = true,
+ )
+ // This is not working for now
+ val error = result.exceptionOrNull()
+ assertThat(error).isInstanceOf(MediaPreProcessor.Failure::class.java)
+ assertThat(error?.cause).isInstanceOf(NoSuchMethodError::class.java)
+ /*
+ val data = result.getOrThrow()
+ assertThat(data.file.path).endsWith("image.png")
+ val info = data as MediaUploadInfo.Image
+ assertThat(info.thumbnailFile).isNull() // TODO Check this
+ assertThat(info.imageInfo).isEqualTo(
+ ImageInfo(
+ height = 1_178,
+ width = 1_818,
+ mimetype = MimeTypes.Png,
+ size = 114_867,
+ thumbnailInfo = null,
+ thumbnailSource = null,
+ blurhash = null,
+ )
+ )
+ assertThat(file.exists()).isTrue()
+ */
+ }
+
+ @Test
+ fun `test processing image no compression`() = runTest {
+ val context = InstrumentationRegistry.getInstrumentation().context
+ val sut = createAndroidMediaPreProcessor(context)
+ val file = getFileFromAssets(context, "image.png")
+ val result = sut.process(
+ uri = file.toUri(),
+ mimeType = MimeTypes.Png,
+ deleteOriginal = false,
+ compressIfPossible = false,
+ ).getOrThrow()
+ assertThat(result.file.path).endsWith("image.png")
+ val info = result as MediaUploadInfo.Image
+ assertThat(info.thumbnailFile).isNotNull()
+ assertThat(info.imageInfo).isEqualTo(
+ ImageInfo(
+ height = 1_178,
+ width = 1_818,
+ mimetype = MimeTypes.Png,
+ size = 1_856_786,
+ thumbnailInfo = ThumbnailInfo(height = 25, width = 25, mimetype = MimeTypes.Jpeg, size = 643),
+ thumbnailSource = null,
+ blurhash = "K00000fQfQfQfQfQfQfQfQ",
+ )
+ )
+ assertThat(file.exists()).isTrue()
+ }
+
+ @Test
+ fun `test processing image and delete`() = runTest {
+ val context = InstrumentationRegistry.getInstrumentation().context
+ val sut = createAndroidMediaPreProcessor(context)
+ val file = getFileFromAssets(context, "image.png")
+ val result = sut.process(
+ uri = file.toUri(),
+ mimeType = MimeTypes.Png,
+ deleteOriginal = true,
+ compressIfPossible = false,
+ ).getOrThrow()
+ assertThat(result.file.path).endsWith("image.png")
+ val info = result as MediaUploadInfo.Image
+ assertThat(info.thumbnailFile).isNotNull()
+ assertThat(info.imageInfo).isEqualTo(
+ ImageInfo(
+ height = 1_178,
+ width = 1_818,
+ mimetype = MimeTypes.Png,
+ size = 1_856_786,
+ thumbnailInfo = ThumbnailInfo(height = 25, width = 25, mimetype = MimeTypes.Jpeg, size = 643),
+ thumbnailSource = null,
+ blurhash = "K00000fQfQfQfQfQfQfQfQ",
+ )
+ )
+ // Does not work
+ // assertThat(file.exists()).isFalse()
+ }
+
+ @Test
+ fun `test processing gif`() = runTest {
+ val context = InstrumentationRegistry.getInstrumentation().context
+ val sut = createAndroidMediaPreProcessor(context)
+ val file = getFileFromAssets(context, "animated_gif.gif")
+ val result = sut.process(
+ uri = file.toUri(),
+ mimeType = MimeTypes.Gif,
+ deleteOriginal = false,
+ compressIfPossible = true,
+ ).getOrThrow()
+ assertThat(result.file.path).endsWith("animated_gif.gif")
+ val info = result as MediaUploadInfo.Image
+ assertThat(info.thumbnailFile).isNotNull()
+ assertThat(info.imageInfo).isEqualTo(
+ ImageInfo(
+ height = 600,
+ width = 800,
+ mimetype = MimeTypes.Gif,
+ size = 687_979,
+ thumbnailInfo = ThumbnailInfo(height = 50, width = 50, mimetype = MimeTypes.Jpeg, size = 691),
+ thumbnailSource = null,
+ blurhash = "K00000fQfQfQfQfQfQfQfQ",
+ )
+ )
+ assertThat(file.exists()).isTrue()
+ }
+
+ @Test
+ fun `test processing file`() = runTest {
+ val context = InstrumentationRegistry.getInstrumentation().context
+ val sut = createAndroidMediaPreProcessor(context)
+ val file = getFileFromAssets(context, "text.txt")
+ val result = sut.process(
+ uri = file.toUri(),
+ mimeType = MimeTypes.PlainText,
+ deleteOriginal = false,
+ compressIfPossible = true,
+ ).getOrThrow()
+ assertThat(result.file.path).endsWith("text.txt")
+ val info = result as MediaUploadInfo.AnyFile
+ assertThat(info.fileInfo).isEqualTo(
+ FileInfo(
+ mimetype = MimeTypes.PlainText,
+ size = 13,
+ thumbnailInfo = null,
+ thumbnailSource = null,
+ )
+ )
+ assertThat(file.exists()).isTrue()
+ }
+
+ @Ignore("Compressing video is not working with Robolectric")
+ @Test
+ fun `test processing video`() = runTest {
+ val context = InstrumentationRegistry.getInstrumentation().context
+ val sut = createAndroidMediaPreProcessor(context)
+ val file = getFileFromAssets(context, "video.mp4")
+ val result = sut.process(
+ uri = file.toUri(),
+ mimeType = MimeTypes.Mp4,
+ deleteOriginal = false,
+ compressIfPossible = true,
+ ).getOrThrow()
+ assertThat(result.file.path).endsWith("video.mp4")
+ val info = result as MediaUploadInfo.Video
+ assertThat(info.thumbnailFile).isNotNull()
+ assertThat(info.videoInfo).isEqualTo(
+ VideoInfo(
+ duration = Duration.ZERO, // Not available with Robolectric?
+ height = 1_178,
+ width = 1_818,
+ mimetype = MimeTypes.Mp4,
+ size = 114_867,
+ thumbnailInfo = null,
+ thumbnailSource = null,
+ blurhash = null,
+ )
+ )
+ assertThat(file.exists()).isTrue()
+ }
+
+ @Test
+ fun `test processing video no compression`() = runTest {
+ val context = InstrumentationRegistry.getInstrumentation().context
+ val sut = createAndroidMediaPreProcessor(context)
+ val file = getFileFromAssets(context, "video.mp4")
+ val result = sut.process(
+ uri = file.toUri(),
+ mimeType = MimeTypes.Mp4,
+ deleteOriginal = false,
+ compressIfPossible = false,
+ ).getOrThrow()
+ assertThat(result.file.path).endsWith("video.mp4")
+ val info = result as MediaUploadInfo.Video
+ assertThat(info.thumbnailFile).isNotNull()
+ assertThat(info.videoInfo).isEqualTo(
+ VideoInfo(
+ duration = Duration.ZERO, // Not available with Robolectric?
+ height = 0, // Not available with Robolectric?
+ width = 0, // Not available with Robolectric?
+ mimetype = MimeTypes.Mp4,
+ size = 1_673_712,
+ thumbnailInfo = ThumbnailInfo(height = null, width = null, mimetype = MimeTypes.Jpeg, size = 0), // Not available with Robolectric?
+ thumbnailSource = null,
+ blurhash = null,
+ )
+ )
+ assertThat(file.exists()).isTrue()
+ }
+
+ @Test
+ fun `test processing audio`() = runTest {
+ val context = InstrumentationRegistry.getInstrumentation().context
+ val sut = createAndroidMediaPreProcessor(context)
+ val file = getFileFromAssets(context, "sample3s.mp3")
+ val result = sut.process(
+ uri = file.toUri(),
+ mimeType = MimeTypes.Mp3,
+ deleteOriginal = false,
+ compressIfPossible = true,
+ ).getOrThrow()
+ assertThat(result.file.path).endsWith("sample3s.mp3")
+ val info = result as MediaUploadInfo.Audio
+ assertThat(info.audioInfo).isEqualTo(
+ AudioInfo(
+ duration = Duration.ZERO, // Not available with Robolectric?
+ size = 52_079,
+ mimetype = MimeTypes.Mp3,
+ )
+ )
+ assertThat(file.exists()).isTrue()
+ }
+
+ @Test
+ fun `test file which does not exist`() = runTest {
+ val context = InstrumentationRegistry.getInstrumentation().context
+ val sut = createAndroidMediaPreProcessor(context)
+ val file = File(context.cacheDir, "not found.txt")
+ val result = sut.process(
+ uri = file.toUri(),
+ mimeType = MimeTypes.PlainText,
+ deleteOriginal = false,
+ compressIfPossible = true,
+ )
+ assertThat(result.isFailure).isTrue()
+ val failure = result.exceptionOrNull()
+ assertThat(failure).isInstanceOf(MediaPreProcessor.Failure::class.java)
+ assertThat(failure?.cause).isInstanceOf(FileNotFoundException::class.java)
+ }
+
+ private fun TestScope.createAndroidMediaPreProcessor(
+ context: Context,
+ sdkIntVersion: Int = Build.VERSION_CODES.P
+ ) = AndroidMediaPreProcessor(
+ context = context,
+ thumbnailFactory = ThumbnailFactory(context, FakeBuildVersionSdkIntProvider(sdkIntVersion)),
+ imageCompressor = ImageCompressor(context, testCoroutineDispatchers()),
+ videoCompressor = VideoCompressor(context),
+ coroutineDispatchers = testCoroutineDispatchers(),
+ )
+
+ @Throws(IOException::class)
+ private fun getFileFromAssets(context: Context, fileName: String): File = File(context.cacheDir, fileName)
+ .also {
+ if (!it.exists()) {
+ it.outputStream().use { cache ->
+ context.assets.open(fileName).use { inputStream ->
+ inputStream.copyTo(cache)
+ }
+ }
+ }
+ }
+}
diff --git a/libraries/mediaviewer/api/build.gradle.kts b/libraries/mediaviewer/api/build.gradle.kts
index 5971f6f0c0..7076a144fe 100644
--- a/libraries/mediaviewer/api/build.gradle.kts
+++ b/libraries/mediaviewer/api/build.gradle.kts
@@ -55,6 +55,7 @@ dependencies {
testImplementation(libs.test.junit)
testImplementation(libs.test.truth)
testImplementation(libs.test.mockk)
+ testImplementation(libs.test.robolectric)
testImplementation(libs.test.turbine)
testImplementation(libs.coroutines.core)
testImplementation(libs.coroutines.test)
diff --git a/libraries/mediaviewer/api/src/test/kotlin/io/element/android/libraries/mediaviewer/api/util/FileExtensionExtractorTest.kt b/libraries/mediaviewer/api/src/test/kotlin/io/element/android/libraries/mediaviewer/api/util/FileExtensionExtractorTest.kt
new file mode 100644
index 0000000000..a2795d2884
--- /dev/null
+++ b/libraries/mediaviewer/api/src/test/kotlin/io/element/android/libraries/mediaviewer/api/util/FileExtensionExtractorTest.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.libraries.mediaviewer.api.util
+
+import com.google.common.truth.Truth.assertThat
+import org.junit.Test
+import org.junit.runner.RunWith
+import org.robolectric.RobolectricTestRunner
+
+@RunWith(RobolectricTestRunner::class)
+class FileExtensionExtractorTest {
+ @Test
+ fun `test FileExtensionExtractor with validation OK`() {
+ val sut = FileExtensionExtractorWithValidation()
+ // The result should be txt, but with Robolectric,
+ // MimeTypeMap.getSingleton().hasExtension() always returns false
+ assertThat(sut.extractFromName("test.txt")).isEqualTo("bin")
+ }
+
+ @Test
+ fun `test FileExtensionExtractor with validation ERROR`() {
+ val sut = FileExtensionExtractorWithValidation()
+ assertThat(sut.extractFromName("test.bla")).isEqualTo("bin")
+ }
+
+ @Test
+ fun `test FileExtensionExtractor no validation`() {
+ val sut = FileExtensionExtractorWithoutValidation()
+ assertThat(sut.extractFromName("test.png")).isEqualTo("png")
+ assertThat(sut.extractFromName("test.bla")).isEqualTo("bla")
+ }
+}
diff --git a/libraries/mediaviewer/impl/build.gradle.kts b/libraries/mediaviewer/impl/build.gradle.kts
index 7cfb9d01f4..0ccfd0b65e 100644
--- a/libraries/mediaviewer/impl/build.gradle.kts
+++ b/libraries/mediaviewer/impl/build.gradle.kts
@@ -46,6 +46,9 @@ dependencies {
testImplementation(libs.test.junit)
testImplementation(libs.test.truth)
testImplementation(libs.test.mockk)
+ testImplementation(libs.molecule.runtime)
+ testImplementation(libs.test.turbine)
+ testImplementation(libs.test.robolectric)
testImplementation(libs.test.turbine)
testImplementation(libs.coroutines.core)
testImplementation(libs.coroutines.test)
diff --git a/libraries/mediaviewer/impl/src/main/kotlin/io/element/android/libraries/mediaviewer/local/AndroidLocalMediaActions.kt b/libraries/mediaviewer/impl/src/main/kotlin/io/element/android/libraries/mediaviewer/impl/local/AndroidLocalMediaActions.kt
similarity index 99%
rename from libraries/mediaviewer/impl/src/main/kotlin/io/element/android/libraries/mediaviewer/local/AndroidLocalMediaActions.kt
rename to libraries/mediaviewer/impl/src/main/kotlin/io/element/android/libraries/mediaviewer/impl/local/AndroidLocalMediaActions.kt
index 04d56a80d6..35ebc0e022 100644
--- a/libraries/mediaviewer/impl/src/main/kotlin/io/element/android/libraries/mediaviewer/local/AndroidLocalMediaActions.kt
+++ b/libraries/mediaviewer/impl/src/main/kotlin/io/element/android/libraries/mediaviewer/impl/local/AndroidLocalMediaActions.kt
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-package io.element.android.libraries.mediaviewer.local
+package io.element.android.libraries.mediaviewer.impl.local
import android.app.Activity
import android.content.ContentResolver
diff --git a/libraries/mediaviewer/impl/src/main/kotlin/io/element/android/libraries/mediaviewer/local/AndroidLocalMediaFactory.kt b/libraries/mediaviewer/impl/src/main/kotlin/io/element/android/libraries/mediaviewer/impl/local/AndroidLocalMediaFactory.kt
similarity index 98%
rename from libraries/mediaviewer/impl/src/main/kotlin/io/element/android/libraries/mediaviewer/local/AndroidLocalMediaFactory.kt
rename to libraries/mediaviewer/impl/src/main/kotlin/io/element/android/libraries/mediaviewer/impl/local/AndroidLocalMediaFactory.kt
index d258da4c88..1c026ce53b 100644
--- a/libraries/mediaviewer/impl/src/main/kotlin/io/element/android/libraries/mediaviewer/local/AndroidLocalMediaFactory.kt
+++ b/libraries/mediaviewer/impl/src/main/kotlin/io/element/android/libraries/mediaviewer/impl/local/AndroidLocalMediaFactory.kt
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-package io.element.android.libraries.mediaviewer.local
+package io.element.android.libraries.mediaviewer.impl.local
import android.content.Context
import android.net.Uri
diff --git a/libraries/mediaviewer/impl/src/test/kotlin/io/element/android/libraries/mediaviewer/impl/local/AndroidLocalMediaActionsTest.kt b/libraries/mediaviewer/impl/src/test/kotlin/io/element/android/libraries/mediaviewer/impl/local/AndroidLocalMediaActionsTest.kt
new file mode 100644
index 0000000000..0e981d73af
--- /dev/null
+++ b/libraries/mediaviewer/impl/src/test/kotlin/io/element/android/libraries/mediaviewer/impl/local/AndroidLocalMediaActionsTest.kt
@@ -0,0 +1,81 @@
+/*
+ * 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.mediaviewer.impl.local
+
+import android.net.Uri
+import androidx.activity.compose.LocalActivityResultRegistryOwner
+import androidx.compose.runtime.CompositionLocalProvider
+import androidx.compose.ui.platform.LocalContext
+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.libraries.matrix.test.core.aBuildMeta
+import io.element.android.libraries.mediaviewer.test.viewer.aLocalMedia
+import io.element.android.tests.testutils.testCoroutineDispatchers
+import kotlinx.coroutines.test.TestScope
+import kotlinx.coroutines.test.runTest
+import org.junit.Test
+import org.junit.runner.RunWith
+import org.robolectric.RobolectricTestRunner
+import org.robolectric.RuntimeEnvironment
+
+@RunWith(RobolectricTestRunner::class)
+class AndroidLocalMediaActionsTest {
+
+ @Test
+ fun `present - AndroidLocalMediaAction configure`() = runTest {
+ val sut = createAndroidLocalMediaActions()
+ moleculeFlow(RecompositionMode.Immediate) {
+ CompositionLocalProvider(
+ LocalContext provides RuntimeEnvironment.getApplication(),
+ LocalActivityResultRegistryOwner provides NoOpActivityResultRegistryOwner()
+ ) {
+ sut.Configure()
+ }
+ }.test {
+ awaitItem()
+ }
+ }
+
+ @Test
+ fun `test AndroidLocalMediaAction share`() = runTest {
+ val sut = createAndroidLocalMediaActions()
+ val result = sut.share(aLocalMedia(Uri.parse("file://afile")))
+ assertThat(result.exceptionOrNull()).isNotNull()
+ }
+
+ @Test
+ fun `test AndroidLocalMediaAction open`() = runTest {
+ val sut = createAndroidLocalMediaActions()
+ val result = sut.open(aLocalMedia(Uri.parse("file://afile")))
+ assertThat(result.exceptionOrNull()).isNotNull()
+ }
+
+ @Test
+ fun `test AndroidLocalMediaAction save on disk`() = runTest {
+ val sut = createAndroidLocalMediaActions()
+ val result = sut.saveOnDisk(aLocalMedia(Uri.parse("file://afile")))
+ assertThat(result.exceptionOrNull()).isNotNull()
+ }
+
+ private fun TestScope.createAndroidLocalMediaActions() = AndroidLocalMediaActions(
+ RuntimeEnvironment.getApplication(),
+ testCoroutineDispatchers(),
+ aBuildMeta()
+ )
+}
diff --git a/libraries/mediaviewer/impl/src/test/kotlin/io/element/android/libraries/mediaviewer/impl/local/AndroidLocalMediaFactoryTest.kt b/libraries/mediaviewer/impl/src/test/kotlin/io/element/android/libraries/mediaviewer/impl/local/AndroidLocalMediaFactoryTest.kt
new file mode 100644
index 0000000000..c6209ae7c3
--- /dev/null
+++ b/libraries/mediaviewer/impl/src/test/kotlin/io/element/android/libraries/mediaviewer/impl/local/AndroidLocalMediaFactoryTest.kt
@@ -0,0 +1,61 @@
+/*
+ * 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.mediaviewer.impl.local
+
+import com.google.common.truth.Truth.assertThat
+import io.element.android.libraries.androidutils.filesize.FakeFileSizeFormatter
+import io.element.android.libraries.core.mimetype.MimeTypes
+import io.element.android.libraries.matrix.api.media.MediaFile
+import io.element.android.libraries.matrix.test.media.FakeMediaFile
+import io.element.android.libraries.mediaviewer.api.local.MediaInfo
+import io.element.android.libraries.mediaviewer.api.local.anImageInfo
+import io.element.android.libraries.mediaviewer.api.util.FileExtensionExtractorWithoutValidation
+import org.junit.Test
+import org.junit.runner.RunWith
+import org.robolectric.RobolectricTestRunner
+import org.robolectric.RuntimeEnvironment
+
+@RunWith(RobolectricTestRunner::class)
+class AndroidLocalMediaFactoryTest {
+
+ @Test
+ fun `test AndroidLocalMediaFactory`() {
+ val sut = createAndroidLocalMediaFactory()
+ val result = sut.createFromMediaFile(aMediaFile(), anImageInfo())
+ assertThat(result.uri.toString()).endsWith("aPath")
+ assertThat(result.info).isEqualTo(
+ MediaInfo(
+ name = "an image file.jpg",
+ mimeType = MimeTypes.Jpeg,
+ formattedFileSize = "4MB",
+ fileExtension = "jpg",
+ )
+ )
+ }
+
+ private fun aMediaFile(): MediaFile {
+ return FakeMediaFile("aPath")
+ }
+
+ private fun createAndroidLocalMediaFactory(): AndroidLocalMediaFactory {
+ return AndroidLocalMediaFactory(
+ RuntimeEnvironment.getApplication(),
+ FakeFileSizeFormatter(),
+ FileExtensionExtractorWithoutValidation()
+ )
+ }
+}
diff --git a/libraries/mediaviewer/impl/src/test/kotlin/io/element/android/libraries/mediaviewer/impl/local/NoOpActivityResultRegistryOwner.kt b/libraries/mediaviewer/impl/src/test/kotlin/io/element/android/libraries/mediaviewer/impl/local/NoOpActivityResultRegistryOwner.kt
new file mode 100644
index 0000000000..9d774bb163
--- /dev/null
+++ b/libraries/mediaviewer/impl/src/test/kotlin/io/element/android/libraries/mediaviewer/impl/local/NoOpActivityResultRegistryOwner.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.libraries.mediaviewer.impl.local
+
+import androidx.activity.result.ActivityResultRegistry
+import androidx.activity.result.ActivityResultRegistryOwner
+import androidx.activity.result.contract.ActivityResultContract
+import androidx.core.app.ActivityOptionsCompat
+
+class NoOpActivityResultRegistryOwner : ActivityResultRegistryOwner {
+ override val activityResultRegistry: ActivityResultRegistry
+ get() = NoOpActivityResultRegistry()
+}
+
+class NoOpActivityResultRegistry : ActivityResultRegistry() {
+ override fun onLaunch(
+ requestCode: Int,
+ contract: ActivityResultContract,
+ input: I,
+ options: ActivityOptionsCompat?,
+ ) = Unit
+}
diff --git a/libraries/permissions/api/src/main/res/values-hu/translations.xml b/libraries/permissions/api/src/main/res/values-hu/translations.xml
new file mode 100644
index 0000000000..de3573fce2
--- /dev/null
+++ b/libraries/permissions/api/src/main/res/values-hu/translations.xml
@@ -0,0 +1,7 @@
+
+
+ "Hogy az alkalmazás használhassa a kamerát, adja meg az engedélyt a rendszerbeállításokban."
+ "Adja meg az engedélyt a rendszerbeállításokban."
+ "Hogy az alkalmazás használhassa a mikrofont, adja meg az engedélyt a rendszerbeállításokban."
+ "Hogy az alkalmazás megjeleníthesse az értesítéseket, adja meg az engedélyt a rendszerbeállításokban."
+
diff --git a/libraries/permissions/api/src/main/res/values-in/translations.xml b/libraries/permissions/api/src/main/res/values-in/translations.xml
new file mode 100644
index 0000000000..40fe4b0390
--- /dev/null
+++ b/libraries/permissions/api/src/main/res/values-in/translations.xml
@@ -0,0 +1,7 @@
+
+
+ "Supaya aplikasinya dapat menggunakan kamera, berikan izin dalam pengaturan sistem."
+ "Silakan memberikan izin dalam pengaturan sistem."
+ "Supaya aplikasinya dapat menggunakan mikrofon, berikan izin dalam pengaturan sistem."
+ "Supaya aplikasinya dapat menampilkan notifikasi, berikan izin dalam pengaturan sistem."
+
diff --git a/libraries/permissions/impl/src/test/kotlin/io/element/android/libraries/permissions/impl/FakeComposablePermissionStateProvider.kt b/libraries/permissions/impl/src/test/kotlin/io/element/android/libraries/permissions/impl/FakeComposablePermissionStateProvider.kt
index 900d9ccc69..948cc603c3 100644
--- a/libraries/permissions/impl/src/test/kotlin/io/element/android/libraries/permissions/impl/FakeComposablePermissionStateProvider.kt
+++ b/libraries/permissions/impl/src/test/kotlin/io/element/android/libraries/permissions/impl/FakeComposablePermissionStateProvider.kt
@@ -27,7 +27,7 @@ import com.google.accompanist.permissions.ExperimentalPermissionsApi
import com.google.accompanist.permissions.PermissionState
import com.google.accompanist.permissions.PermissionStatus
-class FakeComposablePermissionStateProvider constructor(
+class FakeComposablePermissionStateProvider(
private val permissionState: FakePermissionState
) : ComposablePermissionStateProvider {
private lateinit var onPermissionResult: (Boolean) -> Unit
diff --git a/libraries/push/impl/src/main/AndroidManifest.xml b/libraries/push/impl/src/main/AndroidManifest.xml
index 6085ffe4a4..17bd098f90 100644
--- a/libraries/push/impl/src/main/AndroidManifest.xml
+++ b/libraries/push/impl/src/main/AndroidManifest.xml
@@ -15,6 +15,7 @@
-->
+
+
+
+
+
+
+
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 09f622e978..904a6bf2ea 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
@@ -30,6 +30,7 @@ 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.ui.media.ImageLoaderHolder
import io.element.android.libraries.push.api.notifications.NotificationDrawerManager
import io.element.android.libraries.push.impl.notifications.model.NotifiableEvent
import io.element.android.services.appnavstate.api.AppNavigationStateService
@@ -61,6 +62,7 @@ class DefaultNotificationDrawerManager @Inject constructor(
private val dispatchers: CoroutineDispatchers,
private val buildMeta: BuildMeta,
private val matrixClientProvider: MatrixClientProvider,
+ private val imageLoaderHolder: ImageLoaderHolder,
) : NotificationDrawerManager {
private var appNavigationStateObserver: Job? = null
@@ -288,10 +290,11 @@ class DefaultNotificationDrawerManager @Inject constructor(
}
eventsForSessions.forEach { (sessionId, notifiableEvents) ->
+ val client = matrixClientProvider.getOrRestore(sessionId).getOrThrow()
+ val imageLoader = imageLoaderHolder.get(client)
val currentUser = tryOrNull(
onError = { Timber.tag(loggerTag.value).e(it, "Unable to retrieve info for user ${sessionId.value}") },
operation = {
- val client = matrixClientProvider.getOrRestore(sessionId).getOrThrow()
// myUserDisplayName cannot be empty else NotificationCompat.MessagingStyle() will crash
val myUserDisplayName = client.loadUserDisplayName().getOrNull() ?: sessionId.value
val userAvatarUrl = client.loadUserAvatarURLString().getOrNull()
@@ -307,7 +310,7 @@ class DefaultNotificationDrawerManager @Inject constructor(
avatarUrl = null
)
- notificationRenderer.render(currentUser, useCompleteNotificationFormat, notifiableEvents)
+ notificationRenderer.render(currentUser, useCompleteNotificationFormat, notifiableEvents, imageLoader)
}
}
}
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 26c8a7d55b..017627305e 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
@@ -16,7 +16,12 @@
package io.element.android.libraries.push.impl.notifications
+import android.content.Context
+import android.net.Uri
+import androidx.core.content.FileProvider
import io.element.android.libraries.core.log.logger.LoggerTag
+import io.element.android.libraries.di.ApplicationContext
+import io.element.android.libraries.matrix.api.MatrixClient
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
@@ -60,6 +65,8 @@ class NotifiableEventResolver @Inject constructor(
private val stringProvider: StringProvider,
private val clock: SystemClock,
private val matrixClientProvider: MatrixClientProvider,
+ private val notificationMediaRepoFactory: NotificationMediaRepo.Factory,
+ @ApplicationContext private val context: Context,
) {
suspend fun resolveEvent(sessionId: SessionId, roomId: RoomId, eventId: EventId): NotifiableEvent? {
@@ -75,10 +82,13 @@ class NotifiableEventResolver @Inject constructor(
}.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)
+ return notificationData?.asNotifiableEvent(client, sessionId)
}
- private fun NotificationData.asNotifiableEvent(userId: SessionId): NotifiableEvent? {
+ private suspend fun NotificationData.asNotifiableEvent(
+ client: MatrixClient,
+ userId: SessionId,
+ ): NotifiableEvent? {
return when (val content = this.content) {
is NotificationContent.MessageLike.RoomMessage -> {
val messageBody = descriptionFromMessageContent(content, senderDisplayName ?: content.senderId.value)
@@ -96,7 +106,7 @@ class NotifiableEventResolver @Inject constructor(
timestamp = this.timestamp,
senderName = senderDisplayName,
body = notificationBody,
- imageUriString = this.contentUrl,
+ imageUriString = fetchImageIfPresent(client)?.toString(),
roomName = roomDisplayName,
roomIsDirect = isDirect,
roomAvatarPath = roomAvatarUrl,
@@ -238,6 +248,34 @@ class NotifiableEventResolver @Inject constructor(
stringProvider.getString(R.string.notification_room_invite_body)
}
}
+
+ private suspend fun NotificationData.fetchImageIfPresent(client: MatrixClient): Uri? {
+ val fileResult = when (val content = this.content) {
+ is NotificationContent.MessageLike.RoomMessage -> {
+ when (val messageType = content.messageType) {
+ is ImageMessageType -> notificationMediaRepoFactory.create(client)
+ .getMediaFile(
+ mediaSource = messageType.source,
+ mimeType = messageType.info?.mimetype,
+ body = messageType.body,
+ )
+ is VideoMessageType -> null // Use the thumbnail here?
+ else -> null
+ }
+ }
+ else -> null
+ } ?: return null
+
+ return fileResult
+ .onFailure {
+ Timber.tag(loggerTag.value).e(it, "Failed to download image for notification")
+ }
+ .map { mediaFile ->
+ val authority = "${context.packageName}.notifications.fileprovider"
+ FileProvider.getUriForFile(context, authority, mediaFile)
+ }
+ .getOrNull()
+ }
}
@Suppress("LongParameterList")
diff --git a/libraries/push/impl/src/main/kotlin/io/element/android/libraries/push/impl/notifications/NotificationBitmapLoader.kt b/libraries/push/impl/src/main/kotlin/io/element/android/libraries/push/impl/notifications/NotificationBitmapLoader.kt
index e78ce37639..4c1e3043ad 100644
--- a/libraries/push/impl/src/main/kotlin/io/element/android/libraries/push/impl/notifications/NotificationBitmapLoader.kt
+++ b/libraries/push/impl/src/main/kotlin/io/element/android/libraries/push/impl/notifications/NotificationBitmapLoader.kt
@@ -21,7 +21,7 @@ import android.graphics.Bitmap
import android.os.Build
import androidx.core.graphics.drawable.IconCompat
import androidx.core.graphics.drawable.toBitmap
-import coil.imageLoader
+import coil.ImageLoader
import coil.request.ImageRequest
import coil.transform.CircleCropTransformation
import io.element.android.libraries.di.ApplicationContext
@@ -39,21 +39,22 @@ class NotificationBitmapLoader @Inject constructor(
/**
* Get icon of a room.
* @param path mxc url
+ * @param imageLoader Coil image loader
*/
- suspend fun getRoomBitmap(path: String?): Bitmap? {
+ suspend fun getRoomBitmap(path: String?, imageLoader: ImageLoader): Bitmap? {
if (path == null) {
return null
}
- return loadRoomBitmap(path)
+ return loadRoomBitmap(path, imageLoader)
}
- private suspend fun loadRoomBitmap(path: String): Bitmap? {
+ private suspend fun loadRoomBitmap(path: String, imageLoader: ImageLoader): Bitmap? {
return try {
val imageRequest = ImageRequest.Builder(context)
.data(MediaRequestData(MediaSource(path), MediaRequestData.Kind.Thumbnail(1024)))
.transformations(CircleCropTransformation())
.build()
- val result = context.imageLoader.execute(imageRequest)
+ val result = imageLoader.execute(imageRequest)
result.drawable?.toBitmap()
} catch (e: Throwable) {
Timber.e(e, "Unable to load room bitmap")
@@ -65,22 +66,23 @@ class NotificationBitmapLoader @Inject constructor(
* Get icon of a user.
* Before Android P, this does nothing because the icon won't be used
* @param path mxc url
+ * @param imageLoader Coil image loader
*/
- suspend fun getUserIcon(path: String?): IconCompat? {
+ suspend fun getUserIcon(path: String?, imageLoader: ImageLoader): IconCompat? {
if (path == null || sdkIntProvider.get() < Build.VERSION_CODES.P) {
return null
}
- return loadUserIcon(path)
+ return loadUserIcon(path, imageLoader)
}
- private suspend fun loadUserIcon(path: String): IconCompat? {
+ private suspend fun loadUserIcon(path: String, imageLoader: ImageLoader): IconCompat? {
return try {
val imageRequest = ImageRequest.Builder(context)
.data(MediaRequestData(MediaSource(path), MediaRequestData.Kind.Thumbnail(1024)))
.transformations(CircleCropTransformation())
.build()
- val result = context.imageLoader.execute(imageRequest)
+ val result = imageLoader.execute(imageRequest)
val bitmap = result.drawable?.toBitmap()
return bitmap?.let { IconCompat.createWithBitmap(it) }
} catch (e: Throwable) {
diff --git a/libraries/push/impl/src/main/kotlin/io/element/android/libraries/push/impl/notifications/NotificationFactory.kt b/libraries/push/impl/src/main/kotlin/io/element/android/libraries/push/impl/notifications/NotificationFactory.kt
index 15c236eac9..4abdc03123 100644
--- a/libraries/push/impl/src/main/kotlin/io/element/android/libraries/push/impl/notifications/NotificationFactory.kt
+++ b/libraries/push/impl/src/main/kotlin/io/element/android/libraries/push/impl/notifications/NotificationFactory.kt
@@ -17,6 +17,7 @@
package io.element.android.libraries.push.impl.notifications
import android.app.Notification
+import coil.ImageLoader
import io.element.android.libraries.matrix.api.core.RoomId
import io.element.android.libraries.matrix.api.user.MatrixUser
import io.element.android.libraries.push.impl.notifications.factories.NotificationCreator
@@ -36,6 +37,7 @@ class NotificationFactory @Inject constructor(
suspend fun Map.toNotifications(
currentUser: MatrixUser,
+ imageLoader: ImageLoader,
): List {
return map { (roomId, events) ->
when {
@@ -46,6 +48,7 @@ class NotificationFactory @Inject constructor(
currentUser = currentUser,
events = messageEvents,
roomId = roomId,
+ imageLoader = imageLoader,
)
}
}
diff --git a/libraries/push/impl/src/main/kotlin/io/element/android/libraries/push/impl/notifications/NotificationMediaRepo.kt b/libraries/push/impl/src/main/kotlin/io/element/android/libraries/push/impl/notifications/NotificationMediaRepo.kt
new file mode 100644
index 0000000000..505a4f4a3c
--- /dev/null
+++ b/libraries/push/impl/src/main/kotlin/io/element/android/libraries/push/impl/notifications/NotificationMediaRepo.kt
@@ -0,0 +1,120 @@
+/*
+ * 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.push.impl.notifications
+
+import com.squareup.anvil.annotations.ContributesBinding
+import dagger.assisted.Assisted
+import dagger.assisted.AssistedFactory
+import dagger.assisted.AssistedInject
+import io.element.android.libraries.di.AppScope
+import io.element.android.libraries.di.CacheDirectory
+import io.element.android.libraries.matrix.api.MatrixClient
+import io.element.android.libraries.matrix.api.media.MediaSource
+import io.element.android.libraries.matrix.api.mxc.MxcTools
+import java.io.File
+
+/**
+ * Fetches the media file for a notification.
+ *
+ * Media is downloaded from the rust sdk and stored in the application's cache directory.
+ * Media files are indexed by their Matrix Content (mxc://) URI and considered immutable.
+ * Whenever a given mxc is found in the cache, it is returned immediately.
+ */
+interface NotificationMediaRepo {
+
+ /**
+ * Factory for [NotificationMediaRepo].
+ */
+ fun interface Factory {
+ /**
+ * Creates a [NotificationMediaRepo].
+ *
+ */
+ fun create(
+ client: MatrixClient
+ ): NotificationMediaRepo
+ }
+
+ /**
+ * Returns the file.
+ *
+ * In case of a cache hit the file is returned immediately.
+ * In case of a cache miss the file is downloaded and then returned.
+ *
+ * @param mediaSource the media source of the media.
+ * @param mimeType the mime type of the media.
+ * @param body the body of the message.
+ * @return A [Result] holding either the media [File] from the cache directory or an [Exception].
+ */
+ suspend fun getMediaFile(
+ mediaSource: MediaSource,
+ mimeType: String?,
+ body: String?,
+ ): Result
+}
+
+class DefaultNotificationMediaRepo @AssistedInject constructor(
+ @CacheDirectory private val cacheDir: File,
+ private val mxcTools: MxcTools,
+ @Assisted private val client: MatrixClient,
+) : NotificationMediaRepo {
+
+ @ContributesBinding(AppScope::class)
+ @AssistedFactory
+ fun interface Factory : NotificationMediaRepo.Factory {
+ override fun create(
+ client: MatrixClient,
+ ): DefaultNotificationMediaRepo
+ }
+
+ private val matrixMediaLoader = client.mediaLoader
+
+ override suspend fun getMediaFile(
+ mediaSource: MediaSource,
+ mimeType: String?,
+ body: String?,
+ ): Result {
+ val cachedFile = mediaSource.cachedFile()
+ return when {
+ cachedFile == null -> Result.failure(IllegalStateException("Invalid mxcUri."))
+ cachedFile.exists() -> Result.success(cachedFile)
+ else -> matrixMediaLoader.downloadMediaFile(
+ source = mediaSource,
+ mimeType = mimeType,
+ body = body,
+ ).mapCatching {
+ it.use { mediaFile ->
+ val dest = cachedFile.apply { parentFile?.mkdirs() }
+ if (mediaFile.persist(dest.path)) {
+ dest
+ } else {
+ error("Failed to move file to cache.")
+ }
+ }
+ }
+ }
+ }
+
+ private fun MediaSource.cachedFile(): File? = mxcTools.mxcUri2FilePath(url)?.let {
+ File("${cacheDir.path}/$CACHE_NOTIFICATION_SUBDIR/$it")
+ }
+}
+
+/**
+ * Subdirectory of the application's cache directory where file are stored.
+ */
+private const val CACHE_NOTIFICATION_SUBDIR = "temp/notif"
diff --git a/libraries/push/impl/src/main/kotlin/io/element/android/libraries/push/impl/notifications/NotificationRenderer.kt b/libraries/push/impl/src/main/kotlin/io/element/android/libraries/push/impl/notifications/NotificationRenderer.kt
index 713392c695..d05f3a1d03 100644
--- a/libraries/push/impl/src/main/kotlin/io/element/android/libraries/push/impl/notifications/NotificationRenderer.kt
+++ b/libraries/push/impl/src/main/kotlin/io/element/android/libraries/push/impl/notifications/NotificationRenderer.kt
@@ -16,6 +16,7 @@
package io.element.android.libraries.push.impl.notifications
+import coil.ImageLoader
import io.element.android.libraries.core.log.logger.LoggerTag
import io.element.android.libraries.matrix.api.core.RoomId
import io.element.android.libraries.matrix.api.user.MatrixUser
@@ -38,11 +39,12 @@ class NotificationRenderer @Inject constructor(
suspend fun render(
currentUser: MatrixUser,
useCompleteNotificationFormat: Boolean,
- eventsToProcess: List>
+ eventsToProcess: List>,
+ imageLoader: ImageLoader,
) {
val groupedEvents = eventsToProcess.groupByType()
with(notificationFactory) {
- val roomNotifications = groupedEvents.roomEvents.toNotifications(currentUser)
+ val roomNotifications = groupedEvents.roomEvents.toNotifications(currentUser, imageLoader)
val invitationNotifications = groupedEvents.invitationEvents.toNotifications()
val simpleNotifications = groupedEvents.simpleEvents.toNotifications()
val fallbackNotifications = groupedEvents.fallbackEvents.toNotifications()
diff --git a/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/verification/VerificationEmoji.kt b/libraries/push/impl/src/main/kotlin/io/element/android/libraries/push/impl/notifications/NotificationsFileProvider.kt
similarity index 69%
rename from libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/verification/VerificationEmoji.kt
rename to libraries/push/impl/src/main/kotlin/io/element/android/libraries/push/impl/notifications/NotificationsFileProvider.kt
index 43b89b6587..11999207ed 100644
--- a/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/verification/VerificationEmoji.kt
+++ b/libraries/push/impl/src/main/kotlin/io/element/android/libraries/push/impl/notifications/NotificationsFileProvider.kt
@@ -14,9 +14,12 @@
* limitations under the License.
*/
-package io.element.android.libraries.matrix.api.verification
+package io.element.android.libraries.push.impl.notifications
-data class VerificationEmoji(
- val code: String,
- val name: String,
-)
+import androidx.core.content.FileProvider
+
+/**
+ * We have to declare our own file provider to avoid collision with other modules
+ * having their own.
+ */
+class NotificationsFileProvider : FileProvider()
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 cde4f489a2..015b32c1d0 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
@@ -23,6 +23,7 @@ import androidx.core.app.NotificationCompat
import androidx.core.app.Person
import androidx.core.text.buildSpannedString
import androidx.core.text.inSpans
+import coil.ImageLoader
import io.element.android.libraries.matrix.api.core.RoomId
import io.element.android.libraries.matrix.api.user.MatrixUser
import io.element.android.libraries.push.impl.R
@@ -42,6 +43,7 @@ class RoomGroupMessageCreator @Inject constructor(
currentUser: MatrixUser,
events: List,
roomId: RoomId,
+ imageLoader: ImageLoader,
): RoomNotification.Message {
val lastKnownRoomEvent = events.last()
val roomName = lastKnownRoomEvent.roomName ?: lastKnownRoomEvent.senderName ?: "Room name (${roomId.value.take(8)}…)"
@@ -49,13 +51,13 @@ class RoomGroupMessageCreator @Inject constructor(
val style = NotificationCompat.MessagingStyle(
Person.Builder()
.setName(currentUser.displayName?.annotateForDebug(50))
- .setIcon(bitmapLoader.getUserIcon(currentUser.avatarUrl))
+ .setIcon(bitmapLoader.getUserIcon(currentUser.avatarUrl, imageLoader))
.setKey(lastKnownRoomEvent.sessionId.value)
.build()
).also {
it.conversationTitle = roomName.takeIf { roomIsGroup }?.annotateForDebug(51)
it.isGroupConversation = roomIsGroup
- it.addMessagesFromEvents(events)
+ it.addMessagesFromEvents(events, imageLoader)
}
val tickerText = if (roomIsGroup) {
@@ -64,7 +66,7 @@ class RoomGroupMessageCreator @Inject constructor(
stringProvider.getString(R.string.notification_ticker_text_dm, events.last().senderName, events.last().description)
}
- val largeBitmap = getRoomBitmap(events)
+ val largeBitmap = getRoomBitmap(events, imageLoader)
val lastMessageTimestamp = events.last().timestamp
val smartReplyErrors = events.filter { it.isSmartReplyError() }
@@ -98,14 +100,17 @@ class RoomGroupMessageCreator @Inject constructor(
)
}
- private suspend fun NotificationCompat.MessagingStyle.addMessagesFromEvents(events: List) {
+ private suspend fun NotificationCompat.MessagingStyle.addMessagesFromEvents(
+ events: List,
+ imageLoader: ImageLoader,
+ ) {
events.forEach { event ->
val senderPerson = if (event.outGoingMessage) {
null
} else {
Person.Builder()
.setName(event.senderName?.annotateForDebug(70))
- .setIcon(bitmapLoader.getUserIcon(event.senderAvatarPath))
+ .setIcon(bitmapLoader.getUserIcon(event.senderAvatarPath, imageLoader))
.setKey(event.senderId.value)
.build()
}
@@ -167,10 +172,13 @@ class RoomGroupMessageCreator @Inject constructor(
}
}
- private suspend fun getRoomBitmap(events: List): Bitmap? {
+ private suspend fun getRoomBitmap(
+ events: List,
+ imageLoader: ImageLoader,
+ ): Bitmap? {
// Use the last event (most recent?)
return events.reversed().firstNotNullOfOrNull { it.roomAvatarPath }
- ?.let { bitmapLoader.getRoomBitmap(it) }
+ ?.let { bitmapLoader.getRoomBitmap(it, imageLoader) }
}
}
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 a7135cee74..ec2cd227ca 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
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2020 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.
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 1b6bb8a67a..4b30bbe86d 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
@@ -58,9 +58,8 @@ data class NotifiableMessageEvent(
override val description: String = body ?: ""
val title: String = senderName ?: ""
- // TODO EAx The image has to be downloaded and expose using the file provider.
- // Example of value from Element Android:
- // content://im.vector.app.debug.mx-sdk.fileprovider/downloads/downloads/816abf76d806c768760568952b1862c8/F/72c33edd23dee3b95f4d5a18aa25fa54/image.png
+ // Example of value:
+ // content://io.element.android.x.debug.notifications.fileprovider/downloads/temp/notif/matrix.org/XGItzSDOnSyXjYtOPfiKexDJ
val imageUri: Uri?
get() = imageUriString?.let { Uri.parse(it) }
}
diff --git a/libraries/push/impl/src/main/res/values-fr/translations.xml b/libraries/push/impl/src/main/res/values-fr/translations.xml
index 8ba38a31c3..daf8a092a6 100644
--- a/libraries/push/impl/src/main/res/values-fr/translations.xml
+++ b/libraries/push/impl/src/main/res/values-fr/translations.xml
@@ -8,6 +8,7 @@
"Rejoindre"
"Rejeter"
"Vous a invité(e) à discuter"
+ "Mentionné(e): %1$s"
"Nouveaux messages"
"A réagi avec %1$s"
"Marquer comme lu"
diff --git a/libraries/push/impl/src/main/res/values-hu/translations.xml b/libraries/push/impl/src/main/res/values-hu/translations.xml
new file mode 100644
index 0000000000..074a1f7c9f
--- /dev/null
+++ b/libraries/push/impl/src/main/res/values-hu/translations.xml
@@ -0,0 +1,29 @@
+
+
+ "Hívás"
+ "Események figyelése"
+ "Zajos értesítések"
+ "Csendes értesítések"
+ "** Nem sikerült elküldeni – nyissa meg a szobát"
+ "Csatlakozás"
+ "Elutasítás"
+ "Meghívta, hogy csevegjen"
+ "Megemlítette Önt: %1$s"
+ "Új üzenetek"
+ "Ezzel reagált: %1$s"
+ "Megjelölés olvasottként"
+ "Meghívta, hogy csatlakozzon a szobához"
+ "Én"
+ "Az értesítést nézi! Kattintson ide!"
+ "%1$s: %2$s"
+ "%1$s: %2$s %3$s"
+ "%1$s és %2$s"
+ "%1$s itt: %2$s"
+ "%1$s itt: %2$s és %3$s"
+ "Válassza ki az értesítések fogadásának módját"
+ "Háttérszinkronizálás"
+ "Google szolgáltatások"
+ "A Google Play szolgáltatások nem találhatók. Előfordulhat, hogy az értesítések nem működnek megfelelően."
+ "Értesítés"
+ "Gyors válasz"
+
diff --git a/libraries/push/impl/src/main/res/values-in/translations.xml b/libraries/push/impl/src/main/res/values-in/translations.xml
new file mode 100644
index 0000000000..0e3f3699f0
--- /dev/null
+++ b/libraries/push/impl/src/main/res/values-in/translations.xml
@@ -0,0 +1,47 @@
+
+
+ "Panggil"
+ "Mendengarkan peristiwa"
+ "Pemberitahuan berisik"
+ "Pemberitahuan diam"
+ "** Gagal mengirim — silakan buka ruangan"
+ "Bergabung"
+ "Tolak"
+ "Mengundang Anda untuk mengobrol"
+ "Menyebutkan Anda: %1$s"
+ "Pesan Baru"
+ "Menghapus dengan %1$s"
+ "Tandai sebagai dibaca"
+ "Mengundang Anda untuk bergabung ke ruangan"
+ "Saya"
+ "Anda sedang melihat pemberitahuan ini! Klik saya!"
+ "%1$s: %2$s"
+ "%1$s: %2$s %3$s"
+ "%1$s dan %2$s"
+ "%1$s di %2$s"
+ "%1$s di %2$s dan %3$s"
+
+ - "%1$s: %2$d pesan"
+
+
+ - "%d pemberitahuan"
+
+
+ - "%d undangan"
+
+
+ - "%d pesan baru"
+
+
+ - "%d pesan pemberitahuan yang belum dibaca"
+
+
+ - "%d ruangan"
+
+ "Pilih cara menerima notifikasi"
+ "Sinkronisasi latar belakang"
+ "Layanan Google"
+ "Tidak ditemukan Layanan Google Play yang valid. Pemberitahuan mungkin tidak berfungsi dengan baik."
+ "Notifikasi"
+ "Balas cepat"
+
diff --git a/libraries/push/impl/src/main/res/xml/notifications_provider_paths.xml b/libraries/push/impl/src/main/res/xml/notifications_provider_paths.xml
new file mode 100644
index 0000000000..7c15e41df3
--- /dev/null
+++ b/libraries/push/impl/src/main/res/xml/notifications_provider_paths.xml
@@ -0,0 +1,6 @@
+
+
+
+
\ No newline at end of file
diff --git a/libraries/push/impl/src/test/kotlin/io/element/android/libraries/push/impl/notifications/DefaultNotificationDrawerManagerTest.kt b/libraries/push/impl/src/test/kotlin/io/element/android/libraries/push/impl/notifications/DefaultNotificationDrawerManagerTest.kt
index 6b4ea24fd4..e641029c0d 100644
--- a/libraries/push/impl/src/test/kotlin/io/element/android/libraries/push/impl/notifications/DefaultNotificationDrawerManagerTest.kt
+++ b/libraries/push/impl/src/test/kotlin/io/element/android/libraries/push/impl/notifications/DefaultNotificationDrawerManagerTest.kt
@@ -24,6 +24,7 @@ import io.element.android.libraries.matrix.test.A_THREAD_ID
import io.element.android.libraries.matrix.test.FakeMatrixClientProvider
import io.element.android.libraries.matrix.test.core.aBuildMeta
import io.element.android.libraries.push.impl.notifications.fake.FakeAndroidNotificationFactory
+import io.element.android.libraries.push.impl.notifications.fake.FakeImageLoaderHolder
import io.element.android.libraries.push.impl.notifications.fake.FakeRoomGroupMessageCreator
import io.element.android.libraries.push.impl.notifications.fake.FakeSummaryGroupMessageCreator
import io.element.android.libraries.push.impl.notifications.fixtures.aNotifiableMessageEvent
@@ -129,6 +130,7 @@ class DefaultNotificationDrawerManagerTest {
dispatchers = testCoroutineDispatchers(useUnconfinedTestDispatcher = true),
buildMeta = aBuildMeta(),
matrixClientProvider = FakeMatrixClientProvider(),
+ imageLoaderHolder = FakeImageLoaderHolder(),
)
}
}
diff --git a/libraries/push/impl/src/test/kotlin/io/element/android/libraries/push/impl/notifications/NotifiableEventResolverTest.kt b/libraries/push/impl/src/test/kotlin/io/element/android/libraries/push/impl/notifications/NotifiableEventResolverTest.kt
index 6276983cc9..bad49b64ef 100644
--- a/libraries/push/impl/src/test/kotlin/io/element/android/libraries/push/impl/notifications/NotifiableEventResolverTest.kt
+++ b/libraries/push/impl/src/test/kotlin/io/element/android/libraries/push/impl/notifications/NotifiableEventResolverTest.kt
@@ -42,6 +42,7 @@ import io.element.android.libraries.matrix.test.A_USER_ID_2
import io.element.android.libraries.matrix.test.FakeMatrixClient
import io.element.android.libraries.matrix.test.FakeMatrixClientProvider
import io.element.android.libraries.matrix.test.notification.FakeNotificationService
+import io.element.android.libraries.push.impl.notifications.fake.FakeNotificationMediaRepo
import io.element.android.libraries.push.impl.notifications.model.FallbackNotifiableEvent
import io.element.android.libraries.push.impl.notifications.model.InviteNotifiableEvent
import io.element.android.libraries.push.impl.notifications.model.NotifiableMessageEvent
@@ -257,7 +258,7 @@ class NotifiableEventResolverTest {
createNotificationData(
content = NotificationContent.MessageLike.RoomMessage(
senderId = A_USER_ID_2,
- messageType = LocationMessageType("Location", "geo:1,2", null),
+ messageType = LocationMessageType("Location", "geo:1,2", null),
)
)
)
@@ -274,7 +275,7 @@ class NotifiableEventResolverTest {
createNotificationData(
content = NotificationContent.MessageLike.RoomMessage(
senderId = A_USER_ID_2,
- messageType = NoticeMessageType("Notice", null),
+ messageType = NoticeMessageType("Notice", null),
)
)
)
@@ -291,7 +292,7 @@ class NotifiableEventResolverTest {
createNotificationData(
content = NotificationContent.MessageLike.RoomMessage(
senderId = A_USER_ID_2,
- messageType = EmoteMessageType("is happy", null),
+ messageType = EmoteMessageType("is happy", null),
)
)
)
@@ -487,11 +488,15 @@ class NotifiableEventResolverTest {
Result.success(FakeMatrixClient(notificationService = notificationService))
}
})
-
+ val notificationMediaRepoFactory = NotificationMediaRepo.Factory {
+ FakeNotificationMediaRepo()
+ }
return NotifiableEventResolver(
stringProvider = AndroidStringProvider(context.resources),
clock = FakeSystemClock(),
matrixClientProvider = matrixClientProvider,
+ notificationMediaRepoFactory = notificationMediaRepoFactory,
+ context = context,
)
}
@@ -512,7 +517,6 @@ class NotifiableEventResolverTest {
isNoisy = false,
timestamp = A_TIMESTAMP,
content = content,
- contentUrl = null,
hasMention = hasMention,
)
}
diff --git a/libraries/push/impl/src/test/kotlin/io/element/android/libraries/push/impl/notifications/NotificationFactoryTest.kt b/libraries/push/impl/src/test/kotlin/io/element/android/libraries/push/impl/notifications/NotificationFactoryTest.kt
index 18d8870ac3..ca41fcc15a 100644
--- a/libraries/push/impl/src/test/kotlin/io/element/android/libraries/push/impl/notifications/NotificationFactoryTest.kt
+++ b/libraries/push/impl/src/test/kotlin/io/element/android/libraries/push/impl/notifications/NotificationFactoryTest.kt
@@ -23,6 +23,7 @@ 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
import io.element.android.libraries.push.impl.notifications.fake.FakeAndroidNotificationFactory
+import io.element.android.libraries.push.impl.notifications.fake.FakeImageLoader
import io.element.android.libraries.push.impl.notifications.fake.FakeRoomGroupMessageCreator
import io.element.android.libraries.push.impl.notifications.fake.FakeSummaryGroupMessageCreator
import io.element.android.libraries.push.impl.notifications.fixtures.aNotifiableMessageEvent
@@ -30,12 +31,15 @@ import io.element.android.libraries.push.impl.notifications.fixtures.aSimpleNoti
import io.element.android.libraries.push.impl.notifications.fixtures.anInviteNotifiableEvent
import kotlinx.coroutines.test.runTest
import org.junit.Test
+import org.junit.runner.RunWith
+import org.robolectric.RobolectricTestRunner
private val MY_AVATAR_URL: String? = null
private val AN_INVITATION_EVENT = anInviteNotifiableEvent(roomId = A_ROOM_ID)
private val A_SIMPLE_EVENT = aSimpleNotifiableEvent(eventId = AN_EVENT_ID)
private val A_MESSAGE_EVENT = aNotifiableMessageEvent(eventId = AN_EVENT_ID, roomId = A_ROOM_ID)
+@RunWith(RobolectricTestRunner::class)
class NotificationFactoryTest {
private val androidNotificationFactory = FakeAndroidNotificationFactory()
@@ -130,11 +134,14 @@ class NotificationFactoryTest {
)
val roomWithMessage = mapOf(A_ROOM_ID to listOf(ProcessedEvent(ProcessedEvent.Type.KEEP, A_MESSAGE_EVENT)))
+ val fakeImageLoader = FakeImageLoader()
val result = roomWithMessage.toNotifications(
- MatrixUser(A_SESSION_ID, A_SESSION_ID.value, MY_AVATAR_URL)
+ currentUser = MatrixUser(A_SESSION_ID, A_SESSION_ID.value, MY_AVATAR_URL),
+ imageLoader = fakeImageLoader.getImageLoader(),
)
assertThat(result).isEqualTo(listOf(expectedNotification))
+ assertThat(fakeImageLoader.getCoilRequests().size).isEqualTo(0)
}
@Test
@@ -142,8 +149,10 @@ class NotificationFactoryTest {
val events = listOf(ProcessedEvent(ProcessedEvent.Type.REMOVE, A_MESSAGE_EVENT))
val emptyRoom = mapOf(A_ROOM_ID to events)
+ val fakeImageLoader = FakeImageLoader()
val result = emptyRoom.toNotifications(
- MatrixUser(A_SESSION_ID, A_SESSION_ID.value, MY_AVATAR_URL)
+ currentUser = MatrixUser(A_SESSION_ID, A_SESSION_ID.value, MY_AVATAR_URL),
+ imageLoader = fakeImageLoader.getImageLoader(),
)
assertThat(result).isEqualTo(
@@ -153,14 +162,17 @@ class NotificationFactoryTest {
)
)
)
+ assertThat(fakeImageLoader.getCoilRequests().size).isEqualTo(0)
}
@Test
fun `given a room with only redacted events when mapping to notification then is Empty`() = testWith(notificationFactory) {
val redactedRoom = mapOf(A_ROOM_ID to listOf(ProcessedEvent(ProcessedEvent.Type.KEEP, A_MESSAGE_EVENT.copy(isRedacted = true))))
+ val fakeImageLoader = FakeImageLoader()
val result = redactedRoom.toNotifications(
- MatrixUser(A_SESSION_ID, A_SESSION_ID.value, MY_AVATAR_URL)
+ currentUser = MatrixUser(A_SESSION_ID, A_SESSION_ID.value, MY_AVATAR_URL),
+ imageLoader = fakeImageLoader.getImageLoader(),
)
assertThat(result).isEqualTo(
@@ -170,6 +182,7 @@ class NotificationFactoryTest {
)
)
)
+ assertThat(fakeImageLoader.getCoilRequests().size).isEqualTo(0)
}
@Test
@@ -189,11 +202,14 @@ class NotificationFactoryTest {
A_ROOM_ID,
)
+ val fakeImageLoader = FakeImageLoader()
val result = roomWithRedactedMessage.toNotifications(
- MatrixUser(A_SESSION_ID, A_SESSION_ID.value, MY_AVATAR_URL)
+ currentUser = MatrixUser(A_SESSION_ID, A_SESSION_ID.value, MY_AVATAR_URL),
+ imageLoader = fakeImageLoader.getImageLoader(),
)
assertThat(result).isEqualTo(listOf(expectedNotification))
+ assertThat(fakeImageLoader.getCoilRequests().size).isEqualTo(0)
}
}
diff --git a/libraries/push/impl/src/test/kotlin/io/element/android/libraries/push/impl/notifications/NotificationRendererTest.kt b/libraries/push/impl/src/test/kotlin/io/element/android/libraries/push/impl/notifications/NotificationRendererTest.kt
index 80875406c7..18f2266b87 100644
--- a/libraries/push/impl/src/test/kotlin/io/element/android/libraries/push/impl/notifications/NotificationRendererTest.kt
+++ b/libraries/push/impl/src/test/kotlin/io/element/android/libraries/push/impl/notifications/NotificationRendererTest.kt
@@ -21,12 +21,15 @@ import io.element.android.libraries.matrix.api.user.MatrixUser
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
+import io.element.android.libraries.push.impl.notifications.fake.FakeImageLoader
import io.element.android.libraries.push.impl.notifications.fake.FakeNotificationDisplayer
import io.element.android.libraries.push.impl.notifications.fake.FakeNotificationFactory
import io.element.android.libraries.push.impl.notifications.model.NotifiableEvent
import io.mockk.mockk
import kotlinx.coroutines.test.runTest
import org.junit.Test
+import org.junit.runner.RunWith
+import org.robolectric.RobolectricTestRunner
private const val MY_USER_DISPLAY_NAME = "display-name"
private const val MY_USER_AVATAR_URL = "avatar-url"
@@ -42,6 +45,7 @@ private val MESSAGE_META = RoomNotification.Message.Meta(
)
private val ONE_SHOT_META = OneShotNotification.Append.Meta(key = "ignored", summaryLine = "ignored", isNoisy = false, timestamp = -1)
+@RunWith(RobolectricTestRunner::class)
class NotificationRendererTest {
private val notificationDisplayer = FakeNotificationDisplayer()
@@ -197,7 +201,8 @@ class NotificationRendererTest {
notificationRenderer.render(
MatrixUser(A_SESSION_ID, MY_USER_DISPLAY_NAME, MY_USER_AVATAR_URL),
useCompleteNotificationFormat = USE_COMPLETE_NOTIFICATION_FORMAT,
- eventsToProcess = AN_EVENT_LIST
+ eventsToProcess = AN_EVENT_LIST,
+ imageLoader = FakeImageLoader().getImageLoader(),
)
}
diff --git a/libraries/push/impl/src/test/kotlin/io/element/android/libraries/push/impl/notifications/RoomGroupMessageCreatorTest.kt b/libraries/push/impl/src/test/kotlin/io/element/android/libraries/push/impl/notifications/RoomGroupMessageCreatorTest.kt
index 46c41454d3..399b0fc4b3 100644
--- a/libraries/push/impl/src/test/kotlin/io/element/android/libraries/push/impl/notifications/RoomGroupMessageCreatorTest.kt
+++ b/libraries/push/impl/src/test/kotlin/io/element/android/libraries/push/impl/notifications/RoomGroupMessageCreatorTest.kt
@@ -17,19 +17,15 @@
package io.element.android.libraries.push.impl.notifications
import android.content.Context
-import android.graphics.Color
-import android.graphics.drawable.ColorDrawable
import android.os.Build
-import coil.Coil
-import coil.ImageLoader
import coil.annotation.ExperimentalCoilApi
-import coil.test.FakeImageLoaderEngine
import com.google.common.truth.Truth.assertThat
import io.element.android.libraries.matrix.api.media.MediaSource
import io.element.android.libraries.matrix.test.A_ROOM_ID
import io.element.android.libraries.matrix.ui.components.aMatrixUser
import io.element.android.libraries.matrix.ui.media.MediaRequestData
import io.element.android.libraries.push.impl.notifications.factories.createNotificationCreator
+import io.element.android.libraries.push.impl.notifications.fake.FakeImageLoader
import io.element.android.libraries.push.impl.notifications.fixtures.aNotifiableMessageEvent
import io.element.android.services.toolbox.api.sdk.BuildVersionSdkIntProvider
import io.element.android.services.toolbox.impl.strings.AndroidStringProvider
@@ -50,6 +46,7 @@ class RoomGroupMessageCreatorTest {
@Test
fun `test createRoomMessage with one Event`() = runTest {
val sut = createRoomGroupMessageCreator()
+ val fakeImageLoader = FakeImageLoader()
val result = sut.createRoomMessage(
currentUser = aMatrixUser(),
events = listOf(
@@ -58,6 +55,7 @@ class RoomGroupMessageCreatorTest {
)
),
roomId = A_ROOM_ID,
+ imageLoader = fakeImageLoader.getImageLoader(),
)
val resultMetaWithoutFormatting = result.meta.copy(
summaryLine = result.meta.summaryLine.toString()
@@ -71,11 +69,13 @@ class RoomGroupMessageCreatorTest {
shouldBing = false,
)
)
+ assertThat(fakeImageLoader.getCoilRequests().size).isEqualTo(0)
}
@Test
fun `test createRoomMessage with one noisy Event`() = runTest {
val sut = createRoomGroupMessageCreator()
+ val fakeImageLoader = FakeImageLoader()
val result = sut.createRoomMessage(
currentUser = aMatrixUser(),
events = listOf(
@@ -84,6 +84,7 @@ class RoomGroupMessageCreatorTest {
)
),
roomId = A_ROOM_ID,
+ imageLoader = fakeImageLoader.getImageLoader(),
)
val resultMetaWithoutFormatting = result.meta.copy(
summaryLine = result.meta.summaryLine.toString()
@@ -97,6 +98,7 @@ class RoomGroupMessageCreatorTest {
shouldBing = true,
)
)
+ assertThat(fakeImageLoader.getCoilRequests().size).isEqualTo(0)
}
@Test
@@ -141,20 +143,7 @@ class RoomGroupMessageCreatorTest {
api: Int,
expectedCoilRequests: List,
) = runTest {
- val coilRequests = mutableListOf()
- val engine = FakeImageLoaderEngine.Builder()
- .intercept(
- predicate = {
- coilRequests.add(it)
- true
- },
- drawable = ColorDrawable(Color.BLUE)
- )
- .build()
- val imageLoader = ImageLoader.Builder(RuntimeEnvironment.getApplication())
- .components { add(engine) }
- .build()
- Coil.setImageLoader(imageLoader)
+ val fakeImageLoader = FakeImageLoader()
val sut = createRoomGroupMessageCreator(
sdkIntProvider = FakeBuildVersionSdkIntProvider(api)
)
@@ -170,6 +159,7 @@ class RoomGroupMessageCreatorTest {
)
),
roomId = A_ROOM_ID,
+ imageLoader = fakeImageLoader.getImageLoader(),
)
val resultMetaWithoutFormatting = result.meta.copy(
summaryLine = result.meta.summaryLine.toString()
@@ -183,12 +173,13 @@ class RoomGroupMessageCreatorTest {
shouldBing = false,
)
)
- assertThat(coilRequests.toList()).isEqualTo(expectedCoilRequests)
+ assertThat(fakeImageLoader.getCoilRequests()).isEqualTo(expectedCoilRequests)
}
@Test
fun `test createRoomMessage with two Events`() = runTest {
val sut = createRoomGroupMessageCreator()
+ val fakeImageLoader = FakeImageLoader()
val result = sut.createRoomMessage(
currentUser = aMatrixUser(),
events = listOf(
@@ -196,6 +187,7 @@ class RoomGroupMessageCreatorTest {
aNotifiableMessageEvent(timestamp = A_TIMESTAMP + 10),
),
roomId = A_ROOM_ID,
+ imageLoader = fakeImageLoader.getImageLoader(),
)
val resultMetaWithoutFormatting = result.meta.copy(
summaryLine = result.meta.summaryLine.toString()
@@ -209,11 +201,13 @@ class RoomGroupMessageCreatorTest {
shouldBing = false,
)
)
+ assertThat(fakeImageLoader.getCoilRequests().size).isEqualTo(0)
}
@Test
fun `test createRoomMessage with smart reply error`() = runTest {
val sut = createRoomGroupMessageCreator()
+ val fakeImageLoader = FakeImageLoader()
val result = sut.createRoomMessage(
currentUser = aMatrixUser(),
events = listOf(
@@ -223,6 +217,7 @@ class RoomGroupMessageCreatorTest {
),
),
roomId = A_ROOM_ID,
+ imageLoader = fakeImageLoader.getImageLoader(),
)
val resultMetaWithoutFormatting = result.meta.copy(
summaryLine = result.meta.summaryLine.toString()
@@ -236,11 +231,13 @@ class RoomGroupMessageCreatorTest {
shouldBing = false,
)
)
+ assertThat(fakeImageLoader.getCoilRequests().size).isEqualTo(0)
}
@Test
fun `test createRoomMessage for direct room`() = runTest {
val sut = createRoomGroupMessageCreator()
+ val fakeImageLoader = FakeImageLoader()
val result = sut.createRoomMessage(
currentUser = aMatrixUser(),
events = listOf(
@@ -249,6 +246,7 @@ class RoomGroupMessageCreatorTest {
),
),
roomId = A_ROOM_ID,
+ imageLoader = fakeImageLoader.getImageLoader(),
)
val resultMetaWithoutFormatting = result.meta.copy(
summaryLine = result.meta.summaryLine.toString()
@@ -262,6 +260,7 @@ class RoomGroupMessageCreatorTest {
shouldBing = false,
)
)
+ assertThat(fakeImageLoader.getCoilRequests().size).isEqualTo(0)
}
}
diff --git a/libraries/push/impl/src/test/kotlin/io/element/android/libraries/push/impl/notifications/fake/FakeImageLoader.kt b/libraries/push/impl/src/test/kotlin/io/element/android/libraries/push/impl/notifications/fake/FakeImageLoader.kt
new file mode 100644
index 0000000000..5c747b45e2
--- /dev/null
+++ b/libraries/push/impl/src/test/kotlin/io/element/android/libraries/push/impl/notifications/fake/FakeImageLoader.kt
@@ -0,0 +1,55 @@
+/*
+ * 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.push.impl.notifications.fake
+
+import android.graphics.Color
+import android.graphics.drawable.ColorDrawable
+import coil.ImageLoader
+import coil.annotation.ExperimentalCoilApi
+import coil.test.FakeImageLoaderEngine
+import org.robolectric.RuntimeEnvironment
+
+@OptIn(ExperimentalCoilApi::class)
+class FakeImageLoader {
+ private val coilRequests = mutableListOf()
+
+ private var cache: ImageLoader? = null
+
+ fun getImageLoader(): ImageLoader {
+ return cache ?: ImageLoader.Builder(RuntimeEnvironment.getApplication())
+ .components {
+ val engine = FakeImageLoaderEngine.Builder()
+ .intercept(
+ predicate = {
+ coilRequests.add(it)
+ true
+ },
+ drawable = ColorDrawable(Color.BLUE)
+ )
+ .build()
+ add(engine)
+ }
+ .build()
+ .also {
+ cache = it
+ }
+ }
+
+ fun getCoilRequests(): List {
+ return coilRequests.toList()
+ }
+}
diff --git a/libraries/matrixui/src/main/kotlin/io/element/android/libraries/matrix/ui/di/MatrixUIBindings.kt b/libraries/push/impl/src/test/kotlin/io/element/android/libraries/push/impl/notifications/fake/FakeImageLoaderHolder.kt
similarity index 58%
rename from libraries/matrixui/src/main/kotlin/io/element/android/libraries/matrix/ui/di/MatrixUIBindings.kt
rename to libraries/push/impl/src/test/kotlin/io/element/android/libraries/push/impl/notifications/fake/FakeImageLoaderHolder.kt
index 919971b307..0e18036e94 100644
--- a/libraries/matrixui/src/main/kotlin/io/element/android/libraries/matrix/ui/di/MatrixUIBindings.kt
+++ b/libraries/push/impl/src/test/kotlin/io/element/android/libraries/push/impl/notifications/fake/FakeImageLoaderHolder.kt
@@ -14,13 +14,15 @@
* limitations under the License.
*/
-package io.element.android.libraries.matrix.ui.di
+package io.element.android.libraries.push.impl.notifications.fake
-import com.squareup.anvil.annotations.ContributesTo
-import io.element.android.libraries.di.SessionScope
-import io.element.android.libraries.matrix.ui.media.LoggedInImageLoaderFactory
+import coil.ImageLoader
+import io.element.android.libraries.matrix.api.MatrixClient
+import io.element.android.libraries.matrix.ui.media.ImageLoaderHolder
-@ContributesTo(SessionScope::class)
-interface MatrixUIBindings {
- fun loggedInImageLoaderFactory(): LoggedInImageLoaderFactory
+class FakeImageLoaderHolder : ImageLoaderHolder {
+ private val fakeImageLoader = FakeImageLoader()
+ override fun get(client: MatrixClient): ImageLoader {
+ return fakeImageLoader.getImageLoader()
+ }
}
diff --git a/libraries/push/impl/src/test/kotlin/io/element/android/libraries/push/impl/notifications/fake/FakeNotificationFactory.kt b/libraries/push/impl/src/test/kotlin/io/element/android/libraries/push/impl/notifications/fake/FakeNotificationFactory.kt
index 60b9e10c3d..9c7755aa9d 100644
--- a/libraries/push/impl/src/test/kotlin/io/element/android/libraries/push/impl/notifications/fake/FakeNotificationFactory.kt
+++ b/libraries/push/impl/src/test/kotlin/io/element/android/libraries/push/impl/notifications/fake/FakeNotificationFactory.kt
@@ -40,7 +40,7 @@ class FakeNotificationFactory {
summaryNotification: SummaryNotification
) {
with(instance) {
- coEvery { groupedEvents.roomEvents.toNotifications(matrixUser) } returns roomNotifications
+ coEvery { groupedEvents.roomEvents.toNotifications(matrixUser, any()) } returns roomNotifications
every { groupedEvents.invitationEvents.toNotifications() } returns invitationNotifications
every { groupedEvents.simpleEvents.toNotifications() } returns simpleNotifications
every { groupedEvents.fallbackEvents.toNotifications() } returns fallbackNotifications
diff --git a/libraries/push/impl/src/test/kotlin/io/element/android/libraries/push/impl/notifications/fake/FakeNotificationMediaRepo.kt b/libraries/push/impl/src/test/kotlin/io/element/android/libraries/push/impl/notifications/fake/FakeNotificationMediaRepo.kt
new file mode 100644
index 0000000000..2657d984a0
--- /dev/null
+++ b/libraries/push/impl/src/test/kotlin/io/element/android/libraries/push/impl/notifications/fake/FakeNotificationMediaRepo.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.push.impl.notifications.fake
+
+import io.element.android.libraries.matrix.api.media.MediaSource
+import io.element.android.libraries.push.impl.notifications.NotificationMediaRepo
+import java.io.File
+
+class FakeNotificationMediaRepo : NotificationMediaRepo {
+ override suspend fun getMediaFile(
+ mediaSource: MediaSource,
+ mimeType: String?,
+ body: String?,
+ ): Result {
+ return Result.failure(IllegalStateException("Fake class"))
+ }
+}
diff --git a/libraries/push/impl/src/test/kotlin/io/element/android/libraries/push/impl/notifications/fake/FakeRoomGroupMessageCreator.kt b/libraries/push/impl/src/test/kotlin/io/element/android/libraries/push/impl/notifications/fake/FakeRoomGroupMessageCreator.kt
index b896737e6f..946b0ab0db 100644
--- a/libraries/push/impl/src/test/kotlin/io/element/android/libraries/push/impl/notifications/fake/FakeRoomGroupMessageCreator.kt
+++ b/libraries/push/impl/src/test/kotlin/io/element/android/libraries/push/impl/notifications/fake/FakeRoomGroupMessageCreator.kt
@@ -39,6 +39,7 @@ class FakeRoomGroupMessageCreator {
currentUser = matrixUser,
events = events,
roomId = roomId,
+ imageLoader = any(),
)
} returns mockMessage
return mockMessage
diff --git a/libraries/textcomposer/impl/src/main/kotlin/io/element/android/libraries/textcomposer/TextComposer.kt b/libraries/textcomposer/impl/src/main/kotlin/io/element/android/libraries/textcomposer/TextComposer.kt
index d9b284de6a..b3c87bc602 100644
--- a/libraries/textcomposer/impl/src/main/kotlin/io/element/android/libraries/textcomposer/TextComposer.kt
+++ b/libraries/textcomposer/impl/src/main/kotlin/io/element/android/libraries/textcomposer/TextComposer.kt
@@ -44,6 +44,7 @@ import androidx.compose.runtime.remember
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.clip
+import androidx.compose.ui.draw.clipToBounds
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.text.style.TextAlign
import androidx.compose.ui.text.style.TextOverflow
@@ -551,7 +552,7 @@ private fun ReplyToModeView(
) {
Text(
text = senderName,
- modifier = Modifier.fillMaxWidth(),
+ modifier = Modifier.fillMaxWidth().clipToBounds(),
style = ElementTheme.typography.fontBodySmMedium,
textAlign = TextAlign.Start,
color = ElementTheme.materialColors.primary,
diff --git a/libraries/textcomposer/impl/src/main/res/values-de/translations.xml b/libraries/textcomposer/impl/src/main/res/values-de/translations.xml
index 9a35f2b666..1bb9c78dbe 100644
--- a/libraries/textcomposer/impl/src/main/res/values-de/translations.xml
+++ b/libraries/textcomposer/impl/src/main/res/values-de/translations.xml
@@ -21,4 +21,5 @@
"Ohne Einrückung"
"Link"
"Anhang hinzufügen"
+ "Zum Aufnehmen gedrückt halten"
diff --git a/libraries/textcomposer/impl/src/main/res/values-hu/translations.xml b/libraries/textcomposer/impl/src/main/res/values-hu/translations.xml
new file mode 100644
index 0000000000..b4c96d4581
--- /dev/null
+++ b/libraries/textcomposer/impl/src/main/res/values-hu/translations.xml
@@ -0,0 +1,25 @@
+
+
+ "Felsorolás be/ki"
+ "Formázási beállítások bezárása"
+ "Kódblokk be/ki"
+ "Üzenet…"
+ "Hivatkozás létrehozása"
+ "Hivatkozás szerkesztése"
+ "Félkövér formátum alkalmazása"
+ "Dőlt formátum alkalmazása"
+ "Áthúzott formátum alkalmazása"
+ "Aláhúzott formátum alkalmazása"
+ "Teljes képernyős mód be/ki"
+ "Behúzás"
+ "Soron belüli kód formátum alkalmazása"
+ "Hivatkozás beállítása"
+ "Számozott lista be/ki"
+ "Írási beállítások megnyitása"
+ "Idézet be/ki"
+ "Hivatkozás eltávolítása"
+ "Behúzás nélkül"
+ "Hivatkozás"
+ "Melléklet hozzáadása"
+ "Tartsa a rögzítéshez"
+
diff --git a/libraries/textcomposer/impl/src/main/res/values-in/translations.xml b/libraries/textcomposer/impl/src/main/res/values-in/translations.xml
new file mode 100644
index 0000000000..8db2c18619
--- /dev/null
+++ b/libraries/textcomposer/impl/src/main/res/values-in/translations.xml
@@ -0,0 +1,25 @@
+
+
+ "Alihkan daftar poin"
+ "Tutup opsi pemformatan"
+ "Alihkan blok kode"
+ "Kirim pesan…"
+ "Buat tautan"
+ "Sunting tautan"
+ "Terapkan format tebal"
+ "Terapkan format miring"
+ "Terapkan format coret"
+ "Terapkan format garis bawah"
+ "Alihkan mode layar penuh"
+ "Beri indentasi"
+ "Terapkan format kode dalam baris"
+ "Tetapkan tautan"
+ "Alihkan daftar bernomor"
+ "Buka opsi penulisan"
+ "Alihkan kutipan"
+ "Hapus tautan"
+ "Hapus indentasi"
+ "Tautan"
+ "Tambahkan lampiran"
+ "Tahan untuk merekam"
+
diff --git a/libraries/ui-strings/src/main/res/values-cs/translations.xml b/libraries/ui-strings/src/main/res/values-cs/translations.xml
index ad1bbda209..ce469e9a70 100644
--- a/libraries/ui-strings/src/main/res/values-cs/translations.xml
+++ b/libraries/ui-strings/src/main/res/values-cs/translations.xml
@@ -109,6 +109,7 @@
"Tmavé"
"Chyba dešifrování"
"Možnosti pro vývojáře"
+ "Přímý chat"
"(upraveno)"
"Úpravy"
"* %1$s %2$s"
@@ -130,7 +131,7 @@
"Načítání…"
"Zpráva"
"Akce zprávy"
- "Rozložení zprávy"
+ "Zobrazení zpráv"
"Zpráva byla odstraněna"
"Moderní"
"Ztlumit"
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 436f6a95ae..19cadb6625 100644
--- a/libraries/ui-strings/src/main/res/values-de/translations.xml
+++ b/libraries/ui-strings/src/main/res/values-de/translations.xml
@@ -1,13 +1,28 @@
+ "Löschen"
"Passwort verbergen"
+ "Nach unten springen"
"Nur Erwähnungen"
"Stummgeschaltet"
+ "Seite %1$d"
+ "Pausieren"
+ "PIN-Feld"
+ "Abspielen"
"Umfrage"
"Umfrage beendet"
+ "Reagiere mit %1$s"
+ "Mit anderen Emojis reagieren"
+ "Gelesen von %1$s und %2$s"
+ "Gelesen von %1$s"
+ "Tippe, um alle anzuzeigen"
+ "Reaktion mit %1$s entfernen"
"Dateien senden"
"Passwort anzeigen"
+ "Anruf starten"
"Benutzermenü"
+ "Sprachnachricht aufnehmen."
+ "Aufnahme beenden"
"Akzeptieren"
"Zur Zeitleiste hinzufügen"
"Zurück"
@@ -24,6 +39,7 @@
"Erstellen"
"Raum erstellen"
"Ablehnen"
+ "Umfrage löschen"
"Deaktivieren"
"Erledigt"
"Bearbeiten"
@@ -66,23 +82,31 @@
"Nachricht senden"
"Teilen"
"Link teilen"
+ "Erneut anmelden"
+ "Abmelden"
+ "Trotzdem abmelden"
"Überspringen"
"Start"
"Chat starten"
"Verifizierung starten"
"Tippe, um die Karte zu laden"
"Foto machen"
+ "Für Optionen tippen"
+ "Erneut versuchen"
"Quelle anzeigen"
"Ja"
"Über"
"Nutzungsrichtlinie"
"Erweiterte Einstellungen"
"Analysedaten"
+ "Erscheinungsbild"
"Audio"
"Blasen"
+ "Chat-Backup"
"Copyright"
"Raum wird erstellt…"
"Raum verlassen"
+ "Dunkel"
"Dekodierungsfehler"
"Entwickleroptionen"
"(bearbeitet)"
@@ -91,6 +115,7 @@
"Verschlüsselung aktiviert"
"PIN eingeben"
"Fehler"
+ "Alle"
"Datei"
"Datei wurde unter Downloads gespeichert"
"Nachricht weiterleiten"
@@ -100,9 +125,11 @@
"APK installieren"
"Diese Matrix-ID kann nicht gefunden werden, daher wird die Einladung möglicherweise nicht empfangen."
"Raum verlassen"
+ "Hell"
"Link in die Zwischenablage kopiert"
"Laden…"
"Nachricht"
+ "Nachrichtenaktionen"
"Nachrichtenlayout"
"Nachricht entfernt"
"Modern"
@@ -121,23 +148,31 @@
"Wird erneuert…"
"%1$s antworten"
"Einen Fehler melden"
+ "Ein Problem melden"
"Bericht eingereicht"
"Rich-Text-Editor"
+ "Raum"
"Raumname"
"z.B. dein Projektname"
+ "Bildschirmsperre"
"Nach jemandem suchen"
"Suchergebnisse"
"Sicherheit"
+ "Gesehen von"
"Wird gesendet…"
+ "Senden fehlgeschlagen"
+ "Gesendet"
"Server wird nicht unterstützt"
"Server-URL"
"Einstellungen"
"Geteilter Standort"
+ "Abmelden"
"Chat wird gestartet…"
"Sticker"
"Erfolg"
"Vorschläge"
"Synchronisieren"
+ "System"
"Text"
"Hinweise von Drittanbietern"
"Thread"
@@ -146,28 +181,42 @@
"Entschlüsselung nicht möglich"
"Einladungen konnten nicht an einen oder mehrere Benutzer gesendet werden."
"Einladung(en) konnte(n) nicht gesendet werden"
+ "Entsperren"
"Stummschaltung aufheben"
"Nicht unterstütztes Ereignis"
"Benutzername"
"Verifizierung abgebrochen"
"Verifizierung abgeschlossen"
"Video"
+ "Sprachnachricht"
"Warten…"
+ "Warte auf diese Nachricht"
"Bist du sicher, dass du diese Umfrage beenden möchtest?"
"Umfrage: %1$s"
+ "Gerät verifizieren"
"Bestätigung"
"Warnung"
"Fehler beim Erstellen des Permalinks"
"%1$s konnte die Karte nicht laden. Bitte versuche es später erneut."
"Fehler beim Laden der Nachrichten"
"%1$s konnte nicht auf deinen Standort zugreifen. Bitte versuche es später erneut."
+ "Fehler beim Hochladen der Sprachnachricht."
"%1$s hat keine Erlaubnis, auf deinen Standort zuzugreifen. Du kannst den Zugriff in den Einstellungen aktivieren."
"%1$s hat keine Erlaubnis, auf deinen Standort zuzugreifen. Aktiviere unten den Zugriff."
+ "%1$s hat nicht die Erlaubnis auf dein Mikrofon zuzugreifen. Aktiviere den Zugriff, um eine Sprachnachricht aufzunehmen."
"Einige Nachrichten wurden nicht gesendet"
"Entschuldigung, es ist ein Fehler aufgetreten"
"🔐️ Begleite mich auf %1$s"
"Hey, sprich mit mir auf %1$s: %2$s"
"%1$s Android"
+
+ - "%1$d eingegebene Ziffer"
+ - "%1$d eingegebene Ziffern"
+
+
+ - "Gelesen von %1$s und %2$d anderen"
+ - "Gelesen von %1$s und %2$d anderen"
+
- "%1$d Mitglied"
- "%1$d Mitglieder"
diff --git a/libraries/ui-strings/src/main/res/values-fr/translations.xml b/libraries/ui-strings/src/main/res/values-fr/translations.xml
index f13e524ad6..60e4e78c2e 100644
--- a/libraries/ui-strings/src/main/res/values-fr/translations.xml
+++ b/libraries/ui-strings/src/main/res/values-fr/translations.xml
@@ -2,15 +2,21 @@
"Supprimer"
"Masquer le mot de passe"
+ "Retourner à la fin de la conversation"
"Mentions uniquement"
"En sourdine"
+ "Page %1$d"
"Pause"
"Code PIN"
"Lecture"
"Sondage"
"Sondage terminé"
+ "Réagir avec %1$s"
+ "Réagir avec d’autres emojis"
"Lu par %1$s et %2$s"
"Lu par %1$s"
+ "Taper pour voir toute la liste"
+ "Supprimer la réaction avec %1$s"
"Envoyer des fichiers"
"Afficher le mot de passe"
"Démarrer un appel"
@@ -33,6 +39,7 @@
"Créer"
"Créer un salon"
"Refuser"
+ "Supprimer le sondage"
"Désactiver"
"Terminé"
"Modifier"
@@ -88,6 +95,7 @@
"Essayer à nouveau"
"Afficher la source"
"Oui"
+ "Voir plus"
"À propos"
"Politique d’utilisation acceptable"
"Paramètres avancés"
@@ -102,6 +110,7 @@
"Sombre"
"Erreur de déchiffrement"
"Options pour les développeurs"
+ "Discussion à deux"
"(modifié)"
"Édition"
"* %1$s %2$s"
diff --git a/libraries/ui-strings/src/main/res/values-hu/translations.xml b/libraries/ui-strings/src/main/res/values-hu/translations.xml
new file mode 100644
index 0000000000..5c1f2ccf2c
--- /dev/null
+++ b/libraries/ui-strings/src/main/res/values-hu/translations.xml
@@ -0,0 +1,237 @@
+
+
+ "Törlés"
+ "Jelszó elrejtése"
+ "Ugrás az aljára"
+ "Csak megemlítések"
+ "Némítva"
+ "%1$d. oldal"
+ "Szüneteltetés"
+ "PIN-mező"
+ "Lejátszás"
+ "Szavazás"
+ "Szavazás befejezve"
+ "Reagálás a következővel: %1$s"
+ "Reagálás más emodzsikkal"
+ "Olvasta: %1$s és %2$s"
+ "Olvasta: %1$s"
+ "Koppintson az összes megjelenítéséhez"
+ "Reakció eltávolítása: %1$s"
+ "Fájlküldés"
+ "Jelszó megjelenítése"
+ "Hanghívás indítása"
+ "Felhasználói menü"
+ "Hangüzenet felvétele."
+ "Rögzítés leállítása"
+ "Elfogadás"
+ "Hozzáadás az idővonalhoz"
+ "Vissza"
+ "Mégse"
+ "Fénykép kiválasztása"
+ "Törlés"
+ "Bezárás"
+ "Ellenőrzés befejezése"
+ "Megerősítés"
+ "Folytatás"
+ "Másolás"
+ "Hivatkozás másolása"
+ "Üzenetre mutató hivatkozás másolása"
+ "Létrehozás"
+ "Szoba létrehozása"
+ "Elutasítás"
+ "Szavazás törlése"
+ "Letiltás"
+ "Kész"
+ "Szerkesztés"
+ "Szavazás szerkesztése"
+ "Engedélyezés"
+ "Szavazás befejezése"
+ "Adja meg a PIN-kódot"
+ "Elfelejtette a jelszót?"
+ "Tovább"
+ "Meghívás"
+ "Ismerősök meghívása"
+ "Ismerősök meghívása ide: %1$s"
+ "Emberek meghívása ide: %1$s"
+ "Meghívások"
+ "Csatlakozás"
+ "További tudnivalók"
+ "Kilépés"
+ "Szoba elhagyása"
+ "Fiók kezelése"
+ "Eszközök kezelése"
+ "Következő"
+ "Nem"
+ "Most nem"
+ "Rendben"
+ "Beállítások megnyitása"
+ "Megnyitás…"
+ "Gyors válasz"
+ "Idézet"
+ "Reakció"
+ "Eltávolítás"
+ "Válasz"
+ "Válasz az üzenetszálban"
+ "Hiba jelentése"
+ "Tartalom jelentése"
+ "Újra"
+ "Visszafejtés újbóli megpróbálása"
+ "Mentés"
+ "Keresés"
+ "Küldés"
+ "Üzenet küldése"
+ "Megosztás"
+ "Hivatkozás megosztása"
+ "Jelentkezzen be újra"
+ "Kijelentkezés"
+ "Kijelentkezés mindenképp"
+ "Kihagyás"
+ "Indítás"
+ "Csevegés indítása"
+ "Ellenőrzés elindítása"
+ "Koppintson a térkép betöltéséhez"
+ "Fénykép készítése"
+ "Koppintson a lehetőségekért"
+ "Próbálja újra"
+ "Forrás megtekintése"
+ "Igen"
+ "Névjegy"
+ "Elfogadható használatra vonatkozó szabályzat"
+ "Speciális beállítások"
+ "Elemzések"
+ "Megjelenítés"
+ "Hang"
+ "Buborékok"
+ "Csevegés biztonsági mentése"
+ "Szerzői jogok"
+ "Szoba létrehozása…"
+ "Kilépett a szobából"
+ "Sötét"
+ "Visszafejtési hiba"
+ "Fejlesztői beállítások"
+ "Közvetlen csevegés"
+ "(szerkesztve)"
+ "Szerkesztés"
+ "* %1$s %2$s"
+ "Titkosítás engedélyezve"
+ "Adja meg a PIN-kódját"
+ "Hiba"
+ "Mindenki"
+ "Fájl"
+ "A fájl a Letöltések mappába mentve"
+ "Üzenet továbbítása"
+ "GIF"
+ "Kép"
+ "Válaszként erre: %1$s"
+ "APK telepítése"
+ "Ez a Matrix-azonosító nem található, ezért előfordulhat, hogy a meghívó nem érkezik meg."
+ "Szoba elhagyása"
+ "Világos"
+ "Hivatkozás a vágólapra másolva"
+ "Betöltés…"
+ "Üzenet"
+ "Üzenetműveletek"
+ "Üzenet elrendezése"
+ "Üzenet eltávolítva"
+ "Modern"
+ "Némítás"
+ "Nincs találat"
+ "Kapcsolat nélkül"
+ "Jelszó"
+ "Emberek"
+ "Állandó hivatkozás"
+ "Engedély"
+ "Összes szavazat: %1$s"
+ "Az eredmények a szavazás befejezése után jelennek meg"
+ "Adatvédelmi nyilatkozat"
+ "Reakció"
+ "Reakciók"
+ "Helyreállítási kulcs"
+ "Frissítés…"
+ "Válasz %1$s számára"
+ "Hiba jelentése"
+ "Probléma jelentése"
+ "A jelentés elküldve"
+ "Formázott szöveges szerkesztő"
+ "Szoba"
+ "Szoba neve"
+ "például a projekt neve"
+ "Képernyőzár"
+ "Személy keresése"
+ "Keresési találatok"
+ "Biztonság"
+ "Látta:"
+ "Küldés…"
+ "A küldés sikertelen"
+ "Elküldve"
+ "A kiszolgáló nem támogatott"
+ "Kiszolgáló webcíme"
+ "Beállítások"
+ "Megosztott hely"
+ "Kijelentkezés"
+ "Csevegés megkezdése…"
+ "Matrica"
+ "Sikeres"
+ "Javaslatok"
+ "Szinkronizálás"
+ "Rendszer"
+ "Szöveg"
+ "Harmadik felek nyilatkozatai"
+ "Üzenetszál"
+ "Téma"
+ "Miről szól ez a szoba?"
+ "Nem lehet visszafejteni"
+ "Nem sikerült meghívót küldeni egy vagy több felhasználónak."
+ "Nem sikerült meghívót küldeni"
+ "Feloldás"
+ "Némítás feloldása"
+ "Nem támogatott esemény"
+ "Felhasználónév"
+ "Az ellenőrzés megszakítva"
+ "Az ellenőrzés befejeződött"
+ "Videó"
+ "Hangüzenet"
+ "Várakozás…"
+ "Várakozás a visszafejtési kulcsra"
+ "Biztos, hogy befejezi ezt a szavazást?"
+ "Szavazás: %1$s"
+ "Eszköz ellenőrzése"
+ "Megerősítés"
+ "Figyelmeztetés"
+ "Nem sikerült létrehozni az állandó hivatkozást"
+ "Az %1$s nem tudta betölteni a térképet. Próbálja meg újra később."
+ "Nem sikerült betölteni az üzeneteket"
+ "Az %1$s nem tudta elérni a tartózkodási helyét. Próbálja meg újra később."
+ "Nem sikerült feltölteni a hangüzenetét."
+ "Az %1$snek nincs engedélye, hogy hozzáférjen a tartózkodási helyéhez. Ezt a beállításokban engedélyezheti."
+ "Az %1$snek nincs engedélye, hogy hozzáférjen a tartózkodási helyéhez. Engedélyezze alább az elérését."
+ "Az %1$snek nincs engedélye, hogy hozzáférjen a mikrofonjához. Engedélyezze, hogy tudjon hangüzenetet felvenni."
+ "Néhány üzenet nem került elküldésre"
+ "Elnézést, hiba történt"
+ "🔐️ Csatlakozz hozzám itt: %1$s"
+ "Beszélj velem az %1$s használatával: %2$s"
+ "%1$s Android"
+
+ - "%1$d megadott számjegy"
+ - "%1$d megadott számjegy"
+
+
+ - "Olvasta: %1$s és még %2$d felhasználó"
+ - "Olvasta: %1$s és még %2$d felhasználó"
+
+ "Az eszköz rázása a hibajelentéshez"
+ "Nem sikerült kiválasztani a médiát, próbálja újra."
+ "Nem sikerült feldolgozni a feltöltendő médiát, próbálja újra."
+ "Nem sikerült a média feltöltése, próbálja újra."
+ "Hely megosztása"
+ "Saját hely megosztása"
+ "Megnyitás az Apple Mapsben"
+ "Megnyitás a Google Mapsben"
+ "Megnyitás az OpenStreetMapen"
+ "E hely megosztása"
+ "Hely"
+ "Verzió: %1$s (%2$s)"
+ "hu"
+ "Hiba"
+ "Sikeres"
+
diff --git a/libraries/ui-strings/src/main/res/values-in/translations.xml b/libraries/ui-strings/src/main/res/values-in/translations.xml
new file mode 100644
index 0000000000..f7f05f71f2
--- /dev/null
+++ b/libraries/ui-strings/src/main/res/values-in/translations.xml
@@ -0,0 +1,242 @@
+
+
+ "Hapus"
+ "Sembunyikan kata sandi"
+ "Lompat ke bawah"
+ "Hanya sebutan"
+ "Dibisukan"
+ "Halaman %1$d"
+ "Jeda"
+ "Kolom PIN"
+ "Putar"
+ "Pemungutan suara"
+ "Pemungutan suara berakhir"
+ "Bereaksi dengan %1$s"
+ "Reaksi dengan emoji lain"
+ "Dibaca oleh %1$s dan %2$s"
+ "Dibaca oleh %1$s"
+ "Ketuk untuk melihat semua"
+ "Hapus reaksi dengan %1$s"
+ "Kirim berkas"
+ "Tampilkan kata sandi"
+ "Mulai panggilan"
+ "Menu pengguna"
+ "Rekam pesan suara."
+ "Berhenti merekam"
+ "Terima"
+ "Tambahkan ke lini masa"
+ "Kembali"
+ "Batal"
+ "Pilih foto"
+ "Hapus"
+ "Tutup"
+ "Selesaikan verifikasi"
+ "Konfirmasi"
+ "Lanjutkan"
+ "Salin"
+ "Salin tautan"
+ "Salin tautan ke pesan"
+ "Buat"
+ "Buat ruangan"
+ "Tolak"
+ "Hapus pemungutan suara"
+ "Nonaktifkan"
+ "Selesai"
+ "Sunting"
+ "Sunting pemungutan suara"
+ "Aktifkan"
+ "Akhiri pemungutan suara"
+ "Masukkan PIN"
+ "Lupa kata sandi?"
+ "Teruskan"
+ "Undang"
+ "Undang teman"
+ "Undang teman ke %1$s"
+ "Undang orang-orang ke %1$s"
+ "Undangan"
+ "Gabung"
+ "Pelajari lebih lanjut"
+ "Tinggalkan"
+ "Tinggalkan ruangan"
+ "Kelola akun"
+ "Kelola perangkat"
+ "Berikutnya"
+ "Tidak"
+ "Jangan sekarang"
+ "Oke"
+ "Pengaturan"
+ "Buka dengan"
+ "Balas cepat"
+ "Kutip"
+ "Bereaksi"
+ "Hapus"
+ "Balas"
+ "Balas dalam utas"
+ "Laporkan kutu"
+ "Laporkan Konten"
+ "Coba lagi"
+ "Coba dekripsi ulang"
+ "Simpan"
+ "Cari"
+ "Kirim"
+ "Kirim pesan"
+ "Bagikan"
+ "Bagikan tautan"
+ "Masuk lagi"
+ "Keluar dari akun"
+ "Keluar saja"
+ "Lewati"
+ "Mulai"
+ "Mulai obrolan"
+ "Mulai verifikasi"
+ "Ketuk untuk memuat peta"
+ "Ambil foto"
+ "Ketuk untuk opsi"
+ "Coba lagi"
+ "Tampilkan sumber"
+ "Ya"
+ "Muat lainnya"
+ "Tentang"
+ "Kebijakan penggunaan wajar"
+ "Pengaturan tingkat lanjut"
+ "Analitik"
+ "Penampilan"
+ "Audio"
+ "Gelembung"
+ "Pencadangan percakapan"
+ "Hak cipta"
+ "Membuat ruangan…"
+ "Keluar dari ruangan"
+ "Gelap"
+ "Kesalahan dekripsi"
+ "Opsi pengembang"
+ "Obrolan langsung"
+ "(disunting)"
+ "Penyuntingan"
+ "* %1$s %2$s"
+ "Enkripsi diaktifkan"
+ "Masukkan PIN Anda"
+ "Eror"
+ "Semua orang"
+ "Berkas"
+ "Berkas disimpan ke Unduhan"
+ "Teruskan pesan"
+ "GIF"
+ "Gambar"
+ "Membalas kepada %1$s"
+ "Pasang APK"
+ "ID Matrix ini tidak dapat ditemukan, sehingga undangan mungkin tidak diterima."
+ "Meninggalkan ruangan"
+ "Terang"
+ "Tautan disalin ke papan klip"
+ "Memuat…"
+ "Pesan"
+ "Tindakan pesan"
+ "Tata letak pesan"
+ "Pesan dihapus"
+ "Modern"
+ "Bisukan"
+ "Tidak ada hasil"
+ "Luring"
+ "Kata sandi"
+ "Orang"
+ "Tautan Permanen"
+ "Perizinan"
+ "Total suara: %1$s"
+ "Hasil akan terlihat setelah pemungutan suara berakhir"
+ "Kebijakan privasi"
+ "Reaksi"
+ "Reaksi"
+ "Kunci pemulihan"
+ "Menyegarkan…"
+ "Membalas %1$s"
+ "Laporkan kutu"
+ "Laporkan masalah"
+ "Laporan terkirim"
+ "Penyunting teks kaya"
+ "Ruangan"
+ "Nama ruangan"
+ "misalnya, nama proyek Anda"
+ "Layar kunci"
+ "Cari seseorang"
+ "Hasil pencarian"
+ "Keamanan"
+ "Dilihat oleh"
+ "Mengirim…"
+ "Pengiriman gagal"
+ "Terkirim"
+ "Server tidak didukung"
+ "URL Server"
+ "Pengaturan"
+ "Membagikan lokasi"
+ "Mengeluarkan dari akun"
+ "Memulai obrolan…"
+ "Stiker"
+ "Berhasil"
+ "Saran"
+ "Menyinkronkan"
+ "Sistem"
+ "Teks"
+ "Pemberitahuan pihak ketiga"
+ "Utas"
+ "Topik"
+ "Tentang apa ruangan ini?"
+ "Tidak dapat mendekripsi"
+ "Undangan tidak dapat dikirim ke satu atau beberapa pengguna."
+ "Tidak dapat mengirim undangan"
+ "Buka kunci"
+ "Bunyikan"
+ "Peristiwa tidak didukung"
+ "Nama pengguna"
+ "Verifikasi dibatalkan"
+ "Verifikasi selesai"
+ "Video"
+ "Pesan suara"
+ "Menunggu…"
+ "Menunggu pesan ini"
+ "Apakah Anda yakin ingin mengakhiri pemungutan suara ini?"
+ "Pemungutan suara: %1$s"
+ "Verifikasi perangkat"
+ "Konfirmasi"
+ "Peringatan"
+ "Gagal membuat tautan permanen"
+ "%1$s tidak dapat memuat peta. Silakan coba lagi nanti."
+ "Gagal memuat pesan"
+ "%1$s tidak dapat mengakses lokasi Anda. Silakan coba lagi nanti."
+ "Gagal mengunggah pesan suara Anda."
+ "%1$s tidak memiliki izin untuk mengakses lokasi Anda. Anda dapat mengaktifkan akses di Pengaturan."
+ "%1$s tidak memiliki izin untuk mengakses lokasi Anda. Aktifkan akses di bawah ini."
+ "%1$s tidak memiliki izin untuk mengakses mikrofon. Aktifkan akses untuk merekam pesan suara."
+ "Beberapa pesan belum terkirim"
+ "Maaf, terjadi kesalahan"
+ "🔐️ Bergabunglah dengan saya di %1$s"
+ "Hai, bicaralah dengan saya di %1$s: %2$s"
+ "%1$s Android"
+
+ - "%1$d digit dimasukkan"
+
+
+ - "Dibaca oleh %1$s dan %2$d lainnya"
+
+
+ - "%1$d anggota"
+
+
+ - "%d suara"
+
+ "Rageshake untuk melaporkan kutu"
+ "Gagal memilih media, silakan coba lagi."
+ "Gagal memproses media untuk diunggah, silakan coba lagi."
+ "Gagal mengunggah media, silakan coba lagi."
+ "Bagikan lokasi"
+ "Bagikan lokasi saya"
+ "Buka di Apple Maps"
+ "Buka di Google Maps"
+ "Buka di OpenStreetMap"
+ "Bagikan lokasi ini"
+ "Lokasi"
+ "Versi: %1$s (%2$s)"
+ "id"
+ "Eror"
+ "Berhasil"
+
diff --git a/libraries/ui-strings/src/main/res/values-ru/translations.xml b/libraries/ui-strings/src/main/res/values-ru/translations.xml
index 6ad74a9086..b6576d988c 100644
--- a/libraries/ui-strings/src/main/res/values-ru/translations.xml
+++ b/libraries/ui-strings/src/main/res/values-ru/translations.xml
@@ -95,6 +95,7 @@
"Повторить попытку"
"Показать источник"
"Да"
+ "Загрузить еще"
"О приложении"
"Политика допустимого использования"
"Дополнительные параметры"
@@ -109,6 +110,7 @@
"Темная"
"Ошибка расшифровки"
"Для разработчика"
+ "Прямой чат"
"(изменено)"
"Редактирование"
"%1$s%2$s"
@@ -130,7 +132,7 @@
"Загрузка…"
"Сообщение"
"Действия с сообщением"
- "Оформление сообщений"
+ "Оформление сообщения"
"Сообщение удалено"
"Современный"
"Без звука"
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 0dff18fd2f..9b7db8c032 100644
--- a/libraries/ui-strings/src/main/res/values-sk/translations.xml
+++ b/libraries/ui-strings/src/main/res/values-sk/translations.xml
@@ -95,6 +95,7 @@
"Skúste to znova"
"Zobraziť zdroj"
"Áno"
+ "Načítať viac"
"O aplikácii"
"Zásady prijateľného používania"
"Pokročilé nastavenia"
@@ -109,6 +110,7 @@
"Tmavý"
"Chyba dešifrovania"
"Možnosti pre vývojárov"
+ "Priama konverzácia"
"(upravené)"
"Upravuje sa"
"* %1$s %2$s"
diff --git a/libraries/usersearch/impl/src/test/kotlin/io/element/android/libraries/usersearch/impl/MatrixUserListDataSourceTest.kt b/libraries/usersearch/impl/src/test/kotlin/io/element/android/libraries/usersearch/impl/MatrixUserListDataSourceTest.kt
index 76f29aebe5..6ec9f28658 100644
--- a/libraries/usersearch/impl/src/test/kotlin/io/element/android/libraries/usersearch/impl/MatrixUserListDataSourceTest.kt
+++ b/libraries/usersearch/impl/src/test/kotlin/io/element/android/libraries/usersearch/impl/MatrixUserListDataSourceTest.kt
@@ -16,7 +16,7 @@
package io.element.android.libraries.usersearch.impl
-import com.google.common.truth.Truth
+import com.google.common.truth.Truth.assertThat
import io.element.android.libraries.matrix.api.core.UserId
import io.element.android.libraries.matrix.api.user.MatrixSearchUserResults
import io.element.android.libraries.matrix.api.user.MatrixUser
@@ -49,7 +49,7 @@ internal class MatrixUserListDataSourceTest {
val dataSource = MatrixUserListDataSource(matrixClient)
val results = dataSource.search("test", 2)
- Truth.assertThat(results).containsExactly(
+ assertThat(results).containsExactly(
aMatrixUserProfile(),
aMatrixUserProfile(userId = A_USER_ID_2)
)
@@ -65,7 +65,7 @@ internal class MatrixUserListDataSourceTest {
val dataSource = MatrixUserListDataSource(matrixClient)
val results = dataSource.search("test", 2)
- Truth.assertThat(results).isEmpty()
+ assertThat(results).isEmpty()
}
@Test
@@ -78,7 +78,7 @@ internal class MatrixUserListDataSourceTest {
val dataSource = MatrixUserListDataSource(matrixClient)
val result = dataSource.getProfile(A_USER_ID)
- Truth.assertThat(result).isEqualTo(aMatrixUserProfile())
+ assertThat(result).isEqualTo(aMatrixUserProfile())
}
@Test
@@ -91,7 +91,7 @@ internal class MatrixUserListDataSourceTest {
val dataSource = MatrixUserListDataSource(matrixClient)
val result = dataSource.getProfile(A_USER_ID)
- Truth.assertThat(result).isNull()
+ assertThat(result).isNull()
}
private fun aMatrixUserProfile(
diff --git a/libraries/voicerecorder/impl/src/test/kotlin/io/element/android/libraries/voicerecorder/impl/audio/DBovAudioLevelCalculatorTest.kt b/libraries/voicerecorder/impl/src/test/kotlin/io/element/android/libraries/voicerecorder/impl/audio/DBovAudioLevelCalculatorTest.kt
index cb5404d6f2..9aa3432ef6 100644
--- a/libraries/voicerecorder/impl/src/test/kotlin/io/element/android/libraries/voicerecorder/impl/audio/DBovAudioLevelCalculatorTest.kt
+++ b/libraries/voicerecorder/impl/src/test/kotlin/io/element/android/libraries/voicerecorder/impl/audio/DBovAudioLevelCalculatorTest.kt
@@ -16,7 +16,7 @@
package io.element.android.libraries.voicerecorder.impl.audio
-import com.google.common.truth.Truth
+import com.google.common.truth.Truth.assertThat
import org.junit.Test
class DBovAudioLevelCalculatorTest {
@@ -26,7 +26,7 @@ class DBovAudioLevelCalculatorTest {
val calculator = DBovAudioLevelCalculator()
val buffer = ShortArray(100) { Short.MAX_VALUE }
val level = calculator.calculateAudioLevel(buffer)
- Truth.assertThat(level).isEqualTo(1.0f)
+ assertThat(level).isEqualTo(1.0f)
}
@Test
@@ -34,7 +34,7 @@ class DBovAudioLevelCalculatorTest {
val calculator = DBovAudioLevelCalculator()
val buffer = shortArrayOf(100, -200, 300, -400, 500, -600, 700, -800, 900, -1000)
val level = calculator.calculateAudioLevel(buffer)
- Truth.assertThat(level).apply {
+ assertThat(level).apply {
isGreaterThan(0f)
isLessThan(1f)
}
@@ -45,6 +45,6 @@ class DBovAudioLevelCalculatorTest {
val calculator = DBovAudioLevelCalculator()
val buffer = ShortArray(100) { 0 }
val level = calculator.calculateAudioLevel(buffer)
- Truth.assertThat(level).isEqualTo(0.0f)
+ assertThat(level).isEqualTo(0.0f)
}
}
diff --git a/libraries/voicerecorder/impl/src/test/kotlin/io/element/android/libraries/voicerecorder/impl/audio/ResampleTest.kt b/libraries/voicerecorder/impl/src/test/kotlin/io/element/android/libraries/voicerecorder/impl/audio/ResampleTest.kt
index 1edec86018..8413e4b244 100644
--- a/libraries/voicerecorder/impl/src/test/kotlin/io/element/android/libraries/voicerecorder/impl/audio/ResampleTest.kt
+++ b/libraries/voicerecorder/impl/src/test/kotlin/io/element/android/libraries/voicerecorder/impl/audio/ResampleTest.kt
@@ -16,26 +16,26 @@
package io.element.android.libraries.voicerecorder.impl.audio
-import com.google.common.truth.Truth
+import com.google.common.truth.Truth.assertThat
import org.junit.Test
class ResampleTest {
@Test
fun `resample works`() {
listOf(0.0f).resample(10).let {
- Truth.assertThat(it).isEqualTo(listOf(0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f))
+ assertThat(it).isEqualTo(listOf(0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f))
}
listOf(1.0f).resample(10).let {
- Truth.assertThat(it).isEqualTo(listOf(1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f))
+ assertThat(it).isEqualTo(listOf(1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f))
}
listOf(0.0f, 1.0f).resample(10).let {
- Truth.assertThat(it).isEqualTo(listOf(0.0f, 0.2f, 0.4f, 0.6f, 0.8f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f))
+ assertThat(it).isEqualTo(listOf(0.0f, 0.2f, 0.4f, 0.6f, 0.8f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f))
}
listOf(0.0f, 0.5f, 1.0f).resample(10).let {
- Truth.assertThat(it).isEqualTo(listOf(0.0f, 0.15f, 0.3f, 0.45000002f, 0.6f, 0.75f, 0.90000004f, 1.0f, 1.0f, 1.0f))
+ assertThat(it).isEqualTo(listOf(0.0f, 0.15f, 0.3f, 0.45000002f, 0.6f, 0.75f, 0.90000004f, 1.0f, 1.0f, 1.0f))
}
List(100) { it.toFloat() }.resample(10).let {
- Truth.assertThat(it).isEqualTo(listOf(0.0f, 10.0f, 20.0f, 30.0f, 40.0f, 50.0f, 60.0f, 70.0f, 80.0f, 90.0f))
+ assertThat(it).isEqualTo(listOf(0.0f, 10.0f, 20.0f, 30.0f, 40.0f, 50.0f, 60.0f, 70.0f, 80.0f, 90.0f))
}
}
}
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 1d74718aa9..7706cdbb5d 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
@@ -79,7 +79,6 @@ class RoomListScreen(
lastMessageTimestampFormatter = DefaultLastMessageTimestampFormatter(dateTimeProvider, dateFormatters),
roomLastMessageFormatter = DefaultRoomLastMessageFormatter(
sp = stringProvider,
- matrixClient = matrixClient,
roomMembershipContentFormatter = RoomMembershipContentFormatter(matrixClient, stringProvider),
profileChangeContentFormatter = ProfileChangeContentFormatter(stringProvider),
stateContentFormatter = StateContentFormatter(stringProvider),
diff --git a/services/analyticsproviders/posthog/src/main/kotlin/io/element/android/services/analyticsproviders/posthog/PostHogFactory.kt b/services/analyticsproviders/posthog/src/main/kotlin/io/element/android/services/analyticsproviders/posthog/PostHogFactory.kt
index 40c72142c6..6c02b8b788 100644
--- a/services/analyticsproviders/posthog/src/main/kotlin/io/element/android/services/analyticsproviders/posthog/PostHogFactory.kt
+++ b/services/analyticsproviders/posthog/src/main/kotlin/io/element/android/services/analyticsproviders/posthog/PostHogFactory.kt
@@ -17,7 +17,9 @@
package io.element.android.services.analyticsproviders.posthog
import android.content.Context
-import com.posthog.android.PostHog
+import com.posthog.PostHogInterface
+import com.posthog.android.PostHogAndroid
+import com.posthog.android.PostHogAndroidConfig
import io.element.android.libraries.core.meta.BuildMeta
import io.element.android.libraries.di.ApplicationContext
import javax.inject.Inject
@@ -27,31 +29,20 @@ class PostHogFactory @Inject constructor(
private val buildMeta: BuildMeta,
private val posthogEndpointConfigProvider: PosthogEndpointConfigProvider,
) {
-
- fun createPosthog(): PostHog {
+ fun createPosthog(): PostHogInterface {
val endpoint = posthogEndpointConfigProvider.provide()
- return PostHog.Builder(context, endpoint.apiKey, endpoint.host)
- // Record certain application events automatically! (off/false by default)
- // .captureApplicationLifecycleEvents()
- // Record screen views automatically! (off/false by default)
- // .recordScreenViews()
- // Capture deep links as part of the screen call. (off by default)
- // .captureDeepLinks()
- // Maximum number of events to keep in queue before flushing (default 20)
- // .flushQueueSize(20)
- // Max delay before flushing the queue (30 seconds)
- // .flushInterval(30, TimeUnit.SECONDS)
- // Enable or disable collection of ANDROID_ID (true)
- .collectDeviceId(false)
- .logLevel(getLogLevel())
- .build()
- }
-
- private fun getLogLevel(): PostHog.LogLevel {
- return if (buildMeta.isDebuggable) {
- PostHog.LogLevel.DEBUG
- } else {
- PostHog.LogLevel.INFO
- }
+ return PostHogAndroid.with(
+ context,
+ PostHogAndroidConfig(
+ apiKey = endpoint.apiKey,
+ host = endpoint.host,
+ captureApplicationLifecycleEvents = false,
+ captureDeepLinks = false,
+ captureScreenViews = false,
+ ).also {
+ it.debug = buildMeta.isDebuggable
+ it.sendFeatureFlagEvent = false
+ }
+ )
}
}
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 e371c6fef4..16cac5722d 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,8 +16,7 @@
package io.element.android.services.analyticsproviders.posthog
-import com.posthog.android.PostHog
-import com.posthog.android.Properties
+import com.posthog.PostHogInterface
import com.squareup.anvil.annotations.ContributesMultibinding
import im.vector.app.features.analytics.itf.VectorAnalyticsEvent
import im.vector.app.features.analytics.itf.VectorAnalyticsScreen
@@ -37,30 +36,31 @@ class PosthogAnalyticsProvider @Inject constructor(
) : AnalyticsProvider {
override val name = "Posthog"
- private var posthog: PostHog? = null
+ private var posthog: PostHogInterface? = null
private var analyticsId: String? = null
override fun init() {
posthog = createPosthog()
- posthog?.optOut(false)
+ posthog?.optIn()
+ // Timber.e("PostHog distinctId: ${posthog?.distinctId()}")
identifyPostHog()
}
override fun stop() {
// When opting out, ensure that the queue is flushed first, or it will be flushed later (after user has revoked consent)
posthog?.flush()
- posthog?.optOut(true)
- posthog?.shutdown()
+ posthog?.optOut()
+ posthog?.close()
posthog = null
analyticsId = null
}
override fun capture(event: VectorAnalyticsEvent) {
- posthog?.capture(event.getName(), event.getProperties()?.toPostHogProperties())
+ posthog?.capture(event.getName(), properties = event.getProperties()?.keepOnlyNonNullValues())
}
override fun screen(screen: VectorAnalyticsScreen) {
- posthog?.screen(screen.getName(), screen.getProperties()?.toPostHogProperties())
+ posthog?.screen(screen.getName(), properties = screen.getProperties())
}
override fun updateUserProperties(userProperties: UserProperties) {
@@ -74,7 +74,7 @@ class PosthogAnalyticsProvider @Inject constructor(
// Not implemented
}
- private fun createPosthog(): PostHog = postHogFactory.createPosthog()
+ private fun createPosthog(): PostHogInterface = postHogFactory.createPosthog()
private fun identifyPostHog() {
val id = analyticsId ?: return
@@ -86,24 +86,15 @@ class PosthogAnalyticsProvider @Inject constructor(
// posthog?.identify(id, lateInitUserPropertiesFactory.createUserProperties()?.getProperties()?.toPostHogUserProperties(), IGNORED_OPTIONS)
}
}
-
- private fun Map?.toPostHogProperties(): Properties? {
- if (this == null) return null
-
- return Properties().apply {
- putAll(this@toPostHogProperties)
- }
- }
-
- /**
- * 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 })
- }
- }
- */
+}
+
+private fun Map.keepOnlyNonNullValues(): Map {
+ val result = mutableMapOf()
+ for (entry in this) {
+ val value = entry.value
+ if (value != null) {
+ result[entry.key] = value
+ }
+ }
+ return result
}
diff --git a/settings.gradle.kts b/settings.gradle.kts
index 0fe8ca31ee..cd3689abe3 100644
--- a/settings.gradle.kts
+++ b/settings.gradle.kts
@@ -82,9 +82,9 @@ includeProjects(File(rootDir, "services"), ":services")
// Uncomment to include the compound-android module as a local dependency so you can work on it locally.
// You will also need to clone it in the specified folder.
-//includeBuild("checkouts/compound-android") {
+// includeBuild("checkouts/compound-android") {
// dependencySubstitution {
// // substitute remote dependency with local module
// substitute(module("io.element.android:compound-android")).using(project(":compound"))
// }
-//}
+// }
diff --git a/tests/konsist/src/test/kotlin/io/element/android/tests/konsist/KonsistTestTest.kt b/tests/konsist/src/test/kotlin/io/element/android/tests/konsist/KonsistTestTest.kt
index 5f7acf8d39..e85d95650d 100644
--- a/tests/konsist/src/test/kotlin/io/element/android/tests/konsist/KonsistTestTest.kt
+++ b/tests/konsist/src/test/kotlin/io/element/android/tests/konsist/KonsistTestTest.kt
@@ -20,6 +20,8 @@ import com.lemonappdev.konsist.api.Konsist
import com.lemonappdev.konsist.api.ext.list.modifierprovider.withoutOverrideModifier
import com.lemonappdev.konsist.api.ext.list.withFunction
import com.lemonappdev.konsist.api.ext.list.withReturnType
+import com.lemonappdev.konsist.api.ext.list.withoutName
+import com.lemonappdev.konsist.api.verify.assertFalse
import com.lemonappdev.konsist.api.verify.assertTrue
import org.junit.Test
@@ -46,4 +48,66 @@ class KonsistTestTest {
functionDeclaration.name == "create${functionDeclaration.returnType?.name}"
}
}
+
+ @Test
+ fun `assertion methods must be imported`() {
+ Konsist
+ .scopeFromTest()
+ .functions()
+ // Exclude self
+ .withoutName("assertion methods must be imported")
+ .assertFalse(
+ additionalMessage = "Import methods from Truth, instead of using for instance Truth.assertThat(...)"
+ ) { functionDeclaration ->
+ functionDeclaration.text.contains("Truth.")
+ }
+ }
+
+ @Test
+ fun `use isFalse() instead of isEqualTo(false)`() {
+ Konsist
+ .scopeFromTest()
+ .functions()
+ // Exclude self
+ .withoutName("use isFalse() instead of isEqualTo(false)")
+ .assertFalse { functionDeclaration ->
+ functionDeclaration.text.contains("isEqualTo(false)")
+ }
+ }
+
+ @Test
+ fun `use isTrue() instead of isEqualTo(true)`() {
+ Konsist
+ .scopeFromTest()
+ .functions()
+ // Exclude self
+ .withoutName("use isTrue() instead of isEqualTo(true)")
+ .assertFalse { functionDeclaration ->
+ functionDeclaration.text.contains("isEqualTo(true)")
+ }
+ }
+
+ @Test
+ fun `use isEmpty() instead of isEqualTo(empty)`() {
+ Konsist
+ .scopeFromTest()
+ .functions()
+ // Exclude self
+ .withoutName("use isEmpty() instead of isEqualTo(empty)")
+ .assertFalse { functionDeclaration ->
+ functionDeclaration.text.contains("isEqualTo(empty")
+ }
+ }
+
+ @Test
+ fun `use isNull() instead of isEqualTo(null)`() {
+ Konsist
+ .scopeFromTest()
+ .functions()
+ // Exclude self
+ .withoutName("use isNull() instead of isEqualTo(null)")
+ .assertFalse { functionDeclaration ->
+ functionDeclaration.text.contains("isEqualTo(null)")
+ }
+ }
}
diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.customreaction_EmojiItem_null_EmojiItem-Day-29_29_null,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.customreaction_EmojiItem_null_EmojiItem-Day-30_30_null,NEXUS_5,1.0,en].png
similarity index 100%
rename from tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.customreaction_EmojiItem_null_EmojiItem-Day-29_29_null,NEXUS_5,1.0,en].png
rename to tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.customreaction_EmojiItem_null_EmojiItem-Day-30_30_null,NEXUS_5,1.0,en].png
diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.customreaction_EmojiItem_null_EmojiItem-Night-29_30_null,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.customreaction_EmojiItem_null_EmojiItem-Night-30_31_null,NEXUS_5,1.0,en].png
similarity index 100%
rename from tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.customreaction_EmojiItem_null_EmojiItem-Night-29_30_null,NEXUS_5,1.0,en].png
rename to tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.customreaction_EmojiItem_null_EmojiItem-Night-30_31_null,NEXUS_5,1.0,en].png
diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.customreaction_EmojiPicker_null_EmojiPicker-Day-30_30_null,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.customreaction_EmojiPicker_null_EmojiPicker-Day-31_31_null,NEXUS_5,1.0,en].png
similarity index 100%
rename from tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.customreaction_EmojiPicker_null_EmojiPicker-Day-30_30_null,NEXUS_5,1.0,en].png
rename to tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.customreaction_EmojiPicker_null_EmojiPicker-Day-31_31_null,NEXUS_5,1.0,en].png
diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.customreaction_EmojiPicker_null_EmojiPicker-Night-30_31_null,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.customreaction_EmojiPicker_null_EmojiPicker-Night-31_32_null,NEXUS_5,1.0,en].png
similarity index 100%
rename from tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.customreaction_EmojiPicker_null_EmojiPicker-Night-30_31_null,NEXUS_5,1.0,en].png
rename to tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.customreaction_EmojiPicker_null_EmojiPicker-Night-31_32_null,NEXUS_5,1.0,en].png
diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.event_ProgressButton_null_ProgressButton-Day-46_46_null,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.event_ProgressButton_null_ProgressButton-Day-47_47_null,NEXUS_5,1.0,en].png
similarity index 100%
rename from tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.event_ProgressButton_null_ProgressButton-Day-46_46_null,NEXUS_5,1.0,en].png
rename to tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.event_ProgressButton_null_ProgressButton-Day-47_47_null,NEXUS_5,1.0,en].png
diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.event_ProgressButton_null_ProgressButton-Night-46_47_null,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.event_ProgressButton_null_ProgressButton-Night-47_48_null,NEXUS_5,1.0,en].png
similarity index 100%
rename from tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.event_ProgressButton_null_ProgressButton-Night-46_47_null,NEXUS_5,1.0,en].png
rename to tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.event_ProgressButton_null_ProgressButton-Night-47_48_null,NEXUS_5,1.0,en].png
diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.event_TimelineItemAudioView_null_TimelineItemAudioView-Day-31_31_null_0,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.event_TimelineItemAudioView_null_TimelineItemAudioView-Day-32_32_null_0,NEXUS_5,1.0,en].png
similarity index 100%
rename from tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.event_TimelineItemAudioView_null_TimelineItemAudioView-Day-31_31_null_0,NEXUS_5,1.0,en].png
rename to tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.event_TimelineItemAudioView_null_TimelineItemAudioView-Day-32_32_null_0,NEXUS_5,1.0,en].png
diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.event_TimelineItemAudioView_null_TimelineItemAudioView-Day-31_31_null_1,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.event_TimelineItemAudioView_null_TimelineItemAudioView-Day-32_32_null_1,NEXUS_5,1.0,en].png
similarity index 100%
rename from tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.event_TimelineItemAudioView_null_TimelineItemAudioView-Day-31_31_null_1,NEXUS_5,1.0,en].png
rename to tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.event_TimelineItemAudioView_null_TimelineItemAudioView-Day-32_32_null_1,NEXUS_5,1.0,en].png
diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.event_TimelineItemAudioView_null_TimelineItemAudioView-Day-31_31_null_2,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.event_TimelineItemAudioView_null_TimelineItemAudioView-Day-32_32_null_2,NEXUS_5,1.0,en].png
similarity index 100%
rename from tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.event_TimelineItemAudioView_null_TimelineItemAudioView-Day-31_31_null_2,NEXUS_5,1.0,en].png
rename to tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.event_TimelineItemAudioView_null_TimelineItemAudioView-Day-32_32_null_2,NEXUS_5,1.0,en].png
diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.event_TimelineItemAudioView_null_TimelineItemAudioView-Night-31_32_null_0,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.event_TimelineItemAudioView_null_TimelineItemAudioView-Night-32_33_null_0,NEXUS_5,1.0,en].png
similarity index 100%
rename from tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.event_TimelineItemAudioView_null_TimelineItemAudioView-Night-31_32_null_0,NEXUS_5,1.0,en].png
rename to tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.event_TimelineItemAudioView_null_TimelineItemAudioView-Night-32_33_null_0,NEXUS_5,1.0,en].png
diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.event_TimelineItemAudioView_null_TimelineItemAudioView-Night-31_32_null_1,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.event_TimelineItemAudioView_null_TimelineItemAudioView-Night-32_33_null_1,NEXUS_5,1.0,en].png
similarity index 100%
rename from tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.event_TimelineItemAudioView_null_TimelineItemAudioView-Night-31_32_null_1,NEXUS_5,1.0,en].png
rename to tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.event_TimelineItemAudioView_null_TimelineItemAudioView-Night-32_33_null_1,NEXUS_5,1.0,en].png
diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.event_TimelineItemAudioView_null_TimelineItemAudioView-Night-31_32_null_2,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.event_TimelineItemAudioView_null_TimelineItemAudioView-Night-32_33_null_2,NEXUS_5,1.0,en].png
similarity index 100%
rename from tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.event_TimelineItemAudioView_null_TimelineItemAudioView-Night-31_32_null_2,NEXUS_5,1.0,en].png
rename to tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.event_TimelineItemAudioView_null_TimelineItemAudioView-Night-32_33_null_2,NEXUS_5,1.0,en].png
diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.event_TimelineItemEncryptedView_null_TimelineItemEncryptedView-Day-32_32_null,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.event_TimelineItemEncryptedView_null_TimelineItemEncryptedView-Day-33_33_null,NEXUS_5,1.0,en].png
similarity index 100%
rename from tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.event_TimelineItemEncryptedView_null_TimelineItemEncryptedView-Day-32_32_null,NEXUS_5,1.0,en].png
rename to tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.event_TimelineItemEncryptedView_null_TimelineItemEncryptedView-Day-33_33_null,NEXUS_5,1.0,en].png
diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.event_TimelineItemEncryptedView_null_TimelineItemEncryptedView-Night-32_33_null,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.event_TimelineItemEncryptedView_null_TimelineItemEncryptedView-Night-33_34_null,NEXUS_5,1.0,en].png
similarity index 100%
rename from tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.event_TimelineItemEncryptedView_null_TimelineItemEncryptedView-Night-32_33_null,NEXUS_5,1.0,en].png
rename to tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.event_TimelineItemEncryptedView_null_TimelineItemEncryptedView-Night-33_34_null,NEXUS_5,1.0,en].png
diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.event_TimelineItemFileView_null_TimelineItemFileView-Day-33_33_null_0,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.event_TimelineItemFileView_null_TimelineItemFileView-Day-34_34_null_0,NEXUS_5,1.0,en].png
similarity index 100%
rename from tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.event_TimelineItemFileView_null_TimelineItemFileView-Day-33_33_null_0,NEXUS_5,1.0,en].png
rename to tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.event_TimelineItemFileView_null_TimelineItemFileView-Day-34_34_null_0,NEXUS_5,1.0,en].png
diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.event_TimelineItemFileView_null_TimelineItemFileView-Day-33_33_null_1,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.event_TimelineItemFileView_null_TimelineItemFileView-Day-34_34_null_1,NEXUS_5,1.0,en].png
similarity index 100%
rename from tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.event_TimelineItemFileView_null_TimelineItemFileView-Day-33_33_null_1,NEXUS_5,1.0,en].png
rename to tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.event_TimelineItemFileView_null_TimelineItemFileView-Day-34_34_null_1,NEXUS_5,1.0,en].png
diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.event_TimelineItemFileView_null_TimelineItemFileView-Day-33_33_null_2,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.event_TimelineItemFileView_null_TimelineItemFileView-Day-34_34_null_2,NEXUS_5,1.0,en].png
similarity index 100%
rename from tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.event_TimelineItemFileView_null_TimelineItemFileView-Day-33_33_null_2,NEXUS_5,1.0,en].png
rename to tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.event_TimelineItemFileView_null_TimelineItemFileView-Day-34_34_null_2,NEXUS_5,1.0,en].png
diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.event_TimelineItemFileView_null_TimelineItemFileView-Night-33_34_null_0,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.event_TimelineItemFileView_null_TimelineItemFileView-Night-34_35_null_0,NEXUS_5,1.0,en].png
similarity index 100%
rename from tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.event_TimelineItemFileView_null_TimelineItemFileView-Night-33_34_null_0,NEXUS_5,1.0,en].png
rename to tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.event_TimelineItemFileView_null_TimelineItemFileView-Night-34_35_null_0,NEXUS_5,1.0,en].png
diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.event_TimelineItemFileView_null_TimelineItemFileView-Night-33_34_null_1,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.event_TimelineItemFileView_null_TimelineItemFileView-Night-34_35_null_1,NEXUS_5,1.0,en].png
similarity index 100%
rename from tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.event_TimelineItemFileView_null_TimelineItemFileView-Night-33_34_null_1,NEXUS_5,1.0,en].png
rename to tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.event_TimelineItemFileView_null_TimelineItemFileView-Night-34_35_null_1,NEXUS_5,1.0,en].png
diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.event_TimelineItemFileView_null_TimelineItemFileView-Night-33_34_null_2,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.event_TimelineItemFileView_null_TimelineItemFileView-Night-34_35_null_2,NEXUS_5,1.0,en].png
similarity index 100%
rename from tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.event_TimelineItemFileView_null_TimelineItemFileView-Night-33_34_null_2,NEXUS_5,1.0,en].png
rename to tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.event_TimelineItemFileView_null_TimelineItemFileView-Night-34_35_null_2,NEXUS_5,1.0,en].png
diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.event_TimelineItemImageView_null_TimelineItemImageView-Day-34_34_null_0,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.event_TimelineItemImageView_null_TimelineItemImageView-Day-35_35_null_0,NEXUS_5,1.0,en].png
similarity index 100%
rename from tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.event_TimelineItemImageView_null_TimelineItemImageView-Day-34_34_null_0,NEXUS_5,1.0,en].png
rename to tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.event_TimelineItemImageView_null_TimelineItemImageView-Day-35_35_null_0,NEXUS_5,1.0,en].png
diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.event_TimelineItemImageView_null_TimelineItemImageView-Day-34_34_null_1,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.event_TimelineItemImageView_null_TimelineItemImageView-Day-35_35_null_1,NEXUS_5,1.0,en].png
similarity index 100%
rename from tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.event_TimelineItemImageView_null_TimelineItemImageView-Day-34_34_null_1,NEXUS_5,1.0,en].png
rename to tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.event_TimelineItemImageView_null_TimelineItemImageView-Day-35_35_null_1,NEXUS_5,1.0,en].png
diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.event_TimelineItemImageView_null_TimelineItemImageView-Day-34_34_null_2,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.event_TimelineItemImageView_null_TimelineItemImageView-Day-35_35_null_2,NEXUS_5,1.0,en].png
similarity index 100%
rename from tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.event_TimelineItemImageView_null_TimelineItemImageView-Day-34_34_null_2,NEXUS_5,1.0,en].png
rename to tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.event_TimelineItemImageView_null_TimelineItemImageView-Day-35_35_null_2,NEXUS_5,1.0,en].png
diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.event_TimelineItemImageView_null_TimelineItemImageView-Night-34_35_null_0,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.event_TimelineItemImageView_null_TimelineItemImageView-Night-35_36_null_0,NEXUS_5,1.0,en].png
similarity index 100%
rename from tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.event_TimelineItemImageView_null_TimelineItemImageView-Night-34_35_null_0,NEXUS_5,1.0,en].png
rename to tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.event_TimelineItemImageView_null_TimelineItemImageView-Night-35_36_null_0,NEXUS_5,1.0,en].png
diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.event_TimelineItemImageView_null_TimelineItemImageView-Night-34_35_null_1,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.event_TimelineItemImageView_null_TimelineItemImageView-Night-35_36_null_1,NEXUS_5,1.0,en].png
similarity index 100%
rename from tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.event_TimelineItemImageView_null_TimelineItemImageView-Night-34_35_null_1,NEXUS_5,1.0,en].png
rename to tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.event_TimelineItemImageView_null_TimelineItemImageView-Night-35_36_null_1,NEXUS_5,1.0,en].png
diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.event_TimelineItemImageView_null_TimelineItemImageView-Night-34_35_null_2,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.event_TimelineItemImageView_null_TimelineItemImageView-Night-35_36_null_2,NEXUS_5,1.0,en].png
similarity index 100%
rename from tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.event_TimelineItemImageView_null_TimelineItemImageView-Night-34_35_null_2,NEXUS_5,1.0,en].png
rename to tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.event_TimelineItemImageView_null_TimelineItemImageView-Night-35_36_null_2,NEXUS_5,1.0,en].png
diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.event_TimelineItemInformativeView_null_TimelineItemInformativeView-Day-35_35_null,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.event_TimelineItemInformativeView_null_TimelineItemInformativeView-Day-36_36_null,NEXUS_5,1.0,en].png
similarity index 100%
rename from tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.event_TimelineItemInformativeView_null_TimelineItemInformativeView-Day-35_35_null,NEXUS_5,1.0,en].png
rename to tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.event_TimelineItemInformativeView_null_TimelineItemInformativeView-Day-36_36_null,NEXUS_5,1.0,en].png
diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.event_TimelineItemInformativeView_null_TimelineItemInformativeView-Night-35_36_null,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.event_TimelineItemInformativeView_null_TimelineItemInformativeView-Night-36_37_null,NEXUS_5,1.0,en].png
similarity index 100%
rename from tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.event_TimelineItemInformativeView_null_TimelineItemInformativeView-Night-35_36_null,NEXUS_5,1.0,en].png
rename to tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.event_TimelineItemInformativeView_null_TimelineItemInformativeView-Night-36_37_null,NEXUS_5,1.0,en].png
diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.event_TimelineItemLocationView_null_TimelineItemLocationView-Day-36_36_null_0,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.event_TimelineItemLocationView_null_TimelineItemLocationView-Day-37_37_null_0,NEXUS_5,1.0,en].png
similarity index 100%
rename from tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.event_TimelineItemLocationView_null_TimelineItemLocationView-Day-36_36_null_0,NEXUS_5,1.0,en].png
rename to tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.event_TimelineItemLocationView_null_TimelineItemLocationView-Day-37_37_null_0,NEXUS_5,1.0,en].png
diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.event_TimelineItemLocationView_null_TimelineItemLocationView-Day-36_36_null_1,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.event_TimelineItemLocationView_null_TimelineItemLocationView-Day-37_37_null_1,NEXUS_5,1.0,en].png
similarity index 100%
rename from tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.event_TimelineItemLocationView_null_TimelineItemLocationView-Day-36_36_null_1,NEXUS_5,1.0,en].png
rename to tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.event_TimelineItemLocationView_null_TimelineItemLocationView-Day-37_37_null_1,NEXUS_5,1.0,en].png
diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.event_TimelineItemLocationView_null_TimelineItemLocationView-Night-36_37_null_0,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.event_TimelineItemLocationView_null_TimelineItemLocationView-Night-37_38_null_0,NEXUS_5,1.0,en].png
similarity index 100%
rename from tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.event_TimelineItemLocationView_null_TimelineItemLocationView-Night-36_37_null_0,NEXUS_5,1.0,en].png
rename to tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.event_TimelineItemLocationView_null_TimelineItemLocationView-Night-37_38_null_0,NEXUS_5,1.0,en].png
diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.event_TimelineItemLocationView_null_TimelineItemLocationView-Night-36_37_null_1,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.event_TimelineItemLocationView_null_TimelineItemLocationView-Night-37_38_null_1,NEXUS_5,1.0,en].png
similarity index 100%
rename from tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.event_TimelineItemLocationView_null_TimelineItemLocationView-Night-36_37_null_1,NEXUS_5,1.0,en].png
rename to tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.event_TimelineItemLocationView_null_TimelineItemLocationView-Night-37_38_null_1,NEXUS_5,1.0,en].png
diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.event_TimelineItemPollCreatorView_null_TimelineItemPollCreatorView-Day-38_38_null_0,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.event_TimelineItemPollCreatorView_null_TimelineItemPollCreatorView-Day-39_39_null_0,NEXUS_5,1.0,en].png
similarity index 100%
rename from tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.event_TimelineItemPollCreatorView_null_TimelineItemPollCreatorView-Day-38_38_null_0,NEXUS_5,1.0,en].png
rename to tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.event_TimelineItemPollCreatorView_null_TimelineItemPollCreatorView-Day-39_39_null_0,NEXUS_5,1.0,en].png
diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.event_TimelineItemPollCreatorView_null_TimelineItemPollCreatorView-Day-38_38_null_1,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.event_TimelineItemPollCreatorView_null_TimelineItemPollCreatorView-Day-39_39_null_1,NEXUS_5,1.0,en].png
similarity index 100%
rename from tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.event_TimelineItemPollCreatorView_null_TimelineItemPollCreatorView-Day-38_38_null_1,NEXUS_5,1.0,en].png
rename to tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.event_TimelineItemPollCreatorView_null_TimelineItemPollCreatorView-Day-39_39_null_1,NEXUS_5,1.0,en].png
diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.event_TimelineItemPollCreatorView_null_TimelineItemPollCreatorView-Night-38_39_null_0,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.event_TimelineItemPollCreatorView_null_TimelineItemPollCreatorView-Night-39_40_null_0,NEXUS_5,1.0,en].png
similarity index 100%
rename from tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.event_TimelineItemPollCreatorView_null_TimelineItemPollCreatorView-Night-38_39_null_0,NEXUS_5,1.0,en].png
rename to tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.event_TimelineItemPollCreatorView_null_TimelineItemPollCreatorView-Night-39_40_null_0,NEXUS_5,1.0,en].png
diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.event_TimelineItemPollCreatorView_null_TimelineItemPollCreatorView-Night-38_39_null_1,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.event_TimelineItemPollCreatorView_null_TimelineItemPollCreatorView-Night-39_40_null_1,NEXUS_5,1.0,en].png
similarity index 100%
rename from tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.event_TimelineItemPollCreatorView_null_TimelineItemPollCreatorView-Night-38_39_null_1,NEXUS_5,1.0,en].png
rename to tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.event_TimelineItemPollCreatorView_null_TimelineItemPollCreatorView-Night-39_40_null_1,NEXUS_5,1.0,en].png
diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.event_TimelineItemPollView_null_TimelineItemPollView-Day-37_37_null_0,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.event_TimelineItemPollView_null_TimelineItemPollView-Day-38_38_null_0,NEXUS_5,1.0,en].png
similarity index 100%
rename from tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.event_TimelineItemPollView_null_TimelineItemPollView-Day-37_37_null_0,NEXUS_5,1.0,en].png
rename to tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.event_TimelineItemPollView_null_TimelineItemPollView-Day-38_38_null_0,NEXUS_5,1.0,en].png
diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.event_TimelineItemPollView_null_TimelineItemPollView-Day-37_37_null_1,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.event_TimelineItemPollView_null_TimelineItemPollView-Day-38_38_null_1,NEXUS_5,1.0,en].png
similarity index 100%
rename from tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.event_TimelineItemPollView_null_TimelineItemPollView-Day-37_37_null_1,NEXUS_5,1.0,en].png
rename to tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.event_TimelineItemPollView_null_TimelineItemPollView-Day-38_38_null_1,NEXUS_5,1.0,en].png
diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.event_TimelineItemPollView_null_TimelineItemPollView-Night-37_38_null_0,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.event_TimelineItemPollView_null_TimelineItemPollView-Night-38_39_null_0,NEXUS_5,1.0,en].png
similarity index 100%
rename from tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.event_TimelineItemPollView_null_TimelineItemPollView-Night-37_38_null_0,NEXUS_5,1.0,en].png
rename to tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.event_TimelineItemPollView_null_TimelineItemPollView-Night-38_39_null_0,NEXUS_5,1.0,en].png
diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.event_TimelineItemPollView_null_TimelineItemPollView-Night-37_38_null_1,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.event_TimelineItemPollView_null_TimelineItemPollView-Night-38_39_null_1,NEXUS_5,1.0,en].png
similarity index 100%
rename from tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.event_TimelineItemPollView_null_TimelineItemPollView-Night-37_38_null_1,NEXUS_5,1.0,en].png
rename to tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.event_TimelineItemPollView_null_TimelineItemPollView-Night-38_39_null_1,NEXUS_5,1.0,en].png
diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.event_TimelineItemRedactedView_null_TimelineItemRedactedView-Day-39_39_null,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.event_TimelineItemRedactedView_null_TimelineItemRedactedView-Day-40_40_null,NEXUS_5,1.0,en].png
similarity index 100%
rename from tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.event_TimelineItemRedactedView_null_TimelineItemRedactedView-Day-39_39_null,NEXUS_5,1.0,en].png
rename to tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.event_TimelineItemRedactedView_null_TimelineItemRedactedView-Day-40_40_null,NEXUS_5,1.0,en].png
diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.event_TimelineItemRedactedView_null_TimelineItemRedactedView-Night-39_40_null,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.event_TimelineItemRedactedView_null_TimelineItemRedactedView-Night-40_41_null,NEXUS_5,1.0,en].png
similarity index 100%
rename from tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.event_TimelineItemRedactedView_null_TimelineItemRedactedView-Night-39_40_null,NEXUS_5,1.0,en].png
rename to tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.event_TimelineItemRedactedView_null_TimelineItemRedactedView-Night-40_41_null,NEXUS_5,1.0,en].png
diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.event_TimelineItemStateView_null_TimelineItemStateView-Day-40_40_null,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.event_TimelineItemStateView_null_TimelineItemStateView-Day-41_41_null,NEXUS_5,1.0,en].png
similarity index 100%
rename from tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.event_TimelineItemStateView_null_TimelineItemStateView-Day-40_40_null,NEXUS_5,1.0,en].png
rename to tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.event_TimelineItemStateView_null_TimelineItemStateView-Day-41_41_null,NEXUS_5,1.0,en].png
diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.event_TimelineItemStateView_null_TimelineItemStateView-Night-40_41_null,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.event_TimelineItemStateView_null_TimelineItemStateView-Night-41_42_null,NEXUS_5,1.0,en].png
similarity index 100%
rename from tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.event_TimelineItemStateView_null_TimelineItemStateView-Night-40_41_null,NEXUS_5,1.0,en].png
rename to tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.event_TimelineItemStateView_null_TimelineItemStateView-Night-41_42_null,NEXUS_5,1.0,en].png
diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.event_TimelineItemTextView_null_TimelineItemTextView-Day-41_41_null_0,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.event_TimelineItemTextView_null_TimelineItemTextView-Day-42_42_null_0,NEXUS_5,1.0,en].png
similarity index 100%
rename from tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.event_TimelineItemTextView_null_TimelineItemTextView-Day-41_41_null_0,NEXUS_5,1.0,en].png
rename to tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.event_TimelineItemTextView_null_TimelineItemTextView-Day-42_42_null_0,NEXUS_5,1.0,en].png
diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.event_TimelineItemTextView_null_TimelineItemTextView-Day-41_41_null_1,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.event_TimelineItemTextView_null_TimelineItemTextView-Day-42_42_null_1,NEXUS_5,1.0,en].png
similarity index 100%
rename from tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.event_TimelineItemTextView_null_TimelineItemTextView-Day-41_41_null_1,NEXUS_5,1.0,en].png
rename to tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.event_TimelineItemTextView_null_TimelineItemTextView-Day-42_42_null_1,NEXUS_5,1.0,en].png
diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.event_TimelineItemTextView_null_TimelineItemTextView-Day-41_41_null_2,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.event_TimelineItemTextView_null_TimelineItemTextView-Day-42_42_null_2,NEXUS_5,1.0,en].png
similarity index 100%
rename from tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.event_TimelineItemTextView_null_TimelineItemTextView-Day-41_41_null_2,NEXUS_5,1.0,en].png
rename to tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.event_TimelineItemTextView_null_TimelineItemTextView-Day-42_42_null_2,NEXUS_5,1.0,en].png
diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.event_TimelineItemTextView_null_TimelineItemTextView-Day-41_41_null_3,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.event_TimelineItemTextView_null_TimelineItemTextView-Day-42_42_null_3,NEXUS_5,1.0,en].png
similarity index 100%
rename from tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.event_TimelineItemTextView_null_TimelineItemTextView-Day-41_41_null_3,NEXUS_5,1.0,en].png
rename to tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.event_TimelineItemTextView_null_TimelineItemTextView-Day-42_42_null_3,NEXUS_5,1.0,en].png
diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.event_TimelineItemTextView_null_TimelineItemTextView-Day-41_41_null_4,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.event_TimelineItemTextView_null_TimelineItemTextView-Day-42_42_null_4,NEXUS_5,1.0,en].png
similarity index 100%
rename from tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.event_TimelineItemTextView_null_TimelineItemTextView-Day-41_41_null_4,NEXUS_5,1.0,en].png
rename to tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.event_TimelineItemTextView_null_TimelineItemTextView-Day-42_42_null_4,NEXUS_5,1.0,en].png
diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.event_TimelineItemTextView_null_TimelineItemTextView-Day-41_41_null_5,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.event_TimelineItemTextView_null_TimelineItemTextView-Day-42_42_null_5,NEXUS_5,1.0,en].png
similarity index 100%
rename from tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.event_TimelineItemTextView_null_TimelineItemTextView-Day-41_41_null_5,NEXUS_5,1.0,en].png
rename to tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.event_TimelineItemTextView_null_TimelineItemTextView-Day-42_42_null_5,NEXUS_5,1.0,en].png
diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.event_TimelineItemTextView_null_TimelineItemTextView-Night-41_42_null_0,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.event_TimelineItemTextView_null_TimelineItemTextView-Night-42_43_null_0,NEXUS_5,1.0,en].png
similarity index 100%
rename from tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.event_TimelineItemTextView_null_TimelineItemTextView-Night-41_42_null_0,NEXUS_5,1.0,en].png
rename to tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.event_TimelineItemTextView_null_TimelineItemTextView-Night-42_43_null_0,NEXUS_5,1.0,en].png
diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.event_TimelineItemTextView_null_TimelineItemTextView-Night-41_42_null_1,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.event_TimelineItemTextView_null_TimelineItemTextView-Night-42_43_null_1,NEXUS_5,1.0,en].png
similarity index 100%
rename from tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.event_TimelineItemTextView_null_TimelineItemTextView-Night-41_42_null_1,NEXUS_5,1.0,en].png
rename to tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.event_TimelineItemTextView_null_TimelineItemTextView-Night-42_43_null_1,NEXUS_5,1.0,en].png
diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.event_TimelineItemTextView_null_TimelineItemTextView-Night-41_42_null_2,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.event_TimelineItemTextView_null_TimelineItemTextView-Night-42_43_null_2,NEXUS_5,1.0,en].png
similarity index 100%
rename from tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.event_TimelineItemTextView_null_TimelineItemTextView-Night-41_42_null_2,NEXUS_5,1.0,en].png
rename to tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.event_TimelineItemTextView_null_TimelineItemTextView-Night-42_43_null_2,NEXUS_5,1.0,en].png
diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.event_TimelineItemTextView_null_TimelineItemTextView-Night-41_42_null_3,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.event_TimelineItemTextView_null_TimelineItemTextView-Night-42_43_null_3,NEXUS_5,1.0,en].png
similarity index 100%
rename from tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.event_TimelineItemTextView_null_TimelineItemTextView-Night-41_42_null_3,NEXUS_5,1.0,en].png
rename to tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.event_TimelineItemTextView_null_TimelineItemTextView-Night-42_43_null_3,NEXUS_5,1.0,en].png
diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.event_TimelineItemTextView_null_TimelineItemTextView-Night-41_42_null_4,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.event_TimelineItemTextView_null_TimelineItemTextView-Night-42_43_null_4,NEXUS_5,1.0,en].png
similarity index 100%
rename from tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.event_TimelineItemTextView_null_TimelineItemTextView-Night-41_42_null_4,NEXUS_5,1.0,en].png
rename to tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.event_TimelineItemTextView_null_TimelineItemTextView-Night-42_43_null_4,NEXUS_5,1.0,en].png
diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.event_TimelineItemTextView_null_TimelineItemTextView-Night-41_42_null_5,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.event_TimelineItemTextView_null_TimelineItemTextView-Night-42_43_null_5,NEXUS_5,1.0,en].png
similarity index 100%
rename from tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.event_TimelineItemTextView_null_TimelineItemTextView-Night-41_42_null_5,NEXUS_5,1.0,en].png
rename to tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.event_TimelineItemTextView_null_TimelineItemTextView-Night-42_43_null_5,NEXUS_5,1.0,en].png
diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.event_TimelineItemUnknownView_null_TimelineItemUnknownView-Day-42_42_null,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.event_TimelineItemUnknownView_null_TimelineItemUnknownView-Day-43_43_null,NEXUS_5,1.0,en].png
similarity index 100%
rename from tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.event_TimelineItemUnknownView_null_TimelineItemUnknownView-Day-42_42_null,NEXUS_5,1.0,en].png
rename to tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.event_TimelineItemUnknownView_null_TimelineItemUnknownView-Day-43_43_null,NEXUS_5,1.0,en].png
diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.event_TimelineItemUnknownView_null_TimelineItemUnknownView-Night-42_43_null,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.event_TimelineItemUnknownView_null_TimelineItemUnknownView-Night-43_44_null,NEXUS_5,1.0,en].png
similarity index 100%
rename from tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.event_TimelineItemUnknownView_null_TimelineItemUnknownView-Night-42_43_null,NEXUS_5,1.0,en].png
rename to tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.event_TimelineItemUnknownView_null_TimelineItemUnknownView-Night-43_44_null,NEXUS_5,1.0,en].png
diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.event_TimelineItemVideoView_null_TimelineItemVideoView-Day-43_43_null_0,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.event_TimelineItemVideoView_null_TimelineItemVideoView-Day-44_44_null_0,NEXUS_5,1.0,en].png
similarity index 100%
rename from tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.event_TimelineItemVideoView_null_TimelineItemVideoView-Day-43_43_null_0,NEXUS_5,1.0,en].png
rename to tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.event_TimelineItemVideoView_null_TimelineItemVideoView-Day-44_44_null_0,NEXUS_5,1.0,en].png
diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.event_TimelineItemVideoView_null_TimelineItemVideoView-Day-43_43_null_1,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.event_TimelineItemVideoView_null_TimelineItemVideoView-Day-44_44_null_1,NEXUS_5,1.0,en].png
similarity index 100%
rename from tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.event_TimelineItemVideoView_null_TimelineItemVideoView-Day-43_43_null_1,NEXUS_5,1.0,en].png
rename to tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.event_TimelineItemVideoView_null_TimelineItemVideoView-Day-44_44_null_1,NEXUS_5,1.0,en].png
diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.event_TimelineItemVideoView_null_TimelineItemVideoView-Day-43_43_null_2,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.event_TimelineItemVideoView_null_TimelineItemVideoView-Day-44_44_null_2,NEXUS_5,1.0,en].png
similarity index 100%
rename from tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.event_TimelineItemVideoView_null_TimelineItemVideoView-Day-43_43_null_2,NEXUS_5,1.0,en].png
rename to tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.event_TimelineItemVideoView_null_TimelineItemVideoView-Day-44_44_null_2,NEXUS_5,1.0,en].png
diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.event_TimelineItemVideoView_null_TimelineItemVideoView-Night-43_44_null_0,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.event_TimelineItemVideoView_null_TimelineItemVideoView-Night-44_45_null_0,NEXUS_5,1.0,en].png
similarity index 100%
rename from tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.event_TimelineItemVideoView_null_TimelineItemVideoView-Night-43_44_null_0,NEXUS_5,1.0,en].png
rename to tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.event_TimelineItemVideoView_null_TimelineItemVideoView-Night-44_45_null_0,NEXUS_5,1.0,en].png
diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.event_TimelineItemVideoView_null_TimelineItemVideoView-Night-43_44_null_1,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.event_TimelineItemVideoView_null_TimelineItemVideoView-Night-44_45_null_1,NEXUS_5,1.0,en].png
similarity index 100%
rename from tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.event_TimelineItemVideoView_null_TimelineItemVideoView-Night-43_44_null_1,NEXUS_5,1.0,en].png
rename to tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.event_TimelineItemVideoView_null_TimelineItemVideoView-Night-44_45_null_1,NEXUS_5,1.0,en].png
diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.event_TimelineItemVideoView_null_TimelineItemVideoView-Night-43_44_null_2,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.event_TimelineItemVideoView_null_TimelineItemVideoView-Night-44_45_null_2,NEXUS_5,1.0,en].png
similarity index 100%
rename from tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.event_TimelineItemVideoView_null_TimelineItemVideoView-Night-43_44_null_2,NEXUS_5,1.0,en].png
rename to tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.event_TimelineItemVideoView_null_TimelineItemVideoView-Night-44_45_null_2,NEXUS_5,1.0,en].png
diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.event_TimelineItemVoiceViewUnified_null_TimelineItemVoiceViewUnified-Day-45_45_null,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.event_TimelineItemVoiceViewUnified_null_TimelineItemVoiceViewUnified-Day-46_46_null,NEXUS_5,1.0,en].png
similarity index 100%
rename from tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.event_TimelineItemVoiceViewUnified_null_TimelineItemVoiceViewUnified-Day-45_45_null,NEXUS_5,1.0,en].png
rename to tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.event_TimelineItemVoiceViewUnified_null_TimelineItemVoiceViewUnified-Day-46_46_null,NEXUS_5,1.0,en].png
diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.event_TimelineItemVoiceViewUnified_null_TimelineItemVoiceViewUnified-Night-45_46_null,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.event_TimelineItemVoiceViewUnified_null_TimelineItemVoiceViewUnified-Night-46_47_null,NEXUS_5,1.0,en].png
similarity index 100%
rename from tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.event_TimelineItemVoiceViewUnified_null_TimelineItemVoiceViewUnified-Night-45_46_null,NEXUS_5,1.0,en].png
rename to tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.event_TimelineItemVoiceViewUnified_null_TimelineItemVoiceViewUnified-Night-46_47_null,NEXUS_5,1.0,en].png
diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.event_TimelineItemVoiceView_null_TimelineItemVoiceView-Day-44_44_null_0,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.event_TimelineItemVoiceView_null_TimelineItemVoiceView-Day-45_45_null_0,NEXUS_5,1.0,en].png
similarity index 100%
rename from tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.event_TimelineItemVoiceView_null_TimelineItemVoiceView-Day-44_44_null_0,NEXUS_5,1.0,en].png
rename to tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.event_TimelineItemVoiceView_null_TimelineItemVoiceView-Day-45_45_null_0,NEXUS_5,1.0,en].png
diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.event_TimelineItemVoiceView_null_TimelineItemVoiceView-Day-44_44_null_1,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.event_TimelineItemVoiceView_null_TimelineItemVoiceView-Day-45_45_null_1,NEXUS_5,1.0,en].png
similarity index 100%
rename from tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.event_TimelineItemVoiceView_null_TimelineItemVoiceView-Day-44_44_null_1,NEXUS_5,1.0,en].png
rename to tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.event_TimelineItemVoiceView_null_TimelineItemVoiceView-Day-45_45_null_1,NEXUS_5,1.0,en].png
diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.event_TimelineItemVoiceView_null_TimelineItemVoiceView-Day-44_44_null_10,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.event_TimelineItemVoiceView_null_TimelineItemVoiceView-Day-45_45_null_10,NEXUS_5,1.0,en].png
similarity index 100%
rename from tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.event_TimelineItemVoiceView_null_TimelineItemVoiceView-Day-44_44_null_10,NEXUS_5,1.0,en].png
rename to tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.event_TimelineItemVoiceView_null_TimelineItemVoiceView-Day-45_45_null_10,NEXUS_5,1.0,en].png
diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.event_TimelineItemVoiceView_null_TimelineItemVoiceView-Day-44_44_null_11,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.event_TimelineItemVoiceView_null_TimelineItemVoiceView-Day-45_45_null_11,NEXUS_5,1.0,en].png
similarity index 100%
rename from tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.event_TimelineItemVoiceView_null_TimelineItemVoiceView-Day-44_44_null_11,NEXUS_5,1.0,en].png
rename to tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.event_TimelineItemVoiceView_null_TimelineItemVoiceView-Day-45_45_null_11,NEXUS_5,1.0,en].png
diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.event_TimelineItemVoiceView_null_TimelineItemVoiceView-Day-44_44_null_12,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.event_TimelineItemVoiceView_null_TimelineItemVoiceView-Day-45_45_null_12,NEXUS_5,1.0,en].png
similarity index 100%
rename from tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.event_TimelineItemVoiceView_null_TimelineItemVoiceView-Day-44_44_null_12,NEXUS_5,1.0,en].png
rename to tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.event_TimelineItemVoiceView_null_TimelineItemVoiceView-Day-45_45_null_12,NEXUS_5,1.0,en].png
diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.event_TimelineItemVoiceView_null_TimelineItemVoiceView-Day-44_44_null_13,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.event_TimelineItemVoiceView_null_TimelineItemVoiceView-Day-45_45_null_13,NEXUS_5,1.0,en].png
similarity index 100%
rename from tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.event_TimelineItemVoiceView_null_TimelineItemVoiceView-Day-44_44_null_13,NEXUS_5,1.0,en].png
rename to tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.event_TimelineItemVoiceView_null_TimelineItemVoiceView-Day-45_45_null_13,NEXUS_5,1.0,en].png
diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.event_TimelineItemVoiceView_null_TimelineItemVoiceView-Day-44_44_null_14,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.event_TimelineItemVoiceView_null_TimelineItemVoiceView-Day-45_45_null_14,NEXUS_5,1.0,en].png
similarity index 100%
rename from tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.event_TimelineItemVoiceView_null_TimelineItemVoiceView-Day-44_44_null_14,NEXUS_5,1.0,en].png
rename to tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.event_TimelineItemVoiceView_null_TimelineItemVoiceView-Day-45_45_null_14,NEXUS_5,1.0,en].png
diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.event_TimelineItemVoiceView_null_TimelineItemVoiceView-Day-44_44_null_2,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.event_TimelineItemVoiceView_null_TimelineItemVoiceView-Day-45_45_null_2,NEXUS_5,1.0,en].png
similarity index 100%
rename from tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.event_TimelineItemVoiceView_null_TimelineItemVoiceView-Day-44_44_null_2,NEXUS_5,1.0,en].png
rename to tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.event_TimelineItemVoiceView_null_TimelineItemVoiceView-Day-45_45_null_2,NEXUS_5,1.0,en].png
diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.event_TimelineItemVoiceView_null_TimelineItemVoiceView-Day-44_44_null_3,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.event_TimelineItemVoiceView_null_TimelineItemVoiceView-Day-45_45_null_3,NEXUS_5,1.0,en].png
similarity index 100%
rename from tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.event_TimelineItemVoiceView_null_TimelineItemVoiceView-Day-44_44_null_3,NEXUS_5,1.0,en].png
rename to tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.event_TimelineItemVoiceView_null_TimelineItemVoiceView-Day-45_45_null_3,NEXUS_5,1.0,en].png
diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.event_TimelineItemVoiceView_null_TimelineItemVoiceView-Day-44_44_null_4,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.event_TimelineItemVoiceView_null_TimelineItemVoiceView-Day-45_45_null_4,NEXUS_5,1.0,en].png
similarity index 100%
rename from tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.event_TimelineItemVoiceView_null_TimelineItemVoiceView-Day-44_44_null_4,NEXUS_5,1.0,en].png
rename to tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.event_TimelineItemVoiceView_null_TimelineItemVoiceView-Day-45_45_null_4,NEXUS_5,1.0,en].png
diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.event_TimelineItemVoiceView_null_TimelineItemVoiceView-Day-44_44_null_5,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.event_TimelineItemVoiceView_null_TimelineItemVoiceView-Day-45_45_null_5,NEXUS_5,1.0,en].png
similarity index 100%
rename from tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.event_TimelineItemVoiceView_null_TimelineItemVoiceView-Day-44_44_null_5,NEXUS_5,1.0,en].png
rename to tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.event_TimelineItemVoiceView_null_TimelineItemVoiceView-Day-45_45_null_5,NEXUS_5,1.0,en].png
diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.event_TimelineItemVoiceView_null_TimelineItemVoiceView-Day-44_44_null_6,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.event_TimelineItemVoiceView_null_TimelineItemVoiceView-Day-45_45_null_6,NEXUS_5,1.0,en].png
similarity index 100%
rename from tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.event_TimelineItemVoiceView_null_TimelineItemVoiceView-Day-44_44_null_6,NEXUS_5,1.0,en].png
rename to tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.event_TimelineItemVoiceView_null_TimelineItemVoiceView-Day-45_45_null_6,NEXUS_5,1.0,en].png
diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.event_TimelineItemVoiceView_null_TimelineItemVoiceView-Day-44_44_null_7,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.event_TimelineItemVoiceView_null_TimelineItemVoiceView-Day-45_45_null_7,NEXUS_5,1.0,en].png
similarity index 100%
rename from tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.event_TimelineItemVoiceView_null_TimelineItemVoiceView-Day-44_44_null_7,NEXUS_5,1.0,en].png
rename to tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.event_TimelineItemVoiceView_null_TimelineItemVoiceView-Day-45_45_null_7,NEXUS_5,1.0,en].png
diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.event_TimelineItemVoiceView_null_TimelineItemVoiceView-Day-44_44_null_8,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.event_TimelineItemVoiceView_null_TimelineItemVoiceView-Day-45_45_null_8,NEXUS_5,1.0,en].png
similarity index 100%
rename from tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.event_TimelineItemVoiceView_null_TimelineItemVoiceView-Day-44_44_null_8,NEXUS_5,1.0,en].png
rename to tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.event_TimelineItemVoiceView_null_TimelineItemVoiceView-Day-45_45_null_8,NEXUS_5,1.0,en].png
diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.event_TimelineItemVoiceView_null_TimelineItemVoiceView-Day-44_44_null_9,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.event_TimelineItemVoiceView_null_TimelineItemVoiceView-Day-45_45_null_9,NEXUS_5,1.0,en].png
similarity index 100%
rename from tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.event_TimelineItemVoiceView_null_TimelineItemVoiceView-Day-44_44_null_9,NEXUS_5,1.0,en].png
rename to tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.event_TimelineItemVoiceView_null_TimelineItemVoiceView-Day-45_45_null_9,NEXUS_5,1.0,en].png
diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.event_TimelineItemVoiceView_null_TimelineItemVoiceView-Night-44_45_null_0,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.event_TimelineItemVoiceView_null_TimelineItemVoiceView-Night-45_46_null_0,NEXUS_5,1.0,en].png
similarity index 100%
rename from tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.event_TimelineItemVoiceView_null_TimelineItemVoiceView-Night-44_45_null_0,NEXUS_5,1.0,en].png
rename to tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.event_TimelineItemVoiceView_null_TimelineItemVoiceView-Night-45_46_null_0,NEXUS_5,1.0,en].png
diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.event_TimelineItemVoiceView_null_TimelineItemVoiceView-Night-44_45_null_1,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.event_TimelineItemVoiceView_null_TimelineItemVoiceView-Night-45_46_null_1,NEXUS_5,1.0,en].png
similarity index 100%
rename from tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.event_TimelineItemVoiceView_null_TimelineItemVoiceView-Night-44_45_null_1,NEXUS_5,1.0,en].png
rename to tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.event_TimelineItemVoiceView_null_TimelineItemVoiceView-Night-45_46_null_1,NEXUS_5,1.0,en].png
diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.event_TimelineItemVoiceView_null_TimelineItemVoiceView-Night-44_45_null_10,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.event_TimelineItemVoiceView_null_TimelineItemVoiceView-Night-45_46_null_10,NEXUS_5,1.0,en].png
similarity index 100%
rename from tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.event_TimelineItemVoiceView_null_TimelineItemVoiceView-Night-44_45_null_10,NEXUS_5,1.0,en].png
rename to tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.event_TimelineItemVoiceView_null_TimelineItemVoiceView-Night-45_46_null_10,NEXUS_5,1.0,en].png
diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.event_TimelineItemVoiceView_null_TimelineItemVoiceView-Night-44_45_null_11,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.event_TimelineItemVoiceView_null_TimelineItemVoiceView-Night-45_46_null_11,NEXUS_5,1.0,en].png
similarity index 100%
rename from tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.event_TimelineItemVoiceView_null_TimelineItemVoiceView-Night-44_45_null_11,NEXUS_5,1.0,en].png
rename to tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.event_TimelineItemVoiceView_null_TimelineItemVoiceView-Night-45_46_null_11,NEXUS_5,1.0,en].png
diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.event_TimelineItemVoiceView_null_TimelineItemVoiceView-Night-44_45_null_12,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.event_TimelineItemVoiceView_null_TimelineItemVoiceView-Night-45_46_null_12,NEXUS_5,1.0,en].png
similarity index 100%
rename from tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.event_TimelineItemVoiceView_null_TimelineItemVoiceView-Night-44_45_null_12,NEXUS_5,1.0,en].png
rename to tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.event_TimelineItemVoiceView_null_TimelineItemVoiceView-Night-45_46_null_12,NEXUS_5,1.0,en].png
diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.event_TimelineItemVoiceView_null_TimelineItemVoiceView-Night-44_45_null_13,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.event_TimelineItemVoiceView_null_TimelineItemVoiceView-Night-45_46_null_13,NEXUS_5,1.0,en].png
similarity index 100%
rename from tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.event_TimelineItemVoiceView_null_TimelineItemVoiceView-Night-44_45_null_13,NEXUS_5,1.0,en].png
rename to tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.event_TimelineItemVoiceView_null_TimelineItemVoiceView-Night-45_46_null_13,NEXUS_5,1.0,en].png
diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.event_TimelineItemVoiceView_null_TimelineItemVoiceView-Night-44_45_null_14,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.event_TimelineItemVoiceView_null_TimelineItemVoiceView-Night-45_46_null_14,NEXUS_5,1.0,en].png
similarity index 100%
rename from tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.event_TimelineItemVoiceView_null_TimelineItemVoiceView-Night-44_45_null_14,NEXUS_5,1.0,en].png
rename to tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.event_TimelineItemVoiceView_null_TimelineItemVoiceView-Night-45_46_null_14,NEXUS_5,1.0,en].png
diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.event_TimelineItemVoiceView_null_TimelineItemVoiceView-Night-44_45_null_2,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.event_TimelineItemVoiceView_null_TimelineItemVoiceView-Night-45_46_null_2,NEXUS_5,1.0,en].png
similarity index 100%
rename from tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.event_TimelineItemVoiceView_null_TimelineItemVoiceView-Night-44_45_null_2,NEXUS_5,1.0,en].png
rename to tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.event_TimelineItemVoiceView_null_TimelineItemVoiceView-Night-45_46_null_2,NEXUS_5,1.0,en].png
diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.event_TimelineItemVoiceView_null_TimelineItemVoiceView-Night-44_45_null_3,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.event_TimelineItemVoiceView_null_TimelineItemVoiceView-Night-45_46_null_3,NEXUS_5,1.0,en].png
similarity index 100%
rename from tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.event_TimelineItemVoiceView_null_TimelineItemVoiceView-Night-44_45_null_3,NEXUS_5,1.0,en].png
rename to tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.event_TimelineItemVoiceView_null_TimelineItemVoiceView-Night-45_46_null_3,NEXUS_5,1.0,en].png
diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.event_TimelineItemVoiceView_null_TimelineItemVoiceView-Night-44_45_null_4,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.event_TimelineItemVoiceView_null_TimelineItemVoiceView-Night-45_46_null_4,NEXUS_5,1.0,en].png
similarity index 100%
rename from tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.event_TimelineItemVoiceView_null_TimelineItemVoiceView-Night-44_45_null_4,NEXUS_5,1.0,en].png
rename to tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.event_TimelineItemVoiceView_null_TimelineItemVoiceView-Night-45_46_null_4,NEXUS_5,1.0,en].png
diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.event_TimelineItemVoiceView_null_TimelineItemVoiceView-Night-44_45_null_5,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.event_TimelineItemVoiceView_null_TimelineItemVoiceView-Night-45_46_null_5,NEXUS_5,1.0,en].png
similarity index 100%
rename from tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.event_TimelineItemVoiceView_null_TimelineItemVoiceView-Night-44_45_null_5,NEXUS_5,1.0,en].png
rename to tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.event_TimelineItemVoiceView_null_TimelineItemVoiceView-Night-45_46_null_5,NEXUS_5,1.0,en].png
diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.event_TimelineItemVoiceView_null_TimelineItemVoiceView-Night-44_45_null_6,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.event_TimelineItemVoiceView_null_TimelineItemVoiceView-Night-45_46_null_6,NEXUS_5,1.0,en].png
similarity index 100%
rename from tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.event_TimelineItemVoiceView_null_TimelineItemVoiceView-Night-44_45_null_6,NEXUS_5,1.0,en].png
rename to tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.event_TimelineItemVoiceView_null_TimelineItemVoiceView-Night-45_46_null_6,NEXUS_5,1.0,en].png
diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.event_TimelineItemVoiceView_null_TimelineItemVoiceView-Night-44_45_null_7,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.event_TimelineItemVoiceView_null_TimelineItemVoiceView-Night-45_46_null_7,NEXUS_5,1.0,en].png
similarity index 100%
rename from tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.event_TimelineItemVoiceView_null_TimelineItemVoiceView-Night-44_45_null_7,NEXUS_5,1.0,en].png
rename to tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.event_TimelineItemVoiceView_null_TimelineItemVoiceView-Night-45_46_null_7,NEXUS_5,1.0,en].png
diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.event_TimelineItemVoiceView_null_TimelineItemVoiceView-Night-44_45_null_8,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.event_TimelineItemVoiceView_null_TimelineItemVoiceView-Night-45_46_null_8,NEXUS_5,1.0,en].png
similarity index 100%
rename from tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.event_TimelineItemVoiceView_null_TimelineItemVoiceView-Night-44_45_null_8,NEXUS_5,1.0,en].png
rename to tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.event_TimelineItemVoiceView_null_TimelineItemVoiceView-Night-45_46_null_8,NEXUS_5,1.0,en].png
diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.event_TimelineItemVoiceView_null_TimelineItemVoiceView-Night-44_45_null_9,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.event_TimelineItemVoiceView_null_TimelineItemVoiceView-Night-45_46_null_9,NEXUS_5,1.0,en].png
similarity index 100%
rename from tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.event_TimelineItemVoiceView_null_TimelineItemVoiceView-Night-44_45_null_9,NEXUS_5,1.0,en].png
rename to tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.event_TimelineItemVoiceView_null_TimelineItemVoiceView-Night-45_46_null_9,NEXUS_5,1.0,en].png
diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.group_GroupHeaderView_null_GroupHeaderView-Day-47_47_null,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.group_GroupHeaderView_null_GroupHeaderView-Day-47_47_null,NEXUS_5,1.0,en].png
deleted file mode 100644
index f306954150..0000000000
--- a/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.group_GroupHeaderView_null_GroupHeaderView-Day-47_47_null,NEXUS_5,1.0,en].png
+++ /dev/null
@@ -1,3 +0,0 @@
-version https://git-lfs.github.com/spec/v1
-oid sha256:92f929493ff8f4ea9f4a7a7b8a27901896cd00dc2509095885b41513cfe339c1
-size 25381
diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.group_GroupHeaderView_null_GroupHeaderView-Day-48_48_null,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.group_GroupHeaderView_null_GroupHeaderView-Day-48_48_null,NEXUS_5,1.0,en].png
new file mode 100644
index 0000000000..1935bc644c
--- /dev/null
+++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.group_GroupHeaderView_null_GroupHeaderView-Day-48_48_null,NEXUS_5,1.0,en].png
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:910e28b2dc89b08b99b2d692d10bea6b79c85749f804842d63177d5380283006
+size 25411
diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.group_GroupHeaderView_null_GroupHeaderView-Night-47_48_null,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.group_GroupHeaderView_null_GroupHeaderView-Night-47_48_null,NEXUS_5,1.0,en].png
deleted file mode 100644
index 5c756d6306..0000000000
--- a/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.group_GroupHeaderView_null_GroupHeaderView-Night-47_48_null,NEXUS_5,1.0,en].png
+++ /dev/null
@@ -1,3 +0,0 @@
-version https://git-lfs.github.com/spec/v1
-oid sha256:f5f0e119f72f1786bdd72440a3758ddc91360899170e9c38e5b9d3edaf157f17
-size 25022
diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.group_GroupHeaderView_null_GroupHeaderView-Night-48_49_null,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.group_GroupHeaderView_null_GroupHeaderView-Night-48_49_null,NEXUS_5,1.0,en].png
new file mode 100644
index 0000000000..66c090cbb2
--- /dev/null
+++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.group_GroupHeaderView_null_GroupHeaderView-Night-48_49_null,NEXUS_5,1.0,en].png
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:e9af3bd8ae926ca6bf67103aad707c28e72138c564126eeb832bf589fbd2f81e
+size 25033
diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.html_HtmlDocument_null_HtmlDocument-Day-48_48_null_0,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.html_HtmlDocument_null_HtmlDocument-Day-49_49_null_0,NEXUS_5,1.0,en].png
similarity index 100%
rename from tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.html_HtmlDocument_null_HtmlDocument-Day-48_48_null_0,NEXUS_5,1.0,en].png
rename to tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.html_HtmlDocument_null_HtmlDocument-Day-49_49_null_0,NEXUS_5,1.0,en].png
diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.html_HtmlDocument_null_HtmlDocument-Day-48_48_null_1,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.html_HtmlDocument_null_HtmlDocument-Day-49_49_null_1,NEXUS_5,1.0,en].png
similarity index 100%
rename from tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.html_HtmlDocument_null_HtmlDocument-Day-48_48_null_1,NEXUS_5,1.0,en].png
rename to tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.html_HtmlDocument_null_HtmlDocument-Day-49_49_null_1,NEXUS_5,1.0,en].png
diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.html_HtmlDocument_null_HtmlDocument-Day-48_48_null_10,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.html_HtmlDocument_null_HtmlDocument-Day-49_49_null_10,NEXUS_5,1.0,en].png
similarity index 100%
rename from tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.html_HtmlDocument_null_HtmlDocument-Day-48_48_null_10,NEXUS_5,1.0,en].png
rename to tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.html_HtmlDocument_null_HtmlDocument-Day-49_49_null_10,NEXUS_5,1.0,en].png
diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.html_HtmlDocument_null_HtmlDocument-Day-48_48_null_11,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.html_HtmlDocument_null_HtmlDocument-Day-49_49_null_11,NEXUS_5,1.0,en].png
similarity index 100%
rename from tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.html_HtmlDocument_null_HtmlDocument-Day-48_48_null_11,NEXUS_5,1.0,en].png
rename to tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.html_HtmlDocument_null_HtmlDocument-Day-49_49_null_11,NEXUS_5,1.0,en].png
diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.html_HtmlDocument_null_HtmlDocument-Day-48_48_null_12,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.html_HtmlDocument_null_HtmlDocument-Day-49_49_null_12,NEXUS_5,1.0,en].png
similarity index 100%
rename from tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.html_HtmlDocument_null_HtmlDocument-Day-48_48_null_12,NEXUS_5,1.0,en].png
rename to tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.html_HtmlDocument_null_HtmlDocument-Day-49_49_null_12,NEXUS_5,1.0,en].png
diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.html_HtmlDocument_null_HtmlDocument-Day-48_48_null_13,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.html_HtmlDocument_null_HtmlDocument-Day-49_49_null_13,NEXUS_5,1.0,en].png
similarity index 100%
rename from tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.html_HtmlDocument_null_HtmlDocument-Day-48_48_null_13,NEXUS_5,1.0,en].png
rename to tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.html_HtmlDocument_null_HtmlDocument-Day-49_49_null_13,NEXUS_5,1.0,en].png
diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.html_HtmlDocument_null_HtmlDocument-Day-48_48_null_14,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.html_HtmlDocument_null_HtmlDocument-Day-49_49_null_14,NEXUS_5,1.0,en].png
similarity index 100%
rename from tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.html_HtmlDocument_null_HtmlDocument-Day-48_48_null_14,NEXUS_5,1.0,en].png
rename to tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.html_HtmlDocument_null_HtmlDocument-Day-49_49_null_14,NEXUS_5,1.0,en].png
diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.html_HtmlDocument_null_HtmlDocument-Day-48_48_null_15,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.html_HtmlDocument_null_HtmlDocument-Day-49_49_null_15,NEXUS_5,1.0,en].png
similarity index 100%
rename from tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.html_HtmlDocument_null_HtmlDocument-Day-48_48_null_15,NEXUS_5,1.0,en].png
rename to tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.html_HtmlDocument_null_HtmlDocument-Day-49_49_null_15,NEXUS_5,1.0,en].png
diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.html_HtmlDocument_null_HtmlDocument-Day-48_48_null_16,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.html_HtmlDocument_null_HtmlDocument-Day-49_49_null_16,NEXUS_5,1.0,en].png
similarity index 100%
rename from tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.html_HtmlDocument_null_HtmlDocument-Day-48_48_null_16,NEXUS_5,1.0,en].png
rename to tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.html_HtmlDocument_null_HtmlDocument-Day-49_49_null_16,NEXUS_5,1.0,en].png
diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.html_HtmlDocument_null_HtmlDocument-Day-48_48_null_17,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.html_HtmlDocument_null_HtmlDocument-Day-49_49_null_17,NEXUS_5,1.0,en].png
similarity index 100%
rename from tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.html_HtmlDocument_null_HtmlDocument-Day-48_48_null_17,NEXUS_5,1.0,en].png
rename to tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.html_HtmlDocument_null_HtmlDocument-Day-49_49_null_17,NEXUS_5,1.0,en].png
diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.html_HtmlDocument_null_HtmlDocument-Day-48_48_null_18,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.html_HtmlDocument_null_HtmlDocument-Day-49_49_null_18,NEXUS_5,1.0,en].png
similarity index 100%
rename from tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.html_HtmlDocument_null_HtmlDocument-Day-48_48_null_18,NEXUS_5,1.0,en].png
rename to tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.html_HtmlDocument_null_HtmlDocument-Day-49_49_null_18,NEXUS_5,1.0,en].png
diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.html_HtmlDocument_null_HtmlDocument-Day-48_48_null_19,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.html_HtmlDocument_null_HtmlDocument-Day-49_49_null_19,NEXUS_5,1.0,en].png
similarity index 100%
rename from tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.html_HtmlDocument_null_HtmlDocument-Day-48_48_null_19,NEXUS_5,1.0,en].png
rename to tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.html_HtmlDocument_null_HtmlDocument-Day-49_49_null_19,NEXUS_5,1.0,en].png
diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.html_HtmlDocument_null_HtmlDocument-Day-48_48_null_2,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.html_HtmlDocument_null_HtmlDocument-Day-49_49_null_2,NEXUS_5,1.0,en].png
similarity index 100%
rename from tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.html_HtmlDocument_null_HtmlDocument-Day-48_48_null_2,NEXUS_5,1.0,en].png
rename to tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.html_HtmlDocument_null_HtmlDocument-Day-49_49_null_2,NEXUS_5,1.0,en].png
diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.html_HtmlDocument_null_HtmlDocument-Day-48_48_null_20,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.html_HtmlDocument_null_HtmlDocument-Day-49_49_null_20,NEXUS_5,1.0,en].png
similarity index 100%
rename from tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.html_HtmlDocument_null_HtmlDocument-Day-48_48_null_20,NEXUS_5,1.0,en].png
rename to tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.html_HtmlDocument_null_HtmlDocument-Day-49_49_null_20,NEXUS_5,1.0,en].png
diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.html_HtmlDocument_null_HtmlDocument-Day-48_48_null_21,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.html_HtmlDocument_null_HtmlDocument-Day-49_49_null_21,NEXUS_5,1.0,en].png
similarity index 100%
rename from tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.html_HtmlDocument_null_HtmlDocument-Day-48_48_null_21,NEXUS_5,1.0,en].png
rename to tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.html_HtmlDocument_null_HtmlDocument-Day-49_49_null_21,NEXUS_5,1.0,en].png
diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.html_HtmlDocument_null_HtmlDocument-Day-48_48_null_3,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.html_HtmlDocument_null_HtmlDocument-Day-49_49_null_3,NEXUS_5,1.0,en].png
similarity index 100%
rename from tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.html_HtmlDocument_null_HtmlDocument-Day-48_48_null_3,NEXUS_5,1.0,en].png
rename to tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.html_HtmlDocument_null_HtmlDocument-Day-49_49_null_3,NEXUS_5,1.0,en].png
diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.html_HtmlDocument_null_HtmlDocument-Day-48_48_null_4,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.html_HtmlDocument_null_HtmlDocument-Day-49_49_null_4,NEXUS_5,1.0,en].png
similarity index 100%
rename from tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.html_HtmlDocument_null_HtmlDocument-Day-48_48_null_4,NEXUS_5,1.0,en].png
rename to tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.html_HtmlDocument_null_HtmlDocument-Day-49_49_null_4,NEXUS_5,1.0,en].png
diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.html_HtmlDocument_null_HtmlDocument-Day-48_48_null_5,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.html_HtmlDocument_null_HtmlDocument-Day-49_49_null_5,NEXUS_5,1.0,en].png
similarity index 100%
rename from tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.html_HtmlDocument_null_HtmlDocument-Day-48_48_null_5,NEXUS_5,1.0,en].png
rename to tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.html_HtmlDocument_null_HtmlDocument-Day-49_49_null_5,NEXUS_5,1.0,en].png
diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.html_HtmlDocument_null_HtmlDocument-Day-48_48_null_6,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.html_HtmlDocument_null_HtmlDocument-Day-49_49_null_6,NEXUS_5,1.0,en].png
similarity index 100%
rename from tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.html_HtmlDocument_null_HtmlDocument-Day-48_48_null_6,NEXUS_5,1.0,en].png
rename to tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.html_HtmlDocument_null_HtmlDocument-Day-49_49_null_6,NEXUS_5,1.0,en].png
diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.html_HtmlDocument_null_HtmlDocument-Day-48_48_null_7,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.html_HtmlDocument_null_HtmlDocument-Day-49_49_null_7,NEXUS_5,1.0,en].png
similarity index 100%
rename from tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.html_HtmlDocument_null_HtmlDocument-Day-48_48_null_7,NEXUS_5,1.0,en].png
rename to tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.html_HtmlDocument_null_HtmlDocument-Day-49_49_null_7,NEXUS_5,1.0,en].png
diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.html_HtmlDocument_null_HtmlDocument-Day-48_48_null_8,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.html_HtmlDocument_null_HtmlDocument-Day-49_49_null_8,NEXUS_5,1.0,en].png
similarity index 100%
rename from tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.html_HtmlDocument_null_HtmlDocument-Day-48_48_null_8,NEXUS_5,1.0,en].png
rename to tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.html_HtmlDocument_null_HtmlDocument-Day-49_49_null_8,NEXUS_5,1.0,en].png
diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.html_HtmlDocument_null_HtmlDocument-Day-48_48_null_9,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.html_HtmlDocument_null_HtmlDocument-Day-49_49_null_9,NEXUS_5,1.0,en].png
similarity index 100%
rename from tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.html_HtmlDocument_null_HtmlDocument-Day-48_48_null_9,NEXUS_5,1.0,en].png
rename to tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.html_HtmlDocument_null_HtmlDocument-Day-49_49_null_9,NEXUS_5,1.0,en].png
diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.html_HtmlDocument_null_HtmlDocument-Night-48_49_null_0,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.html_HtmlDocument_null_HtmlDocument-Night-49_50_null_0,NEXUS_5,1.0,en].png
similarity index 100%
rename from tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.html_HtmlDocument_null_HtmlDocument-Night-48_49_null_0,NEXUS_5,1.0,en].png
rename to tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.html_HtmlDocument_null_HtmlDocument-Night-49_50_null_0,NEXUS_5,1.0,en].png
diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.html_HtmlDocument_null_HtmlDocument-Night-48_49_null_1,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.html_HtmlDocument_null_HtmlDocument-Night-49_50_null_1,NEXUS_5,1.0,en].png
similarity index 100%
rename from tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.html_HtmlDocument_null_HtmlDocument-Night-48_49_null_1,NEXUS_5,1.0,en].png
rename to tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.html_HtmlDocument_null_HtmlDocument-Night-49_50_null_1,NEXUS_5,1.0,en].png
diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.html_HtmlDocument_null_HtmlDocument-Night-48_49_null_10,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.html_HtmlDocument_null_HtmlDocument-Night-49_50_null_10,NEXUS_5,1.0,en].png
similarity index 100%
rename from tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.html_HtmlDocument_null_HtmlDocument-Night-48_49_null_10,NEXUS_5,1.0,en].png
rename to tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.html_HtmlDocument_null_HtmlDocument-Night-49_50_null_10,NEXUS_5,1.0,en].png
diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.html_HtmlDocument_null_HtmlDocument-Night-48_49_null_11,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.html_HtmlDocument_null_HtmlDocument-Night-49_50_null_11,NEXUS_5,1.0,en].png
similarity index 100%
rename from tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.html_HtmlDocument_null_HtmlDocument-Night-48_49_null_11,NEXUS_5,1.0,en].png
rename to tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.html_HtmlDocument_null_HtmlDocument-Night-49_50_null_11,NEXUS_5,1.0,en].png
diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.html_HtmlDocument_null_HtmlDocument-Night-48_49_null_12,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.html_HtmlDocument_null_HtmlDocument-Night-49_50_null_12,NEXUS_5,1.0,en].png
similarity index 100%
rename from tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.html_HtmlDocument_null_HtmlDocument-Night-48_49_null_12,NEXUS_5,1.0,en].png
rename to tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.html_HtmlDocument_null_HtmlDocument-Night-49_50_null_12,NEXUS_5,1.0,en].png
diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.html_HtmlDocument_null_HtmlDocument-Night-48_49_null_13,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.html_HtmlDocument_null_HtmlDocument-Night-49_50_null_13,NEXUS_5,1.0,en].png
similarity index 100%
rename from tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.html_HtmlDocument_null_HtmlDocument-Night-48_49_null_13,NEXUS_5,1.0,en].png
rename to tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.html_HtmlDocument_null_HtmlDocument-Night-49_50_null_13,NEXUS_5,1.0,en].png
diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.html_HtmlDocument_null_HtmlDocument-Night-48_49_null_14,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.html_HtmlDocument_null_HtmlDocument-Night-49_50_null_14,NEXUS_5,1.0,en].png
similarity index 100%
rename from tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.html_HtmlDocument_null_HtmlDocument-Night-48_49_null_14,NEXUS_5,1.0,en].png
rename to tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.html_HtmlDocument_null_HtmlDocument-Night-49_50_null_14,NEXUS_5,1.0,en].png
diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.html_HtmlDocument_null_HtmlDocument-Night-48_49_null_15,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.html_HtmlDocument_null_HtmlDocument-Night-49_50_null_15,NEXUS_5,1.0,en].png
similarity index 100%
rename from tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.html_HtmlDocument_null_HtmlDocument-Night-48_49_null_15,NEXUS_5,1.0,en].png
rename to tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.html_HtmlDocument_null_HtmlDocument-Night-49_50_null_15,NEXUS_5,1.0,en].png
diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.html_HtmlDocument_null_HtmlDocument-Night-48_49_null_16,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.html_HtmlDocument_null_HtmlDocument-Night-49_50_null_16,NEXUS_5,1.0,en].png
similarity index 100%
rename from tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.html_HtmlDocument_null_HtmlDocument-Night-48_49_null_16,NEXUS_5,1.0,en].png
rename to tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.html_HtmlDocument_null_HtmlDocument-Night-49_50_null_16,NEXUS_5,1.0,en].png
diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.html_HtmlDocument_null_HtmlDocument-Night-48_49_null_17,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.html_HtmlDocument_null_HtmlDocument-Night-49_50_null_17,NEXUS_5,1.0,en].png
similarity index 100%
rename from tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.html_HtmlDocument_null_HtmlDocument-Night-48_49_null_17,NEXUS_5,1.0,en].png
rename to tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.html_HtmlDocument_null_HtmlDocument-Night-49_50_null_17,NEXUS_5,1.0,en].png
diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.html_HtmlDocument_null_HtmlDocument-Night-48_49_null_18,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.html_HtmlDocument_null_HtmlDocument-Night-49_50_null_18,NEXUS_5,1.0,en].png
similarity index 100%
rename from tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.html_HtmlDocument_null_HtmlDocument-Night-48_49_null_18,NEXUS_5,1.0,en].png
rename to tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.html_HtmlDocument_null_HtmlDocument-Night-49_50_null_18,NEXUS_5,1.0,en].png
diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.html_HtmlDocument_null_HtmlDocument-Night-48_49_null_19,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.html_HtmlDocument_null_HtmlDocument-Night-49_50_null_19,NEXUS_5,1.0,en].png
similarity index 100%
rename from tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.html_HtmlDocument_null_HtmlDocument-Night-48_49_null_19,NEXUS_5,1.0,en].png
rename to tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.html_HtmlDocument_null_HtmlDocument-Night-49_50_null_19,NEXUS_5,1.0,en].png
diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.html_HtmlDocument_null_HtmlDocument-Night-48_49_null_2,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.html_HtmlDocument_null_HtmlDocument-Night-49_50_null_2,NEXUS_5,1.0,en].png
similarity index 100%
rename from tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.html_HtmlDocument_null_HtmlDocument-Night-48_49_null_2,NEXUS_5,1.0,en].png
rename to tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.html_HtmlDocument_null_HtmlDocument-Night-49_50_null_2,NEXUS_5,1.0,en].png
diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.html_HtmlDocument_null_HtmlDocument-Night-48_49_null_20,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.html_HtmlDocument_null_HtmlDocument-Night-49_50_null_20,NEXUS_5,1.0,en].png
similarity index 100%
rename from tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.html_HtmlDocument_null_HtmlDocument-Night-48_49_null_20,NEXUS_5,1.0,en].png
rename to tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.html_HtmlDocument_null_HtmlDocument-Night-49_50_null_20,NEXUS_5,1.0,en].png
diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.html_HtmlDocument_null_HtmlDocument-Night-48_49_null_21,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.html_HtmlDocument_null_HtmlDocument-Night-49_50_null_21,NEXUS_5,1.0,en].png
similarity index 100%
rename from tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.html_HtmlDocument_null_HtmlDocument-Night-48_49_null_21,NEXUS_5,1.0,en].png
rename to tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.html_HtmlDocument_null_HtmlDocument-Night-49_50_null_21,NEXUS_5,1.0,en].png
diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.html_HtmlDocument_null_HtmlDocument-Night-48_49_null_3,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.html_HtmlDocument_null_HtmlDocument-Night-49_50_null_3,NEXUS_5,1.0,en].png
similarity index 100%
rename from tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.html_HtmlDocument_null_HtmlDocument-Night-48_49_null_3,NEXUS_5,1.0,en].png
rename to tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.html_HtmlDocument_null_HtmlDocument-Night-49_50_null_3,NEXUS_5,1.0,en].png
diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.html_HtmlDocument_null_HtmlDocument-Night-48_49_null_4,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.html_HtmlDocument_null_HtmlDocument-Night-49_50_null_4,NEXUS_5,1.0,en].png
similarity index 100%
rename from tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.html_HtmlDocument_null_HtmlDocument-Night-48_49_null_4,NEXUS_5,1.0,en].png
rename to tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.html_HtmlDocument_null_HtmlDocument-Night-49_50_null_4,NEXUS_5,1.0,en].png
diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.html_HtmlDocument_null_HtmlDocument-Night-48_49_null_5,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.html_HtmlDocument_null_HtmlDocument-Night-49_50_null_5,NEXUS_5,1.0,en].png
similarity index 100%
rename from tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.html_HtmlDocument_null_HtmlDocument-Night-48_49_null_5,NEXUS_5,1.0,en].png
rename to tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.html_HtmlDocument_null_HtmlDocument-Night-49_50_null_5,NEXUS_5,1.0,en].png
diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.html_HtmlDocument_null_HtmlDocument-Night-48_49_null_6,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.html_HtmlDocument_null_HtmlDocument-Night-49_50_null_6,NEXUS_5,1.0,en].png
similarity index 100%
rename from tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.html_HtmlDocument_null_HtmlDocument-Night-48_49_null_6,NEXUS_5,1.0,en].png
rename to tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.html_HtmlDocument_null_HtmlDocument-Night-49_50_null_6,NEXUS_5,1.0,en].png
diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.html_HtmlDocument_null_HtmlDocument-Night-48_49_null_7,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.html_HtmlDocument_null_HtmlDocument-Night-49_50_null_7,NEXUS_5,1.0,en].png
similarity index 100%
rename from tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.html_HtmlDocument_null_HtmlDocument-Night-48_49_null_7,NEXUS_5,1.0,en].png
rename to tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.html_HtmlDocument_null_HtmlDocument-Night-49_50_null_7,NEXUS_5,1.0,en].png
diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.html_HtmlDocument_null_HtmlDocument-Night-48_49_null_8,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.html_HtmlDocument_null_HtmlDocument-Night-49_50_null_8,NEXUS_5,1.0,en].png
similarity index 100%
rename from tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.html_HtmlDocument_null_HtmlDocument-Night-48_49_null_8,NEXUS_5,1.0,en].png
rename to tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.html_HtmlDocument_null_HtmlDocument-Night-49_50_null_8,NEXUS_5,1.0,en].png
diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.html_HtmlDocument_null_HtmlDocument-Night-48_49_null_9,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.html_HtmlDocument_null_HtmlDocument-Night-49_50_null_9,NEXUS_5,1.0,en].png
similarity index 100%
rename from tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.html_HtmlDocument_null_HtmlDocument-Night-48_49_null_9,NEXUS_5,1.0,en].png
rename to tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.html_HtmlDocument_null_HtmlDocument-Night-49_50_null_9,NEXUS_5,1.0,en].png
diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.reactionsummary_SheetContent_null_SheetContent-Day-49_49_null_0,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.reactionsummary_SheetContent_null_SheetContent-Day-50_50_null_0,NEXUS_5,1.0,en].png
similarity index 100%
rename from tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.reactionsummary_SheetContent_null_SheetContent-Day-49_49_null_0,NEXUS_5,1.0,en].png
rename to tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.reactionsummary_SheetContent_null_SheetContent-Day-50_50_null_0,NEXUS_5,1.0,en].png
diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.reactionsummary_SheetContent_null_SheetContent-Night-49_50_null_0,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.reactionsummary_SheetContent_null_SheetContent-Night-50_51_null_0,NEXUS_5,1.0,en].png
similarity index 100%
rename from tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.reactionsummary_SheetContent_null_SheetContent-Night-49_50_null_0,NEXUS_5,1.0,en].png
rename to tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.reactionsummary_SheetContent_null_SheetContent-Night-50_51_null_0,NEXUS_5,1.0,en].png
diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.receipt.bottomsheet_ReadReceiptBottomSheet_null_ReadReceiptBottomSheet-Day-51_51_null_0,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.receipt.bottomsheet_ReadReceiptBottomSheet_null_ReadReceiptBottomSheet-Day-52_52_null_0,NEXUS_5,1.0,en].png
similarity index 100%
rename from tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.receipt.bottomsheet_ReadReceiptBottomSheet_null_ReadReceiptBottomSheet-Day-51_51_null_0,NEXUS_5,1.0,en].png
rename to tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.receipt.bottomsheet_ReadReceiptBottomSheet_null_ReadReceiptBottomSheet-Day-52_52_null_0,NEXUS_5,1.0,en].png
diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.receipt.bottomsheet_ReadReceiptBottomSheet_null_ReadReceiptBottomSheet-Day-51_51_null_1,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.receipt.bottomsheet_ReadReceiptBottomSheet_null_ReadReceiptBottomSheet-Day-52_52_null_1,NEXUS_5,1.0,en].png
similarity index 100%
rename from tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.receipt.bottomsheet_ReadReceiptBottomSheet_null_ReadReceiptBottomSheet-Day-51_51_null_1,NEXUS_5,1.0,en].png
rename to tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.receipt.bottomsheet_ReadReceiptBottomSheet_null_ReadReceiptBottomSheet-Day-52_52_null_1,NEXUS_5,1.0,en].png
diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.receipt.bottomsheet_ReadReceiptBottomSheet_null_ReadReceiptBottomSheet-Day-51_51_null_2,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.receipt.bottomsheet_ReadReceiptBottomSheet_null_ReadReceiptBottomSheet-Day-52_52_null_2,NEXUS_5,1.0,en].png
similarity index 100%
rename from tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.receipt.bottomsheet_ReadReceiptBottomSheet_null_ReadReceiptBottomSheet-Day-51_51_null_2,NEXUS_5,1.0,en].png
rename to tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.receipt.bottomsheet_ReadReceiptBottomSheet_null_ReadReceiptBottomSheet-Day-52_52_null_2,NEXUS_5,1.0,en].png
diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.receipt.bottomsheet_ReadReceiptBottomSheet_null_ReadReceiptBottomSheet-Day-51_51_null_3,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.receipt.bottomsheet_ReadReceiptBottomSheet_null_ReadReceiptBottomSheet-Day-52_52_null_3,NEXUS_5,1.0,en].png
similarity index 100%
rename from tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.receipt.bottomsheet_ReadReceiptBottomSheet_null_ReadReceiptBottomSheet-Day-51_51_null_3,NEXUS_5,1.0,en].png
rename to tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.receipt.bottomsheet_ReadReceiptBottomSheet_null_ReadReceiptBottomSheet-Day-52_52_null_3,NEXUS_5,1.0,en].png
diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.receipt.bottomsheet_ReadReceiptBottomSheet_null_ReadReceiptBottomSheet-Day-51_51_null_4,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.receipt.bottomsheet_ReadReceiptBottomSheet_null_ReadReceiptBottomSheet-Day-52_52_null_4,NEXUS_5,1.0,en].png
similarity index 100%
rename from tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.receipt.bottomsheet_ReadReceiptBottomSheet_null_ReadReceiptBottomSheet-Day-51_51_null_4,NEXUS_5,1.0,en].png
rename to tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.receipt.bottomsheet_ReadReceiptBottomSheet_null_ReadReceiptBottomSheet-Day-52_52_null_4,NEXUS_5,1.0,en].png
diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.receipt.bottomsheet_ReadReceiptBottomSheet_null_ReadReceiptBottomSheet-Day-51_51_null_5,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.receipt.bottomsheet_ReadReceiptBottomSheet_null_ReadReceiptBottomSheet-Day-52_52_null_5,NEXUS_5,1.0,en].png
similarity index 100%
rename from tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.receipt.bottomsheet_ReadReceiptBottomSheet_null_ReadReceiptBottomSheet-Day-51_51_null_5,NEXUS_5,1.0,en].png
rename to tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.receipt.bottomsheet_ReadReceiptBottomSheet_null_ReadReceiptBottomSheet-Day-52_52_null_5,NEXUS_5,1.0,en].png
diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.receipt.bottomsheet_ReadReceiptBottomSheet_null_ReadReceiptBottomSheet-Night-51_52_null_0,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.receipt.bottomsheet_ReadReceiptBottomSheet_null_ReadReceiptBottomSheet-Night-52_53_null_0,NEXUS_5,1.0,en].png
similarity index 100%
rename from tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.receipt.bottomsheet_ReadReceiptBottomSheet_null_ReadReceiptBottomSheet-Night-51_52_null_0,NEXUS_5,1.0,en].png
rename to tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.receipt.bottomsheet_ReadReceiptBottomSheet_null_ReadReceiptBottomSheet-Night-52_53_null_0,NEXUS_5,1.0,en].png
diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.receipt.bottomsheet_ReadReceiptBottomSheet_null_ReadReceiptBottomSheet-Night-51_52_null_1,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.receipt.bottomsheet_ReadReceiptBottomSheet_null_ReadReceiptBottomSheet-Night-52_53_null_1,NEXUS_5,1.0,en].png
similarity index 100%
rename from tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.receipt.bottomsheet_ReadReceiptBottomSheet_null_ReadReceiptBottomSheet-Night-51_52_null_1,NEXUS_5,1.0,en].png
rename to tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.receipt.bottomsheet_ReadReceiptBottomSheet_null_ReadReceiptBottomSheet-Night-52_53_null_1,NEXUS_5,1.0,en].png
diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.receipt.bottomsheet_ReadReceiptBottomSheet_null_ReadReceiptBottomSheet-Night-51_52_null_2,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.receipt.bottomsheet_ReadReceiptBottomSheet_null_ReadReceiptBottomSheet-Night-52_53_null_2,NEXUS_5,1.0,en].png
similarity index 100%
rename from tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.receipt.bottomsheet_ReadReceiptBottomSheet_null_ReadReceiptBottomSheet-Night-51_52_null_2,NEXUS_5,1.0,en].png
rename to tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.receipt.bottomsheet_ReadReceiptBottomSheet_null_ReadReceiptBottomSheet-Night-52_53_null_2,NEXUS_5,1.0,en].png
diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.receipt.bottomsheet_ReadReceiptBottomSheet_null_ReadReceiptBottomSheet-Night-51_52_null_3,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.receipt.bottomsheet_ReadReceiptBottomSheet_null_ReadReceiptBottomSheet-Night-52_53_null_3,NEXUS_5,1.0,en].png
similarity index 100%
rename from tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.receipt.bottomsheet_ReadReceiptBottomSheet_null_ReadReceiptBottomSheet-Night-51_52_null_3,NEXUS_5,1.0,en].png
rename to tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.receipt.bottomsheet_ReadReceiptBottomSheet_null_ReadReceiptBottomSheet-Night-52_53_null_3,NEXUS_5,1.0,en].png
diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.receipt.bottomsheet_ReadReceiptBottomSheet_null_ReadReceiptBottomSheet-Night-51_52_null_4,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.receipt.bottomsheet_ReadReceiptBottomSheet_null_ReadReceiptBottomSheet-Night-52_53_null_4,NEXUS_5,1.0,en].png
similarity index 100%
rename from tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.receipt.bottomsheet_ReadReceiptBottomSheet_null_ReadReceiptBottomSheet-Night-51_52_null_4,NEXUS_5,1.0,en].png
rename to tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.receipt.bottomsheet_ReadReceiptBottomSheet_null_ReadReceiptBottomSheet-Night-52_53_null_4,NEXUS_5,1.0,en].png
diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.receipt.bottomsheet_ReadReceiptBottomSheet_null_ReadReceiptBottomSheet-Night-51_52_null_5,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.receipt.bottomsheet_ReadReceiptBottomSheet_null_ReadReceiptBottomSheet-Night-52_53_null_5,NEXUS_5,1.0,en].png
similarity index 100%
rename from tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.receipt.bottomsheet_ReadReceiptBottomSheet_null_ReadReceiptBottomSheet-Night-51_52_null_5,NEXUS_5,1.0,en].png
rename to tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.receipt.bottomsheet_ReadReceiptBottomSheet_null_ReadReceiptBottomSheet-Night-52_53_null_5,NEXUS_5,1.0,en].png
diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.receipt_TimelineItemReactionsView_null_TimelineItemReactionsView-Day-50_50_null_0,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.receipt_TimelineItemReactionsView_null_TimelineItemReactionsView-Day-51_51_null_0,NEXUS_5,1.0,en].png
similarity index 100%
rename from tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.receipt_TimelineItemReactionsView_null_TimelineItemReactionsView-Day-50_50_null_0,NEXUS_5,1.0,en].png
rename to tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.receipt_TimelineItemReactionsView_null_TimelineItemReactionsView-Day-51_51_null_0,NEXUS_5,1.0,en].png
diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.receipt_TimelineItemReactionsView_null_TimelineItemReactionsView-Day-50_50_null_1,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.receipt_TimelineItemReactionsView_null_TimelineItemReactionsView-Day-51_51_null_1,NEXUS_5,1.0,en].png
similarity index 100%
rename from tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.receipt_TimelineItemReactionsView_null_TimelineItemReactionsView-Day-50_50_null_1,NEXUS_5,1.0,en].png
rename to tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.receipt_TimelineItemReactionsView_null_TimelineItemReactionsView-Day-51_51_null_1,NEXUS_5,1.0,en].png
diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.receipt_TimelineItemReactionsView_null_TimelineItemReactionsView-Day-50_50_null_2,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.receipt_TimelineItemReactionsView_null_TimelineItemReactionsView-Day-51_51_null_2,NEXUS_5,1.0,en].png
similarity index 100%
rename from tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.receipt_TimelineItemReactionsView_null_TimelineItemReactionsView-Day-50_50_null_2,NEXUS_5,1.0,en].png
rename to tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.receipt_TimelineItemReactionsView_null_TimelineItemReactionsView-Day-51_51_null_2,NEXUS_5,1.0,en].png
diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.receipt_TimelineItemReactionsView_null_TimelineItemReactionsView-Day-50_50_null_3,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.receipt_TimelineItemReactionsView_null_TimelineItemReactionsView-Day-51_51_null_3,NEXUS_5,1.0,en].png
similarity index 100%
rename from tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.receipt_TimelineItemReactionsView_null_TimelineItemReactionsView-Day-50_50_null_3,NEXUS_5,1.0,en].png
rename to tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.receipt_TimelineItemReactionsView_null_TimelineItemReactionsView-Day-51_51_null_3,NEXUS_5,1.0,en].png
diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.receipt_TimelineItemReactionsView_null_TimelineItemReactionsView-Day-50_50_null_4,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.receipt_TimelineItemReactionsView_null_TimelineItemReactionsView-Day-51_51_null_4,NEXUS_5,1.0,en].png
similarity index 100%
rename from tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.receipt_TimelineItemReactionsView_null_TimelineItemReactionsView-Day-50_50_null_4,NEXUS_5,1.0,en].png
rename to tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.receipt_TimelineItemReactionsView_null_TimelineItemReactionsView-Day-51_51_null_4,NEXUS_5,1.0,en].png
diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.receipt_TimelineItemReactionsView_null_TimelineItemReactionsView-Day-50_50_null_5,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.receipt_TimelineItemReactionsView_null_TimelineItemReactionsView-Day-51_51_null_5,NEXUS_5,1.0,en].png
similarity index 100%
rename from tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.receipt_TimelineItemReactionsView_null_TimelineItemReactionsView-Day-50_50_null_5,NEXUS_5,1.0,en].png
rename to tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.receipt_TimelineItemReactionsView_null_TimelineItemReactionsView-Day-51_51_null_5,NEXUS_5,1.0,en].png
diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.receipt_TimelineItemReactionsView_null_TimelineItemReactionsView-Day-50_50_null_6,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.receipt_TimelineItemReactionsView_null_TimelineItemReactionsView-Day-51_51_null_6,NEXUS_5,1.0,en].png
similarity index 100%
rename from tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.receipt_TimelineItemReactionsView_null_TimelineItemReactionsView-Day-50_50_null_6,NEXUS_5,1.0,en].png
rename to tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.receipt_TimelineItemReactionsView_null_TimelineItemReactionsView-Day-51_51_null_6,NEXUS_5,1.0,en].png
diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.receipt_TimelineItemReactionsView_null_TimelineItemReactionsView-Day-50_50_null_7,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.receipt_TimelineItemReactionsView_null_TimelineItemReactionsView-Day-51_51_null_7,NEXUS_5,1.0,en].png
similarity index 100%
rename from tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.receipt_TimelineItemReactionsView_null_TimelineItemReactionsView-Day-50_50_null_7,NEXUS_5,1.0,en].png
rename to tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.receipt_TimelineItemReactionsView_null_TimelineItemReactionsView-Day-51_51_null_7,NEXUS_5,1.0,en].png
diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.receipt_TimelineItemReactionsView_null_TimelineItemReactionsView-Night-50_51_null_0,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.receipt_TimelineItemReactionsView_null_TimelineItemReactionsView-Night-51_52_null_0,NEXUS_5,1.0,en].png
similarity index 100%
rename from tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.receipt_TimelineItemReactionsView_null_TimelineItemReactionsView-Night-50_51_null_0,NEXUS_5,1.0,en].png
rename to tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.receipt_TimelineItemReactionsView_null_TimelineItemReactionsView-Night-51_52_null_0,NEXUS_5,1.0,en].png
diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.receipt_TimelineItemReactionsView_null_TimelineItemReactionsView-Night-50_51_null_1,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.receipt_TimelineItemReactionsView_null_TimelineItemReactionsView-Night-51_52_null_1,NEXUS_5,1.0,en].png
similarity index 100%
rename from tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.receipt_TimelineItemReactionsView_null_TimelineItemReactionsView-Night-50_51_null_1,NEXUS_5,1.0,en].png
rename to tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.receipt_TimelineItemReactionsView_null_TimelineItemReactionsView-Night-51_52_null_1,NEXUS_5,1.0,en].png
diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.receipt_TimelineItemReactionsView_null_TimelineItemReactionsView-Night-50_51_null_2,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.receipt_TimelineItemReactionsView_null_TimelineItemReactionsView-Night-51_52_null_2,NEXUS_5,1.0,en].png
similarity index 100%
rename from tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.receipt_TimelineItemReactionsView_null_TimelineItemReactionsView-Night-50_51_null_2,NEXUS_5,1.0,en].png
rename to tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.receipt_TimelineItemReactionsView_null_TimelineItemReactionsView-Night-51_52_null_2,NEXUS_5,1.0,en].png
diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.receipt_TimelineItemReactionsView_null_TimelineItemReactionsView-Night-50_51_null_3,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.receipt_TimelineItemReactionsView_null_TimelineItemReactionsView-Night-51_52_null_3,NEXUS_5,1.0,en].png
similarity index 100%
rename from tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.receipt_TimelineItemReactionsView_null_TimelineItemReactionsView-Night-50_51_null_3,NEXUS_5,1.0,en].png
rename to tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.receipt_TimelineItemReactionsView_null_TimelineItemReactionsView-Night-51_52_null_3,NEXUS_5,1.0,en].png
diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.receipt_TimelineItemReactionsView_null_TimelineItemReactionsView-Night-50_51_null_4,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.receipt_TimelineItemReactionsView_null_TimelineItemReactionsView-Night-51_52_null_4,NEXUS_5,1.0,en].png
similarity index 100%
rename from tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.receipt_TimelineItemReactionsView_null_TimelineItemReactionsView-Night-50_51_null_4,NEXUS_5,1.0,en].png
rename to tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.receipt_TimelineItemReactionsView_null_TimelineItemReactionsView-Night-51_52_null_4,NEXUS_5,1.0,en].png
diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.receipt_TimelineItemReactionsView_null_TimelineItemReactionsView-Night-50_51_null_5,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.receipt_TimelineItemReactionsView_null_TimelineItemReactionsView-Night-51_52_null_5,NEXUS_5,1.0,en].png
similarity index 100%
rename from tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.receipt_TimelineItemReactionsView_null_TimelineItemReactionsView-Night-50_51_null_5,NEXUS_5,1.0,en].png
rename to tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.receipt_TimelineItemReactionsView_null_TimelineItemReactionsView-Night-51_52_null_5,NEXUS_5,1.0,en].png
diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.receipt_TimelineItemReactionsView_null_TimelineItemReactionsView-Night-50_51_null_6,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.receipt_TimelineItemReactionsView_null_TimelineItemReactionsView-Night-51_52_null_6,NEXUS_5,1.0,en].png
similarity index 100%
rename from tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.receipt_TimelineItemReactionsView_null_TimelineItemReactionsView-Night-50_51_null_6,NEXUS_5,1.0,en].png
rename to tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.receipt_TimelineItemReactionsView_null_TimelineItemReactionsView-Night-51_52_null_6,NEXUS_5,1.0,en].png
diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.receipt_TimelineItemReactionsView_null_TimelineItemReactionsView-Night-50_51_null_7,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.receipt_TimelineItemReactionsView_null_TimelineItemReactionsView-Night-51_52_null_7,NEXUS_5,1.0,en].png
similarity index 100%
rename from tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.receipt_TimelineItemReactionsView_null_TimelineItemReactionsView-Night-50_51_null_7,NEXUS_5,1.0,en].png
rename to tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.receipt_TimelineItemReactionsView_null_TimelineItemReactionsView-Night-51_52_null_7,NEXUS_5,1.0,en].png
diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.retrysendmenu_RetrySendMessageMenu_null_RetrySendMessageMenu-Day-52_52_null_0,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.retrysendmenu_RetrySendMessageMenu_null_RetrySendMessageMenu-Day-53_53_null_0,NEXUS_5,1.0,en].png
similarity index 100%
rename from tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.retrysendmenu_RetrySendMessageMenu_null_RetrySendMessageMenu-Day-52_52_null_0,NEXUS_5,1.0,en].png
rename to tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.retrysendmenu_RetrySendMessageMenu_null_RetrySendMessageMenu-Day-53_53_null_0,NEXUS_5,1.0,en].png
diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.retrysendmenu_RetrySendMessageMenu_null_RetrySendMessageMenu-Day-52_52_null_1,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.retrysendmenu_RetrySendMessageMenu_null_RetrySendMessageMenu-Day-53_53_null_1,NEXUS_5,1.0,en].png
similarity index 100%
rename from tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.retrysendmenu_RetrySendMessageMenu_null_RetrySendMessageMenu-Day-52_52_null_1,NEXUS_5,1.0,en].png
rename to tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.retrysendmenu_RetrySendMessageMenu_null_RetrySendMessageMenu-Day-53_53_null_1,NEXUS_5,1.0,en].png
diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.retrysendmenu_RetrySendMessageMenu_null_RetrySendMessageMenu-Night-52_53_null_0,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.retrysendmenu_RetrySendMessageMenu_null_RetrySendMessageMenu-Night-53_54_null_0,NEXUS_5,1.0,en].png
similarity index 100%
rename from tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.retrysendmenu_RetrySendMessageMenu_null_RetrySendMessageMenu-Night-52_53_null_0,NEXUS_5,1.0,en].png
rename to tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.retrysendmenu_RetrySendMessageMenu_null_RetrySendMessageMenu-Night-53_54_null_0,NEXUS_5,1.0,en].png
diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.retrysendmenu_RetrySendMessageMenu_null_RetrySendMessageMenu-Night-52_53_null_1,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.retrysendmenu_RetrySendMessageMenu_null_RetrySendMessageMenu-Night-53_54_null_1,NEXUS_5,1.0,en].png
similarity index 100%
rename from tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.retrysendmenu_RetrySendMessageMenu_null_RetrySendMessageMenu-Night-52_53_null_1,NEXUS_5,1.0,en].png
rename to tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.retrysendmenu_RetrySendMessageMenu_null_RetrySendMessageMenu-Night-53_54_null_1,NEXUS_5,1.0,en].png
diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.virtual_EncryptedHistoryBannerView_null_EncryptedHistoryBannerView-Day-53_53_null_0,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.virtual_EncryptedHistoryBannerView_null_EncryptedHistoryBannerView-Day-54_54_null_0,NEXUS_5,1.0,en].png
similarity index 100%
rename from tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.virtual_EncryptedHistoryBannerView_null_EncryptedHistoryBannerView-Day-53_53_null_0,NEXUS_5,1.0,en].png
rename to tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.virtual_EncryptedHistoryBannerView_null_EncryptedHistoryBannerView-Day-54_54_null_0,NEXUS_5,1.0,en].png
diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.virtual_EncryptedHistoryBannerView_null_EncryptedHistoryBannerView-Day-53_53_null_1,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.virtual_EncryptedHistoryBannerView_null_EncryptedHistoryBannerView-Day-54_54_null_1,NEXUS_5,1.0,en].png
similarity index 100%
rename from tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.virtual_EncryptedHistoryBannerView_null_EncryptedHistoryBannerView-Day-53_53_null_1,NEXUS_5,1.0,en].png
rename to tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.virtual_EncryptedHistoryBannerView_null_EncryptedHistoryBannerView-Day-54_54_null_1,NEXUS_5,1.0,en].png
diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.virtual_EncryptedHistoryBannerView_null_EncryptedHistoryBannerView-Day-53_53_null_2,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.virtual_EncryptedHistoryBannerView_null_EncryptedHistoryBannerView-Day-54_54_null_2,NEXUS_5,1.0,en].png
similarity index 100%
rename from tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.virtual_EncryptedHistoryBannerView_null_EncryptedHistoryBannerView-Day-53_53_null_2,NEXUS_5,1.0,en].png
rename to tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.virtual_EncryptedHistoryBannerView_null_EncryptedHistoryBannerView-Day-54_54_null_2,NEXUS_5,1.0,en].png
diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.virtual_EncryptedHistoryBannerView_null_EncryptedHistoryBannerView-Night-53_54_null_0,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.virtual_EncryptedHistoryBannerView_null_EncryptedHistoryBannerView-Night-54_55_null_0,NEXUS_5,1.0,en].png
similarity index 100%
rename from tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.virtual_EncryptedHistoryBannerView_null_EncryptedHistoryBannerView-Night-53_54_null_0,NEXUS_5,1.0,en].png
rename to tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.virtual_EncryptedHistoryBannerView_null_EncryptedHistoryBannerView-Night-54_55_null_0,NEXUS_5,1.0,en].png
diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.virtual_EncryptedHistoryBannerView_null_EncryptedHistoryBannerView-Night-53_54_null_1,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.virtual_EncryptedHistoryBannerView_null_EncryptedHistoryBannerView-Night-54_55_null_1,NEXUS_5,1.0,en].png
similarity index 100%
rename from tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.virtual_EncryptedHistoryBannerView_null_EncryptedHistoryBannerView-Night-53_54_null_1,NEXUS_5,1.0,en].png
rename to tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.virtual_EncryptedHistoryBannerView_null_EncryptedHistoryBannerView-Night-54_55_null_1,NEXUS_5,1.0,en].png
diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.virtual_EncryptedHistoryBannerView_null_EncryptedHistoryBannerView-Night-53_54_null_2,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.virtual_EncryptedHistoryBannerView_null_EncryptedHistoryBannerView-Night-54_55_null_2,NEXUS_5,1.0,en].png
similarity index 100%
rename from tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.virtual_EncryptedHistoryBannerView_null_EncryptedHistoryBannerView-Night-53_54_null_2,NEXUS_5,1.0,en].png
rename to tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.virtual_EncryptedHistoryBannerView_null_EncryptedHistoryBannerView-Night-54_55_null_2,NEXUS_5,1.0,en].png
diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.virtual_TimelineItemDaySeparatorView_null_TimelineItemDaySeparatorView-Day-54_54_null_0,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.virtual_TimelineItemDaySeparatorView_null_TimelineItemDaySeparatorView-Day-55_55_null_0,NEXUS_5,1.0,en].png
similarity index 100%
rename from tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.virtual_TimelineItemDaySeparatorView_null_TimelineItemDaySeparatorView-Day-54_54_null_0,NEXUS_5,1.0,en].png
rename to tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.virtual_TimelineItemDaySeparatorView_null_TimelineItemDaySeparatorView-Day-55_55_null_0,NEXUS_5,1.0,en].png
diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.virtual_TimelineItemDaySeparatorView_null_TimelineItemDaySeparatorView-Day-54_54_null_1,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.virtual_TimelineItemDaySeparatorView_null_TimelineItemDaySeparatorView-Day-55_55_null_1,NEXUS_5,1.0,en].png
similarity index 100%
rename from tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.virtual_TimelineItemDaySeparatorView_null_TimelineItemDaySeparatorView-Day-54_54_null_1,NEXUS_5,1.0,en].png
rename to tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.virtual_TimelineItemDaySeparatorView_null_TimelineItemDaySeparatorView-Day-55_55_null_1,NEXUS_5,1.0,en].png
diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.virtual_TimelineItemDaySeparatorView_null_TimelineItemDaySeparatorView-Night-54_55_null_0,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.virtual_TimelineItemDaySeparatorView_null_TimelineItemDaySeparatorView-Night-55_56_null_0,NEXUS_5,1.0,en].png
similarity index 100%
rename from tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.virtual_TimelineItemDaySeparatorView_null_TimelineItemDaySeparatorView-Night-54_55_null_0,NEXUS_5,1.0,en].png
rename to tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.virtual_TimelineItemDaySeparatorView_null_TimelineItemDaySeparatorView-Night-55_56_null_0,NEXUS_5,1.0,en].png
diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.virtual_TimelineItemDaySeparatorView_null_TimelineItemDaySeparatorView-Night-54_55_null_1,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.virtual_TimelineItemDaySeparatorView_null_TimelineItemDaySeparatorView-Night-55_56_null_1,NEXUS_5,1.0,en].png
similarity index 100%
rename from tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.virtual_TimelineItemDaySeparatorView_null_TimelineItemDaySeparatorView-Night-54_55_null_1,NEXUS_5,1.0,en].png
rename to tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.virtual_TimelineItemDaySeparatorView_null_TimelineItemDaySeparatorView-Night-55_56_null_1,NEXUS_5,1.0,en].png
diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.virtual_TimelineItemReadMarkerView_null_TimelineItemReadMarkerView-Day-55_55_null,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.virtual_TimelineItemReadMarkerView_null_TimelineItemReadMarkerView-Day-56_56_null,NEXUS_5,1.0,en].png
similarity index 100%
rename from tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.virtual_TimelineItemReadMarkerView_null_TimelineItemReadMarkerView-Day-55_55_null,NEXUS_5,1.0,en].png
rename to tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.virtual_TimelineItemReadMarkerView_null_TimelineItemReadMarkerView-Day-56_56_null,NEXUS_5,1.0,en].png
diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.virtual_TimelineItemReadMarkerView_null_TimelineItemReadMarkerView-Night-55_56_null,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.virtual_TimelineItemReadMarkerView_null_TimelineItemReadMarkerView-Night-56_57_null,NEXUS_5,1.0,en].png
similarity index 100%
rename from tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.virtual_TimelineItemReadMarkerView_null_TimelineItemReadMarkerView-Night-55_56_null,NEXUS_5,1.0,en].png
rename to tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.virtual_TimelineItemReadMarkerView_null_TimelineItemReadMarkerView-Night-56_57_null,NEXUS_5,1.0,en].png
diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.virtual_TimelineItemRoomBeginningView_null_TimelineItemRoomBeginningView-Day-56_56_null,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.virtual_TimelineItemRoomBeginningView_null_TimelineItemRoomBeginningView-Day-57_57_null,NEXUS_5,1.0,en].png
similarity index 100%
rename from tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.virtual_TimelineItemRoomBeginningView_null_TimelineItemRoomBeginningView-Day-56_56_null,NEXUS_5,1.0,en].png
rename to tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.virtual_TimelineItemRoomBeginningView_null_TimelineItemRoomBeginningView-Day-57_57_null,NEXUS_5,1.0,en].png
diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.virtual_TimelineItemRoomBeginningView_null_TimelineItemRoomBeginningView-Night-56_57_null,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.virtual_TimelineItemRoomBeginningView_null_TimelineItemRoomBeginningView-Night-57_58_null,NEXUS_5,1.0,en].png
similarity index 100%
rename from tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.virtual_TimelineItemRoomBeginningView_null_TimelineItemRoomBeginningView-Night-56_57_null,NEXUS_5,1.0,en].png
rename to tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.virtual_TimelineItemRoomBeginningView_null_TimelineItemRoomBeginningView-Night-57_58_null,NEXUS_5,1.0,en].png
diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.virtual_TimelineLoadingMoreIndicator_null_TimelineLoadingMoreIndicator-Day-57_57_null,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.virtual_TimelineLoadingMoreIndicator_null_TimelineLoadingMoreIndicator-Day-58_58_null,NEXUS_5,1.0,en].png
similarity index 100%
rename from tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.virtual_TimelineLoadingMoreIndicator_null_TimelineLoadingMoreIndicator-Day-57_57_null,NEXUS_5,1.0,en].png
rename to tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.virtual_TimelineLoadingMoreIndicator_null_TimelineLoadingMoreIndicator-Day-58_58_null,NEXUS_5,1.0,en].png
diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.virtual_TimelineLoadingMoreIndicator_null_TimelineLoadingMoreIndicator-Night-57_58_null,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.virtual_TimelineLoadingMoreIndicator_null_TimelineLoadingMoreIndicator-Night-58_59_null,NEXUS_5,1.0,en].png
similarity index 100%
rename from tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.virtual_TimelineLoadingMoreIndicator_null_TimelineLoadingMoreIndicator-Night-57_58_null,NEXUS_5,1.0,en].png
rename to tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.virtual_TimelineLoadingMoreIndicator_null_TimelineLoadingMoreIndicator-Night-58_59_null,NEXUS_5,1.0,en].png
diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components_TimelineItemEventRowForDirectRoom_null_TimelineItemEventRowForDirectRoom-Day-17_17_null,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components_TimelineItemEventRowForDirectRoom_null_TimelineItemEventRowForDirectRoom-Day-17_17_null,NEXUS_5,1.0,en].png
new file mode 100644
index 0000000000..789007fe0c
--- /dev/null
+++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components_TimelineItemEventRowForDirectRoom_null_TimelineItemEventRowForDirectRoom-Day-17_17_null,NEXUS_5,1.0,en].png
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:ac57513cabbd198391eccf3421cb8afa346e6503106bb893f6c1c484518ff6c7
+size 151624
diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components_TimelineItemEventRowForDirectRoom_null_TimelineItemEventRowForDirectRoom-Night-17_18_null,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components_TimelineItemEventRowForDirectRoom_null_TimelineItemEventRowForDirectRoom-Night-17_18_null,NEXUS_5,1.0,en].png
new file mode 100644
index 0000000000..0008bb1f14
--- /dev/null
+++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components_TimelineItemEventRowForDirectRoom_null_TimelineItemEventRowForDirectRoom-Night-17_18_null,NEXUS_5,1.0,en].png
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:1ae079566531615abc37d3e430e00207f06ca78e6583f131f82d30c1636800fb
+size 146728
diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components_TimelineItemEventRowTimestamp_null_TimelineItemEventRowTimestamp-Day-17_17_null_0,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components_TimelineItemEventRowTimestamp_null_TimelineItemEventRowTimestamp-Day-18_18_null_0,NEXUS_5,1.0,en].png
similarity index 100%
rename from tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components_TimelineItemEventRowTimestamp_null_TimelineItemEventRowTimestamp-Day-17_17_null_0,NEXUS_5,1.0,en].png
rename to tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components_TimelineItemEventRowTimestamp_null_TimelineItemEventRowTimestamp-Day-18_18_null_0,NEXUS_5,1.0,en].png
diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components_TimelineItemEventRowTimestamp_null_TimelineItemEventRowTimestamp-Day-17_17_null_1,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components_TimelineItemEventRowTimestamp_null_TimelineItemEventRowTimestamp-Day-18_18_null_1,NEXUS_5,1.0,en].png
similarity index 100%
rename from tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components_TimelineItemEventRowTimestamp_null_TimelineItemEventRowTimestamp-Day-17_17_null_1,NEXUS_5,1.0,en].png
rename to tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components_TimelineItemEventRowTimestamp_null_TimelineItemEventRowTimestamp-Day-18_18_null_1,NEXUS_5,1.0,en].png
diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components_TimelineItemEventRowTimestamp_null_TimelineItemEventRowTimestamp-Day-17_17_null_2,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components_TimelineItemEventRowTimestamp_null_TimelineItemEventRowTimestamp-Day-18_18_null_2,NEXUS_5,1.0,en].png
similarity index 100%
rename from tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components_TimelineItemEventRowTimestamp_null_TimelineItemEventRowTimestamp-Day-17_17_null_2,NEXUS_5,1.0,en].png
rename to tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components_TimelineItemEventRowTimestamp_null_TimelineItemEventRowTimestamp-Day-18_18_null_2,NEXUS_5,1.0,en].png
diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components_TimelineItemEventRowTimestamp_null_TimelineItemEventRowTimestamp-Day-17_17_null_3,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components_TimelineItemEventRowTimestamp_null_TimelineItemEventRowTimestamp-Day-18_18_null_3,NEXUS_5,1.0,en].png
similarity index 100%
rename from tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components_TimelineItemEventRowTimestamp_null_TimelineItemEventRowTimestamp-Day-17_17_null_3,NEXUS_5,1.0,en].png
rename to tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components_TimelineItemEventRowTimestamp_null_TimelineItemEventRowTimestamp-Day-18_18_null_3,NEXUS_5,1.0,en].png
diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components_TimelineItemEventRowTimestamp_null_TimelineItemEventRowTimestamp-Night-17_18_null_0,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components_TimelineItemEventRowTimestamp_null_TimelineItemEventRowTimestamp-Night-18_19_null_0,NEXUS_5,1.0,en].png
similarity index 100%
rename from tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components_TimelineItemEventRowTimestamp_null_TimelineItemEventRowTimestamp-Night-17_18_null_0,NEXUS_5,1.0,en].png
rename to tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components_TimelineItemEventRowTimestamp_null_TimelineItemEventRowTimestamp-Night-18_19_null_0,NEXUS_5,1.0,en].png
diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components_TimelineItemEventRowTimestamp_null_TimelineItemEventRowTimestamp-Night-17_18_null_1,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components_TimelineItemEventRowTimestamp_null_TimelineItemEventRowTimestamp-Night-18_19_null_1,NEXUS_5,1.0,en].png
similarity index 100%
rename from tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components_TimelineItemEventRowTimestamp_null_TimelineItemEventRowTimestamp-Night-17_18_null_1,NEXUS_5,1.0,en].png
rename to tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components_TimelineItemEventRowTimestamp_null_TimelineItemEventRowTimestamp-Night-18_19_null_1,NEXUS_5,1.0,en].png
diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components_TimelineItemEventRowTimestamp_null_TimelineItemEventRowTimestamp-Night-17_18_null_2,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components_TimelineItemEventRowTimestamp_null_TimelineItemEventRowTimestamp-Night-18_19_null_2,NEXUS_5,1.0,en].png
similarity index 100%
rename from tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components_TimelineItemEventRowTimestamp_null_TimelineItemEventRowTimestamp-Night-17_18_null_2,NEXUS_5,1.0,en].png
rename to tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components_TimelineItemEventRowTimestamp_null_TimelineItemEventRowTimestamp-Night-18_19_null_2,NEXUS_5,1.0,en].png
diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components_TimelineItemEventRowTimestamp_null_TimelineItemEventRowTimestamp-Night-17_18_null_3,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components_TimelineItemEventRowTimestamp_null_TimelineItemEventRowTimestamp-Night-18_19_null_3,NEXUS_5,1.0,en].png
similarity index 100%
rename from tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components_TimelineItemEventRowTimestamp_null_TimelineItemEventRowTimestamp-Night-17_18_null_3,NEXUS_5,1.0,en].png
rename to tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components_TimelineItemEventRowTimestamp_null_TimelineItemEventRowTimestamp-Night-18_19_null_3,NEXUS_5,1.0,en].png
diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components_TimelineItemEventRowWithManyReactions_null_TimelineItemEventRowWithManyReactions-Day-18_18_null,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components_TimelineItemEventRowWithManyReactions_null_TimelineItemEventRowWithManyReactions-Day-19_19_null,NEXUS_5,1.0,en].png
similarity index 100%
rename from tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components_TimelineItemEventRowWithManyReactions_null_TimelineItemEventRowWithManyReactions-Day-18_18_null,NEXUS_5,1.0,en].png
rename to tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components_TimelineItemEventRowWithManyReactions_null_TimelineItemEventRowWithManyReactions-Day-19_19_null,NEXUS_5,1.0,en].png
diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components_TimelineItemEventRowWithManyReactions_null_TimelineItemEventRowWithManyReactions-Night-18_19_null,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components_TimelineItemEventRowWithManyReactions_null_TimelineItemEventRowWithManyReactions-Night-19_20_null,NEXUS_5,1.0,en].png
similarity index 100%
rename from tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components_TimelineItemEventRowWithManyReactions_null_TimelineItemEventRowWithManyReactions-Night-18_19_null,NEXUS_5,1.0,en].png
rename to tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components_TimelineItemEventRowWithManyReactions_null_TimelineItemEventRowWithManyReactions-Night-19_20_null,NEXUS_5,1.0,en].png
diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components_TimelineItemEventRowWithRR_null_TimelineItemEventRowWithRR-Day-19_19_null_0,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components_TimelineItemEventRowWithRR_null_TimelineItemEventRowWithRR-Day-20_20_null_0,NEXUS_5,1.0,en].png
similarity index 100%
rename from tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components_TimelineItemEventRowWithRR_null_TimelineItemEventRowWithRR-Day-19_19_null_0,NEXUS_5,1.0,en].png
rename to tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components_TimelineItemEventRowWithRR_null_TimelineItemEventRowWithRR-Day-20_20_null_0,NEXUS_5,1.0,en].png
diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components_TimelineItemEventRowWithRR_null_TimelineItemEventRowWithRR-Day-19_19_null_1,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components_TimelineItemEventRowWithRR_null_TimelineItemEventRowWithRR-Day-20_20_null_1,NEXUS_5,1.0,en].png
similarity index 100%
rename from tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components_TimelineItemEventRowWithRR_null_TimelineItemEventRowWithRR-Day-19_19_null_1,NEXUS_5,1.0,en].png
rename to tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components_TimelineItemEventRowWithRR_null_TimelineItemEventRowWithRR-Day-20_20_null_1,NEXUS_5,1.0,en].png
diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components_TimelineItemEventRowWithRR_null_TimelineItemEventRowWithRR-Day-19_19_null_2,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components_TimelineItemEventRowWithRR_null_TimelineItemEventRowWithRR-Day-20_20_null_2,NEXUS_5,1.0,en].png
similarity index 100%
rename from tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components_TimelineItemEventRowWithRR_null_TimelineItemEventRowWithRR-Day-19_19_null_2,NEXUS_5,1.0,en].png
rename to tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components_TimelineItemEventRowWithRR_null_TimelineItemEventRowWithRR-Day-20_20_null_2,NEXUS_5,1.0,en].png
diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components_TimelineItemEventRowWithRR_null_TimelineItemEventRowWithRR-Night-19_20_null_0,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components_TimelineItemEventRowWithRR_null_TimelineItemEventRowWithRR-Night-20_21_null_0,NEXUS_5,1.0,en].png
similarity index 100%
rename from tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components_TimelineItemEventRowWithRR_null_TimelineItemEventRowWithRR-Night-19_20_null_0,NEXUS_5,1.0,en].png
rename to tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components_TimelineItemEventRowWithRR_null_TimelineItemEventRowWithRR-Night-20_21_null_0,NEXUS_5,1.0,en].png
diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components_TimelineItemEventRowWithRR_null_TimelineItemEventRowWithRR-Night-19_20_null_1,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components_TimelineItemEventRowWithRR_null_TimelineItemEventRowWithRR-Night-20_21_null_1,NEXUS_5,1.0,en].png
similarity index 100%
rename from tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components_TimelineItemEventRowWithRR_null_TimelineItemEventRowWithRR-Night-19_20_null_1,NEXUS_5,1.0,en].png
rename to tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components_TimelineItemEventRowWithRR_null_TimelineItemEventRowWithRR-Night-20_21_null_1,NEXUS_5,1.0,en].png
diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components_TimelineItemEventRowWithRR_null_TimelineItemEventRowWithRR-Night-19_20_null_2,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components_TimelineItemEventRowWithRR_null_TimelineItemEventRowWithRR-Night-20_21_null_2,NEXUS_5,1.0,en].png
similarity index 100%
rename from tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components_TimelineItemEventRowWithRR_null_TimelineItemEventRowWithRR-Night-19_20_null_2,NEXUS_5,1.0,en].png
rename to tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components_TimelineItemEventRowWithRR_null_TimelineItemEventRowWithRR-Night-20_21_null_2,NEXUS_5,1.0,en].png
diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components_TimelineItemEventRowWithReply_null_TimelineItemEventRowWithReply-Day-20_20_null_0,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components_TimelineItemEventRowWithReply_null_TimelineItemEventRowWithReply-Day-21_21_null_0,NEXUS_5,1.0,en].png
similarity index 100%
rename from tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components_TimelineItemEventRowWithReply_null_TimelineItemEventRowWithReply-Day-20_20_null_0,NEXUS_5,1.0,en].png
rename to tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components_TimelineItemEventRowWithReply_null_TimelineItemEventRowWithReply-Day-21_21_null_0,NEXUS_5,1.0,en].png
diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components_TimelineItemEventRowWithReply_null_TimelineItemEventRowWithReply-Day-20_20_null_1,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components_TimelineItemEventRowWithReply_null_TimelineItemEventRowWithReply-Day-21_21_null_1,NEXUS_5,1.0,en].png
similarity index 100%
rename from tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components_TimelineItemEventRowWithReply_null_TimelineItemEventRowWithReply-Day-20_20_null_1,NEXUS_5,1.0,en].png
rename to tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components_TimelineItemEventRowWithReply_null_TimelineItemEventRowWithReply-Day-21_21_null_1,NEXUS_5,1.0,en].png
diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components_TimelineItemEventRowWithReply_null_TimelineItemEventRowWithReply-Day-20_20_null_10,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components_TimelineItemEventRowWithReply_null_TimelineItemEventRowWithReply-Day-21_21_null_10,NEXUS_5,1.0,en].png
similarity index 100%
rename from tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components_TimelineItemEventRowWithReply_null_TimelineItemEventRowWithReply-Day-20_20_null_10,NEXUS_5,1.0,en].png
rename to tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components_TimelineItemEventRowWithReply_null_TimelineItemEventRowWithReply-Day-21_21_null_10,NEXUS_5,1.0,en].png
diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components_TimelineItemEventRowWithReply_null_TimelineItemEventRowWithReply-Day-20_20_null_2,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components_TimelineItemEventRowWithReply_null_TimelineItemEventRowWithReply-Day-21_21_null_2,NEXUS_5,1.0,en].png
similarity index 100%
rename from tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components_TimelineItemEventRowWithReply_null_TimelineItemEventRowWithReply-Day-20_20_null_2,NEXUS_5,1.0,en].png
rename to tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components_TimelineItemEventRowWithReply_null_TimelineItemEventRowWithReply-Day-21_21_null_2,NEXUS_5,1.0,en].png
diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components_TimelineItemEventRowWithReply_null_TimelineItemEventRowWithReply-Day-20_20_null_3,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components_TimelineItemEventRowWithReply_null_TimelineItemEventRowWithReply-Day-21_21_null_3,NEXUS_5,1.0,en].png
similarity index 100%
rename from tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components_TimelineItemEventRowWithReply_null_TimelineItemEventRowWithReply-Day-20_20_null_3,NEXUS_5,1.0,en].png
rename to tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components_TimelineItemEventRowWithReply_null_TimelineItemEventRowWithReply-Day-21_21_null_3,NEXUS_5,1.0,en].png
diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components_TimelineItemEventRowWithReply_null_TimelineItemEventRowWithReply-Day-20_20_null_4,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components_TimelineItemEventRowWithReply_null_TimelineItemEventRowWithReply-Day-21_21_null_4,NEXUS_5,1.0,en].png
similarity index 100%
rename from tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components_TimelineItemEventRowWithReply_null_TimelineItemEventRowWithReply-Day-20_20_null_4,NEXUS_5,1.0,en].png
rename to tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components_TimelineItemEventRowWithReply_null_TimelineItemEventRowWithReply-Day-21_21_null_4,NEXUS_5,1.0,en].png
diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components_TimelineItemEventRowWithReply_null_TimelineItemEventRowWithReply-Day-20_20_null_5,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components_TimelineItemEventRowWithReply_null_TimelineItemEventRowWithReply-Day-21_21_null_5,NEXUS_5,1.0,en].png
similarity index 100%
rename from tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components_TimelineItemEventRowWithReply_null_TimelineItemEventRowWithReply-Day-20_20_null_5,NEXUS_5,1.0,en].png
rename to tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components_TimelineItemEventRowWithReply_null_TimelineItemEventRowWithReply-Day-21_21_null_5,NEXUS_5,1.0,en].png
diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components_TimelineItemEventRowWithReply_null_TimelineItemEventRowWithReply-Day-20_20_null_6,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components_TimelineItemEventRowWithReply_null_TimelineItemEventRowWithReply-Day-21_21_null_6,NEXUS_5,1.0,en].png
similarity index 100%
rename from tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components_TimelineItemEventRowWithReply_null_TimelineItemEventRowWithReply-Day-20_20_null_6,NEXUS_5,1.0,en].png
rename to tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components_TimelineItemEventRowWithReply_null_TimelineItemEventRowWithReply-Day-21_21_null_6,NEXUS_5,1.0,en].png
diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components_TimelineItemEventRowWithReply_null_TimelineItemEventRowWithReply-Day-20_20_null_7,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components_TimelineItemEventRowWithReply_null_TimelineItemEventRowWithReply-Day-21_21_null_7,NEXUS_5,1.0,en].png
similarity index 100%
rename from tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components_TimelineItemEventRowWithReply_null_TimelineItemEventRowWithReply-Day-20_20_null_7,NEXUS_5,1.0,en].png
rename to tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components_TimelineItemEventRowWithReply_null_TimelineItemEventRowWithReply-Day-21_21_null_7,NEXUS_5,1.0,en].png
diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components_TimelineItemEventRowWithReply_null_TimelineItemEventRowWithReply-Day-20_20_null_8,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components_TimelineItemEventRowWithReply_null_TimelineItemEventRowWithReply-Day-21_21_null_8,NEXUS_5,1.0,en].png
similarity index 100%
rename from tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components_TimelineItemEventRowWithReply_null_TimelineItemEventRowWithReply-Day-20_20_null_8,NEXUS_5,1.0,en].png
rename to tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components_TimelineItemEventRowWithReply_null_TimelineItemEventRowWithReply-Day-21_21_null_8,NEXUS_5,1.0,en].png
diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components_TimelineItemEventRowWithReply_null_TimelineItemEventRowWithReply-Day-20_20_null_9,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components_TimelineItemEventRowWithReply_null_TimelineItemEventRowWithReply-Day-21_21_null_9,NEXUS_5,1.0,en].png
similarity index 100%
rename from tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components_TimelineItemEventRowWithReply_null_TimelineItemEventRowWithReply-Day-20_20_null_9,NEXUS_5,1.0,en].png
rename to tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components_TimelineItemEventRowWithReply_null_TimelineItemEventRowWithReply-Day-21_21_null_9,NEXUS_5,1.0,en].png
diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components_TimelineItemEventRowWithReply_null_TimelineItemEventRowWithReply-Night-20_21_null_0,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components_TimelineItemEventRowWithReply_null_TimelineItemEventRowWithReply-Night-21_22_null_0,NEXUS_5,1.0,en].png
similarity index 100%
rename from tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components_TimelineItemEventRowWithReply_null_TimelineItemEventRowWithReply-Night-20_21_null_0,NEXUS_5,1.0,en].png
rename to tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components_TimelineItemEventRowWithReply_null_TimelineItemEventRowWithReply-Night-21_22_null_0,NEXUS_5,1.0,en].png
diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components_TimelineItemEventRowWithReply_null_TimelineItemEventRowWithReply-Night-20_21_null_1,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components_TimelineItemEventRowWithReply_null_TimelineItemEventRowWithReply-Night-21_22_null_1,NEXUS_5,1.0,en].png
similarity index 100%
rename from tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components_TimelineItemEventRowWithReply_null_TimelineItemEventRowWithReply-Night-20_21_null_1,NEXUS_5,1.0,en].png
rename to tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components_TimelineItemEventRowWithReply_null_TimelineItemEventRowWithReply-Night-21_22_null_1,NEXUS_5,1.0,en].png
diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components_TimelineItemEventRowWithReply_null_TimelineItemEventRowWithReply-Night-20_21_null_10,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components_TimelineItemEventRowWithReply_null_TimelineItemEventRowWithReply-Night-21_22_null_10,NEXUS_5,1.0,en].png
similarity index 100%
rename from tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components_TimelineItemEventRowWithReply_null_TimelineItemEventRowWithReply-Night-20_21_null_10,NEXUS_5,1.0,en].png
rename to tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components_TimelineItemEventRowWithReply_null_TimelineItemEventRowWithReply-Night-21_22_null_10,NEXUS_5,1.0,en].png
diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components_TimelineItemEventRowWithReply_null_TimelineItemEventRowWithReply-Night-20_21_null_2,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components_TimelineItemEventRowWithReply_null_TimelineItemEventRowWithReply-Night-21_22_null_2,NEXUS_5,1.0,en].png
similarity index 100%
rename from tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components_TimelineItemEventRowWithReply_null_TimelineItemEventRowWithReply-Night-20_21_null_2,NEXUS_5,1.0,en].png
rename to tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components_TimelineItemEventRowWithReply_null_TimelineItemEventRowWithReply-Night-21_22_null_2,NEXUS_5,1.0,en].png
diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components_TimelineItemEventRowWithReply_null_TimelineItemEventRowWithReply-Night-20_21_null_3,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components_TimelineItemEventRowWithReply_null_TimelineItemEventRowWithReply-Night-21_22_null_3,NEXUS_5,1.0,en].png
similarity index 100%
rename from tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components_TimelineItemEventRowWithReply_null_TimelineItemEventRowWithReply-Night-20_21_null_3,NEXUS_5,1.0,en].png
rename to tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components_TimelineItemEventRowWithReply_null_TimelineItemEventRowWithReply-Night-21_22_null_3,NEXUS_5,1.0,en].png
diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components_TimelineItemEventRowWithReply_null_TimelineItemEventRowWithReply-Night-20_21_null_4,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components_TimelineItemEventRowWithReply_null_TimelineItemEventRowWithReply-Night-21_22_null_4,NEXUS_5,1.0,en].png
similarity index 100%
rename from tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components_TimelineItemEventRowWithReply_null_TimelineItemEventRowWithReply-Night-20_21_null_4,NEXUS_5,1.0,en].png
rename to tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components_TimelineItemEventRowWithReply_null_TimelineItemEventRowWithReply-Night-21_22_null_4,NEXUS_5,1.0,en].png
diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components_TimelineItemEventRowWithReply_null_TimelineItemEventRowWithReply-Night-20_21_null_5,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components_TimelineItemEventRowWithReply_null_TimelineItemEventRowWithReply-Night-21_22_null_5,NEXUS_5,1.0,en].png
similarity index 100%
rename from tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components_TimelineItemEventRowWithReply_null_TimelineItemEventRowWithReply-Night-20_21_null_5,NEXUS_5,1.0,en].png
rename to tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components_TimelineItemEventRowWithReply_null_TimelineItemEventRowWithReply-Night-21_22_null_5,NEXUS_5,1.0,en].png
diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components_TimelineItemEventRowWithReply_null_TimelineItemEventRowWithReply-Night-20_21_null_6,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components_TimelineItemEventRowWithReply_null_TimelineItemEventRowWithReply-Night-21_22_null_6,NEXUS_5,1.0,en].png
similarity index 100%
rename from tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components_TimelineItemEventRowWithReply_null_TimelineItemEventRowWithReply-Night-20_21_null_6,NEXUS_5,1.0,en].png
rename to tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components_TimelineItemEventRowWithReply_null_TimelineItemEventRowWithReply-Night-21_22_null_6,NEXUS_5,1.0,en].png
diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components_TimelineItemEventRowWithReply_null_TimelineItemEventRowWithReply-Night-20_21_null_7,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components_TimelineItemEventRowWithReply_null_TimelineItemEventRowWithReply-Night-21_22_null_7,NEXUS_5,1.0,en].png
similarity index 100%
rename from tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components_TimelineItemEventRowWithReply_null_TimelineItemEventRowWithReply-Night-20_21_null_7,NEXUS_5,1.0,en].png
rename to tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components_TimelineItemEventRowWithReply_null_TimelineItemEventRowWithReply-Night-21_22_null_7,NEXUS_5,1.0,en].png
diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components_TimelineItemEventRowWithReply_null_TimelineItemEventRowWithReply-Night-20_21_null_8,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components_TimelineItemEventRowWithReply_null_TimelineItemEventRowWithReply-Night-21_22_null_8,NEXUS_5,1.0,en].png
similarity index 100%
rename from tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components_TimelineItemEventRowWithReply_null_TimelineItemEventRowWithReply-Night-20_21_null_8,NEXUS_5,1.0,en].png
rename to tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components_TimelineItemEventRowWithReply_null_TimelineItemEventRowWithReply-Night-21_22_null_8,NEXUS_5,1.0,en].png
diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components_TimelineItemEventRowWithReply_null_TimelineItemEventRowWithReply-Night-20_21_null_9,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components_TimelineItemEventRowWithReply_null_TimelineItemEventRowWithReply-Night-21_22_null_9,NEXUS_5,1.0,en].png
similarity index 100%
rename from tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components_TimelineItemEventRowWithReply_null_TimelineItemEventRowWithReply-Night-20_21_null_9,NEXUS_5,1.0,en].png
rename to tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components_TimelineItemEventRowWithReply_null_TimelineItemEventRowWithReply-Night-21_22_null_9,NEXUS_5,1.0,en].png
diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components_TimelineItemGroupedEventsRowContentCollapse_null_TimelineItemGroupedEventsRowContentCollapse-Day-22_22_null,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components_TimelineItemGroupedEventsRowContentCollapse_null_TimelineItemGroupedEventsRowContentCollapse-Day-22_22_null,NEXUS_5,1.0,en].png
deleted file mode 100644
index 65f7da1648..0000000000
--- a/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components_TimelineItemGroupedEventsRowContentCollapse_null_TimelineItemGroupedEventsRowContentCollapse-Day-22_22_null,NEXUS_5,1.0,en].png
+++ /dev/null
@@ -1,3 +0,0 @@
-version https://git-lfs.github.com/spec/v1
-oid sha256:2b90128e9c4bd1ff8c0c41ef114738c503270c9761882f8bed234f788b811d30
-size 8884
diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components_TimelineItemGroupedEventsRowContentCollapse_null_TimelineItemGroupedEventsRowContentCollapse-Day-23_23_null,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components_TimelineItemGroupedEventsRowContentCollapse_null_TimelineItemGroupedEventsRowContentCollapse-Day-23_23_null,NEXUS_5,1.0,en].png
new file mode 100644
index 0000000000..49a9557b79
--- /dev/null
+++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components_TimelineItemGroupedEventsRowContentCollapse_null_TimelineItemGroupedEventsRowContentCollapse-Day-23_23_null,NEXUS_5,1.0,en].png
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:61760159b2e8967b5349392935e88fd62353d1f8b8842b4e02090a20b34d7956
+size 8896
diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components_TimelineItemGroupedEventsRowContentCollapse_null_TimelineItemGroupedEventsRowContentCollapse-Night-22_23_null,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components_TimelineItemGroupedEventsRowContentCollapse_null_TimelineItemGroupedEventsRowContentCollapse-Night-22_23_null,NEXUS_5,1.0,en].png
deleted file mode 100644
index 192f2f4e72..0000000000
--- a/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components_TimelineItemGroupedEventsRowContentCollapse_null_TimelineItemGroupedEventsRowContentCollapse-Night-22_23_null,NEXUS_5,1.0,en].png
+++ /dev/null
@@ -1,3 +0,0 @@
-version https://git-lfs.github.com/spec/v1
-oid sha256:154d0c63842b54d5335a16ee45997f169d569e305a682b4b07719b35f793cb56
-size 8988
diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components_TimelineItemGroupedEventsRowContentCollapse_null_TimelineItemGroupedEventsRowContentCollapse-Night-23_24_null,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components_TimelineItemGroupedEventsRowContentCollapse_null_TimelineItemGroupedEventsRowContentCollapse-Night-23_24_null,NEXUS_5,1.0,en].png
new file mode 100644
index 0000000000..af82f3930d
--- /dev/null
+++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components_TimelineItemGroupedEventsRowContentCollapse_null_TimelineItemGroupedEventsRowContentCollapse-Night-23_24_null,NEXUS_5,1.0,en].png
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:65d4b7b84353c27830048ff783e1f1cf99e81b23bac46152ec17c16dcb63546c
+size 8994
diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components_TimelineItemGroupedEventsRowContentExpanded_null_TimelineItemGroupedEventsRowContentExpanded-Day-21_21_null,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components_TimelineItemGroupedEventsRowContentExpanded_null_TimelineItemGroupedEventsRowContentExpanded-Day-21_21_null,NEXUS_5,1.0,en].png
deleted file mode 100644
index a07840d3b0..0000000000
--- a/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components_TimelineItemGroupedEventsRowContentExpanded_null_TimelineItemGroupedEventsRowContentExpanded-Day-21_21_null,NEXUS_5,1.0,en].png
+++ /dev/null
@@ -1,3 +0,0 @@
-version https://git-lfs.github.com/spec/v1
-oid sha256:ea21e9a1c33ef17c9d3b6c43168c1da3e2f7da71f67d1d7db6422d7f6387409f
-size 14551
diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components_TimelineItemGroupedEventsRowContentExpanded_null_TimelineItemGroupedEventsRowContentExpanded-Day-22_22_null,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components_TimelineItemGroupedEventsRowContentExpanded_null_TimelineItemGroupedEventsRowContentExpanded-Day-22_22_null,NEXUS_5,1.0,en].png
new file mode 100644
index 0000000000..a61015babf
--- /dev/null
+++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components_TimelineItemGroupedEventsRowContentExpanded_null_TimelineItemGroupedEventsRowContentExpanded-Day-22_22_null,NEXUS_5,1.0,en].png
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:16fb79b80d6dc1cd032bdc4383be80d6ed0f4eddf4bf42e95e28cc5c92635154
+size 14560
diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components_TimelineItemGroupedEventsRowContentExpanded_null_TimelineItemGroupedEventsRowContentExpanded-Night-21_22_null,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components_TimelineItemGroupedEventsRowContentExpanded_null_TimelineItemGroupedEventsRowContentExpanded-Night-21_22_null,NEXUS_5,1.0,en].png
deleted file mode 100644
index e388fc3eaf..0000000000
--- a/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components_TimelineItemGroupedEventsRowContentExpanded_null_TimelineItemGroupedEventsRowContentExpanded-Night-21_22_null,NEXUS_5,1.0,en].png
+++ /dev/null
@@ -1,3 +0,0 @@
-version https://git-lfs.github.com/spec/v1
-oid sha256:5bc67cb31ab08fb10247c4a261e91a83f1b6af8722f2c2820efa0fd9ea85aced
-size 14612
diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components_TimelineItemGroupedEventsRowContentExpanded_null_TimelineItemGroupedEventsRowContentExpanded-Night-22_23_null,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components_TimelineItemGroupedEventsRowContentExpanded_null_TimelineItemGroupedEventsRowContentExpanded-Night-22_23_null,NEXUS_5,1.0,en].png
new file mode 100644
index 0000000000..588014a61b
--- /dev/null
+++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components_TimelineItemGroupedEventsRowContentExpanded_null_TimelineItemGroupedEventsRowContentExpanded-Night-22_23_null,NEXUS_5,1.0,en].png
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:f067cd464e7c14b0034fcfdbe4df3dba2bc95c05b8ac48f6788395f4631dd075
+size 14601
diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components_TimelineItemReactionsLayout_null_TimelineItemReactionsLayout-Day-23_23_null,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components_TimelineItemReactionsLayout_null_TimelineItemReactionsLayout-Day-24_24_null,NEXUS_5,1.0,en].png
similarity index 100%
rename from tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components_TimelineItemReactionsLayout_null_TimelineItemReactionsLayout-Day-23_23_null,NEXUS_5,1.0,en].png
rename to tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components_TimelineItemReactionsLayout_null_TimelineItemReactionsLayout-Day-24_24_null,NEXUS_5,1.0,en].png
diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components_TimelineItemReactionsLayout_null_TimelineItemReactionsLayout-Night-23_24_null,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components_TimelineItemReactionsLayout_null_TimelineItemReactionsLayout-Night-24_25_null,NEXUS_5,1.0,en].png
similarity index 100%
rename from tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components_TimelineItemReactionsLayout_null_TimelineItemReactionsLayout-Night-23_24_null,NEXUS_5,1.0,en].png
rename to tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components_TimelineItemReactionsLayout_null_TimelineItemReactionsLayout-Night-24_25_null,NEXUS_5,1.0,en].png
diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components_TimelineItemReactionsViewFew_null_TimelineItemReactionsViewFew-Day-25_25_null,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components_TimelineItemReactionsViewFew_null_TimelineItemReactionsViewFew-Day-26_26_null,NEXUS_5,1.0,en].png
similarity index 100%
rename from tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components_TimelineItemReactionsViewFew_null_TimelineItemReactionsViewFew-Day-25_25_null,NEXUS_5,1.0,en].png
rename to tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components_TimelineItemReactionsViewFew_null_TimelineItemReactionsViewFew-Day-26_26_null,NEXUS_5,1.0,en].png
diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components_TimelineItemReactionsViewFew_null_TimelineItemReactionsViewFew-Night-25_26_null,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components_TimelineItemReactionsViewFew_null_TimelineItemReactionsViewFew-Night-26_27_null,NEXUS_5,1.0,en].png
similarity index 100%
rename from tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components_TimelineItemReactionsViewFew_null_TimelineItemReactionsViewFew-Night-25_26_null,NEXUS_5,1.0,en].png
rename to tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components_TimelineItemReactionsViewFew_null_TimelineItemReactionsViewFew-Night-26_27_null,NEXUS_5,1.0,en].png
diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components_TimelineItemReactionsViewIncoming_null_TimelineItemReactionsViewIncoming-Day-26_26_null,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components_TimelineItemReactionsViewIncoming_null_TimelineItemReactionsViewIncoming-Day-27_27_null,NEXUS_5,1.0,en].png
similarity index 100%
rename from tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components_TimelineItemReactionsViewIncoming_null_TimelineItemReactionsViewIncoming-Day-26_26_null,NEXUS_5,1.0,en].png
rename to tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components_TimelineItemReactionsViewIncoming_null_TimelineItemReactionsViewIncoming-Day-27_27_null,NEXUS_5,1.0,en].png
diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components_TimelineItemReactionsViewIncoming_null_TimelineItemReactionsViewIncoming-Night-26_27_null,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components_TimelineItemReactionsViewIncoming_null_TimelineItemReactionsViewIncoming-Night-27_28_null,NEXUS_5,1.0,en].png
similarity index 100%
rename from tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components_TimelineItemReactionsViewIncoming_null_TimelineItemReactionsViewIncoming-Night-26_27_null,NEXUS_5,1.0,en].png
rename to tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components_TimelineItemReactionsViewIncoming_null_TimelineItemReactionsViewIncoming-Night-27_28_null,NEXUS_5,1.0,en].png
diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components_TimelineItemReactionsViewOutgoing_null_TimelineItemReactionsViewOutgoing-Day-27_27_null,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components_TimelineItemReactionsViewOutgoing_null_TimelineItemReactionsViewOutgoing-Day-28_28_null,NEXUS_5,1.0,en].png
similarity index 100%
rename from tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components_TimelineItemReactionsViewOutgoing_null_TimelineItemReactionsViewOutgoing-Day-27_27_null,NEXUS_5,1.0,en].png
rename to tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components_TimelineItemReactionsViewOutgoing_null_TimelineItemReactionsViewOutgoing-Day-28_28_null,NEXUS_5,1.0,en].png
diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components_TimelineItemReactionsViewOutgoing_null_TimelineItemReactionsViewOutgoing-Night-27_28_null,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components_TimelineItemReactionsViewOutgoing_null_TimelineItemReactionsViewOutgoing-Night-28_29_null,NEXUS_5,1.0,en].png
similarity index 100%
rename from tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components_TimelineItemReactionsViewOutgoing_null_TimelineItemReactionsViewOutgoing-Night-27_28_null,NEXUS_5,1.0,en].png
rename to tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components_TimelineItemReactionsViewOutgoing_null_TimelineItemReactionsViewOutgoing-Night-28_29_null,NEXUS_5,1.0,en].png
diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components_TimelineItemReactionsView_null_TimelineItemReactionsView-Day-24_24_null,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components_TimelineItemReactionsView_null_TimelineItemReactionsView-Day-25_25_null,NEXUS_5,1.0,en].png
similarity index 100%
rename from tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components_TimelineItemReactionsView_null_TimelineItemReactionsView-Day-24_24_null,NEXUS_5,1.0,en].png
rename to tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components_TimelineItemReactionsView_null_TimelineItemReactionsView-Day-25_25_null,NEXUS_5,1.0,en].png
diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components_TimelineItemReactionsView_null_TimelineItemReactionsView-Night-24_25_null,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components_TimelineItemReactionsView_null_TimelineItemReactionsView-Night-25_26_null,NEXUS_5,1.0,en].png
similarity index 100%
rename from tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components_TimelineItemReactionsView_null_TimelineItemReactionsView-Night-24_25_null,NEXUS_5,1.0,en].png
rename to tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components_TimelineItemReactionsView_null_TimelineItemReactionsView-Night-25_26_null,NEXUS_5,1.0,en].png
diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components_TimelineItemStateEventRow_null_TimelineItemStateEventRow-Day-28_28_null,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components_TimelineItemStateEventRow_null_TimelineItemStateEventRow-Day-29_29_null,NEXUS_5,1.0,en].png
similarity index 100%
rename from tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components_TimelineItemStateEventRow_null_TimelineItemStateEventRow-Day-28_28_null,NEXUS_5,1.0,en].png
rename to tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components_TimelineItemStateEventRow_null_TimelineItemStateEventRow-Day-29_29_null,NEXUS_5,1.0,en].png
diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components_TimelineItemStateEventRow_null_TimelineItemStateEventRow-Night-28_29_null,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components_TimelineItemStateEventRow_null_TimelineItemStateEventRow-Night-29_30_null,NEXUS_5,1.0,en].png
similarity index 100%
rename from tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components_TimelineItemStateEventRow_null_TimelineItemStateEventRow-Night-28_29_null,NEXUS_5,1.0,en].png
rename to tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components_TimelineItemStateEventRow_null_TimelineItemStateEventRow-Night-29_30_null,NEXUS_5,1.0,en].png
diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.debug_EventDebugInfoView_null_EventDebugInfoView-Day-58_58_null,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.debug_EventDebugInfoView_null_EventDebugInfoView-Day-59_59_null,NEXUS_5,1.0,en].png
similarity index 100%
rename from tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.debug_EventDebugInfoView_null_EventDebugInfoView-Day-58_58_null,NEXUS_5,1.0,en].png
rename to tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.debug_EventDebugInfoView_null_EventDebugInfoView-Day-59_59_null,NEXUS_5,1.0,en].png
diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.debug_EventDebugInfoView_null_EventDebugInfoView-Night-58_59_null,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.debug_EventDebugInfoView_null_EventDebugInfoView-Night-59_60_null,NEXUS_5,1.0,en].png
similarity index 100%
rename from tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.debug_EventDebugInfoView_null_EventDebugInfoView-Night-58_59_null,NEXUS_5,1.0,en].png
rename to tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.debug_EventDebugInfoView_null_EventDebugInfoView-Night-59_60_null,NEXUS_5,1.0,en].png
diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline_TimelineView_null_TimelineView-Day-8_8_null_0,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline_TimelineView_null_TimelineView-Day-8_8_null_0,NEXUS_5,1.0,en].png
index a204ecda7c..1c79761f05 100644
--- a/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline_TimelineView_null_TimelineView-Day-8_8_null_0,NEXUS_5,1.0,en].png
+++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline_TimelineView_null_TimelineView-Day-8_8_null_0,NEXUS_5,1.0,en].png
@@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
-oid sha256:63c52c283b0590a42d81a785af8a673b145dcd71727a8bdf11cc12fd435f6c66
-size 52492
+oid sha256:edf895e9fcf992db6a82c58678b441e82480d7aa3bdcd389ecc487c23105b59c
+size 52505
diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline_TimelineView_null_TimelineView-Day-8_8_null_1,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline_TimelineView_null_TimelineView-Day-8_8_null_1,NEXUS_5,1.0,en].png
index 66535ee78f..2a8a434a95 100644
--- a/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline_TimelineView_null_TimelineView-Day-8_8_null_1,NEXUS_5,1.0,en].png
+++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline_TimelineView_null_TimelineView-Day-8_8_null_1,NEXUS_5,1.0,en].png
@@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
-oid sha256:984002d033b8b81ca485a0edc4b4d03760eed41fcdcd3a87f55938ec87cc88db
-size 74726
+oid sha256:a8d8205687fd1c5a7579b3c426ea9547dae4250ba4261cec36f1ef2ea588c982
+size 74730
diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline_TimelineView_null_TimelineView-Day-8_8_null_12,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline_TimelineView_null_TimelineView-Day-8_8_null_12,NEXUS_5,1.0,en].png
index 20913cdf75..54e30ae744 100644
--- a/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline_TimelineView_null_TimelineView-Day-8_8_null_12,NEXUS_5,1.0,en].png
+++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline_TimelineView_null_TimelineView-Day-8_8_null_12,NEXUS_5,1.0,en].png
@@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
-oid sha256:f1ca4acb3d53773cb45e40586588bb91b7faa013292fde952b0781401df18054
-size 53979
+oid sha256:5d0f7cf75caeb2fe64452753afd9e310e645aa15be23b6726f282adb55ad54a2
+size 53987
diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline_TimelineView_null_TimelineView-Day-8_8_null_13,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline_TimelineView_null_TimelineView-Day-8_8_null_13,NEXUS_5,1.0,en].png
index be297bb3da..47af42a833 100644
--- a/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline_TimelineView_null_TimelineView-Day-8_8_null_13,NEXUS_5,1.0,en].png
+++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline_TimelineView_null_TimelineView-Day-8_8_null_13,NEXUS_5,1.0,en].png
@@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
-oid sha256:b4ed2085ac63c2d94b7bcd0e92464f5b2209f9f7500346421c7f594ebf2baa8b
-size 66904
+oid sha256:28266d8283d1e453832c3c88f223edc4be28d84406981f5fe87f254aecc736ca
+size 66910
diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline_TimelineView_null_TimelineView-Day-8_8_null_14,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline_TimelineView_null_TimelineView-Day-8_8_null_14,NEXUS_5,1.0,en].png
index 3fdd2bad13..9b2728a0d9 100644
--- a/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline_TimelineView_null_TimelineView-Day-8_8_null_14,NEXUS_5,1.0,en].png
+++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline_TimelineView_null_TimelineView-Day-8_8_null_14,NEXUS_5,1.0,en].png
@@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
-oid sha256:7ab70caa3587294275ee7e2dd5b34e0b5d85645d017718d1dfe9f077a8dc76b2
-size 50458
+oid sha256:8029f81df796cdc60a9919a1764ee1621b154683cc1fe0c3fff3b9c91806fa7a
+size 50469
diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline_TimelineView_null_TimelineView-Day-8_8_null_15,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline_TimelineView_null_TimelineView-Day-8_8_null_15,NEXUS_5,1.0,en].png
index 20c088df19..d5a17da77b 100644
--- a/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline_TimelineView_null_TimelineView-Day-8_8_null_15,NEXUS_5,1.0,en].png
+++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline_TimelineView_null_TimelineView-Day-8_8_null_15,NEXUS_5,1.0,en].png
@@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
-oid sha256:2c4fb9d68245959dd4ad4df3a65a2ed88937120f5edbfc0244298142b38bd9af
-size 67754
+oid sha256:8ef232876e00b2c9b1448973a0fa5856f4574ce340d4035c9a3f60e41fa99fcb
+size 67758
diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline_TimelineView_null_TimelineView-Day-8_8_null_16,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline_TimelineView_null_TimelineView-Day-8_8_null_16,NEXUS_5,1.0,en].png
index 9b7759b942..1c29f1f108 100644
--- a/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline_TimelineView_null_TimelineView-Day-8_8_null_16,NEXUS_5,1.0,en].png
+++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline_TimelineView_null_TimelineView-Day-8_8_null_16,NEXUS_5,1.0,en].png
@@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
-oid sha256:bd8df43def756f27d22bc6e81038f8246b624d280f8d0c75b24ca4fb86658f10
-size 57555
+oid sha256:083c7dcc7d366172d3d6431f17697a2aa8382a7919d1cf54250ab91d5dd63874
+size 57571
diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline_TimelineView_null_TimelineView-Day-8_8_null_4,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline_TimelineView_null_TimelineView-Day-8_8_null_4,NEXUS_5,1.0,en].png
index 92c2f8ee8d..31cf1c000f 100644
--- a/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline_TimelineView_null_TimelineView-Day-8_8_null_4,NEXUS_5,1.0,en].png
+++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline_TimelineView_null_TimelineView-Day-8_8_null_4,NEXUS_5,1.0,en].png
@@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
-oid sha256:2e1b50da12b09ce80fcc63a695489dbf4f7dc20a5f329b2f7ecdb6daee822f9d
-size 72585
+oid sha256:130f469d7ef167154e708a28fe1b76165cb998334d08479af46046c40c8721af
+size 72592
diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline_TimelineView_null_TimelineView-Day-8_8_null_6,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline_TimelineView_null_TimelineView-Day-8_8_null_6,NEXUS_5,1.0,en].png
index bf772ca4ba..36e54147b1 100644
--- a/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline_TimelineView_null_TimelineView-Day-8_8_null_6,NEXUS_5,1.0,en].png
+++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline_TimelineView_null_TimelineView-Day-8_8_null_6,NEXUS_5,1.0,en].png
@@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
-oid sha256:0fdf9321cca8bc80076e8c071c44911d23a1913117828e63721eec3b5b120702
-size 74702
+oid sha256:dce3e468b31c14d39bcdfe449b837702730efa1ae42b30820c76cbdbd63b7de1
+size 74704
diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline_TimelineView_null_TimelineView-Day-8_8_null_8,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline_TimelineView_null_TimelineView-Day-8_8_null_8,NEXUS_5,1.0,en].png
index 125df25ff2..691959b549 100644
--- a/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline_TimelineView_null_TimelineView-Day-8_8_null_8,NEXUS_5,1.0,en].png
+++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline_TimelineView_null_TimelineView-Day-8_8_null_8,NEXUS_5,1.0,en].png
@@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
-oid sha256:e80cb8546650e737a355203ac441d88e9e118771d0a9752f6468af6aa48bb0bc
-size 57863
+oid sha256:e39e18ebdcd6ed0fb1ca53cf46b990920d26426489c5a4ae904977299beae6e4
+size 57867
diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline_TimelineView_null_TimelineView-Night-8_9_null_0,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline_TimelineView_null_TimelineView-Night-8_9_null_0,NEXUS_5,1.0,en].png
index a05ce865cb..24131d2100 100644
--- a/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline_TimelineView_null_TimelineView-Night-8_9_null_0,NEXUS_5,1.0,en].png
+++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline_TimelineView_null_TimelineView-Night-8_9_null_0,NEXUS_5,1.0,en].png
@@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
-oid sha256:508f29c5d9784610f79c681d49d81f5a337b34ec464d9d4d2f3c37ad8cbbd3f9
-size 50875
+oid sha256:a45cd74d0d4c030672f6ba1ad587fac5ec8dfd9aaa3906aa17748268ea74a232
+size 50883
diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline_TimelineView_null_TimelineView-Night-8_9_null_1,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline_TimelineView_null_TimelineView-Night-8_9_null_1,NEXUS_5,1.0,en].png
index f459df3f61..a9a8ef4cc6 100644
--- a/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline_TimelineView_null_TimelineView-Night-8_9_null_1,NEXUS_5,1.0,en].png
+++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline_TimelineView_null_TimelineView-Night-8_9_null_1,NEXUS_5,1.0,en].png
@@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
-oid sha256:fd561f53b5fd958eaa5fba0034dad7706493444d61fe01791e200338bb4580b3
-size 71539
+oid sha256:62a81a4f33a8a76a2a9864fc522b6fe15765237a96663c8ecc8aca230642a771
+size 71545
diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline_TimelineView_null_TimelineView-Night-8_9_null_12,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline_TimelineView_null_TimelineView-Night-8_9_null_12,NEXUS_5,1.0,en].png
index 82d5797425..b25f6dc396 100644
--- a/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline_TimelineView_null_TimelineView-Night-8_9_null_12,NEXUS_5,1.0,en].png
+++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline_TimelineView_null_TimelineView-Night-8_9_null_12,NEXUS_5,1.0,en].png
@@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
-oid sha256:2e343f38f71c4629f80b4fd9811a53cac07dc6c76a38b18339640321adc8a253
-size 52185
+oid sha256:37e3405d346d421faec0aa0065d220bf757dd3851bb948a716a802ca3c7664a6
+size 52189
diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline_TimelineView_null_TimelineView-Night-8_9_null_13,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline_TimelineView_null_TimelineView-Night-8_9_null_13,NEXUS_5,1.0,en].png
index 2e2daf6207..32b7c884c3 100644
--- a/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline_TimelineView_null_TimelineView-Night-8_9_null_13,NEXUS_5,1.0,en].png
+++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline_TimelineView_null_TimelineView-Night-8_9_null_13,NEXUS_5,1.0,en].png
@@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
-oid sha256:b9a64e74dc5f1ced6e73a33f7b8fbfaaa4ecba3db8007c02bad8bd494bf1eb31
-size 64178
+oid sha256:e472556771fa5cc4253706bce70775664ba85b73566f34542aa580121583f153
+size 64185
diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline_TimelineView_null_TimelineView-Night-8_9_null_14,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline_TimelineView_null_TimelineView-Night-8_9_null_14,NEXUS_5,1.0,en].png
index b86b1f8cb1..140d7fd86c 100644
--- a/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline_TimelineView_null_TimelineView-Night-8_9_null_14,NEXUS_5,1.0,en].png
+++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline_TimelineView_null_TimelineView-Night-8_9_null_14,NEXUS_5,1.0,en].png
@@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
-oid sha256:8fdf0a733ce2417006388fd3143d937f8e3de5b3ebb44c916d5be532dc977506
-size 49021
+oid sha256:2aa310bd7a292b7958b4e87bceaaac1616e3b418134ad6337d84dd221663a3c9
+size 49023
diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline_TimelineView_null_TimelineView-Night-8_9_null_15,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline_TimelineView_null_TimelineView-Night-8_9_null_15,NEXUS_5,1.0,en].png
index 7dbf56639c..7647372468 100644
--- a/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline_TimelineView_null_TimelineView-Night-8_9_null_15,NEXUS_5,1.0,en].png
+++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline_TimelineView_null_TimelineView-Night-8_9_null_15,NEXUS_5,1.0,en].png
@@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
-oid sha256:3b2f56ea59bebce67ce5fd490ab92f195f561dcab57b3b25859aa40773b8092c
-size 64920
+oid sha256:0f483afa9110508d712f9ba0d6640b23e64d4ce7441506662c278e39b2213dc6
+size 64926
diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline_TimelineView_null_TimelineView-Night-8_9_null_16,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline_TimelineView_null_TimelineView-Night-8_9_null_16,NEXUS_5,1.0,en].png
index d7b097dcd4..26d5d57080 100644
--- a/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline_TimelineView_null_TimelineView-Night-8_9_null_16,NEXUS_5,1.0,en].png
+++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline_TimelineView_null_TimelineView-Night-8_9_null_16,NEXUS_5,1.0,en].png
@@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
-oid sha256:d84115b839a3d0ea1ba357837bcd1e63457efedfe3eb6976d8f84b148293ce90
-size 55456
+oid sha256:6babf64bf9fa9e948f35b711bad8e96a7354593e92c8dc35cc0d38e8effa3ea7
+size 55462
diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline_TimelineView_null_TimelineView-Night-8_9_null_4,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline_TimelineView_null_TimelineView-Night-8_9_null_4,NEXUS_5,1.0,en].png
index d167cb5b2d..0d20ccd8eb 100644
--- a/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline_TimelineView_null_TimelineView-Night-8_9_null_4,NEXUS_5,1.0,en].png
+++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline_TimelineView_null_TimelineView-Night-8_9_null_4,NEXUS_5,1.0,en].png
@@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
-oid sha256:41450dafa7adb97bf4f4490f7054161352161263ef99ec6a93134ad3965c14ee
-size 70013
+oid sha256:8c42c1e00764debb166afe9db8c5818ae53f46ab544ba1d36af5d1aefeca2ebf
+size 70002
diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline_TimelineView_null_TimelineView-Night-8_9_null_6,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline_TimelineView_null_TimelineView-Night-8_9_null_6,NEXUS_5,1.0,en].png
index b4e9a09509..969d677448 100644
--- a/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline_TimelineView_null_TimelineView-Night-8_9_null_6,NEXUS_5,1.0,en].png
+++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline_TimelineView_null_TimelineView-Night-8_9_null_6,NEXUS_5,1.0,en].png
@@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
-oid sha256:5a03f9dc697e81f7b1dc8918de55ad4992a92d25576cd90fab22224e7ad5a0d8
-size 71946
+oid sha256:26992624618cdf42097166cb319c477cc03b0220b7f8e1cfce43458cd0e9d6a8
+size 71941
diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline_TimelineView_null_TimelineView-Night-8_9_null_8,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline_TimelineView_null_TimelineView-Night-8_9_null_8,NEXUS_5,1.0,en].png
index e5ebcda7c2..0d79825dfa 100644
--- a/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline_TimelineView_null_TimelineView-Night-8_9_null_8,NEXUS_5,1.0,en].png
+++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline_TimelineView_null_TimelineView-Night-8_9_null_8,NEXUS_5,1.0,en].png
@@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
-oid sha256:87e4676fad9b6ef136f18cea95110c934ed508e5d57b26d54a2015b3f209d4b7
-size 56235
+oid sha256:a6c73969522738d052b253abad1f8090702923f9cbcbee5935791e61bbcf40fe
+size 56240
diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.preferences.impl.notifications_NotificationSettingsView_null_NotificationSettingsView-Day-5_5_null_0,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.preferences.impl.notifications_NotificationSettingsView_null_NotificationSettingsView-Day-5_5_null_0,NEXUS_5,1.0,en].png
index 668e2a9f55..d143e02b07 100644
--- a/tests/uitests/src/test/snapshots/images/ui_S_t[f.preferences.impl.notifications_NotificationSettingsView_null_NotificationSettingsView-Day-5_5_null_0,NEXUS_5,1.0,en].png
+++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.preferences.impl.notifications_NotificationSettingsView_null_NotificationSettingsView-Day-5_5_null_0,NEXUS_5,1.0,en].png
@@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
-oid sha256:2f9516130ee975b723283523d1d62eaa116ae075be3ce62477aaf0429eeff13c
-size 52832
+oid sha256:a4b146a10957549dd4410bff3ce4793d25c31910607eec43db44b7be019af068
+size 60521
diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.preferences.impl.notifications_NotificationSettingsView_null_NotificationSettingsView-Day-5_5_null_1,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.preferences.impl.notifications_NotificationSettingsView_null_NotificationSettingsView-Day-5_5_null_1,NEXUS_5,1.0,en].png
index c3d1b9b899..b980dba66a 100644
--- a/tests/uitests/src/test/snapshots/images/ui_S_t[f.preferences.impl.notifications_NotificationSettingsView_null_NotificationSettingsView-Day-5_5_null_1,NEXUS_5,1.0,en].png
+++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.preferences.impl.notifications_NotificationSettingsView_null_NotificationSettingsView-Day-5_5_null_1,NEXUS_5,1.0,en].png
@@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
-oid sha256:3ae4c265af9ff1c5ffeff7f4aa6adfb5e0091ae9fd6360f46ee8261cf4ca213d
-size 48895
+oid sha256:340808b11e072679e7b90c939bcb5367a723b9881f084dccc0b594de5f12d543
+size 54830
diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.preferences.impl.notifications_NotificationSettingsView_null_NotificationSettingsView-Day-5_5_null_2,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.preferences.impl.notifications_NotificationSettingsView_null_NotificationSettingsView-Day-5_5_null_2,NEXUS_5,1.0,en].png
index 2a54285bdc..dc7c28e222 100644
--- a/tests/uitests/src/test/snapshots/images/ui_S_t[f.preferences.impl.notifications_NotificationSettingsView_null_NotificationSettingsView-Day-5_5_null_2,NEXUS_5,1.0,en].png
+++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.preferences.impl.notifications_NotificationSettingsView_null_NotificationSettingsView-Day-5_5_null_2,NEXUS_5,1.0,en].png
@@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
-oid sha256:e5b745897ee2bfb084a80ebbc585577532261d5a8d71926ad42c02008be46003
-size 48810
+oid sha256:ff00bafd64a4827472d757e6519955550327bb9dca97ea8a7163da4ce278f445
+size 54777
diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.preferences.impl.notifications_NotificationSettingsView_null_NotificationSettingsView-Night-5_6_null_0,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.preferences.impl.notifications_NotificationSettingsView_null_NotificationSettingsView-Night-5_6_null_0,NEXUS_5,1.0,en].png
index 7848721702..3b40c8ceda 100644
--- a/tests/uitests/src/test/snapshots/images/ui_S_t[f.preferences.impl.notifications_NotificationSettingsView_null_NotificationSettingsView-Night-5_6_null_0,NEXUS_5,1.0,en].png
+++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.preferences.impl.notifications_NotificationSettingsView_null_NotificationSettingsView-Night-5_6_null_0,NEXUS_5,1.0,en].png
@@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
-oid sha256:3a68d87c82275e80a6774712ea0ab85b04cece2c2d2dc8c19133e6878d71a1b4
-size 49178
+oid sha256:d0b8f14d6bcd6309cf8a961104738c529164621a2de4c642ce7944a48217d609
+size 55838
diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.preferences.impl.notifications_NotificationSettingsView_null_NotificationSettingsView-Night-5_6_null_1,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.preferences.impl.notifications_NotificationSettingsView_null_NotificationSettingsView-Night-5_6_null_1,NEXUS_5,1.0,en].png
index ed511c6980..68440b467a 100644
--- a/tests/uitests/src/test/snapshots/images/ui_S_t[f.preferences.impl.notifications_NotificationSettingsView_null_NotificationSettingsView-Night-5_6_null_1,NEXUS_5,1.0,en].png
+++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.preferences.impl.notifications_NotificationSettingsView_null_NotificationSettingsView-Night-5_6_null_1,NEXUS_5,1.0,en].png
@@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
-oid sha256:8ecc7a31d53543fae8950e2773da0aea2ebdb6c9b557254e0062ce000dcd79b3
-size 45061
+oid sha256:964fc455b25f442bfc89e917148c15f7f9301d9b6db5c94f2075d994b74a6eef
+size 50975
diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.preferences.impl.notifications_NotificationSettingsView_null_NotificationSettingsView-Night-5_6_null_2,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.preferences.impl.notifications_NotificationSettingsView_null_NotificationSettingsView-Night-5_6_null_2,NEXUS_5,1.0,en].png
index 33d23d7081..a6ff4a3317 100644
--- a/tests/uitests/src/test/snapshots/images/ui_S_t[f.preferences.impl.notifications_NotificationSettingsView_null_NotificationSettingsView-Night-5_6_null_2,NEXUS_5,1.0,en].png
+++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.preferences.impl.notifications_NotificationSettingsView_null_NotificationSettingsView-Night-5_6_null_2,NEXUS_5,1.0,en].png
@@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
-oid sha256:8bb56b559b52efdd9f6ac41e0ae674054b6f511292b2cf88208bbf32afb765a9
-size 44414
+oid sha256:fccd2b3e6fff431b0b650cccef21c0b8129c838dfc3b1b0bc6ee83321dcfe698
+size 50386
diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl.members.details_RoomMemberDetailsViewDark_null_RoomMemberDetailsViewDark--3_5_null_0,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl.members.details_RoomMemberDetailsViewDark_null_RoomMemberDetailsViewDark--3_5_null_0,NEXUS_5,1.0,en].png
index 6cbb96f072..966a6e3d0d 100644
--- a/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl.members.details_RoomMemberDetailsViewDark_null_RoomMemberDetailsViewDark--3_5_null_0,NEXUS_5,1.0,en].png
+++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl.members.details_RoomMemberDetailsViewDark_null_RoomMemberDetailsViewDark--3_5_null_0,NEXUS_5,1.0,en].png
@@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
-oid sha256:3f209aba9d799dfd6b3b947beef7f5e9ec8b6e45209579c406b41f545300ed9b
-size 19562
+oid sha256:635af24c8306297ac954aa7ddb4286c36904b763e8f32acbbad841334dda8253
+size 22352
diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl.members.details_RoomMemberDetailsViewDark_null_RoomMemberDetailsViewDark--3_5_null_1,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl.members.details_RoomMemberDetailsViewDark_null_RoomMemberDetailsViewDark--3_5_null_1,NEXUS_5,1.0,en].png
index bf4bf45d77..3d6ff401a2 100644
--- a/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl.members.details_RoomMemberDetailsViewDark_null_RoomMemberDetailsViewDark--3_5_null_1,NEXUS_5,1.0,en].png
+++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl.members.details_RoomMemberDetailsViewDark_null_RoomMemberDetailsViewDark--3_5_null_1,NEXUS_5,1.0,en].png
@@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
-oid sha256:9e23c9f4c52976030b3c397ad2e68f94bed265c147d3a40f65b6fa4d1459405d
-size 17392
+oid sha256:c8b5d1c152ed4f3334fc5d6fa74546a1fa7f50dd4975f6f108028a34be0db63c
+size 20248
diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl.members.details_RoomMemberDetailsViewDark_null_RoomMemberDetailsViewDark--3_5_null_2,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl.members.details_RoomMemberDetailsViewDark_null_RoomMemberDetailsViewDark--3_5_null_2,NEXUS_5,1.0,en].png
index cae6a921c3..201c88ab4a 100644
--- a/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl.members.details_RoomMemberDetailsViewDark_null_RoomMemberDetailsViewDark--3_5_null_2,NEXUS_5,1.0,en].png
+++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl.members.details_RoomMemberDetailsViewDark_null_RoomMemberDetailsViewDark--3_5_null_2,NEXUS_5,1.0,en].png
@@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
-oid sha256:8109e9c96d3f89ed6747b21fe326f6cdc61157b376497560ba6415d6ee592b79
-size 19932
+oid sha256:a7caaac71c2c280fc18036e725d9a64aae77e351b494440bbac6f6776658c856
+size 22544
diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl.members.details_RoomMemberDetailsViewDark_null_RoomMemberDetailsViewDark--3_5_null_3,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl.members.details_RoomMemberDetailsViewDark_null_RoomMemberDetailsViewDark--3_5_null_3,NEXUS_5,1.0,en].png
index 9c0a35fc1e..cf98fbcce8 100644
--- a/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl.members.details_RoomMemberDetailsViewDark_null_RoomMemberDetailsViewDark--3_5_null_3,NEXUS_5,1.0,en].png
+++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl.members.details_RoomMemberDetailsViewDark_null_RoomMemberDetailsViewDark--3_5_null_3,NEXUS_5,1.0,en].png
@@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
-oid sha256:64c553c7647dcf8e6e65e0e5f6958a1e77b67490f7f9b97670ff5ca9a5695cef
-size 36807
+oid sha256:44e2a0e5c2adb1d80c2bf2abfc3ab481ef28a7dd44de8fcdca73d87933219f65
+size 38735
diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl.members.details_RoomMemberDetailsViewDark_null_RoomMemberDetailsViewDark--3_5_null_4,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl.members.details_RoomMemberDetailsViewDark_null_RoomMemberDetailsViewDark--3_5_null_4,NEXUS_5,1.0,en].png
index b6b596bd7c..ab06f857b9 100644
--- a/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl.members.details_RoomMemberDetailsViewDark_null_RoomMemberDetailsViewDark--3_5_null_4,NEXUS_5,1.0,en].png
+++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl.members.details_RoomMemberDetailsViewDark_null_RoomMemberDetailsViewDark--3_5_null_4,NEXUS_5,1.0,en].png
@@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
-oid sha256:40b07513dadf6339d9d46bcedc3b5e69f798262d10c9072854a9e3c07a184113
-size 28163
+oid sha256:29a24d3f9c01d866f2b3cfdff1460a47f956c2b30865f1c0c74a505a7ee40581
+size 30824
diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl.members.details_RoomMemberDetailsViewDark_null_RoomMemberDetailsViewDark--3_5_null_5,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl.members.details_RoomMemberDetailsViewDark_null_RoomMemberDetailsViewDark--3_5_null_5,NEXUS_5,1.0,en].png
index 9d9369cec3..baca4fe9e0 100644
--- a/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl.members.details_RoomMemberDetailsViewDark_null_RoomMemberDetailsViewDark--3_5_null_5,NEXUS_5,1.0,en].png
+++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl.members.details_RoomMemberDetailsViewDark_null_RoomMemberDetailsViewDark--3_5_null_5,NEXUS_5,1.0,en].png
@@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
-oid sha256:57428cc1459dab91ffae11e4c719e08b147d3692e24ceea3cec0997659890487
-size 20526
+oid sha256:52009b1f8c129638c82568c0d23822cbed4de45f6ce49062aa38a79dfedecbe8
+size 23041
diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl.members.details_RoomMemberDetailsViewDark_null_RoomMemberDetailsViewDark--3_5_null_6,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl.members.details_RoomMemberDetailsViewDark_null_RoomMemberDetailsViewDark--3_5_null_6,NEXUS_5,1.0,en].png
new file mode 100644
index 0000000000..03ff1f7b4b
--- /dev/null
+++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl.members.details_RoomMemberDetailsViewDark_null_RoomMemberDetailsViewDark--3_5_null_6,NEXUS_5,1.0,en].png
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:68ceadfa7696c8350c45bc4c47553e8fe8c10e283ae2a3420a4192160bd97ab7
+size 22925
diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl.members.details_RoomMemberDetailsViewLight_null_RoomMemberDetailsViewLight--2_4_null_0,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl.members.details_RoomMemberDetailsViewLight_null_RoomMemberDetailsViewLight--2_4_null_0,NEXUS_5,1.0,en].png
index 52363a0f76..8da2d0200a 100644
--- a/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl.members.details_RoomMemberDetailsViewLight_null_RoomMemberDetailsViewLight--2_4_null_0,NEXUS_5,1.0,en].png
+++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl.members.details_RoomMemberDetailsViewLight_null_RoomMemberDetailsViewLight--2_4_null_0,NEXUS_5,1.0,en].png
@@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
-oid sha256:fd6633077a2c6e45374beb32e377c813c121bac8d7312439a85808520d061676
-size 20015
+oid sha256:52dcc40a72b799510a4400662b462bba34bbb6be98a35eaa5c3edc3a671aa786
+size 23016
diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl.members.details_RoomMemberDetailsViewLight_null_RoomMemberDetailsViewLight--2_4_null_1,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl.members.details_RoomMemberDetailsViewLight_null_RoomMemberDetailsViewLight--2_4_null_1,NEXUS_5,1.0,en].png
index 831427f42b..7d7ea4300c 100644
--- a/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl.members.details_RoomMemberDetailsViewLight_null_RoomMemberDetailsViewLight--2_4_null_1,NEXUS_5,1.0,en].png
+++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl.members.details_RoomMemberDetailsViewLight_null_RoomMemberDetailsViewLight--2_4_null_1,NEXUS_5,1.0,en].png
@@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
-oid sha256:e0ef4293fb45a3703c992616709bdd7252d939f419dfd7f3254900cdfdd4b890
-size 17771
+oid sha256:6099039f33757df49245866f6dbcca9576b216b1fe9e1f87c6c4f4e92add153c
+size 20945
diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl.members.details_RoomMemberDetailsViewLight_null_RoomMemberDetailsViewLight--2_4_null_2,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl.members.details_RoomMemberDetailsViewLight_null_RoomMemberDetailsViewLight--2_4_null_2,NEXUS_5,1.0,en].png
index d31ae5a8bc..fbdffe0bb4 100644
--- a/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl.members.details_RoomMemberDetailsViewLight_null_RoomMemberDetailsViewLight--2_4_null_2,NEXUS_5,1.0,en].png
+++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl.members.details_RoomMemberDetailsViewLight_null_RoomMemberDetailsViewLight--2_4_null_2,NEXUS_5,1.0,en].png
@@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
-oid sha256:9019d3716d171d24a02832ec8db6885f811304a76ac6f55d0b4cba5561e51a0a
-size 20419
+oid sha256:6f5586f7c60ea5959713a66cb97397c5d834b27100e1603bcbb98c430dc0873e
+size 23539
diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl.members.details_RoomMemberDetailsViewLight_null_RoomMemberDetailsViewLight--2_4_null_3,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl.members.details_RoomMemberDetailsViewLight_null_RoomMemberDetailsViewLight--2_4_null_3,NEXUS_5,1.0,en].png
index 10038e1407..f76a02a956 100644
--- a/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl.members.details_RoomMemberDetailsViewLight_null_RoomMemberDetailsViewLight--2_4_null_3,NEXUS_5,1.0,en].png
+++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl.members.details_RoomMemberDetailsViewLight_null_RoomMemberDetailsViewLight--2_4_null_3,NEXUS_5,1.0,en].png
@@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
-oid sha256:30dcf6770898700a1fbbd85f80cc957b90af606badcbd22ef5b9ee114142e166
-size 41500
+oid sha256:10d2ea969c9cd2bcd809e72cc56d8ae086b1b4d848636c55e9db5ef23783620d
+size 43647
diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl.members.details_RoomMemberDetailsViewLight_null_RoomMemberDetailsViewLight--2_4_null_4,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl.members.details_RoomMemberDetailsViewLight_null_RoomMemberDetailsViewLight--2_4_null_4,NEXUS_5,1.0,en].png
index f81750567c..350f21eeb0 100644
--- a/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl.members.details_RoomMemberDetailsViewLight_null_RoomMemberDetailsViewLight--2_4_null_4,NEXUS_5,1.0,en].png
+++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl.members.details_RoomMemberDetailsViewLight_null_RoomMemberDetailsViewLight--2_4_null_4,NEXUS_5,1.0,en].png
@@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
-oid sha256:414cfa386a1c3d97317eaa6ce4272c071420f2b3191ab56e1f4b46904febf552
-size 32491
+oid sha256:e220d275226ae8820e0119a767b2baf964f2173c430531a379e338bdf9e08adc
+size 35530
diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl.members.details_RoomMemberDetailsViewLight_null_RoomMemberDetailsViewLight--2_4_null_5,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl.members.details_RoomMemberDetailsViewLight_null_RoomMemberDetailsViewLight--2_4_null_5,NEXUS_5,1.0,en].png
index 752c962509..86f5985e6f 100644
--- a/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl.members.details_RoomMemberDetailsViewLight_null_RoomMemberDetailsViewLight--2_4_null_5,NEXUS_5,1.0,en].png
+++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl.members.details_RoomMemberDetailsViewLight_null_RoomMemberDetailsViewLight--2_4_null_5,NEXUS_5,1.0,en].png
@@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
-oid sha256:209f2821d99c15981b457682dc8e99036f592858404773ca3165baa66807053c
-size 21020
+oid sha256:fd3964a31217ccef0ba53ab1f5341311b52746b20660461220375dcad3befcec
+size 24194
diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl.members.details_RoomMemberDetailsViewLight_null_RoomMemberDetailsViewLight--2_4_null_6,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl.members.details_RoomMemberDetailsViewLight_null_RoomMemberDetailsViewLight--2_4_null_6,NEXUS_5,1.0,en].png
new file mode 100644
index 0000000000..b99279289b
--- /dev/null
+++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl.members.details_RoomMemberDetailsViewLight_null_RoomMemberDetailsViewLight--2_4_null_6,NEXUS_5,1.0,en].png
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:1745fbfae1996203b192b07bbbf424eb129944b37b83c0203fcd05c7f332096d
+size 25874
diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.verifysession.impl.emoji_SasEmojis_null_SasEmojis-Day-1_2_null,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.verifysession.impl.emoji_SasEmojis_null_SasEmojis-Day-1_2_null,NEXUS_5,1.0,en].png
new file mode 100644
index 0000000000..63acb4565c
--- /dev/null
+++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.verifysession.impl.emoji_SasEmojis_null_SasEmojis-Day-1_2_null,NEXUS_5,1.0,en].png
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:f0d2eb0d4631129167e2a2d0e88341723050fe737e9ef807de028177fadde63f
+size 145991
diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.verifysession.impl.emoji_SasEmojis_null_SasEmojis-Night-1_3_null,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.verifysession.impl.emoji_SasEmojis_null_SasEmojis-Night-1_3_null,NEXUS_5,1.0,en].png
new file mode 100644
index 0000000000..487447301e
--- /dev/null
+++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.verifysession.impl.emoji_SasEmojis_null_SasEmojis-Night-1_3_null,NEXUS_5,1.0,en].png
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:259c86326608b0d9c3595c1fb53768322c9c43463f4ce7442ceb11e684115978
+size 143665
diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.verifysession.impl_VerifySelfSessionView_null_VerifySelfSessionView-Day-0_1_null_2,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.verifysession.impl_VerifySelfSessionView_null_VerifySelfSessionView-Day-0_1_null_2,NEXUS_5,1.0,en].png
index d42407f5bb..de0e46a071 100644
--- a/tests/uitests/src/test/snapshots/images/ui_S_t[f.verifysession.impl_VerifySelfSessionView_null_VerifySelfSessionView-Day-0_1_null_2,NEXUS_5,1.0,en].png
+++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.verifysession.impl_VerifySelfSessionView_null_VerifySelfSessionView-Day-0_1_null_2,NEXUS_5,1.0,en].png
@@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
-oid sha256:b801d06d7ec8cab2a9a2804541cdf2e0e27dfed949bddb29b3ce7e6b348ac452
-size 56485
+oid sha256:8425428904c58fd9a22f4505c7dbb47798efcf2f2e5007fbf3f402222cb0cf53
+size 51381
diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.verifysession.impl_VerifySelfSessionView_null_VerifySelfSessionView-Day-0_1_null_3,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.verifysession.impl_VerifySelfSessionView_null_VerifySelfSessionView-Day-0_1_null_3,NEXUS_5,1.0,en].png
index 806c701471..258a528e6c 100644
--- a/tests/uitests/src/test/snapshots/images/ui_S_t[f.verifysession.impl_VerifySelfSessionView_null_VerifySelfSessionView-Day-0_1_null_3,NEXUS_5,1.0,en].png
+++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.verifysession.impl_VerifySelfSessionView_null_VerifySelfSessionView-Day-0_1_null_3,NEXUS_5,1.0,en].png
@@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
-oid sha256:41983afd517fc4a8ad8347ee1e07ce65a58ab4677dc2c07582aefef2764f1263
-size 57899
+oid sha256:f5318f2a7564c319c58971daf76a60a696d0835476d06666a190849a7222c98d
+size 52689
diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.verifysession.impl_VerifySelfSessionView_null_VerifySelfSessionView-Day-0_1_null_6,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.verifysession.impl_VerifySelfSessionView_null_VerifySelfSessionView-Day-0_1_null_6,NEXUS_5,1.0,en].png
new file mode 100644
index 0000000000..fb2edac72f
--- /dev/null
+++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.verifysession.impl_VerifySelfSessionView_null_VerifySelfSessionView-Day-0_1_null_6,NEXUS_5,1.0,en].png
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:22817cd770e9eb1d438128804007a33cc038f8da17788f0848ec5db26211a179
+size 35569
diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.verifysession.impl_VerifySelfSessionView_null_VerifySelfSessionView-Night-0_2_null_2,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.verifysession.impl_VerifySelfSessionView_null_VerifySelfSessionView-Night-0_2_null_2,NEXUS_5,1.0,en].png
index 81d26981a8..1c24f49ca9 100644
--- a/tests/uitests/src/test/snapshots/images/ui_S_t[f.verifysession.impl_VerifySelfSessionView_null_VerifySelfSessionView-Night-0_2_null_2,NEXUS_5,1.0,en].png
+++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.verifysession.impl_VerifySelfSessionView_null_VerifySelfSessionView-Night-0_2_null_2,NEXUS_5,1.0,en].png
@@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
-oid sha256:2d5701107cf5091ac15c167daa45e7eb38d36ee119eef31ffaaaa0e94da1c7d6
-size 55684
+oid sha256:77668eb95611c9b72913d286956b1b5e6bafe1cf6a1facfc00a5c4fd0ceab3d2
+size 49133
diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.verifysession.impl_VerifySelfSessionView_null_VerifySelfSessionView-Night-0_2_null_3,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.verifysession.impl_VerifySelfSessionView_null_VerifySelfSessionView-Night-0_2_null_3,NEXUS_5,1.0,en].png
index 4f3e4a9556..dd78bc04ea 100644
--- a/tests/uitests/src/test/snapshots/images/ui_S_t[f.verifysession.impl_VerifySelfSessionView_null_VerifySelfSessionView-Night-0_2_null_3,NEXUS_5,1.0,en].png
+++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.verifysession.impl_VerifySelfSessionView_null_VerifySelfSessionView-Night-0_2_null_3,NEXUS_5,1.0,en].png
@@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
-oid sha256:4c56c2c33e4b4c1e4175a2f9ea147680bd1b463a925cc62d2f4fc5a82d53bae9
-size 57085
+oid sha256:121d1b8f9a6abf9c50a951b2db6a7e52602ec34876a55e38b009f1fdffcd725d
+size 50525
diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.verifysession.impl_VerifySelfSessionView_null_VerifySelfSessionView-Night-0_2_null_6,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.verifysession.impl_VerifySelfSessionView_null_VerifySelfSessionView-Night-0_2_null_6,NEXUS_5,1.0,en].png
new file mode 100644
index 0000000000..7fb3f28454
--- /dev/null
+++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.verifysession.impl_VerifySelfSessionView_null_VerifySelfSessionView-Night-0_2_null_6,NEXUS_5,1.0,en].png
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:83961b489de278edf3f2646f228e059e71f381363ffb751f44244a7d12604cb9
+size 33443
diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[l.textcomposer_TextComposerFormatting_null_TextComposerFormatting-Day-1_2_null,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[l.textcomposer_TextComposerFormatting_null_TextComposerFormatting-Day-1_2_null,NEXUS_5,1.0,en].png
index 5597d00a90..b1c018b7b2 100644
--- a/tests/uitests/src/test/snapshots/images/ui_S_t[l.textcomposer_TextComposerFormatting_null_TextComposerFormatting-Day-1_2_null,NEXUS_5,1.0,en].png
+++ b/tests/uitests/src/test/snapshots/images/ui_S_t[l.textcomposer_TextComposerFormatting_null_TextComposerFormatting-Day-1_2_null,NEXUS_5,1.0,en].png
@@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
-oid sha256:8e84a8f99437d6de1ab8775e449135a27f808ddef5271f9024618ca57a50c44b
-size 43184
+oid sha256:afb9bd4fc5d01e408b1b9dfb0b6a2b2d47c3f6605ef9065ae2b50c16d641b26e
+size 43147
diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[l.textcomposer_TextComposerFormatting_null_TextComposerFormatting-Night-1_3_null,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[l.textcomposer_TextComposerFormatting_null_TextComposerFormatting-Night-1_3_null,NEXUS_5,1.0,en].png
index 13d75ecb01..523de5a3a2 100644
--- a/tests/uitests/src/test/snapshots/images/ui_S_t[l.textcomposer_TextComposerFormatting_null_TextComposerFormatting-Night-1_3_null,NEXUS_5,1.0,en].png
+++ b/tests/uitests/src/test/snapshots/images/ui_S_t[l.textcomposer_TextComposerFormatting_null_TextComposerFormatting-Night-1_3_null,NEXUS_5,1.0,en].png
@@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
-oid sha256:4cf016ba5afe1015ab2ba9359f721f7cde8431aa24af51b55aa35fc13746a3fc
-size 40644
+oid sha256:769f171a6891c4414f6571fadc75b00a3c977bd108474750c714f4a53a491bd3
+size 40538
diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[l.textcomposer_TextComposerSimple_null_TextComposerSimple-Day-0_1_null,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[l.textcomposer_TextComposerSimple_null_TextComposerSimple-Day-0_1_null,NEXUS_5,1.0,en].png
index 71296a13fb..487fc50f71 100644
--- a/tests/uitests/src/test/snapshots/images/ui_S_t[l.textcomposer_TextComposerSimple_null_TextComposerSimple-Day-0_1_null,NEXUS_5,1.0,en].png
+++ b/tests/uitests/src/test/snapshots/images/ui_S_t[l.textcomposer_TextComposerSimple_null_TextComposerSimple-Day-0_1_null,NEXUS_5,1.0,en].png
@@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
-oid sha256:f17d7621796f3fdf4e3995ba1d51b30cdf700e7f548140d179edea9e46baa39f
-size 48147
+oid sha256:263604e2a52e424fe88fcb28b8c0493405a200bc0f1738d394dce3a63b182a83
+size 47996
diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[l.textcomposer_TextComposerSimple_null_TextComposerSimple-Night-0_2_null,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[l.textcomposer_TextComposerSimple_null_TextComposerSimple-Night-0_2_null,NEXUS_5,1.0,en].png
index 50fe021505..f4a962cb5c 100644
--- a/tests/uitests/src/test/snapshots/images/ui_S_t[l.textcomposer_TextComposerSimple_null_TextComposerSimple-Night-0_2_null,NEXUS_5,1.0,en].png
+++ b/tests/uitests/src/test/snapshots/images/ui_S_t[l.textcomposer_TextComposerSimple_null_TextComposerSimple-Night-0_2_null,NEXUS_5,1.0,en].png
@@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
-oid sha256:978d26cf93122ac0c903d04222ae12caf320038f78aa084639ef8d90f8e4845e
-size 45189
+oid sha256:3c304d9a5b4d3ef45281785a67ff7fd0ffc7c8b8cb5975dd50a557a004cb993f
+size 45109
diff --git a/tools/danger/dangerfile.js b/tools/danger/dangerfile.js
index d183911c39..b9f46d5666 100644
--- a/tools/danger/dangerfile.js
+++ b/tools/danger/dangerfile.js
@@ -38,7 +38,7 @@ if (requiresChangelog) {
const changelogFiles = editedFiles.filter(file => file.startsWith("changelog.d/"))
if (changelogFiles.length == 0) {
- warn("Please add a changelog. See instructions [here](https://github.com/vector-im/element-android/blob/develop/CONTRIBUTING.md#changelog)")
+ warn("Please add a changelog. See instructions [here](https://github.com/element-hq/element-android/blob/develop/CONTRIBUTING.md#changelog)")
} else {
const validTowncrierExtensions = [
"bugfix",
@@ -48,7 +48,7 @@ if (requiresChangelog) {
"wip",
]
if (!changelogFiles.every(file => validTowncrierExtensions.includes(file.split(".").pop()))) {
- fail("Invalid extension for changelog. See instructions [here](https://github.com/vector-im/element-android/blob/develop/CONTRIBUTING.md#changelog)")
+ fail("Invalid extension for changelog. See instructions [here](https://github.com/element-hq/element-android/blob/develop/CONTRIBUTING.md#changelog)")
}
}
}
@@ -107,11 +107,11 @@ if (allowList.includes(user)) {
signoff_unneeded("allow-list")
} else {
// github.api.rest.orgs.checkMembershipForUser({
-// org: "vector-im",
+// org: "element-hq",
// username: user,
// }).then((result) => {
github.api.rest.teams.getMembershipForUserInOrg({
- org: "vector-im",
+ org: "element-hq",
team_slug: "vector-core",
username: user,
}).then((result) => {
@@ -172,7 +172,7 @@ const translationAllowList = [
if (!translationAllowList.includes(user)) {
if (editedFiles.some(file => file.endsWith("strings.xml") && !file.endsWith("values/strings.xml"))) {
- fail("Some translation files have been edited. Only user `RiotTranslateBot` (i.e. translations coming from Weblate) or `github-actions[bot]` (i.e. translations coming from automation) are allowed to do that.\nPlease read more about translations management [in the doc](https://github.com/vector-im/element-android/blob/develop/CONTRIBUTING.md#internationalisation).")
+ fail("Some translation files have been edited. Only user `RiotTranslateBot` (i.e. translations coming from Weblate) or `github-actions[bot]` (i.e. translations coming from automation) are allowed to do that.\nPlease read more about translations management [in the doc](https://github.com/element-hq/element-android/blob/develop/CONTRIBUTING.md#internationalisation).")
}
// Check that new strings are not added to `values/strings.xml`
diff --git a/tools/github/download_github_artifacts.py b/tools/github/download_github_artifacts.py
index 892a4affa6..4424c0e009 100755
--- a/tools/github/download_github_artifacts.py
+++ b/tools/github/download_github_artifacts.py
@@ -65,7 +65,7 @@ if args.verbose:
print(args)
# Split the artifact URL to get information
-# Ex: https://github.com/vector-im/element-android/suites/9293388174/artifacts/435942121
+# Ex: https://github.com/element-hq/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)
diff --git a/tools/localazy/config.json b/tools/localazy/config.json
index cc949b7dde..9377a1f3f4 100644
--- a/tools/localazy/config.json
+++ b/tools/localazy/config.json
@@ -116,7 +116,8 @@
"screen_dm_details_.*",
"screen_room_notification_settings_.*",
"screen_notification_settings_edit_failed_updating_default_mode",
- "screen_polls_history_title"
+ "screen_polls_history_title",
+ "screen_start_chat_error_starting_chat"
]
},
{
diff --git a/tools/localazy/downloadStrings.sh b/tools/localazy/downloadStrings.sh
index bc00488258..c4a97868af 100755
--- a/tools/localazy/downloadStrings.sh
+++ b/tools/localazy/downloadStrings.sh
@@ -46,6 +46,14 @@ if [[ $allFiles == 1 ]]; then
find . -name 'translations.xml' -print0 -exec bash -c "echo \"\" >> \"{}\"" \; >> /dev/null
fi
+set +e
+echo "Moving files from values-id to values-in..."
+find . -type d -name 'values-id' -execdir mv {}/translations.xml {}/../values-in/translations.xml 2> /dev/null \;
+
+echo "Deleting all the folders values-id..."
+find . -type d -name 'values-id' -exec rm -rf {} 2> /dev/null \;
+set -e
+
echo "Removing the generated config"
rm ./tools/localazy/localazy.json
diff --git a/tools/localazy/generateLocalazyConfig.py b/tools/localazy/generateLocalazyConfig.py
index 464c67c70a..b1ade3fdb0 100755
--- a/tools/localazy/generateLocalazyConfig.py
+++ b/tools/localazy/generateLocalazyConfig.py
@@ -31,7 +31,7 @@ baseAction = {
}
}
-# Store all regex specific to module, to eclude the corresponding keyx from the common string module
+# Store all regex specific to module, to exclude the corresponding key from the common string module
allRegexToExcludeFromMainModule = []
# All actions that will be serialized in the localazy config
allActions = []
diff --git a/tools/release/release.sh b/tools/release/release.sh
index a5701ea5e1..26a94cb09e 100755
--- a/tools/release/release.sh
+++ b/tools/release/release.sh
@@ -166,7 +166,7 @@ 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}
+printf "Main changes in this version: TODO.\nFull changelog: https://github.com/element-hq/element-x-android/releases" > ${fastlanePathFile}
read -p "I have created the file ${fastlanePathFile}, please edit it and press enter to continue. "
git add ${fastlanePathFile}
@@ -217,7 +217,7 @@ else
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"
+printf "Wait for the GitHub action https://github.com/element-hq/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"
@@ -292,7 +292,7 @@ else
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}"
+githubCreateReleaseLink="https://github.com/element-hq/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"
@@ -303,7 +303,7 @@ read -p ". Press enter to continue. "
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}. Installation instructions can be found [here](https://github.com/vector-im/element-x-android/blob/develop/docs/install_from_github_release.md). Please report any feedback. Thanks!"
+message="@room Element X Android ${version} is ready to be tested. You can get it from https://github.com/element-hq/element-x-android/releases/tag/v${version}. Installation instructions can be found [here](https://github.com/element-hq/element-x-android/blob/develop/docs/install_from_github_release.md). Please report any feedback. Thanks!"
printf "${message}\n\n"
if [[ -z "${elementBotToken}" ]]; then
diff --git a/tools/sas/import_sas_emojis.py b/tools/sas/import_sas_emojis.py
new file mode 100755
index 0000000000..0c7f539af1
--- /dev/null
+++ b/tools/sas/import_sas_emojis.py
@@ -0,0 +1,83 @@
+#!/usr/bin/env python3
+
+# Copyright (c) 2020 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 json
+import os
+import os.path
+# Run `pip3 install requests` if not installed yet
+import requests
+
+### Arguments
+
+parser = argparse.ArgumentParser(description='Download sas string from matrix-doc.')
+parser.add_argument('-v',
+ '--verbose',
+ help="increase output verbosity.",
+ action="store_true")
+
+args = parser.parse_args()
+
+if args.verbose:
+ print("Argument:")
+ print(args)
+
+base_url = "https://raw.githubusercontent.com/matrix-org/matrix-spec/main/data-definitions/sas-emoji.json"
+
+base_emoji_url = "https://raw.githubusercontent.com/twitter/twemoji/master/assets/svg/"
+
+print("Downloading " + base_url + "…")
+
+r0 = requests.get(base_url)
+data0 = json.loads(r0.content.decode())
+
+if args.verbose:
+ print("Json data:")
+ print(data0)
+
+print()
+
+scripts_dir = os.path.dirname(os.path.abspath(__file__))
+data_defs_dir = os.path.join(scripts_dir, "../../tmp/emoji/")
+
+def handle_emoji(dict):
+ print("Handle emoji " + str(dict["number"]) + " (" + dict["description"] + ")…")
+ if args.verbose:
+ print("With")
+ print(dict)
+ # Transform dict["unicode"] from "U+2601U+FE0F" to "2601U"
+ emoji = dict["unicode"].split("U+")[1].lower()
+ url = base_emoji_url + emoji + ".svg"
+ file = os.path.join(data_defs_dir, "ic_verification_" + format(dict["number"], '02d') + ".svg")
+ print("Downloading " + url + " to " + file + "…")
+ r = requests.get(url)
+ if r.status_code != 200:
+ print("Fatal: " + str(r.status_code))
+ # Stop script with error
+ sys.exit(1)
+ os.makedirs(os.path.dirname(file), exist_ok=True)
+ with open(file, "w") as f:
+ f.write(r.content.decode())
+
+for emoji in data0:
+ handle_emoji(emoji)
+
+print()
+print("Success!")
+print()
+print("To convert to vector drawable, download tool from https://www.androiddesignpatterns.com/2018/11/android-studio-svg-to-vector-cli.html")
+print("unzip it, and run:")
+print("vd-tool/bin/vd-tool -c -in ./tmp/emoji -out features/verifysession/impl/src/main/res/drawable")
diff --git a/tools/sas/import_sas_strings.py b/tools/sas/import_sas_strings.py
new file mode 100755
index 0000000000..5f6d948133
--- /dev/null
+++ b/tools/sas/import_sas_strings.py
@@ -0,0 +1,113 @@
+#!/usr/bin/env python3
+
+# Copyright (c) 2020 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 json
+import os
+import os.path
+# Run `pip3 install requests` if not installed yet
+import requests
+
+### Arguments
+
+parser = argparse.ArgumentParser(description='Download sas string from matrix-doc.')
+parser.add_argument('-v',
+ '--verbose',
+ help="increase output verbosity.",
+ action="store_true")
+
+args = parser.parse_args()
+
+if args.verbose:
+ print("Argument:")
+ print(args)
+
+base_url = "https://raw.githubusercontent.com/matrix-org/matrix-spec/main/data-definitions/sas-emoji.json"
+
+print("Downloading " + base_url + "…")
+
+r0 = requests.get(base_url)
+data0 = json.loads(r0.content.decode())
+
+if args.verbose:
+ print("Json data:")
+ print(data0)
+
+print()
+
+# number -> translation
+default = dict()
+# Language -> emoji -> translation
+cumul = dict()
+
+for emoji in data0:
+ d = dict()
+ number = emoji["number"]
+ d["description"] = emoji["description"]
+ d["emoji"] = emoji["emoji"]
+ d["unicode"] = emoji["unicode"]
+ if args.verbose:
+ print("Dict: " + str(d))
+ default[number] = d
+
+ for lang in emoji["translated_descriptions"]:
+ if args.verbose:
+ print("Lang: " + lang)
+ if not (lang in cumul):
+ cumul[lang] = dict()
+ d = dict()
+ d["description"] = emoji["translated_descriptions"][lang]
+ cumul[lang][number] = d
+
+if args.verbose:
+ print(default)
+ print(cumul)
+
+def write_file(file, dict):
+ print("Writing file " + file)
+ if args.verbose:
+ print("With")
+ print(dict)
+ os.makedirs(os.path.dirname(file), exist_ok=True)
+ with open(file, mode="w", encoding="utf8") as o:
+ o.write("\n")
+ o.write("\n")
+ o.write(" \n")
+ for key in dict:
+ if dict[key] is None:
+ continue
+ if dict[key]["description"] is None:
+ continue
+ o.write(" " + dict[key]["description"].replace("'", "\\'") + "\n")
+ o.write("\n")
+
+scripts_dir = os.path.dirname(os.path.abspath(__file__))
+data_defs_dir = os.path.join(scripts_dir, "../../features/verifysession/impl/src/main/res")
+
+# Write default file
+write_file(os.path.join(data_defs_dir, "values/strings_sas.xml"), default)
+
+# Write each language file
+for lang in cumul:
+ androidLang = lang \
+ .replace("_", "-r") \
+ .replace("zh-rHans", "zh-rCN") \
+ .replace("zh-rHant", "zh-rTW") \
+ .replace("id", "in")
+ write_file(os.path.join(data_defs_dir, "values-" + androidLang + "/strings_sas.xml"), cumul[lang])
+
+print()
+print("Success!")
diff --git a/towncrier.toml b/towncrier.toml
index c9be3af199..e018467aec 100644
--- a/towncrier.toml
+++ b/towncrier.toml
@@ -3,7 +3,7 @@
filename = "CHANGES.md"
name = "Changes in Element X"
template = "tools/towncrier/template.md"
- issue_format = "[#{issue}](https://github.com/vector-im/element-x-android/issues/{issue})"
+ issue_format = "[#{issue}](https://github.com/element-hq/element-x-android/issues/{issue})"
[[tool.towncrier.type]]
directory = "feature"