diff --git a/.editorconfig b/.editorconfig
index 0a49eadc0b..1966f91763 100644
--- a/.editorconfig
+++ b/.editorconfig
@@ -9,25 +9,6 @@ insert_final_newline=true
# it's automatically set to 100 on `ktlint --android ...` (per Android Kotlin Style Guide)
max_line_length=off
-# Comma-separated list of rules to disable (Since 0.34.0)
-# Note that rules in any ruleset other than the standard ruleset will need to be prefixed
-# by the ruleset identifier.
-disabled_rules=no-multi-spaces,colon-spacing,chain-wrapping,import-ordering,experimental:annotation
-
-# The following (so far identified) rules are kept:
-# no-blank-line-before-rbrace
-# final-newline
-# no-consecutive-blank-lines
-# comment-spacing
-# filename
-# comma-spacing
-# paren-spacing
-# op-spacing
-# string-template
-# no-unused-imports
-# curly-spacing
-# no-semi
-# no-empty-class-body
-# experimental:multiline-if-else
-# experimental:no-empty-first-line-in-method-block
-# no-wildcard-imports
+# From https://github.com/pinterest/ktlint#custom-ktlint-specific-editorconfig-properties
+# default IntelliJ IDEA style, same as alphabetical, but with "java", "javax", "kotlin" and alias imports in the end of the imports list
+ij_kotlin_imports_layout=*,java.**,javax.**,kotlin.**,^
diff --git a/.github/ISSUE_TEMPLATE/bug.yml b/.github/ISSUE_TEMPLATE/bug.yml
new file mode 100644
index 0000000000..c4eccd5b1f
--- /dev/null
+++ b/.github/ISSUE_TEMPLATE/bug.yml
@@ -0,0 +1,74 @@
+name: Bug report for the Element Android app
+description: Report any issues that you have found with the Element app. Please [check open issues](https://github.com/vector-im/element-android/issues) first, in case it has already been reported.
+labels: [T-Defect]
+body:
+ - type: markdown
+ attributes:
+ value: |
+ Thanks for taking the time to fill out this bug report!
+
+ Please report security issues by email to security@matrix.org
+ - type: textarea
+ id: reproduction-steps
+ attributes:
+ label: Steps to reproduce
+ description: Please attach screenshots, videos or logs if you can.
+ placeholder: Tell us what you see!
+ value: |
+ 1. Where are you starting? What can you see?
+ 2. What do you click?
+ 3. More steps…
+ validations:
+ required: true
+ - type: textarea
+ id: result
+ attributes:
+ label: Outcome
+ placeholder: Tell us what went wrong
+ value: |
+ #### What did you expect?
+
+ #### What happened instead?
+ validations:
+ required: true
+ - type: input
+ id: device
+ attributes:
+ label: Your phone model
+ placeholder: e.g. Samsung S6
+ validations:
+ required: false
+ - type: input
+ id: os
+ attributes:
+ label: Operating system version
+ placeholder: e.g. Android 10.0
+ validations:
+ required: false
+ - type: input
+ id: version
+ attributes:
+ label: Application version and app store
+ description: You can find the version information in Settings -> Help & About.
+ placeholder: e.g. Element version 1.7.34, olm version 3.2.3 from F-Droid
+ validations:
+ required: false
+ - type: input
+ id: homeserver
+ attributes:
+ label: Homeserver
+ description: Which server is your account registered on?
+ placeholder: e.g. matrix.org
+ validations:
+ required: false
+ - type: dropdown
+ id: rageshake
+ attributes:
+ label: Will you send logs?
+ description: |
+ Did you know that you can shake your phone to submit logs for this issue? Trigger the defect, then shake your phone and you will see a popup asking if you would like to open the bug report screen. Click YES, and describe the issue, mentioning that you have also filed a bug (it's helpful if you can include a link to the bug). Send the report to submit anonymous logs to the developers.
+ options:
+ - 'Yes'
+ - 'No'
+ validations:
+ required: true
diff --git a/.github/ISSUE_TEMPLATE/bug_report.md b/.github/ISSUE_TEMPLATE/bug_report.md
deleted file mode 100644
index d7c3506fa0..0000000000
--- a/.github/ISSUE_TEMPLATE/bug_report.md
+++ /dev/null
@@ -1,34 +0,0 @@
----
-name: Bug report
-about: Create a report to help us improve Element
-title: ''
-labels: ''
-assignees: ''
-
----
-
-#### Describe the bug
-A clear and concise description of what the bug is.
-
-#### To Reproduce
-Steps to reproduce the behavior:
-1. Go to '...'
-2. Click on '....'
-3. Scroll down to '....'
-4. See error
-
-#### Expected behavior
-A clear and concise description of what you expected to happen.
-
-#### Screenshots
-If applicable, add screenshots to help explain your problem.
-
-#### Smartphone (please complete the following information):
- - Device: [e.g. Samsung S6]
- - OS: [e.g. Android 6.0]
-
-#### Additional context
- - App version and store [e.g. 1.0.0 - F-Droid]
- - Homeserver: [e.g. matrix.org]
-
-Add any other context about the problem here.
diff --git a/.github/ISSUE_TEMPLATE/enhancement.yml b/.github/ISSUE_TEMPLATE/enhancement.yml
new file mode 100644
index 0000000000..71adce718e
--- /dev/null
+++ b/.github/ISSUE_TEMPLATE/enhancement.yml
@@ -0,0 +1,36 @@
+name: Enhancement request
+description: Do you have a suggestion or feature request?
+labels: [T-Enhancement]
+body:
+ - type: markdown
+ attributes:
+ value: |
+ Thank you for taking the time to propose a new feature or make a suggestion.
+ - type: textarea
+ id: usecase
+ attributes:
+ label: Your use case
+ description: Please feel welcome to include screenshots or mock ups.
+ placeholder: Tell us what you would like to do!
+ value: |
+ #### What would you like to do?
+
+ #### Why would you like to do it?
+
+ #### How would you like to achieve it?
+ validations:
+ required: true
+ - type: textarea
+ id: alternative
+ attributes:
+ label: Have you considered any alternatives?
+ placeholder: A clear and concise description of any alternative solutions or features you've considered.
+ validations:
+ required: false
+ - type: textarea
+ id: additional-context
+ attributes:
+ label: Additional context
+ placeholder: Is there anything else you'd like to add?
+ validations:
+ required: false
diff --git a/.github/ISSUE_TEMPLATE/feature_request.md b/.github/ISSUE_TEMPLATE/feature_request.md
deleted file mode 100644
index da96d461c5..0000000000
--- a/.github/ISSUE_TEMPLATE/feature_request.md
+++ /dev/null
@@ -1,20 +0,0 @@
----
-name: Feature request
-about: Suggest an idea for this project
-title: ''
-labels: type:suggestion
-assignees: ''
-
----
-
-#### Is your feature request related to a problem? Please describe.
-A clear and concise description of what the problem is. Ex. I'm always frustrated when [...]
-
-#### Describe the solution you'd like.
-A clear and concise description of what you want to happen.
-
-#### Describe alternatives you've considered.
-A clear and concise description of any alternative solutions or features you've considered.
-
-#### Additional context
-Add any other context or screenshots about the feature request here.
diff --git a/.github/ISSUE_TEMPLATE/matrix-sdk.md b/.github/ISSUE_TEMPLATE/matrix-sdk.md
deleted file mode 100644
index 30f705a575..0000000000
--- a/.github/ISSUE_TEMPLATE/matrix-sdk.md
+++ /dev/null
@@ -1,10 +0,0 @@
----
-name: Matrix SDK
-about: Report issue or ask for a feature regarding the Android Matrix SDK
-title: "[SDK] "
-labels: matrix-sdk
-assignees: ''
-
----
-
-
diff --git a/.github/ISSUE_TEMPLATE/matrix-sdk.yml b/.github/ISSUE_TEMPLATE/matrix-sdk.yml
new file mode 100644
index 0000000000..4033423dd5
--- /dev/null
+++ b/.github/ISSUE_TEMPLATE/matrix-sdk.yml
@@ -0,0 +1,20 @@
+name: Matrix SDK bug or enhancement
+description: Report issue or ask for a feature in the [Android Matrix SDK](https://github.com/matrix-org/matrix-android-sdk2)
+title: "[SDK] "
+labels: [matrix-sdk]
+
+body:
+ - type: markdown
+ attributes:
+ value: |
+ Thanks for taking the time to fill out this issue!
+
+ Please report security issues by email to security@matrix.org
+ - type: textarea
+ id: description
+ attributes:
+ label: Description
+ description: Report issue or ask for a feature in the [Android Matrix SDK](https://github.com/matrix-org/matrix-android-sdk2)
+ placeholder: This issue template should be used by third party application maintainers, to report a bug or to request a feature on the SDK module of the Element Android application.
+ validations:
+ required: true
diff --git a/.github/ISSUE_TEMPLATE/release.md b/.github/ISSUE_TEMPLATE/release.md
deleted file mode 100644
index 154e93286c..0000000000
--- a/.github/ISSUE_TEMPLATE/release.md
+++ /dev/null
@@ -1,84 +0,0 @@
----
-name: Release
-about: Checklist for each release. To be used by the core team only.
-title: "[Release] Element Android v"
-labels: "\U0001F680 Release"
-assignees: bmarty
-
----
-
-For the example, we are releasing the version 1.1.10. Delete this line and replace 1.1.10 with the version in the issue content.
-
-### Before the release
-
-- [ ] Weblate sync, fix lint issue if any (in a dedicated PR)
-- [ ] Check the update of the store descriptions (using Google Translate if necessary) to ensure that the changes are acceptable to be published to the stores.
-- [ ] Run the script `./tools/release/pushPlayStoreMetaData.sh`. You can check in the GooglePlay console the Activity log to check the effect.
-
-### Do the release
-
-- [ ] Create release with gitflow, branch name `release/1.1.10`
-- [ ] Run `./tools/import_emojis.py` and commit the change if any.
-- [ ] Run `./tools/import_sas_strings.py` and commit the change if any. If there is no change since a while, ping Travis
-- [ ] Check the crashes from the PlayStore
-- [ ] Check the rageshake with the current dev version: https://github.com/matrix-org/element-android-rageshakes/labels/1.1.10-dev
-- [ ] Run the integration test, and especially `UiAllScreensSanityTest.allScreensTest()`
-- [ ] Create an account on matrix.org
-- [ ] Run towncrier: `towncrier --version v1.1.10 --draft` (remove `--draft` do write the file CHANGES.md)
-- [ ] Add file for fastlane under ./fastlane/metadata/android/en-US/changelogs
-- [ ] Push the branch and start a draft PR (will not be merged), to check that the CI is happy with all the changes.
-- [ ] Finish release with gitflow, delete the draft PR
-- [ ] Push `main` and the new tag `v1.1.10` to origin
-- [ ] Checkout `develop`
-- [ ] Increase version in `./vector/build.gradle`
-- [ ] Commit and push `develop`
-- [ ] Wait for [Buildkite](https://buildkite.com/matrix-dot-org/element-android/builds?branch=main) to build the `main` branch.
-- [ ] Run the script `~/scripts/releaseElement.sh`. It will download the APKs from Buildkite check them and sign them.
-- [ ] Install the APK on your phone to check that the upgrade went well (no init sync, etc.)
-- [ ] Create a new beta release on the GooglePlay console and upload the 4 signed Apks.
-- [ ] Check that the version codes are correct
-- [ ] Copy the fastlane change to the GooglePlay console in the section en-GB.
-- [ ] Push to beta release to 100% of the users
-- [ ] Create the release on gitHub [from the tag](https://github.com/vector-im/element-android/tags), copy paste the block from the file CHANGES.md
-- [ ] Add the 4 signed APKs to the GitHub release
-- [ ] Ping the Android Internal room
-- [ ] Add an entry in the internal diary
-
-### Once Live on PlayStore
-
-- [ ] Ping the Android public room and update its topic
-
-### After at least 2 days
-
-- [ ] Check the [rageshakes](https://github.com/matrix-org/element-android-rageshakes/issues)
-- [ ] Check the crash reports on the GooglePlay console
-- [ ] Check the Android Element room for any reported issues on the new version
-- [ ] If all is OK, push to production and notify Markus (Bubu) to release the F-Droid version
-- [ ] Ping the Android public room and update its topic with the new available version
-
-### Android SDK2
-
-- [ ] Checkout the `main` branch on Element Android project
-
-#### On the SDK2 project
-
-https://github.com/matrix-org/matrix-android-sdk2
-
-- [ ] Create a release with GitFlow
-- [ ] Update the files `./build.gradle` and `./gradle/gradle-wrapper.properties` manually, to use the latest version for the dependency. You can get inspired by the same files on Element Android project.
-- [ ] Run the script `./tools/import_from_element.sh`
-- [ ] Update the version in `./matrix-sdk-android/build.gradle` and let the script finish to build the library
-- [ ] Update the file `CHANGES.md`
-- [ ] Finish the release using GitFlow
-- [ ] Create the release on GitHub from [the tag](https://github.com/matrix-org/matrix-android-sdk2/tags)
-- [ ] Upload the AAR on the GitHub release
-
-### Android SDK2 sample
-
-https://github.com/matrix-org/matrix-android-sdk2-sample
-
-- [ ] Update the dependency to the new version of the SDK2. Jitpack will have to build the AAR, it can take a few minutes. You can check status on https://jitpack.io/#matrix-org/matrix-android-sdk2
-- [ ] Build and run the sample, you may have to fix some API break
-- [ ] Commit and push directly on `main`
-
-
diff --git a/.github/ISSUE_TEMPLATE/release.yml b/.github/ISSUE_TEMPLATE/release.yml
new file mode 100644
index 0000000000..7ac55427a9
--- /dev/null
+++ b/.github/ISSUE_TEMPLATE/release.yml
@@ -0,0 +1,104 @@
+name: Release checklist
+description: Checklist for each release. This template is only for the core team.
+title: "[Release] Element Android v"
+labels: [🚀 Release]
+assignees:
+ - bmarty
+
+body:
+ - type: textarea
+ id: checklist
+ attributes:
+ label: Release checklist
+ description: For the template example, we are releasing the version 1.1.10. Replace 1.1.10 with the version in the issue body.
+ placeholder: |
+ If you are reading this, you have deleted the content of the release template: undo the deletion or start again.
+ value: |
+ ### Before the release
+
+ - [ ] Weblate sync, fix lint issue if any (in a dedicated PR)
+ - [ ] Check the update of the store descriptions (using Google Translate if necessary) to ensure that the changes are acceptable to be published to the stores.
+ - [ ] Run the script `./tools/release/pushPlayStoreMetaData.sh`. You can check in the GooglePlay console the Activity log to check the effect.
+
+ ### Do the release
+
+ - [ ] Create release with gitflow, branch name `release/1.1.10`
+ - [ ] Check the crashes from the PlayStore
+ - [ ] Check the rageshake with the current dev version: https://github.com/matrix-org/element-android-rageshakes/labels/1.1.10-dev
+ - [ ] Run the integration test, and especially `UiAllScreensSanityTest.allScreensTest()`
+ - [ ] Create an account on matrix.org
+ - [ ] Run towncrier: `towncrier --version v1.1.10 --draft` (remove `--draft` do write the file CHANGES.md)
+ - [ ] Add file for fastlane under ./fastlane/metadata/android/en-US/changelogs
+ - [ ] Push the branch and start a draft PR (will not be merged), to check that the CI is happy with all the changes.
+ - [ ] Finish release with gitflow, delete the draft PR
+ - [ ] Push `main` and the new tag `v1.1.10` to origin
+ - [ ] Checkout `develop`
+ - [ ] Increase version in `./vector/build.gradle`
+ - [ ] Change the value of SDK_VERSION in the file `./matrix-sdk-android/build.gradle`
+ - [ ] Commit and push `develop`
+ - [ ] Wait for [Buildkite](https://buildkite.com/matrix-dot-org/element-android/builds?branch=main) to build the `main` branch.
+ - [ ] Run the script `~/scripts/releaseElement.sh`. It will download the APKs from Buildkite check them and sign them.
+ - [ ] Install the APK on your phone to check that the upgrade went well (no init sync, etc.)
+ - [ ] Create a new beta release on the GooglePlay console and upload the 4 signed Apks.
+ - [ ] Check that the version codes are correct
+ - [ ] Copy the fastlane change to the GooglePlay console in the section en-GB.
+ - [ ] Push to beta release to 100% of the users
+ - [ ] Create the release on gitHub [from the tag](https://github.com/vector-im/element-android/tags), copy paste the block from the file CHANGES.md
+ - [ ] Add the 4 signed APKs to the GitHub release
+ - [ ] Ping the Android Internal room
+ - [ ] Add an entry in the internal diary
+
+ ### Once Live on PlayStore
+
+ - [ ] Ping the Android public room and update its topic
+
+ ### After at least 2 days
+
+ - [ ] Check the [rageshakes](https://github.com/matrix-org/element-android-rageshakes/issues)
+ - [ ] Check the crash reports on the GooglePlay console
+ - [ ] Check the Android Element room for any reported issues on the new version
+ - [ ] If all is OK, push to production and notify Markus (Bubu) to release the F-Droid version
+ - [ ] Ping the Android public room and update its topic with the new available version
+
+ ### Android SDK2
+
+ - [ ] Checkout the `main` branch on Element Android project
+
+ #### On the SDK2 project
+
+ https://github.com/matrix-org/matrix-android-sdk2
+
+ - [ ] Create a release with GitFlow
+ - [ ] Update the value of VERSION_NAME in the file gradle.properties
+ - [ ] Update the files `./build.gradle` and `./gradle/gradle-wrapper.properties` manually, to use the latest version for the dependency. You can get inspired by the same files on Element Android project.
+ - [ ] Run the script `./tools/import_from_element.sh`
+ - [ ] Check the diff in the file `./matrix-sdk-android/build.gradle` and restore what may have been erased (in particular the line `apply plugin: "com.vanniktech.maven.publish"` and the line about the version)
+ - [ ] Let the script finish to build the library
+ - [ ] Update the file `CHANGES.md`
+ - [ ] Finish the release using GitFlow
+ - [ ] Push the branch `main`, the new tag and the branch `develop` to origin
+
+ ##### Release on MavenCentral
+
+ - [ ] Run the command `./gradlew publish --no-daemon --no-parallel`. You'll need some non-public element to do so
+ - [ ] Connect to https://s01.oss.sonatype.org
+ - [ ] Click on Staging Repositories and check the the files have been uploaded
+ - [ ] Click on close
+ - [ ] Wait (check Activity tab until step "Repository closed" is displayed)
+ - [ ] Click on release. The staging repository will disappear
+ - [ ] Check that the release is available in https://repo1.maven.org/maven2/org/matrix/android/matrix-android-sdk2/ (it can take a few minutes)
+
+ ##### Release on GitHub
+
+ - [ ] Create the release on GitHub from [the tag](https://github.com/matrix-org/matrix-android-sdk2/tags)
+ - [ ] Upload the AAR on the GitHub release
+
+ ### Android SDK2 sample
+
+ https://github.com/matrix-org/matrix-android-sdk2-sample
+
+ - [ ] Update the dependency to the new version of the SDK2. It can take some time for MavenCentral to make the librarie available. You can check status on https://repo1.maven.org/maven2/org/matrix/android/matrix-android-sdk2/
+ - [ ] Build and run the sample, you may have to fix some API break
+ - [ ] Commit and push directly on `main`
+ validations:
+ required: true
diff --git a/.github/PULL_REQUEST_TEMPLATE.md b/.github/PULL_REQUEST_TEMPLATE.md
index 8fbc5602fe..eb30c18fcf 100644
--- a/.github/PULL_REQUEST_TEMPLATE.md
+++ b/.github/PULL_REQUEST_TEMPLATE.md
@@ -1,10 +1,16 @@
### Pull Request Checklist
-
+
- [ ] Changes has been tested on an Android device or Android emulator with API 21
- [ ] UI change has been tested on both light and dark themes
+- [ ] Accessibility has been taken into account. See https://github.com/vector-im/element-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-android/blob/develop/CONTRIBUTING.md#changelog
- [ ] Pull request includes screenshots or videos if containing UI changes
-- [ ] Pull request includes a [sign off](https://github.com/matrix-org/synapse/blob/master/CONTRIBUTING.md#sign-off)
+- [ ] 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
+- [ ] If you have modified the screen flow, or added new screens to the application, you have updated the test [UiAllScreensSanityTest.allScreensTest()](https://github.com/vector-im/element-android/blob/main/vector/src/androidTest/java/im/vector/app/ui/UiAllScreensSanityTest.kt#L73)
diff --git a/.github/dependabot.yml b/.github/dependabot.yml
index e552f5fd43..8c2f1041e0 100644
--- a/.github/dependabot.yml
+++ b/.github/dependabot.yml
@@ -18,6 +18,5 @@ updates:
open-pull-requests-limit: 200
reviewers:
- "bmarty"
-### ignore:
-### - dependency-name: com.squareup.okhttp3:logging-interceptor
-### versions: "> 3.12.10"
+ ignore:
+ - dependency-name: com.google.zxing:core
diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml
index 85148a2632..91dc6d830b 100644
--- a/.github/workflows/build.yml
+++ b/.github/workflows/build.yml
@@ -5,6 +5,12 @@ on:
push:
branches: [ main, develop ]
+# Enrich gradle.properties for CI/CD
+env:
+ CI_GRADLE_ARG_PROPERTIES: >
+ -Porg.gradle.jvmargs=-Xmx2g
+ -Porg.gradle.parallel=false
+
jobs:
debug:
name: Build debug APKs (${{ matrix.target }})
@@ -25,7 +31,7 @@ jobs:
restore-keys: |
${{ runner.os }}-gradle-
- name: Assemble ${{ matrix.target }} debug apk
- run: ./gradlew assemble${{ matrix.target }}Debug --stacktrace
+ run: ./gradlew assemble${{ matrix.target }}Debug $CI_GRADLE_ARG_PROPERTIES --stacktrace
- name: Upload ${{ matrix.target }} debug APKs
uses: actions/upload-artifact@v2
with:
@@ -48,7 +54,7 @@ jobs:
restore-keys: |
${{ runner.os }}-gradle-
- name: Assemble GPlay unsigned apk
- run: ./gradlew clean assembleGplayRelease --stacktrace
+ run: ./gradlew clean assembleGplayRelease $CI_GRADLE_ARG_PROPERTIES --stacktrace
- name: Upload Gplay unsigned APKs
uses: actions/upload-artifact@v2
with:
diff --git a/.github/workflows/integration.yml b/.github/workflows/integration.yml
index cb6f1b0e48..c18ca69fde 100644
--- a/.github/workflows/integration.yml
+++ b/.github/workflows/integration.yml
@@ -5,15 +5,45 @@ on:
push:
branches: [ main, develop ]
+# Enrich gradle.properties for CI/CD
+env:
+ CI_GRADLE_ARG_PROPERTIES: >
+ -Porg.gradle.jvmargs=-Xmx2g
+ -Porg.gradle.parallel=false
+
jobs:
+ # Temporary add build of Android tests, which cannot be run on the CI right now, but they need to at least compile
+ # So it will be mandatory for this action to be successful on every PRs
+ compile-android-test:
+ name: Compile Android tests
+ runs-on: ubuntu-latest
+ steps:
+ - uses: actions/checkout@v2
+ - uses: actions/cache@v2
+ with:
+ path: |
+ ~/.gradle/caches
+ ~/.gradle/wrapper
+ key: ${{ runner.os }}-gradle-${{ hashFiles('**/*.gradle*', '**/gradle-wrapper.properties') }}
+ restore-keys: |
+ ${{ runner.os }}-gradle-
+ - name: Compile Android tests
+ run: ./gradlew clean assembleAndroidTest $CI_GRADLE_ARG_PROPERTIES --stacktrace -PallWarningsAsErrors=false
+
integration-tests:
name: Integration Tests (Synapse)
runs-on: ubuntu-latest
strategy:
+ fail-fast: false
matrix:
- api-level: [21, 30]
+ api-level: [28]
steps:
- uses: actions/checkout@v2
+ - uses: gradle/wrapper-validation-action@v1
+ - uses: actions/setup-java@v2
+ with:
+ distribution: 'adopt'
+ java-version: 11
- name: Set up Python 3.8
uses: actions/setup-python@v2
with:
@@ -45,5 +75,12 @@ jobs:
uses: reactivecircus/android-emulator-runner@v2
with:
api-level: ${{ matrix.api-level }}
+ #arch: x86_64
+ #disable-animations: true
# script: ./gradlew -PallWarningsAsErrors=false vector:connectedAndroidTest matrix-sdk-android:connectedAndroidTest
- script: ./gradlew -PallWarningsAsErrors=false connectedCheck
+ arch: x86
+ profile: Nexus 5X
+ force-avd-creation: false
+ emulator-options: -no-snapshot-save -no-window -gpu swiftshader_indirect -noaudio -no-boot-anim -camera-back none
+ emulator-build: 7425822
+ script: ./gradlew $CI_GRADLE_ARG_PROPERTIES -PallWarningsAsErrors=false connectedCheck --stacktrace
diff --git a/.github/workflows/quality.yml b/.github/workflows/quality.yml
index a65e6b5dee..5ccd00a02b 100644
--- a/.github/workflows/quality.yml
+++ b/.github/workflows/quality.yml
@@ -14,16 +14,21 @@ jobs:
- name: Run code quality check suite
run: ./tools/check/check_code_quality.sh
- klint:
+ ktlint:
name: Kotlin Linter
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- - name: Run klint
+ - name: Run ktlint
run: |
- curl -sSLO https://github.com/pinterest/ktlint/releases/download/0.36.0/ktlint && chmod a+x ktlint
- ./ktlint --android --experimental -v
+ ./gradlew ktlintCheck --continue
+ - name: Upload reports
+ uses: actions/upload-artifact@v2
+ with:
+ name: ktlinting-report
+ path: vector/build/reports/ktlint/*.*
+# Lint for main module and all the other modules
android-lint:
name: Android Linter
runs-on: ubuntu-latest
@@ -37,14 +42,16 @@ jobs:
key: ${{ runner.os }}-gradle-${{ hashFiles('**/*.gradle*', '**/gradle-wrapper.properties') }}
restore-keys: |
${{ runner.os }}-gradle-
- - name: Lint analysis of the SDK
- run: ./gradlew clean :matrix-sdk-android:lintRelease --stacktrace
+ - name: Lint analysis
+ run: ./gradlew clean :vector:lint --stacktrace
- name: Upload reports
uses: actions/upload-artifact@v2
with:
- name: linting-report-android-sdk
- path: matrix-sdk-android/build/reports/*.*
+ name: lint-report
+ path: |
+ vector/build/reports/*.*
+# Lint for Gplay and Fdroid release APK
apk-lint:
name: Lint APK (${{ matrix.target }})
runs-on: ubuntu-latest
@@ -69,6 +76,6 @@ jobs:
uses: actions/upload-artifact@v2
if: always()
with:
- name: release-debug-linting-report-${{ matrix.target }}
+ name: release-lint-report-${{ matrix.target }}
path: |
vector/build/reports/*.*
diff --git a/.github/workflows/sanity_test.yml b/.github/workflows/sanity_test.yml
new file mode 100644
index 0000000000..53b70276c5
--- /dev/null
+++ b/.github/workflows/sanity_test.yml
@@ -0,0 +1,79 @@
+name: Sanity Test
+
+on:
+ schedule:
+ # At 20:00 every day UTC
+ - cron: '0 20 * * *'
+
+# Enrich gradle.properties for CI/CD
+env:
+ CI_GRADLE_ARG_PROPERTIES: >
+ -Porg.gradle.jvmargs=-Xmx2g
+ -Porg.gradle.parallel=false
+
+jobs:
+ integration-tests:
+ name: Sanity Tests (Synapse)
+ runs-on: macos-latest
+ strategy:
+ fail-fast: false
+ matrix:
+ api-level: [ 29 ]
+ steps:
+ - uses: actions/checkout@v2
+ with:
+ ref: develop
+ - name: Set up Python 3.8
+ uses: actions/setup-python@v2
+ with:
+ python-version: 3.8
+ - name: Cache pip
+ uses: actions/cache@v2
+ with:
+ path: ~/.cache/pip
+ key: ${{ runner.os }}-pip
+ restore-keys: |
+ ${{ runner.os }}-pip-
+ ${{ runner.os }}-
+ - uses: actions/cache@v2
+ with:
+ path: |
+ ~/.gradle/caches
+ ~/.gradle/wrapper
+ key: ${{ runner.os }}-gradle-${{ hashFiles('**/*.gradle*', '**/gradle-wrapper.properties') }}
+ restore-keys: |
+ ${{ runner.os }}-gradle-
+ - name: Start synapse server
+ run: |
+ python3 -m venv .synapse
+ source .synapse/bin/activate
+ pip install synapse matrix-synapse
+ curl -sL https://raw.githubusercontent.com/matrix-org/synapse/develop/demo/start.sh \
+ | sed s/127.0.0.1/0.0.0.0/g | sed 's/http:\/\/localhost/http:\/\/10.0.2.2/g' | bash -s -- --no-rate-limit
+ - uses: actions/setup-java@v2
+ with:
+ distribution: 'adopt'
+ java-version: '11'
+ - name: Run sanity tests on API ${{ matrix.api-level }}
+ uses: reactivecircus/android-emulator-runner@v2
+ continue-on-error: true # allow pipeline to upload failure results
+ with:
+ emulator-options: -no-snapshot-save -no-window -gpu swiftshader_indirect -noaudio -no-boot-anim -camera-back none
+ api-level: ${{ matrix.api-level }}
+ emulator-build: 7425822 # workaround to emulator bug: https://github.com/ReactiveCircus/android-emulator-runner/issues/160
+ script: |
+ adb root
+ adb logcat -c
+ touch emulator.log
+ chmod 777 emulator.log
+ adb logcat >> emulator.log &
+ ./gradlew $CI_GRADLE_ARG_PROPERTIES -PallWarningsAsErrors=false connectedGplayDebugAndroidTest -Pandroid.testInstrumentationRunnerArguments.class=im.vector.app.ui.UiAllScreensSanityTest || adb pull storage/emulated/0/Pictures/failure_screenshots
+
+ - name: Upload Failing Test Report Log
+ if: failure()
+ uses: actions/upload-artifact@v2
+ with:
+ name: sanity-error-results
+ path: |
+ emulator.log
+ failure_screenshots/
diff --git a/.github/workflows/sync-from-external-sources.yml b/.github/workflows/sync-from-external-sources.yml
new file mode 100644
index 0000000000..6a4f8ef147
--- /dev/null
+++ b/.github/workflows/sync-from-external-sources.yml
@@ -0,0 +1,69 @@
+name: Sync Data From External Sources
+on:
+ schedule:
+ # At 00:00 on every Monday UTC
+ - cron: '0 0 * * 1'
+
+jobs:
+ sync-emojis:
+ runs-on: ubuntu-latest
+ steps:
+ - uses: actions/checkout@v2
+ - name: Set up Python 3.8
+ uses: actions/setup-python@v2
+ with:
+ python-version: 3.8
+ - name: Cache pip
+ uses: actions/cache@v2
+ with:
+ path: ~/.cache/pip
+ key: ${{ runner.os }}-pip
+ restore-keys: |
+ ${{ runner.os }}-pip-
+ ${{ runner.os }}-
+ - name: Install Prerequisite dependencies
+ run: |
+ pip install BeautifulSoup4
+ pip install requests
+ - name: Run Emoji script
+ run: ./tools/import_emojis.py
+ - name: Create Pull Request for Emojis
+ uses: peter-evans/create-pull-request@v3
+ with:
+ commit-message: Sync Emojis
+ title: Sync Emojis
+ body: |
+ - Update Emojis from Unicode.org
+ branch: sync-emojis
+ base: develop
+
+ sync-sas-strings:
+ runs-on: ubuntu-latest
+ steps:
+ - uses: actions/checkout@v2
+ - name: Set up Python 3.8
+ uses: actions/setup-python@v2
+ with:
+ python-version: 3.8
+ - name: Cache pip
+ uses: actions/cache@v2
+ with:
+ path: ~/.cache/pip
+ key: ${{ runner.os }}-pip
+ restore-keys: |
+ ${{ runner.os }}-pip-
+ ${{ runner.os }}-
+ - name: Install Prerequisite dependencies
+ run: |
+ pip install requests
+ - name: Run SAS String script
+ run: ./tools/import_sas_strings.py
+ - name: Create Pull Request for SAS Strings
+ uses: peter-evans/create-pull-request@v3
+ with:
+ commit-message: Sync SAS Strings
+ title: Sync SAS Strings
+ body: |
+ - Update SAS Strings from matrix-doc.
+ branch: sync-sas-strings
+ base: develop
\ No newline at end of file
diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml
index 6e51368ce5..50195638de 100644
--- a/.github/workflows/tests.yml
+++ b/.github/workflows/tests.yml
@@ -5,6 +5,12 @@ on:
push:
branches: [main, develop]
+# Enrich gradle.properties for CI/CD
+env:
+ CI_GRADLE_ARG_PROPERTIES: >
+ -Porg.gradle.jvmargs=-Xmx2g
+ -Porg.gradle.parallel=false
+
jobs:
unit-tests:
name: Run Unit Tests
@@ -20,4 +26,11 @@ jobs:
restore-keys: |
${{ runner.os }}-gradle-
- name: Run unit tests
- run: ./gradlew clean test --stacktrace -PallWarningsAsErrors=false
+ run: ./gradlew clean test $CI_GRADLE_ARG_PROPERTIES -PallWarningsAsErrors=false --stacktrace
+ - name: Publish Unit Test Results
+ uses: EnricoMi/publish-unit-test-result-action@v1
+ if: always() &&
+ github.event.sender.login != 'dependabot[bot]' &&
+ ( github.event_name != 'pull_request' || github.event.pull_request.head.repo.full_name == github.repository )
+ with:
+ files: ./**/build/test-results/**/*.xml
diff --git a/.github/workflows/triage-incoming.yml b/.github/workflows/triage-incoming.yml
new file mode 100644
index 0000000000..4ecc824424
--- /dev/null
+++ b/.github/workflows/triage-incoming.yml
@@ -0,0 +1,15 @@
+name: Move new issues onto Issue triage board
+
+on:
+ issues:
+ types: [opened]
+
+jobs:
+ automate-project-columns:
+ runs-on: ubuntu-latest
+ steps:
+ - uses: alex-page/github-project-automation-plus@bb266ff4dde9242060e2d5418e120a133586d488
+ with:
+ project: Issue triage
+ column: Incoming
+ repo-token: ${{ secrets.ELEMENT_BOT_TOKEN }}
diff --git a/.github/workflows/triage-move-labelled.yml b/.github/workflows/triage-move-labelled.yml
new file mode 100644
index 0000000000..f910cdf7ea
--- /dev/null
+++ b/.github/workflows/triage-move-labelled.yml
@@ -0,0 +1,124 @@
+name: Move labelled issues to correct boards and columns
+
+on:
+ issues:
+ types: [labeled]
+
+jobs:
+ move_needs_info_issues:
+ name: Move X-Needs-Info issues to Need info on triage board
+ runs-on: ubuntu-latest
+ steps:
+ - uses: konradpabjan/move-labeled-or-milestoned-issue@219d384e03fa4b6460cd24f9f37d19eb033a4338
+ with:
+ action-token: "${{ secrets.ELEMENT_BOT_TOKEN }}"
+ project-url: "https://github.com/vector-im/element-android/projects/4"
+ column-name: "Need info"
+ label-name: "X-Needs-Info"
+
+ add_priority_design_issues_to_project:
+ name: Move priority X-Needs-Design issues to Design project board
+ runs-on: ubuntu-latest
+ if: >
+ contains(github.event.issue.labels.*.name, 'X-Needs-Design') &&
+ (contains(github.event.issue.labels.*.name, 'O-Frequent') ||
+ contains(github.event.issue.labels.*.name, 'O-Occasional')) &&
+ (contains(github.event.issue.labels.*.name, 'S-Critical') ||
+ contains(github.event.issue.labels.*.name, 'S-Major') ||
+ contains(github.event.issue.labels.*.name, 'S-Minor'))
+ steps:
+ - uses: octokit/graphql-action@v2.x
+ id: add_to_project
+ with:
+ headers: '{"GraphQL-Features": "projects_next_graphql"}'
+ query: |
+ mutation add_to_project($projectid:String!,$contentid:String!) {
+ addProjectNextItem(input:{projectId:$projectid contentId:$contentid}) {
+ projectNextItem {
+ id
+ }
+ }
+ }
+ projectid: ${{ env.PROJECT_ID }}
+ contentid: ${{ github.event.issue.node_id }}
+ env:
+ PROJECT_ID: "PN_kwDOAM0swc0sUA"
+ GITHUB_TOKEN: ${{ secrets.ELEMENT_BOT_TOKEN }}
+
+ move_spaces_issues:
+ name: Move Spaces issues to Delight project board
+ runs-on: ubuntu-latest
+ if: >
+ contains(github.event.issue.labels.*.name, 'A-Spaces') ||
+ contains(github.event.issue.labels.*.name, 'A-Space-Settings') ||
+ contains(github.event.issue.labels.*.name, 'A-Subspaces')
+ steps:
+ - uses: konradpabjan/move-labeled-or-milestoned-issue@219d384e03fa4b6460cd24f9f37d19eb033a4338
+ with:
+ action-token: "${{ secrets.ELEMENT_BOT_TOKEN }}"
+ project-url: "https://github.com/orgs/vector-im/projects/6"
+ column-name: "📥 Inbox"
+ label-name: "A-Spaces"
+ - uses: octokit/graphql-action@v2.x
+ id: add_to_delight2
+ with:
+ headers: '{"GraphQL-Features": "projects_next_graphql"}'
+ query: |
+ mutation add_to_project($projectid:String!,$contentid:String!) {
+ addProjectNextItem(input:{projectId:$projectid contentId:$contentid}) {
+ projectNextItem {
+ id
+ }
+ }
+ }
+ projectid: ${{ env.PROJECT_ID }}
+ contentid: ${{ github.event.issue.node_id }}
+ env:
+ PROJECT_ID: "PN_kwDOAM0swc1HvQ"
+ GITHUB_TOKEN: ${{ secrets.ELEMENT_BOT_TOKEN }}
+
+ move_voice-message_issues:
+ name: Move A-Voice Messages to Voice message board
+ runs-on: ubuntu-latest
+ if: >
+ contains(github.event.issue.labels.*.name, 'A-Voice Messages')
+ steps:
+ - uses: octokit/graphql-action@v2.x
+ with:
+ headers: '{"GraphQL-Features": "projects_next_graphql"}'
+ query: |
+ mutation add_to_project($projectid:String!,$contentid:String!) {
+ addProjectNextItem(input:{projectId:$projectid contentId:$contentid}) {
+ projectNextItem {
+ id
+ }
+ }
+ }
+ projectid: ${{ env.PROJECT_ID }}
+ contentid: ${{ github.event.issue.node_id }}
+ env:
+ PROJECT_ID: "PN_kwDOAM0swc2KCw"
+ GITHUB_TOKEN: ${{ secrets.ELEMENT_BOT_TOKEN }}
+
+ move_threads_issues:
+ name: Move A-Threads to Thread board
+ runs-on: ubuntu-latest
+ if: >
+ contains(github.event.issue.labels.*.name, 'A-Threads')
+ steps:
+ - uses: octokit/graphql-action@v2.x
+ with:
+ headers: '{"GraphQL-Features": "projects_next_graphql"}'
+ query: |
+ mutation add_to_project($projectid:String!,$contentid:String!) {
+ addProjectNextItem(input:{projectId:$projectid contentId:$contentid}) {
+ projectNextItem {
+ id
+ }
+ }
+ }
+ projectid: ${{ env.PROJECT_ID }}
+ contentid: ${{ github.event.issue.node_id }}
+ env:
+ PROJECT_ID: "PN_kwDOAM0swc0rRA"
+ GITHUB_TOKEN: ${{ secrets.ELEMENT_BOT_TOKEN }}
diff --git a/.github/workflows/triage-move-unlabelled.yml b/.github/workflows/triage-move-unlabelled.yml
new file mode 100644
index 0000000000..94bd049b91
--- /dev/null
+++ b/.github/workflows/triage-move-unlabelled.yml
@@ -0,0 +1,35 @@
+name: Move unlabelled from needs info columns to triaged
+
+on:
+ issues:
+ types: [unlabeled]
+
+jobs:
+ Move_Unabeled_Issue_On_Project_Board:
+ name: Move no longer X-Needs-Info issues to Triaged
+ runs-on: ubuntu-latest
+ if: >
+ ${{
+ !contains(github.event.issue.labels.*.name, 'X-Needs-Info') }}
+ env:
+ BOARD_NAME: "Issue triage"
+ OWNER: ${{ github.repository_owner }}
+ REPO: ${{ github.event.repository.name }}
+ ISSUE: ${{ github.event.issue.number }}
+ steps:
+ - name: Check if issue is already in "${{ env.BOARD_NAME }}"
+ run: |
+ if curl -i -H 'Content-Type: application/json' -H "Authorization: bearer ${{ secrets.GITHUB_TOKEN }}" -X POST -d '{"query": "query($issue: Int!, $owner: String!, $repo: String!) { repository(owner: $owner, name: $repo) { issue(number: $issue) { projectCards { nodes { project { name } } } } } } ", "variables" : "{ \"issue\": '${ISSUE}', \"owner\": \"'${OWNER}'\", \"repo\": \"'${REPO}'\" }" }' https://api.github.com/graphql | grep "\b$BOARD_NAME\b"; then
+ echo "Issue is already in Project '$BOARD_NAME', proceeding";
+ echo "ALREADY_IN_BOARD=true" >> $GITHUB_ENV
+ else
+ echo "Issue is not in project '$BOARD_NAME', cancelling this workflow"
+ echo "ALREADY_IN_BOARD=false" >> $GITHUB_ENV
+ fi
+ - name: Move issue
+ uses: alex-page/github-project-automation-plus@bb266ff4dde9242060e2d5418e120a133586d488
+ if: ${{ env.ALREADY_IN_BOARD == 'true' }}
+ with:
+ project: Issue triage
+ column: Triaged
+ repo-token: ${{ secrets.ELEMENT_BOT_TOKEN }}
diff --git a/.github/workflows/triage-priority-bugs.yml b/.github/workflows/triage-priority-bugs.yml
new file mode 100644
index 0000000000..018bb8bb55
--- /dev/null
+++ b/.github/workflows/triage-priority-bugs.yml
@@ -0,0 +1,55 @@
+name: Move P1 issues into the P1 column for the App Team and Crypto team
+
+on:
+ issues:
+ types: [labeled, unlabeled]
+
+jobs:
+ p1_issues_to_team_workboard:
+ runs-on: ubuntu-latest
+ if: >
+ (!contains(github.event.issue.labels.*.name, 'A-E2EE') &&
+ !contains(github.event.issue.labels.*.name, 'A-E2EE-Cross-Signing') &&
+ !contains(github.event.issue.labels.*.name, 'A-E2EE-Dehydration') &&
+ !contains(github.event.issue.labels.*.name, 'A-E2EE-Key-Backup') &&
+ !contains(github.event.issue.labels.*.name, 'A-E2EE-SAS-Verification') &&
+ !contains(github.event.issue.labels.*.name, 'A-Spaces') &&
+ !contains(github.event.issue.labels.*.name, 'A-Spaces-Settings') &&
+ !contains(github.event.issue.labels.*.name, 'A-Subspaces')) &&
+ (contains(github.event.issue.labels.*.name, 'T-Defect') &&
+ contains(github.event.issue.labels.*.name, 'S-Critical') &&
+ (contains(github.event.issue.labels.*.name, 'O-Frequent') ||
+ contains(github.event.issue.labels.*.name, 'O-Occasional')) ||
+ contains(github.event.issue.labels.*.name, 'S-Major') &&
+ contains(github.event.issue.labels.*.name, 'O-Frequent') ||
+ contains(github.event.issue.labels.*.name, 'A11y') &&
+ contains(github.event.issue.labels.*.name, 'O-Frequent'))
+ steps:
+ - uses: alex-page/github-project-automation-plus@bb266ff4dde9242060e2d5418e120a133586d488
+ with:
+ project: Android App Team
+ column: P1
+ repo-token: ${{ secrets.ELEMENT_BOT_TOKEN }}
+
+ P1_issues_to_crypto_team_workboard:
+ runs-on: ubuntu-latest
+ if: >
+ (contains(github.event.issue.labels.*.name, 'A-E2EE') ||
+ contains(github.event.issue.labels.*.name, 'A-E2EE-Cross-Signing') ||
+ contains(github.event.issue.labels.*.name, 'A-E2EE-Dehydration') ||
+ contains(github.event.issue.labels.*.name, 'A-E2EE-Key-Backup') ||
+ contains(github.event.issue.labels.*.name, 'A-E2EE-SAS-Verification')) &&
+ (contains(github.event.issue.labels.*.name, 'T-Defect') &&
+ contains(github.event.issue.labels.*.name, 'S-Critical') &&
+ (contains(github.event.issue.labels.*.name, 'O-Frequent') ||
+ contains(github.event.issue.labels.*.name, 'O-Occasional')) ||
+ contains(github.event.issue.labels.*.name, 'S-Major') &&
+ contains(github.event.issue.labels.*.name, 'O-Frequent') ||
+ contains(github.event.issue.labels.*.name, 'A11y') &&
+ contains(github.event.issue.labels.*.name, 'O-Frequent'))
+ steps:
+ - uses: alex-page/github-project-automation-plus@bb266ff4dde9242060e2d5418e120a133586d488
+ with:
+ project: Crypto Team
+ column: Ready
+ repo-token: ${{ secrets.ELEMENT_BOT_TOKEN }}
diff --git a/.gitignore b/.gitignore
index aaab3b7cd5..2661fdd7fe 100644
--- a/.gitignore
+++ b/.gitignore
@@ -8,6 +8,7 @@
.idea/*.xml
.DS_Store
/build
+/benchmark-out
/captures
.externalNativeBuild
rust-sdk/target/*
@@ -18,4 +19,4 @@ Cargo.lock
/fastlane/private
/fastlane/report.xml
-ktlint
+/library/build
diff --git a/CHANGES.md b/CHANGES.md
index 640d56a9fd..9590adc060 100644
--- a/CHANGES.md
+++ b/CHANGES.md
@@ -1,3 +1,261 @@
+Changes in Element v1.3.7 (2021-11-04)
+======================================
+
+Features ✨
+----------
+ - Adding the room name to the invitation notification (if the room summary is available) ([#582](https://github.com/vector-im/element-android/issues/582))
+ - Updating single sign on providers ordering to match priority/popularity ([#4277](https://github.com/vector-im/element-android/issues/4277))
+
+Bugfixes 🐛
+----------
+ - Stops showing a dedicated redacted event notification, the message notifications will update accordingly ([#1491](https://github.com/vector-im/element-android/issues/1491))
+ - Fixes marking individual notifications as read causing other notifications to be dismissed ([#3395](https://github.com/vector-im/element-android/issues/3395))
+ - Fixing missing send button in light mode dev tools - send * event ([#3674](https://github.com/vector-im/element-android/issues/3674))
+ - Fixing room search needing exact casing for non latin-1 character named rooms ([#3968](https://github.com/vector-im/element-android/issues/3968))
+ - Fixing call ringtones only playing once when the ringtone doesn't contain looping metadata (android 9.0 and above) ([#4047](https://github.com/vector-im/element-android/issues/4047))
+ - Tentatively fixing the doubled notifications by updating the group summary at specific points in the notification rendering cycle ([#4152](https://github.com/vector-im/element-android/issues/4152))
+ - Do not show shortcuts if a PIN code is set ([#4170](https://github.com/vector-im/element-android/issues/4170))
+ - Fixes being unable to join rooms by name ([#4255](https://github.com/vector-im/element-android/issues/4255))
+ - Fixing missing F-Droid notifications when in background due to background syncs not triggering ([#4298](https://github.com/vector-im/element-android/issues/4298))
+ - Fix video compression before upload ([#4353](https://github.com/vector-im/element-android/issues/4353))
+ - Fixing QR code crashes caused by a known issue in the zxing library for older versions of android by downgrading to 3.3.3 ([#4361](https://github.com/vector-im/element-android/issues/4361))
+ - Fixing timeline crash when rotating with the emoji window open ([#4365](https://github.com/vector-im/element-android/issues/4365))
+ - Fix handling of links coming from web instance reported as malformed by mistake ([#4369](https://github.com/vector-im/element-android/issues/4369))
+
+SDK API changes ⚠️
+------------------
+ - Add API `LoginWizard.loginCustom(data: JsonDict): Session` to be able to login to a homeserver using arbitrary request content ([#4266](https://github.com/vector-im/element-android/issues/4266))
+ - Add optional deviceId to the login API ([#4334](https://github.com/vector-im/element-android/issues/4334))
+
+Other changes
+-------------
+ - Migrate app DI framework to Hilt ([#3888](https://github.com/vector-im/element-android/issues/3888))
+ - Limit supported TLS versions and cipher suites ([#4192](https://github.com/vector-im/element-android/issues/4192))
+ - Fixed capitalisation of text on initial sync screen ([#4292](https://github.com/vector-im/element-android/issues/4292))
+
+
+Changes in Element v1.3.6 (2021-10-26)
+======================================
+
+Bugfixes 🐛
+----------
+ - Correctly handle url of type https://mobile.element.io/?hs_url=…&is_url=…
+ Skip the choose server screen when such URL are open when Element ([#2684](https://github.com/vector-im/element-android/issues/2684))
+
+
+Changes in Element v1.3.5 (2021-10-25)
+======================================
+
+Bugfixes 🐛
+----------
+ - Fixing malformed link pop up when tapping on notifications ([#4267](https://github.com/vector-im/element-android/issues/4267))
+ - Fix Broken EditText when using FromEditTextItem ([#4276](https://github.com/vector-im/element-android/issues/4276))
+ - Fix crash when clicking on ViewEvent source actions ([#4279](https://github.com/vector-im/element-android/issues/4279))
+ - Fix voice message record button wrong visibility ([#4283](https://github.com/vector-im/element-android/issues/4283))
+ - Fix unread marker not showing ([#4313](https://github.com/vector-im/element-android/issues/4313))
+
+
+Changes in Element v1.3.4 (2021-10-20)
+======================================
+
+Features ✨
+----------
+ - Implement /part command, with or without parameter ([#2909](https://github.com/vector-im/element-android/issues/2909))
+ - Handle Presence support, for Direct Message room ([#4090](https://github.com/vector-im/element-android/issues/4090))
+ - Priority conversations for Android 11+ ([#3313](https://github.com/vector-im/element-android/issues/3313))
+
+Bugfixes 🐛
+----------
+ - Issue #908 Adding trailing space " " or ": " if the user started a sentence by mentioning someone, ([#908](https://github.com/vector-im/element-android/issues/908))
+ - Fixes reappearing notifications when dismissing notifications from slow homeservers or delayed /sync responses ([#3437](https://github.com/vector-im/element-android/issues/3437))
+ - Catching event decryption crash and logging when attempting to markOlmSessionForUnwedging fails ([#3608](https://github.com/vector-im/element-android/issues/3608))
+ - Fixing notification sounds being triggered for every message, now they only trigger for the first, consistent with the vibrations ([#3774](https://github.com/vector-im/element-android/issues/3774))
+ - Voice Message not sendable if recorded while flight mode was on ([#4006](https://github.com/vector-im/element-android/issues/4006))
+ - Fixes push notification emails list not refreshing the first time seeing the notifications page.
+ Also improves the error handling in the email notification toggling by using synchronous flows instead of the WorkManager ([#4106](https://github.com/vector-im/element-android/issues/4106))
+ - Make MegolmBackupAuthData.signatures optional for robustness ([#4162](https://github.com/vector-im/element-android/issues/4162))
+ - Fixing push notifications starting the looping background sync when the push notification causes the application to be created. ([#4167](https://github.com/vector-im/element-android/issues/4167))
+ - Fix random crash when user logs out just after the log in. ([#4193](https://github.com/vector-im/element-android/issues/4193))
+ - Make the font size selection dialog scrollable ([#4201](https://github.com/vector-im/element-android/issues/4201))
+ - Fix conversation notification for sent messages ([#4221](https://github.com/vector-im/element-android/issues/4221))
+ - Fixes the developer sync options being displayed in the home menu when developer mode is disabled ([#4234](https://github.com/vector-im/element-android/issues/4234))
+ - Restore support for Android Auto as sent messages are no longer read aloud ([#4247](https://github.com/vector-im/element-android/issues/4247))
+ - Fix crash on slash commands Exceptions ([#4261](https://github.com/vector-im/element-android/issues/4261))
+
+Other changes
+-------------
+ - Scrub user sensitive data like gps location from images when sending on original quality ([#465](https://github.com/vector-im/element-android/issues/465))
+ - Migrate to MvRx2 (Mavericks) ([#3890](https://github.com/vector-im/element-android/issues/3890))
+ - Implement a new github action workflow to generate two PRs for emoji and sas string sync ([#4216](https://github.com/vector-im/element-android/issues/4216))
+ - Improve wording around rageshakes in the defect issue template. ([#4226](https://github.com/vector-im/element-android/issues/4226))
+ - Add automation to move incoming issues and X-Needs-Info into the right places on the issue triage board. ([#4250](https://github.com/vector-im/element-android/issues/4250))
+ - Uppon sharing image compression fails, return the original image ([#4264](https://github.com/vector-im/element-android/issues/4264))
+
+
+Changes in Element v1.3.3 (2021-10-11)
+======================================
+
+Bugfixes 🐛
+----------
+ - Disable Android Auto supports ([#4205](https://github.com/vector-im/element-android/issues/4205))
+
+
+Changes in Element v1.3.2 (2021-10-08)
+======================================
+
+Features ✨
+----------
+ - Android Auto notification support ([#240](https://github.com/vector-im/element-android/issues/240))
+ - Add a fallback for user displayName when this one is null or empty ([#3732](https://github.com/vector-im/element-android/issues/3732))
+ - Add client base url config to customize permalinks ([#4027](https://github.com/vector-im/element-android/issues/4027))
+ - Check if DM exists before creating a new one ([#4157](https://github.com/vector-im/element-android/issues/4157))
+ - Handle 8 new slash commands: `/ignore`, `/unignore`, `/roomname`, `/myroomnick`, `/roomavatar`, `/myroomavatar`, `/lenny`, `/whois`. ([#4158](https://github.com/vector-im/element-android/issues/4158))
+ - Display identity server policies in the Discovery screen ([#4184](https://github.com/vector-im/element-android/issues/4184))
+
+Bugfixes 🐛
+----------
+ - Ensure initial sync progress dialog is hidden when the initial sync is over ([#983](https://github.com/vector-im/element-android/issues/983))
+ - Avoid resending notifications that are already shown ([#1673](https://github.com/vector-im/element-android/issues/1673))
+ - Room filter no results bad CTA in space mode when a space selected ([#3048](https://github.com/vector-im/element-android/issues/3048))
+ - Fixes notifications not dismissing when reading messages on other devices ([#3347](https://github.com/vector-im/element-android/issues/3347))
+ - Fixes the passphrase screen being incorrectly shown when pressing back on the key verification screen.
+ When the user doesn't have a passphrase set we don't show the passphrase screen. ([#3898](https://github.com/vector-im/element-android/issues/3898))
+ - App doesn't take you to a Space after choosing to Join it ([#3933](https://github.com/vector-im/element-android/issues/3933))
+ - Validate public space addresses and room aliases length ([#3934](https://github.com/vector-im/element-android/issues/3934))
+ - Save button for adding rooms to a space is hidden when scrolling through list of rooms ([#3935](https://github.com/vector-im/element-android/issues/3935))
+ - Align new room encryption default to Web ([#4045](https://github.com/vector-im/element-android/issues/4045))
+ - Fix Reply/Edit mode animation is broken when sending ([#4077](https://github.com/vector-im/element-android/issues/4077))
+ - Added changes that will make SearchView in search bar focused by default on opening reaction picker.
+
+ When tapping close icon of SearchView, the SearchView did not collapse therefore added the on close listener
+ which will collapse the SearchView on close. ([#4092](https://github.com/vector-im/element-android/issues/4092))
+ - Troubleshoot notification: Fix button not clickable ([#4109](https://github.com/vector-im/element-android/issues/4109))
+ - Harmonize wording in the message bottom sheet and move up the View Reactions item ([#4155](https://github.com/vector-im/element-android/issues/4155))
+ - Remove unused SendRelationWorker and related API call (3588) ([#4156](https://github.com/vector-im/element-android/issues/4156))
+ - SIP user to native user mapping is wrong ([#4176](https://github.com/vector-im/element-android/issues/4176))
+
+SDK API changes ⚠️
+------------------
+ - Create extension `String.isMxcUrl()` ([#4158](https://github.com/vector-im/element-android/issues/4158))
+
+Other changes
+-------------
+ - Use ktlint plugin. See [the documentation](https://github.com/vector-im/element-android/blob/develop/CONTRIBUTING.md#ktlint) for more detail. ([#3957](https://github.com/vector-im/element-android/issues/3957))
+ - Minimize the use of exported="true" in android Manifest (link: https://github.com/matrix-org/matrix-dinsic/issues/618) ([#4018](https://github.com/vector-im/element-android/issues/4018))
+ - Fix redundancy in heading in the bug report issue form ([#4076](https://github.com/vector-im/element-android/issues/4076))
+ - Fix release label in the release issue template ([#4113](https://github.com/vector-im/element-android/issues/4113))
+
+
+Changes in Element v1.3.1 (2021-09-29)
+======================================
+
+Bugfixes 🐛
+----------
+ - Verifying exported E2E keys to provide user feedback when the output is malformed ([#4082](https://github.com/vector-im/element-android/issues/4082))
+ - Fix settings crash when accelerometer not available ([#4103](https://github.com/vector-im/element-android/issues/4103))
+ - Crash while rendering failed message warning ([#4110](https://github.com/vector-im/element-android/issues/4110))
+
+
+Changes in Element v1.3.0 (2021-09-27)
+======================================
+
+Features ✨
+----------
+ - Spaces!
+ - Adds email notification registration to Settings ([#2243](https://github.com/vector-im/element-android/issues/2243))
+ - Spaces | M3.23 Invite by email in create private space flow ([#3678](https://github.com/vector-im/element-android/issues/3678))
+ - Improve space invite bottom sheet ([#4057](https://github.com/vector-im/element-android/issues/4057))
+ - Allow to also leave rooms when leaving a space ([#3692](https://github.com/vector-im/element-android/issues/3692))
+ - Better expose adding spaces as Subspaces ([#3752](https://github.com/vector-im/element-android/issues/3752))
+ - Push and syncs: add debug info on room list and on room detail screen and improves the log format. ([#4046](https://github.com/vector-im/element-android/issues/4046))
+
+Bugfixes 🐛
+----------
+ - Remove the "Teammate spaces aren't quite ready" bottom sheet ([#3945](https://github.com/vector-im/element-android/issues/3945))
+ - Restricted Room previews aren't working ([#3946](https://github.com/vector-im/element-android/issues/3946))
+ - A removed room from a space can't be re-added as it won't be shown in add-room ([#3947](https://github.com/vector-im/element-android/issues/3947))
+ - "Non-Admin" user able to invite others to Private Space (by default) ([#3951](https://github.com/vector-im/element-android/issues/3951))
+ - Kick user dialog for spaces talks about rooms ([#3956](https://github.com/vector-im/element-android/issues/3956))
+ - Messages are displayed as unable to decrypt then decrypted a few seconds later ([#4011](https://github.com/vector-im/element-android/issues/4011))
+ - Fix DTMF not working ([#4015](https://github.com/vector-im/element-android/issues/4015))
+ - Fix sticky end call notification ([#4019](https://github.com/vector-im/element-android/issues/4019))
+ - Fix call screen stuck with some hanging up scenarios ([#4026](https://github.com/vector-im/element-android/issues/4026))
+ - Fix other call not always refreshed when ended ([#4028](https://github.com/vector-im/element-android/issues/4028))
+ - Private space invite bottomsheet only offering inviting by username not by email ([#4042](https://github.com/vector-im/element-android/issues/4042))
+ - Spaces invitation system notifications don't take me to the join space toast ([#4043](https://github.com/vector-im/element-android/issues/4043))
+ - Space Invites are not lighting up the drawer menu ([#4059](https://github.com/vector-im/element-android/issues/4059))
+ - MessageActionsBottomSheet not being shown on local echos ([#4068](https://github.com/vector-im/element-android/issues/4068))
+
+SDK API changes ⚠️
+------------------
+ - InitialSyncProgressService has been renamed to SyncStatusService and its function getInitialSyncProgressStatus() has been renamed to getSyncStatusLive() ([#4046](https://github.com/vector-im/element-android/issues/4046))
+
+Other changes
+-------------
+ - Better support for Sdk2 version. Also slight change in the default user agent: `MatrixAndroidSDK_X` is replaced by `MatrixAndroidSdk2` ([#3994](https://github.com/vector-im/element-android/issues/3994))
+ - Introduces ConferenceEvent to abstract usage of Jitsi BroadcastEvent class. ([#4014](https://github.com/vector-im/element-android/issues/4014))
+ - Improve performances on RoomDetail screen ([#4065](https://github.com/vector-im/element-android/issues/4065))
+
+
+Changes in Element v1.2.2 (2021-09-13)
+======================================
+
+Bugfixes 🐛
+----------
+
+- Fix a security issue with message key sharing. See https://matrix.org/blog/2021/09/13/vulnerability-disclosure-key-sharing for details.
+
+
+Changes in Element v1.2.1 (2021-09-08)
+======================================
+
+Features ✨
+----------
+ - Support Android 11 Conversation features ([#1809](https://github.com/vector-im/element-android/issues/1809))
+ - Introduces AutoAcceptInvites which can be enabled at compile time. ([#3531](https://github.com/vector-im/element-android/issues/3531))
+ - New call designs ([#3599](https://github.com/vector-im/element-android/issues/3599))
+ - Restricted Join Rule | Inform admins of new option ([#3631](https://github.com/vector-im/element-android/issues/3631))
+ - Mention and Keyword Notification Settings: Turn on/off keyword notifications and edit keywords. ([#3650](https://github.com/vector-im/element-android/issues/3650))
+ - Support accept 3pid invite when email is not bound to account ([#3691](https://github.com/vector-im/element-android/issues/3691))
+ - Space summary pagination ([#3693](https://github.com/vector-im/element-android/issues/3693))
+ - Update Email invite to be aware of spaces ([#3695](https://github.com/vector-im/element-android/issues/3695))
+ - M11.12 Spaces | Default to 'Home' in settings ([#3754](https://github.com/vector-im/element-android/issues/3754))
+ - Call: show dialog for some ended reasons. ([#3853](https://github.com/vector-im/element-android/issues/3853))
+ - Add expired account error code in the matrix SDK ([#3900](https://github.com/vector-im/element-android/issues/3900))
+ - Add password errors in the matrix SDK ([#3927](https://github.com/vector-im/element-android/issues/3927))
+ - Upgrade AGP to 7.0.2.
+ When compiling using command line, make sure to use the JDK 11 by adding for instance `-Dorg.gradle.java.home=/Applications/Android\ Studio\ Preview.app/Contents/jre/Contents/Home` or by setting JAVA_HOME. ([#3954](https://github.com/vector-im/element-android/issues/3954))
+ - Check power level before displaying actions in the room details' timeline ([#3959](https://github.com/vector-im/element-android/issues/3959))
+
+Bugfixes 🐛
+----------
+ - Add mxid to autocomplete suggestion if more than one user in a room has the same displayname ([#1823](https://github.com/vector-im/element-android/issues/1823))
+ - Use WebView cache for widgets to avoid excessive data use ([#2648](https://github.com/vector-im/element-android/issues/2648))
+ - Jitsi-hosted jitsi conferences not loading ([#2846](https://github.com/vector-im/element-android/issues/2846))
+ - Space Explore Rooms no feedback on failed to join ([#3207](https://github.com/vector-im/element-android/issues/3207))
+ - Notifications - Fix missing sound on notifications. ([#3243](https://github.com/vector-im/element-android/issues/3243))
+ - the element-based domain permalinks (e.g. https://app.element.io/#/user/@chagai95:matrix.org) don't have the mxid in the first param (like matrix.to does - https://matrix.to/#/@chagai95:matrix.org) but rather in the second after /user/ so /user/mxid ([#3735](https://github.com/vector-im/element-android/issues/3735))
+ - Update the AccountData with the users' matrix Id instead of their email for those invited by email in a direct chat ([#3743](https://github.com/vector-im/element-android/issues/3743))
+ - Send an empty body for POST rooms/{roomId}/receipt/{receiptType}/{eventId} ([#3789](https://github.com/vector-im/element-android/issues/3789))
+ - Fix order in which the items of the attachment menu appear ([#3793](https://github.com/vector-im/element-android/issues/3793))
+ - Authenticated Jitsi not working in release ([#3841](https://github.com/vector-im/element-android/issues/3841))
+ - Home: Dial pad lost entry when config changes ([#3845](https://github.com/vector-im/element-android/issues/3845))
+ - Message edition is not rendered in e2e rooms after pagination ([#3887](https://github.com/vector-im/element-android/issues/3887))
+ - Crash on opening a room on Android 5.0 and 5.1 - Regression with Voice message ([#3897](https://github.com/vector-im/element-android/issues/3897))
+ - Fix a crash at start-up if translated string is empty ([#3910](https://github.com/vector-im/element-android/issues/3910))
+ - PushRule enabling request is not following the spec ([#3911](https://github.com/vector-im/element-android/issues/3911))
+ - Enable image preview in Android's share sheet (Android 11+) ([#3965](https://github.com/vector-im/element-android/issues/3965))
+ - Voice Message - Cannot render voice message if the waveform data is corrupted ([#3983](https://github.com/vector-im/element-android/issues/3983))
+ - Fix memory leak on RoomDetailFragment (ValueAnimator) ([#3990](https://github.com/vector-im/element-android/issues/3990))
+
+Other changes
+-------------
+ - VoIP: Merge virtual room timeline in corresponding native room (call events only). ([#3520](https://github.com/vector-im/element-android/issues/3520))
+ - Issue templates: modernise and sync with element-web ([#3883](https://github.com/vector-im/element-android/issues/3883))
+ - Issue templates: modernise SDK and release checklists, and add homeserver question for bugs ([#3889](https://github.com/vector-im/element-android/issues/3889))
+ - Issue templates: merge expected and actual results ([#3960](https://github.com/vector-im/element-android/issues/3960))
+
+
Changes in Element v1.2.0 (2021-08-12)
======================================
diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md
index 5151a618f6..dbc0ce9b72 100644
--- a/CONTRIBUTING.md
+++ b/CONTRIBUTING.md
@@ -9,7 +9,7 @@ Android support can be found in this [![Element Android Matrix room #element-and
## Android Studio settings
Please set the "hard wrap" setting of Android Studio to 160 chars, this is the setting we use internally to format the source code (Menu `Settings/Editor/Code Style` then `Hard wrap at`).
-Please ensure that your using the project formatting rules (which are in the project at .idea/codeStyles/), and format the file before committing them.
+Please ensure that you're using the project formatting rules (which are in the project at .idea/codeStyles/), and format the file before committing them.
### Template
@@ -80,14 +80,13 @@ Make sure the following commands execute without any error:
#### ktlint
-curl -sSLO https://github.com/pinterest/ktlint/releases/download/0.34.2/ktlint && chmod a+x ktlint
-./ktlint --android --experimental -v
+./gradlew ktlintCheck --continue
Note that you can run
-./ktlint --android --experimental -v -F
+./gradlew ktlintFormat
For ktlint to fix some detected errors for you (you still have to check and commit the fix of course)
@@ -116,13 +115,40 @@ You should consider adding Unit tests with your PR, and also integration tests (
### Internationalisation
-When adding new string resources, please only add new entries in file `value/strings.xml`. Translations will be added later by the community of translators with a specific tool named [Weblate](https://translate.riot.im/projects/riot-android/).
+Translations are handled using an external tool: [Weblate](https://translate.element.io/projects/element-android/)
+
+As a general rule, please never edit or add or remove translations to the project in a Pull Request. It can lead to merge conflict if the translations are also modified in Weblate side.
+
+#### Adding new string
+
+When adding new string resources, please only add new entries in file `value/strings.xml`. Translations will be added later by the community of translators using Weblate.
+
+New strings can be added anywhere in the file `value/strings.xml`, not necessarily at the end of the file. Generally, it's even better to add the new strings in some dedicated section per feature, and not at the end of the file, to avoid merge conflict between 2 PR adding strings at the end of the same file.
+
Do not hesitate to use plurals when appropriate.
+#### Editing existing strings
+
+Two cases:
+- If the meaning stays the same, it's OK to edit the original string (i.e. the English version).
+- If the meaning is not the same, please create a new string and do not remove the existing string. See below for instructions to remove existing string.
+
+#### Removing existing strings
+
+If a string is not used anymore, it should be removed from the resource, but please do not remove the strings or its translations in the PR. It can lead to merge conflict with Weblate, and to lint error if new translations from deleted strings are added with Weblate.
+
+Instead, please comment the original string with:
+```xml
+
+```
+The string will be removed during the next sync with Weblate.
+
### Accessibility
Please consider accessibility as an important point. As a minimum requirement, in layout XML files please use attributes such as `android:contentDescription` and `android:importantForAccessibility`, and test with a screen reader if it's working well. You can add new string resources, dedicated to accessibility, in this case, please prefix theirs id with `a11y_`.
+For instance, when updating the image `src` of an ImageView, please also consider updating its `contentDescription`. A good example is a play pause button.
+
### Layout
When adding or editing layouts, make sure the layout will render correctly if device uses a RTL (Right To Left) language.
diff --git a/attachment-viewer/build.gradle b/attachment-viewer/build.gradle
index c393c5f483..02fbfc794c 100644
--- a/attachment-viewer/build.gradle
+++ b/attachment-viewer/build.gradle
@@ -18,13 +18,12 @@ apply plugin: 'com.android.library'
apply plugin: 'kotlin-android'
android {
- compileSdkVersion 30
+
+ compileSdk versions.compileSdk
defaultConfig {
- minSdkVersion 21
- targetSdkVersion 30
- versionCode 1
- versionName "1.0"
+ minSdk versions.minSdk
+ targetSdk versions.targetSdk
}
buildTypes {
@@ -34,11 +33,11 @@ android {
}
}
compileOptions {
- sourceCompatibility JavaVersion.VERSION_1_8
- targetCompatibility JavaVersion.VERSION_1_8
+ sourceCompatibility versions.sourceCompat
+ targetCompatibility versions.targetCompat
}
kotlinOptions {
- jvmTarget = '1.8'
+ jvmTarget = "11"
}
buildFeatures {
@@ -51,13 +50,12 @@ dependencies {
implementation 'com.github.chrisbanes:PhotoView:2.3.0'
- implementation 'io.reactivex.rxjava2:rxkotlin:2.4.0'
- implementation 'io.reactivex.rxjava2:rxandroid:2.1.1'
+ implementation libs.rx.rxKotlin
+ implementation libs.rx.rxAndroid
- implementation "org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version"
- implementation 'androidx.core:core-ktx:1.6.0'
- implementation 'androidx.appcompat:appcompat:1.3.1'
- implementation "androidx.recyclerview:recyclerview:1.2.1"
+ implementation libs.androidx.core
+ implementation libs.androidx.appCompat
+ implementation libs.androidx.recyclerview
- implementation 'com.google.android.material:material:1.4.0'
+ implementation libs.google.material
}
\ No newline at end of file
diff --git a/attachment-viewer/src/main/java/im/vector/lib/attachmentviewer/AttachmentViewerActivity.kt b/attachment-viewer/src/main/java/im/vector/lib/attachmentviewer/AttachmentViewerActivity.kt
index f909418d6f..573138bf5c 100644
--- a/attachment-viewer/src/main/java/im/vector/lib/attachmentviewer/AttachmentViewerActivity.kt
+++ b/attachment-viewer/src/main/java/im/vector/lib/attachmentviewer/AttachmentViewerActivity.kt
@@ -17,6 +17,7 @@
package im.vector.lib.attachmentviewer
+import android.annotation.SuppressLint
import android.graphics.Color
import android.os.Build
import android.os.Bundle
@@ -39,7 +40,6 @@ import androidx.core.view.updatePadding
import androidx.transition.TransitionManager
import androidx.viewpager2.widget.ViewPager2
import im.vector.lib.attachmentviewer.databinding.ActivityAttachmentViewerBinding
-
import java.lang.ref.WeakReference
import kotlin.math.abs
@@ -142,7 +142,12 @@ abstract class AttachmentViewerActivity : AppCompatActivity(), AttachmentEventLi
// New API instead of SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN and SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION
window.setDecorFitsSystemWindows(false)
// New API instead of SYSTEM_UI_FLAG_IMMERSIVE
- window.decorView.windowInsetsController?.systemBarsBehavior = WindowInsetsController.BEHAVIOR_SHOW_BARS_BY_SWIPE
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) {
+ window.decorView.windowInsetsController?.systemBarsBehavior = WindowInsetsController.BEHAVIOR_SHOW_TRANSIENT_BARS_BY_SWIPE
+ } else {
+ @SuppressLint("WrongConstant")
+ window.decorView.windowInsetsController?.systemBarsBehavior = WindowInsetsController.BEHAVIOR_SHOW_BARS_BY_SWIPE
+ }
// New API instead of FLAG_TRANSLUCENT_STATUS
window.statusBarColor = ContextCompat.getColor(this, R.color.half_transparent_status_bar)
// new API instead of FLAG_TRANSLUCENT_NAVIGATION
@@ -291,8 +296,8 @@ abstract class AttachmentViewerActivity : AppCompatActivity(), AttachmentEventLi
private fun calculateTranslationAlpha(translationY: Float, translationLimit: Int): Float =
1.0f - 1.0f / translationLimit.toFloat() / 4f * abs(translationY)
- private fun createSwipeToDismissHandler()
- : SwipeToDismissHandler = SwipeToDismissHandler(
+ private fun createSwipeToDismissHandler(): SwipeToDismissHandler =
+ SwipeToDismissHandler(
swipeView = views.dismissContainer,
shouldAnimateDismiss = { shouldAnimateDismiss() },
onDismiss = { animateClose() },
@@ -348,7 +353,12 @@ abstract class AttachmentViewerActivity : AppCompatActivity(), AttachmentEventLi
// new API instead of SYSTEM_UI_FLAG_HIDE_NAVIGATION
window.decorView.windowInsetsController?.hide(WindowInsets.Type.navigationBars())
// New API instead of SYSTEM_UI_FLAG_IMMERSIVE
- window.decorView.windowInsetsController?.systemBarsBehavior = WindowInsetsController.BEHAVIOR_SHOW_BARS_BY_SWIPE
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) {
+ window.decorView.windowInsetsController?.systemBarsBehavior = WindowInsetsController.BEHAVIOR_SHOW_TRANSIENT_BARS_BY_SWIPE
+ } else {
+ @SuppressLint("WrongConstant")
+ window.decorView.windowInsetsController?.systemBarsBehavior = WindowInsetsController.BEHAVIOR_SHOW_BARS_BY_SWIPE
+ }
// New API instead of FLAG_TRANSLUCENT_STATUS
window.statusBarColor = ContextCompat.getColor(this, R.color.half_transparent_status_bar)
// New API instead of FLAG_TRANSLUCENT_NAVIGATION
diff --git a/attachment-viewer/src/main/java/im/vector/lib/attachmentviewer/ImageLoaderTarget.kt b/attachment-viewer/src/main/java/im/vector/lib/attachmentviewer/ImageLoaderTarget.kt
index 531e8171e1..99686eaabb 100644
--- a/attachment-viewer/src/main/java/im/vector/lib/attachmentviewer/ImageLoaderTarget.kt
+++ b/attachment-viewer/src/main/java/im/vector/lib/attachmentviewer/ImageLoaderTarget.kt
@@ -36,8 +36,8 @@ interface ImageLoaderTarget {
fun onResourceReady(uid: String, resource: Drawable)
}
-internal class DefaultImageLoaderTarget(val holder: AnimatedImageViewHolder, private val contextView: ImageView)
- : ImageLoaderTarget {
+internal class DefaultImageLoaderTarget(val holder: AnimatedImageViewHolder, private val contextView: ImageView) :
+ ImageLoaderTarget {
override fun contextView(): ImageView {
return contextView
}
diff --git a/attachment-viewer/src/main/res/layout/item_animated_image_attachment.xml b/attachment-viewer/src/main/res/layout/item_animated_image_attachment.xml
index 1096267124..cfeb5e9cc6 100644
--- a/attachment-viewer/src/main/res/layout/item_animated_image_attachment.xml
+++ b/attachment-viewer/src/main/res/layout/item_animated_image_attachment.xml
@@ -1,21 +1,22 @@
+ android:layout_height="match_parent">
+ android:layout_height="match_parent"
+ android:importantForAccessibility="no"
+ android:visibility="visible" />
diff --git a/attachment-viewer/src/main/res/layout/item_video_attachment.xml b/attachment-viewer/src/main/res/layout/item_video_attachment.xml
index 7dd13ea460..cd55be5cb4 100644
--- a/attachment-viewer/src/main/res/layout/item_video_attachment.xml
+++ b/attachment-viewer/src/main/res/layout/item_video_attachment.xml
@@ -9,6 +9,7 @@
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_gravity="center"
+ android:importantForAccessibility="no"
android:scaleType="centerInside" />
diff --git a/attachment-viewer/src/main/res/values/strings.xml b/attachment-viewer/src/main/res/values/strings.xml
new file mode 100644
index 0000000000..3b32209868
--- /dev/null
+++ b/attachment-viewer/src/main/res/values/strings.xml
@@ -0,0 +1,5 @@
+
+
+
+ Play or pause the video
+
\ No newline at end of file
diff --git a/build.gradle b/build.gradle
index d7ba0168dd..e9045b99c7 100644
--- a/build.gradle
+++ b/build.gradle
@@ -1,9 +1,9 @@
// Top-level build file where you can add configuration options common to all sub-projects/modules.
buildscript {
- // Ref: https://kotlinlang.org/releases.html
- ext.kotlin_version = '1.5.21'
- ext.kotlin_coroutines_version = "1.5.0"
+
+ apply from: 'dependencies.gradle'
+
repositories {
google()
jcenter()
@@ -11,10 +11,14 @@ buildscript {
url "https://plugins.gradle.org/m2/"
}
}
+
dependencies {
- classpath 'com.android.tools.build:gradle:4.2.2'
- classpath 'com.google.gms:google-services:4.3.8'
- classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
+ // Release notes of Android Gradle Plugin (AGP):
+ // https://developer.android.com/studio/releases/gradle-plugin
+ classpath libs.gradle.gradlePlugin
+ classpath libs.gradle.kotlinPlugin
+ classpath libs.gradle.hiltPlugin
+ classpath 'com.google.gms:google-services:4.3.10'
classpath 'org.sonarsource.scanner.gradle:sonarqube-gradle-plugin:3.3'
classpath 'com.google.android.gms:oss-licenses-plugin:0.10.4'
classpath "com.likethesalad.android:string-reference:1.2.2"
@@ -24,7 +28,14 @@ buildscript {
}
}
+// ktlint Plugin
+plugins {
+ id "org.jlleitschuh.gradle.ktlint" version "10.2.0"
+}
+
allprojects {
+ apply plugin: "org.jlleitschuh.gradle.ktlint"
+
repositories {
// For olm library. This has to be declared first, to ensure that Olm library is not downloaded from another repo
maven {
@@ -44,6 +55,8 @@ allprojects {
includeGroupByRegex 'com\\.github\\.chrisbanes'
// PFLockScreen-Android
includeGroupByRegex 'com\\.github\\.vector-im'
+ // DraggableView
+ includeGroupByRegex 'com\\.github\\.hyuwah'
// Chat effects
includeGroupByRegex 'com\\.github\\.jetradarmobile'
@@ -70,6 +83,26 @@ allprojects {
// You can override by passing `-PallWarningsAsErrors=false` in the command line
kotlinOptions.allWarningsAsErrors = project.getProperties().getOrDefault("allWarningsAsErrors", "true").toBoolean()
}
+
+ // Fix "Java heap space" issue
+ tasks.withType(org.jlleitschuh.gradle.ktlint.tasks.BaseKtLintCheckTask).configureEach {
+ it.workerMaxHeapSize.set("2G")
+ }
+
+ // See https://github.com/JLLeitschuh/ktlint-gradle#configuration
+ ktlint {
+ android = true
+ ignoreFailures = false
+ enableExperimentalRules = true
+ // display the corresponding rule
+ verbose = true
+ disabledRules = [
+ "spacing-between-declarations-with-comments",
+ "no-multi-spaces",
+ "experimental:spacing-between-declarations-with-annotations",
+ "experimental:annotation"
+ ]
+ }
}
task clean(type: Delete) {
diff --git a/changelog.d/3477.feature b/changelog.d/3477.feature
new file mode 100644
index 0000000000..c6f8820b4c
--- /dev/null
+++ b/changelog.d/3477.feature
@@ -0,0 +1 @@
+Make notification text spoiler aware
\ No newline at end of file
diff --git a/changelog.d/4219.misc b/changelog.d/4219.misc
new file mode 100644
index 0000000000..69950e0915
--- /dev/null
+++ b/changelog.d/4219.misc
@@ -0,0 +1 @@
+Finish migration from RxJava to Flow
\ No newline at end of file
diff --git a/changelog.d/4257.misc b/changelog.d/4257.misc
new file mode 100644
index 0000000000..fa0657bfea
--- /dev/null
+++ b/changelog.d/4257.misc
@@ -0,0 +1 @@
+Remove redundant text in feature request issue form
diff --git a/changelog.d/4367.feature b/changelog.d/4367.feature
new file mode 100644
index 0000000000..c001cc778f
--- /dev/null
+++ b/changelog.d/4367.feature
@@ -0,0 +1 @@
+Poll Feature - Create Poll Screen (Disabled for now)
\ No newline at end of file
diff --git a/changelog.d/4392.removal b/changelog.d/4392.removal
new file mode 100644
index 0000000000..42ba81152a
--- /dev/null
+++ b/changelog.d/4392.removal
@@ -0,0 +1,2 @@
+Add content scanner API from MSC1453
+API documentation : https://github.com/matrix-org/matrix-content-scanner#api
\ No newline at end of file
diff --git a/changelog.d/4401.removal b/changelog.d/4401.removal
new file mode 100644
index 0000000000..ce58372a18
--- /dev/null
+++ b/changelog.d/4401.removal
@@ -0,0 +1 @@
+Breaking SDK API change to PushRuleListener, the separated callbacks have been merged into one with a data class which includes all the previously separated push information
diff --git a/changelog.d/4402.feature b/changelog.d/4402.feature
new file mode 100644
index 0000000000..29b9f9a337
--- /dev/null
+++ b/changelog.d/4402.feature
@@ -0,0 +1 @@
+Adds support for images inside message notifications
\ No newline at end of file
diff --git a/changelog.d/4424.bugfix b/changelog.d/4424.bugfix
new file mode 100644
index 0000000000..679440d204
--- /dev/null
+++ b/changelog.d/4424.bugfix
@@ -0,0 +1 @@
+Fix incorrect cropping of conversation icons
\ No newline at end of file
diff --git a/changelog.d/4428.bugfix b/changelog.d/4428.bugfix
new file mode 100644
index 0000000000..381f246fee
--- /dev/null
+++ b/changelog.d/4428.bugfix
@@ -0,0 +1 @@
+Fix potential NullPointerException crashes in Room and User account data sources
diff --git a/changelog.d/4435.misc b/changelog.d/4435.misc
new file mode 100644
index 0000000000..14e2425d79
--- /dev/null
+++ b/changelog.d/4435.misc
@@ -0,0 +1 @@
+Add and improve issue triage workflows
diff --git a/changelog.d/4446.bugfix b/changelog.d/4446.bugfix
new file mode 100644
index 0000000000..140e18a3ba
--- /dev/null
+++ b/changelog.d/4446.bugfix
@@ -0,0 +1 @@
+Unable to establish Olm outbound session from fallback key
\ No newline at end of file
diff --git a/changelog.d/4452.misc b/changelog.d/4452.misc
new file mode 100644
index 0000000000..10d98c32c3
--- /dev/null
+++ b/changelog.d/4452.misc
@@ -0,0 +1 @@
+Update issue template to bring in line with element-web
diff --git a/changelog.d/4480.bugfix b/changelog.d/4480.bugfix
new file mode 100644
index 0000000000..5769fb4efa
--- /dev/null
+++ b/changelog.d/4480.bugfix
@@ -0,0 +1 @@
+Fixes intermittent crash on sign out due to the session being incorrectly recreated whilst being closed
\ No newline at end of file
diff --git a/changelog.d/452.bugfix b/changelog.d/452.bugfix
new file mode 100644
index 0000000000..6e3d2539b5
--- /dev/null
+++ b/changelog.d/452.bugfix
@@ -0,0 +1 @@
+Render markdown in room list
\ No newline at end of file
diff --git a/dependencies.gradle b/dependencies.gradle
new file mode 100644
index 0000000000..8cc7b3b260
--- /dev/null
+++ b/dependencies.gradle
@@ -0,0 +1,143 @@
+ext.versions = [
+
+ 'minSdk' : 21,
+ 'compileSdk' : 31,
+ 'targetSdk' : 31,
+ 'sourceCompat' : JavaVersion.VERSION_11,
+ 'targetCompat' : JavaVersion.VERSION_11,
+]
+
+def gradle = "7.0.3"
+// Ref: https://kotlinlang.org/releases.html
+def kotlin = "1.5.31"
+def kotlinCoroutines = "1.5.2"
+def dagger = "2.40.1"
+def retrofit = "2.9.0"
+def arrow = "0.8.2"
+def markwon = "4.6.2"
+def moshi = "1.12.0"
+def lifecycle = "2.4.0"
+def flowBinding = "1.2.0"
+def epoxy = "4.6.2"
+def mavericks = "2.4.0"
+def glide = "4.12.0"
+def bigImageViewer = "1.8.1"
+def jjwt = "0.11.2"
+def vanniktechEmoji = "0.8.0"
+
+// Testing
+def mockk = "1.12.1"
+def espresso = "3.4.0"
+def androidxTest = "1.4.0"
+
+
+ext.libs = [
+ gradle : [
+ 'gradlePlugin' : "com.android.tools.build:gradle:$gradle",
+ 'kotlinPlugin' : "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin",
+ 'hiltPlugin' : "com.google.dagger:hilt-android-gradle-plugin:$dagger"
+
+ ],
+ jetbrains : [
+ 'coroutinesCore' : "org.jetbrains.kotlinx:kotlinx-coroutines-core:$kotlinCoroutines",
+ 'coroutinesAndroid' : "org.jetbrains.kotlinx:kotlinx-coroutines-android:$kotlinCoroutines",
+ 'coroutinesRx2' : "org.jetbrains.kotlinx:kotlinx-coroutines-rx2:$kotlinCoroutines",
+ 'coroutinesTest' : "org.jetbrains.kotlinx:kotlinx-coroutines-test:$kotlinCoroutines"
+ ],
+ androidx : [
+ 'appCompat' : "androidx.appcompat:appcompat:1.3.1",
+ 'core' : "androidx.core:core-ktx:1.7.0",
+ 'recyclerview' : "androidx.recyclerview:recyclerview:1.2.1",
+ 'exifinterface' : "androidx.exifinterface:exifinterface:1.3.3",
+ 'fragmentKtx' : "androidx.fragment:fragment-ktx:1.3.6",
+ 'constraintLayout' : "androidx.constraintlayout:constraintlayout:2.1.1",
+ 'work' : "androidx.work:work-runtime-ktx:2.7.0",
+ 'autoFill' : "androidx.autofill:autofill:1.1.0",
+ 'preferenceKtx' : "androidx.preference:preference-ktx:1.1.1",
+ 'junit' : "androidx.test.ext:junit:1.1.3",
+ 'lifecycleCommon' : "androidx.lifecycle:lifecycle-common:$lifecycle",
+ 'lifecycleLivedata' : "androidx.lifecycle:lifecycle-livedata-ktx:$lifecycle",
+ 'lifecycleProcess' : "androidx.lifecycle:lifecycle-process:$lifecycle",
+ 'datastore' : "androidx.datastore:datastore:1.0.0",
+ 'datastorepreferences' : "androidx.datastore:datastore-preferences:1.0.0",
+ 'pagingRuntimeKtx' : "androidx.paging:paging-runtime-ktx:2.1.2",
+ 'coreTesting' : "androidx.arch.core:core-testing:2.1.0",
+ 'testCore' : "androidx.test:core:$androidxTest",
+ 'orchestrator' : "androidx.test:orchestrator:$androidxTest",
+ 'testRunner' : "androidx.test:runner:$androidxTest",
+ 'testRules' : "androidx.test:rules:$androidxTest",
+ 'espressoCore' : "androidx.test.espresso:espresso-core:$espresso",
+ 'espressoContrib' : "androidx.test.espresso:espresso-contrib:$espresso",
+ 'espressoIntents' : "androidx.test.espresso:espresso-intents:$espresso"
+ ],
+ google : [
+ 'material' : "com.google.android.material:material:1.4.0"
+ ],
+ dagger : [
+ 'dagger' : "com.google.dagger:dagger:$dagger",
+ 'daggerCompiler' : "com.google.dagger:dagger-compiler:$dagger",
+ 'hilt' : "com.google.dagger:hilt-android:$dagger",
+ 'hiltCompiler' : "com.google.dagger:hilt-compiler:$dagger"
+ ],
+ squareup : [
+ 'moshi' : "com.squareup.moshi:moshi-adapters:$moshi",
+ 'moshiKotlin' : "com.squareup.moshi:moshi-kotlin-codegen:$moshi",
+ 'retrofit' : "com.squareup.retrofit2:retrofit:$retrofit",
+ 'retrofitMoshi' : "com.squareup.retrofit2:converter-moshi:$retrofit"
+ ],
+ rx : [
+ 'rxKotlin' : "io.reactivex.rxjava2:rxkotlin:2.4.0",
+ 'rxAndroid' : "io.reactivex.rxjava2:rxandroid:2.1.1"
+ ],
+ arrow : [
+ 'core' : "io.arrow-kt:arrow-core:$arrow",
+ 'instances' : "io.arrow-kt:arrow-instances-core:$arrow"
+ ],
+ markwon : [
+ 'core' : "io.noties.markwon:core:$markwon",
+ 'html' : "io.noties.markwon:html:$markwon"
+ ],
+ airbnb : [
+ 'epoxy' : "com.airbnb.android:epoxy:$epoxy",
+ 'epoxyGlide' : "com.airbnb.android:epoxy-glide-preloading:$epoxy",
+ 'epoxyProcessor' : "com.airbnb.android:epoxy-processor:$epoxy",
+ 'epoxyPaging' : "com.airbnb.android:epoxy-paging:$epoxy",
+ 'mavericks' : "com.airbnb.android:mavericks:$mavericks",
+ 'mavericksTesting' : "com.airbnb.android:mavericks-testing:$mavericks"
+ ],
+ mockk : [
+ 'mockk' : "io.mockk:mockk:$mockk",
+ 'mockkAndroid' : "io.mockk:mockk-android:$mockk"
+ ],
+ github : [
+ 'glide' : "com.github.bumptech.glide:glide:$glide",
+ 'glideCompiler' : "com.github.bumptech.glide:compiler:$glide",
+ 'bigImageViewer' : "com.github.piasy:BigImageViewer:$bigImageViewer",
+ 'glideImageLoader' : "com.github.piasy:GlideImageLoader:$bigImageViewer",
+ 'progressPieIndicator' : "com.github.piasy:ProgressPieIndicator:$bigImageViewer",
+ 'glideImageViewFactory' : "com.github.piasy:GlideImageViewFactory:$bigImageViewer",
+ 'flowBinding' : "io.github.reactivecircus.flowbinding:flowbinding-android:$flowBinding",
+ 'flowBindingAppcompat' : "io.github.reactivecircus.flowbinding:flowbinding-appcompat:$flowBinding",
+ 'flowBindingMaterial' : "io.github.reactivecircus.flowbinding:flowbinding-material:$flowBinding"
+ ],
+ jakewharton : [
+ 'timber' : "com.jakewharton.timber:timber:5.0.1"
+ ],
+ jsonwebtoken: [
+ 'jjwtApi' : "io.jsonwebtoken:jjwt-api:$jjwt",
+ 'jjwtImpl' : "io.jsonwebtoken:jjwt-impl:$jjwt",
+ 'jjwtOrgjson' : "io.jsonwebtoken:jjwt-orgjson:$jjwt"
+ ],
+ vanniktech : [
+ 'emojiMaterial' : "com.vanniktech:emoji-material:$vanniktechEmoji",
+ 'emojiGoogle' : "com.vanniktech:emoji-google:$vanniktechEmoji"
+ ],
+ apache : [
+ 'commonsImaging' : "org.apache.sanselan:sanselan:0.97-incubator"
+ ],
+ tests : [
+ 'kluent' : "org.amshove.kluent:kluent-android:1.68",
+ 'timberJunitRule' : "net.lachlanmckee:timber-junit-rule:1.0.1",
+ 'junit' : "junit:junit:4.13.2"
+ ]
+]
\ No newline at end of file
diff --git a/diff-match-patch/build.gradle b/diff-match-patch/build.gradle
index 82292e24db..f623c57a49 100644
--- a/diff-match-patch/build.gradle
+++ b/diff-match-patch/build.gradle
@@ -3,6 +3,3 @@ apply plugin: 'java-library'
dependencies {
implementation fileTree(dir: 'libs', include: ['*.jar'])
}
-
-sourceCompatibility = "8"
-targetCompatibility = "8"
diff --git a/docs/design.md b/docs/design.md
new file mode 100644
index 0000000000..2e27f00ebf
--- /dev/null
+++ b/docs/design.md
@@ -0,0 +1,104 @@
+# Element Android design
+
+## Introduction
+
+Design at element.io is done using Figma - https://www.figma.com
+
+## How to import from Figma to the Element Android project
+
+Integration should be done using the Android development best practice, and should follow the existing convention in the code.
+
+### Colors
+
+Element Android already contains all the colors which can be used by the designer, in the module `ui-style`.
+Some of them depend on the theme, so ensure to use theme attributes and not colors directly.
+
+### Text
+
+ - click on a text on Figma
+ - on the right panel, information about the style and colors are displayed
+ - in Element Android, text style are already defined, generally you should not create new style
+ - apply the style and the color to the layout
+
+### Dimension, position and margin
+
+ - click on an item on Figma
+ - dimensions of the item will be displayed.
+ - move the mouse to other items to get relative positioning, margin, etc.
+
+### Icons
+
+#### Export drawable from Figma
+
+ - click on the element to export
+ - ensure that the correct layer is selected. Sometimes the parent layer has to be selected on the left panel
+ - on the right panel, click on "export"
+ - select SVG
+ - you can check the preview of what will be exported
+ - click on "export" and save the file locally
+ - unzip the file if necessary
+
+It's also possible for any icon to go to the main component by right-clicking on the icon.
+
+#### Import in Android Studio
+
+ - right click on the drawable folder where the drawable will be created
+ - click on "New"/"Vector Asset"
+ - select the exported file
+ - update the filename if necessary
+ - click on "Next" and click on "Finish"
+ - open the created vector drawable
+ - optionally update the color(s) to "#FF0000" (red) to ensure that the drawable is correctly tinted at runtime.
+
+## Figma links
+
+Figma links can be included in the layout, for future reference, but it is also OK to add a paragraph below here, to centralize the information
+
+Main entry point: https://www.figma.com/files/project/5612863/Element?fuid=779371459522484071
+
+Note: all the Figma links are not publicly available.
+
+### Coumpound
+
+Coumpound contains the theme of the application, with all the components, in Light and Dark theme: palette (colors), typography, iconography, etc.
+
+https://www.figma.com/file/X4XTH9iS2KGJ2wFKDqkyed/Compound
+
+### Login
+
+TBD
+
+#### Login v2
+
+https://www.figma.com/file/xdV4PuI3DlzA1EiBvbrggz/Login-Flow-v2
+
+### Room list
+
+TBD
+
+### Timeline
+
+https://www.figma.com/file/x1HYYLYMmbYnhfoz2c2nGD/%5BRiotX%5D-Misc?node-id=0%3A1
+
+### Voice message
+
+https://www.figma.com/file/uaWc62Ux2DkZC4OGtAGcNc/Voice-Messages?node-id=473%3A12
+
+### Room settings
+
+TBD
+
+### VoIP
+
+https://www.figma.com/file/V6m2z0oAtUV1l8MdyIrAep/VoIP?node-id=4254%3A25767
+
+### Presence
+
+https://www.figma.com/file/qmvEskET5JWva8jZJ4jX8o/Presence---User-Status?node-id=114%3A9174
+(Option B is chosen)
+
+### Spaces
+
+https://www.figma.com/file/m7L63aGPW7iHnIYStfdxCe/Spaces?node-id=192%3A30161
+
+### List to be continued...
diff --git a/docs/hilt_migration.md b/docs/hilt_migration.md
new file mode 100644
index 0000000000..50021e9792
--- /dev/null
+++ b/docs/hilt_migration.md
@@ -0,0 +1,33 @@
+Useful links:
+- https://dagger.dev/hilt/migration-guide
+- https://dagger.dev/hilt/quick-start
+
+Hilt is built on top of Dagger 2 and simplify usage by removing needs to create components manually.
+
+When you create a new feature, you should have the following:
+
+Annotate your Activity with @AndroidEntryPoint
+If you have a BottomSheetFragment => Annotate it with @AndroidEntryPoint
+Otherwise => Add your Fragment to the FragmentModule
+Add your ViewModel.Factory to the MavericksViewModelModule
+Makes sure your ViewModel as the following code:
+
+```
+ @AssistedFactory
+ interface Factory: MavericksAssistedViewModelFactory {
+ override fun create(initialState: MyViewState): MyViewModel
+ }
+
+ companion object : MavericksViewModelFactory by hiltMavericksViewModelFactory()
+```
+
+## Some remarks
+
+@MavericksViewModelScope dependencies can't be injected inside Fragments/Activities
+You can only inject @Singleton, @MavericksViewModelScope or unscoped dependencies inside Maverick ViewModels
+You can access some specific dependencies from Singleton component by using
+```
+context.singletonEntryPoint()
+```
+Be aware that only the app has been migrated to Hilt and not the SDK.
+
diff --git a/docs/mavericks_migration.md b/docs/mavericks_migration.md
new file mode 100644
index 0000000000..a36ae8261a
--- /dev/null
+++ b/docs/mavericks_migration.md
@@ -0,0 +1,11 @@
+Useful links:
+- https://airbnb.io/mavericks/#/new-2x
+
+Mavericks 2 is replacing MvRx, by removing usage of Rx by Flow, both internally and in the API.
+See the link ^ to have more intel, but basically, the changes are:
+
+session.rx() => session.flow()
+room.rx() => room.flow()
+subscribe { }.disposeOnClear() => onEach { }.launchIn(viewModelScope)
+
+Only using manually onEach requires to add launchIn,any other methods provided by Mavericks on viewModel and activity/fragment are already taking care of lifecycle.
\ No newline at end of file
diff --git a/docs/rx_flow_migration.md b/docs/rx_flow_migration.md
new file mode 100644
index 0000000000..a438b0f6fb
--- /dev/null
+++ b/docs/rx_flow_migration.md
@@ -0,0 +1,41 @@
+Useful links:
+- https://github.com/ReactiveCircus/FlowBinding
+- https://ivanisidrowu.github.io/kotlin/2020/08/09/Kotlin-Flow-Migration-And-Testing.html
+
+
+Rx is now completely removed from Element dependencies.
+Some examples of the changes:
+
+```
+ sharedActionViewModel
+ .observe()
+ .subscribe { handleQuickActions(it) }
+ .disposeOnDestroyView()
+ ```
+
+became
+
+ ```
+ sharedActionViewModel
+ .stream()
+ .onEach { handleQuickActions(it) }
+ .launchIn(viewLifecycleOwner.lifecycleScope)
+
+```
+
+Inside fragment use
+```
+launchIn(viewLifecycleOwner.lifecycleScope)
+```
+Inside activity use
+```
+launchIn(lifecycleScope)
+```
+Inside viewModel use
+```
+launchIn(viewModelScope)
+```
+
+Also be aware that when using these scopes the coroutine is launched on Dispatchers.Main by default.
+
+
diff --git a/fastlane/README.md b/fastlane/README.md
index 54d3a005a6..dc33f422d6 100644
--- a/fastlane/README.md
+++ b/fastlane/README.md
@@ -44,6 +44,6 @@ Get version code
----
-This README.md is auto-generated and will be re-generated every time [fastlane](https://fastlane.tools) is run.
+This README.md is auto-generated and will be re-generated every time [_fastlane_](https://fastlane.tools) is run.
More information about fastlane can be found on [fastlane.tools](https://fastlane.tools).
The documentation of fastlane can be found on [docs.fastlane.tools](https://docs.fastlane.tools).
diff --git a/fastlane/metadata/android/cs-CZ/changelogs/40101160.txt b/fastlane/metadata/android/cs-CZ/changelogs/40101160.txt
new file mode 100644
index 0000000000..df927bca03
--- /dev/null
+++ b/fastlane/metadata/android/cs-CZ/changelogs/40101160.txt
@@ -0,0 +1,2 @@
+Hlavní změny v této verzi: Oprava chyby při odesílání šifrované zprávy, pokud se někdo v místnosti odhlásí.
+Úplný seznam změn: https://github.com/vector-im/element-android/releases/tag/v1.1.16
diff --git a/fastlane/metadata/android/cs-CZ/changelogs/40102000.txt b/fastlane/metadata/android/cs-CZ/changelogs/40102000.txt
new file mode 100644
index 0000000000..929281c388
--- /dev/null
+++ b/fastlane/metadata/android/cs-CZ/changelogs/40102000.txt
@@ -0,0 +1,2 @@
+Hlavní změny v této verzi: Hlasové zprávy jsou povoleny ve výchozím nastavení.
+Úplný seznam změn: https://github.com/vector-im/element-android/releases/tag/v1.2.0
diff --git a/fastlane/metadata/android/cs-CZ/changelogs/40102010.txt b/fastlane/metadata/android/cs-CZ/changelogs/40102010.txt
new file mode 100644
index 0000000000..ca75c6b5d8
--- /dev/null
+++ b/fastlane/metadata/android/cs-CZ/changelogs/40102010.txt
@@ -0,0 +1,2 @@
+Hlavní změny v této verzi: Mnohá vylepšení VoIP a prostorů (stále v beta verzi).
+Úplný seznam změn: https://github.com/vector-im/element-android/releases/tag/v1.2.1
diff --git a/fastlane/metadata/android/cs-CZ/changelogs/40103000.txt b/fastlane/metadata/android/cs-CZ/changelogs/40103000.txt
new file mode 100644
index 0000000000..f97ff3ef3a
--- /dev/null
+++ b/fastlane/metadata/android/cs-CZ/changelogs/40103000.txt
@@ -0,0 +1,2 @@
+Hlavní změny v této verzi: Uspořádejte si místnosti pomocí Prostorů!
+Úplný seznam změn: https://github.com/vector-im/element-android/releases/tag/v1.3.0
diff --git a/fastlane/metadata/android/cs-CZ/changelogs/40103010.txt b/fastlane/metadata/android/cs-CZ/changelogs/40103010.txt
new file mode 100644
index 0000000000..37f8aaa759
--- /dev/null
+++ b/fastlane/metadata/android/cs-CZ/changelogs/40103010.txt
@@ -0,0 +1,2 @@
+Hlavní změny v této verzi: Uspořádejte si místnosti pomocí Prostorů! Verze 1.3.1 opravuje pády, ke kterým může docházet ve verzi v1.3.0.
+Úplný seznam změn: https://github.com/vector-im/element-android/releases/tag/v1.3.1
diff --git a/fastlane/metadata/android/cs-CZ/changelogs/40103020.txt b/fastlane/metadata/android/cs-CZ/changelogs/40103020.txt
new file mode 100644
index 0000000000..2a9dd4bb10
--- /dev/null
+++ b/fastlane/metadata/android/cs-CZ/changelogs/40103020.txt
@@ -0,0 +1,2 @@
+Hlavní změny v této verzi: Přidání podpory pro Android Auto. Spousta oprav chyb!
+Úplný seznam změn: https://github.com/vector-im/element-android/releases/tag/v1.3.2
diff --git a/fastlane/metadata/android/cs-CZ/changelogs/40103030.txt b/fastlane/metadata/android/cs-CZ/changelogs/40103030.txt
new file mode 100644
index 0000000000..8faffd36ed
--- /dev/null
+++ b/fastlane/metadata/android/cs-CZ/changelogs/40103030.txt
@@ -0,0 +1,2 @@
+Hlavní změny v této verzi: Umožňuje v nastavení zviditelnit zásady serveru identit. Dočasně odstraňuje podporu pro Android Auto.
+Úplný seznam změn: https://github.com/vector-im/element-android/releases/tag/v1.3.3
diff --git a/fastlane/metadata/android/cs-CZ/changelogs/40103040.txt b/fastlane/metadata/android/cs-CZ/changelogs/40103040.txt
new file mode 100644
index 0000000000..ac909485d7
--- /dev/null
+++ b/fastlane/metadata/android/cs-CZ/changelogs/40103040.txt
@@ -0,0 +1,2 @@
+Hlavní změny v této verzi: Přidání podpory přítomnosti pro místnost s přímými zprávami (poznámka: přítomnost je na matrix.org zakázána). Opět přidána podpora Android Auto.
+Úplný seznam změn: https://github.com/vector-im/element-android/releases/tag/v1.3.4
diff --git a/fastlane/metadata/android/cs-CZ/changelogs/40103050.txt b/fastlane/metadata/android/cs-CZ/changelogs/40103050.txt
new file mode 100644
index 0000000000..6aee9110ef
--- /dev/null
+++ b/fastlane/metadata/android/cs-CZ/changelogs/40103050.txt
@@ -0,0 +1,2 @@
+Hlavní změny v této verzi: Přidání podpory přítomnosti pro místnost s přímými zprávami (poznámka: přítomnost je na matrix.org zakázána). Opět přidána podpora Android Auto.
+Úplný seznam změn: https://github.com/vector-im/element-android/releases/tag/v1.3.5
diff --git a/fastlane/metadata/android/cs-CZ/changelogs/40103060.txt b/fastlane/metadata/android/cs-CZ/changelogs/40103060.txt
new file mode 100644
index 0000000000..ef29377a46
--- /dev/null
+++ b/fastlane/metadata/android/cs-CZ/changelogs/40103060.txt
@@ -0,0 +1,2 @@
+Hlavní změny v této verzi: Přidání podpory přítomnosti pro místnost s přímými zprávami (poznámka: přítomnost je na matrix.org zakázána). Opět přidána podpora Android Auto.
+Úplný seznam změn: https://github.com/vector-im/element-android/releases/tag/v1.3.6
diff --git a/fastlane/metadata/android/cs-CZ/full_description.txt b/fastlane/metadata/android/cs-CZ/full_description.txt
index d169c077e1..a74c58b413 100644
--- a/fastlane/metadata/android/cs-CZ/full_description.txt
+++ b/fastlane/metadata/android/cs-CZ/full_description.txt
@@ -11,7 +11,7 @@ Element je zabezpečený komunikátor a zároveň aplikace pro týmovou spolupr
Element se zcela liší od ostatních aplikací pro zasílání zpráv a spolupráci. Funguje na platformě Matrix, otevřené síti pro bezpečné zasílání zpráv a decentralizovanou komunikaci. Umožňuje vlastní hostování, aby uživatelé měli maximální vlastnictví a kontrolu nad svými daty a zprávami.
Soukromí a šifrované zprávy
-Element vás chrání před nežádoucími reklamami, vytěžováním dat a tzv. walled gardens. Zabezpečuje také všechna vaše data, video a hlasovou komunikaci jeden na jednoho prostřednictvím šifrování end-to-end a křížového ověřování zařízení.
+Element vás chrání před nežádoucími reklamami, vytěžováním dat a tzv. walled gardens. Zabezpečuje také všechna vaše data, video a hlasovou komunikaci jeden na jednoho prostřednictvím koncového šifrování a křížového ověřování zařízení.
Element vám dává kontrolu nad vaším soukromím a zároveň vám umožňuje bezpečně komunikovat s kýmkoli v síti Matrix nebo s dalšími nástroji pro firemní spolupráci díky integraci s aplikacemi, jako je Slack.
@@ -30,10 +30,13 @@ Element vám dává kontrolu různými způsoby:
Můžete chatovat s kýmkoli v síti Matrix, ať už používá aplikaci Element, jinou aplikaci podporující protokol Matrix nebo dokonce i když používá jinou aplikaci pro zasílání zpráv.
Superbezpečné
-Skutečné end-to-end šifrování (zprávy mohou dešifrovat pouze účastníci konverzace) a křížové ověřování zařízení.
+Skutečné koncové šifrování (zprávy mohou dešifrovat pouze účastníci konverzace) a křížové ověřování zařízení.
Kompletní komunikace a integrace
Zprávy, hlasové a videohovory, sdílení souborů, sdílení obrazovky a celá řada integrací, botů a widgetů. Vytvářejte místnosti, komunity, zůstaňte v kontaktu a spolupracujte.
Navažte tam, kde jste skončili
Zůstaňte v kontaktu, ať jste kdekoli, díky plně synchronizované historii zpráv ve všech zařízeních a na webu https://app.element.io
+
+Open source
+Element Android je projekt s otevřeným zdrojovým kódem, který je hostován na GitHubu. Nahlaste prosím chyby a přispějte k jeho vývoji na adrese https://github.com/vector-im/element-android
diff --git a/fastlane/metadata/android/de-DE/changelogs/40101120.txt b/fastlane/metadata/android/de-DE/changelogs/40101120.txt
new file mode 100644
index 0000000000..ac147c6cbb
--- /dev/null
+++ b/fastlane/metadata/android/de-DE/changelogs/40101120.txt
@@ -0,0 +1,2 @@
+Hauptänderungen in dieser Version: Überarbeitetes Design, Crash nach Videoanruf gefixt
+Alle Änderungen: https://github.com/vector-im/element-android/releases/tag/v1.1.12
diff --git a/fastlane/metadata/android/de-DE/changelogs/40101130.txt b/fastlane/metadata/android/de-DE/changelogs/40101130.txt
new file mode 100644
index 0000000000..4ef31c67ed
--- /dev/null
+++ b/fastlane/metadata/android/de-DE/changelogs/40101130.txt
@@ -0,0 +1,2 @@
+Stabilitäts- und Bugfixupdate
+Alle Änderungen: https://github.com/vector-im/element-android/releases/tag/v1.1.13
diff --git a/fastlane/metadata/android/de-DE/changelogs/40101150.txt b/fastlane/metadata/android/de-DE/changelogs/40101150.txt
new file mode 100644
index 0000000000..7fa18ed944
--- /dev/null
+++ b/fastlane/metadata/android/de-DE/changelogs/40101150.txt
@@ -0,0 +1,2 @@
+Hauptänderungen: Sprachnachrichten in experimentellen Einstellungen
+Alle Änderungen: https://github.com/vector-im/element-android/releases/tag/v1.1.15
diff --git a/fastlane/metadata/android/de-DE/changelogs/40101160.txt b/fastlane/metadata/android/de-DE/changelogs/40101160.txt
new file mode 100644
index 0000000000..babd4af04f
--- /dev/null
+++ b/fastlane/metadata/android/de-DE/changelogs/40101160.txt
@@ -0,0 +1,2 @@
+Hauptänderungen in dieser Version: Fehler beim Senden verschlüsselter Nachrichten behoben.
+Alle Änderungen: https://github.com/vector-im/element-android/releases/tag/v1.1.16
diff --git a/fastlane/metadata/android/de-DE/changelogs/40102000.txt b/fastlane/metadata/android/de-DE/changelogs/40102000.txt
new file mode 100644
index 0000000000..cfa9f725f2
--- /dev/null
+++ b/fastlane/metadata/android/de-DE/changelogs/40102000.txt
@@ -0,0 +1,2 @@
+Hauptänderungen: Sprachnachrichten standardmäßig aktiviert.
+Ganze Änderungsliste: https://github.com/vector-im/element-android/releases/tag/v1.2.0
diff --git a/fastlane/metadata/android/de-DE/changelogs/40102010.txt b/fastlane/metadata/android/de-DE/changelogs/40102010.txt
new file mode 100644
index 0000000000..2635704a81
--- /dev/null
+++ b/fastlane/metadata/android/de-DE/changelogs/40102010.txt
@@ -0,0 +1,2 @@
+VoIP und Spaces verbessert
+Vollständige Änderungsliste: https://github.com/vector-im/element-android/releases/tag/v1.2.1
diff --git a/fastlane/metadata/android/de-DE/changelogs/40103000.txt b/fastlane/metadata/android/de-DE/changelogs/40103000.txt
new file mode 100644
index 0000000000..85386226db
--- /dev/null
+++ b/fastlane/metadata/android/de-DE/changelogs/40103000.txt
@@ -0,0 +1,2 @@
+Hauptänderungen: Organisiere deine Räume mit Spaces!
+Alle Änderungen: https://github.com/vector-im/element-android/releases/tag/v1.3.0
diff --git a/fastlane/metadata/android/de-DE/changelogs/40103010.txt b/fastlane/metadata/android/de-DE/changelogs/40103010.txt
new file mode 100644
index 0000000000..3323a37a59
--- /dev/null
+++ b/fastlane/metadata/android/de-DE/changelogs/40103010.txt
@@ -0,0 +1,2 @@
+Hauptänderungen: Organisiere deine Räume mit Spaces, Crash aus 1.3.0 gefixt.
+Alle Änderungen: https://github.com/vector-im/element-android/releases/tag/v1.3.1
diff --git a/fastlane/metadata/android/de-DE/changelogs/40103020.txt b/fastlane/metadata/android/de-DE/changelogs/40103020.txt
new file mode 100644
index 0000000000..880ec71c4d
--- /dev/null
+++ b/fastlane/metadata/android/de-DE/changelogs/40103020.txt
@@ -0,0 +1,2 @@
+Hauptänderungen: Unterstützung für Android Auto, Viele Fehlerbehebungen
+Alle Änderungen: https://github.com/vector-im/element-android/releases/tag/v1.3.2
diff --git a/fastlane/metadata/android/de-DE/changelogs/40103030.txt b/fastlane/metadata/android/de-DE/changelogs/40103030.txt
new file mode 100644
index 0000000000..da3451fb0d
--- /dev/null
+++ b/fastlane/metadata/android/de-DE/changelogs/40103030.txt
@@ -0,0 +1,2 @@
+Hauptänderungen: Bedingungen des Identitätsservers in Einstellungen anzeigen. Unterstützung für Android Auto temporär entfernt.
+Alle Änderungen: https://github.com/vector-im/element-android/releases/tag/v1.3.3
diff --git a/fastlane/metadata/android/de-DE/changelogs/40103040.txt b/fastlane/metadata/android/de-DE/changelogs/40103040.txt
new file mode 100644
index 0000000000..37ab9ccd8f
--- /dev/null
+++ b/fastlane/metadata/android/de-DE/changelogs/40103040.txt
@@ -0,0 +1,4 @@
+Hauptänderungen:
+- Anwesenheiten in Direktnachrichten anzeigen (Momentan auf Matrix.org deaktiviert)
+- Android Auto wird wieder unterstützt
+Alle Änderungen: https://github.com/vector-im/element-android/releases/tag/v1.3.4
diff --git a/fastlane/metadata/android/de-DE/full_description.txt b/fastlane/metadata/android/de-DE/full_description.txt
index 30eb153ee9..c4fecf7674 100644
--- a/fastlane/metadata/android/de-DE/full_description.txt
+++ b/fastlane/metadata/android/de-DE/full_description.txt
@@ -37,3 +37,6 @@ Kurznachrichten, Sprach- und Videoanrufe, Dateifreigaben, Bildschirmübertragung
Da Weitermachen, wo Sie aufgehört haben
Bleiben Sie in Kontakt, egal wo Sie sind, mit vollständig synchronisiertem Nachrichtenverlauf quer über all Ihre Geräte und im Netz auf https://app.element.io
+
+Open source
+Element ist ein Open-Source-Projekt und wird auf GitHub gehostet. Solltest du Fehler in Element finden, melde diese bitte hier: https://github.com/vector-im/element-android
diff --git a/fastlane/metadata/android/en-US/changelogs/40102000.txt b/fastlane/metadata/android/en-US/changelogs/40102000.txt
index 46d9b07809..4fc02966cd 100644
--- a/fastlane/metadata/android/en-US/changelogs/40102000.txt
+++ b/fastlane/metadata/android/en-US/changelogs/40102000.txt
@@ -1,2 +1,2 @@
Main changes in this version: Voice Message is enabled by default.
-Full changelog: https://github.com/vector-im/element-android/releases/tag/v1.1.16
\ No newline at end of file
+Full changelog: https://github.com/vector-im/element-android/releases/tag/v1.2.0
\ No newline at end of file
diff --git a/fastlane/metadata/android/en-US/changelogs/40102010.txt b/fastlane/metadata/android/en-US/changelogs/40102010.txt
new file mode 100644
index 0000000000..799b7dc8b6
--- /dev/null
+++ b/fastlane/metadata/android/en-US/changelogs/40102010.txt
@@ -0,0 +1,2 @@
+Main changes in this version: Many improvements on VoIP and Spaces (still in beta).
+Full changelog: https://github.com/vector-im/element-android/releases/tag/v1.2.1
\ No newline at end of file
diff --git a/fastlane/metadata/android/en-US/changelogs/40103000.txt b/fastlane/metadata/android/en-US/changelogs/40103000.txt
new file mode 100644
index 0000000000..d4ef2f75a0
--- /dev/null
+++ b/fastlane/metadata/android/en-US/changelogs/40103000.txt
@@ -0,0 +1,2 @@
+Main changes in this version: Organize your rooms using Spaces!
+Full changelog: https://github.com/vector-im/element-android/releases/tag/v1.3.0
\ No newline at end of file
diff --git a/fastlane/metadata/android/en-US/changelogs/40103010.txt b/fastlane/metadata/android/en-US/changelogs/40103010.txt
new file mode 100644
index 0000000000..e3760f1882
--- /dev/null
+++ b/fastlane/metadata/android/en-US/changelogs/40103010.txt
@@ -0,0 +1,2 @@
+Main changes in this version: Organize your rooms using Spaces! v1.3.1 is fixing a crash which can occurs in v1.3.0.
+Full changelog: https://github.com/vector-im/element-android/releases/tag/v1.3.1
\ No newline at end of file
diff --git a/fastlane/metadata/android/en-US/changelogs/40103020.txt b/fastlane/metadata/android/en-US/changelogs/40103020.txt
new file mode 100644
index 0000000000..7ac48f4890
--- /dev/null
+++ b/fastlane/metadata/android/en-US/changelogs/40103020.txt
@@ -0,0 +1,2 @@
+Main changes in this version: Add support for Android Auto. Lot of bug fixes!
+Full changelog: https://github.com/vector-im/element-android/releases/tag/v1.3.2
\ No newline at end of file
diff --git a/fastlane/metadata/android/en-US/changelogs/40103030.txt b/fastlane/metadata/android/en-US/changelogs/40103030.txt
new file mode 100644
index 0000000000..2068aeed95
--- /dev/null
+++ b/fastlane/metadata/android/en-US/changelogs/40103030.txt
@@ -0,0 +1,2 @@
+Main changes in this version: Make identity server policy(ies) visible in the settings. Temporarily remove Android Auto support.
+Full changelog: https://github.com/vector-im/element-android/releases/tag/v1.3.3
\ No newline at end of file
diff --git a/fastlane/metadata/android/en-US/changelogs/40103040.txt b/fastlane/metadata/android/en-US/changelogs/40103040.txt
new file mode 100644
index 0000000000..a6af2efe00
--- /dev/null
+++ b/fastlane/metadata/android/en-US/changelogs/40103040.txt
@@ -0,0 +1,2 @@
+Main changes in this version: Add Presence support, for Direct Message room (note: presence is disabled on matrix.org). Add again Android Auto support.
+Full changelog: https://github.com/vector-im/element-android/releases/tag/v1.3.4
\ No newline at end of file
diff --git a/fastlane/metadata/android/en-US/changelogs/40103050.txt b/fastlane/metadata/android/en-US/changelogs/40103050.txt
new file mode 100644
index 0000000000..93227f1a6d
--- /dev/null
+++ b/fastlane/metadata/android/en-US/changelogs/40103050.txt
@@ -0,0 +1,2 @@
+Main changes in this version: Add Presence support, for Direct Message room (note: presence is disabled on matrix.org). Add again Android Auto support.
+Full changelog: https://github.com/vector-im/element-android/releases/tag/v1.3.5
\ No newline at end of file
diff --git a/fastlane/metadata/android/en-US/changelogs/40103060.txt b/fastlane/metadata/android/en-US/changelogs/40103060.txt
new file mode 100644
index 0000000000..7afd03a5c8
--- /dev/null
+++ b/fastlane/metadata/android/en-US/changelogs/40103060.txt
@@ -0,0 +1,2 @@
+Main changes in this version: Add Presence support, for Direct Message room (note: presence is disabled on matrix.org). Add again Android Auto support.
+Full changelog: https://github.com/vector-im/element-android/releases/tag/v1.3.6
\ No newline at end of file
diff --git a/fastlane/metadata/android/en-US/changelogs/40103070.txt b/fastlane/metadata/android/en-US/changelogs/40103070.txt
new file mode 100644
index 0000000000..ad225133c2
--- /dev/null
+++ b/fastlane/metadata/android/en-US/changelogs/40103070.txt
@@ -0,0 +1,2 @@
+Main changes in this version: Bug fixes mainly regarding the notifications.
+Full changelog: https://github.com/vector-im/element-android/releases/tag/v1.3.7
\ No newline at end of file
diff --git a/fastlane/metadata/android/en-US/full_description.txt b/fastlane/metadata/android/en-US/full_description.txt
index 853885944c..ef8d4e6a27 100644
--- a/fastlane/metadata/android/en-US/full_description.txt
+++ b/fastlane/metadata/android/en-US/full_description.txt
@@ -36,4 +36,7 @@ Real end-to-end encryption (only those in the conversation can decrypt messages)
Messaging, voice and video calls, file sharing, screen sharing and a whole bunch of integrations, bots and widgets. Build rooms, communities, stay in touch and get things done.
Pick up where you left off
-Stay in touch wherever you are with fully synchronised message history across all your devices and on the web at https://app.element.io
\ No newline at end of file
+Stay in touch wherever you are with fully synchronised message history across all your devices and on the web at https://app.element.io
+
+Open source
+Element Android is an open source project, hosted by GitHub. Please report bugs and/or contribute to its development at https://github.com/vector-im/element-android
\ No newline at end of file
diff --git a/fastlane/metadata/android/es-ES/changelogs/40100100.txt b/fastlane/metadata/android/es-ES/changelogs/40100100.txt
index 70b786d12e..5cfcde2145 100644
--- a/fastlane/metadata/android/es-ES/changelogs/40100100.txt
+++ b/fastlane/metadata/android/es-ES/changelogs/40100100.txt
@@ -1 +1,2 @@
-// TODO
+Esta nueva versión contiene principalmente correcciones de errores y mejoras. Enviar un mensaje ahora es mucho más rápido.
+Registro de cambios completo: https://github.com/vector-im/element-android/releases/tag/v1.0.10
diff --git a/fastlane/metadata/android/es-ES/changelogs/40100110.txt b/fastlane/metadata/android/es-ES/changelogs/40100110.txt
new file mode 100644
index 0000000000..5444087750
--- /dev/null
+++ b/fastlane/metadata/android/es-ES/changelogs/40100110.txt
@@ -0,0 +1,2 @@
+Esta nueva versión contiene principalmente mejoras en la interfaz de usuario y la experiencia del usuario. Ahora puedes invitar amigos y crear mensajes directos muy rápido escaneando códigos QR.
+Registro de cambios completo: https://github.com/vector-im/element-android/releases/tag/v1.0.11
diff --git a/fastlane/metadata/android/es-ES/changelogs/40100120.txt b/fastlane/metadata/android/es-ES/changelogs/40100120.txt
new file mode 100644
index 0000000000..3e17b0359b
--- /dev/null
+++ b/fastlane/metadata/android/es-ES/changelogs/40100120.txt
@@ -0,0 +1,2 @@
+Principales cambios en esta versión: Vista previa de URL, nuevo teclado Emoji, nuevas capacidades de configuración de la habitación y ¡nieve para Navidad!
+Registro de cambios completo: https://github.com/vector-im/element-android/releases/tag/v1.0.12
diff --git a/fastlane/metadata/android/es-ES/changelogs/40100130.txt b/fastlane/metadata/android/es-ES/changelogs/40100130.txt
new file mode 100644
index 0000000000..c87cb0faf5
--- /dev/null
+++ b/fastlane/metadata/android/es-ES/changelogs/40100130.txt
@@ -0,0 +1,2 @@
+Principales cambios en esta versión: Vista previa de URL, nuevo teclado Emoji, nuevas capacidades de configuración de la habitación y ¡nieve para Navidad!
+Registro de cambios completo: https://github.com/vector-im/element-android/releases/tag/v1.0.13
diff --git a/fastlane/metadata/android/es-ES/changelogs/40100140.txt b/fastlane/metadata/android/es-ES/changelogs/40100140.txt
new file mode 100644
index 0000000000..9bd36b13db
--- /dev/null
+++ b/fastlane/metadata/android/es-ES/changelogs/40100140.txt
@@ -0,0 +1,2 @@
+Principales cambios en esta versión: Editar permisos de sala, tema automático de luz / oscuridad y un montón de correcciones de errores.
+Registro de cambios completo: https://github.com/vector-im/element-android/releases/tag/v1.0.14
diff --git a/fastlane/metadata/android/es-ES/changelogs/40100150.txt b/fastlane/metadata/android/es-ES/changelogs/40100150.txt
new file mode 100644
index 0000000000..f1b7d303d1
--- /dev/null
+++ b/fastlane/metadata/android/es-ES/changelogs/40100150.txt
@@ -0,0 +1,2 @@
+Principales cambios en esta versión: Soporte de inicio de sesión social.
+Registro de cambios completo: https://github.com/vector-im/element-android/releases/tag/v1.0.15
diff --git a/fastlane/metadata/android/es-ES/changelogs/40100160.txt b/fastlane/metadata/android/es-ES/changelogs/40100160.txt
new file mode 100644
index 0000000000..707ec23519
--- /dev/null
+++ b/fastlane/metadata/android/es-ES/changelogs/40100160.txt
@@ -0,0 +1,2 @@
+Principales cambios en esta versión: Soporte de inicio de sesión social.
+Registro de cambios completo: https://github.com/vector-im/element-android/releases/tag/v1.0.15 y https://github.com/vector-im/element-android/releases/tag/v1.0.16
diff --git a/fastlane/metadata/android/es-ES/changelogs/40100170.txt b/fastlane/metadata/android/es-ES/changelogs/40100170.txt
new file mode 100644
index 0000000000..9c6d3d7f54
--- /dev/null
+++ b/fastlane/metadata/android/es-ES/changelogs/40100170.txt
@@ -0,0 +1,2 @@
+Principales cambios en esta versión: ¡Corrección de errores!
+Registro de cambios completo: https://github.com/vector-im/element-android/releases/tag/v1.0.17
diff --git a/fastlane/metadata/android/es-ES/changelogs/40101000.txt b/fastlane/metadata/android/es-ES/changelogs/40101000.txt
new file mode 100644
index 0000000000..996f9fdde8
--- /dev/null
+++ b/fastlane/metadata/android/es-ES/changelogs/40101000.txt
@@ -0,0 +1,2 @@
+Principales cambios en esta versión: ¡Mejora de VoIP (audio y videollamadas en DM) y corrección de errores!
+Registro de cambios completo: https://github.com/vector-im/element-android/releases/tag/v1.1.0
diff --git a/fastlane/metadata/android/es-ES/changelogs/40101010.txt b/fastlane/metadata/android/es-ES/changelogs/40101010.txt
new file mode 100644
index 0000000000..ea9662576c
--- /dev/null
+++ b/fastlane/metadata/android/es-ES/changelogs/40101010.txt
@@ -0,0 +1,2 @@
+Principales cambios en esta versión: mejora del rendimiento y corrección de errores.
+Registro de cambios completo: https://github.com/vector-im/element-android/releases/tag/v1.1.1
diff --git a/fastlane/metadata/android/es-ES/changelogs/40101020.txt b/fastlane/metadata/android/es-ES/changelogs/40101020.txt
new file mode 100644
index 0000000000..87a92a96cd
--- /dev/null
+++ b/fastlane/metadata/android/es-ES/changelogs/40101020.txt
@@ -0,0 +1,2 @@
+Principales cambios en esta versión: mejora del rendimiento y corrección de errores.
+Registro de cambios completo: https://github.com/vector-im/element-android/releases/tag/v1.1.2
diff --git a/fastlane/metadata/android/es-ES/changelogs/40101030.txt b/fastlane/metadata/android/es-ES/changelogs/40101030.txt
new file mode 100644
index 0000000000..ca82a2c59c
--- /dev/null
+++ b/fastlane/metadata/android/es-ES/changelogs/40101030.txt
@@ -0,0 +1,2 @@
+Principales cambios en esta versión: mejora del rendimiento y corrección de errores.
+Registro de cambios completo: https://github.com/vector-im/element-android/releases/tag/v1.1.3
diff --git a/fastlane/metadata/android/es-ES/changelogs/40101040.txt b/fastlane/metadata/android/es-ES/changelogs/40101040.txt
new file mode 100644
index 0000000000..59acee78de
--- /dev/null
+++ b/fastlane/metadata/android/es-ES/changelogs/40101040.txt
@@ -0,0 +1,2 @@
+Principales cambios en esta versión: mejora del rendimiento y corrección de errores.
+Registro de cambios completo: https://github.com/vector-im/element-android/releases/tag/v1.1.4
diff --git a/fastlane/metadata/android/es-ES/changelogs/40101050.txt b/fastlane/metadata/android/es-ES/changelogs/40101050.txt
new file mode 100644
index 0000000000..ccdd9fd8d6
--- /dev/null
+++ b/fastlane/metadata/android/es-ES/changelogs/40101050.txt
@@ -0,0 +1,2 @@
+Principales cambios en esta versión: correcciones urgentes para 1.1.4
+Registro de cambios completo: https://github.com/vector-im/element-android/releases/tag/v1.1.5
diff --git a/fastlane/metadata/android/es-ES/changelogs/40101060.txt b/fastlane/metadata/android/es-ES/changelogs/40101060.txt
new file mode 100644
index 0000000000..9da3a09866
--- /dev/null
+++ b/fastlane/metadata/android/es-ES/changelogs/40101060.txt
@@ -0,0 +1,2 @@
+Principales cambios en esta versión: correcciones urgentes para 1.1.5
+Registro de cambios completo: https://github.com/vector-im/element-android/releases/tag/v1.1.6
diff --git a/fastlane/metadata/android/es-ES/changelogs/40101070.txt b/fastlane/metadata/android/es-ES/changelogs/40101070.txt
new file mode 100644
index 0000000000..6abb774b93
--- /dev/null
+++ b/fastlane/metadata/android/es-ES/changelogs/40101070.txt
@@ -0,0 +1,2 @@
+Principales cambios en esta versión: soporte beta para Spaces. Comprima el video antes de enviarlo.
+Registro de cambios completo: https://github.com/vector-im/element-android/releases/tag/v1.1.7
diff --git a/fastlane/metadata/android/es-ES/changelogs/40101080.txt b/fastlane/metadata/android/es-ES/changelogs/40101080.txt
new file mode 100644
index 0000000000..776bc52a25
--- /dev/null
+++ b/fastlane/metadata/android/es-ES/changelogs/40101080.txt
@@ -0,0 +1,2 @@
+Principales cambios en esta versión: mejora de Spaces.
+Registro de cambios completo: https://github.com/vector-im/element-android/releases/tag/v1.1.8
diff --git a/fastlane/metadata/android/es-ES/changelogs/40101090.txt b/fastlane/metadata/android/es-ES/changelogs/40101090.txt
new file mode 100644
index 0000000000..eaeab1517a
--- /dev/null
+++ b/fastlane/metadata/android/es-ES/changelogs/40101090.txt
@@ -0,0 +1,2 @@
+Principales cambios en esta versión: agregar soporte para la red gitter.im.
+Registro de cambios completo: https://github.com/vector-im/element-android/releases/tag/v1.1.9
diff --git a/fastlane/metadata/android/es-ES/changelogs/40101100.txt b/fastlane/metadata/android/es-ES/changelogs/40101100.txt
new file mode 100644
index 0000000000..d82529cf22
--- /dev/null
+++ b/fastlane/metadata/android/es-ES/changelogs/40101100.txt
@@ -0,0 +1,2 @@
+Principales cambios en esta versión: actualización de tema y estilo y nuevas funcionalidades para espacios.
+Registro de cambios completo: https://github.com/vector-im/element-android/releases/tag/v1.1.10
diff --git a/fastlane/metadata/android/es-ES/changelogs/40101110.txt b/fastlane/metadata/android/es-ES/changelogs/40101110.txt
new file mode 100644
index 0000000000..6432d2052a
--- /dev/null
+++ b/fastlane/metadata/android/es-ES/changelogs/40101110.txt
@@ -0,0 +1,2 @@
+Principales cambios en esta versión: actualización de tema y estilo y nuevas funciones para espacios (corrección de errores para 1.1.10)
+Registro de cambios completo: https://github.com/vector-im/element-android/releases/tag/v1.1.11
diff --git a/fastlane/metadata/android/es-ES/changelogs/40101120.txt b/fastlane/metadata/android/es-ES/changelogs/40101120.txt
new file mode 100644
index 0000000000..a657fff51c
--- /dev/null
+++ b/fastlane/metadata/android/es-ES/changelogs/40101120.txt
@@ -0,0 +1,2 @@
+Principales cambios en esta versión: actualización de tema y estilo y corrección de un bloqueo después de la videollamada
+Registro de cambios completo: https://github.com/vector-im/element-android/releases/tag/v1.1.12
diff --git a/fastlane/metadata/android/es-ES/changelogs/40101130.txt b/fastlane/metadata/android/es-ES/changelogs/40101130.txt
new file mode 100644
index 0000000000..c9fbf424ae
--- /dev/null
+++ b/fastlane/metadata/android/es-ES/changelogs/40101130.txt
@@ -0,0 +1,2 @@
+Principales cambios en esta versión: principalmente actualización de estabilidad y corrección de errores.
+Registro de cambios completo: https://github.com/vector-im/element-android/releases/tag/v1.1.13
diff --git a/fastlane/metadata/android/es-ES/changelogs/40101140.txt b/fastlane/metadata/android/es-ES/changelogs/40101140.txt
new file mode 100644
index 0000000000..77399d6aef
--- /dev/null
+++ b/fastlane/metadata/android/es-ES/changelogs/40101140.txt
@@ -0,0 +1,2 @@
+Principales cambios en esta versión: arreglado un problema con los mensajes encriptados.
+Conjunto de cambios completo: https://github.com/vector-im/element-android/releases/tag/v1.1.14
diff --git a/fastlane/metadata/android/es-ES/changelogs/40101150.txt b/fastlane/metadata/android/es-ES/changelogs/40101150.txt
new file mode 100644
index 0000000000..c127db1ef7
--- /dev/null
+++ b/fastlane/metadata/android/es-ES/changelogs/40101150.txt
@@ -0,0 +1,2 @@
+Principales cambios en esta versión: implementación de mensajes de voz bajo los ajustes lab.
+Conjunto de cambios completo: https://github.com/vector-im/element-android/releases/tag/v1.1.15
diff --git a/fastlane/metadata/android/es-ES/changelogs/40101160.txt b/fastlane/metadata/android/es-ES/changelogs/40101160.txt
new file mode 100644
index 0000000000..0d2ab3e13d
--- /dev/null
+++ b/fastlane/metadata/android/es-ES/changelogs/40101160.txt
@@ -0,0 +1,2 @@
+Principales cambios en esta versión: Solucionado error al enviar mensajes encriptados si alguien en la sala cierra la sesión.
+Conjunto de cambios completo: https://github.com/vector-im/element-android/releases/tag/v1.1.16
diff --git a/fastlane/metadata/android/es-ES/changelogs/40102000.txt b/fastlane/metadata/android/es-ES/changelogs/40102000.txt
new file mode 100644
index 0000000000..907019b6d6
--- /dev/null
+++ b/fastlane/metadata/android/es-ES/changelogs/40102000.txt
@@ -0,0 +1,2 @@
+Principales cambios en esta versión: Mensaje de voz está habilitado por defecto.
+Registro de cambios completo: https://github.com/vector-im/element-android/releases/tag/v1.2.0
diff --git a/fastlane/metadata/android/es-ES/changelogs/40102010.txt b/fastlane/metadata/android/es-ES/changelogs/40102010.txt
new file mode 100644
index 0000000000..909921ffd4
--- /dev/null
+++ b/fastlane/metadata/android/es-ES/changelogs/40102010.txt
@@ -0,0 +1,2 @@
+Principales cambios en esta versión: Muchas mejoras en VoIP y Spaces (aún en beta).
+Registro de cambios completo: https://github.com/vector-im/element-android/releases/tag/v1.2.1
diff --git a/fastlane/metadata/android/es-ES/changelogs/40103000.txt b/fastlane/metadata/android/es-ES/changelogs/40103000.txt
new file mode 100644
index 0000000000..054aa68541
--- /dev/null
+++ b/fastlane/metadata/android/es-ES/changelogs/40103000.txt
@@ -0,0 +1,2 @@
+Principales cambios en esta versión: ¡Organiza tus habitaciones usando Spaces!
+Registro de cambios completo: https://github.com/vector-im/element-android/releases/tag/v1.3.0
diff --git a/fastlane/metadata/android/es-ES/changelogs/40103010.txt b/fastlane/metadata/android/es-ES/changelogs/40103010.txt
new file mode 100644
index 0000000000..6ff7b0502e
--- /dev/null
+++ b/fastlane/metadata/android/es-ES/changelogs/40103010.txt
@@ -0,0 +1,2 @@
+Principales cambios en esta versión: ¡Organiza tus habitaciones usando Spaces! v1.3.1 está arreglando un bloqueo que puede ocurrir en v1.3.0.
+Registro de cambios completo: https://github.com/vector-im/element-android/releases/tag/v1.3.1
diff --git a/fastlane/metadata/android/es-ES/changelogs/40103020.txt b/fastlane/metadata/android/es-ES/changelogs/40103020.txt
new file mode 100644
index 0000000000..22f7592aea
--- /dev/null
+++ b/fastlane/metadata/android/es-ES/changelogs/40103020.txt
@@ -0,0 +1,2 @@
+Principales cambios en esta versión: agregar soporte para Android Auto. ¡Muchas correcciones de errores!
+Registro de cambios completo: https://github.com/vector-im/element-android/releases/tag/v1.3.2
diff --git a/fastlane/metadata/android/es-ES/full_description.txt b/fastlane/metadata/android/es-ES/full_description.txt
index 8c9915a735..fdba15e90e 100644
--- a/fastlane/metadata/android/es-ES/full_description.txt
+++ b/fastlane/metadata/android/es-ES/full_description.txt
@@ -1,30 +1,39 @@
-Element es un nuevo tipo de aplicación de mensajería y colaboración que:
+Element es un mensajero seguro y una aplicación de colaboración en equipo de productividad que es ideal para chats grupales mientras se trabaja a distancia. Esta aplicación de chat utiliza encriptación de un extremo a otro para proporcionar poderosas videoconferencias, uso compartido de archivos y llamadas de voz.
-1. Te da el control para preservar su privacidad
-2. Te permite comunicarse con cualquier persona en la red Matrix e incluso más allá al integrarse con aplicaciones como Slack
-3. Te protege de la publicidad, la minería de datos y los jardines vallados
-4. Te protege a través de encriptación de Extremo-a-Extremo, con firma cruzada para verificar a otros
+Las características de Element incluyen:
+- Herramientas de comunicación online avanzadas
+- Mensajes totalmente encriptados para permitir una comunicación corporativa más segura, incluso para trabajadores remotos
+- Chat descentralizado basado en el marco de código abierto Matrix
+- Uso compartido de archivos de forma segura con datos cifrados mientras gestiona proyectos
+- Chats de video con voz sobre IP y pantalla compartida
+- Fácil integración con sus herramientas de colaboración en línea favoritas, herramientas de gestión de proyectos, servicios VoIP y otras aplicaciones de mensajería para equipos
-Element es completamente diferente de otras aplicaciones de mensajería y colaboración porque es descentralizado y de código abierto.
+Element es completamente diferente de otras aplicaciones de mensajería y colaboración. Opera en Matrix, una red abierta para mensajería segura y comunicación descentralizada. Permite el autohospedaje para brindar a los usuarios la máxima propiedad y control de sus datos y mensajes.
-Element te permite tener su propio servidor privado, o elegir uno público, para que tenga privacidad, posesión, y control de sus datos y conversaciones. Te da acceso a una red abierta; para que no se quede atrapado hablando solo con otros usuarios de Element. Y es muy seguro.
+Privacidad y mensajería encriptada
+Element lo protege de anuncios no deseados, minería de datos y jardines amurallados. También protege todos sus datos, video uno a uno y comunicación de voz a través del cifrado de extremo a extremo y la verificación de dispositivos con firma cruzada.
-Element puede hacer todo esto porque opera en Matrix, el estándar para la comunicación abierta y descentralizada.
+Element le brinda control sobre su privacidad al mismo tiempo que le permite comunicarse de manera segura con cualquier persona en la red Matrix u otras herramientas de colaboración empresarial al integrarse con aplicaciones como Slack.
-Element te da el control permitiéndote elegir quién aloja tus conversaciones. Desde la aplicación Element, puedes elegir hospedar de diferentes maneras:
+El elemento puede ser autohospedado
+Para permitir un mayor control de sus conversaciones y datos confidenciales, Element puede ser autohospedado o puede elegir cualquier host basado en Matrix, el estándar para la comunicación descentralizada de código abierto. Element le brinda privacidad, cumplimiento de seguridad y flexibilidad de integración.
-1. Obtén una cuenta gratuita en el servidor público de matrix.org alojado por los desarrolladores de Matrix, o elije entre miles de servidores públicos alojados por voluntarios
-2. Autohospeda tu cuenta con un servidor en tu propio hardware
-3. Regístrate para obtener una cuenta en un servidor personalizado simplemente suscribiéndote a la plataforma de alojamiento de Element Matrix Services
+Sea dueño de sus datos
+Tú decides dónde guardar tus datos y mensajes. Sin riesgo de minería de datos o acceso de terceros.
-¿Por qué elegir Element?
+Element te da el control de diferentes maneras:
+1. Obtenga una cuenta gratuita en el servidor público de matrix.org alojado por los desarrolladores de Matrix, o elija entre miles de servidores públicos alojados por voluntarios
+2. Autohospede su cuenta ejecutando un servidor en su propia infraestructura de TI
+3. Regístrese para obtener una cuenta en un servidor personalizado simplemente suscribiéndose a la plataforma de alojamiento de Element Matrix Services
-TOMA POSESIÓN DE TUS DATOS : Tú decides dónde guardar tus datos y mensajes. Tú eres el propietario y quien lo controla, no alguna MEGACORP que extrae tu datos o da acceso a terceros.
+Colaboración y mensajería abierta
+Puede chatear con cualquier persona en la red Matrix, ya sea que esté usando Element, otra aplicación Matrix o incluso si está usando una aplicación de mensajería diferente.
-MENSAJERÍA ABIERTA Y COLABORACIÓN : Puede chatear con cualquier otra persona en la red de Matrix, tanto si usan Element u otra aplicación de Matrix, e incluso si están usando un sistema de mensajería diferente como Slack, IRC o XMPP.
+Súper seguro
+Cifrado real de extremo a extremo (solo aquellos en la conversación pueden descifrar mensajes) y verificación de dispositivos con firma cruzada.
-SUPER SEGURO : Encriptación de Extremo-a-Extremo real (solo aquellos en la conversación pueden descifrar mensajes) y firma cruzada para verificar los dispositivos de los participantes de la conversación.
+Completa comunicación e integración
+Mensajería, llamadas de voz y video, uso compartido de archivos, uso compartido de pantalla y un montón de integraciones, bots y widgets. Construya salas, comunidades, manténgase en contacto y haga las cosas.
-COMUNICACIÓN COMPLETA : Mensajería, llamadas de voz y video, uso compartido de archivos, uso compartido de pantalla y un montón de integraciones, bots y widgets. Crea salas, comunidades, mantente en contacto y organízate con eficacia.
-
-EN TODAS PARTES : Mantente en contacto donde quiera que estés con un historial de mensajes totalmente sincronizado en todos sus dispositivos y en la web en https://app.element.io.
+Continúa donde lo dejaste
+Manténgase en contacto donde quiera que esté con el historial de mensajes totalmente sincronizado en todos sus dispositivos y en la web en https://app.element.io
diff --git a/fastlane/metadata/android/es-ES/short_description.txt b/fastlane/metadata/android/es-ES/short_description.txt
index 473228e0df..0bd47ccf15 100644
--- a/fastlane/metadata/android/es-ES/short_description.txt
+++ b/fastlane/metadata/android/es-ES/short_description.txt
@@ -1 +1 @@
-Chat y VoIP descentralizados y seguros. Mantén tus datos a salvo de terceros.
+Mensajería para grupos - mensajería encriptada, chat para grupos y videollamadas
diff --git a/fastlane/metadata/android/es-ES/title.txt b/fastlane/metadata/android/es-ES/title.txt
index 971e5cf146..2e011d7ee7 100644
--- a/fastlane/metadata/android/es-ES/title.txt
+++ b/fastlane/metadata/android/es-ES/title.txt
@@ -1 +1 @@
-Element (previamente Riot.im)
+Element - Mensajero seguro
diff --git a/fastlane/metadata/android/et/changelogs/40101160.txt b/fastlane/metadata/android/et/changelogs/40101160.txt
new file mode 100644
index 0000000000..449a6edfee
--- /dev/null
+++ b/fastlane/metadata/android/et/changelogs/40101160.txt
@@ -0,0 +1,2 @@
+Põhilised muutused selles versioonis: samaaegse krüptitud sõnumi saatmise ja jututoast väljalogimisega seotud vea parandus.
+Kogu ingliskeelne muudatuste logi: https://github.com/vector-im/element-android/releases/tag/v1.1.16
diff --git a/fastlane/metadata/android/et/changelogs/40102000.txt b/fastlane/metadata/android/et/changelogs/40102000.txt
new file mode 100644
index 0000000000..57f28039c5
--- /dev/null
+++ b/fastlane/metadata/android/et/changelogs/40102000.txt
@@ -0,0 +1,2 @@
+Põhilised muutused selles versioonis: häälsõnumid on nüüd vaikimisi kasutusel.
+Kogu ingliskeelne muudatuste logi: https://github.com/vector-im/element-android/releases/tag/v1.2.0
diff --git a/fastlane/metadata/android/et/changelogs/40102010.txt b/fastlane/metadata/android/et/changelogs/40102010.txt
new file mode 100644
index 0000000000..0dc70c90af
--- /dev/null
+++ b/fastlane/metadata/android/et/changelogs/40102010.txt
@@ -0,0 +1,2 @@
+Põhilised muutused selles versioonis: palju täiendusi kõnede ja veel testjärgus olevas kogukonnakeskuste loogikas.
+Kogu ingliskeelne muudatuste logi: https://github.com/vector-im/element-android/releases/tag/v1.2.1
diff --git a/fastlane/metadata/android/et/changelogs/40103000.txt b/fastlane/metadata/android/et/changelogs/40103000.txt
new file mode 100644
index 0000000000..643ae1ce0e
--- /dev/null
+++ b/fastlane/metadata/android/et/changelogs/40103000.txt
@@ -0,0 +1,2 @@
+Põhilised muutused selles versioonis: halda oma jututubasid koondades neid uut tüüpi kogukondadesse!
+Kogu ingliskeelne muudatuste logi: https://github.com/vector-im/element-android/releases/tag/v1.3.0
diff --git a/fastlane/metadata/android/et/changelogs/40103010.txt b/fastlane/metadata/android/et/changelogs/40103010.txt
new file mode 100644
index 0000000000..e292f6db81
--- /dev/null
+++ b/fastlane/metadata/android/et/changelogs/40103010.txt
@@ -0,0 +1,2 @@
+Põhilised muutused selles versioonis: halda oma jututubasid koondades neid uut tüüpi kogukondadesse! Lisaks parandasime versioonis 1.3.0 tekkinud olulise vea.
+Kogu ingliskeelne muudatuste logi: https://github.com/vector-im/element-android/releases/tag/v1.3.1
diff --git a/fastlane/metadata/android/et/changelogs/40103020.txt b/fastlane/metadata/android/et/changelogs/40103020.txt
new file mode 100644
index 0000000000..ca3c0d3ea5
--- /dev/null
+++ b/fastlane/metadata/android/et/changelogs/40103020.txt
@@ -0,0 +1,2 @@
+Põhilised muutused selles versioonis: Android Auto tugi ning palju veaparandusi!
+Kogu ingliskeelne muudatuste logi: https://github.com/vector-im/element-android/releases/tag/v1.3.2
diff --git a/fastlane/metadata/android/et/changelogs/40103030.txt b/fastlane/metadata/android/et/changelogs/40103030.txt
new file mode 100644
index 0000000000..6293ccab85
--- /dev/null
+++ b/fastlane/metadata/android/et/changelogs/40103030.txt
@@ -0,0 +1,2 @@
+Põhilised muutused selles versioonis: Isikutuvastusserveri kasutustingimused on leitavad seadistustest ja ajutiselt eemaldasime Android Auto toe.
+Kogu ingliskeelne muudatuste logi: https://github.com/vector-im/element-android/releases/tag/v1.3.3
diff --git a/fastlane/metadata/android/et/changelogs/40103040.txt b/fastlane/metadata/android/et/changelogs/40103040.txt
new file mode 100644
index 0000000000..2ede9de81e
--- /dev/null
+++ b/fastlane/metadata/android/et/changelogs/40103040.txt
@@ -0,0 +1,2 @@
+Põhilised muutused selles versioonis: Lisasime otsevestlustele kasutaja võrguolekute toe (matrix.org puhul on välja lülitatud) ja uuesti lisasime Android Auto toe.
+Kogu ingliskeelne muudatuste logi: https://github.com/vector-im/element-android/releases/tag/v1.3.4
diff --git a/fastlane/metadata/android/et/changelogs/40103050.txt b/fastlane/metadata/android/et/changelogs/40103050.txt
new file mode 100644
index 0000000000..c68db70b6a
--- /dev/null
+++ b/fastlane/metadata/android/et/changelogs/40103050.txt
@@ -0,0 +1,2 @@
+Põhilised muutused selles versioonis: Lisasime otsevestlustele kasutaja võrguolekute toe (matrix.org puhul on välja lülitatud) ja uuesti lisasime Android Auto toe.
+Kogu ingliskeelne muudatuste logi: https://github.com/vector-im/element-android/releases/tag/v1.3.5
diff --git a/fastlane/metadata/android/et/changelogs/40103060.txt b/fastlane/metadata/android/et/changelogs/40103060.txt
new file mode 100644
index 0000000000..d1c44870fa
--- /dev/null
+++ b/fastlane/metadata/android/et/changelogs/40103060.txt
@@ -0,0 +1,2 @@
+Põhilised muutused selles versioonis: Lisasime otsevestlustele kasutaja võrguolekute toe (matrix.org puhul on välja lülitatud) ja uuesti lisasime Android Auto toe.
+Kogu ingliskeelne muudatuste logi: https://github.com/vector-im/element-android/releases/tag/v1.3.6
diff --git a/fastlane/metadata/android/et/full_description.txt b/fastlane/metadata/android/et/full_description.txt
index ee0adef9ac..a3a3bc37e2 100644
--- a/fastlane/metadata/android/et/full_description.txt
+++ b/fastlane/metadata/android/et/full_description.txt
@@ -37,3 +37,6 @@ Sõnumid, hääl- ja videokõned, failide jagamine, ekraani jagamine ja terve hu
Jätka sealt, kus pooleli jäid
Saad suhelda kõigis oma seadmetes ja ka veebis aadressil https://app.element.io ning sealjuures täielikult sünkroonitud sõnumite ajalooga.
+
+Avatud lähtekoodiga tarkvara
+Element Android on Github'is hallatud avatud lähtekoodiga tarkvaraprojekt. Palun teata vigadest ja/või osale arenduses https://github.com/vector-im/element-android lehel
diff --git a/fastlane/metadata/android/fa/changelogs/40101020.txt b/fastlane/metadata/android/fa/changelogs/40101020.txt
new file mode 100644
index 0000000000..6c0c205f5c
--- /dev/null
+++ b/fastlane/metadata/android/fa/changelogs/40101020.txt
@@ -0,0 +1,2 @@
+تغییرات اصلی در این نگارش: بهبودهای کارایی و رفع اشکالها!
+گزارش دگرگونی کامل: https://github.com/vector-im/element-android/releases/tag/v1.1.2
diff --git a/fastlane/metadata/android/fa/changelogs/40101030.txt b/fastlane/metadata/android/fa/changelogs/40101030.txt
new file mode 100644
index 0000000000..6b252e051c
--- /dev/null
+++ b/fastlane/metadata/android/fa/changelogs/40101030.txt
@@ -0,0 +1,2 @@
+تغییرات اصلی در این نگارش: بهبودهای کارایی و رفع اشکالها!
+گزارش دگرگونی کامل: https://github.com/vector-im/element-android/releases/tag/v1.1.3
diff --git a/fastlane/metadata/android/fa/changelogs/40101040.txt b/fastlane/metadata/android/fa/changelogs/40101040.txt
new file mode 100644
index 0000000000..043647a793
--- /dev/null
+++ b/fastlane/metadata/android/fa/changelogs/40101040.txt
@@ -0,0 +1,2 @@
+تغییرات اصلی در این نگارش: بهبودهای کارایی و رفع اشکالها!
+گزارش دگرگونی کامل: https://github.com/vector-im/element-android/releases/tag/v1.1.4
diff --git a/fastlane/metadata/android/fa/changelogs/40101050.txt b/fastlane/metadata/android/fa/changelogs/40101050.txt
new file mode 100644
index 0000000000..1c29a55d53
--- /dev/null
+++ b/fastlane/metadata/android/fa/changelogs/40101050.txt
@@ -0,0 +1,2 @@
+تغییرات اصلی در این نگارش: تعمیرات فوری برای 1.1.4
+گزارش دگرگونی کامل: https://github.com/vector-im/element-android/releases/tag/v1.1.5
diff --git a/fastlane/metadata/android/fa/changelogs/40101060.txt b/fastlane/metadata/android/fa/changelogs/40101060.txt
new file mode 100644
index 0000000000..b9542a3bd7
--- /dev/null
+++ b/fastlane/metadata/android/fa/changelogs/40101060.txt
@@ -0,0 +1,2 @@
+تغییرات اصلی در این نگارش: تعمیرات فوری برای 1.1.5
+گزارش دگرگونی کامل: https://github.com/vector-im/element-android/releases/tag/v1.1.6
diff --git a/fastlane/metadata/android/fa/changelogs/40101070.txt b/fastlane/metadata/android/fa/changelogs/40101070.txt
new file mode 100644
index 0000000000..8330a5060e
--- /dev/null
+++ b/fastlane/metadata/android/fa/changelogs/40101070.txt
@@ -0,0 +1,2 @@
+تغییرات اصلی در این نگارش: پشتیبانی آزمایشی برای فضاها. فشردهسازی ویدیو پیش از فرستادن.
+گزارش دگرگونی کامل: https://github.com/vector-im/element-android/releases/tag/v1.1.7
diff --git a/fastlane/metadata/android/fa/changelogs/40101080.txt b/fastlane/metadata/android/fa/changelogs/40101080.txt
new file mode 100644
index 0000000000..02cb3390a3
--- /dev/null
+++ b/fastlane/metadata/android/fa/changelogs/40101080.txt
@@ -0,0 +1,2 @@
+تغییرات اصلی در این نگارش: بهبود برای فضاها.
+گزارش دگرگونی کامل: https://github.com/vector-im/element-android/releases/tag/v1.1.8
diff --git a/fastlane/metadata/android/fa/changelogs/40101090.txt b/fastlane/metadata/android/fa/changelogs/40101090.txt
new file mode 100644
index 0000000000..d458caf46c
--- /dev/null
+++ b/fastlane/metadata/android/fa/changelogs/40101090.txt
@@ -0,0 +1,2 @@
+تغییرات اصلی در این نگارش: افزودن پشتیبانی برای شبکهٔ gitter.im.
+گزارش دگرگونی کامل: https://github.com/vector-im/element-android/releases/tag/v1.1.9
diff --git a/fastlane/metadata/android/fa/changelogs/40101100.txt b/fastlane/metadata/android/fa/changelogs/40101100.txt
new file mode 100644
index 0000000000..d51bd2427b
--- /dev/null
+++ b/fastlane/metadata/android/fa/changelogs/40101100.txt
@@ -0,0 +1,2 @@
+تغییرات اصلی در این نگارش: بهروز رسانی زمینه و سبک و ویژگیهای جدید برای فضاها.
+گزارش دگرگونی کامل: https://github.com/vector-im/element-android/releases/tag/v1.1.10
diff --git a/fastlane/metadata/android/fa/changelogs/40101110.txt b/fastlane/metadata/android/fa/changelogs/40101110.txt
new file mode 100644
index 0000000000..efd2ec9f4d
--- /dev/null
+++ b/fastlane/metadata/android/fa/changelogs/40101110.txt
@@ -0,0 +1,2 @@
+تغییرات اصلی در این نگارش: بهروز رسانی زمینه و سبک و ویژگیهای جدید برای فضاها (رفع اشکال برای 1.1.10)
+گزارش دگرگونی کامل: https://github.com/vector-im/element-android/releases/tag/v1.1.11
diff --git a/fastlane/metadata/android/fa/changelogs/40101120.txt b/fastlane/metadata/android/fa/changelogs/40101120.txt
new file mode 100644
index 0000000000..1c8fb47c19
--- /dev/null
+++ b/fastlane/metadata/android/fa/changelogs/40101120.txt
@@ -0,0 +1,2 @@
+تغییرات اصلی در این نگارش: بهروز رسانی زمینه و سبک و رفع یک فروپاشی پس از تماس ویدیویی
+گزارش دگرگونی کامل: https://github.com/vector-im/element-android/releases/tag/v1.1.12
diff --git a/fastlane/metadata/android/fa/changelogs/40101130.txt b/fastlane/metadata/android/fa/changelogs/40101130.txt
new file mode 100644
index 0000000000..55d0801920
--- /dev/null
+++ b/fastlane/metadata/android/fa/changelogs/40101130.txt
@@ -0,0 +1,2 @@
+تغییرات اصلی در این نگارش:بهروز رسانی پایداری و رفع مشکل.
+گزارش دگرگونی کامل: https://github.com/vector-im/element-android/releases/tag/v1.1.13
diff --git a/fastlane/metadata/android/fa/changelogs/40101140.txt b/fastlane/metadata/android/fa/changelogs/40101140.txt
new file mode 100644
index 0000000000..2239799429
--- /dev/null
+++ b/fastlane/metadata/android/fa/changelogs/40101140.txt
@@ -0,0 +1,2 @@
+تغییرات اصلی در این نگارش: درست کردن مشکلی دربارهٔ پیامهای رمزنگاریشده.
+گزارش دگرگونی کامل: https://github.com/vector-im/element-android/releases/tag/v1.1.14
diff --git a/fastlane/metadata/android/fa/changelogs/40101160.txt b/fastlane/metadata/android/fa/changelogs/40101160.txt
new file mode 100644
index 0000000000..82e3668777
--- /dev/null
+++ b/fastlane/metadata/android/fa/changelogs/40101160.txt
@@ -0,0 +1,2 @@
+تغییرات اصلی در این نگارش: تعمیر خطا هنگام فرستادن پیام رمزنگاشته در صورت خروج عضوی از سامانه.
+گزارش دگرگونی کامل: https://github.com/vector-im/element-android/releases/tag/v1.1.16
diff --git a/fastlane/metadata/android/fa/changelogs/40102000.txt b/fastlane/metadata/android/fa/changelogs/40102000.txt
new file mode 100644
index 0000000000..9c9a7c51d0
--- /dev/null
+++ b/fastlane/metadata/android/fa/changelogs/40102000.txt
@@ -0,0 +1,2 @@
+تغییرهای اصلی در این نگارش: پیام صوتی به صورت پیشگزیده به کار افتاده.
+گزارش دگرگونی کامل: https://github.com/vector-im/element-android/releases/tag/v1.2.0
diff --git a/fastlane/metadata/android/fa/changelogs/40102010.txt b/fastlane/metadata/android/fa/changelogs/40102010.txt
new file mode 100644
index 0000000000..a2cc27d1b5
--- /dev/null
+++ b/fastlane/metadata/android/fa/changelogs/40102010.txt
@@ -0,0 +1,2 @@
+تغییرات اصلی در این نگارش: چندین بهبود در ویپ و فضاها (همچنان در حالت آزمایشی).
+گزارش دگرگونی کامل: https://github.com/vector-im/element-android/releases/tag/v1.2.1
diff --git a/fastlane/metadata/android/fa/changelogs/40103000.txt b/fastlane/metadata/android/fa/changelogs/40103000.txt
new file mode 100644
index 0000000000..ba43459c0a
--- /dev/null
+++ b/fastlane/metadata/android/fa/changelogs/40103000.txt
@@ -0,0 +1,2 @@
+تغییرات عمده در این نگارش: سازماندهی اتاقهایتان با استفاده از فضاها
+گزارش دگرگونی کامل: https://github.com/vector-im/element-android/releases/tag/v1.3.0
diff --git a/fastlane/metadata/android/fa/changelogs/40103010.txt b/fastlane/metadata/android/fa/changelogs/40103010.txt
new file mode 100644
index 0000000000..1a800ac505
--- /dev/null
+++ b/fastlane/metadata/android/fa/changelogs/40103010.txt
@@ -0,0 +1,2 @@
+تغییرات اصلی در این نگارش: سازماندهی اتاقهایتان با فضاها! نگارش ۱٫۳٫۱ فروپاشیای را که میتوانست در نگارش ۱٫۳٫۰ رخ دهد، رفع میکند.
+گزارش دگرگونی کامل: https://github.com/vector-im/element-android/releases/tag/v1.3.1
diff --git a/fastlane/metadata/android/fa/changelogs/40103020.txt b/fastlane/metadata/android/fa/changelogs/40103020.txt
new file mode 100644
index 0000000000..be669d29a9
--- /dev/null
+++ b/fastlane/metadata/android/fa/changelogs/40103020.txt
@@ -0,0 +1,2 @@
+تغییرات اصلی در این نگارش: افزودن پشتیبانی از اندروید خودرو. کلّی رفع اشکال!
+گزارش دگرگونی کامل: https://github.com/vector-im/element-android/releases/tag/v1.3.2
diff --git a/fastlane/metadata/android/fa/changelogs/40103030.txt b/fastlane/metadata/android/fa/changelogs/40103030.txt
new file mode 100644
index 0000000000..49efae1951
--- /dev/null
+++ b/fastlane/metadata/android/fa/changelogs/40103030.txt
@@ -0,0 +1,2 @@
+تغییرات اصلی در این نگارش: نمایان کردن سیاست(های) کارساز هویت در تنظیمات. برداشتن موقّتی پشتیبانی اندروید خودرو.
+گزارش دگرگونی کامل: https://github.com/vector-im/element-android/releases/tag/v1.3.3
diff --git a/fastlane/metadata/android/fa/changelogs/40103040.txt b/fastlane/metadata/android/fa/changelogs/40103040.txt
new file mode 100644
index 0000000000..5da14baf6e
--- /dev/null
+++ b/fastlane/metadata/android/fa/changelogs/40103040.txt
@@ -0,0 +1,2 @@
+تغییرات اصلی در این نگارش: افزودن پشتیبانی حضور برای اتاق پیام خصوصی (توجه: حضور روی matrix.org از کار افتاده است). افزودن دوبارهٔ پشتیبانی اندروید خودرو.
+گزارش دگرگونی کامل: https://github.com/vector-im/element-android/releases/tag/v1.3.4
diff --git a/fastlane/metadata/android/fa/full_description.txt b/fastlane/metadata/android/fa/full_description.txt
index 3051f491ba..98055857bb 100644
--- a/fastlane/metadata/android/fa/full_description.txt
+++ b/fastlane/metadata/android/fa/full_description.txt
@@ -1,30 +1,42 @@
-المنت گونهای جدید از کارههای پیامرسانی و همکاری است که:
+المنت پیامرسانی امن و کارهای برای همکاری گروهی است که برای گپهای گروهی هنگام دورکاری، آرمانیست. این کارهٔ گپ برای فراهم کردن کنفرانس ویدیویی، همرسانی پرونده و تماسهای صوتی، از رمزنگاری سرتاسری استفاده میکند.
-۱. کنترل محرمانگیتان را در دست خودتان میگذارد
-۲. میگذارد با هرکسی در شبکهٔ ماتریکس و حتا فراتر از آن، ارتباط برقرار کنید
-۳. از شما در برابر تبلیغات، دادهکاوری و دیوارهای پرداختی، محافظت میکند
-۴. با رمزنگاری سرتاسری با ورود چندگانه، امنتان میکند
+ویژگیهای المنت شامل:
+- ابزارهای ارتباط برخط پیشرفته
+- پیامهای کاملاً مزنگاری شده برای ارتباط سازمانی امن، حتا هنگام دورکاری
+- گپ نامتمرکز برپایهٔ چارچوب نرمافزاری آزاد ماتریکس
+- همرسانی پروندهٔ امن با دادههای رمزنگاری شده هنگام مدیریت پروژهها
+- گپهای ویدیویی با صدا روی قرارداد اینترنتی و همرسانی پرونده
+- یکپارچگی آسان با دیگر کارههای پیامرسانی گروهی، خدمات وًیپ، ابزارهای مدیریت پروژه و ابزارهای همکاری برخط محبوبتان
-المنت به خاطر نامتمرکز و نرمافزار آزاد بودن، کاملاً با دیگر کارههای پیامرسانی و همکاری، فرق دارد.
+المنت کاملاً با دیگر کارههای پیامرسانی و همکاری، فرق دارد؛ چرا که روی ماتریکس، شبکهای باز برای پیامرسانی امن و ارتباط نامتمرکز عمل میکند. این امر، خودمیزبانی را برای دادن بیشینهٔ مالکیت و واپایش روی دادهها و پیامها ممکن میکند.
-المنت میگذارد خودمیزبانی کرده یا میزبانی برگزینید که امنیت، مالکیت و واپایش دادهها و گفتوگوهایتان را در اختیار داشته باشید. این کاره شما را به شبکهای باز و شدیداً امن وصل کرده تا مجبور نباشید فقط با دیگر کاربران المنت صحبت کنید.
+پیامرسانی رمزنگاری شده و امن
+المنت شما را از تبلیغات ناخواسته، دادهکاوی و زمینهای محصور در امان نگه میدارد. همچنین تمامی دادههایتان و ارتباطات صوتی و تصویری یکبهیکتان را با رمزنگاری سرتاسری و تأیید افزاره با ورود چندگانه، امن میکند.
-المنت میتواند همهٔ این کارها را بکند، چرا که روی ماتریکس، استانداردی برای گفتوگوی باز و نامتمرکز عمل میکند.
+المنت مهار محرمانگیتان را به دست خودتان میدهد؛ در عین این که میگذار با هرکسی روی شبکهٔ ماتریکس یا با یکپارچگی با کارههایی چون اسلک، دیگر ابزارهای همکاری تجاری، در ارتباط باشید.
-المنت با اجازه برای گزینش کسی که گفتوگوهایتان را میزبانی میکند، کنترل را به شما میدهد. با کارهٔ المنت، میتوانید برگزینید که به روشهای مختلفی میزبانی شوید:
+المنت میتواند خودمیزبانی شود
+المنت میتواند برای دادن واپایش بیشتر روی گفتوگوها و دادههای حسّاستان، خودمیزبانی شده یا میتوانید هر میزبان مبتنی بر ماتریکسی را که استانداردی برای ارتباط نامتمرکز نرمافزار آزاد است، برگزینید. المنت به شما محرمانگی، امنیت و انعطاف میدهد.
-۱. گرفتن حسابی رایگان روی کارساز عمومی matrix.org که به دست توسعهدهندگان ماتریکس میزبانی میشود، یا گرینش از میان هزاران کارساز عمومی میزبانیشده به دست داوطلبان
-۲. خودمیزبانی حسابتان با اجرای کراسازی روی سختافزار خودتان
-۳. ثبتنام برای حسابی روی یک کارساز سفارشی با اشتراک در بنیازهٔ میزبانی خدمات ماتریکس المنت
+مالک دادههایتان باشید
+خودتان تصمیم میگیرید که دادهها و پیامهایتان، کجا ذخیره شوند. بدون خطر دادهکاوی یا دسترسی سومشخص.
-چرا المنت را برگزینیم؟
+المنت به روشهای مختلفی مهار را در دستان شما میگذارد:
+۱. گرفتن حسابی رایگان روی کارساز عمومی matrix.org که به دست توسعهدهندگان ماتریکس میزبانی میشود، یا گزینش از میان هزاران کارساز عمومی میزبانیشده به دست داوطلبان
+۲. خودمیزبانی حسابتان با اجرای کارسازی روی زیرساخت آیتی خودتان
+۳. ثبتنام برای حسابی روی یک کارساز سفارشی با اشتراک در بنسازهٔ میزبانی خدمات ماتریکس المنت
-مالک دادههایتان باشید : خوتان تصمیم میگیرید که دادهها و پیامهایتان را کجا نگه دارید. شما صاحبشان هستید و واپایششان میکنید، نه شرکتهای بزرگی که دادههایتان را کاویده و به شرکتهای دیگر دسترسی میدهند.
+پیامرسانی و همکاری باز
+میتوانید با هرکسی در شبکهٔ ماتریکس گپ بزنید، چه از المنت استفاده کنند، چه از کارهٔ ماتریکس دیگری و حتا از کارههای پیامرسانی دیگر.
-پیامرسانی و همکاری باز : میتوانید با هرکسی در شبکهٔ ماتریکس گپ بزنید، چه از المنت استفاده کنند و چه از هر کارهٔ ماتریکس دیگری؛ و حتا اگر از سامانهٔ پیامرسانی متفاوتی مثل اسلک، آیآرسی یا جبر استفاده کنند.
+فوق امن
+رمزنگاری سرتاسری واقعی (فقط کسانی که در گفتوگو هستند،میتوانند پیامها را رمزگشایی کنند) و تأیید هویت افزاره با ورود چندگانه.
-b>فوق امن: رمزنگاری سرتاسری واقعی (فقط کسانی که در گفتوگو هستند،میتوانند پیامها را رمزگشایی کنند) و ورود چندگانه برای تأیید هویت افزارههای شرکتکنندگان در گفتوگو.
+یکپارچگی ارتباط کامل
+پیامرسانی، تماسهای صوتی و تصویری، همرسانی پرونده، همرسانی صفحه و یه عالمه یکپارچگی، بات و ابزارک. اتاق و اجتماع ساخته، در دسترس بوده و کارها را انجام دهید.
-ارتباط کامل : پیامرسانی، تماسهای صوتی و تصویری،همرسانی پرونده، همرسانی صفحه و یه عالمه یکپارچگی، بات و ابزارک. اتاق و اجتماع ساخته، در دسترس بوده و کارها را انجام دهید.
+ادامه از جایی که رها کردهاید
+هر کجا که هستید، با همگام سازی کامل تاریخچهٔ پیامها بین همهٔ افزارههایتان و وب روی https://app.element.io در دسترس باشید
-هرجا که هستید : هر کجا که هستید، با همگام سازی کامل تاریخچهٔ پیامها بین همهٔ افزارههایتان و وب روی https://app.element.io در دسترس باشید.
+نرمافزار آزاد
+المنت اندروید، یک پروژهٔ نرمافزار آزاد میزبانیشده روی گیتهاب است. لطفاً گزارش مشکلات و مشارکتها را به توسهاش به این نشانی بفرستید: https://github.com/vector-im/element-android
diff --git a/fastlane/metadata/android/fr-FR/changelogs/40101160.txt b/fastlane/metadata/android/fr-FR/changelogs/40101160.txt
new file mode 100644
index 0000000000..785be4ab69
--- /dev/null
+++ b/fastlane/metadata/android/fr-FR/changelogs/40101160.txt
@@ -0,0 +1,2 @@
+Principaux changements pour cette version : correction d’une erreur lors de l’envoi d’un message chiffré si quelqu’un du salon se déconnecte.
+Intégralité des changements : https://github.com/vector-im/element-android/releases/tag/v1.1.16
diff --git a/fastlane/metadata/android/fr-FR/changelogs/40102000.txt b/fastlane/metadata/android/fr-FR/changelogs/40102000.txt
new file mode 100644
index 0000000000..0bcf3551f6
--- /dev/null
+++ b/fastlane/metadata/android/fr-FR/changelogs/40102000.txt
@@ -0,0 +1,2 @@
+Principaux changements pour cette version : messages vocaux activés par défaut.
+Intégralité des changements : https://github.com/vector-im/element-android/releases/tag/v1.2.0
diff --git a/fastlane/metadata/android/fr-FR/changelogs/40102010.txt b/fastlane/metadata/android/fr-FR/changelogs/40102010.txt
new file mode 100644
index 0000000000..910d4bd9c0
--- /dev/null
+++ b/fastlane/metadata/android/fr-FR/changelogs/40102010.txt
@@ -0,0 +1,2 @@
+Principaux changements pour cette version : Beaucoup d’améliorations sur la VoIP et les Espaces (toujours en bêta).
+Intégralité des changements : https://github.com/vector-im/element-android/releases/tag/v1.2.1
diff --git a/fastlane/metadata/android/fr-FR/changelogs/40103000.txt b/fastlane/metadata/android/fr-FR/changelogs/40103000.txt
new file mode 100644
index 0000000000..66c2c3db86
--- /dev/null
+++ b/fastlane/metadata/android/fr-FR/changelogs/40103000.txt
@@ -0,0 +1,2 @@
+Principaux changements pour cette version : Organisez vous salons à l’aide des Espaces !
+Intégralité des changements : https://github.com/vector-im/element-android/releases/tag/v1.3.0
diff --git a/fastlane/metadata/android/fr-FR/changelogs/40103010.txt b/fastlane/metadata/android/fr-FR/changelogs/40103010.txt
new file mode 100644
index 0000000000..326319edb0
--- /dev/null
+++ b/fastlane/metadata/android/fr-FR/changelogs/40103010.txt
@@ -0,0 +1,2 @@
+Principaux changements pour cette version : Organisez vos salons à l’aide des espaces ! La v1.3.1 corrige également un plantage dans la version v1.3.0
+Liste de tous les changements : https://github.com/vector-im/element-android/releases/tag/v1.3.1
diff --git a/fastlane/metadata/android/fr-FR/changelogs/40103020.txt b/fastlane/metadata/android/fr-FR/changelogs/40103020.txt
new file mode 100644
index 0000000000..8a4868cee5
--- /dev/null
+++ b/fastlane/metadata/android/fr-FR/changelogs/40103020.txt
@@ -0,0 +1,2 @@
+Principaux changements pour cette version : Ajout du support pour Android Auto. Beaucoup de corrections de bogues !
+Liste de tous les changements : https ://github.com/vector-im/element-android/releases/tag/v1.3.2
diff --git a/fastlane/metadata/android/fr-FR/changelogs/40103030.txt b/fastlane/metadata/android/fr-FR/changelogs/40103030.txt
new file mode 100644
index 0000000000..0130080ca7
--- /dev/null
+++ b/fastlane/metadata/android/fr-FR/changelogs/40103030.txt
@@ -0,0 +1,2 @@
+Principaux changements pour cette version : Affiche le(s) politique(s) des serveurs d’identité dans les réglages. Retrait temporaire du support d’Android Auto
+Liste de tous les changements : https ://github.com/vector-im/element-android/releases/tag/v1.3.3
diff --git a/fastlane/metadata/android/fr-FR/changelogs/40103040.txt b/fastlane/metadata/android/fr-FR/changelogs/40103040.txt
new file mode 100644
index 0000000000..7017fa243f
--- /dev/null
+++ b/fastlane/metadata/android/fr-FR/changelogs/40103040.txt
@@ -0,0 +1,2 @@
+Principaux changements pour cette version : ajout du support pour les indicateurs de présence, dans les conversations privées (attention : les indicateurs de présence sont désactivés sur matrix.org). Réactivation de la prise en charge de Android Auto.
+Intégralité des changements : https://github.com/vector-im/element-android/releases/tag/v1.3.4
diff --git a/fastlane/metadata/android/fr-FR/changelogs/40103050.txt b/fastlane/metadata/android/fr-FR/changelogs/40103050.txt
new file mode 100644
index 0000000000..08143ead2f
--- /dev/null
+++ b/fastlane/metadata/android/fr-FR/changelogs/40103050.txt
@@ -0,0 +1,2 @@
+Principaux changements pour cette version : ajout du support pour les indicateurs de présence, dans les conversations privées (attention : les indicateurs de présence sont désactivés sur matrix.org). Réactivation de la prise en charge de Android Auto.
+Intégralité des changements : https://github.com/vector-im/element-android/releases/tag/v1.3.5
diff --git a/fastlane/metadata/android/fr-FR/changelogs/40103060.txt b/fastlane/metadata/android/fr-FR/changelogs/40103060.txt
new file mode 100644
index 0000000000..0187c4bf88
--- /dev/null
+++ b/fastlane/metadata/android/fr-FR/changelogs/40103060.txt
@@ -0,0 +1,2 @@
+Principaux changements pour cette version : ajout du support pour les indicateurs de présence, dans les conversations privées (attention : les indicateurs de présence sont désactivés sur matrix.org). Réactivation de la prise en charge de Android Auto.
+Intégralité des changements : https://github.com/vector-im/element-android/releases/tag/v1.3.6
diff --git a/fastlane/metadata/android/fr-FR/full_description.txt b/fastlane/metadata/android/fr-FR/full_description.txt
index 78fcdf5617..7ffdb6cb9d 100644
--- a/fastlane/metadata/android/fr-FR/full_description.txt
+++ b/fastlane/metadata/android/fr-FR/full_description.txt
@@ -37,3 +37,6 @@ Messagerie instantannée, appels audio et vidéo, partage de fichier, partage d
Reprenez où vous vous êtes arrêté
Restez en contact où que vous soyez grâce à l’historique des messages synchronisé entre tous vos appareils et sur le web sur https://app.element.io
+
+Open source
+Element Adroid est un projet libre, hébergé par GitHub. Veuillez signaler tous les problèmes et / ou contribuer à son développement sur https://github.com/vector-im/element-android
diff --git a/fastlane/metadata/android/fy/changelogs/40101060.txt b/fastlane/metadata/android/fy/changelogs/40101060.txt
index 47ac5692d5..34b367f6a1 100644
--- a/fastlane/metadata/android/fy/changelogs/40101060.txt
+++ b/fastlane/metadata/android/fy/changelogs/40101060.txt
@@ -1,2 +1,2 @@
-Haadferoaring yn disse ferzje: feroaringen foar 1.1.5
-Folsleine feroaringslist: https://github.com/vector-im/element-android/releases/tag/v1.1.6
+Haadwiziging yn dizze ferzje: feroaringen foar 1.1.5
+Folsleine wizigingslist: https://github.com/vector-im/element-android/releases/tag/v1.1.6
diff --git a/fastlane/metadata/android/fy/short_description.txt b/fastlane/metadata/android/fy/short_description.txt
index ddc559b59c..f0f44ad06c 100644
--- a/fastlane/metadata/android/fy/short_description.txt
+++ b/fastlane/metadata/android/fy/short_description.txt
@@ -1 +1 @@
-Groepsberjochtetsjinst - fersifere berjochten, groeps petearen en fideo skilje
+Groepsberjochtetsjinst - fersifere berjochten, groepspetearen en fideobelje
diff --git a/fastlane/metadata/android/fy/title.txt b/fastlane/metadata/android/fy/title.txt
index c4b5b596fc..0c77d7d613 100644
--- a/fastlane/metadata/android/fy/title.txt
+++ b/fastlane/metadata/android/fy/title.txt
@@ -1 +1 @@
-Element - Feilige Berjochtetsjinst
+Element - Feilige berjochtetsjinst
diff --git a/fastlane/metadata/android/hu-HU/changelogs/40101150.txt b/fastlane/metadata/android/hu-HU/changelogs/40101150.txt
new file mode 100644
index 0000000000..48765e903b
--- /dev/null
+++ b/fastlane/metadata/android/hu-HU/changelogs/40101150.txt
@@ -0,0 +1,2 @@
+Fő változás ebben a verzióban: hang üzenetek implementálva a labor beállítások alatt
+Teljes változásnapló: https://github.com/vector-im/element-android/releases/tag/v1.1.5
diff --git a/fastlane/metadata/android/hu-HU/changelogs/40101160.txt b/fastlane/metadata/android/hu-HU/changelogs/40101160.txt
new file mode 100644
index 0000000000..54f435eb96
--- /dev/null
+++ b/fastlane/metadata/android/hu-HU/changelogs/40101160.txt
@@ -0,0 +1,2 @@
+Fő változás ebben a verzióban: Titkosított üzenetküldés hibájának javítása ha valaki kilépett a szobából.
+Teljes változásnapló: https://github.com/vector-im/element-android/releases/tag/v1.1.16
diff --git a/fastlane/metadata/android/hu-HU/changelogs/40102000.txt b/fastlane/metadata/android/hu-HU/changelogs/40102000.txt
new file mode 100644
index 0000000000..87824693f7
--- /dev/null
+++ b/fastlane/metadata/android/hu-HU/changelogs/40102000.txt
@@ -0,0 +1,2 @@
+Fő változás ebben a verzióban: Hangüzenetek alapértelmezetten engedélyezettek.
+Teljes változásnapló: https://github.com/vector-im/element-android/releases/tag/v1.2.0
diff --git a/fastlane/metadata/android/hu-HU/changelogs/40102010.txt b/fastlane/metadata/android/hu-HU/changelogs/40102010.txt
new file mode 100644
index 0000000000..1ccd51aa8a
--- /dev/null
+++ b/fastlane/metadata/android/hu-HU/changelogs/40102010.txt
@@ -0,0 +1,2 @@
+Fő változás ebben a verzióban: Sok fejlesztés a VoIP és Terek kapcsán (még béta)
+Teljes változásnapló: https://github.com/vector-im/element-android/releases/tag/v1.2.1
diff --git a/fastlane/metadata/android/hu-HU/changelogs/40103000.txt b/fastlane/metadata/android/hu-HU/changelogs/40103000.txt
new file mode 100644
index 0000000000..40673b30b1
--- /dev/null
+++ b/fastlane/metadata/android/hu-HU/changelogs/40103000.txt
@@ -0,0 +1,2 @@
+Fő változás ebben a verzióban: Szobák terekbe szervezése
+Teljes változásnapló: https://github.com/vector-im/element-android/releases/tag/v1.3.0
diff --git a/fastlane/metadata/android/hu-HU/changelogs/40103010.txt b/fastlane/metadata/android/hu-HU/changelogs/40103010.txt
new file mode 100644
index 0000000000..2cc0dab42d
--- /dev/null
+++ b/fastlane/metadata/android/hu-HU/changelogs/40103010.txt
@@ -0,0 +1,2 @@
+Fő változás ebben a verzióban: Rendezd a szobáidat terekbe! v1.3.1 a v1.3.0 összeomlásait javítja.
+Teljes változásnapló: https://github.com/vector-im/element-android/releases/tag/v1.3.1
diff --git a/fastlane/metadata/android/hu-HU/changelogs/40103020.txt b/fastlane/metadata/android/hu-HU/changelogs/40103020.txt
new file mode 100644
index 0000000000..ff8af250e2
--- /dev/null
+++ b/fastlane/metadata/android/hu-HU/changelogs/40103020.txt
@@ -0,0 +1,2 @@
+Fő változás ebben a verzióban: Android Auto támogatás és sok hibajavítás!
+Teljes változásnapló: https://github.com/vector-im/element-android/releases/tag/v1.3.2
diff --git a/fastlane/metadata/android/hu-HU/changelogs/40103030.txt b/fastlane/metadata/android/hu-HU/changelogs/40103030.txt
new file mode 100644
index 0000000000..8795818607
--- /dev/null
+++ b/fastlane/metadata/android/hu-HU/changelogs/40103030.txt
@@ -0,0 +1,2 @@
+Fő változás ebben a verzióban: Azonosítási szerver feltételek megjelenítése a beállításoknál. Ideiglenesen az Android Auto támogatás eltávolítása.
+Teljes változásnapló: https://github.com/vector-im/element-android/releases/tag/v1.3.3
diff --git a/fastlane/metadata/android/hu-HU/changelogs/40103040.txt b/fastlane/metadata/android/hu-HU/changelogs/40103040.txt
new file mode 100644
index 0000000000..de2e859028
--- /dev/null
+++ b/fastlane/metadata/android/hu-HU/changelogs/40103040.txt
@@ -0,0 +1,2 @@
+Fő változás ebben a verzióban: Állapot állítási lehetőség közvetlen beszélgetéseknél (megj.: a matrix.org-on az állapot jelzés ki van kapcsolva). Újra elérhető az Android Auto.
+Teljes változásnapló: https://github.com/vector-im/element-android/releases/tag/v1.3.4
diff --git a/fastlane/metadata/android/hu-HU/changelogs/40103050.txt b/fastlane/metadata/android/hu-HU/changelogs/40103050.txt
new file mode 100644
index 0000000000..e46bf39f83
--- /dev/null
+++ b/fastlane/metadata/android/hu-HU/changelogs/40103050.txt
@@ -0,0 +1,2 @@
+Fő változás ebben a verzióban: Állapot állítási lehetőség közvetlen beszélgetéseknél (megj.: a matrix.org-on az állapot jelzés ki van kapcsolva). Újra elérhető az Android Auto.
+Teljes változásnapló: https://github.com/vector-im/element-android/releases/tag/v1.3.5
diff --git a/fastlane/metadata/android/hu-HU/changelogs/40103060.txt b/fastlane/metadata/android/hu-HU/changelogs/40103060.txt
new file mode 100644
index 0000000000..1fc6ce5b8a
--- /dev/null
+++ b/fastlane/metadata/android/hu-HU/changelogs/40103060.txt
@@ -0,0 +1,2 @@
+Fő változás ebben a verzióban: Állapot állítási lehetőség közvetlen beszélgetéseknél (megj.: a matrix.org-on az állapot jelzés ki van kapcsolva). Újra elérhető az Android Auto.
+Teljes változásnapló: https://github.com/vector-im/element-android/releases/tag/v1.3.6
diff --git a/fastlane/metadata/android/hu-HU/full_description.txt b/fastlane/metadata/android/hu-HU/full_description.txt
index 032346ccb8..899b4cd978 100644
--- a/fastlane/metadata/android/hu-HU/full_description.txt
+++ b/fastlane/metadata/android/hu-HU/full_description.txt
@@ -38,3 +38,6 @@ Igazi végpontok között titkosítás (csak a beszélgetésben résztvevők tud
Vedd fel a fonalat
Maradj kapcsolatban bárhol minden eszközödön a szinkronizált üzenetekkel és a weben a https://app.element.io oldallal
+
+Nyílt forráskód
+Element Android egy nyílt forráskódú projekt a GitHubon. Küldj hibajegyet és/vagy vegyél részt a fejlesztésében itt: https://github.com/vector-im/element-android
diff --git a/fastlane/metadata/android/id/changelogs/40101160.txt b/fastlane/metadata/android/id/changelogs/40101160.txt
new file mode 100644
index 0000000000..19209bacf2
--- /dev/null
+++ b/fastlane/metadata/android/id/changelogs/40101160.txt
@@ -0,0 +1,2 @@
+Perubahan utama dalam versi ini: Memperbaiki kesalahan saat mengirim pesan terenkripsi jika seseorang yang ada di ruangan keluar.
+Changelog lanjutan: https://github.com/vector-im/element-android/releases/tag/v1.1.16
diff --git a/fastlane/metadata/android/id/changelogs/40102000.txt b/fastlane/metadata/android/id/changelogs/40102000.txt
new file mode 100644
index 0000000000..f7d93e2e4f
--- /dev/null
+++ b/fastlane/metadata/android/id/changelogs/40102000.txt
@@ -0,0 +1,2 @@
+Perubahan utama dalam versi ini: Pesan Suara diaktifkan secara default
+Changelog lanjutan: https://github.com/vector-im/element-android/releases/tag/v1.2.0
diff --git a/fastlane/metadata/android/id/changelogs/40102010.txt b/fastlane/metadata/android/id/changelogs/40102010.txt
new file mode 100644
index 0000000000..e77f0327b0
--- /dev/null
+++ b/fastlane/metadata/android/id/changelogs/40102010.txt
@@ -0,0 +1,2 @@
+Perubahan utama di versi ini: Banyak perbaikan di VoIP dan Space (masih beta).
+Changelog lanjutan: https://github.com/vector-im/element-android/releases/tag/v1.2.1
diff --git a/fastlane/metadata/android/id/changelogs/40103000.txt b/fastlane/metadata/android/id/changelogs/40103000.txt
new file mode 100644
index 0000000000..bf7b5d8d5d
--- /dev/null
+++ b/fastlane/metadata/android/id/changelogs/40103000.txt
@@ -0,0 +1,2 @@
+Perubahan utama di versi ini: Organisir ruangan Anda menggunakan sebuah Space!
+Changelog lanjutan: https://github.com/vector-im/element-android/releases/tag/v1.3.0
diff --git a/fastlane/metadata/android/id/changelogs/40103010.txt b/fastlane/metadata/android/id/changelogs/40103010.txt
new file mode 100644
index 0000000000..7823017895
--- /dev/null
+++ b/fastlane/metadata/android/id/changelogs/40103010.txt
@@ -0,0 +1,2 @@
+Perubahan utama dalam versi ini: Organisir ruangan Anda dengan menggunakan sebuah Space! v1.3.1 memperbaiki crash yang dapat terjadi di v1.3.0.
+Changelog lengkap: https://github.com/vector-im/element-android/releases/tag/v1.3.1
diff --git a/fastlane/metadata/android/id/changelogs/40103020.txt b/fastlane/metadata/android/id/changelogs/40103020.txt
new file mode 100644
index 0000000000..4f46881d68
--- /dev/null
+++ b/fastlane/metadata/android/id/changelogs/40103020.txt
@@ -0,0 +1,2 @@
+Perubahan utama dalam versi ini: Penambahan dukungan untuk Android Auto. Banyak perbaikan bug!
+Changelog lanjutan: https://github.com/vector-im/element-android/releases/tag/v1.3.2
diff --git a/fastlane/metadata/android/id/changelogs/40103030.txt b/fastlane/metadata/android/id/changelogs/40103030.txt
new file mode 100644
index 0000000000..630593a107
--- /dev/null
+++ b/fastlane/metadata/android/id/changelogs/40103030.txt
@@ -0,0 +1,2 @@
+Perubahan utama dalam versi ini: Membuat kebijakan server identitas terlihat di pengaturan. Menghilangkan dukungan Android Auto untuk sementara.
+Changelog lanjutan: https://github.com/vector-im/element-android/releases/tag/v1.3.3
diff --git a/fastlane/metadata/android/id/changelogs/40103040.txt b/fastlane/metadata/android/id/changelogs/40103040.txt
new file mode 100644
index 0000000000..0641f72ffd
--- /dev/null
+++ b/fastlane/metadata/android/id/changelogs/40103040.txt
@@ -0,0 +1,2 @@
+Perubahan utama di versi ini: Tambahkan dukungan presensi, untuk ruangan Pesan Langsung (diingat bahwa presensi dinonaktifkan di matrix.org). Tambahkan lagi dukungan Android Auto.
+Changelog lanjutan: https://github.com/vector-im/element-android/releases/tag/v1.3.4
diff --git a/fastlane/metadata/android/id/changelogs/40103050.txt b/fastlane/metadata/android/id/changelogs/40103050.txt
new file mode 100644
index 0000000000..ec7c9423bf
--- /dev/null
+++ b/fastlane/metadata/android/id/changelogs/40103050.txt
@@ -0,0 +1,2 @@
+Perubahan utama dalam versi ini: Tambahkan dukungan presensi, untuk ruangan Pesan Langsung (diingat bahwa presensi dinonaktifkan di matrix.org). Tambahkan lagi dukungan Android Auto.
+Changelog lanjutan: https://github.com/vector-im/element-android/releases/tag/v1.3.5
diff --git a/fastlane/metadata/android/id/changelogs/40103060.txt b/fastlane/metadata/android/id/changelogs/40103060.txt
new file mode 100644
index 0000000000..4265699d2f
--- /dev/null
+++ b/fastlane/metadata/android/id/changelogs/40103060.txt
@@ -0,0 +1,2 @@
+Perubahan utama dalam versi ini: Tambahkan dukungan presensi, untuk ruangan Pesan Langsung (catatan: presensi dinonaktifkan di matrix.org). Tambahkan lagi dukungan Android Auto.
+Changelog lanjutan: https://github.com/vector-im/element-android/releases/tag/v1.3.6
diff --git a/fastlane/metadata/android/id/full_description.txt b/fastlane/metadata/android/id/full_description.txt
index 0a18b8d64a..d28ae8b004 100644
--- a/fastlane/metadata/android/id/full_description.txt
+++ b/fastlane/metadata/android/id/full_description.txt
@@ -1,39 +1,42 @@
-Element adalah perpesanan yang aman dan aplikasi kolaborasi tim produktivitas yang ideal untuk obrolan grup saat bekerja jarak jauh. Aplikasi obrolan ini menggunakan enkripsi ujung-ke-ujung untuk memberikan konferensi video, berbagi file, dan panggilan suara.
+Element adalah perpesanan yang aman dan aplikasi kolaborasi tim produktivitas yang ideal untuk obrolan grup saat bekerja jarak jauh. Aplikasi perpesanan ini menggunakan enkripsi ujung-ke-ujung untuk memberikan konferensi video, pembagian file, dan panggilan suara yang aman.
-Fitur Element termasuk:
+Fitur Element termasuk
- Alat komunikasi online yang canggih
-- Pesan terenkripsi sepenuhnya untuk memungkinkan komunikasi perusahaan yang lebih aman, bahkan untuk pekerja jarak jauh
-- Obrolan terdesentralisasi berdasarkan framework sumber-terbuka Matrix
-- Berbagi file dengan aman dengan data terenkripsi saat mengelola proyek
-- Obrolan video dengan VoIP dan berbagi layar
+- Pesan-pesan yang dienkripsi sepenuhnya untuk memungkinkan komunikasi perusahaan yang lebih aman, bahkan untuk pekerja jarak jauh
+- Obrolan terdesentralisasi berdasarkan kerangka Matrix yang sumber terbuka
+- Pembagian file aman dengan data terenkripsi saat mengelola proyek
+- Obrolan video dengan VoIP dan pembagian layar
- Integrasi yang mudah dengan alat kolaborasi online favorit Anda, alat manajemen proyek, layanan VoIP dan aplikasi perpesanan tim lainnya
-Element benar-benar berbeda dari aplikasi perpesanan dan kolaborasi lainnya. Ini beroperasi pada Matrix, jaringan terbuka untuk pengiriman pesan yang aman dan komunikasi terdesentralisasi. Ini memungkinkan hosting sendiri untuk memberi pengguna kepemilikan maksimum dan kontrol data dan pesan mereka.
+Element benar-benar berbeda dari aplikasi perpesanan dan aplikasi kolaborasi lainnya. Element beroperasi pada Matrix, jaringan terbuka untuk pengiriman pesan yang aman dan komunikasi terdesentralisasi.
-Pesan privasi dan terenkripsi
-Element melindungi Anda dari iklan yang tidak diinginkan, data penambangan dan taman berdinding. Ini juga mengamankan semua data Anda, komunikasi video dan suara satu-ke-satu melalui enkripsi ujung-ke-ujung dan verifikasi perangkat yang di-cross-signed.
+Perpesanan dengan privasi dan enkripsi
+Element melindungi Anda dari iklan yang tidak diinginkan, penambangan data dan taman berdinding. Element juga mengamankan semua data Anda, komunikasi video dan suara satu-ke-satu dengan enkripsi ujung-ke-ujung dan verifikasi perangkat menggunakan penandatanganan silang.
-Element memberi Anda kendali atas privasi Anda sambil memungkinkan Anda untuk berkomunikasi dengan aman dengan siapa pun di jaringan Matrix, atau alat kolaborasi bisnis lainnya dengan mengintegrasikan dengan aplikasi seperti Slack.
+Element memberikan Anda kendali atas privasi Anda sambil memungkinkan Anda untuk berkomunikasi dengan siapa saja secara aman di jaringan Matrix, atau alat kolaborasi bisnis lainnya dengan mengintegrasikan aplikasi-aplikasi seperti Slack.
Element dapat dihost sendiri
-Untuk memungkinkan lebih banyak kendali atas data dan percakapan sensitif Anda, Element bisa dihost sendiri atau Anda dapat memilih host berbasis Matrix - standar untuk komunikasi terdesentralisasi sumber-terbuka. Element memberi Anda privasi, kepatuhan keamanan, dan fleksibilitas integrasi.
+Untuk memungkinkan lebih banyak kendali atas data dan pesan-pesan sensitif Anda, Element dapat dihost sendiri atau Anda dapat memilih host berbasis Matrix, standar untuk komunikasi terdesentralisasi sumber terbuka. Element memberi Anda privasi, kepatuhan keamanan, dan fleksibilitas integrasi.
Miliki data Anda
-Anda memutuskan di mana menyimpan data dan pesan Anda. Tanpa risiko penambangan data atau akses dari pihak ketiga.
+Anda memutuskan di mana untuk menyimpan data dan pesan-pesan Anda, tanpa risiko penambangan data atau akses dari pihak ketiga.
Element menempatkan Anda dalam kendali dengan cara yang berbeda:
1. Dapatkan akun gratis pada server publik matrix.org yang dihost oleh pengembang Matrix, atau memilih dari ribuan server publik yang dihost oleh sukarelawan
2. Host sendiri akun Anda dengan menjalankan server pada infrastruktur IT Anda sendiri
-3. Daftar untuk akun di server khusus dengan hanya berlangganan platform hosting Element Matrix Services
+3. Daftar untuk akun di server khusus dengan berlangganan platform hosting Layanan Matrix Element
Pesan terbuka dan kolaborasi
-Anda dapat mengobrol dengan siapa saja di jaringan Matrix, apakah mereka menggunakan Element, aplikasi Matrix lain atau bahkan jika mereka menggunakan aplikasi perpesanan yang berbeda.
+Anda dapat mengobrol dengan siapa saja di jaringan Matrix, jika mereka menggunakan Element, aplikasi Matrix lain atau bahkan menggunakan aplikasi perpesanan yang berbeda.
Sangat aman
-Enkripsi ujung-ke-ujung beneran (hanya mereka yang dalam percakapan dapat mendekripsi pesan), dan verifikasi perangkat yang di-cross-signed.
+Enkripsi ujung-ke-ujung yang nyata (hanya mereka yang dalam obrolan dapat mendekripsi pesan), dan verifikasi perangkat menggunakan penandatanganan silang.
Komunikasi dan integrasi lengkap
-Perpesanan, panggilan suara dan video, berbagi file, berbagi layar dan banyak integrasi, bot dan widget. Buat ruangan, komunitas, tetap terhubung dan selesaikan hal-hal.
+Perpesanan, panggilan suara dan video, pembagian file, pembagian layar dan banyak integrasi bot dan widget. Buat ruangan dan komunitas, tetap terhubung dan selesaikan hal-hal penting.
Ambil di mana Anda tinggalkan
-Tetap terhubung di mana pun Anda berada dengan riwayat pesan yang sepenuhnya disinkronkan di semua perangkat Anda dan di web di https://app.element.io
+Tetap terhubung di mana Anda berada, dengan riwayat pesan yang disinkronkan di semua perangkat Anda dan web di https://app.element.io
+
+Sumber terbuka
+Element Android adalah proyek sumber terbuka, dihost oleh GitHub. Silakan laporkan masalah yang Anda temukan, atau membuat kontribusi ke pengembangannya di https://github.com/vector-im/element-android
diff --git a/fastlane/metadata/android/id/short_description.txt b/fastlane/metadata/android/id/short_description.txt
index e6c3a2f7a9..1cd770dd73 100644
--- a/fastlane/metadata/android/id/short_description.txt
+++ b/fastlane/metadata/android/id/short_description.txt
@@ -1 +1 @@
-Perpesanan grup - pesan terenkripsi, panggilan grup dan video
+Perpesanan grup - perpesanan, panggilan suara dan video grup terenkripsi
diff --git a/fastlane/metadata/android/it-IT/changelogs/40101160.txt b/fastlane/metadata/android/it-IT/changelogs/40101160.txt
new file mode 100644
index 0000000000..1c217f50cc
--- /dev/null
+++ b/fastlane/metadata/android/it-IT/changelogs/40101160.txt
@@ -0,0 +1,2 @@
+Modifiche principali in questa versione: corretto errore nell'invio di messaggi cifrati se qualcuno nella stanza si disconnette.
+Cronologia completa: https://github.com/vector-im/element-android/releases/tag/v1.1.16
diff --git a/fastlane/metadata/android/it-IT/changelogs/40102000.txt b/fastlane/metadata/android/it-IT/changelogs/40102000.txt
new file mode 100644
index 0000000000..e10007a7b7
--- /dev/null
+++ b/fastlane/metadata/android/it-IT/changelogs/40102000.txt
@@ -0,0 +1,2 @@
+Modifiche principali in questa versione: i messaggi vocali sono attivi in modo predefinito.
+Cronologia completa: https://github.com/vector-im/element-android/releases/tag/v1.2.0
diff --git a/fastlane/metadata/android/it-IT/changelogs/40102010.txt b/fastlane/metadata/android/it-IT/changelogs/40102010.txt
new file mode 100644
index 0000000000..33c2d998a7
--- /dev/null
+++ b/fastlane/metadata/android/it-IT/changelogs/40102010.txt
@@ -0,0 +1,2 @@
+Modifiche principali in questa versione: molti miglioramenti nel VoIP e negli Spazi (ancora in beta).
+Cronologia completa: https://github.com/vector-im/element-android/releases/tag/v1.2.1
diff --git a/fastlane/metadata/android/it-IT/changelogs/40103000.txt b/fastlane/metadata/android/it-IT/changelogs/40103000.txt
new file mode 100644
index 0000000000..6ad9001bfd
--- /dev/null
+++ b/fastlane/metadata/android/it-IT/changelogs/40103000.txt
@@ -0,0 +1,2 @@
+Modifiche principali in questa versione: organizza le tue stanze usando gli Spazi!
+Cronologia completa: https://github.com/vector-im/element-android/releases/tag/v1.3.0
diff --git a/fastlane/metadata/android/it-IT/changelogs/40103010.txt b/fastlane/metadata/android/it-IT/changelogs/40103010.txt
new file mode 100644
index 0000000000..125cf58137
--- /dev/null
+++ b/fastlane/metadata/android/it-IT/changelogs/40103010.txt
@@ -0,0 +1,2 @@
+Modifiche principali in questa versione: organizza le tue stanze usando gli Spazi! v1.3.1 corregge un errore della v1.3.0.
+Full changelog: https://github.com/vector-im/element-android/releases/tag/v1.3.1
diff --git a/fastlane/metadata/android/it-IT/changelogs/40103020.txt b/fastlane/metadata/android/it-IT/changelogs/40103020.txt
new file mode 100644
index 0000000000..c088edc3b5
--- /dev/null
+++ b/fastlane/metadata/android/it-IT/changelogs/40103020.txt
@@ -0,0 +1,2 @@
+Modifiche principali in questa versione: aggiunto supporto per Android Auto. Corretti molti errori!
+Cronologia completa: https://github.com/vector-im/element-android/releases/tag/v1.3.2
diff --git a/fastlane/metadata/android/it-IT/changelogs/40103030.txt b/fastlane/metadata/android/it-IT/changelogs/40103030.txt
new file mode 100644
index 0000000000..e5c12d2b5e
--- /dev/null
+++ b/fastlane/metadata/android/it-IT/changelogs/40103030.txt
@@ -0,0 +1,2 @@
+Modifiche principali in questa versione: rese visibili le informative dei server d'identità nelle impostazioni. Rimosso temporaneamente il supporto per Android Auto.
+Cronologia completa: https://github.com/vector-im/element-android/releases/tag/v1.3.3
diff --git a/fastlane/metadata/android/it-IT/changelogs/40103040.txt b/fastlane/metadata/android/it-IT/changelogs/40103040.txt
new file mode 100644
index 0000000000..e28ce08e03
--- /dev/null
+++ b/fastlane/metadata/android/it-IT/changelogs/40103040.txt
@@ -0,0 +1,2 @@
+Modifiche principali in questa versione: aggiunto supporto alla presenza per messaggi diretti (nota: la presenza è disattivata su matrix.org). Aggiunto di nuovo il supporto ad Android Auto.
+Cronologia completa: https://github.com/vector-im/element-android/releases/tag/v1.3.4
diff --git a/fastlane/metadata/android/it-IT/changelogs/40103050.txt b/fastlane/metadata/android/it-IT/changelogs/40103050.txt
new file mode 100644
index 0000000000..2762949682
--- /dev/null
+++ b/fastlane/metadata/android/it-IT/changelogs/40103050.txt
@@ -0,0 +1,2 @@
+Modifiche principali in questa versione: aggiunto supporto alla presenza per messaggi diretti (nota: la presenza è disattivata su matrix.org). Aggiunto di nuovo il supporto ad Android Auto.
+Cronologia completa: https://github.com/vector-im/element-android/releases/tag/v1.3.5
diff --git a/fastlane/metadata/android/it-IT/changelogs/40103060.txt b/fastlane/metadata/android/it-IT/changelogs/40103060.txt
new file mode 100644
index 0000000000..f241fa9e57
--- /dev/null
+++ b/fastlane/metadata/android/it-IT/changelogs/40103060.txt
@@ -0,0 +1,2 @@
+Modifiche principali in questa versione: aggiunto supporto alla presenza per i messaggi diretti (nota: la presenza è disattivata su matrix.org). Aggiunto di nuovo il supporto a Android Auto.
+Cronologia completa: https://github.com/vector-im/element-android/releases/tag/v1.3.6
diff --git a/fastlane/metadata/android/it-IT/full_description.txt b/fastlane/metadata/android/it-IT/full_description.txt
index dd7716ffbf..f0e4c04477 100644
--- a/fastlane/metadata/android/it-IT/full_description.txt
+++ b/fastlane/metadata/android/it-IT/full_description.txt
@@ -37,3 +37,6 @@ Messaggi, chiamate audio e video, condivisione file e schermo, un vasto numero d
Riprendi da dove ti eri fermato
Resta in contatto ovunque tu sia con la cronologia dei messaggi sincronizzata tra tutti i tuoi dispositivi e in rete su https://app.element.io
+
+Open source
+Element Android è un progetto open source, ospitato su GitHub. Segnala errori e/o contribuisci al suo sviluppo su https://github.com/vector-im/element-android
diff --git a/fastlane/metadata/android/ja-JP/changelogs/40101160.txt b/fastlane/metadata/android/ja-JP/changelogs/40101160.txt
new file mode 100644
index 0000000000..a498487f46
--- /dev/null
+++ b/fastlane/metadata/android/ja-JP/changelogs/40101160.txt
@@ -0,0 +1,2 @@
+このバージョンの主な変更点:ルームにて誰かがログアウトした際に発生するエラーを修正しました。
+すべての変更履歴はこちら: https://github.com/vector-im/element-android/releases/tag/v1.1.16
diff --git a/fastlane/metadata/android/ja-JP/full_description.txt b/fastlane/metadata/android/ja-JP/full_description.txt
index 855eb309c9..4e7b01cce3 100644
--- a/fastlane/metadata/android/ja-JP/full_description.txt
+++ b/fastlane/metadata/android/ja-JP/full_description.txt
@@ -1,30 +1,39 @@
-Elementはまったく新しいタイプのメッセンジャーアプリです。
+Elementはセキュアなメッセンジャーであると同時に、リモートワークでのグループチャットにも最適です。エンドツーエンドの暗号化を使用して、強力なビデオ会議、ファイル共有、音声通話を提供します。
-1. あなた自身がプライバシーをコントロールすることを可能にします。
-2. Matrixネットワークにいる誰とでも通信できることはもちろん、Slackなどのアプリとの連携によって他のネットワークとも通信ができます。
-3. 広告、データ収集、バックドア、ユーザーの囲い込みから逃れることができます。
-4. エンドツーエンド暗号化とクロス署名によってあなたを保護します。
+Elementの特徴
+- 高度なオンラインコミュニケーションツール
+- 完全に暗号化されたメッセージ
+- Matrixオープンソースフレームワークをベースにした分散型のチャット
+- プロジェクトを管理しながら、暗号化されたデータで安全にファイル共有
+- Voice over IPによるビデオチャットと画面共有
+- お気に入りのオンラインコラボレーションツール、プロジェクト管理ツール、VoIPサービス、その他のチームメッセージングアプリと統合可能
-Elementは非中央集権型でオープンソースであるため、他のメッセンジャーアプリとは完全に異なっています。
+Elementは他のメッセージングアプリやコラボレーションアプリとは異なります。安全なメッセージングと分散型(非中央集権)コミュニケーションのためのオープンネットワークであるMatrixで動作します。また、ユーザーが自分のデータやメッセージを最大限にコントロールできるように、セルフホスティングも可能です。
-Elementはあなた自身でサーバーをホストすることも、サーバーを選ぶこともできます。これによってあなたのデータと会話に関するプライバシーや所有権はあなた自身で管理できるようになります。さらに、あなたは他のElementユーザーと話せるだけでなくオープンネットワークへのアクセスも可能です。とてもセキュアです。
+プライバシーと暗号化されたやりとり
+Elementは、望ましくない広告、データマイニング、ウォールドガーデンからユーザーを保護します。また、エンド・ツー・エンドの暗号化と相互署名されたデバイスの検証により、すべてのデータ、1対1のビデオおよび音声通信を保護します。
-Elementは、オープンな分散型通信の標準規格であるMatrixで動作するため、これらすべてを実現することができています。
+Elementは、Slackなどのアプリと統合することで、Matrixネットワーク上の誰とでも安全にコミュニケーションをとることができると同時に、プライバシーをコントロールすることができます。
-Elementではあなたの会話をどのサーバーでホストするか決めることができます。アプリでは、さまざまな方法で選択できます。
+Elementはセルフホスティングが可能
+機密データや会話の管理を強化するために、Elementはセルフホスティングが可能で、オープンソースの分散型コミュニケーションの標準であるマトリックスベースのホストを選択することもできます。Elementは、プライバシー、セキュリティコンプライアンス、および統合の柔軟性を提供します。
-1. matrix.orgの公開サーバーで無料のアカウントを取得します。
-2. あなた自身のハードウェアでサーバーを動かし、アカウントを管理します。
-3. Element Matrix Servicesのホスティングプラットフォームに登録することで、カスタムサーバー上のアカウントを取得できます。
+データを所有する
+データやメッセージをどこに保管するかは、お客様が決めることができます。データマイニングやサードパーティからのアクセスされません。
-なぜElementを選ぶべきなのか?
+Elementではどのサーバーを使うか決めることができます。さまざまな方法で選択できます。
+1. 開発者がホストする matrix.org のパブリックサーバーで無料アカウントを取得するか、ボランティアがホストしているパブリックサーバーから選択する。
+2. 自分でサーバを実行することにより、アカウントをセルフホストする。
+3. Element Matrix Servicesのホスティングプラットフォームに加入しカスタムサーバー上でアカウントを作る。
-データの所有権 : 自分でデータやメッセージを保管する場所を決めることができます。あなたが所有権を持ってコントロールすることで、第三者にあなたのデータを渡したり、ビッグデータを収集する巨大テック企業に依存する必要がなくなります。
+オープンなメッセージングとコラボレーション
+Matrixネットワーク上の誰とでも、相手がElementを使っているか、他のMatrixアプリを使っていてもコミュニケーションすることができます。
-開かれたネットワークと共同作業 : Matrixネットワーク内の他の誰とでも、あるいはElementや他のMatrixアプリを使っているかどうかに関わらず、またSlack、IRC、XMPPのような他のメッセージングシステムを使っているかどうかに関わらず、チャットすることができます。
+すごく安全
+本物のエンド・ツー・エンドの暗号化(会話に参加している人だけがメッセージを復号化できる)と、相互署名されたデバイスの検証を行います。
-はるかに安全 : 本物のエンドツーエンド暗号化(会話に参加している者のみがメッセージを読める)と会話参加者の真正性を確認するためクロス署名によって。
+包括的なコミュニケーションと統合
+メッセージング、音声およびビデオ通話、ファイル共有、画面共有、その他多くの統合、ボット、ウィジェットを提供します。部屋やコミュニティを作り、連絡を取り合い、物事を成し遂げることができます。
-完全なるコミュニケーションの訪れ : テキスト、音声通話、ビデオ通話、ファイル共有、画面共有、連携機能、ボット、ウィジェットなどのコミュニケーションに必要な機能の全てが実装されています。ルームやコミュニティを立ち上げて連絡を取り合い、物事をスムーズに成し遂げることができます。
-
-いつでもどこでも! : すべてのデバイスとウェブ(https://app.element.io)でメッセージの履歴が完全に同期されるため、どこにいても連絡を取ることができます。
+中断からの再開は
+すべてのデバイスとウェブで完全に同期されたメッセージにより、どこにいても連絡を取り合うことができます。https://app.element.io
diff --git a/fastlane/metadata/android/ja-JP/short_description.txt b/fastlane/metadata/android/ja-JP/short_description.txt
index c3991b7a93..0d37b108ac 100644
--- a/fastlane/metadata/android/ja-JP/short_description.txt
+++ b/fastlane/metadata/android/ja-JP/short_description.txt
@@ -1 +1 @@
-安全な分散型チャットとVoIP。あなたの情報が第三者から守られます。
+メッセンジャー - 暗号化されたメッセージング、グループチャット、ビデオコールなど
diff --git a/fastlane/metadata/android/ja-JP/title.txt b/fastlane/metadata/android/ja-JP/title.txt
index 376f4a95de..7c2b777407 100644
--- a/fastlane/metadata/android/ja-JP/title.txt
+++ b/fastlane/metadata/android/ja-JP/title.txt
@@ -1 +1 @@
-Element(エレメントメッセンジャー)
+Element - セキュアメッセンジャー
diff --git a/fastlane/metadata/android/no-NO/changelogs/40101040.txt b/fastlane/metadata/android/no-NO/changelogs/40101040.txt
new file mode 100644
index 0000000000..5d1ecba7fc
--- /dev/null
+++ b/fastlane/metadata/android/no-NO/changelogs/40101040.txt
@@ -0,0 +1,2 @@
+Hovedendringer i denne versjonen: forbedring av ytelsen og feilrettinger!
+Full endringslogg: https://github.com/vector-im/element-android/releases/tag/v1.1.4
diff --git a/fastlane/metadata/android/no-NO/changelogs/40101050.txt b/fastlane/metadata/android/no-NO/changelogs/40101050.txt
new file mode 100644
index 0000000000..3ddcb9d04b
--- /dev/null
+++ b/fastlane/metadata/android/no-NO/changelogs/40101050.txt
@@ -0,0 +1,2 @@
+Hovedendringer i denne versjonen: hurtigreparasjoner for 1.1.4
+Full endringslogg: https://github.com/vector-im/element-android/releases/tag/v1.1.5
diff --git a/fastlane/metadata/android/no-NO/changelogs/40101060.txt b/fastlane/metadata/android/no-NO/changelogs/40101060.txt
new file mode 100644
index 0000000000..c556359851
--- /dev/null
+++ b/fastlane/metadata/android/no-NO/changelogs/40101060.txt
@@ -0,0 +1,2 @@
+Hovedendringer i denne versjonen: hurtigreparasjoner for 1.1.5
+Full endringslogg: https://github.com/vector-im/element-android/releases/tag/v1.1.6
diff --git a/fastlane/metadata/android/no-NO/changelogs/40101070.txt b/fastlane/metadata/android/no-NO/changelogs/40101070.txt
new file mode 100644
index 0000000000..bc786eb454
--- /dev/null
+++ b/fastlane/metadata/android/no-NO/changelogs/40101070.txt
@@ -0,0 +1,2 @@
+Hovedendringer i denne versjonen: beta støtte for Mellomrom. Komprimer video før du sender.
+Full endringslogg: https://github.com/vector-im/element-android/releases/tag/v1.1.7
diff --git a/fastlane/metadata/android/no-NO/changelogs/40101080.txt b/fastlane/metadata/android/no-NO/changelogs/40101080.txt
new file mode 100644
index 0000000000..02d6aa868b
--- /dev/null
+++ b/fastlane/metadata/android/no-NO/changelogs/40101080.txt
@@ -0,0 +1,2 @@
+Hovedendringer i denne versjonen: forbedring for Mellomrom.
+Full endringslogg: https://github.com/vector-im/element-android/releases/tag/v1.1.8
diff --git a/fastlane/metadata/android/no-NO/changelogs/40101090.txt b/fastlane/metadata/android/no-NO/changelogs/40101090.txt
new file mode 100644
index 0000000000..cdcb4909c7
--- /dev/null
+++ b/fastlane/metadata/android/no-NO/changelogs/40101090.txt
@@ -0,0 +1,2 @@
+Hovedendringer i denne versjonen: legg til støtte for gitter.im -nettverket.
+Full endringslogg: https://github.com/vector-im/element-android/releases/tag/v1.1.9
diff --git a/fastlane/metadata/android/no-NO/changelogs/40101100.txt b/fastlane/metadata/android/no-NO/changelogs/40101100.txt
new file mode 100644
index 0000000000..8a397f63bb
--- /dev/null
+++ b/fastlane/metadata/android/no-NO/changelogs/40101100.txt
@@ -0,0 +1,2 @@
+Hovedendringer i denne versjonen: oppdatering av tema og stil og nye funksjoner for mellomrom.
+Full endringslogg: https://github.com/vector-im/element-android/releases/tag/v1.1.10
diff --git a/fastlane/metadata/android/no-NO/changelogs/40101110.txt b/fastlane/metadata/android/no-NO/changelogs/40101110.txt
new file mode 100644
index 0000000000..2db46e97a8
--- /dev/null
+++ b/fastlane/metadata/android/no-NO/changelogs/40101110.txt
@@ -0,0 +1,2 @@
+Hovedendringer i denne versjonen: oppdatering av tema og stil og nye funksjoner for mellomrom (feilrettelse for 1.1.10)
+Full endringslogg: https://github.com/vector-im/element-android/releases/tag/v1.1.11
diff --git a/fastlane/metadata/android/no-NO/changelogs/40101120.txt b/fastlane/metadata/android/no-NO/changelogs/40101120.txt
new file mode 100644
index 0000000000..6b7e160a80
--- /dev/null
+++ b/fastlane/metadata/android/no-NO/changelogs/40101120.txt
@@ -0,0 +1,2 @@
+Hovedendringer i denne versjonen: tema og stiloppdatering og fikse et krasj etter videosamtale
+Full endringslogg: https://github.com/vector-im/element-android/releases/tag/v1.1.12
diff --git a/fastlane/metadata/android/no-NO/changelogs/40101130.txt b/fastlane/metadata/android/no-NO/changelogs/40101130.txt
new file mode 100644
index 0000000000..db67b87bf9
--- /dev/null
+++ b/fastlane/metadata/android/no-NO/changelogs/40101130.txt
@@ -0,0 +1,2 @@
+Hovedendringer i denne versjonen: hovedsakelig stabilitet og oppdateringer av feilrettinger.
+Full endringslogg: https://github.com/vector-im/element-android/releases/tag/v1.1.13
diff --git a/fastlane/metadata/android/no-NO/changelogs/40101140.txt b/fastlane/metadata/android/no-NO/changelogs/40101140.txt
new file mode 100644
index 0000000000..7921bd03e0
--- /dev/null
+++ b/fastlane/metadata/android/no-NO/changelogs/40101140.txt
@@ -0,0 +1,2 @@
+Hovedendringer i denne versjonen: Løs et problem om krypterte meldinger.
+Full endringslogg: https://github.com/vector-im/element-android/releases/tag/v1.1.14
diff --git a/fastlane/metadata/android/no-NO/changelogs/40101150.txt b/fastlane/metadata/android/no-NO/changelogs/40101150.txt
new file mode 100644
index 0000000000..2f4fcb8266
--- /dev/null
+++ b/fastlane/metadata/android/no-NO/changelogs/40101150.txt
@@ -0,0 +1,2 @@
+Hovedendringer i denne versjonen: implementering av talemeldinger under laboratorieinnstillinger.
+Full endringslogg: https://github.com/vector-im/element-android/releases/tag/v1.1.15
diff --git a/fastlane/metadata/android/no-NO/changelogs/40101160.txt b/fastlane/metadata/android/no-NO/changelogs/40101160.txt
new file mode 100644
index 0000000000..d7f7ca2387
--- /dev/null
+++ b/fastlane/metadata/android/no-NO/changelogs/40101160.txt
@@ -0,0 +1,2 @@
+Hovedendringer i denne versjonen: Løs feil ved sending av kryptert melding hvis noen i rommet logger av.
+Full endringslogg: https://github.com/vector-im/element-android/releases/tag/v1.1.16
diff --git a/fastlane/metadata/android/no-NO/full_description.txt b/fastlane/metadata/android/no-NO/full_description.txt
index 92a3c4c5c3..08d2383532 100644
--- a/fastlane/metadata/android/no-NO/full_description.txt
+++ b/fastlane/metadata/android/no-NO/full_description.txt
@@ -1,30 +1,39 @@
-Element er en ny type messenger og samarbeidsapp som:
+Element er både en sikker budbringer og en produktivitets team -samarbeidsprogram som er ideell for gruppechatter mens du jobber på fjernkontroll. Denne chat-appen bruker ende-til-ende-kryptering for å tilby kraftige videokonferanser, fildeling og taleanrop.
-1. Gir deg kontrollen for å bevare personvernet ditt
-2. Lar deg kommunisere med hvem som helst i Matrix-nettverket, og til og med ved å integrere med apper som Slack
-3. Beskytter deg mot reklame, datamining og inngjerdede hager
-4. Sikrer deg gjennom end-to-end-kryptering, med kryssignering for å bekrefte andre
+ Elementets funksjoner inkluderer:
+- Avanserte elektroniske kommunikasjonsverktøy
+- Fullt krypterte meldinger for å tillate tryggere bedriftskommunikasjon, selv for eksterne arbeidere
+- Desentralisert chat basert på Matrix open source -rammeverket
+- Fildeling sikkert med krypterte data mens du administrerer prosjekter
+- Videochatter med Voice over IP og skjermdeling
+- Enkel integrering med dine favoritt online samarbeidsverktøy, prosjektstyringsverktøy, VoIP -tjenester og andre teammeldingsapper
-Element er helt forskjellig fra andre meldings- og samarbeidsapper fordi det er desentralisert og åpen kildekode.
+Element er helt annerledes enn andre meldings- og samarbeidsapper. Den opererer på Matrix, et åpent nettverk for sikre meldinger og desentralisert kommunikasjon. Det gjør det mulig for egen hosting å gi brukerne maksimal eierskap og kontroll over sine data og meldinger.
-Element lar deg selv være vert - eller velge en vert - slik at du har personvern, eierskap og kontroll over dataene og samtalene dine. Det gir deg tilgang til et åpent nettverk; slik at du ikke bare holder på å snakke med bare andre Element-brukere. Og det er veldig sikkert.
+ Personvern og krypterte meldinger
+Element beskytter deg mot uønskede annonser, datautvinning og inngjerdede hager. Den sikrer også alle dataene dine, en-til-en video- og talekommunikasjon gjennom ende-til-ende-kryptering og kryssignert enhetsverifisering.
-Element er i stand til å gjøre alt dette fordi det opererer på Matrix - standarden for åpen, desentralisert kommunikasjon.
+Element gir deg kontroll over personvernet ditt, samtidig som du kan kommunisere trygt med alle på Matrix -nettverket eller andre forretningssamarbeidsverktøy ved å integrere med apper som Slack.
-Element setter deg i kontroll ved å la deg velge hvem som er vert for samtalene dine. Fra Element-appen kan du velge å være vert på forskjellige måter:
+ Elementet kan hostes selv
+For å tillate mer kontroll over dine sensitive data og samtaler, kan Element være egenvert, eller du kan velge hvilken som helst Matrix-basert vert-standarden for åpen kildekode, desentralisert kommunikasjon. Element gir deg personvern, overholdelse av sikkerhet og fleksibilitet for integrering.
-1. Få en gratis konto på matrix.org-serveren som er vert for Matrix-utviklerne, eller velg blant tusenvis av offentlige servere som er vert for frivillige
-2. Vær vert for kontoen din ved å kjøre en server på din egen maskinvare
-3. Registrer deg for en konto på en tilpasset server ved å bare abonnere på Hosting Matrix Services-vertsplattformen
+ Ei dataene dine
+Du bestemmer hvor du vil beholde dataene og meldingene dine. Uten risiko for datautvinning eller tilgang fra tredjeparter.
- Hvorfor velge Element?
+Element gir deg kontroll på forskjellige måter:
+1. Få en gratis konto på den matrix.org offentlige serveren som Matrix -utviklerne er vert for, eller velg blant tusenvis av offentlige servere som er arrangert av frivillige
+2. Vær vert for kontoen din ved å kjøre en server på din egen IT-infrastruktur
+3. Registrer deg for en konto på en tilpasset server ved ganske enkelt å abonnere på Element Matrix Services hosting -plattform
- EGNE DATA DINE : Du bestemmer hvor du vil oppbevare dataene og meldingene dine. Du eier den og kontrollerer den, ikke noe MEGACORP som utvinner dataene dine eller gir tilgang til tredjeparter.
+ Åpen melding og samarbeid
+Du kan chatte med alle på Matrix -nettverket, enten de bruker Element, en annen Matrix -app eller til og med om de bruker en annen meldingsapp.
- ÅPEN MELDING OG SAMARBEID : Du kan chatte med alle andre i Matrix-nettverket, enten de bruker Element eller en annen Matrix-app, og selv om de bruker et annet meldingssystem som Slack, IRC eller XMPP.
+ Super sikker
+Ekte ende-til-ende-kryptering (bare de i samtalen kan dekryptere meldinger) og kryssignert enhetsbekreftelse.
- SUPER-SECURE : Ekte end-to-end-kryptering (bare de i samtalen kan dekryptere meldinger), og kryssignering for å verifisere enhetene til samtaledeltakerne.
+ Fullstendig kommunikasjon og integrering
+Meldinger, tale- og videosamtaler, fildeling, skjermdeling og en hel haug med integrasjoner, bots og widgets. Bygg rom, lokalsamfunn, hold kontakten og få ting gjort.
- KOMPLETT KOMMUNIKASJON : Meldinger, tale- og videosamtaler, fildeling, skjermdeling og en hel haug med integrasjoner, bots og widgets. Bygg rom, lokalsamfunn, hold kontakten og få ting gjort.
-
- ALT DER DU ER : Hold kontakten uansett hvor du er med fullt synkronisert meldingslogg på alle enhetene dine og på nettet på https://app.element.io.
+ Hent der du slapp
+Hold kontakten uansett hvor du er med fullt synkronisert meldingshistorikk på alle enhetene dine og på nettet på https://app.element.io
diff --git a/fastlane/metadata/android/no-NO/short_description.txt b/fastlane/metadata/android/no-NO/short_description.txt
index b7cad4c849..04c4a8c2e5 100644
--- a/fastlane/metadata/android/no-NO/short_description.txt
+++ b/fastlane/metadata/android/no-NO/short_description.txt
@@ -1 +1 @@
-Sikker desentralisert chat & VoIP. Beskytt dataene dine fra tredjeparter.
+Gruppe meldinger - kryptert meldinger, gruppechat og videosamtaler
diff --git a/fastlane/metadata/android/pt-BR/changelogs/40101160.txt b/fastlane/metadata/android/pt-BR/changelogs/40101160.txt
new file mode 100644
index 0000000000..9ed83f641b
--- /dev/null
+++ b/fastlane/metadata/android/pt-BR/changelogs/40101160.txt
@@ -0,0 +1,2 @@
+Principais mudanças nesta versão: Consertar erro quando enviando mensagem encriptada se alguém na sala faz logout.
+Changelog completo: https://github.com/vector-im/element-android/releases/tag/v1.1.16
diff --git a/fastlane/metadata/android/pt-BR/changelogs/40102000.txt b/fastlane/metadata/android/pt-BR/changelogs/40102000.txt
new file mode 100644
index 0000000000..c6d01391da
--- /dev/null
+++ b/fastlane/metadata/android/pt-BR/changelogs/40102000.txt
@@ -0,0 +1,2 @@
+Principais mudanças nesta versão: Mensagem de Voz está habilitada por default.
+Changelog completo: https://github.com/vector-im/element-android/releases/tag/v1.2.0
diff --git a/fastlane/metadata/android/pt-BR/changelogs/40102010.txt b/fastlane/metadata/android/pt-BR/changelogs/40102010.txt
new file mode 100644
index 0000000000..0894dd2022
--- /dev/null
+++ b/fastlane/metadata/android/pt-BR/changelogs/40102010.txt
@@ -0,0 +1,2 @@
+Principais mudanças nesta versão: Muitas melhorias em VoIP e Espaços (ainda em beta).
+Changelog completo: https://github.com/vector-im/element-android/releases/tag/v1.2.1
diff --git a/fastlane/metadata/android/pt-BR/changelogs/40103000.txt b/fastlane/metadata/android/pt-BR/changelogs/40103000.txt
new file mode 100644
index 0000000000..c046c1cbc9
--- /dev/null
+++ b/fastlane/metadata/android/pt-BR/changelogs/40103000.txt
@@ -0,0 +1,2 @@
+Principais mudanças nesta versão: Organize suas salas usando Espaços!
+Changelog completo: https://github.com/vector-im/element-android/releases/tag/v1.3.0
diff --git a/fastlane/metadata/android/pt-BR/changelogs/40103010.txt b/fastlane/metadata/android/pt-BR/changelogs/40103010.txt
new file mode 100644
index 0000000000..25d497eaa9
--- /dev/null
+++ b/fastlane/metadata/android/pt-BR/changelogs/40103010.txt
@@ -0,0 +1,2 @@
+Principais mudanças nesta versão: Organize suas salas usando Espaços! v1.3.1 está consertando um crash que pode ocorrer em v1.3.0.
+Changelog completo: https://github.com/vector-im/element-android/releases/tag/v1.3.1
diff --git a/fastlane/metadata/android/pt-BR/changelogs/40103020.txt b/fastlane/metadata/android/pt-BR/changelogs/40103020.txt
new file mode 100644
index 0000000000..e34e321494
--- /dev/null
+++ b/fastlane/metadata/android/pt-BR/changelogs/40103020.txt
@@ -0,0 +1,2 @@
+Principais mudanças nesta versão: Adicionar suporte para Android Auto. Muitos consertos de bugs!
+Changelog completo: https://github.com/vector-im/element-android/releases/tag/v1.3.2
diff --git a/fastlane/metadata/android/pt-BR/changelogs/40103030.txt b/fastlane/metadata/android/pt-BR/changelogs/40103030.txt
new file mode 100644
index 0000000000..12ababb2ce
--- /dev/null
+++ b/fastlane/metadata/android/pt-BR/changelogs/40103030.txt
@@ -0,0 +1,2 @@
+Principais mudanças nesta versão: Fazer política(s) de servidor de identidade visível(is) nas configurações. Remover temporariamente suporte a Android Auto.
+Changelog completo: https://github.com/vector-im/element-android/releases/tag/v1.3.3
diff --git a/fastlane/metadata/android/pt-BR/changelogs/40103040.txt b/fastlane/metadata/android/pt-BR/changelogs/40103040.txt
new file mode 100644
index 0000000000..b713e0418f
--- /dev/null
+++ b/fastlane/metadata/android/pt-BR/changelogs/40103040.txt
@@ -0,0 +1,2 @@
+Principais mudanças nesta versão: Adicionar suporte a Presença, para sala de Mensagem Direta (nota: presença está desabilitada em matrix.org). Adicionar de novo suporte a Android Auto.
+Changelog completo: https://github.com/vector-im/element-android/releases/tag/v1.3.4
diff --git a/fastlane/metadata/android/pt-BR/changelogs/40103050.txt b/fastlane/metadata/android/pt-BR/changelogs/40103050.txt
new file mode 100644
index 0000000000..e565d269ed
--- /dev/null
+++ b/fastlane/metadata/android/pt-BR/changelogs/40103050.txt
@@ -0,0 +1,2 @@
+Principais mudanças nesta versão: Adicionar suporte a Presença, para sala de Mensagem Direta (nota: presença está desabilitada em matrix.org). Adicionar de novo suporte a Android Auto.
+Changelog completo: https://github.com/vector-im/element-android/releases/tag/v1.3.5
diff --git a/fastlane/metadata/android/pt-BR/changelogs/40103060.txt b/fastlane/metadata/android/pt-BR/changelogs/40103060.txt
new file mode 100644
index 0000000000..b246759d26
--- /dev/null
+++ b/fastlane/metadata/android/pt-BR/changelogs/40103060.txt
@@ -0,0 +1,2 @@
+Principais mudanças nesta versão: Adicionar suporte a Presença, para sala de Mensagem Direta (nota: presença está desabilitada em matrix.org). Adicionar de novo suporte a Android Auto.
+Changelog completo: https://github.com/vector-im/element-android/releases/tag/v1.3.6
diff --git a/fastlane/metadata/android/pt-BR/full_description.txt b/fastlane/metadata/android/pt-BR/full_description.txt
index 7bb3d0981d..fe560cdda0 100644
--- a/fastlane/metadata/android/pt-BR/full_description.txt
+++ b/fastlane/metadata/android/pt-BR/full_description.txt
@@ -1,4 +1,4 @@
-Element é tanto um mensageiro seguro como um app de colaboração de time de produtividade que é ideal para chats de grupo enquanto se trabalha remotamente. Este app de chat usa encriptação ponta-a-ponta para prover conferência de vídeo, compartilhamento de arquivo e chamadas de voz poderasos.
+Element é tanto um mensageiro seguro como um app de colaboração de time de produtividade que é ideal para chats de grupo enquanto se trabalha remotamente. Este app de chat usa encriptação ponta-a-ponta para prover conferência de vídeo, compartilhamento de arquivo e chamadas de voz poderosos.
As funções de Element incluem:
- Ferramentas de comunicação online avançadas
@@ -22,9 +22,9 @@ Para permitir mais controle de seus dados e conversas sensíveis, Element pode s
Você decide onde manter seus dados e mensagens. Sem o risco de data mining ou acesso de terceiros.
Element põe você em controle de diferentes maneiras:
-1. Pegar uma conta grátis no servidor público matrix.org hospedado pelos desenvolvedores Matrix, ou escolha de milhares de servidores públicos hospedados por pessoas se voluntariando
-2. Auto-hospedar sua conta ao rodar um servidor em sua própria infraestrutura de TI
-3. Fazer signup para uma conta num servidor personalizado ao simplesmente assinar a plataforma de hospedagem Element Matrix Services
+1. Pegue uma conta grátis no servidor público matrix.org hospedado pelos desenvolvedores Matrix, ou escolha de milhares de servidores públicos hospedados por pessoas se voluntariando
+2. Auto-hospede sua conta ao rodar um servidor em sua própria infraestrutura de TI
+3. Faça signup para uma conta num servidor personalizado ao simplesmente assinar a plataforma de hospedagem Element Matrix Services
Mensageria e colaboração abertos
Você pode fazer chat com qualquer pessoa na rede Matrix, caso ela esteja usando Element, um outro app de Matrix ou mesmo se ela estiver usando um app de mensageria diferente.
@@ -37,3 +37,6 @@ Messageria, chamadas de voz e vídeo, compartilhamento de arquivo, compartilhame
Continue de onde você parou
Fique em contato onde quer que você esteja com histórico de mensagem completamente sincronizado por todos os seus dispositivos e na web em https://app.element.io
+
+Open source
+Element Android é um projeto open source, hospedado por GitHub. Por favor reporte bugs e/ou contribua para seu desenvolvimento em https://github.com/vector-im/element-android
diff --git a/fastlane/metadata/android/ru-RU/changelogs/40101150.txt b/fastlane/metadata/android/ru-RU/changelogs/40101150.txt
new file mode 100644
index 0000000000..cbf64e470b
--- /dev/null
+++ b/fastlane/metadata/android/ru-RU/changelogs/40101150.txt
@@ -0,0 +1,2 @@
+Основные изменения в этой версии: реализация голосовых сообщений в настройках лабораторий.
+Полный список изменений: https://github.com/vector-im/element-android/releases/tag/v1.1.15
diff --git a/fastlane/metadata/android/ru-RU/changelogs/40101160.txt b/fastlane/metadata/android/ru-RU/changelogs/40101160.txt
new file mode 100644
index 0000000000..5f0e555d94
--- /dev/null
+++ b/fastlane/metadata/android/ru-RU/changelogs/40101160.txt
@@ -0,0 +1,2 @@
+Основные изменения в этой версии: Исправление ошибки при отправке зашифрованного сообщения, если кто-то в комнате выходит.
+Полный список изменений: https://github.com/vector-im/element-android/releases/tag/v1.1.16
diff --git a/fastlane/metadata/android/ru-RU/changelogs/40102000.txt b/fastlane/metadata/android/ru-RU/changelogs/40102000.txt
new file mode 100644
index 0000000000..af0a444afa
--- /dev/null
+++ b/fastlane/metadata/android/ru-RU/changelogs/40102000.txt
@@ -0,0 +1,2 @@
+Основные изменения в этой версии: Голосовое сообщение включено по умолчанию.
+Полный список изменений: https://github.com/vector-im/element-android/releases/tag/v1.2.0
diff --git a/fastlane/metadata/android/ru-RU/changelogs/40102010.txt b/fastlane/metadata/android/ru-RU/changelogs/40102010.txt
new file mode 100644
index 0000000000..167af260d5
--- /dev/null
+++ b/fastlane/metadata/android/ru-RU/changelogs/40102010.txt
@@ -0,0 +1,2 @@
+Основные изменения в этой версии: Множество улучшений в VoIP и пространствах (все еще в бета-версии).
+Полный список изменений: https://github.com/vector-im/element-android/releases/tag/v1.2.1
diff --git a/fastlane/metadata/android/ru-RU/changelogs/40103000.txt b/fastlane/metadata/android/ru-RU/changelogs/40103000.txt
new file mode 100644
index 0000000000..7e87ca8524
--- /dev/null
+++ b/fastlane/metadata/android/ru-RU/changelogs/40103000.txt
@@ -0,0 +1,2 @@
+Основные изменения в этой версии: Организуйте свои комнаты с помощью Пространств!
+Весь список изменений: https://github.com/vector-im/element-android/releases/tag/v1.3.0
diff --git a/fastlane/metadata/android/ru-RU/changelogs/40103010.txt b/fastlane/metadata/android/ru-RU/changelogs/40103010.txt
new file mode 100644
index 0000000000..e3a14e2d93
--- /dev/null
+++ b/fastlane/metadata/android/ru-RU/changelogs/40103010.txt
@@ -0,0 +1,2 @@
+Основные изменения в этой версии: Организуйте свои комнаты с помощью Пространств! В версии 1.3.1 исправлен сбой, который мог произойти в версии 1.3.0.
+Весь список изменений: https://github.com/vector-im/element-android/releases/tag/v1.3.1
diff --git a/fastlane/metadata/android/ru-RU/changelogs/40103020.txt b/fastlane/metadata/android/ru-RU/changelogs/40103020.txt
new file mode 100644
index 0000000000..66059d5b92
--- /dev/null
+++ b/fastlane/metadata/android/ru-RU/changelogs/40103020.txt
@@ -0,0 +1,2 @@
+Основные изменения в этой версии: Добавлена поддержка Android Auto. Исправлено множество ошибок!
+Весь список изменений: https://github.com/vector-im/element-android/releases/tag/v1.3.2
diff --git a/fastlane/metadata/android/ru-RU/changelogs/40103030.txt b/fastlane/metadata/android/ru-RU/changelogs/40103030.txt
new file mode 100644
index 0000000000..94b43e5f30
--- /dev/null
+++ b/fastlane/metadata/android/ru-RU/changelogs/40103030.txt
@@ -0,0 +1,2 @@
+Основные изменения в этой версии: Правила сервера идентификации теперь видимы в настройках. Временно убрана поддержка Android Auto.
+Полный список изменений: https://github.com/vector-im/element-android/releases/tag/v1.3.3
diff --git a/fastlane/metadata/android/ru-RU/changelogs/40103040.txt b/fastlane/metadata/android/ru-RU/changelogs/40103040.txt
new file mode 100644
index 0000000000..e4e5edc5b1
--- /dev/null
+++ b/fastlane/metadata/android/ru-RU/changelogs/40103040.txt
@@ -0,0 +1,2 @@
+Основные изменения в этой версии: Добавлена поддержка присутствия, для комнат личных сообщений (примечание: присутствие отключено на matrix.org). Снова добавлена поддержка Android Auto.
+Полный список изменений: https://github.com/vector-im/element-android/releases/tag/v1.3.4
diff --git a/fastlane/metadata/android/ru-RU/full_description.txt b/fastlane/metadata/android/ru-RU/full_description.txt
index 3d21b20a90..3d8949e466 100644
--- a/fastlane/metadata/android/ru-RU/full_description.txt
+++ b/fastlane/metadata/android/ru-RU/full_description.txt
@@ -37,3 +37,7 @@ Element дает вам возможность контролировать си
Восстанавливайте связь с того места, где остановились .
Оставайтесь на связи, где бы вы ни находились, с полностью синхронизированной историей сообщений на всех ваших устройствах и в Интернете по адресу https://app.element.io
+
+
+Открытый исходный код
+Element Android - это проект с открытым исходным кодом, размещенный на GitHub. Пожалуйста, сообщайте об ошибках и/или вносите вклад в его развитие по адресу https://github.com/vector-im/element-android.
diff --git a/fastlane/metadata/android/sq/changelogs/40100100.txt b/fastlane/metadata/android/sq/changelogs/40100100.txt
new file mode 100644
index 0000000000..aba7bebd5a
--- /dev/null
+++ b/fastlane/metadata/android/sq/changelogs/40100100.txt
@@ -0,0 +1,2 @@
+Ky version i ri përmban kryesisht ndreqje të metash dhe përmirësime. Dërgimi i një mesazhi tani është shumë i shpejtë.
+Regjistër i plotë ndryshimesh: https://github.com/vector-im/element-android/releases/tag/v1.0.10
diff --git a/fastlane/metadata/android/sq/changelogs/40100110.txt b/fastlane/metadata/android/sq/changelogs/40100110.txt
new file mode 100644
index 0000000000..d1b8e9f9d3
--- /dev/null
+++ b/fastlane/metadata/android/sq/changelogs/40100110.txt
@@ -0,0 +1,2 @@
+Ky version i ri përmban kryesisht përmirësime të ndërfaqes dhe punimit të përdoruesit. Tani mund të ftoni shokë, dhe të krijoni MD shumë shpejt, përmes skanimit të kodesh QR.
+Regjistër i plotë ndryshimesh: https://github.com/vector-im/element-android/releases/tag/v1.0.11
diff --git a/fastlane/metadata/android/sq/changelogs/40100120.txt b/fastlane/metadata/android/sq/changelogs/40100120.txt
new file mode 100644
index 0000000000..d7d9998e0b
--- /dev/null
+++ b/fastlane/metadata/android/sq/changelogs/40100120.txt
@@ -0,0 +1,2 @@
+Ndryshimet kryesore në këtë version: Paraparje URL-sh, tastierë e re për emoji, aftësi të reja për rregullime dhome, dhe dëborë për Krishtlindje!
+Regjistër i plotë ndryshimesh: https://github.com/vector-im/element-android/releases/tag/v1.0.12
diff --git a/fastlane/metadata/android/sq/changelogs/40100130.txt b/fastlane/metadata/android/sq/changelogs/40100130.txt
new file mode 100644
index 0000000000..5d50ff531d
--- /dev/null
+++ b/fastlane/metadata/android/sq/changelogs/40100130.txt
@@ -0,0 +1,2 @@
+Ndryshimet kryesore në këtë version: Paraparje URL-sh, tastierë e re për emoji, aftësi të reja për rregullime dhome, dhe dëborë për Krishtlindje!
+Regjistër i plotë ndryshimesh: https://github.com/vector-im/element-android/releases/tag/v1.0.13
diff --git a/fastlane/metadata/android/sq/changelogs/40100140.txt b/fastlane/metadata/android/sq/changelogs/40100140.txt
new file mode 100644
index 0000000000..bdab3841b0
--- /dev/null
+++ b/fastlane/metadata/android/sq/changelogs/40100140.txt
@@ -0,0 +1,2 @@
+Ndryshimet kryesore në këtë version: Përpunim lejesh dhome, temë e çelët/e errët e automatizuar, dhe një dorë ndreqjesh të metash.
+Regjistër i plotë ndryshimesh: https://github.com/vector-im/element-android/releases/tag/v1.0.14
diff --git a/fastlane/metadata/android/sq/changelogs/40100150.txt b/fastlane/metadata/android/sq/changelogs/40100150.txt
new file mode 100644
index 0000000000..045f2369b6
--- /dev/null
+++ b/fastlane/metadata/android/sq/changelogs/40100150.txt
@@ -0,0 +1,2 @@
+Ndryshimet kryesore në këtë version: Mbulim Hyrjesh nga rrjete shoqërorë.
+Regjistër i plotë ndryshimesh: https://github.com/vector-im/element-android/releases/tag/v1.0.15
diff --git a/fastlane/metadata/android/sq/changelogs/40100160.txt b/fastlane/metadata/android/sq/changelogs/40100160.txt
new file mode 100644
index 0000000000..ece7bbd2a6
--- /dev/null
+++ b/fastlane/metadata/android/sq/changelogs/40100160.txt
@@ -0,0 +1,2 @@
+Ndryshimet kryesore në këtë version: Mbulim Hyrjesh nga rrjete shoqërorë.
+Regjistër i plotë ndryshimesh: https://github.com/vector-im/element-android/releases/tag/v1.0.15 dhe https://github.com/vector-im/element-android/releases/tag/v1.0.16
diff --git a/fastlane/metadata/android/sq/changelogs/40100170.txt b/fastlane/metadata/android/sq/changelogs/40100170.txt
new file mode 100644
index 0000000000..76cf7a9ffa
--- /dev/null
+++ b/fastlane/metadata/android/sq/changelogs/40100170.txt
@@ -0,0 +1,2 @@
+Ndryshimet kryesore në këtë version: Ndreqje të metash!
+Regjistër i plotë ndryshimesh: https://github.com/vector-im/element-android/releases/tag/v1.0.17
diff --git a/fastlane/metadata/android/sq/changelogs/40101000.txt b/fastlane/metadata/android/sq/changelogs/40101000.txt
new file mode 100644
index 0000000000..b4424f55bc
--- /dev/null
+++ b/fastlane/metadata/android/sq/changelogs/40101000.txt
@@ -0,0 +1,2 @@
+Ndryshimet kryesore në këtë version: Përmirësime për VoIP (thirrje audio dhe video në DM) dhe ndreqje të metash!
+Regjistër i plotë ndryshimesh: https://github.com/vector-im/element-android/releases/tag/v1.1.0
diff --git a/fastlane/metadata/android/sq/changelogs/40101010.txt b/fastlane/metadata/android/sq/changelogs/40101010.txt
new file mode 100644
index 0000000000..20b35d3439
--- /dev/null
+++ b/fastlane/metadata/android/sq/changelogs/40101010.txt
@@ -0,0 +1,2 @@
+Ndryshimet kryesore në këtë version: përmirësime funksionimi dhe ndreqje të metash!
+Regjistër i plotë ndryshimesh: https://github.com/vector-im/element-android/releases/tag/v1.1.1
diff --git a/fastlane/metadata/android/sq/changelogs/40101020.txt b/fastlane/metadata/android/sq/changelogs/40101020.txt
new file mode 100644
index 0000000000..6f53ec219e
--- /dev/null
+++ b/fastlane/metadata/android/sq/changelogs/40101020.txt
@@ -0,0 +1,2 @@
+Ndryshimet kryesore në këtë version: përmirësime funksionimi dhe ndreqje të metash!
+Regjistër i plotë ndryshimesh: https://github.com/vector-im/element-android/releases/tag/v1.1.2
diff --git a/fastlane/metadata/android/sq/changelogs/40101030.txt b/fastlane/metadata/android/sq/changelogs/40101030.txt
new file mode 100644
index 0000000000..9dbc4f142a
--- /dev/null
+++ b/fastlane/metadata/android/sq/changelogs/40101030.txt
@@ -0,0 +1,2 @@
+Ndryshimet kryesore në këtë version: përmirësime funksionimi dhe ndreqje të metash!
+Regjistër i plotë ndryshimesh: https://github.com/vector-im/element-android/releases/tag/v1.1.3
diff --git a/fastlane/metadata/android/sq/changelogs/40101040.txt b/fastlane/metadata/android/sq/changelogs/40101040.txt
new file mode 100644
index 0000000000..949fa629b9
--- /dev/null
+++ b/fastlane/metadata/android/sq/changelogs/40101040.txt
@@ -0,0 +1,2 @@
+Ndryshimet kryesore në këtë version: përmirësime funksionimi dhe ndreqje të metash!
+Regjistër i plotë ndryshimesh: https://github.com/vector-im/element-android/releases/tag/v1.1.4
diff --git a/fastlane/metadata/android/sq/changelogs/40101050.txt b/fastlane/metadata/android/sq/changelogs/40101050.txt
new file mode 100644
index 0000000000..28e2852356
--- /dev/null
+++ b/fastlane/metadata/android/sq/changelogs/40101050.txt
@@ -0,0 +1,2 @@
+Ndryshimet kryesore në këtë version: ndreqje të metash për 1.1.4
+Regjistër i plotë ndryshimesh: https://github.com/vector-im/element-android/releases/tag/v1.1.5
diff --git a/fastlane/metadata/android/sq/changelogs/40101060.txt b/fastlane/metadata/android/sq/changelogs/40101060.txt
new file mode 100644
index 0000000000..ab01eede45
--- /dev/null
+++ b/fastlane/metadata/android/sq/changelogs/40101060.txt
@@ -0,0 +1,2 @@
+Ndryshimet kryesore në këtë version: ndreqje të metash për 1.1.5
+Regjistër i plotë ndryshimesh: https://github.com/vector-im/element-android/releases/tag/v1.1.6
diff --git a/fastlane/metadata/android/sq/changelogs/40101070.txt b/fastlane/metadata/android/sq/changelogs/40101070.txt
new file mode 100644
index 0000000000..8d23bb5b94
--- /dev/null
+++ b/fastlane/metadata/android/sq/changelogs/40101070.txt
@@ -0,0 +1,2 @@
+Ndryshimet kryesore në këtë version: mbulim për Hapësira, në fazë beta. Ngjeshje videosh, përpara dërgimi.
+Regjistër i plotë ndryshimesh: https://github.com/vector-im/element-android/releases/tag/v1.1.7
diff --git a/fastlane/metadata/android/sq/changelogs/40101080.txt b/fastlane/metadata/android/sq/changelogs/40101080.txt
new file mode 100644
index 0000000000..f9282142cb
--- /dev/null
+++ b/fastlane/metadata/android/sq/changelogs/40101080.txt
@@ -0,0 +1,2 @@
+Ndryshimet kryesore në këtë version: përmirësime për Hapësira.
+Regjistër i plotë ndryshimesh: https://github.com/vector-im/element-android/releases/tag/v1.1.8
diff --git a/fastlane/metadata/android/sq/changelogs/40101090.txt b/fastlane/metadata/android/sq/changelogs/40101090.txt
new file mode 100644
index 0000000000..069ab4954d
--- /dev/null
+++ b/fastlane/metadata/android/sq/changelogs/40101090.txt
@@ -0,0 +1,2 @@
+Ndryshimet kryesore në këtë version: shtim mbulimi për rrjetin gitter.im.
+Regjistër i plotë ndryshimesh: https://github.com/vector-im/element-android/releases/tag/v1.1.9
diff --git a/fastlane/metadata/android/sq/changelogs/40101100.txt b/fastlane/metadata/android/sq/changelogs/40101100.txt
new file mode 100644
index 0000000000..bf5079bc9a
--- /dev/null
+++ b/fastlane/metadata/android/sq/changelogs/40101100.txt
@@ -0,0 +1,2 @@
+Ndryshimet kryesore në këtë version: përditësime teme dhe stili dhe veçori të reja për hapësira.
+Regjistër i plotë ndryshimesh: https://github.com/vector-im/element-android/releases/tag/v1.1.10
diff --git a/fastlane/metadata/android/sq/changelogs/40101110.txt b/fastlane/metadata/android/sq/changelogs/40101110.txt
new file mode 100644
index 0000000000..44d03bb8cb
--- /dev/null
+++ b/fastlane/metadata/android/sq/changelogs/40101110.txt
@@ -0,0 +1,2 @@
+Ndryshimet kryesore në këtë version: përditësime teme dhe stili dhe veçori të reja për hapësira (ndreqje të mete për 1.1.10)
+Regjistër i plotë ndryshimesh: https://github.com/vector-im/element-android/releases/tag/v1.1.11
diff --git a/fastlane/metadata/android/sq/changelogs/40101120.txt b/fastlane/metadata/android/sq/changelogs/40101120.txt
new file mode 100644
index 0000000000..aecede8d91
--- /dev/null
+++ b/fastlane/metadata/android/sq/changelogs/40101120.txt
@@ -0,0 +1,2 @@
+Ndryshimet kryesore në këtë version: përditësime teme dhe stili dhe ndreqje e një vithisjeje pas një thirrjeje video
+Regjistër i plotë ndryshimesh: https://github.com/vector-im/element-android/releases/tag/v1.1.12
diff --git a/fastlane/metadata/android/sq/changelogs/40101130.txt b/fastlane/metadata/android/sq/changelogs/40101130.txt
new file mode 100644
index 0000000000..535ccd7518
--- /dev/null
+++ b/fastlane/metadata/android/sq/changelogs/40101130.txt
@@ -0,0 +1,2 @@
+Ndryshimet kryesore në këtë version: përditësim kryesisht për qëndrueshmërinë dhe ndreqje të metash.
+Regjistër i plotë ndryshimesh: https://github.com/vector-im/element-android/releases/tag/v1.1.13
diff --git a/fastlane/metadata/android/sq/changelogs/40101140.txt b/fastlane/metadata/android/sq/changelogs/40101140.txt
new file mode 100644
index 0000000000..2dc279e1f7
--- /dev/null
+++ b/fastlane/metadata/android/sq/changelogs/40101140.txt
@@ -0,0 +1,2 @@
+Ndryshimet kryesore në këtë version: ndreqje e një problemi rreth mesazhesh të fshehtëzuar.
+Regjistër i plotë ndryshimesh: https://github.com/vector-im/element-android/releases/tag/v1.1.14
diff --git a/fastlane/metadata/android/sq/changelogs/40101150.txt b/fastlane/metadata/android/sq/changelogs/40101150.txt
new file mode 100644
index 0000000000..1fbf2bae7a
--- /dev/null
+++ b/fastlane/metadata/android/sq/changelogs/40101150.txt
@@ -0,0 +1,2 @@
+Ndryshimet kryesore në këtë version: sendërtim mesazhesh zanore, nën mjedis laboratori.
+Regjistër i plotë ndryshimesh: https://github.com/vector-im/element-android/releases/tag/v1.1.15
diff --git a/fastlane/metadata/android/sq/changelogs/40101160.txt b/fastlane/metadata/android/sq/changelogs/40101160.txt
new file mode 100644
index 0000000000..ecb9a83918
--- /dev/null
+++ b/fastlane/metadata/android/sq/changelogs/40101160.txt
@@ -0,0 +1,2 @@
+Ndryshimet kryesore në këtë version: Ndreqje gabimi, kur dërgohet mesazh i fshehtëzuar, nëse dikush nga dhoma bën dalje prej saj.
+Regjistër i plotë ndryshimesh: https://github.com/vector-im/element-android/releases/tag/v1.1.16
diff --git a/fastlane/metadata/android/sq/changelogs/40102000.txt b/fastlane/metadata/android/sq/changelogs/40102000.txt
new file mode 100644
index 0000000000..c1f2333f1c
--- /dev/null
+++ b/fastlane/metadata/android/sq/changelogs/40102000.txt
@@ -0,0 +1,2 @@
+Ndryshimet kryesore në këtë version: Mesazh Zanor është i aktivizuar, si parazgjedhje.
+Regjistër i plotë ndryshimesh: https://github.com/vector-im/element-android/releases/tag/v1.2.0
diff --git a/fastlane/metadata/android/sq/changelogs/40102010.txt b/fastlane/metadata/android/sq/changelogs/40102010.txt
new file mode 100644
index 0000000000..6ffe456bd4
--- /dev/null
+++ b/fastlane/metadata/android/sq/changelogs/40102010.txt
@@ -0,0 +1,2 @@
+Ndryshimet kryesore në këtë version: Mjaft përmirësime në VoIP dhe Hapësira (ende në beta).
+Regjistër i plotë ndryshimesh: https://github.com/vector-im/element-android/releases/tag/v1.2.1
diff --git a/fastlane/metadata/android/sq/changelogs/40103000.txt b/fastlane/metadata/android/sq/changelogs/40103000.txt
new file mode 100644
index 0000000000..ecd5568c02
--- /dev/null
+++ b/fastlane/metadata/android/sq/changelogs/40103000.txt
@@ -0,0 +1,2 @@
+Ndryshime kryesore në këtë version: Sistemoni dhomat tuaja duke përdorur Hapësira!
+Regjistër i plotë ndryshimesh: https://github.com/vector-im/element-android/releases/tag/v1.3.0
diff --git a/fastlane/metadata/android/sq/changelogs/40103010.txt b/fastlane/metadata/android/sq/changelogs/40103010.txt
new file mode 100644
index 0000000000..1981135963
--- /dev/null
+++ b/fastlane/metadata/android/sq/changelogs/40103010.txt
@@ -0,0 +1,2 @@
+Ndryshime kryesore në këtë version: Sistemoni dhomat tuaja duke përdorur Hapësira! v1.3.1 ndreq një vithisje që mund të ndodhë në v1.3.0.
+Regjistër i plotë ndryshimesh: https://github.com/vector-im/element-android/releases/tag/v1.3.1
diff --git a/fastlane/metadata/android/sq/changelogs/40103020.txt b/fastlane/metadata/android/sq/changelogs/40103020.txt
new file mode 100644
index 0000000000..6c8bd02cf0
--- /dev/null
+++ b/fastlane/metadata/android/sq/changelogs/40103020.txt
@@ -0,0 +1,2 @@
+Ndryshime kryesore në këtë version: Shtim mbulimi për Android Auto. Plot ndreqje të metash!
+Regjistër i plotë ndryshimesh: https://github.com/vector-im/element-android/releases/tag/v1.3.2
diff --git a/fastlane/metadata/android/sq/changelogs/40103030.txt b/fastlane/metadata/android/sq/changelogs/40103030.txt
new file mode 100644
index 0000000000..e52e91eed4
--- /dev/null
+++ b/fastlane/metadata/android/sq/changelogs/40103030.txt
@@ -0,0 +1,2 @@
+Ndryshimet kryesore në këtë version: Bërje të dukshëm e rregullit(ave) të shërbyesit të identiteteve te rregullimet. Heqje përkohësisht e mbulimit për Android Auto.
+Regjistër i plotë ndryshimesh: https://github.com/vector-im/element-android/releases/tag/v1.3.3
diff --git a/fastlane/metadata/android/sq/changelogs/40103040.txt b/fastlane/metadata/android/sq/changelogs/40103040.txt
new file mode 100644
index 0000000000..6ad044b6a4
--- /dev/null
+++ b/fastlane/metadata/android/sq/changelogs/40103040.txt
@@ -0,0 +1,2 @@
+Ndryshimet kryesore në këtë version: Shtim mbulimi për Prani, për dhomë Mesazh i Drejtpërdrejtë (shënim: në matrix.org prania është e çaktivizuar). Shtim sërish i mbulimit për Android Auto.
+Regjistër i plotë ndryshimesh: https://github.com/vector-im/element-android/releases/tag/v1.3.4
diff --git a/fastlane/metadata/android/sq/changelogs/40103050.txt b/fastlane/metadata/android/sq/changelogs/40103050.txt
new file mode 100644
index 0000000000..bb609da987
--- /dev/null
+++ b/fastlane/metadata/android/sq/changelogs/40103050.txt
@@ -0,0 +1,2 @@
+Ndryshimet kryesore në këtë version: Shtim mbulimi për Prani, për dhomën Mesazh i Drejtpërdrejtë (shënim: prania është e çaktivizuar në matrix.org). Shtim sërish i mbulimit për Android Auto.
+Regjistër i plotë ndryshimesh: https://github.com/vector-im/element-android/releases/tag/v1.3.5
diff --git a/fastlane/metadata/android/sq/changelogs/40103060.txt b/fastlane/metadata/android/sq/changelogs/40103060.txt
new file mode 100644
index 0000000000..96afd47a5d
--- /dev/null
+++ b/fastlane/metadata/android/sq/changelogs/40103060.txt
@@ -0,0 +1,2 @@
+Ndryshimet kryesore në këtë version: Shtim mbulimi për Prani, për dhomën Mesazh i Drejtpërdrejtë (shënim: prania është e çaktivizuar në matrix.org). Shtim sërish i mbulimit për Android Auto.
+Regjistër i plotë ndryshimesh: https://github.com/vector-im/element-android/releases/tag/v1.3.6
diff --git a/fastlane/metadata/android/sq/full_description.txt b/fastlane/metadata/android/sq/full_description.txt
new file mode 100644
index 0000000000..ff0ea20da7
--- /dev/null
+++ b/fastlane/metadata/android/sq/full_description.txt
@@ -0,0 +1,42 @@
+Element-i është si aplikacion shkëmbyes i sigurt mesazhesh, ashtu edhe bashkëpunimi prodhimtar ekipi, i cili është ideal për fjalosje në grup, teksa punohet së largëti. Ky aplikacion fjalosjeje përdor fshehtëzim skaj-më-skaj për të furnizuar konferencë video, shkëmbim kartelash dhe thirrje me zë të fuqishme.
+
+Në veçoritë e Element-it përfshihen:
+- Mjete të thelluara komunikimi internetor
+- Mesazhe plotësisht të fshehtëzuar, për të lejuar komunikim në nivel korporate, madje edhe për punonjës së largëti
+- Fjalosje e decentralizuar, bazuar në platformën me burim të hapët Matrix
+- Shkëmbim i sigurt kartelash, me të dhëna të fshehtëzuara, teksa administrohen projekte
+- Fjalosje video të llojit VoIP dhe tregim ekrani
+- Integrim i kollajtë me mjetet tuaja të parapëlqyera të bashkëpunimit internetor, mjete administrimi projektesh, shërbime VoIP dhe aplikacione të tjera shkëmbimi mesazhesh në ekip
+
+Element-i është plotësisht i ndryshëm nga aplikacione të tjera shkëmbimi mesazhesh dhe bashkëpunimi. Funksionimi i tij bazohet në Matrix, një rrjet i hapët për mesazhe të siguruar dhe komunikim të decentralizuar. Lejon vetëstrehim, për t’u dhënë përdoruesve pronësi dhe kontroll maksimal të të dhënave dhe mesazheve të tyre.
+
+Privatësi dhe shkëmbim mesazhesh të fshehtëzuar
+Element-i ju mbron nga reklama të padëshiruara, shfrytëzim të dhënash dhe vatha dixhitale. Ai siguron gjithashtu krejt të dhënat tuaja, komunikime tek-për-tek me video dhe me zë, përmes fshehtëzimi skaj-më-skaj dhe verifikim “cross-signed” pajisjesh.
+
+Element-i ju jep kontrollin e privatësisë tuaj, teksa ju lejon të komunikoni në mënyrë të siguruar me këdo në rrjetin Matrix, ose me mjete të tjera bashkëpunimi në shkallë biznesi, duke u integruar me aplikacione të tillë si Slack.
+
+Element-i mund të vetëstrehohet
+Për të lejuar më tepër kontroll mbi të dhënat dhe bisedat tuaja rezervat, Element-i mund të vetëstrehohet, ose mund të zgjidhni cilëndo strehë të bazuar në Matrix - standardi për komunikim me burim të hapët, të decentralizuar. Element-i ju jep privatësi, pajtueshmëri sigurie dhe zhdërvjelltësi integrimesh.
+
+Jini zot i të dhënave tuaja
+Ju vendosni ku të mbahen të dhënat dhe mesazhet tuaja. Pa rrezikun e shfrytëzimit të të dhënave apo hyrjes në to nga palë të treta.
+
+Element-i ju vë ju në kontroll përmes rrugësh të ndryshme:
+1. Merrni një llogari falas te shërbyesi publik matrix.org strehuar nga zhvillues të Matrix-it, ose zgjidhni prej mijëra shërbyesish publikë të strehuar nga vullnetarë
+2. Vetëstrehoni llogarinë tuaj duke xhiruar një shërbyes në infrastrukturën tuaj TI
+3. Regjistrohuni për një llogari në një shërbyes vetjak, thjesht duke u pajtuar te platforma Element Matrix Services e strehimeve
+
+Shkëmbim mesazhesh dhe bashkëpunim me burim të hapët
+Mund të fjaloseni me këdo në rrjetin Matrix, qoftë kur përdorin Element, një tjetër aplikacion Matrix, apo edhe kur përdorin një tjetër aplikacion shkëmbimi mesazhesh.
+
+Super i sigurt
+Fshehtëzim i njëmendtë skaj-më-skaj (vetëm ata te biseda mund të shfshehtëzojnë mesazhe), dhe verifikim “cross-signed” pajisjesh.
+
+Komunikim dhe integrim i plotë
+Shkëmbim mesazhesh, thirrje me zë dhe me video, shkëmbim kartelash, tregim ekrani dhe një grup i tërë integrimesh, robotësh dhe widget-esh. Krijoni dhoma, bashkësi, mbani lidhjet dhe mbaroni punë.
+
+Rifillojani atje ku e latë
+Jini në dijeni, kudo ku gjendeni, me historik plotësisht të njëkohësuar mesazhesh nëpër krejt pajisjet tuaja dhe në internet te https://app.element.io
+
+Me burim të hapët
+Element-i për Android është një projekt me burim të hapët, strehuar në GitHub. Ju lutemi, njoftoni të meta dhe/ose jepni ndihmesë në zhvillimin e tij te https://github.com/vector-im/element-android
diff --git a/fastlane/metadata/android/sq/short_description.txt b/fastlane/metadata/android/sq/short_description.txt
new file mode 100644
index 0000000000..21937ccce5
--- /dev/null
+++ b/fastlane/metadata/android/sq/short_description.txt
@@ -0,0 +1 @@
+Mesazhe grupi - mesazhe, fjalosje në grup dhe thirrje me video, të fshehtëzuara
diff --git a/fastlane/metadata/android/sq/title.txt b/fastlane/metadata/android/sq/title.txt
new file mode 100644
index 0000000000..097f9c48ea
--- /dev/null
+++ b/fastlane/metadata/android/sq/title.txt
@@ -0,0 +1 @@
+Element - Shkëmbyes i Sigurt Mesazhesh
diff --git a/fastlane/metadata/android/sv-SE/changelogs/40101160.txt b/fastlane/metadata/android/sv-SE/changelogs/40101160.txt
new file mode 100644
index 0000000000..cfdf3b54d4
--- /dev/null
+++ b/fastlane/metadata/android/sv-SE/changelogs/40101160.txt
@@ -0,0 +1,2 @@
+Huvudsakliga ändringar i den här versionen: Fixa fel vid sändning av krypterade meddelanden om någon i rummet loggar ut.
+Full ändringslogg: https://github.com/vector-im/element-android/releases/tag/v1.1.16
diff --git a/fastlane/metadata/android/sv-SE/changelogs/40102000.txt b/fastlane/metadata/android/sv-SE/changelogs/40102000.txt
new file mode 100644
index 0000000000..c31355dc09
--- /dev/null
+++ b/fastlane/metadata/android/sv-SE/changelogs/40102000.txt
@@ -0,0 +1,2 @@
+Huvudsakliga ändringar i den här versionen: Röstmeddelanden är aktiverade som förval.
+Full ändringslogg: https://github.com/vector-im/element-android/releases/tag/v1.2.0
diff --git a/fastlane/metadata/android/sv-SE/changelogs/40102010.txt b/fastlane/metadata/android/sv-SE/changelogs/40102010.txt
new file mode 100644
index 0000000000..f29b95de79
--- /dev/null
+++ b/fastlane/metadata/android/sv-SE/changelogs/40102010.txt
@@ -0,0 +1,2 @@
+Huvudsakliga ändringar i den här versionen: Många förbättringar för VoIP och utrymmen (fortfarande i beta).
+Full ändringslogg: https://github.com/vector-im/element-android/releases/tag/v1.2.1
diff --git a/fastlane/metadata/android/sv-SE/changelogs/40103000.txt b/fastlane/metadata/android/sv-SE/changelogs/40103000.txt
new file mode 100644
index 0000000000..d9a2c34f1d
--- /dev/null
+++ b/fastlane/metadata/android/sv-SE/changelogs/40103000.txt
@@ -0,0 +1,2 @@
+Huvudsakliga ändringar i den här versionen: Organisera dina rum med utrymmen!
+Full ändringslogg: https://github.com/vector-im/element-android/releases/tag/v1.3.0
diff --git a/fastlane/metadata/android/sv-SE/changelogs/40103010.txt b/fastlane/metadata/android/sv-SE/changelogs/40103010.txt
new file mode 100644
index 0000000000..78c2c57ae6
--- /dev/null
+++ b/fastlane/metadata/android/sv-SE/changelogs/40103010.txt
@@ -0,0 +1,2 @@
+Huvudsakliga ändringar i den här versionen: Organisera dina rum med utrymmen! v1.3.1 fixar en krasch som kan hända i v1.3.0.
+Full ändringslogg: https://github.com/vector-im/element-android/releases/tag/v1.3.1
diff --git a/fastlane/metadata/android/sv-SE/changelogs/40103020.txt b/fastlane/metadata/android/sv-SE/changelogs/40103020.txt
new file mode 100644
index 0000000000..4afd54d9be
--- /dev/null
+++ b/fastlane/metadata/android/sv-SE/changelogs/40103020.txt
@@ -0,0 +1,2 @@
+Huvudsakliga ändringar i den här versionen: Lägg till stöd för Android Auto. Massa buggfixar!
+Full ändringslogg: https://github.com/vector-im/element-android/releases/tag/v1.3.2
diff --git a/fastlane/metadata/android/sv-SE/changelogs/40103030.txt b/fastlane/metadata/android/sv-SE/changelogs/40103030.txt
new file mode 100644
index 0000000000..3d55703e86
--- /dev/null
+++ b/fastlane/metadata/android/sv-SE/changelogs/40103030.txt
@@ -0,0 +1,2 @@
+Huvudsakliga ändringar i den här versionen: Gör identitetsserverpolicy(er) synliga i inställningarna. Ta tillfälligt bort stöd för Android Auto.
+Full ändringslogg: https://github.com/vector-im/element-android/releases/tag/v1.3.3
diff --git a/fastlane/metadata/android/sv-SE/changelogs/40103040.txt b/fastlane/metadata/android/sv-SE/changelogs/40103040.txt
new file mode 100644
index 0000000000..faec3bef4d
--- /dev/null
+++ b/fastlane/metadata/android/sv-SE/changelogs/40103040.txt
@@ -0,0 +1,2 @@
+Huvudsakliga ändringar i den här versionen: Lägg till närvarostöd för direktmeddelanden (obs: närvaro är inaktiverat på matrix.org). Lägg till stöd för Android Auto igen.
+Full ändringslogg: https://github.com/vector-im/element-android/releases/tag/v1.3.4
diff --git a/fastlane/metadata/android/sv-SE/changelogs/40103050.txt b/fastlane/metadata/android/sv-SE/changelogs/40103050.txt
new file mode 100644
index 0000000000..57ee7189e3
--- /dev/null
+++ b/fastlane/metadata/android/sv-SE/changelogs/40103050.txt
@@ -0,0 +1,2 @@
+Huvudsakliga ändringar i den här versionen: Lägg till närvarostöd för direktmeddelanden (obs: närvaro är inaktiverat på matrix.org). Lägg till stöd för Android Auto igen.
+Full ändringslogg: https://github.com/vector-im/element-android/releases/tag/v1.3.5
diff --git a/fastlane/metadata/android/sv-SE/changelogs/40103060.txt b/fastlane/metadata/android/sv-SE/changelogs/40103060.txt
new file mode 100644
index 0000000000..bac3775a2a
--- /dev/null
+++ b/fastlane/metadata/android/sv-SE/changelogs/40103060.txt
@@ -0,0 +1,2 @@
+Huvudsakliga ändringar i den här versionen: Lägg till närvarostöd för direktmeddelanden (obs: närvaro är inaktiverat på matrix.org). Lägg till stöd för Android Auto igen.
+Full ändringslogg: https://github.com/vector-im/element-android/releases/tag/v1.3.6
diff --git a/fastlane/metadata/android/sv-SE/full_description.txt b/fastlane/metadata/android/sv-SE/full_description.txt
index 5302976ed7..03d837626e 100644
--- a/fastlane/metadata/android/sv-SE/full_description.txt
+++ b/fastlane/metadata/android/sv-SE/full_description.txt
@@ -37,3 +37,6 @@ Meddelanden, röst- och videosamtal, fildelning, skärmdelning och massa integra
Fortsätt där du lämnade
Håll kontakten vart du än är med fullt synkroniserad meddelandehistorik på alla dina enheter och på webben på https://app.element.io
+
+Öppen källkod
+Element Android är projekt baserat på öppen källkod, som ligger på GitHub. Vänligen rapportera buggar och/eller bidra till dess utveckling på https://github.com/vector-im/element-android
diff --git a/fastlane/metadata/android/uk/changelogs/40101150.txt b/fastlane/metadata/android/uk/changelogs/40101150.txt
new file mode 100644
index 0000000000..c3e724a8a0
--- /dev/null
+++ b/fastlane/metadata/android/uk/changelogs/40101150.txt
@@ -0,0 +1,2 @@
+Основні зміни в цій версії: впровадження голосових повідомлень у налаштуваннях лабораторії.
+Повний журнал змін: https://github.com/vector-im/element-android/releases/tag/v1.1.15
diff --git a/fastlane/metadata/android/uk/changelogs/40101160.txt b/fastlane/metadata/android/uk/changelogs/40101160.txt
new file mode 100644
index 0000000000..fe7bb6c7cc
--- /dev/null
+++ b/fastlane/metadata/android/uk/changelogs/40101160.txt
@@ -0,0 +1,2 @@
+Основні зміни у цій версії: виправлення помилок надсилання зашифрованого повідомлення, якщо хтось виходить з кімнати.
+Усі зміни: https://github.com/vector-im/element-android/releases/tag/v1.1.16
diff --git a/fastlane/metadata/android/uk/changelogs/40102000.txt b/fastlane/metadata/android/uk/changelogs/40102000.txt
new file mode 100644
index 0000000000..9abc8c0298
--- /dev/null
+++ b/fastlane/metadata/android/uk/changelogs/40102000.txt
@@ -0,0 +1,2 @@
+Основні зміни в цій версії: голосові повідомлення типово увімкнено.
+Повний журнал змін: https://github.com/vector-im/element-android/releases/tag/v1.2.0
diff --git a/fastlane/metadata/android/uk/changelogs/40102010.txt b/fastlane/metadata/android/uk/changelogs/40102010.txt
new file mode 100644
index 0000000000..39a8d839b6
--- /dev/null
+++ b/fastlane/metadata/android/uk/changelogs/40102010.txt
@@ -0,0 +1,2 @@
+Основні зміни в цій версії: багато вдосконалень VoIP і просторів (досі бета)
+Повний журнал змін: https://github.com/vector-im/element-android/releases/tag/v1.2.1
diff --git a/fastlane/metadata/android/uk/changelogs/40103000.txt b/fastlane/metadata/android/uk/changelogs/40103000.txt
new file mode 100644
index 0000000000..64a168cbe9
--- /dev/null
+++ b/fastlane/metadata/android/uk/changelogs/40103000.txt
@@ -0,0 +1,2 @@
+Основні зміни в цій версії: Упорядковуйте свої кімнати за допомогою Просторів!
+Повний журнал змін: https://github.com/vector-im/element-android/releases/tag/v1.3.0
diff --git a/fastlane/metadata/android/uk/changelogs/40103010.txt b/fastlane/metadata/android/uk/changelogs/40103010.txt
new file mode 100644
index 0000000000..5940cdedb0
--- /dev/null
+++ b/fastlane/metadata/android/uk/changelogs/40103010.txt
@@ -0,0 +1,2 @@
+Основні зміни в цій версії: Впорядковуйте кімнати у простори. v1.3.1 виправляє збої, які виникали у v1.3.0.
+Повний журнал змін: https://github.com/vector-im/element-android/releases/tag/v1.3.1
diff --git a/fastlane/metadata/android/uk/changelogs/40103020.txt b/fastlane/metadata/android/uk/changelogs/40103020.txt
new file mode 100644
index 0000000000..dc80b0be10
--- /dev/null
+++ b/fastlane/metadata/android/uk/changelogs/40103020.txt
@@ -0,0 +1,2 @@
+Основні зміни в цій версії: Додано підтримку Android Auto. Виправлення багато помилок!
+Повний журнал змін: https://github.com/vector-im/element-android/releases/tag/v1.3.2
diff --git a/fastlane/metadata/android/uk/changelogs/40103030.txt b/fastlane/metadata/android/uk/changelogs/40103030.txt
new file mode 100644
index 0000000000..af25d23c42
--- /dev/null
+++ b/fastlane/metadata/android/uk/changelogs/40103030.txt
@@ -0,0 +1,2 @@
+Основні зміни в цій версії: додано політику ідентифікації сервера (IES) у налаштуваннях. Тимчасово вилучено автозаповнення Android.
+Усі зміни: https://github.com/vector-im/element-android/releases/tag/v1.3.3
diff --git a/fastlane/metadata/android/uk/changelogs/40103040.txt b/fastlane/metadata/android/uk/changelogs/40103040.txt
new file mode 100644
index 0000000000..b6d237241b
--- /dev/null
+++ b/fastlane/metadata/android/uk/changelogs/40103040.txt
@@ -0,0 +1,2 @@
+Основні зміни в цій версії: Додано підтримку присутності для кімнати особистих повідомлень (примітка: присутність вимкнено на matrix.org). Знову додано підтримку Android Auto.
+Повний журнал змін: https://github.com/vector-im/element-android/releases/tag/v1.3.4
diff --git a/fastlane/metadata/android/uk/changelogs/40103050.txt b/fastlane/metadata/android/uk/changelogs/40103050.txt
new file mode 100644
index 0000000000..846d1a2d84
--- /dev/null
+++ b/fastlane/metadata/android/uk/changelogs/40103050.txt
@@ -0,0 +1,2 @@
+Основні зміни у цій версії: Додано підтримку присутності для кімнати особистих повідомлень (примітка: присутність вимкнена на matrix.org). Знову додано підтримку Android Auto.
+Повний журнал змін: https://github.com/vector-im/element-android/releases/tag/v1.3.5
diff --git a/fastlane/metadata/android/uk/changelogs/40103060.txt b/fastlane/metadata/android/uk/changelogs/40103060.txt
new file mode 100644
index 0000000000..a1eec4d4de
--- /dev/null
+++ b/fastlane/metadata/android/uk/changelogs/40103060.txt
@@ -0,0 +1,2 @@
+Основні зміни у цій версії: Додано підтримку присутності для кімнати особистих повідомлень (примітка: присутність вимкнена на matrix.org). Знову додано підтримку Android Auto.
+Повний журнал змін: https://github.com/vector-im/element-android/releases/tag/v1.3.6
diff --git a/fastlane/metadata/android/uk/full_description.txt b/fastlane/metadata/android/uk/full_description.txt
index df06315754..3c59d860ac 100644
--- a/fastlane/metadata/android/uk/full_description.txt
+++ b/fastlane/metadata/android/uk/full_description.txt
@@ -33,7 +33,10 @@ Element надає такі можливості на вибір:
Справжнє наскрізне шифрування (лише учасники бесіди можуть розшифровувати повідомлення) та взаємне підписування пристроїв.
Повноцінні спілкування та інтеграція
-Обмін повідомленнями, голосові та відеовиклики, обмін файлами, спільний доступ до екрана та ціла купа інтеграцій, ботів та віджетів. Створюйте кімнати, спільноти, залишайтеся на зв’язку та виконуйте завдання.
+Обмін повідомленнями, голосові та відеовиклики, обмін файлами, спільний доступ до екрана та ціла купа інтеграцій, ботів та розширень. Створюйте кімнати, спільноти, залишайтеся на зв’язку та виконуйте завдання.
Продовжуйте, де зупинилися
Залишайтеся на зв'язку, де б ви не знаходились, з повністю синхронізованою історією повідомлень на всіх своїх пристроях та в Інтернеті за адресою https://app.element.io
+
+Відкритий код
+Element для Android це проєкт з відкритим кодом, розміщений GitHub. Будь ласка, повідомте про помилки та/або сприяйте його розвитку на https://github.com/vector-im/element-android
diff --git a/fastlane/metadata/android/vi/changelogs/40100120.txt b/fastlane/metadata/android/vi/changelogs/40100120.txt
new file mode 100644
index 0000000000..28c983ef2c
--- /dev/null
+++ b/fastlane/metadata/android/vi/changelogs/40100120.txt
@@ -0,0 +1,2 @@
+Những thay đổi chính trong phiên bản này: xem trước URL, bàn phím Emoji mới, các khả năng cài đặt phòng mới và tuyết cho Giáng Sinh!
+Log thay đổi đầy đủ: https://github.com/vector-im/element-android/releases/tag/v1.0.12
diff --git a/fastlane/metadata/android/vi/changelogs/40100130.txt b/fastlane/metadata/android/vi/changelogs/40100130.txt
new file mode 100644
index 0000000000..baf756a7be
--- /dev/null
+++ b/fastlane/metadata/android/vi/changelogs/40100130.txt
@@ -0,0 +1,2 @@
+Những thay đổi chính trong phiên bản này: xem trước URL, bàn phím Emoji mới, các khả năng cài đặt phòng mới và tuyết cho Giáng Sinh!
+Log thay đổi đầy đủ: https://github.com/vector-im/element-android/releases/tag/v1.0.13
diff --git a/fastlane/metadata/android/vi/changelogs/40100140.txt b/fastlane/metadata/android/vi/changelogs/40100140.txt
new file mode 100644
index 0000000000..83617e28a3
--- /dev/null
+++ b/fastlane/metadata/android/vi/changelogs/40100140.txt
@@ -0,0 +1,2 @@
+Những thay đổi chính trong phiên bản này: chỉnh sửa quyền phòng, chủ đề Sáng/Tối tự động, và một loạt các bản sửa lỗi.
+Log thay đổi đầy đủ: https://github.com/vector-im/element-android/releases/tag/v1.0.14
diff --git a/fastlane/metadata/android/vi/changelogs/40100150.txt b/fastlane/metadata/android/vi/changelogs/40100150.txt
new file mode 100644
index 0000000000..b24be2665e
--- /dev/null
+++ b/fastlane/metadata/android/vi/changelogs/40100150.txt
@@ -0,0 +1,2 @@
+Những thay đổi chính trong phiên bản này: hỗ trợ đăng nhập từ mạng xã hội.
+Log thay đổi đầy đủ: https://github.com/vector-im/element-android/releases/tag/v1.0.15
diff --git a/fastlane/metadata/android/vi/changelogs/40100160.txt b/fastlane/metadata/android/vi/changelogs/40100160.txt
new file mode 100644
index 0000000000..3602b769ed
--- /dev/null
+++ b/fastlane/metadata/android/vi/changelogs/40100160.txt
@@ -0,0 +1,2 @@
+Những thay đổi chính trong phiên bản này: hỗ trợ đăng nhập từ mạng xã hội.
+Log thay đổi đầy đủ: https://github.com/vector-im/element-android/releases/tag/v1.0.15 và https://github.com/vector-im/element-android/releases/tag/v1.0.16
diff --git a/fastlane/metadata/android/vi/changelogs/40100170.txt b/fastlane/metadata/android/vi/changelogs/40100170.txt
new file mode 100644
index 0000000000..40bb26719e
--- /dev/null
+++ b/fastlane/metadata/android/vi/changelogs/40100170.txt
@@ -0,0 +1,2 @@
+Những thay đổi chính trong phiên bản này: Sửa lỗi!
+Log thay đổi đầy đủ: https://github.com/vector-im/element-android/releases/tag/v1.0.17
diff --git a/fastlane/metadata/android/vi/changelogs/40101000.txt b/fastlane/metadata/android/vi/changelogs/40101000.txt
new file mode 100644
index 0000000000..7c89b1b7ee
--- /dev/null
+++ b/fastlane/metadata/android/vi/changelogs/40101000.txt
@@ -0,0 +1,2 @@
+Những thay đổi chính trong phiên bản này: cải tiến VoIP (các cuộc gọi thoại và video trong Tin nhắn Trực tiếp) và sửa lỗi!
+Log thay đổi đầy đủ: https://github.com/vector-im/element-android/releases/tag/v1.1.0
diff --git a/fastlane/metadata/android/vi/changelogs/40101010.txt b/fastlane/metadata/android/vi/changelogs/40101010.txt
new file mode 100644
index 0000000000..08b4dbf65c
--- /dev/null
+++ b/fastlane/metadata/android/vi/changelogs/40101010.txt
@@ -0,0 +1,2 @@
+Những thay đổi chính trong phiên bản này: cải thiện hiệu suất và sửa lỗi!
+Log thay đổi đầy đủ: https://github.com/vector-im/element-android/releases/tag/v1.1.1
diff --git a/fastlane/metadata/android/vi/changelogs/40101020.txt b/fastlane/metadata/android/vi/changelogs/40101020.txt
new file mode 100644
index 0000000000..7bdfe395e8
--- /dev/null
+++ b/fastlane/metadata/android/vi/changelogs/40101020.txt
@@ -0,0 +1,2 @@
+Những thay đổi chính trong phiên bản này: cải thiện hiệu suất và sửa lỗi!
+Log thay đổi đầy đủ: https://github.com/vector-im/element-android/releases/tag/v1.1.2
diff --git a/fastlane/metadata/android/vi/changelogs/40101030.txt b/fastlane/metadata/android/vi/changelogs/40101030.txt
new file mode 100644
index 0000000000..b058f5265f
--- /dev/null
+++ b/fastlane/metadata/android/vi/changelogs/40101030.txt
@@ -0,0 +1,2 @@
+Những thay đổi chính trong phiên bản này: cải thiện hiệu suất và sửa lỗi!
+Log thay đổi đầy đủ: https://github.com/vector-im/element-android/releases/tag/v1.1.3
diff --git a/fastlane/metadata/android/vi/changelogs/40101040.txt b/fastlane/metadata/android/vi/changelogs/40101040.txt
new file mode 100644
index 0000000000..30a5a009b1
--- /dev/null
+++ b/fastlane/metadata/android/vi/changelogs/40101040.txt
@@ -0,0 +1,2 @@
+Những thay đổi chính trong phiên bản này: cải thiện hiệu suất và sửa lỗi!
+Log thay đổi đầy đủ: https://github.com/vector-im/element-android/releases/tag/v1.1.4
diff --git a/fastlane/metadata/android/vi/changelogs/40101050.txt b/fastlane/metadata/android/vi/changelogs/40101050.txt
new file mode 100644
index 0000000000..01de425aa6
--- /dev/null
+++ b/fastlane/metadata/android/vi/changelogs/40101050.txt
@@ -0,0 +1,2 @@
+Những thay đổi chính trong phiên bản này: sửa lỗi nhanh cho 1.1.4
+Log thay đổi đầy đủ: https://github.com/vector-im/element-android/releases/tag/v1.1.5
diff --git a/fastlane/metadata/android/vi/changelogs/40101060.txt b/fastlane/metadata/android/vi/changelogs/40101060.txt
new file mode 100644
index 0000000000..887cc07d8e
--- /dev/null
+++ b/fastlane/metadata/android/vi/changelogs/40101060.txt
@@ -0,0 +1,2 @@
+Những thay đổi chính trong phiên bản này: sửa lỗi nhanh cho 1.1.5
+Log thay đổi đầy đủ: https://github.com/vector-im/element-android/releases/tag/v1.1.6
diff --git a/fastlane/metadata/android/vi/changelogs/40101070.txt b/fastlane/metadata/android/vi/changelogs/40101070.txt
new file mode 100644
index 0000000000..64441edcc6
--- /dev/null
+++ b/fastlane/metadata/android/vi/changelogs/40101070.txt
@@ -0,0 +1,2 @@
+Những thay đổi chính trong phiên bản này: hỗ trợ beta cho Space. Nén video trước khi gửi.
+Log thay đổi đầy đủ: https://github.com/vector-im/element-android/releases/tag/v1.1.7
diff --git a/fastlane/metadata/android/vi/changelogs/40101080.txt b/fastlane/metadata/android/vi/changelogs/40101080.txt
new file mode 100644
index 0000000000..2584b0c156
--- /dev/null
+++ b/fastlane/metadata/android/vi/changelogs/40101080.txt
@@ -0,0 +1,2 @@
+Những thay đổi chính trong phiên bản này: Cải tiến cho Space.
+Log thay đổi đầy đủ: https://github.com/vector-im/element-android/releases/tag/v1.1.8
diff --git a/fastlane/metadata/android/vi/changelogs/40101090.txt b/fastlane/metadata/android/vi/changelogs/40101090.txt
new file mode 100644
index 0000000000..ebf2c0f141
--- /dev/null
+++ b/fastlane/metadata/android/vi/changelogs/40101090.txt
@@ -0,0 +1,2 @@
+Những thay đổi chính trong phiên bản này: thêm hỗ trợ cho mạng gitter.im.
+Log thay đổi đầy đủ: https://github.com/vector-im/element-android/releases/tag/v1.1.9
diff --git a/fastlane/metadata/android/vi/changelogs/40101100.txt b/fastlane/metadata/android/vi/changelogs/40101100.txt
new file mode 100644
index 0000000000..ba62ad1c9f
--- /dev/null
+++ b/fastlane/metadata/android/vi/changelogs/40101100.txt
@@ -0,0 +1,2 @@
+Những thay đổi chính trong phiên bản này: cập nhật chủ đề và phong cách và các tính năng mới cho Space.
+Log thay đổi đầy đủ: https://github.com/vector-im/element-android/releases/tag/v1.1.10
diff --git a/fastlane/metadata/android/vi/changelogs/40101110.txt b/fastlane/metadata/android/vi/changelogs/40101110.txt
new file mode 100644
index 0000000000..07fce22a35
--- /dev/null
+++ b/fastlane/metadata/android/vi/changelogs/40101110.txt
@@ -0,0 +1,2 @@
+Những thay đổi chính trong phiên bản này: cập nhật chủ đề và phong cách và các tính năng mới cho Space (sửa lỗi cho 1.1.1.0)
+Log thay đổi đầy đủ: https://github.com/vector-im/element-android/releases/tag/v1.1.11
diff --git a/fastlane/metadata/android/vi/changelogs/40101120.txt b/fastlane/metadata/android/vi/changelogs/40101120.txt
new file mode 100644
index 0000000000..fddcd9656e
--- /dev/null
+++ b/fastlane/metadata/android/vi/changelogs/40101120.txt
@@ -0,0 +1,2 @@
+Những thay đổi chính trong phiên bản này: cập nhật chủ đề và phong cách và sửa lỗi sau khi gọi video
+Log thay đổi đầy đủ: https://github.com/vector-im/element-android/releases/tag/v1.1.12
diff --git a/fastlane/metadata/android/vi/changelogs/40101130.txt b/fastlane/metadata/android/vi/changelogs/40101130.txt
new file mode 100644
index 0000000000..003154de91
--- /dev/null
+++ b/fastlane/metadata/android/vi/changelogs/40101130.txt
@@ -0,0 +1,2 @@
+Những thay đổi chính trong phiên bản này: chủ yếu là sự ổn định và cập nhật sửa lỗi.
+Log thay đổi đầy đủ: https://github.com/vector-im/element-android/releases/tag/v1.1.13
diff --git a/fastlane/metadata/android/vi/changelogs/40101140.txt b/fastlane/metadata/android/vi/changelogs/40101140.txt
new file mode 100644
index 0000000000..b247be0ce3
--- /dev/null
+++ b/fastlane/metadata/android/vi/changelogs/40101140.txt
@@ -0,0 +1,2 @@
+Những thay đổi chính trong phiên bản này: sửa lỗi các tin nhắn mã hóa.
+Log thay đổi đầy đủ: https://github.com/vector-im/element-android/releases/tag/v1.1.14
diff --git a/fastlane/metadata/android/vi/changelogs/40101150.txt b/fastlane/metadata/android/vi/changelogs/40101150.txt
new file mode 100644
index 0000000000..28d6523ffb
--- /dev/null
+++ b/fastlane/metadata/android/vi/changelogs/40101150.txt
@@ -0,0 +1,2 @@
+Những thay đổi chính trong phiên bản này: triển khai tin nhắn thoại trong cài đặt thí nghiệm.
+Log thay đổi đầy đủ: https://github.com/vector-im/element-android/releases/tag/v1.1.15
diff --git a/fastlane/metadata/android/vi/changelogs/40101160.txt b/fastlane/metadata/android/vi/changelogs/40101160.txt
new file mode 100644
index 0000000000..4ff2c813dc
--- /dev/null
+++ b/fastlane/metadata/android/vi/changelogs/40101160.txt
@@ -0,0 +1,2 @@
+Những thay đổi chính trong phiên bản này: Sửa lỗi gửi tin nhắn mã hóa khi có ai đó trong phòng đăng xuất.
+Log thay đổi đầy đủ: https://github.com/vector-im/element-android/releases/tag/v1.1.16
diff --git a/fastlane/metadata/android/vi/changelogs/40102000.txt b/fastlane/metadata/android/vi/changelogs/40102000.txt
new file mode 100644
index 0000000000..067d8c5705
--- /dev/null
+++ b/fastlane/metadata/android/vi/changelogs/40102000.txt
@@ -0,0 +1,2 @@
+Những thay đổi chính trong phiên bản này: Tin nhắn Thoại được bật mặc định.
+Log thay đổi đầy đủ: https://github.com/vector-im/element-android/releases/tag/v1.2.0
diff --git a/fastlane/metadata/android/vi/changelogs/40102010.txt b/fastlane/metadata/android/vi/changelogs/40102010.txt
new file mode 100644
index 0000000000..3e71d31446
--- /dev/null
+++ b/fastlane/metadata/android/vi/changelogs/40102010.txt
@@ -0,0 +1,2 @@
+Những thay đổi chính trong phiên bản này: Nhiều cải tiến trong VoIP và Space (vẫn đang trong beta).
+Log thay đổi đầy đủ: https://github.com/vector-im/element-android/releases/tag/v1.2.1
diff --git a/fastlane/metadata/android/vi/changelogs/40103000.txt b/fastlane/metadata/android/vi/changelogs/40103000.txt
new file mode 100644
index 0000000000..1bbfba8f38
--- /dev/null
+++ b/fastlane/metadata/android/vi/changelogs/40103000.txt
@@ -0,0 +1,2 @@
+Những thay đổi chính trong phiên bản này: Sắp xếp các phòng của bạn bằng Space!
+Log thay đổi đầy đủ: https://github.com/vector-im/element-android/releases/tag/v1.3.0
diff --git a/fastlane/metadata/android/vi/changelogs/40103010.txt b/fastlane/metadata/android/vi/changelogs/40103010.txt
new file mode 100644
index 0000000000..d3995343c4
--- /dev/null
+++ b/fastlane/metadata/android/vi/changelogs/40103010.txt
@@ -0,0 +1,2 @@
+Những thay đổi chính trong phiên bản này: Sắp xếp các phòng của bạn bằng Space! V1.3.1 khắc phục sự cố có thể xảy ra ở v1.3.0
+Log thay đổi đầy đủ: https://github.com/vector-im/element-android/releases/tag/v1.3.1
diff --git a/fastlane/metadata/android/vi/changelogs/40103020.txt b/fastlane/metadata/android/vi/changelogs/40103020.txt
new file mode 100644
index 0000000000..33a81f4a5d
--- /dev/null
+++ b/fastlane/metadata/android/vi/changelogs/40103020.txt
@@ -0,0 +1,2 @@
+Những thay đổi chính trong phiên bản này: Thêm hỗ trợ Android Auto. Sửa rất nhiều lỗi!
+Log thay đổi đầy đủ: https://github.com/vector-im/element-android/releases/tag/v1.3.2
diff --git a/fastlane/metadata/android/vi/changelogs/40103030.txt b/fastlane/metadata/android/vi/changelogs/40103030.txt
new file mode 100644
index 0000000000..a36a3bb46d
--- /dev/null
+++ b/fastlane/metadata/android/vi/changelogs/40103030.txt
@@ -0,0 +1,2 @@
+Những thay đổi chính trong phiên bản này: Hiển thị (các) chính sách máy chủ xác thực trong phần cài đặt. Tạm thời bỏ hỗ trợ Android Auto.
+Log thay đổi đầy đủ: https://github.com/vector-im/element-android/releases/tag/v1.3.3
diff --git a/fastlane/metadata/android/vi/changelogs/40103040.txt b/fastlane/metadata/android/vi/changelogs/40103040.txt
new file mode 100644
index 0000000000..aadb92827d
--- /dev/null
+++ b/fastlane/metadata/android/vi/changelogs/40103040.txt
@@ -0,0 +1,2 @@
+Những thay đổi chính trong phiên bản này: Thêm hỗ trợ hiển thị, cho phòng Tin nhắn Trực tiếp (lưu ý: hiển thị bị vô hiệu hóa trên matrix.org. Thêm hỗ trợ Android Auto trở lại.
+Log thay đổi đầy đủ: https://github.com/vector-im/element-android/releases/tag/v1.3.4
diff --git a/fastlane/metadata/android/vi/full_description.txt b/fastlane/metadata/android/vi/full_description.txt
new file mode 100644
index 0000000000..6bccb64fd5
--- /dev/null
+++ b/fastlane/metadata/android/vi/full_description.txt
@@ -0,0 +1,42 @@
+Element vừa là một ứng dụng nhắn tin an toàn vừa là một ứng dụng cộng tác nhóm năng suất, lý tưởng cho các cuộc trò chuyện nhóm trong khi làm việc từ xa. Ứng dụng trò chuyện này sử dụng mã hóa đầu cuối để cung cấp tính năng hội nghị truyền hình, chia sẻ tệp và cuộc gọi thoại mạnh mẽ.
+
+ Các tính năng của Element bao gồm:
+- Các công cụ giao tiếp trực tuyến tiên tiến
+- Các tin nhắn được mã hóa hoàn toàn để cho phép liên lạc doanh nghiệp an toàn hơn, ngay cả đối với những người làm việc từ xa
+- Trò chuyện phi tập trung dựa trên khung mã nguồn mở Matrix
+- Chia sẻ tệp một cách an toàn với dữ liệu được mã hóa trong khi quản lý dự án
+- Trò chuyện video với VoIP và chia sẻ màn hình
+- Tích hợp dễ dàng với các công cụ cộng tác trực tuyến yêu thích của bạn, công cụ quản lý dự án, dịch vụ VoIP và các ứng dụng nhắn tin nhóm khác
+
+Element hoàn toàn khác với các ứng dụng nhắn tin và cộng tác khác. Nó hoạt động trên Matrix, một mạng mở để nhắn tin bảo mật và giao tiếp phi tập trung. Nó cho phép tự lưu trữ để cung cấp cho người dùng quyền sở hữu và kiểm soát tối đa dữ liệu và tin nhắn của họ.
+
+ Nhắn tin mã hóa và riêng tư
+Element bảo vệ bạn khỏi các quảng cáo không mong muốn, khai thác dữ liệu và khu vườn có tường bao quanh. Nó cũng bảo mật tất cả dữ liệu của bạn, video 1-1 và giao tiếp thoại thông qua mã hóa đầu cuối và xác minh thiết bị có chữ ký chéo.
+
+Element cung cấp cho bạn quyền kiểm soát quyền riêng tư của mình đồng thời cho phép bạn giao tiếp an toàn với bất kỳ ai trên mạng Ma trận hoặc các công cụ cộng tác kinh doanh khác bằng cách tích hợp với các ứng dụng như Slack.
+
+ Phần tử có thể được tự lưu trữ
+Để cho phép kiểm soát nhiều hơn dữ liệu nhạy cảm và các cuộc trò chuyện của bạn, Element có thể được tự host hoặc bạn có thể chọn bất kỳ host Matrix nào - tiêu chuẩn cho giao tiếp phân tán, mã nguồn mở. Element cung cấp cho bạn quyền riêng tư, tuân thủ bảo mật và tính linh hoạt trong tích hợp.
+
+ Sở hữu dữ liệu của bạn
+Bạn quyết định nơi lưu giữ dữ liệu và tin nhắn của mình. Không có rủi ro khai thác dữ liệu hoặc truy cập từ bên thứ ba.
+
+Element giúp bạn kiểm soát theo những cách khác nhau:
+1. Nhận một tài khoản miễn phí trên máy chủ công cộng matrix.org do các nhà phát triển Matrix host hoặc chọn từ hàng nghìn máy chủ công cộng do các tình nguyện viên lưu trữ
+2. Tự host tài khoản của bạn bằng cách chạy một máy chủ trên cơ sở hạ tầng CNTT của riêng bạn
+3. Đăng ký tài khoản trên máy chủ tùy chỉnh bằng cách chỉ cần đăng ký nền tảng Element Matrix Services hosting
+
+ Mở tin nhắn và cộng tác
+Bạn có thể trò chuyện với bất kỳ ai trên mạng Matrix, cho dù họ đang sử dụng Element, một ứng dụng Matrix khác hay ngay cả khi họ đang sử dụng một ứng dụng nhắn tin khác.
+
+ Siêu bảo mật
+Mã hóa đầu-cuối thực (chỉ những người trong cuộc trò chuyện mới có thể giải mã tin nhắn) và xác minh thiết bị xác thực chéo.
+
+ Giao tiếp và tích hợp hoàn chỉnh
+Nhắn tin, cuộc gọi thoại và video, chia sẻ tệp, chia sẻ màn hình và một loạt các tích hợp, bot và widget. Xây dựng phòng, cộng đồng, giữ liên lạc và hoàn thành công việc.
+
+ Tiếp tục nơi bạn đã dừng lại
+Giữ liên lạc mọi lúc mọi nơi với lịch sử tin nhắn được đồng bộ hóa hoàn toàn trên tất cả các thiết bị của bạn và trên web tại https://app.element.io
+
+ Mã nguồn mở
+Element Android là một dự án mã nguồn mở, được host bởi GitHub. Vui lòng báo cáo lỗi và / hoặc đóng góp vào sự phát triển của nó tại https://github.com/vector-im/element-android
diff --git a/fastlane/metadata/android/zh-CN/changelogs/40101120.txt b/fastlane/metadata/android/zh-CN/changelogs/40101120.txt
new file mode 100644
index 0000000000..06d0540f58
--- /dev/null
+++ b/fastlane/metadata/android/zh-CN/changelogs/40101120.txt
@@ -0,0 +1,2 @@
+此版本的主要变化:主题和样式更新,以及修复视频通话后崩溃的问题
+完整更新日志:https://github.com/vector-im/element-android/releases/tag/v1.1.12
diff --git a/fastlane/metadata/android/zh-CN/changelogs/40101130.txt b/fastlane/metadata/android/zh-CN/changelogs/40101130.txt
new file mode 100644
index 0000000000..623cfca705
--- /dev/null
+++ b/fastlane/metadata/android/zh-CN/changelogs/40101130.txt
@@ -0,0 +1,2 @@
+此版本的主要变化:主要是稳定性和错误修正更新。
+完整更新日志:https://github.com/vector-im/element-android/releases/tag/v1.1.13
diff --git a/fastlane/metadata/android/zh-CN/changelogs/40101140.txt b/fastlane/metadata/android/zh-CN/changelogs/40101140.txt
new file mode 100644
index 0000000000..81dea97d96
--- /dev/null
+++ b/fastlane/metadata/android/zh-CN/changelogs/40101140.txt
@@ -0,0 +1,2 @@
+此版本的主要变化:修复有关加密消息的问题。
+完整更新日志:https://github.com/vector-im/element-android/releases/tag/v1.1.14
diff --git a/fastlane/metadata/android/zh-CN/changelogs/40101150.txt b/fastlane/metadata/android/zh-CN/changelogs/40101150.txt
new file mode 100644
index 0000000000..a6caddbf30
--- /dev/null
+++ b/fastlane/metadata/android/zh-CN/changelogs/40101150.txt
@@ -0,0 +1,2 @@
+此版本的主要变化:实验室设置下的语音消息实现。
+完整更新日志:https://github.com/vector-im/element-android/releases/tag/v1.1.15
diff --git a/fastlane/metadata/android/zh-CN/changelogs/40101160.txt b/fastlane/metadata/android/zh-CN/changelogs/40101160.txt
new file mode 100644
index 0000000000..98357b0dc5
--- /dev/null
+++ b/fastlane/metadata/android/zh-CN/changelogs/40101160.txt
@@ -0,0 +1,2 @@
+此版本的主要变化:修复聊天室中有人登出时发送加密消息所遇到的错误。
+完整更新日志:https://github.com/vector-im/element-android/releases/tag/v1.1.16
diff --git a/fastlane/metadata/android/zh-CN/changelogs/40102000.txt b/fastlane/metadata/android/zh-CN/changelogs/40102000.txt
new file mode 100644
index 0000000000..fa1db16805
--- /dev/null
+++ b/fastlane/metadata/android/zh-CN/changelogs/40102000.txt
@@ -0,0 +1,2 @@
+此版本中的主要更改:默认启用语音消息。
+完整更新日志:https://github.com/vector-im/element-android/releases/tag/v1.2.0
diff --git a/fastlane/metadata/android/zh-CN/changelogs/40102010.txt b/fastlane/metadata/android/zh-CN/changelogs/40102010.txt
new file mode 100644
index 0000000000..2ec2ae22b3
--- /dev/null
+++ b/fastlane/metadata/android/zh-CN/changelogs/40102010.txt
@@ -0,0 +1,2 @@
+这个版本的主要变化:VoIP和空间的许多改进(仍在测试中)。
+完整更新日志:https://github.com/vector-im/element-android/releases/tag/v1.2.1
diff --git a/fastlane/metadata/android/zh-CN/changelogs/40103000.txt b/fastlane/metadata/android/zh-CN/changelogs/40103000.txt
new file mode 100644
index 0000000000..96ec8b3322
--- /dev/null
+++ b/fastlane/metadata/android/zh-CN/changelogs/40103000.txt
@@ -0,0 +1,2 @@
+此版本主要更改:使用空间组织你的聊天室!
+完整更新日志:https://github.com/vector-im/element-android/releases/tag/v1.3.0
diff --git a/fastlane/metadata/android/zh-CN/changelogs/40103010.txt b/fastlane/metadata/android/zh-CN/changelogs/40103010.txt
new file mode 100644
index 0000000000..98b506fb6e
--- /dev/null
+++ b/fastlane/metadata/android/zh-CN/changelogs/40103010.txt
@@ -0,0 +1,2 @@
+此版本的主要变化:使用空间组织您的聊天室! v1.3.1 正在修复 v1.3.0 中可能发生的崩溃。
+完整更新日志:https://github.com/vector-im/element-android/releases/tag/v1.3.1
diff --git a/fastlane/metadata/android/zh-CN/changelogs/40103020.txt b/fastlane/metadata/android/zh-CN/changelogs/40103020.txt
new file mode 100644
index 0000000000..586ba8d892
--- /dev/null
+++ b/fastlane/metadata/android/zh-CN/changelogs/40103020.txt
@@ -0,0 +1,2 @@
+此版本的主要变化: 添加对 Android Auto 的支持。 许多错误修复!
+完整更新日志:https://github.com/vector-im/element-android/releases/tag/v1.3.2
diff --git a/fastlane/metadata/android/zh-CN/changelogs/40103030.txt b/fastlane/metadata/android/zh-CN/changelogs/40103030.txt
new file mode 100644
index 0000000000..1f6ff391e1
--- /dev/null
+++ b/fastlane/metadata/android/zh-CN/changelogs/40103030.txt
@@ -0,0 +1,2 @@
+此版本中的主要更改:使身份服务器策略在设置中可见。 暂时移除 Android Auto 支持。
+完整更新日志:https://github.com/vector-im/element-android/releases/tag/v1.3.3
diff --git a/fastlane/metadata/android/zh-CN/changelogs/40103040.txt b/fastlane/metadata/android/zh-CN/changelogs/40103040.txt
new file mode 100644
index 0000000000..c879c3d036
--- /dev/null
+++ b/fastlane/metadata/android/zh-CN/changelogs/40103040.txt
@@ -0,0 +1,2 @@
+此版本主要变化:为 Direct Message 聊天室添加 Presence 支持 (注意:presence 在 matrix.org 上是禁用的)。再次添加 Android Auto 支持。
+完整更新日志:https://github.com/vector-im/element-android/releases/tag/v1.3.4
diff --git a/fastlane/metadata/android/zh-CN/changelogs/40103050.txt b/fastlane/metadata/android/zh-CN/changelogs/40103050.txt
new file mode 100644
index 0000000000..7343ae0b9f
--- /dev/null
+++ b/fastlane/metadata/android/zh-CN/changelogs/40103050.txt
@@ -0,0 +1,2 @@
+此版本的主要变化:为私信聊天室添加 Presence 支持 (注意:在 matrix.org 上 Presence 是禁用的)。再次添加 Android Auto 支持。
+完整更新日志:https://github.com/vector-im/element-android/releases/tag/v1.3.5
diff --git a/fastlane/metadata/android/zh-CN/changelogs/40103060.txt b/fastlane/metadata/android/zh-CN/changelogs/40103060.txt
new file mode 100644
index 0000000000..8322539927
--- /dev/null
+++ b/fastlane/metadata/android/zh-CN/changelogs/40103060.txt
@@ -0,0 +1,2 @@
+此版本的主要变化:为私信聊天室添加 Presence 支持(注意:在 matrix.org 上 Presence 是禁用的)。再次添加 Android Auto 支持。
+完整更新日志:https://github.com/vector-im/element-android/releases/tag/v1.3.6
diff --git a/fastlane/metadata/android/zh-CN/full_description.txt b/fastlane/metadata/android/zh-CN/full_description.txt
index fa6b00f1e4..3dae8deb67 100644
--- a/fastlane/metadata/android/zh-CN/full_description.txt
+++ b/fastlane/metadata/android/zh-CN/full_description.txt
@@ -37,3 +37,6 @@ Element 透过不同的方式让你掌控一切:
从上次离开的地方开始
无论你身在何处,都可以透过在你所有设备与网页 https://app.element.io 间完全同步的信息历史保持联络
+
+开源
+ Element Android 是一个开源项目,由 GitHub 托管。 请在 https://github.com/vector-im/element-android 报告错误和/或为其开发做出贡献
diff --git a/fastlane/metadata/android/zh-TW/changelogs/40101160.txt b/fastlane/metadata/android/zh-TW/changelogs/40101160.txt
new file mode 100644
index 0000000000..364bec14b9
--- /dev/null
+++ b/fastlane/metadata/android/zh-TW/changelogs/40101160.txt
@@ -0,0 +1,2 @@
+此版本中的主要變動:修復在聊天室中有人登出時傳送加密訊息所發生的問題。
+完整的變更紀錄:https://github.com/vector-im/element-android/releases/tag/v1.1.16
diff --git a/fastlane/metadata/android/zh-TW/changelogs/40102000.txt b/fastlane/metadata/android/zh-TW/changelogs/40102000.txt
new file mode 100644
index 0000000000..993a59c825
--- /dev/null
+++ b/fastlane/metadata/android/zh-TW/changelogs/40102000.txt
@@ -0,0 +1,2 @@
+此版本中的主要變動:語音訊息預設啟用。
+完整的變更紀錄:https://github.com/vector-im/element-android/releases/tag/v1.2.0
diff --git a/fastlane/metadata/android/zh-TW/changelogs/40102010.txt b/fastlane/metadata/android/zh-TW/changelogs/40102010.txt
new file mode 100644
index 0000000000..b520266a78
--- /dev/null
+++ b/fastlane/metadata/android/zh-TW/changelogs/40102010.txt
@@ -0,0 +1,2 @@
+此版本中的主要變動:對 VoIP 與空間功能的諸多改善(仍在測試中)。
+完整的變更紀錄:https://github.com/vector-im/element-android/releases/tag/v1.2.1
diff --git a/fastlane/metadata/android/zh-TW/changelogs/40103000.txt b/fastlane/metadata/android/zh-TW/changelogs/40103000.txt
new file mode 100644
index 0000000000..fbae69cd21
--- /dev/null
+++ b/fastlane/metadata/android/zh-TW/changelogs/40103000.txt
@@ -0,0 +1,2 @@
+此版本中的主要變動:使用空間來整理您的聊天室!
+完整的變更紀錄:https://github.com/vector-im/element-android/releases/tag/v1.3.0
diff --git a/fastlane/metadata/android/zh-TW/changelogs/40103010.txt b/fastlane/metadata/android/zh-TW/changelogs/40103010.txt
new file mode 100644
index 0000000000..95dcd59e46
--- /dev/null
+++ b/fastlane/metadata/android/zh-TW/changelogs/40103010.txt
@@ -0,0 +1,2 @@
+此版本中的主要變動:使用空間來整理您的聊天室!v1.3.1 修復了在 v1.3.0 中遇到的當機問題。
+完整的變更紀錄:https://github.com/vector-im/element-android/releases/tag/v1.3.1
diff --git a/fastlane/metadata/android/zh-TW/changelogs/40103020.txt b/fastlane/metadata/android/zh-TW/changelogs/40103020.txt
new file mode 100644
index 0000000000..6a00bed1e7
--- /dev/null
+++ b/fastlane/metadata/android/zh-TW/changelogs/40103020.txt
@@ -0,0 +1,2 @@
+此版本中的主要變動:新增對 Android Auto 的支援。以及許多錯誤修復!
+完整的變更紀錄:https://github.com/vector-im/element-android/releases/tag/v1.3.2
diff --git a/fastlane/metadata/android/zh-TW/changelogs/40103030.txt b/fastlane/metadata/android/zh-TW/changelogs/40103030.txt
new file mode 100644
index 0000000000..7531d1d4a2
--- /dev/null
+++ b/fastlane/metadata/android/zh-TW/changelogs/40103030.txt
@@ -0,0 +1,2 @@
+此版本中的主要變動:讓身份伺服器政策在設定中可見。暫時移除 Android Auto 支援。
+完整的變更紀錄:https://github.com/vector-im/element-android/releases/tag/v1.3.3
diff --git a/fastlane/metadata/android/zh-TW/changelogs/40103040.txt b/fastlane/metadata/android/zh-TW/changelogs/40103040.txt
new file mode 100644
index 0000000000..bd82b54e45
--- /dev/null
+++ b/fastlane/metadata/android/zh-TW/changelogs/40103040.txt
@@ -0,0 +1,2 @@
+此版本中的主要變動:為直接訊息聊天室新增 Presence 支援(請注意:此功能在 matrix.org 上停用)。加回 Android Auto 支援。
+完整的變更紀錄:https://github.com/vector-im/element-android/releases/tag/v1.3.4
diff --git a/fastlane/metadata/android/zh-TW/changelogs/40103050.txt b/fastlane/metadata/android/zh-TW/changelogs/40103050.txt
new file mode 100644
index 0000000000..659be479f5
--- /dev/null
+++ b/fastlane/metadata/android/zh-TW/changelogs/40103050.txt
@@ -0,0 +1,2 @@
+此版本中的主要變動:為直接訊息聊天室新增 Presence 支援(請注意:此功能在 matrix.org 上停用)。加回 Android Auto 支援。
+完整的變更紀錄:https://github.com/vector-im/element-android/releases/tag/v1.3.5
diff --git a/fastlane/metadata/android/zh-TW/changelogs/40103060.txt b/fastlane/metadata/android/zh-TW/changelogs/40103060.txt
new file mode 100644
index 0000000000..e1223a40e5
--- /dev/null
+++ b/fastlane/metadata/android/zh-TW/changelogs/40103060.txt
@@ -0,0 +1,2 @@
+此版本中的主要變動:為直接訊息聊天室新增 Presence 支援(請注意:此功能在 matrix.org 上停用)。加回 Android Auto 支援。
+完整的變更紀錄:https://github.com/vector-im/element-android/releases/tag/v1.3.6
diff --git a/fastlane/metadata/android/zh-TW/full_description.txt b/fastlane/metadata/android/zh-TW/full_description.txt
index 90c0eb4c4c..eda511c4af 100644
--- a/fastlane/metadata/android/zh-TW/full_description.txt
+++ b/fastlane/metadata/android/zh-TW/full_description.txt
@@ -37,3 +37,6 @@ Element 透過不同的方式讓您掌控一切:
從上次離開的地方開始
無論您身在何處,都可以透過在您所有裝置與網頁 https://app.element.io 間完全同步的訊息歷史保持聯絡
+
+開放原始碼
+Android 版的 Element 是開放原始碼專案,託管於 GitHub 上。請在 https://github.com/vector-im/element-android 上回報臭蟲及/或貢獻其開發
diff --git a/gradle.properties b/gradle.properties
index 9282f3c84e..6c7a7fd118 100644
--- a/gradle.properties
+++ b/gradle.properties
@@ -6,18 +6,21 @@
# http://www.gradle.org/docs/current/userguide/build_environment.html
# Specifies the JVM arguments used for the daemon process.
# The setting is particularly useful for tweaking memory settings.
-android.enableJetifier=true
-android.useAndroidX=true
-org.gradle.jvmargs=-Xmx4096m
-# When configured, Gradle will run in incubating parallel mode.
-# This option should only be used with decoupled projects. More details, visit
-# http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects
-# org.gradle.parallel=true
-# Enable file system watch (https://docs.gradle.org/6.7/release-notes.html)
+# Build Time Optimizations
+org.gradle.jvmargs=-Xmx3g -Xms512M -XX:MaxMetaspaceSize=1g -XX:+HeapDumpOnOutOfMemoryError -Dfile.encoding=UTF-8 -XX:+UseParallelGC
+org.gradle.configureondemand=true
+org.gradle.parallel=true
org.gradle.vfs.watch=true
+# Android Settings
+android.enableJetifier=true
+android.useAndroidX=true
+
+#Project Settings
+# Change debugPrivateData to true for debugging
vector.debugPrivateData=false
+# httpLogLevel values: NONE, BASIC, HEADERS, BODY
vector.httpLogLevel=BASIC
# Note: to debug, you can put and uncomment the following lines in the file ~/.gradle/gradle.properties to override the value above
diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties
index 17ba19021b..f5e3b23f79 100644
--- a/gradle/wrapper/gradle-wrapper.properties
+++ b/gradle/wrapper/gradle-wrapper.properties
@@ -1,6 +1,6 @@
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
-distributionSha256Sum=9bb8bc05f562f2d42bdf1ba8db62f6b6fa1c3bf6c392228802cc7cb0578fe7e0
-distributionUrl=https\://services.gradle.org/distributions/gradle-7.1.1-all.zip
+distributionSha256Sum=00b273629df4ce46e68df232161d5a7c4e495b9a029ce6e0420f071e21316867
+distributionUrl=https\://services.gradle.org/distributions/gradle-7.3-all.zip
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists
diff --git a/gradlew b/gradlew
index 744e882ed5..1b6c787337 100755
--- a/gradlew
+++ b/gradlew
@@ -1,7 +1,7 @@
-#!/usr/bin/env sh
+#!/bin/sh
#
-# Copyright 2015 the original author or authors.
+# Copyright © 2015-2021 the original authors.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
@@ -17,67 +17,101 @@
#
##############################################################################
-##
-## Gradle start up script for UN*X
-##
+#
+# Gradle start up script for POSIX generated by Gradle.
+#
+# Important for running:
+#
+# (1) You need a POSIX-compliant shell to run this script. If your /bin/sh is
+# noncompliant, but you have some other compliant shell such as ksh or
+# bash, then to run this script, type that shell name before the whole
+# command line, like:
+#
+# ksh Gradle
+#
+# Busybox and similar reduced shells will NOT work, because this script
+# requires all of these POSIX shell features:
+# * functions;
+# * expansions «$var», «${var}», «${var:-default}», «${var+SET}»,
+# «${var#prefix}», «${var%suffix}», and «$( cmd )»;
+# * compound commands having a testable exit status, especially «case»;
+# * various built-in commands including «command», «set», and «ulimit».
+#
+# Important for patching:
+#
+# (2) This script targets any POSIX shell, so it avoids extensions provided
+# by Bash, Ksh, etc; in particular arrays are avoided.
+#
+# The "traditional" practice of packing multiple parameters into a
+# space-separated string is a well documented source of bugs and security
+# problems, so this is (mostly) avoided, by progressively accumulating
+# options in "$@", and eventually passing that to Java.
+#
+# Where the inherited environment variables (DEFAULT_JVM_OPTS, JAVA_OPTS,
+# and GRADLE_OPTS) rely on word-splitting, this is performed explicitly;
+# see the in-line comments for details.
+#
+# There are tweaks for specific operating systems such as AIX, CygWin,
+# Darwin, MinGW, and NonStop.
+#
+# (3) This script is generated from the Groovy template
+# https://github.com/gradle/gradle/blob/master/subprojects/plugins/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt
+# within the Gradle project.
+#
+# You can find Gradle at https://github.com/gradle/gradle/.
+#
##############################################################################
# Attempt to set APP_HOME
+
# Resolve links: $0 may be a link
-PRG="$0"
-# Need this for relative symlinks.
-while [ -h "$PRG" ] ; do
- ls=`ls -ld "$PRG"`
- link=`expr "$ls" : '.*-> \(.*\)$'`
- if expr "$link" : '/.*' > /dev/null; then
- PRG="$link"
- else
- PRG=`dirname "$PRG"`"/$link"
- fi
+app_path=$0
+
+# Need this for daisy-chained symlinks.
+while
+ APP_HOME=${app_path%"${app_path##*/}"} # leaves a trailing /; empty if no leading path
+ [ -h "$app_path" ]
+do
+ ls=$( ls -ld "$app_path" )
+ link=${ls#*' -> '}
+ case $link in #(
+ /*) app_path=$link ;; #(
+ *) app_path=$APP_HOME$link ;;
+ esac
done
-SAVED="`pwd`"
-cd "`dirname \"$PRG\"`/" >/dev/null
-APP_HOME="`pwd -P`"
-cd "$SAVED" >/dev/null
+
+APP_HOME=$( cd "${APP_HOME:-./}" && pwd -P ) || exit
APP_NAME="Gradle"
-APP_BASE_NAME=`basename "$0"`
+APP_BASE_NAME=${0##*/}
# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"'
# Use the maximum available, or set MAX_FD != -1 to use that value.
-MAX_FD="maximum"
+MAX_FD=maximum
warn () {
echo "$*"
-}
+} >&2
die () {
echo
echo "$*"
echo
exit 1
-}
+} >&2
# OS specific support (must be 'true' or 'false').
cygwin=false
msys=false
darwin=false
nonstop=false
-case "`uname`" in
- CYGWIN* )
- cygwin=true
- ;;
- Darwin* )
- darwin=true
- ;;
- MSYS* | MINGW* )
- msys=true
- ;;
- NONSTOP* )
- nonstop=true
- ;;
+case "$( uname )" in #(
+ CYGWIN* ) cygwin=true ;; #(
+ Darwin* ) darwin=true ;; #(
+ MSYS* | MINGW* ) msys=true ;; #(
+ NONSTOP* ) nonstop=true ;;
esac
CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
@@ -87,9 +121,9 @@ CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
if [ -n "$JAVA_HOME" ] ; then
if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
# IBM's JDK on AIX uses strange locations for the executables
- JAVACMD="$JAVA_HOME/jre/sh/java"
+ JAVACMD=$JAVA_HOME/jre/sh/java
else
- JAVACMD="$JAVA_HOME/bin/java"
+ JAVACMD=$JAVA_HOME/bin/java
fi
if [ ! -x "$JAVACMD" ] ; then
die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
@@ -98,7 +132,7 @@ Please set the JAVA_HOME variable in your environment to match the
location of your Java installation."
fi
else
- JAVACMD="java"
+ JAVACMD=java
which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
Please set the JAVA_HOME variable in your environment to match the
@@ -106,80 +140,95 @@ location of your Java installation."
fi
# Increase the maximum file descriptors if we can.
-if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then
- MAX_FD_LIMIT=`ulimit -H -n`
- if [ $? -eq 0 ] ; then
- if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then
- MAX_FD="$MAX_FD_LIMIT"
- fi
- ulimit -n $MAX_FD
- if [ $? -ne 0 ] ; then
- warn "Could not set maximum file descriptor limit: $MAX_FD"
- fi
- else
- warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT"
- fi
-fi
-
-# For Darwin, add options to specify how the application appears in the dock
-if $darwin; then
- GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\""
-fi
-
-# For Cygwin or MSYS, switch paths to Windows format before running java
-if [ "$cygwin" = "true" -o "$msys" = "true" ] ; then
- APP_HOME=`cygpath --path --mixed "$APP_HOME"`
- CLASSPATH=`cygpath --path --mixed "$CLASSPATH"`
-
- JAVACMD=`cygpath --unix "$JAVACMD"`
-
- # We build the pattern for arguments to be converted via cygpath
- ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null`
- SEP=""
- for dir in $ROOTDIRSRAW ; do
- ROOTDIRS="$ROOTDIRS$SEP$dir"
- SEP="|"
- done
- OURCYGPATTERN="(^($ROOTDIRS))"
- # Add a user-defined pattern to the cygpath arguments
- if [ "$GRADLE_CYGPATTERN" != "" ] ; then
- OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)"
- fi
- # Now convert the arguments - kludge to limit ourselves to /bin/sh
- i=0
- for arg in "$@" ; do
- CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -`
- CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option
-
- if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition
- eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"`
- else
- eval `echo args$i`="\"$arg\""
- fi
- i=`expr $i + 1`
- done
- case $i in
- 0) set -- ;;
- 1) set -- "$args0" ;;
- 2) set -- "$args0" "$args1" ;;
- 3) set -- "$args0" "$args1" "$args2" ;;
- 4) set -- "$args0" "$args1" "$args2" "$args3" ;;
- 5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;;
- 6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;;
- 7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;;
- 8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;;
- 9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;;
+if ! "$cygwin" && ! "$darwin" && ! "$nonstop" ; then
+ case $MAX_FD in #(
+ max*)
+ MAX_FD=$( ulimit -H -n ) ||
+ warn "Could not query maximum file descriptor limit"
+ esac
+ case $MAX_FD in #(
+ '' | soft) :;; #(
+ *)
+ ulimit -n "$MAX_FD" ||
+ warn "Could not set maximum file descriptor limit to $MAX_FD"
esac
fi
-# Escape application args
-save () {
- for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done
- echo " "
-}
-APP_ARGS=`save "$@"`
+# Collect all arguments for the java command, stacking in reverse order:
+# * args from the command line
+# * the main class name
+# * -classpath
+# * -D...appname settings
+# * --module-path (only if needed)
+# * DEFAULT_JVM_OPTS, JAVA_OPTS, and GRADLE_OPTS environment variables.
-# Collect all arguments for the java command, following the shell quoting and substitution rules
-eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS"
+# For Cygwin or MSYS, switch paths to Windows format before running java
+if "$cygwin" || "$msys" ; then
+ APP_HOME=$( cygpath --path --mixed "$APP_HOME" )
+ CLASSPATH=$( cygpath --path --mixed "$CLASSPATH" )
+
+ JAVACMD=$( cygpath --unix "$JAVACMD" )
+
+ # Now convert the arguments - kludge to limit ourselves to /bin/sh
+ for arg do
+ if
+ case $arg in #(
+ -*) false ;; # don't mess with options #(
+ /?*) t=${arg#/} t=/${t%%/*} # looks like a POSIX filepath
+ [ -e "$t" ] ;; #(
+ *) false ;;
+ esac
+ then
+ arg=$( cygpath --path --ignore --mixed "$arg" )
+ fi
+ # Roll the args list around exactly as many times as the number of
+ # args, so each arg winds up back in the position where it started, but
+ # possibly modified.
+ #
+ # NB: a `for` loop captures its iteration list before it begins, so
+ # changing the positional parameters here affects neither the number of
+ # iterations, nor the values presented in `arg`.
+ shift # remove old arg
+ set -- "$@" "$arg" # push replacement arg
+ done
+fi
+
+# Collect all arguments for the java command;
+# * $DEFAULT_JVM_OPTS, $JAVA_OPTS, and $GRADLE_OPTS can contain fragments of
+# shell script including quotes and variable substitutions, so put them in
+# double quotes to make sure that they get re-expanded; and
+# * put everything else in single quotes, so that it's not re-expanded.
+
+set -- \
+ "-Dorg.gradle.appname=$APP_BASE_NAME" \
+ -classpath "$CLASSPATH" \
+ org.gradle.wrapper.GradleWrapperMain \
+ "$@"
+
+# Use "xargs" to parse quoted args.
+#
+# With -n1 it outputs one arg per line, with the quotes and backslashes removed.
+#
+# In Bash we could simply go:
+#
+# readarray ARGS < <( xargs -n1 <<<"$var" ) &&
+# set -- "${ARGS[@]}" "$@"
+#
+# but POSIX shell has neither arrays nor command substitution, so instead we
+# post-process each arg (as a line of input to sed) to backslash-escape any
+# character that might be a shell metacharacter, then use eval to reverse
+# that process (while maintaining the separation between arguments), and wrap
+# the whole thing up as a single "set" statement.
+#
+# This will of course break if any of these variables contains a newline or
+# an unmatched quote.
+#
+
+eval "set -- $(
+ printf '%s\n' "$DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS" |
+ xargs -n1 |
+ sed ' s~[^-[:alnum:]+,./:=@_]~\\&~g; ' |
+ tr '\n' ' '
+ )" '"$@"'
exec "$JAVACMD" "$@"
diff --git a/library/ui-styles/build.gradle b/library/ui-styles/build.gradle
index e264ef8319..cee58414c7 100644
--- a/library/ui-styles/build.gradle
+++ b/library/ui-styles/build.gradle
@@ -20,14 +20,11 @@ plugins {
}
android {
- compileSdkVersion 30
- buildToolsVersion "30.0.3"
+ compileSdk versions.compileSdk
defaultConfig {
- minSdkVersion 21
- targetSdkVersion 30
- versionCode 1
- versionName "1.0"
+ minSdk versions.minSdk
+ targetSdk versions.targetSdk
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
consumerProguardFiles "consumer-rules.pro"
@@ -39,23 +36,26 @@ android {
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
}
}
+
compileOptions {
- sourceCompatibility JavaVersion.VERSION_1_8
- targetCompatibility JavaVersion.VERSION_1_8
+ sourceCompatibility versions.sourceCompat
+ targetCompatibility versions.targetCompat
}
+
kotlinOptions {
- jvmTarget = '1.8'
+ jvmTarget = "11"
}
+
buildFeatures {
viewBinding true
}
}
dependencies {
- implementation 'androidx.appcompat:appcompat:1.3.1'
- implementation 'com.google.android.material:material:1.4.0'
+ implementation libs.androidx.appCompat
+ implementation libs.google.material
// Pref theme
- implementation 'androidx.preference:preference-ktx:1.1.1'
+ implementation libs.androidx.preferenceKtx
// PFLockScreen attrs
implementation 'com.github.vector-im:PFLockScreen-Android:1.0.0-beta12'
// dialpad dimen
diff --git a/library/ui-styles/src/main/AndroidManifest.xml b/library/ui-styles/src/main/AndroidManifest.xml
index 19aa89e2e7..254827465d 100644
--- a/library/ui-styles/src/main/AndroidManifest.xml
+++ b/library/ui-styles/src/main/AndroidManifest.xml
@@ -1,2 +1,7 @@
-
\ No newline at end of file
+
+
+
+
+
\ No newline at end of file
diff --git a/library/ui-styles/src/main/res/color/form_edit_text_hint_color_selector.xml b/library/ui-styles/src/main/res/color/form_edit_text_hint_color_selector.xml
new file mode 100644
index 0000000000..343c42ebf3
--- /dev/null
+++ b/library/ui-styles/src/main/res/color/form_edit_text_hint_color_selector.xml
@@ -0,0 +1,6 @@
+
+
+
+
+
+
diff --git a/library/ui-styles/src/main/res/color/form_edit_text_stroke_color_selector.xml b/library/ui-styles/src/main/res/color/form_edit_text_stroke_color_selector.xml
new file mode 100644
index 0000000000..7079cc271b
--- /dev/null
+++ b/library/ui-styles/src/main/res/color/form_edit_text_stroke_color_selector.xml
@@ -0,0 +1,7 @@
+
+
+
+
+
+
+
diff --git a/library/ui-styles/src/main/res/color/keyword_background_selector.xml b/library/ui-styles/src/main/res/color/keyword_background_selector.xml
new file mode 100644
index 0000000000..3420cfeaba
--- /dev/null
+++ b/library/ui-styles/src/main/res/color/keyword_background_selector.xml
@@ -0,0 +1,5 @@
+
+
+
+
+
\ No newline at end of file
diff --git a/library/ui-styles/src/main/res/color/keyword_foreground_selector.xml b/library/ui-styles/src/main/res/color/keyword_foreground_selector.xml
new file mode 100644
index 0000000000..339f240246
--- /dev/null
+++ b/library/ui-styles/src/main/res/color/keyword_foreground_selector.xml
@@ -0,0 +1,5 @@
+
+
+
+
+
diff --git a/library/ui-styles/src/main/res/layout/dialog_progress_material.xml b/library/ui-styles/src/main/res/layout/dialog_progress_material.xml
index 09c88cc50b..32c4f666c7 100644
--- a/library/ui-styles/src/main/res/layout/dialog_progress_material.xml
+++ b/library/ui-styles/src/main/res/layout/dialog_progress_material.xml
@@ -2,7 +2,8 @@
+ android:layout_height="wrap_content"
+ tools:ignore="UselessParent">
@android:color/black
+ #0BAC7E
#80000000
@@ -128,8 +129,12 @@
@color/black_alpha
@android:color/transparent
-
- @color/palette_black_900
- @color/palette_gray_400
+
+ @color/palette_black_900
+ @color/palette_gray_400
+
+
+ @color/palette_gray_100
+ @color/palette_gray_450
diff --git a/library/ui-styles/src/main/res/values/dimens.xml b/library/ui-styles/src/main/res/values/dimens.xml
index 88338f799b..e2e50449ce 100644
--- a/library/ui-styles/src/main/res/values/dimens.xml
+++ b/library/ui-styles/src/main/res/values/dimens.xml
@@ -28,6 +28,10 @@
20dp
4dp
+ 128dp
+ 88dp
+ 8dp
+
76dp
diff --git a/library/ui-styles/src/main/res/values/stylable_bottom_sheet_action.xml b/library/ui-styles/src/main/res/values/stylable_bottom_sheet_action.xml
index d6fa160d6b..b0c45b1fea 100644
--- a/library/ui-styles/src/main/res/values/stylable_bottom_sheet_action.xml
+++ b/library/ui-styles/src/main/res/values/stylable_bottom_sheet_action.xml
@@ -8,6 +8,7 @@
+
diff --git a/library/ui-styles/src/main/res/values/styles_buttons.xml b/library/ui-styles/src/main/res/values/styles_buttons.xml
index ad90469a52..d09d0a399d 100644
--- a/library/ui-styles/src/main/res/values/styles_buttons.xml
+++ b/library/ui-styles/src/main/res/values/styles_buttons.xml
@@ -10,6 +10,11 @@
- 24sp
+
+
-
+
\ No newline at end of file
diff --git a/library/ui-styles/src/main/res/values/styles_text_input_layout.xml b/library/ui-styles/src/main/res/values/styles_text_input_layout.xml
new file mode 100644
index 0000000000..95a406ea5c
--- /dev/null
+++ b/library/ui-styles/src/main/res/values/styles_text_input_layout.xml
@@ -0,0 +1,17 @@
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/library/ui-styles/src/main/res/values/styles_toast.xml b/library/ui-styles/src/main/res/values/styles_toast.xml
new file mode 100644
index 0000000000..22f4da7ac0
--- /dev/null
+++ b/library/ui-styles/src/main/res/values/styles_toast.xml
@@ -0,0 +1,15 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/library/ui-styles/src/main/res/values/styles_voice_message.xml b/library/ui-styles/src/main/res/values/styles_voice_message.xml
index 59fea75074..2e87353303 100644
--- a/library/ui-styles/src/main/res/values/styles_voice_message.xml
+++ b/library/ui-styles/src/main/res/values/styles_voice_message.xml
@@ -12,15 +12,4 @@
- rightToLeft
-
-
\ No newline at end of file
diff --git a/library/ui-styles/src/main/res/values/theme_dark.xml b/library/ui-styles/src/main/res/values/theme_dark.xml
index 0dbdc5ad4f..4d525f7eee 100644
--- a/library/ui-styles/src/main/res/values/theme_dark.xml
+++ b/library/ui-styles/src/main/res/values/theme_dark.xml
@@ -42,6 +42,9 @@
- @android:color/black
- #FFFFFFFF
+
+ - @color/vctr_presence_indicator_offline_dark
+
- ?vctr_system
- ?vctr_content_quinary
@@ -134,9 +137,10 @@
- @style/Widget.Vector.Button.Outlined.SocialLogin.Gitlab.Dark
- @style/Widget.Vector.JumpToUnread.Dark
+
+ - @style/Widget.Vector.Keyword
-
- - @color/vctr_voice_message_toast_background_dark
+ - @color/vctr_toast_background_dark
diff --git a/library/ui-styles/src/main/res/values/theme_light.xml b/library/ui-styles/src/main/res/values/theme_light.xml
index 17e0ff2938..790a0bfc7c 100644
--- a/library/ui-styles/src/main/res/values/theme_light.xml
+++ b/library/ui-styles/src/main/res/values/theme_light.xml
@@ -42,6 +42,9 @@
- #FFEEEEEE
- #FF000000
+
+ - @color/vctr_presence_indicator_offline_light
+
- ?vctr_system
- ?vctr_content_quinary
@@ -137,8 +140,10 @@
- @style/Widget.Vector.JumpToUnread.Light
-
- - @color/vctr_voice_message_toast_background_light
+
+ - @style/Widget.Vector.Keyword
+
+ - @color/vctr_toast_background_light
diff --git a/matrix-sdk-android-flow/.gitignore b/matrix-sdk-android-flow/.gitignore
new file mode 100644
index 0000000000..42afabfd2a
--- /dev/null
+++ b/matrix-sdk-android-flow/.gitignore
@@ -0,0 +1 @@
+/build
\ No newline at end of file
diff --git a/matrix-sdk-android-flow/build.gradle b/matrix-sdk-android-flow/build.gradle
new file mode 100644
index 0000000000..ea43ce20c8
--- /dev/null
+++ b/matrix-sdk-android-flow/build.gradle
@@ -0,0 +1,47 @@
+
+plugins {
+ id 'com.android.library'
+ id 'org.jetbrains.kotlin.android'
+}
+
+android {
+ compileSdk versions.compileSdk
+
+ defaultConfig {
+ minSdk versions.minSdk
+ targetSdk versions.targetSdk
+
+ testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
+ consumerProguardFiles "consumer-rules.pro"
+ }
+
+ buildTypes {
+ release {
+ minifyEnabled false
+ proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
+ }
+ }
+ compileOptions {
+ sourceCompatibility versions.sourceCompat
+ targetCompatibility versions.targetCompat
+ }
+ kotlinOptions {
+ jvmTarget = "11"
+ }
+}
+
+dependencies {
+
+ implementation project(":matrix-sdk-android")
+ implementation libs.androidx.appCompat
+
+ implementation libs.jetbrains.coroutinesCore
+ implementation libs.jetbrains.coroutinesAndroid
+ implementation libs.androidx.lifecycleLivedata
+
+ // Paging
+ implementation libs.androidx.pagingRuntimeKtx
+
+ // Logging
+ implementation libs.jakewharton.timber
+}
diff --git a/matrix-sdk-android-flow/consumer-rules.pro b/matrix-sdk-android-flow/consumer-rules.pro
new file mode 100644
index 0000000000..e69de29bb2
diff --git a/matrix-sdk-android-flow/proguard-rules.pro b/matrix-sdk-android-flow/proguard-rules.pro
new file mode 100644
index 0000000000..481bb43481
--- /dev/null
+++ b/matrix-sdk-android-flow/proguard-rules.pro
@@ -0,0 +1,21 @@
+# Add project specific ProGuard rules here.
+# You can control the set of applied configuration files using the
+# proguardFiles setting in build.gradle.
+#
+# For more details, see
+# http://developer.android.com/guide/developing/tools/proguard.html
+
+# If your project uses WebView with JS, uncomment the following
+# and specify the fully qualified class name to the JavaScript interface
+# class:
+#-keepclassmembers class fqcn.of.javascript.interface.for.webview {
+# public *;
+#}
+
+# Uncomment this to preserve the line number information for
+# debugging stack traces.
+#-keepattributes SourceFile,LineNumberTable
+
+# If you keep the line number information, uncomment this to
+# hide the original source file name.
+#-renamesourcefileattribute SourceFile
\ No newline at end of file
diff --git a/matrix-sdk-android-flow/src/main/AndroidManifest.xml b/matrix-sdk-android-flow/src/main/AndroidManifest.xml
new file mode 100644
index 0000000000..2392c0bfcb
--- /dev/null
+++ b/matrix-sdk-android-flow/src/main/AndroidManifest.xml
@@ -0,0 +1,5 @@
+
+
+
+
\ No newline at end of file
diff --git a/matrix-sdk-android-flow/src/main/java/org/matrix/android/sdk/flow/FlowExt.kt b/matrix-sdk-android-flow/src/main/java/org/matrix/android/sdk/flow/FlowExt.kt
new file mode 100644
index 0000000000..72493325c3
--- /dev/null
+++ b/matrix-sdk-android-flow/src/main/java/org/matrix/android/sdk/flow/FlowExt.kt
@@ -0,0 +1,31 @@
+/*
+ * Copyright (c) 2021 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 org.matrix.android.sdk.flow
+
+import kotlinx.coroutines.CoroutineDispatcher
+import kotlinx.coroutines.flow.Flow
+import kotlinx.coroutines.flow.onStart
+import kotlinx.coroutines.withContext
+
+internal fun Flow.startWith(dispatcher: CoroutineDispatcher, supplier: suspend () -> T): Flow {
+ return onStart {
+ val value = withContext(dispatcher) {
+ supplier()
+ }
+ emit(value)
+ }
+}
diff --git a/matrix-sdk-android-flow/src/main/java/org/matrix/android/sdk/flow/FlowRoom.kt b/matrix-sdk-android-flow/src/main/java/org/matrix/android/sdk/flow/FlowRoom.kt
new file mode 100644
index 0000000000..42c1476b79
--- /dev/null
+++ b/matrix-sdk-android-flow/src/main/java/org/matrix/android/sdk/flow/FlowRoom.kt
@@ -0,0 +1,105 @@
+/*
+ * Copyright 2020 The Matrix.org Foundation C.I.C.
+ *
+ * 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 org.matrix.android.sdk.flow
+
+import androidx.lifecycle.asFlow
+import kotlinx.coroutines.flow.Flow
+import org.matrix.android.sdk.api.query.QueryStringValue
+import org.matrix.android.sdk.api.session.events.model.Event
+import org.matrix.android.sdk.api.session.room.Room
+import org.matrix.android.sdk.api.session.room.members.RoomMemberQueryParams
+import org.matrix.android.sdk.api.session.room.model.EventAnnotationsSummary
+import org.matrix.android.sdk.api.session.room.model.ReadReceipt
+import org.matrix.android.sdk.api.session.room.model.RoomMemberSummary
+import org.matrix.android.sdk.api.session.room.model.RoomSummary
+import org.matrix.android.sdk.api.session.room.notification.RoomNotificationState
+import org.matrix.android.sdk.api.session.room.send.UserDraft
+import org.matrix.android.sdk.api.session.room.timeline.TimelineEvent
+import org.matrix.android.sdk.api.util.Optional
+import org.matrix.android.sdk.api.util.toOptional
+
+class FlowRoom(private val room: Room) {
+
+ fun liveRoomSummary(): Flow> {
+ return room.getRoomSummaryLive().asFlow()
+ .startWith(room.coroutineDispatchers.io) {
+ room.roomSummary().toOptional()
+ }
+ }
+
+ fun liveRoomMembers(queryParams: RoomMemberQueryParams): Flow> {
+ return room.getRoomMembersLive(queryParams).asFlow()
+ .startWith(room.coroutineDispatchers.io) {
+ room.getRoomMembers(queryParams)
+ }
+ }
+
+ fun liveAnnotationSummary(eventId: String): Flow> {
+ return room.getEventAnnotationsSummaryLive(eventId).asFlow()
+ .startWith(room.coroutineDispatchers.io) {
+ room.getEventAnnotationsSummary(eventId).toOptional()
+ }
+ }
+
+ fun liveTimelineEvent(eventId: String): Flow> {
+ return room.getTimeLineEventLive(eventId).asFlow()
+ .startWith(room.coroutineDispatchers.io) {
+ room.getTimeLineEvent(eventId).toOptional()
+ }
+ }
+
+ fun liveStateEvent(eventType: String, stateKey: QueryStringValue): Flow> {
+ return room.getStateEventLive(eventType, stateKey).asFlow()
+ .startWith(room.coroutineDispatchers.io) {
+ room.getStateEvent(eventType, stateKey).toOptional()
+ }
+ }
+
+ fun liveStateEvents(eventTypes: Set): Flow> {
+ return room.getStateEventsLive(eventTypes).asFlow()
+ .startWith(room.coroutineDispatchers.io) {
+ room.getStateEvents(eventTypes)
+ }
+ }
+
+ fun liveReadMarker(): Flow> {
+ return room.getReadMarkerLive().asFlow()
+ }
+
+ fun liveReadReceipt(): Flow> {
+ return room.getMyReadReceiptLive().asFlow()
+ }
+
+ fun liveEventReadReceipts(eventId: String): Flow> {
+ return room.getEventReadReceiptsLive(eventId).asFlow()
+ }
+
+ fun liveDraft(): Flow> {
+ return room.getDraftLive().asFlow()
+ .startWith(room.coroutineDispatchers.io) {
+ room.getDraft().toOptional()
+ }
+ }
+
+ fun liveNotificationState(): Flow {
+ return room.getLiveRoomNotificationState().asFlow()
+ }
+}
+
+fun Room.flow(): FlowRoom {
+ return FlowRoom(this)
+}
diff --git a/matrix-sdk-android-flow/src/main/java/org/matrix/android/sdk/flow/FlowSession.kt b/matrix-sdk-android-flow/src/main/java/org/matrix/android/sdk/flow/FlowSession.kt
new file mode 100644
index 0000000000..2a0abd3d24
--- /dev/null
+++ b/matrix-sdk-android-flow/src/main/java/org/matrix/android/sdk/flow/FlowSession.kt
@@ -0,0 +1,181 @@
+/*
+ * Copyright 2020 The Matrix.org Foundation C.I.C.
+ *
+ * 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 org.matrix.android.sdk.flow
+
+import androidx.lifecycle.asFlow
+import androidx.paging.PagedList
+import kotlinx.coroutines.flow.Flow
+import org.matrix.android.sdk.api.query.QueryStringValue
+import org.matrix.android.sdk.api.session.Session
+import org.matrix.android.sdk.api.session.accountdata.UserAccountDataEvent
+import org.matrix.android.sdk.api.session.crypto.crosssigning.MXCrossSigningInfo
+import org.matrix.android.sdk.api.session.group.GroupSummaryQueryParams
+import org.matrix.android.sdk.api.session.group.model.GroupSummary
+import org.matrix.android.sdk.api.session.identity.ThreePid
+import org.matrix.android.sdk.api.session.pushers.Pusher
+import org.matrix.android.sdk.api.session.room.RoomSortOrder
+import org.matrix.android.sdk.api.session.room.RoomSummaryQueryParams
+import org.matrix.android.sdk.api.session.room.accountdata.RoomAccountDataEvent
+import org.matrix.android.sdk.api.session.room.members.ChangeMembershipState
+import org.matrix.android.sdk.api.session.room.model.RoomMemberSummary
+import org.matrix.android.sdk.api.session.room.model.RoomSummary
+import org.matrix.android.sdk.api.session.space.SpaceSummaryQueryParams
+import org.matrix.android.sdk.api.session.sync.SyncState
+import org.matrix.android.sdk.api.session.user.model.User
+import org.matrix.android.sdk.api.session.widgets.model.Widget
+import org.matrix.android.sdk.api.util.Optional
+import org.matrix.android.sdk.api.util.toOptional
+import org.matrix.android.sdk.internal.crypto.model.CryptoDeviceInfo
+import org.matrix.android.sdk.internal.crypto.model.rest.DeviceInfo
+import org.matrix.android.sdk.internal.crypto.store.PrivateKeysInfo
+
+class FlowSession(private val session: Session) {
+
+ fun liveRoomSummaries(queryParams: RoomSummaryQueryParams, sortOrder: RoomSortOrder = RoomSortOrder.NONE): Flow> {
+ return session.getRoomSummariesLive(queryParams, sortOrder).asFlow()
+ .startWith(session.coroutineDispatchers.io) {
+ session.getRoomSummaries(queryParams, sortOrder)
+ }
+ }
+
+ fun liveGroupSummaries(queryParams: GroupSummaryQueryParams): Flow> {
+ return session.getGroupSummariesLive(queryParams).asFlow()
+ .startWith(session.coroutineDispatchers.io) {
+ session.getGroupSummaries(queryParams)
+ }
+ }
+
+ fun liveSpaceSummaries(queryParams: SpaceSummaryQueryParams): Flow> {
+ return session.spaceService().getSpaceSummariesLive(queryParams).asFlow()
+ .startWith(session.coroutineDispatchers.io) {
+ session.spaceService().getSpaceSummaries(queryParams)
+ }
+ }
+
+ fun liveBreadcrumbs(queryParams: RoomSummaryQueryParams): Flow> {
+ return session.getBreadcrumbsLive(queryParams).asFlow()
+ .startWith(session.coroutineDispatchers.io) {
+ session.getBreadcrumbs(queryParams)
+ }
+ }
+
+ fun liveMyDevicesInfo(): Flow> {
+ return session.cryptoService().getLiveMyDevicesInfo().asFlow()
+ .startWith(session.coroutineDispatchers.io) {
+ session.cryptoService().getMyDevicesInfo()
+ }
+ }
+
+ fun liveSyncState(): Flow {
+ return session.getSyncStateLive().asFlow()
+ }
+
+ fun livePushers(): Flow> {
+ return session.getPushersLive().asFlow()
+ }
+
+ fun liveUser(userId: String): Flow> {
+ return session.getUserLive(userId).asFlow()
+ .startWith(session.coroutineDispatchers.io) {
+ session.getUser(userId).toOptional()
+ }
+ }
+
+ fun liveRoomMember(userId: String, roomId: String): Flow> {
+ return session.getRoomMemberLive(userId, roomId).asFlow()
+ .startWith(session.coroutineDispatchers.io) {
+ session.getRoomMember(userId, roomId).toOptional()
+ }
+ }
+
+ fun liveUsers(): Flow> {
+ return session.getUsersLive().asFlow()
+ }
+
+ fun liveIgnoredUsers(): Flow> {
+ return session.getIgnoredUsersLive().asFlow()
+ }
+
+ fun livePagedUsers(filter: String? = null, excludedUserIds: Set? = null): Flow> {
+ return session.getPagedUsersLive(filter, excludedUserIds).asFlow()
+ }
+
+ fun liveThreePIds(refreshData: Boolean): Flow> {
+ return session.getThreePidsLive(refreshData).asFlow()
+ .startWith(session.coroutineDispatchers.io) { session.getThreePids() }
+ }
+
+ fun livePendingThreePIds(): Flow> {
+ return session.getPendingThreePidsLive().asFlow()
+ .startWith(session.coroutineDispatchers.io) { session.getPendingThreePids() }
+ }
+
+ fun liveUserCryptoDevices(userId: String): Flow> {
+ return session.cryptoService().getLiveCryptoDeviceInfo(userId).asFlow()
+ .startWith(session.coroutineDispatchers.io) {
+ session.cryptoService().getCryptoDeviceInfo(userId)
+ }
+ }
+
+ fun liveCrossSigningInfo(userId: String): Flow> {
+ return session.cryptoService().crossSigningService().getLiveCrossSigningKeys(userId).asFlow()
+ .startWith(session.coroutineDispatchers.io) {
+ session.cryptoService().crossSigningService().getUserCrossSigningKeys(userId).toOptional()
+ }
+ }
+
+ fun liveCrossSigningPrivateKeys(): Flow> {
+ return session.cryptoService().crossSigningService().getLiveCrossSigningPrivateKeys().asFlow()
+ .startWith(session.coroutineDispatchers.io) {
+ session.cryptoService().crossSigningService().getCrossSigningPrivateKeys().toOptional()
+ }
+ }
+
+ fun liveUserAccountData(types: Set): Flow> {
+ return session.accountDataService().getLiveUserAccountDataEvents(types).asFlow()
+ .startWith(session.coroutineDispatchers.io) {
+ session.accountDataService().getUserAccountDataEvents(types)
+ }
+ }
+
+ fun liveRoomAccountData(types: Set): Flow> {
+ return session.accountDataService().getLiveRoomAccountDataEvents(types).asFlow()
+ .startWith(session.coroutineDispatchers.io) {
+ session.accountDataService().getRoomAccountDataEvents(types)
+ }
+ }
+
+ fun liveRoomWidgets(
+ roomId: String,
+ widgetId: QueryStringValue,
+ widgetTypes: Set? = null,
+ excludedTypes: Set? = null
+ ): Flow> {
+ return session.widgetService().getRoomWidgetsLive(roomId, widgetId, widgetTypes, excludedTypes).asFlow()
+ .startWith(session.coroutineDispatchers.io) {
+ session.widgetService().getRoomWidgets(roomId, widgetId, widgetTypes, excludedTypes)
+ }
+ }
+
+ fun liveRoomChangeMembershipState(): Flow> {
+ return session.getChangeMembershipsLive().asFlow()
+ }
+}
+
+fun Session.flow(): FlowSession {
+ return FlowSession(this)
+}
diff --git a/matrix-sdk-android-flow/src/main/java/org/matrix/android/sdk/flow/OptionalFlow.kt b/matrix-sdk-android-flow/src/main/java/org/matrix/android/sdk/flow/OptionalFlow.kt
new file mode 100644
index 0000000000..a9f062f379
--- /dev/null
+++ b/matrix-sdk-android-flow/src/main/java/org/matrix/android/sdk/flow/OptionalFlow.kt
@@ -0,0 +1,32 @@
+/*
+ * Copyright (c) 2021 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 org.matrix.android.sdk.flow
+
+import kotlinx.coroutines.flow.Flow
+import kotlinx.coroutines.flow.filter
+import kotlinx.coroutines.flow.map
+import org.matrix.android.sdk.api.util.Optional
+
+fun Flow>.unwrap(): Flow {
+ return filter { it.hasValue() }.map { it.get() }
+}
+
+fun Flow>.mapOptional(fn: (T) -> U?): Flow> {
+ return map {
+ it.map(fn)
+ }
+}
diff --git a/matrix-sdk-android-rx/build.gradle b/matrix-sdk-android-rx/build.gradle
index 899432b498..dbd761cee3 100644
--- a/matrix-sdk-android-rx/build.gradle
+++ b/matrix-sdk-android-rx/build.gradle
@@ -3,13 +3,11 @@ apply plugin: 'kotlin-android'
apply plugin: 'kotlin-kapt'
android {
- compileSdkVersion 30
+ compileSdk versions.compileSdk
defaultConfig {
- minSdkVersion 21
- targetSdkVersion 30
- versionCode 1
- versionName "1.0"
+ minSdk versions.minSdk
+ targetSdk versions.targetSdk
// Multidex is useful for tests
multiDexEnabled true
@@ -24,25 +22,26 @@ android {
}
compileOptions {
- sourceCompatibility JavaVersion.VERSION_1_8
- targetCompatibility JavaVersion.VERSION_1_8
+ sourceCompatibility versions.sourceCompat
+ targetCompatibility versions.targetCompat
}
kotlinOptions {
- jvmTarget = "1.8"
+ jvmTarget = "11"
}
}
dependencies {
+
implementation project(":matrix-sdk-android")
- implementation 'androidx.appcompat:appcompat:1.3.1'
- implementation 'io.reactivex.rxjava2:rxkotlin:2.4.0'
- implementation 'io.reactivex.rxjava2:rxandroid:2.1.1'
- implementation "org.jetbrains.kotlinx:kotlinx-coroutines-rx2:$kotlin_coroutines_version"
+ implementation libs.androidx.appCompat
+ implementation libs.rx.rxKotlin
+ implementation libs.rx.rxAndroid
+ implementation libs.jetbrains.coroutinesRx2
// Paging
- implementation "androidx.paging:paging-runtime-ktx:2.1.2"
+ implementation libs.androidx.pagingRuntimeKtx
// Logging
- implementation 'com.jakewharton.timber:timber:4.7.1'
+ implementation libs.jakewharton.timber
}
diff --git a/matrix-sdk-android-rx/src/main/java/org/matrix/android/sdk/rx/LiveDataObservable.kt b/matrix-sdk-android-rx/src/main/java/org/matrix/android/sdk/rx/LiveDataObservable.kt
index 2174c6f118..56b52facf9 100644
--- a/matrix-sdk-android-rx/src/main/java/org/matrix/android/sdk/rx/LiveDataObservable.kt
+++ b/matrix-sdk-android-rx/src/main/java/org/matrix/android/sdk/rx/LiveDataObservable.kt
@@ -34,8 +34,8 @@ private class LiveDataObservable(
liveData.observeForever(relay)
}
- private inner class RemoveObserverInMainThread(private val observer: io.reactivex.Observer)
- : MainThreadDisposable(), Observer {
+ private inner class RemoveObserverInMainThread(private val observer: io.reactivex.Observer) :
+ MainThreadDisposable(), Observer {
override fun onChanged(t: T?) {
if (!isDisposed) {
diff --git a/matrix-sdk-android-rx/src/main/java/org/matrix/android/sdk/rx/OptionalRx.kt b/matrix-sdk-android-rx/src/main/java/org/matrix/android/sdk/rx/OptionalRx.kt
index ff4b0d755c..936bd824e7 100644
--- a/matrix-sdk-android-rx/src/main/java/org/matrix/android/sdk/rx/OptionalRx.kt
+++ b/matrix-sdk-android-rx/src/main/java/org/matrix/android/sdk/rx/OptionalRx.kt
@@ -16,8 +16,8 @@
package org.matrix.android.sdk.rx
-import org.matrix.android.sdk.api.util.Optional
import io.reactivex.Observable
+import org.matrix.android.sdk.api.util.Optional
fun Observable>.unwrap(): Observable {
return filter { it.hasValue() }.map { it.get() }
diff --git a/matrix-sdk-android-rx/src/main/java/org/matrix/android/sdk/rx/RxSession.kt b/matrix-sdk-android-rx/src/main/java/org/matrix/android/sdk/rx/RxSession.kt
index 58fb760ff5..47203816b4 100644
--- a/matrix-sdk-android-rx/src/main/java/org/matrix/android/sdk/rx/RxSession.kt
+++ b/matrix-sdk-android-rx/src/main/java/org/matrix/android/sdk/rx/RxSession.kt
@@ -32,6 +32,7 @@ import org.matrix.android.sdk.api.session.crypto.crosssigning.SELF_SIGNING_KEY_S
import org.matrix.android.sdk.api.session.crypto.crosssigning.USER_SIGNING_KEY_SSSS_NAME
import org.matrix.android.sdk.api.session.group.GroupSummaryQueryParams
import org.matrix.android.sdk.api.session.group.model.GroupSummary
+import org.matrix.android.sdk.api.session.identity.FoundThreePid
import org.matrix.android.sdk.api.session.identity.ThreePid
import org.matrix.android.sdk.api.session.pushers.Pusher
import org.matrix.android.sdk.api.session.room.RoomSummaryQueryParams
@@ -239,6 +240,10 @@ class RxSession(private val session: Session) {
)
.distinctUntilChanged()
}
+
+ fun lookupThreePid(threePid: ThreePid): Single> = rxSingle {
+ session.identityService().lookUp(listOf(threePid)).firstOrNull().toOptional()
+ }
}
fun Session.rx(): RxSession {
diff --git a/matrix-sdk-android/build.gradle b/matrix-sdk-android/build.gradle
index fbaae97fdc..c067199f91 100644
--- a/matrix-sdk-android/build.gradle
+++ b/matrix-sdk-android/build.gradle
@@ -9,19 +9,19 @@ buildscript {
mavenCentral()
}
dependencies {
- classpath "io.realm:realm-gradle-plugin:10.6.1"
+ classpath "io.realm:realm-gradle-plugin:10.8.1"
}
}
android {
- compileSdkVersion 30
testOptions.unitTests.includeAndroidResources = true
+ compileSdk versions.compileSdk
+
defaultConfig {
- minSdkVersion 21
- targetSdkVersion 30
- versionCode 1
- versionName "0.0.1"
+ minSdk versions.minSdk
+ targetSdk versions.targetSdk
+
// Multidex is useful for tests
multiDexEnabled true
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
@@ -31,9 +31,7 @@ android {
// that the app's state is completely cleared between tests.
testInstrumentationRunnerArguments clearPackageData: 'true'
- // Seems that the build tools 4.1.0 does not generate BuildConfig.VERSION_NAME anymore.
- // Add it manually here. We may remove this trick in the future
- buildConfigField "String", "VERSION_NAME", "\"0.0.1\""
+ buildConfigField "String", "SDK_VERSION", "\"1.3.8\""
buildConfigField "String", "GIT_SDK_REVISION", "\"${gitRevision()}\""
resValue "string", "git_sdk_revision", "\"${gitRevision()}\""
@@ -46,6 +44,7 @@ android {
}
testOptions {
+ // Comment to run on Android 12
execution 'ANDROIDX_TEST_ORCHESTRATOR'
}
@@ -67,17 +66,13 @@ android {
installOptions "-g"
}
- lintOptions {
- lintConfig file("lint.xml")
- }
-
compileOptions {
- sourceCompatibility JavaVersion.VERSION_1_8
- targetCompatibility JavaVersion.VERSION_1_8
+ sourceCompatibility versions.sourceCompat
+ targetCompatibility versions.targetCompat
}
kotlinOptions {
- jvmTarget = "1.8"
+ jvmTarget = "11"
}
sourceSets {
@@ -120,95 +115,91 @@ static def gitRevisionDate() {
}
dependencies {
+ implementation libs.jetbrains.coroutinesCore
+ implementation libs.jetbrains.coroutinesAndroid
- def arrow_version = "0.8.2"
- def moshi_version = '1.12.0'
- def lifecycle_version = '2.2.0'
- def arch_version = '2.1.0'
- def markwon_version = '3.1.0'
- def daggerVersion = '2.38'
- def work_version = '2.5.0'
- def retrofit_version = '2.9.0'
+ implementation 'net.java.dev.jna:jna:5.10.0@aar'
- implementation 'net.java.dev.jna:jna:5.6.0@aar'
+ implementation libs.androidx.appCompat
+ implementation libs.androidx.core
- implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version"
- implementation "org.jetbrains.kotlinx:kotlinx-coroutines-core:$kotlin_coroutines_version"
- implementation "org.jetbrains.kotlinx:kotlinx-coroutines-android:$kotlin_coroutines_version"
-
- implementation "androidx.appcompat:appcompat:1.3.1"
- implementation "androidx.core:core-ktx:1.6.0"
-
- implementation "androidx.lifecycle:lifecycle-extensions:$lifecycle_version"
- implementation "androidx.lifecycle:lifecycle-common-java8:$lifecycle_version"
+ // Lifecycle
+ implementation libs.androidx.lifecycleCommon
+ implementation libs.androidx.lifecycleProcess
// Network
- implementation "com.squareup.retrofit2:retrofit:$retrofit_version"
- implementation "com.squareup.retrofit2:converter-moshi:$retrofit_version"
+ implementation libs.squareup.retrofit
+ implementation libs.squareup.retrofitMoshi
- implementation(platform("com.squareup.okhttp3:okhttp-bom:4.9.1"))
+ implementation(platform("com.squareup.okhttp3:okhttp-bom:4.9.2"))
implementation 'com.squareup.okhttp3:okhttp'
implementation 'com.squareup.okhttp3:logging-interceptor'
implementation 'com.squareup.okhttp3:okhttp-urlconnection'
- implementation "com.squareup.moshi:moshi-adapters:$moshi_version"
- kapt "com.squareup.moshi:moshi-kotlin-codegen:$moshi_version"
+ implementation libs.squareup.moshi
+ kapt libs.squareup.moshiKotlin
- implementation "ru.noties.markwon:core:$markwon_version"
+ implementation libs.markwon.core
// Image
- implementation 'androidx.exifinterface:exifinterface:1.3.2'
+ implementation libs.androidx.exifinterface
// Database
implementation 'com.github.Zhuinden:realm-monarchy:0.7.1'
+
kapt 'dk.ilios:realmfieldnameshelper:2.0.0'
// Work
- implementation "androidx.work:work-runtime-ktx:$work_version"
+ implementation libs.androidx.work
// FP
- implementation "io.arrow-kt:arrow-core:$arrow_version"
- implementation "io.arrow-kt:arrow-instances-core:$arrow_version"
+ implementation libs.arrow.core
+ implementation libs.arrow.instances
// olm lib is now hosted by jitpack: https://jitpack.io/#org.matrix.gitlab.matrix-org/olm
implementation 'org.matrix.gitlab.matrix-org:olm:3.2.4'
// DI
- implementation "com.google.dagger:dagger:$daggerVersion"
- kapt "com.google.dagger:dagger-compiler:$daggerVersion"
+ implementation libs.dagger.dagger
+ kapt libs.dagger.daggerCompiler
// Logging
- implementation 'com.jakewharton.timber:timber:4.7.1'
+ implementation libs.jakewharton.timber
implementation 'com.facebook.stetho:stetho-okhttp3:1.6.0'
// Video compression
- implementation 'com.otaliastudios:transcoder:0.10.3'
+ implementation 'com.otaliastudios:transcoder:0.10.4'
+
+ // Exif data handling
+ implementation libs.apache.commonsImaging
// Phone number https://github.com/google/libphonenumber
- implementation 'com.googlecode.libphonenumber:libphonenumber:8.12.28'
+ implementation 'com.googlecode.libphonenumber:libphonenumber:8.12.37'
- testImplementation 'junit:junit:4.13.2'
- testImplementation 'org.robolectric:robolectric:4.5.1'
+ testImplementation libs.tests.junit
+ testImplementation 'org.robolectric:robolectric:4.7'
//testImplementation 'org.robolectric:shadows-support-v4:3.0'
// Note: version sticks to 1.9.2 due to https://github.com/mockk/mockk/issues/281
- testImplementation 'io.mockk:mockk:1.12.0'
- testImplementation 'org.amshove.kluent:kluent-android:1.68'
- testImplementation "org.jetbrains.kotlinx:kotlinx-coroutines-android:$kotlin_coroutines_version"
+ testImplementation libs.mockk.mockk
+ testImplementation libs.tests.kluent
+ implementation libs.jetbrains.coroutinesAndroid
// Plant Timber tree for test
testImplementation 'net.lachlanmckee:timber-junit-rule:1.0.1'
+ // Transitively required for mocking realm as monarchy doesn't expose Rx
+ testImplementation libs.rx.rxKotlin
- kaptAndroidTest "com.google.dagger:dagger-compiler:$daggerVersion"
- androidTestImplementation 'androidx.test:core:1.4.0'
- androidTestImplementation 'androidx.test:runner:1.4.0'
- androidTestImplementation 'androidx.test:rules:1.4.0'
- androidTestImplementation 'androidx.test.ext:junit:1.1.3'
- androidTestImplementation 'androidx.test.espresso:espresso-core:3.4.0'
- androidTestImplementation 'org.amshove.kluent:kluent-android:1.68'
- androidTestImplementation 'io.mockk:mockk-android:1.12.0'
- androidTestImplementation "androidx.arch.core:core-testing:$arch_version"
- androidTestImplementation "org.jetbrains.kotlinx:kotlinx-coroutines-android:$kotlin_coroutines_version"
+ kaptAndroidTest libs.dagger.daggerCompiler
+ androidTestImplementation libs.androidx.testCore
+ androidTestImplementation libs.androidx.testRunner
+ androidTestImplementation libs.androidx.testRules
+ androidTestImplementation libs.androidx.junit
+ androidTestImplementation libs.androidx.espressoCore
+ androidTestImplementation libs.tests.kluent
+ androidTestImplementation libs.mockk.mockkAndroid
+ androidTestImplementation libs.androidx.coreTesting
+ androidTestImplementation libs.jetbrains.coroutinesAndroid
// Plant Timber tree for test
- androidTestImplementation 'net.lachlanmckee:timber-junit-rule:1.0.1'
+ androidTestImplementation libs.tests.timberJunitRule
- androidTestUtil 'androidx.test:orchestrator:1.4.0'
+ androidTestUtil libs.androidx.orchestrator
}
diff --git a/matrix-sdk-android/lint.xml b/matrix-sdk-android/lint.xml
deleted file mode 100644
index 134aba822b..0000000000
--- a/matrix-sdk-android/lint.xml
+++ /dev/null
@@ -1,34 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/matrix-sdk-android/src/androidTest/AndroidManifest.xml b/matrix-sdk-android/src/androidTest/AndroidManifest.xml
new file mode 100644
index 0000000000..40360fcd19
--- /dev/null
+++ b/matrix-sdk-android/src/androidTest/AndroidManifest.xml
@@ -0,0 +1,23 @@
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/InstrumentedTest.kt b/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/InstrumentedTest.kt
index 583406346e..a763766821 100644
--- a/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/InstrumentedTest.kt
+++ b/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/InstrumentedTest.kt
@@ -18,8 +18,8 @@ package org.matrix.android.sdk
import android.content.Context
import androidx.test.core.app.ApplicationProvider
-import org.matrix.android.sdk.test.shared.createTimberTestRule
import org.junit.Rule
+import org.matrix.android.sdk.test.shared.createTimberTestRule
interface InstrumentedTest {
diff --git a/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/PermalinkParserTest.kt b/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/PermalinkParserTest.kt
new file mode 100644
index 0000000000..b11a538949
--- /dev/null
+++ b/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/PermalinkParserTest.kt
@@ -0,0 +1,60 @@
+/*
+ * Copyright 2021 The Matrix.org Foundation C.I.C.
+ *
+ * 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 org.matrix.android.sdk
+
+import org.junit.Assert
+import org.junit.FixMethodOrder
+import org.junit.Test
+import org.junit.runners.MethodSorters
+import org.matrix.android.sdk.api.session.permalinks.PermalinkData
+import org.matrix.android.sdk.api.session.permalinks.PermalinkParser
+
+@FixMethodOrder(MethodSorters.JVM)
+class PermalinkParserTest {
+
+ @Test
+ fun testParseEmailInvite() {
+ val rawInvite = """
+ https://app.element.io/#/room/%21MRBNLPtFnMAazZVPMO%3Amatrix.org?email=bob%2Bspace%40example.com&signurl=https%3A%2F%2Fvector.im%2F_matrix%2Fidentity%2Fapi%2Fv1%2Fsign-ed25519%3Ftoken%3DXmOwRZnSFabCRhTywFbJWKXWVNPysOpXIbroMGaUymqkJSvHeVKRsjHajwjCYdBsvGSvHauxbKfJmOxtXldtyLnyBMLKpBQCMzyYggrdapbVIceWZBtmslOQrXLABRoe%26private_key%3DT2gq0c3kJB_8OroXVxl1pBnzHsN7V6Xn4bEBSeW1ep4&room_name=Team2&room_avatar_url=&inviter_name=hiphop5&guest_access_token=&guest_user_id=
+ """.trimIndent()
+ .replace("https://app.element.io/#/room/", "https://matrix.to/#/")
+
+ val parsedLink = PermalinkParser.parse(rawInvite)
+ Assert.assertTrue("Should be parsed as email invite but was ${parsedLink::class.java}", parsedLink is PermalinkData.RoomEmailInviteLink)
+ parsedLink as PermalinkData.RoomEmailInviteLink
+ Assert.assertEquals("!MRBNLPtFnMAazZVPMO:matrix.org", parsedLink.roomId)
+ Assert.assertEquals("XmOwRZnSFabCRhTywFbJWKXWVNPysOpXIbroMGaUymqkJSvHeVKRsjHajwjCYdBsvGSvHauxbKfJmOxtXldtyLnyBMLKpBQCMzyYggrdapbVIceWZBtmslOQrXLABRoe", parsedLink.token)
+ Assert.assertEquals("vector.im", parsedLink.identityServer)
+ Assert.assertEquals("Team2", parsedLink.roomName)
+ Assert.assertEquals("hiphop5", parsedLink.inviterName)
+ }
+
+ @Test
+ fun testParseLinkWIthEvent() {
+ val rawInvite = "https://matrix.to/#/!OGEhHVWSdvArJzumhm:matrix.org/\$xuvJUVDJnwEeVjPx029rAOZ50difpmU_5gZk_T0jGfc?via=matrix.org&via=libera.chat&via=matrix.example.io"
+
+ val parsedLink = PermalinkParser.parse(rawInvite)
+ Assert.assertTrue("Should be parsed as room link", parsedLink is PermalinkData.RoomLink)
+ parsedLink as PermalinkData.RoomLink
+ Assert.assertEquals("!OGEhHVWSdvArJzumhm:matrix.org", parsedLink.roomIdOrAlias)
+ Assert.assertEquals("\$xuvJUVDJnwEeVjPx029rAOZ50difpmU_5gZk_T0jGfc", parsedLink.eventId)
+ Assert.assertEquals(3, parsedLink.viaParameters.size)
+ Assert.assertTrue(parsedLink.viaParameters.contains("matrix.example.io"))
+ Assert.assertTrue(parsedLink.viaParameters.contains("matrix.org"))
+ Assert.assertTrue(parsedLink.viaParameters.contains("matrix.example.io"))
+ }
+}
diff --git a/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/SingleThreadCoroutineDispatcher.kt b/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/SingleThreadCoroutineDispatcher.kt
index 9942ea9db3..3e3af10799 100644
--- a/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/SingleThreadCoroutineDispatcher.kt
+++ b/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/SingleThreadCoroutineDispatcher.kt
@@ -16,9 +16,9 @@
package org.matrix.android.sdk
-import org.matrix.android.sdk.internal.util.MatrixCoroutineDispatchers
import kotlinx.coroutines.Dispatchers.Main
import kotlinx.coroutines.asCoroutineDispatcher
+import org.matrix.android.sdk.api.MatrixCoroutineDispatchers
import java.util.concurrent.Executors
internal val testCoroutineDispatchers = MatrixCoroutineDispatchers(Main, Main, Main, Main,
diff --git a/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/account/AccountCreationTest.kt b/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/account/AccountCreationTest.kt
index 5dede9dcfd..e0451bea38 100644
--- a/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/account/AccountCreationTest.kt
+++ b/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/account/AccountCreationTest.kt
@@ -16,16 +16,16 @@
package org.matrix.android.sdk.account
-import org.matrix.android.sdk.InstrumentedTest
-import org.matrix.android.sdk.common.CommonTestHelper
-import org.matrix.android.sdk.common.CryptoTestHelper
-import org.matrix.android.sdk.common.SessionTestParams
-import org.matrix.android.sdk.common.TestConstants
import org.junit.FixMethodOrder
import org.junit.Test
import org.junit.runner.RunWith
import org.junit.runners.JUnit4
import org.junit.runners.MethodSorters
+import org.matrix.android.sdk.InstrumentedTest
+import org.matrix.android.sdk.common.CommonTestHelper
+import org.matrix.android.sdk.common.CryptoTestHelper
+import org.matrix.android.sdk.common.SessionTestParams
+import org.matrix.android.sdk.common.TestConstants
@RunWith(JUnit4::class)
@FixMethodOrder(MethodSorters.JVM)
diff --git a/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/account/ChangePasswordTest.kt b/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/account/ChangePasswordTest.kt
index 103b638c39..d32bcb3fe5 100644
--- a/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/account/ChangePasswordTest.kt
+++ b/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/account/ChangePasswordTest.kt
@@ -16,17 +16,17 @@
package org.matrix.android.sdk.account
-import org.matrix.android.sdk.InstrumentedTest
-import org.matrix.android.sdk.api.failure.isInvalidPassword
-import org.matrix.android.sdk.common.CommonTestHelper
-import org.matrix.android.sdk.common.SessionTestParams
-import org.matrix.android.sdk.common.TestConstants
import org.amshove.kluent.shouldBeTrue
import org.junit.FixMethodOrder
import org.junit.Test
import org.junit.runner.RunWith
import org.junit.runners.JUnit4
import org.junit.runners.MethodSorters
+import org.matrix.android.sdk.InstrumentedTest
+import org.matrix.android.sdk.api.failure.isInvalidPassword
+import org.matrix.android.sdk.common.CommonTestHelper
+import org.matrix.android.sdk.common.SessionTestParams
+import org.matrix.android.sdk.common.TestConstants
@RunWith(JUnit4::class)
@FixMethodOrder(MethodSorters.JVM)
diff --git a/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/account/DeactivateAccountTest.kt b/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/account/DeactivateAccountTest.kt
index 01c4f8ccb3..f8d108fb73 100644
--- a/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/account/DeactivateAccountTest.kt
+++ b/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/account/DeactivateAccountTest.kt
@@ -67,9 +67,9 @@ class DeactivateAccountTest : InstrumentedTest {
val throwable = commonTestHelper.logAccountWithError(session.myUserId, TestConstants.PASSWORD)
// Test the error
- assertTrue(throwable is Failure.ServerError
- && throwable.error.code == MatrixError.M_USER_DEACTIVATED
- && throwable.error.message == "This account has been deactivated")
+ assertTrue(throwable is Failure.ServerError &&
+ throwable.error.code == MatrixError.M_USER_DEACTIVATED &&
+ throwable.error.message == "This account has been deactivated")
// Try to create an account with the deactivate account user id, it will fail (M_USER_IN_USE)
val hs = commonTestHelper.createHomeServerConfig()
@@ -95,8 +95,8 @@ class DeactivateAccountTest : InstrumentedTest {
// Test the error
accountCreationError.let {
- assertTrue(it is Failure.ServerError
- && it.error.code == MatrixError.M_USER_IN_USE)
+ assertTrue(it is Failure.ServerError &&
+ it.error.code == MatrixError.M_USER_IN_USE)
}
// No need to close the session, it has been deactivated
diff --git a/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/api/Matrix.kt b/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/api/Matrix.kt
index c439da8407..8b9b6efa11 100644
--- a/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/api/Matrix.kt
+++ b/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/api/Matrix.kt
@@ -117,7 +117,7 @@ class Matrix private constructor(context: Context, matrixConfiguration: MatrixCo
}
fun getSdkVersion(): String {
- return BuildConfig.VERSION_NAME + " (" + BuildConfig.GIT_SDK_REVISION + ")"
+ return BuildConfig.SDK_VERSION + " (" + BuildConfig.GIT_SDK_REVISION + ")"
}
}
}
diff --git a/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/common/CommonTestHelper.kt b/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/common/CommonTestHelper.kt
index 6e07223ac7..cf9b8f87c1 100644
--- a/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/common/CommonTestHelper.kt
+++ b/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/common/CommonTestHelper.kt
@@ -19,6 +19,8 @@ package org.matrix.android.sdk.common
import android.content.Context
import android.net.Uri
import androidx.lifecycle.Observer
+import androidx.test.internal.runner.junit4.statement.UiThreadStatement
+import androidx.test.internal.runner.junit4.statement.UiThreadStatement.runOnUiThread
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.GlobalScope
import kotlinx.coroutines.delay
@@ -59,13 +61,15 @@ class CommonTestHelper(context: Context) {
fun getTestInterceptor(session: Session): MockOkHttpInterceptor? = TestNetworkModule.interceptorForSession(session.sessionId) as? MockOkHttpInterceptor
init {
- Matrix.initialize(
- context,
- MatrixConfiguration(
- applicationFlavor = "TestFlavor",
- roomDisplayNameFallbackProvider = TestRoomDisplayNameFallbackProvider()
- )
- )
+ UiThreadStatement.runOnUiThread {
+ Matrix.initialize(
+ context,
+ MatrixConfiguration(
+ applicationFlavor = "TestFlavor",
+ roomDisplayNameFallbackProvider = TestRoomDisplayNameFallbackProvider()
+ )
+ )
+ }
matrix = Matrix.getInstance(context)
}
@@ -91,6 +95,7 @@ class CommonTestHelper(context: Context) {
*
* @param session the session to sync
*/
+ @Suppress("EXPERIMENTAL_API_USAGE")
fun syncSession(session: Session, timeout: Long = TestConstants.timeOutMillis) {
val lock = CountDownLatch(1)
@@ -327,6 +332,7 @@ class CommonTestHelper(context: Context) {
assertTrue(latch.await(timeout ?: TestConstants.timeOutMillis, TimeUnit.MILLISECONDS))
}
+ @Suppress("EXPERIMENTAL_API_USAGE")
fun retryPeriodicallyWithLatch(latch: CountDownLatch, condition: (() -> Boolean)) {
GlobalScope.launch {
while (true) {
diff --git a/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/common/CryptoTestHelper.kt b/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/common/CryptoTestHelper.kt
index da176491c6..a8cbc160dd 100644
--- a/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/common/CryptoTestHelper.kt
+++ b/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/common/CryptoTestHelper.kt
@@ -84,6 +84,7 @@ class CryptoTestHelper(private val mTestHelper: CommonTestHelper) {
/**
* @return alice and bob sessions
*/
+ @Suppress("EXPERIMENTAL_API_USAGE")
fun doE2ETestWithAliceAndBobInARoom(encryptedRoom: Boolean = true): CryptoTestData {
val cryptoTestData = doE2ETestWithAliceInARoom(encryptedRoom)
val aliceSession = cryptoTestData.firstSession
@@ -255,6 +256,7 @@ class CryptoTestHelper(private val mTestHelper: CommonTestHelper) {
)
}
+ @Suppress("EXPERIMENTAL_API_USAGE")
fun createDM(alice: Session, bob: Session): String {
val roomId = mTestHelper.runBlockingTest {
alice.createDirectRoom(bob.myUserId)
diff --git a/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/common/MockOkHttpInterceptor.kt b/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/common/MockOkHttpInterceptor.kt
index e7978a9cb2..b6d833a77c 100644
--- a/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/common/MockOkHttpInterceptor.kt
+++ b/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/common/MockOkHttpInterceptor.kt
@@ -15,12 +15,12 @@
*/
package org.matrix.android.sdk.common
-import org.matrix.android.sdk.internal.session.TestInterceptor
import okhttp3.Interceptor
import okhttp3.Protocol
import okhttp3.Request
import okhttp3.Response
import okhttp3.ResponseBody.Companion.toResponseBody
+import org.matrix.android.sdk.internal.session.TestInterceptor
import javax.net.ssl.HttpsURLConnection
/**
diff --git a/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/common/TestMatrixCallback.kt b/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/common/TestMatrixCallback.kt
index c2e1ec0f92..9f6d6eb136 100644
--- a/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/common/TestMatrixCallback.kt
+++ b/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/common/TestMatrixCallback.kt
@@ -17,8 +17,8 @@
package org.matrix.android.sdk.common
import androidx.annotation.CallSuper
-import org.matrix.android.sdk.api.MatrixCallback
import org.junit.Assert.fail
+import org.matrix.android.sdk.api.MatrixCallback
import timber.log.Timber
import java.util.concurrent.CountDownLatch
diff --git a/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/internal/crypto/AttachmentEncryptionTest.kt b/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/internal/crypto/AttachmentEncryptionTest.kt
index b6cb7f9e79..aaf779212b 100644
--- a/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/internal/crypto/AttachmentEncryptionTest.kt
+++ b/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/internal/crypto/AttachmentEncryptionTest.kt
@@ -26,9 +26,9 @@ import org.junit.Test
import org.junit.runner.RunWith
import org.junit.runners.MethodSorters
import org.matrix.android.sdk.internal.crypto.attachments.MXEncryptedAttachments
+import org.matrix.android.sdk.internal.crypto.attachments.toElementToDecrypt
import org.matrix.android.sdk.internal.crypto.model.rest.EncryptedFileInfo
import org.matrix.android.sdk.internal.crypto.model.rest.EncryptedFileKey
-import org.matrix.android.sdk.internal.crypto.attachments.toElementToDecrypt
import java.io.ByteArrayOutputStream
import java.io.InputStream
diff --git a/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/internal/crypto/CryptoStoreHelper.kt b/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/internal/crypto/CryptoStoreHelper.kt
index 75ccce0db9..c717c8e33f 100644
--- a/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/internal/crypto/CryptoStoreHelper.kt
+++ b/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/internal/crypto/CryptoStoreHelper.kt
@@ -16,12 +16,12 @@
package org.matrix.android.sdk.internal.crypto
+import io.realm.RealmConfiguration
import org.matrix.android.sdk.internal.crypto.store.IMXCryptoStore
import org.matrix.android.sdk.internal.crypto.store.db.RealmCryptoStore
import org.matrix.android.sdk.internal.crypto.store.db.RealmCryptoStoreModule
import org.matrix.android.sdk.internal.crypto.store.db.mapper.CrossSigningKeysMapper
import org.matrix.android.sdk.internal.di.MoshiProvider
-import io.realm.RealmConfiguration
import kotlin.random.Random
internal class CryptoStoreHelper {
diff --git a/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/internal/crypto/CryptoStoreTest.kt b/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/internal/crypto/CryptoStoreTest.kt
index 1d838b5c84..f43c425cc9 100644
--- a/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/internal/crypto/CryptoStoreTest.kt
+++ b/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/internal/crypto/CryptoStoreTest.kt
@@ -17,9 +17,6 @@
package org.matrix.android.sdk.internal.crypto
import androidx.test.ext.junit.runners.AndroidJUnit4
-import org.matrix.android.sdk.InstrumentedTest
-import org.matrix.android.sdk.internal.crypto.model.OlmSessionWrapper
-import org.matrix.android.sdk.internal.crypto.store.IMXCryptoStore
import io.realm.Realm
import org.junit.Assert.assertEquals
import org.junit.Assert.assertNotEquals
@@ -27,6 +24,9 @@ import org.junit.Assert.assertNull
import org.junit.Before
import org.junit.Test
import org.junit.runner.RunWith
+import org.matrix.android.sdk.InstrumentedTest
+import org.matrix.android.sdk.internal.crypto.model.OlmSessionWrapper
+import org.matrix.android.sdk.internal.crypto.store.IMXCryptoStore
import org.matrix.olm.OlmAccount
import org.matrix.olm.OlmManager
import org.matrix.olm.OlmSession
diff --git a/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/internal/crypto/PreShareKeysTest.kt b/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/internal/crypto/PreShareKeysTest.kt
index a2566c1414..825fba570a 100644
--- a/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/internal/crypto/PreShareKeysTest.kt
+++ b/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/internal/crypto/PreShareKeysTest.kt
@@ -50,8 +50,8 @@ class PreShareKeysTest : InstrumentedTest {
aliceSession.cryptoService().discardOutboundSession(e2eRoomID)
val preShareCount = bobSession.cryptoService().getGossipingEvents().count {
- it.senderId == aliceSession.myUserId
- && it.getClearType() == EventType.ROOM_KEY
+ it.senderId == aliceSession.myUserId &&
+ it.getClearType() == EventType.ROOM_KEY
}
assertEquals("Bob should not have receive any key from alice at this point", 0, preShareCount)
@@ -65,16 +65,16 @@ class PreShareKeysTest : InstrumentedTest {
mTestHelper.waitWithLatch { latch ->
mTestHelper.retryPeriodicallyWithLatch(latch) {
val newGossipCount = bobSession.cryptoService().getGossipingEvents().count {
- it.senderId == aliceSession.myUserId
- && it.getClearType() == EventType.ROOM_KEY
+ it.senderId == aliceSession.myUserId &&
+ it.getClearType() == EventType.ROOM_KEY
}
newGossipCount > preShareCount
}
}
val latest = bobSession.cryptoService().getGossipingEvents().lastOrNull {
- it.senderId == aliceSession.myUserId
- && it.getClearType() == EventType.ROOM_KEY
+ it.senderId == aliceSession.myUserId &&
+ it.getClearType() == EventType.ROOM_KEY
}
val content = latest?.getClearContent().toModel()
diff --git a/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/internal/crypto/gossiping/WithHeldTests.kt b/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/internal/crypto/gossiping/WithHeldTests.kt
index b2516ea2be..c939952dc9 100644
--- a/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/internal/crypto/gossiping/WithHeldTests.kt
+++ b/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/internal/crypto/gossiping/WithHeldTests.kt
@@ -18,6 +18,11 @@ package org.matrix.android.sdk.internal.crypto.gossiping
import android.util.Log
import androidx.test.ext.junit.runners.AndroidJUnit4
+import org.junit.Assert
+import org.junit.FixMethodOrder
+import org.junit.Test
+import org.junit.runner.RunWith
+import org.junit.runners.MethodSorters
import org.matrix.android.sdk.InstrumentedTest
import org.matrix.android.sdk.api.NoOpMatrixCallback
import org.matrix.android.sdk.api.extensions.tryOrNull
@@ -31,11 +36,6 @@ import org.matrix.android.sdk.common.SessionTestParams
import org.matrix.android.sdk.common.TestConstants
import org.matrix.android.sdk.internal.crypto.model.event.EncryptedEventContent
import org.matrix.android.sdk.internal.crypto.model.event.WithHeldCode
-import org.junit.Assert
-import org.junit.FixMethodOrder
-import org.junit.Test
-import org.junit.runner.RunWith
-import org.junit.runners.MethodSorters
@RunWith(AndroidJUnit4::class)
@FixMethodOrder(MethodSorters.JVM)
diff --git a/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/internal/crypto/keysbackup/KeysBackupPasswordTest.kt b/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/internal/crypto/keysbackup/KeysBackupPasswordTest.kt
index cc71f88fc0..63e74603d0 100644
--- a/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/internal/crypto/keysbackup/KeysBackupPasswordTest.kt
+++ b/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/internal/crypto/keysbackup/KeysBackupPasswordTest.kt
@@ -17,9 +17,6 @@
package org.matrix.android.sdk.internal.crypto.keysbackup
import androidx.test.ext.junit.runners.AndroidJUnit4
-import org.matrix.android.sdk.InstrumentedTest
-import org.matrix.android.sdk.api.listeners.ProgressListener
-import org.matrix.android.sdk.common.assertByteArrayNotEqual
import org.junit.Assert.assertArrayEquals
import org.junit.Assert.assertEquals
import org.junit.Assert.assertTrue
@@ -28,6 +25,9 @@ import org.junit.FixMethodOrder
import org.junit.Test
import org.junit.runner.RunWith
import org.junit.runners.MethodSorters
+import org.matrix.android.sdk.InstrumentedTest
+import org.matrix.android.sdk.api.listeners.ProgressListener
+import org.matrix.android.sdk.common.assertByteArrayNotEqual
import org.matrix.olm.OlmManager
import org.matrix.olm.OlmPkDecryption
diff --git a/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/internal/crypto/keysbackup/KeysBackupTest.kt b/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/internal/crypto/keysbackup/KeysBackupTest.kt
index 89d297c592..0785dba8b9 100644
--- a/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/internal/crypto/keysbackup/KeysBackupTest.kt
+++ b/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/internal/crypto/keysbackup/KeysBackupTest.kt
@@ -17,6 +17,16 @@
package org.matrix.android.sdk.internal.crypto.keysbackup
import androidx.test.ext.junit.runners.AndroidJUnit4
+import org.junit.Assert.assertEquals
+import org.junit.Assert.assertFalse
+import org.junit.Assert.assertNotNull
+import org.junit.Assert.assertNull
+import org.junit.Assert.assertTrue
+import org.junit.Assert.fail
+import org.junit.FixMethodOrder
+import org.junit.Test
+import org.junit.runner.RunWith
+import org.junit.runners.MethodSorters
import org.matrix.android.sdk.InstrumentedTest
import org.matrix.android.sdk.api.listeners.ProgressListener
import org.matrix.android.sdk.api.listeners.StepProgressListener
@@ -33,16 +43,6 @@ import org.matrix.android.sdk.internal.crypto.keysbackup.model.MegolmBackupCreat
import org.matrix.android.sdk.internal.crypto.keysbackup.model.rest.KeysVersion
import org.matrix.android.sdk.internal.crypto.keysbackup.model.rest.KeysVersionResult
import org.matrix.android.sdk.internal.crypto.model.ImportRoomKeysResult
-import org.junit.Assert.assertEquals
-import org.junit.Assert.assertFalse
-import org.junit.Assert.assertNotNull
-import org.junit.Assert.assertNull
-import org.junit.Assert.assertTrue
-import org.junit.Assert.fail
-import org.junit.FixMethodOrder
-import org.junit.Test
-import org.junit.runner.RunWith
-import org.junit.runners.MethodSorters
import java.util.ArrayList
import java.util.Collections
import java.util.concurrent.CountDownLatch
diff --git a/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/internal/crypto/keysbackup/KeysBackupTestHelper.kt b/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/internal/crypto/keysbackup/KeysBackupTestHelper.kt
index b6e5ae7364..a625ffc0e9 100644
--- a/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/internal/crypto/keysbackup/KeysBackupTestHelper.kt
+++ b/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/internal/crypto/keysbackup/KeysBackupTestHelper.kt
@@ -16,6 +16,7 @@
package org.matrix.android.sdk.internal.crypto.keysbackup
+import org.junit.Assert
import org.matrix.android.sdk.api.listeners.ProgressListener
import org.matrix.android.sdk.api.session.Session
import org.matrix.android.sdk.api.session.crypto.keysbackup.KeysBackupService
@@ -28,7 +29,6 @@ import org.matrix.android.sdk.common.assertListEquals
import org.matrix.android.sdk.internal.crypto.MegolmSessionData
import org.matrix.android.sdk.internal.crypto.keysbackup.model.MegolmBackupCreationInfo
import org.matrix.android.sdk.internal.crypto.keysbackup.model.rest.KeysVersion
-import org.junit.Assert
import java.util.concurrent.CountDownLatch
class KeysBackupTestHelper(
diff --git a/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/internal/crypto/keysbackup/StateObserver.kt b/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/internal/crypto/keysbackup/StateObserver.kt
index ff8ce43b55..80e54d82ec 100644
--- a/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/internal/crypto/keysbackup/StateObserver.kt
+++ b/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/internal/crypto/keysbackup/StateObserver.kt
@@ -16,11 +16,11 @@
package org.matrix.android.sdk.internal.crypto.keysbackup
+import org.junit.Assert.assertEquals
+import org.junit.Assert.assertNull
import org.matrix.android.sdk.api.session.crypto.keysbackup.KeysBackupService
import org.matrix.android.sdk.api.session.crypto.keysbackup.KeysBackupState
import org.matrix.android.sdk.api.session.crypto.keysbackup.KeysBackupStateListener
-import org.junit.Assert.assertEquals
-import org.junit.Assert.assertNull
import java.util.concurrent.CountDownLatch
/**
@@ -91,8 +91,8 @@ internal class StateObserver(private val keysBackup: KeysBackupService,
stateList.add(newState)
// Check that state transition is valid
- if (stateList.size >= 2
- && !allowedStateTransitions.contains(stateList[stateList.size - 2] to newState)) {
+ if (stateList.size >= 2 &&
+ !allowedStateTransitions.contains(stateList[stateList.size - 2] to newState)) {
// Forbidden transition detected
lastTransitionError = "Forbidden transition detected from " + stateList[stateList.size - 2] + " to " + newState
}
diff --git a/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/internal/crypto/ssss/QuadSTests.kt b/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/internal/crypto/ssss/QuadSTests.kt
index d14de30c90..b343d7334a 100644
--- a/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/internal/crypto/ssss/QuadSTests.kt
+++ b/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/internal/crypto/ssss/QuadSTests.kt
@@ -18,8 +18,20 @@ package org.matrix.android.sdk.internal.crypto.ssss
import androidx.lifecycle.Observer
import androidx.test.ext.junit.runners.AndroidJUnit4
+import kotlinx.coroutines.Dispatchers
+import kotlinx.coroutines.GlobalScope
+import kotlinx.coroutines.launch
+import kotlinx.coroutines.runBlocking
+import org.junit.Assert.assertEquals
+import org.junit.Assert.assertNotNull
+import org.junit.Assert.assertNull
+import org.junit.FixMethodOrder
+import org.junit.Test
+import org.junit.runner.RunWith
+import org.junit.runners.MethodSorters
import org.matrix.android.sdk.InstrumentedTest
import org.matrix.android.sdk.api.session.Session
+import org.matrix.android.sdk.api.session.accountdata.UserAccountDataEvent
import org.matrix.android.sdk.api.session.securestorage.EncryptedSecretContent
import org.matrix.android.sdk.api.session.securestorage.KeySigner
import org.matrix.android.sdk.api.session.securestorage.RawBytesKeySpec
@@ -33,18 +45,6 @@ import org.matrix.android.sdk.common.TestConstants
import org.matrix.android.sdk.internal.crypto.SSSS_ALGORITHM_AES_HMAC_SHA2
import org.matrix.android.sdk.internal.crypto.crosssigning.toBase64NoPadding
import org.matrix.android.sdk.internal.crypto.secrets.DefaultSharedSecretStorageService
-import org.matrix.android.sdk.api.session.accountdata.UserAccountDataEvent
-import kotlinx.coroutines.Dispatchers
-import kotlinx.coroutines.GlobalScope
-import kotlinx.coroutines.launch
-import kotlinx.coroutines.runBlocking
-import org.junit.Assert.assertEquals
-import org.junit.Assert.assertNotNull
-import org.junit.Assert.assertNull
-import org.junit.FixMethodOrder
-import org.junit.Test
-import org.junit.runner.RunWith
-import org.junit.runners.MethodSorters
import java.util.concurrent.CountDownLatch
@RunWith(AndroidJUnit4::class)
@@ -60,6 +60,7 @@ class QuadSTests : InstrumentedTest {
}
@Test
+ @Suppress("EXPERIMENTAL_API_USAGE")
fun test_Generate4SKey() {
val aliceSession = mTestHelper.createAccount(TestConstants.USER_ALICE, SessionTestParams(true))
@@ -275,6 +276,7 @@ class QuadSTests : InstrumentedTest {
mTestHelper.signOutAndClose(aliceSession)
}
+ @Suppress("EXPERIMENTAL_API_USAGE")
private fun assertAccountData(session: Session, type: String): UserAccountDataEvent {
val accountDataLock = CountDownLatch(1)
var accountData: UserAccountDataEvent? = null
diff --git a/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/internal/crypto/verification/qrcode/SharedSecretTest.kt b/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/internal/crypto/verification/qrcode/SharedSecretTest.kt
index 97b93dcf5a..9b10f9e9af 100644
--- a/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/internal/crypto/verification/qrcode/SharedSecretTest.kt
+++ b/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/internal/crypto/verification/qrcode/SharedSecretTest.kt
@@ -17,13 +17,13 @@
package org.matrix.android.sdk.internal.crypto.verification.qrcode
import androidx.test.ext.junit.runners.AndroidJUnit4
-import org.matrix.android.sdk.InstrumentedTest
import org.amshove.kluent.shouldBe
import org.amshove.kluent.shouldNotBeEqualTo
import org.junit.FixMethodOrder
import org.junit.Test
import org.junit.runner.RunWith
import org.junit.runners.MethodSorters
+import org.matrix.android.sdk.InstrumentedTest
@RunWith(AndroidJUnit4::class)
@FixMethodOrder(MethodSorters.JVM)
diff --git a/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/internal/session/room/send/MarkdownParserTest.kt b/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/internal/session/room/send/MarkdownParserTest.kt
index 94303dda08..1ed2f89977 100644
--- a/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/internal/session/room/send/MarkdownParserTest.kt
+++ b/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/internal/session/room/send/MarkdownParserTest.kt
@@ -25,6 +25,9 @@ import org.junit.Test
import org.junit.runner.RunWith
import org.junit.runners.MethodSorters
import org.matrix.android.sdk.InstrumentedTest
+import org.matrix.android.sdk.api.MatrixConfiguration
+import org.matrix.android.sdk.common.TestRoomDisplayNameFallbackProvider
+import org.matrix.android.sdk.internal.session.displayname.DisplayNameResolver
import org.matrix.android.sdk.internal.session.room.send.pills.MentionLinkSpecComparator
import org.matrix.android.sdk.internal.session.room.send.pills.TextPillsUtils
@@ -48,7 +51,14 @@ class MarkdownParserTest : InstrumentedTest {
private val markdownParser = MarkdownParser(
Parser.builder().build(),
HtmlRenderer.builder().softbreak(" ").build(),
- TextPillsUtils(MentionLinkSpecComparator())
+ TextPillsUtils(
+ MentionLinkSpecComparator(),
+ DisplayNameResolver(
+ MatrixConfiguration(
+ applicationFlavor = "TestFlavor",
+ roomDisplayNameFallbackProvider = TestRoomDisplayNameFallbackProvider()
+ )
+ ))
)
@Test
diff --git a/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/internal/util/JsonCanonicalizerTest.kt b/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/internal/util/JsonCanonicalizerTest.kt
index b5ab6589ff..d38afc6b62 100644
--- a/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/internal/util/JsonCanonicalizerTest.kt
+++ b/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/internal/util/JsonCanonicalizerTest.kt
@@ -17,10 +17,10 @@
package org.matrix.android.sdk.internal.util
import androidx.test.ext.junit.runners.AndroidJUnit4
-import org.matrix.android.sdk.InstrumentedTest
import org.junit.Assert.assertEquals
import org.junit.Test
import org.junit.runner.RunWith
+import org.matrix.android.sdk.InstrumentedTest
@RunWith(AndroidJUnit4::class)
internal class JsonCanonicalizerTest : InstrumentedTest {
diff --git a/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/session/room/timeline/TimelineBackToPreviousLastForwardTest.kt b/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/session/room/timeline/TimelineBackToPreviousLastForwardTest.kt
index 3774e6f513..7628f287c9 100644
--- a/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/session/room/timeline/TimelineBackToPreviousLastForwardTest.kt
+++ b/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/session/room/timeline/TimelineBackToPreviousLastForwardTest.kt
@@ -16,6 +16,14 @@
package org.matrix.android.sdk.session.room.timeline
+import org.amshove.kluent.shouldBeFalse
+import org.amshove.kluent.shouldBeTrue
+import org.junit.Assert.assertTrue
+import org.junit.FixMethodOrder
+import org.junit.Test
+import org.junit.runner.RunWith
+import org.junit.runners.JUnit4
+import org.junit.runners.MethodSorters
import org.matrix.android.sdk.InstrumentedTest
import org.matrix.android.sdk.api.extensions.orFalse
import org.matrix.android.sdk.api.session.events.model.EventType
@@ -26,14 +34,6 @@ import org.matrix.android.sdk.api.session.room.timeline.TimelineSettings
import org.matrix.android.sdk.common.CommonTestHelper
import org.matrix.android.sdk.common.CryptoTestHelper
import org.matrix.android.sdk.common.checkSendOrder
-import org.amshove.kluent.shouldBeFalse
-import org.amshove.kluent.shouldBeTrue
-import org.junit.Assert.assertTrue
-import org.junit.FixMethodOrder
-import org.junit.Test
-import org.junit.runner.RunWith
-import org.junit.runners.JUnit4
-import org.junit.runners.MethodSorters
import timber.log.Timber
import java.util.concurrent.CountDownLatch
@@ -111,8 +111,8 @@ class TimelineBackToPreviousLastForwardTest : InstrumentedTest {
}
// Ok, we have the 10 last messages from Alice.
- snapshot.size == 10
- && snapshot.all { it.root.content.toModel()?.body?.startsWith(messageRoot).orFalse() }
+ snapshot.size == 10 &&
+ snapshot.all { it.root.content.toModel()?.body?.startsWith(messageRoot).orFalse() }
}
bobTimeline.addListener(eventsListener)
@@ -160,10 +160,10 @@ class TimelineBackToPreviousLastForwardTest : InstrumentedTest {
}
// Bob can see the first event of the room (so Back pagination has worked)
- snapshot.lastOrNull()?.root?.getClearType() == EventType.STATE_ROOM_CREATE
+ snapshot.lastOrNull()?.root?.getClearType() == EventType.STATE_ROOM_CREATE &&
// 8 for room creation item, and 30 for the forward pagination
- && snapshot.size == 38
- && snapshot.checkSendOrder(messageRoot, 30, 0)
+ snapshot.size == 38 &&
+ snapshot.checkSendOrder(messageRoot, 30, 0)
}
bobTimeline.addListener(eventsListener)
diff --git a/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/session/room/timeline/TimelineForwardPaginationTest.kt b/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/session/room/timeline/TimelineForwardPaginationTest.kt
index f156a5eb64..dfa6ec10ae 100644
--- a/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/session/room/timeline/TimelineForwardPaginationTest.kt
+++ b/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/session/room/timeline/TimelineForwardPaginationTest.kt
@@ -16,6 +16,13 @@
package org.matrix.android.sdk.session.room.timeline
+import org.amshove.kluent.shouldBeFalse
+import org.amshove.kluent.shouldBeTrue
+import org.junit.FixMethodOrder
+import org.junit.Test
+import org.junit.runner.RunWith
+import org.junit.runners.JUnit4
+import org.junit.runners.MethodSorters
import org.matrix.android.sdk.InstrumentedTest
import org.matrix.android.sdk.api.extensions.orFalse
import org.matrix.android.sdk.api.session.events.model.EventType
@@ -26,13 +33,6 @@ import org.matrix.android.sdk.api.session.room.timeline.TimelineSettings
import org.matrix.android.sdk.common.CommonTestHelper
import org.matrix.android.sdk.common.CryptoTestHelper
import org.matrix.android.sdk.common.checkSendOrder
-import org.amshove.kluent.shouldBeFalse
-import org.amshove.kluent.shouldBeTrue
-import org.junit.FixMethodOrder
-import org.junit.Test
-import org.junit.runner.RunWith
-import org.junit.runners.JUnit4
-import org.junit.runners.MethodSorters
import timber.log.Timber
import java.util.concurrent.CountDownLatch
@@ -86,8 +86,8 @@ class TimelineForwardPaginationTest : InstrumentedTest {
}
// Ok, we have the 10 last messages of the initial sync
- snapshot.size == 10
- && snapshot.all { it.root.content.toModel()?.body?.startsWith(message).orFalse() }
+ snapshot.size == 10 &&
+ snapshot.all { it.root.content.toModel()?.body?.startsWith(message).orFalse() }
}
// Open the timeline at last sent message
@@ -110,8 +110,8 @@ class TimelineForwardPaginationTest : InstrumentedTest {
}
// The event is not in db, so it is fetch alone
- snapshot.size == 1
- && snapshot.all { it.root.content.toModel()?.body?.startsWith("Message from Alice").orFalse() }
+ snapshot.size == 1 &&
+ snapshot.all { it.root.content.toModel()?.body?.startsWith("Message from Alice").orFalse() }
}
aliceTimeline.addListener(aliceEventsListener)
@@ -137,9 +137,9 @@ class TimelineForwardPaginationTest : InstrumentedTest {
}
// Alice can see the first event of the room (so Back pagination has worked)
- snapshot.lastOrNull()?.root?.getClearType() == EventType.STATE_ROOM_CREATE
+ snapshot.lastOrNull()?.root?.getClearType() == EventType.STATE_ROOM_CREATE &&
// 6 for room creation item (backward pagination), 1 for the context, and 50 for the forward pagination
- && snapshot.size == 6 + 1 + 50
+ snapshot.size == 57 // 6 + 1 + 50
}
aliceTimeline.addListener(aliceEventsListener)
@@ -166,8 +166,8 @@ class TimelineForwardPaginationTest : InstrumentedTest {
Timber.w(" event ${it.root.content}")
}
// 6 for room creation item (backward pagination),and numberOfMessagesToSend (all the message of the room)
- snapshot.size == 6 + numberOfMessagesToSend
- && snapshot.checkSendOrder(message, numberOfMessagesToSend, 0)
+ snapshot.size == 6 + numberOfMessagesToSend &&
+ snapshot.checkSendOrder(message, numberOfMessagesToSend, 0)
}
aliceTimeline.addListener(aliceEventsListener)
diff --git a/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/session/room/timeline/TimelinePreviousLastForwardTest.kt b/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/session/room/timeline/TimelinePreviousLastForwardTest.kt
index 9ebac8766a..e865fe17da 100644
--- a/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/session/room/timeline/TimelinePreviousLastForwardTest.kt
+++ b/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/session/room/timeline/TimelinePreviousLastForwardTest.kt
@@ -16,6 +16,13 @@
package org.matrix.android.sdk.session.room.timeline
+import org.amshove.kluent.shouldBeFalse
+import org.amshove.kluent.shouldBeTrue
+import org.junit.FixMethodOrder
+import org.junit.Test
+import org.junit.runner.RunWith
+import org.junit.runners.JUnit4
+import org.junit.runners.MethodSorters
import org.matrix.android.sdk.InstrumentedTest
import org.matrix.android.sdk.api.extensions.orFalse
import org.matrix.android.sdk.api.session.events.model.EventType
@@ -26,13 +33,6 @@ import org.matrix.android.sdk.api.session.room.timeline.TimelineSettings
import org.matrix.android.sdk.common.CommonTestHelper
import org.matrix.android.sdk.common.CryptoTestHelper
import org.matrix.android.sdk.common.checkSendOrder
-import org.amshove.kluent.shouldBeFalse
-import org.amshove.kluent.shouldBeTrue
-import org.junit.FixMethodOrder
-import org.junit.Test
-import org.junit.runner.RunWith
-import org.junit.runners.JUnit4
-import org.junit.runners.MethodSorters
import timber.log.Timber
import java.util.concurrent.CountDownLatch
@@ -107,8 +107,8 @@ class TimelinePreviousLastForwardTest : InstrumentedTest {
}
// Ok, we have the 10 last messages from Alice. This will be our future previous lastForward chunk
- snapshot.size == 10
- && snapshot.all { it.root.content.toModel()?.body?.startsWith(firstMessage).orFalse() }
+ snapshot.size == 10 &&
+ snapshot.all { it.root.content.toModel()?.body?.startsWith(firstMessage).orFalse() }
}
bobTimeline.addListener(eventsListener)
@@ -141,8 +141,8 @@ class TimelinePreviousLastForwardTest : InstrumentedTest {
}
// Ok, we have the 10 last messages from Alice. This will be our future previous lastForward chunk
- snapshot.size == 10
- && snapshot.all { it.root.content.toModel()?.body?.startsWith(secondMessage).orFalse() }
+ snapshot.size == 10 &&
+ snapshot.all { it.root.content.toModel()?.body?.startsWith(secondMessage).orFalse() }
}
bobTimeline.addListener(eventsListener)
@@ -189,7 +189,7 @@ class TimelinePreviousLastForwardTest : InstrumentedTest {
Timber.w(" event ${it.root}")
}
- snapshot.size == 8 + 1 + 35
+ snapshot.size == 44 // 8 + 1 + 35
}
bobTimeline.addListener(eventsListener)
@@ -216,11 +216,11 @@ class TimelinePreviousLastForwardTest : InstrumentedTest {
}
// Bob can see the first event of the room (so Back pagination has worked)
- snapshot.lastOrNull()?.root?.getClearType() == EventType.STATE_ROOM_CREATE
+ snapshot.lastOrNull()?.root?.getClearType() == EventType.STATE_ROOM_CREATE &&
// 8 for room creation item 60 message from Alice
- && snapshot.size == 8 + 60
- && snapshot.checkSendOrder(secondMessage, 30, 0)
- && snapshot.checkSendOrder(firstMessage, 30, 30)
+ snapshot.size == 68 && // 8 + 60
+ snapshot.checkSendOrder(secondMessage, 30, 0) &&
+ snapshot.checkSendOrder(firstMessage, 30, 30)
}
bobTimeline.addListener(eventsListener)
diff --git a/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/session/space/SpaceCreationTest.kt b/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/session/space/SpaceCreationTest.kt
index a1744a0dae..5911414c25 100644
--- a/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/session/space/SpaceCreationTest.kt
+++ b/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/session/space/SpaceCreationTest.kt
@@ -28,12 +28,9 @@ import org.junit.runner.RunWith
import org.junit.runners.JUnit4
import org.junit.runners.MethodSorters
import org.matrix.android.sdk.InstrumentedTest
-import org.matrix.android.sdk.api.query.ActiveSpaceFilter
import org.matrix.android.sdk.api.session.events.model.EventType
import org.matrix.android.sdk.api.session.events.model.toModel
-import org.matrix.android.sdk.api.session.room.RoomSummaryQueryParams
import org.matrix.android.sdk.api.session.room.model.GuestAccess
-import org.matrix.android.sdk.api.session.room.model.Membership
import org.matrix.android.sdk.api.session.room.model.PowerLevelsContent
import org.matrix.android.sdk.api.session.room.model.RoomGuestAccessContent
import org.matrix.android.sdk.api.session.room.model.RoomHistoryVisibility
@@ -42,7 +39,6 @@ import org.matrix.android.sdk.api.session.room.model.RoomType
import org.matrix.android.sdk.api.session.room.model.create.CreateRoomParams
import org.matrix.android.sdk.api.session.room.model.create.CreateRoomPreset
import org.matrix.android.sdk.api.session.room.model.create.RoomCreateContent
-import org.matrix.android.sdk.api.session.room.roomSummaryQueryParams
import org.matrix.android.sdk.api.session.space.JoinSpaceResult
import org.matrix.android.sdk.common.CommonTestHelper
import org.matrix.android.sdk.common.SessionTestParams
@@ -54,6 +50,7 @@ class SpaceCreationTest : InstrumentedTest {
private val commonTestHelper = CommonTestHelper(context())
@Test
+ @Suppress("EXPERIMENTAL_API_USAGE")
fun createSimplePublicSpace() {
val session = commonTestHelper.createAccount("Hubble", SessionTestParams(true))
val roomName = "My Space"
@@ -137,6 +134,7 @@ class SpaceCreationTest : InstrumentedTest {
}
@Test
+ @Suppress("EXPERIMENTAL_API_USAGE")
fun testSimplePublicSpaceWithChildren() {
val aliceSession = commonTestHelper.createAccount("alice", SessionTestParams(true))
val bobSession = commonTestHelper.createAccount("bob", SessionTestParams(true))
@@ -162,7 +160,7 @@ class SpaceCreationTest : InstrumentedTest {
commonTestHelper.waitWithLatch {
GlobalScope.launch {
- syncedSpace?.addChildren(firstChild!!, listOf(aliceSession.sessionParams.homeServerHost ?: ""), "a", true, suggested = true)
+ syncedSpace?.addChildren(firstChild!!, listOf(aliceSession.sessionParams.homeServerHost ?: ""), "a", suggested = true)
it.countDown()
}
}
@@ -181,7 +179,7 @@ class SpaceCreationTest : InstrumentedTest {
commonTestHelper.waitWithLatch {
GlobalScope.launch {
- syncedSpace?.addChildren(secondChild!!, listOf(aliceSession.sessionParams.homeServerHost ?: ""), "b", false, suggested = true)
+ syncedSpace?.addChildren(secondChild!!, listOf(aliceSession.sessionParams.homeServerHost ?: ""), "b", suggested = true)
it.countDown()
}
}
@@ -202,19 +200,20 @@ class SpaceCreationTest : InstrumentedTest {
assertEquals("Room name should be set", roomName, spaceBobPov?.asRoom()?.roomSummary()?.name)
assertEquals("Room topic should be set", topic, spaceBobPov?.asRoom()?.roomSummary()?.topic)
+ // /!\ AUTO_JOIN has been descoped
// check if bob has joined automatically the first room
- val bobMembershipFirstRoom = bobSession.getRoomSummary(firstChild!!)?.membership
- assertEquals("Bob should have joined this room", Membership.JOIN, bobMembershipFirstRoom)
- RoomSummaryQueryParams.Builder()
-
- val childCount = bobSession.getRoomSummaries(
- roomSummaryQueryParams {
- activeSpaceFilter = ActiveSpaceFilter.ActiveSpace(spaceId)
- }
- ).size
-
- assertEquals("Unexpected number of joined children", 1, childCount)
+// val bobMembershipFirstRoom = bobSession.getRoomSummary(firstChild!!)?.membership
+// assertEquals("Bob should have joined this room", Membership.JOIN, bobMembershipFirstRoom)
+// RoomSummaryQueryParams.Builder()
+//
+// val childCount = bobSession.getRoomSummaries(
+// roomSummaryQueryParams {
+// activeSpaceFilter = ActiveSpaceFilter.ActiveSpace(spaceId)
+// }
+// ).size
+//
+// assertEquals("Unexpected number of joined children", 1, childCount)
commonTestHelper.signOutAndClose(aliceSession)
commonTestHelper.signOutAndClose(bobSession)
diff --git a/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/session/space/SpaceHierarchyTest.kt b/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/session/space/SpaceHierarchyTest.kt
index 521b5805bd..436daf001b 100644
--- a/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/session/space/SpaceHierarchyTest.kt
+++ b/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/session/space/SpaceHierarchyTest.kt
@@ -32,10 +32,19 @@ import org.junit.runners.JUnit4
import org.junit.runners.MethodSorters
import org.matrix.android.sdk.InstrumentedTest
import org.matrix.android.sdk.api.query.ActiveSpaceFilter
+import org.matrix.android.sdk.api.query.QueryStringValue
import org.matrix.android.sdk.api.session.Session
+import org.matrix.android.sdk.api.session.events.model.EventType
+import org.matrix.android.sdk.api.session.events.model.toContent
+import org.matrix.android.sdk.api.session.events.model.toModel
+import org.matrix.android.sdk.api.session.room.model.PowerLevelsContent
+import org.matrix.android.sdk.api.session.room.model.RoomJoinRulesAllowEntry
import org.matrix.android.sdk.api.session.room.model.RoomSummary
import org.matrix.android.sdk.api.session.room.model.RoomType
import org.matrix.android.sdk.api.session.room.model.create.CreateRoomParams
+import org.matrix.android.sdk.api.session.room.model.create.RestrictedRoomPreset
+import org.matrix.android.sdk.api.session.room.powerlevels.PowerLevelsHelper
+import org.matrix.android.sdk.api.session.room.powerlevels.Role
import org.matrix.android.sdk.api.session.room.roomSummaryQueryParams
import org.matrix.android.sdk.common.CommonTestHelper
import org.matrix.android.sdk.common.SessionTestParams
@@ -47,6 +56,7 @@ class SpaceHierarchyTest : InstrumentedTest {
private val commonTestHelper = CommonTestHelper(context())
@Test
+ @Suppress("EXPERIMENTAL_API_USAGE")
fun createCanonicalChildRelation() {
val session = commonTestHelper.createAccount("John", SessionTestParams(true))
val spaceName = "My Space"
@@ -171,6 +181,7 @@ class SpaceHierarchyTest : InstrumentedTest {
// }
@Test
+ @Suppress("EXPERIMENTAL_API_USAGE")
fun testFilteringBySpace() {
val session = commonTestHelper.createAccount("John", SessionTestParams(true))
@@ -179,7 +190,7 @@ class SpaceHierarchyTest : InstrumentedTest {
Triple("A2", true, true)
))
- val spaceBInfo = createPublicSpace(session, "SpaceB", listOf(
+ /* val spaceBInfo = */ createPublicSpace(session, "SpaceB", listOf(
Triple("B1", true /*auto-join*/, true/*canonical*/),
Triple("B2", true, true),
Triple("B3", true, true)
@@ -254,6 +265,7 @@ class SpaceHierarchyTest : InstrumentedTest {
}
@Test
+ @Suppress("EXPERIMENTAL_API_USAGE")
fun testBreakCycle() {
val session = commonTestHelper.createAccount("John", SessionTestParams(true))
@@ -301,6 +313,7 @@ class SpaceHierarchyTest : InstrumentedTest {
}
@Test
+ @Suppress("EXPERIMENTAL_API_USAGE")
fun testLiveFlatChildren() {
val session = commonTestHelper.createAccount("John", SessionTestParams(true))
@@ -382,6 +395,8 @@ class SpaceHierarchyTest : InstrumentedTest {
// The room should have disapear from flat children
GlobalScope.launch(Dispatchers.Main) { flatAChildren.observeForever(childObserver) }
}
+
+ commonTestHelper.signOutAndClose(session)
}
data class TestSpaceCreationResult(
@@ -389,6 +404,7 @@ class SpaceHierarchyTest : InstrumentedTest {
val roomIds: List
)
+ @Suppress("EXPERIMENTAL_API_USAGE")
private fun createPublicSpace(session: Session,
spaceName: String,
childInfo: List>
@@ -429,11 +445,62 @@ class SpaceHierarchyTest : InstrumentedTest {
return TestSpaceCreationResult(spaceId, roomIds)
}
+ @Suppress("EXPERIMENTAL_API_USAGE")
+ private fun createPrivateSpace(session: Session,
+ spaceName: String,
+ childInfo: List>
+ /** Name, auto-join, canonical*/
+ ): TestSpaceCreationResult {
+ var spaceId = ""
+ commonTestHelper.waitWithLatch {
+ GlobalScope.launch {
+ spaceId = session.spaceService().createSpace(spaceName, "My Private Space", null, false)
+ it.countDown()
+ }
+ }
+
+ val syncedSpace = session.spaceService().getSpace(spaceId)
+ val viaServers = listOf(session.sessionParams.homeServerHost ?: "")
+
+ val roomIds =
+ childInfo.map { entry ->
+ var roomId = ""
+ commonTestHelper.waitWithLatch {
+ GlobalScope.launch {
+ val homeServerCapabilities = session
+ .getHomeServerCapabilities()
+ roomId = session.createRoom(CreateRoomParams().apply {
+ name = entry.first
+ this.featurePreset = RestrictedRoomPreset(
+ homeServerCapabilities,
+ listOf(
+ RoomJoinRulesAllowEntry.restrictedToRoom(spaceId)
+ )
+ )
+ })
+ it.countDown()
+ }
+ }
+ roomId
+ }
+
+ roomIds.forEachIndexed { index, roomId ->
+ runBlocking {
+ syncedSpace!!.addChildren(roomId, viaServers, null, childInfo[index].second)
+ val canonical = childInfo[index].third
+ if (canonical != null) {
+ session.spaceService().setSpaceParent(roomId, spaceId, canonical, viaServers)
+ }
+ }
+ }
+ return TestSpaceCreationResult(spaceId, roomIds)
+ }
+
@Test
fun testRootSpaces() {
val session = commonTestHelper.createAccount("John", SessionTestParams(true))
- val spaceAInfo = createPublicSpace(session, "SpaceA", listOf(
+ /* val spaceAInfo = */ createPublicSpace(session, "SpaceA", listOf(
Triple("A1", true /*auto-join*/, true/*canonical*/),
Triple("A2", true, true)
))
@@ -468,5 +535,111 @@ class SpaceHierarchyTest : InstrumentedTest {
val rootSpaces = session.spaceService().getRootSpaceSummaries()
assertEquals("Unexpected number of root spaces ${rootSpaces.map { it.name }}", 2, rootSpaces.size)
+
+ commonTestHelper.signOutAndClose(session)
+ }
+
+ @Test
+ fun testParentRelation() {
+ val aliceSession = commonTestHelper.createAccount("Alice", SessionTestParams(true))
+ val bobSession = commonTestHelper.createAccount("Bib", SessionTestParams(true))
+
+ val spaceAInfo = createPrivateSpace(aliceSession, "Private Space A", listOf(
+ Triple("General", true /*suggested*/, true/*canonical*/),
+ Triple("Random", true, true)
+ ))
+
+ commonTestHelper.runBlockingTest {
+ aliceSession.getRoom(spaceAInfo.spaceId)!!.invite(bobSession.myUserId, null)
+ }
+
+ commonTestHelper.runBlockingTest {
+ bobSession.joinRoom(spaceAInfo.spaceId, null, emptyList())
+ }
+
+ var bobRoomId = ""
+ commonTestHelper.waitWithLatch {
+ GlobalScope.launch {
+ bobRoomId = bobSession.createRoom(CreateRoomParams().apply { name = "A Bob Room" })
+ bobSession.getRoom(bobRoomId)!!.invite(aliceSession.myUserId)
+ it.countDown()
+ }
+ }
+
+ commonTestHelper.runBlockingTest {
+ aliceSession.joinRoom(bobRoomId)
+ }
+
+ commonTestHelper.waitWithLatch { latch ->
+ commonTestHelper.retryPeriodicallyWithLatch(latch) {
+ aliceSession.getRoomSummary(bobRoomId)?.membership?.isActive() == true
+ }
+ }
+
+ commonTestHelper.waitWithLatch {
+ GlobalScope.launch {
+ bobSession.spaceService().setSpaceParent(bobRoomId, spaceAInfo.spaceId, false, listOf(bobSession.sessionParams.homeServerHost ?: ""))
+ it.countDown()
+ }
+ }
+
+ commonTestHelper.waitWithLatch { latch ->
+ commonTestHelper.retryPeriodicallyWithLatch(latch) {
+ val stateEvent = aliceSession.getRoom(bobRoomId)!!.getStateEvent(EventType.STATE_SPACE_PARENT, QueryStringValue.Equals(spaceAInfo.spaceId))
+ stateEvent != null
+ }
+ }
+
+ // This should be an invalid space parent relation, because no opposite child and bob is not admin of the space
+ commonTestHelper.runBlockingTest {
+ // we can see the state event
+ // but it is not valid and room is not in hierarchy
+ assertTrue("Bob Room should not be listed as a child of the space", aliceSession.getRoomSummary(bobRoomId)?.flattenParentIds?.isEmpty() == true)
+ }
+
+ // Let's now try to make alice admin of the room
+
+ commonTestHelper.waitWithLatch {
+ GlobalScope.launch {
+ val room = bobSession.getRoom(bobRoomId)!!
+ val currentPLContent = room
+ .getStateEvent(EventType.STATE_ROOM_POWER_LEVELS)
+ ?.let { it.content.toModel() }
+
+ val newPowerLevelsContent = currentPLContent
+ ?.setUserPowerLevel(aliceSession.myUserId, Role.Admin.value)
+ ?.toContent()
+
+ room.sendStateEvent(EventType.STATE_ROOM_POWER_LEVELS, null, newPowerLevelsContent!!)
+ it.countDown()
+ }
+ }
+
+ commonTestHelper.waitWithLatch { latch ->
+ commonTestHelper.retryPeriodicallyWithLatch(latch) {
+ val powerLevelsHelper = aliceSession.getRoom(bobRoomId)!!
+ .getStateEvent(EventType.STATE_ROOM_POWER_LEVELS)
+ ?.content
+ ?.toModel()
+ ?.let { PowerLevelsHelper(it) }
+ powerLevelsHelper!!.isUserAllowedToSend(aliceSession.myUserId, true, EventType.STATE_SPACE_PARENT)
+ }
+ }
+
+ commonTestHelper.waitWithLatch {
+ GlobalScope.launch {
+ aliceSession.spaceService().setSpaceParent(bobRoomId, spaceAInfo.spaceId, false, listOf(bobSession.sessionParams.homeServerHost ?: ""))
+ it.countDown()
+ }
+ }
+
+ commonTestHelper.waitWithLatch { latch ->
+ commonTestHelper.retryPeriodicallyWithLatch(latch) {
+ bobSession.getRoomSummary(bobRoomId)?.flattenParentIds?.contains(spaceAInfo.spaceId) == true
+ }
+ }
+
+ commonTestHelper.signOutAndClose(aliceSession)
+ commonTestHelper.signOutAndClose(bobSession)
}
}
diff --git a/matrix-sdk-android/src/debug/java/org/matrix/android/sdk/internal/network/interceptors/CurlLoggingInterceptor.kt b/matrix-sdk-android/src/debug/java/org/matrix/android/sdk/internal/network/interceptors/CurlLoggingInterceptor.kt
index 2103dc954d..3add757efa 100644
--- a/matrix-sdk-android/src/debug/java/org/matrix/android/sdk/internal/network/interceptors/CurlLoggingInterceptor.kt
+++ b/matrix-sdk-android/src/debug/java/org/matrix/android/sdk/internal/network/interceptors/CurlLoggingInterceptor.kt
@@ -17,10 +17,10 @@
package org.matrix.android.sdk.internal.network.interceptors
-import org.matrix.android.sdk.internal.di.MatrixScope
import okhttp3.Interceptor
import okhttp3.Response
import okio.Buffer
+import org.matrix.android.sdk.internal.di.MatrixScope
import timber.log.Timber
import java.io.IOException
import java.nio.charset.Charset
@@ -36,8 +36,8 @@ import javax.inject.Inject
* non-production environment.
*/
@MatrixScope
-internal class CurlLoggingInterceptor @Inject constructor()
- : Interceptor {
+internal class CurlLoggingInterceptor @Inject constructor() :
+ Interceptor {
/**
* Set any additional curl command options (see 'curl --help').
@@ -90,8 +90,8 @@ internal class CurlLoggingInterceptor @Inject constructor()
curlCmd += ((if (compressed) " --compressed " else " ") + "'" + request.url.toString()
// Replace localhost for emulator by localhost for shell
- .replace("://10.0.2.2:8080/".toRegex(), "://127.0.0.1:8080/")
- + "'")
+ .replace("://10.0.2.2:8080/".toRegex(), "://127.0.0.1:8080/") +
+ "'")
// Add Json formatting
curlCmd += " | python -m json.tool"
diff --git a/matrix-sdk-android/src/main/AndroidManifest.xml b/matrix-sdk-android/src/main/AndroidManifest.xml
index 220a168f60..de0731422c 100644
--- a/matrix-sdk-android/src/main/AndroidManifest.xml
+++ b/matrix-sdk-android/src/main/AndroidManifest.xml
@@ -10,15 +10,6 @@
-
-
-
+
-
@@ -47,6 +47,7 @@
+
diff --git a/vector/proguard-rules.pro b/vector/proguard-rules.pro
index 46fae8338c..7fd72ba895 100644
--- a/vector/proguard-rules.pro
+++ b/vector/proguard-rules.pro
@@ -64,4 +64,15 @@
-keepclassmembers class * { @com.facebook.react.uimanager.annotations.ReactPropGroup ; }
-dontwarn com.facebook.react.**
--keep,includedescriptorclasses class com.facebook.react.bridge.** { *; }
\ No newline at end of file
+-keep,includedescriptorclasses class com.facebook.react.bridge.** { *; }
+
+-keepattributes InnerClasses
+
+# JWT dependencies
+-keep class io.jsonwebtoken.** { *; }
+-keepnames class io.jsonwebtoken.* { *; }
+-keepnames interface io.jsonwebtoken.* { *; }
+
+-keep class org.bouncycastle.** { *; }
+-keepnames class org.bouncycastle.** { *; }
+-dontwarn org.bouncycastle.**
\ No newline at end of file
diff --git a/vector/src/androidTest/java/im/vector/app/EspressoExt.kt b/vector/src/androidTest/java/im/vector/app/EspressoExt.kt
index d247d88caa..fbcb9b8cb3 100644
--- a/vector/src/androidTest/java/im/vector/app/EspressoExt.kt
+++ b/vector/src/androidTest/java/im/vector/app/EspressoExt.kt
@@ -18,7 +18,10 @@ package im.vector.app
import android.app.Activity
import android.view.View
+import androidx.annotation.StringRes
+import androidx.fragment.app.FragmentActivity
import androidx.lifecycle.Observer
+import androidx.test.espresso.Espresso
import androidx.test.espresso.IdlingRegistry
import androidx.test.espresso.IdlingResource
import androidx.test.espresso.PerformException
@@ -32,6 +35,12 @@ import androidx.test.platform.app.InstrumentationRegistry.getInstrumentation
import androidx.test.runner.lifecycle.ActivityLifecycleCallback
import androidx.test.runner.lifecycle.ActivityLifecycleMonitorRegistry
import androidx.test.runner.lifecycle.Stage
+import com.adevinta.android.barista.interaction.BaristaClickInteractions
+import com.google.android.material.bottomsheet.BottomSheetBehavior
+import com.google.android.material.bottomsheet.BottomSheetDialog
+import com.google.android.material.bottomsheet.BottomSheetDialogFragment
+import im.vector.app.core.platform.VectorBaseBottomSheetDialogFragment
+import im.vector.app.espresso.tools.waitUntilViewVisible
import org.hamcrest.Matcher
import org.hamcrest.Matchers
import org.hamcrest.StringDescription
@@ -49,6 +58,18 @@ object EspressoHelper {
}
return currentActivity
}
+
+ inline fun > getBottomSheetDialog(): BottomSheetDialogFragment? {
+ return (getCurrentActivity() as? FragmentActivity)
+ ?.supportFragmentManager
+ ?.fragments
+ ?.filterIsInstance()
+ ?.firstOrNull()
+ }
+}
+
+fun getString(@StringRes id: Int): String {
+ return EspressoHelper.getCurrentActivity()!!.resources.getString(id)
}
fun waitForView(viewMatcher: Matcher, timeout: Long = 10_000, waitForDisplayed: Boolean = true): ViewAction {
@@ -70,6 +91,8 @@ fun waitForView(viewMatcher: Matcher, timeout: Long = 10_000, waitForDispl
val endTime = startTime + timeout
val visibleMatcher = isDisplayed()
+ uiController.loopMainThreadForAtLeast(100)
+
do {
println("*** waitForView loop $view end:$endTime current:${System.currentTimeMillis()}")
val viewVisible = TreeIterables.breadthFirstViewTraversal(view)
@@ -129,7 +152,7 @@ fun activityIdlingResource(activityClass: Class<*>): IdlingResource {
private var callback: IdlingResource.ResourceCallback? = null
var hasResumed = false
- private var currentActivity : Activity? = null
+ private var currentActivity: Activity? = null
val uniqTS = System.currentTimeMillis()
override fun getName() = "activityIdlingResource_${activityClass.name}_$uniqTS"
@@ -205,3 +228,52 @@ fun allSecretsKnownIdling(session: Session): IdlingResource {
return res
}
+
+fun clickOnAndGoBack(@StringRes name: Int, block: () -> Unit) {
+ BaristaClickInteractions.clickOn(name)
+ block()
+ Espresso.pressBack()
+}
+
+inline fun > interactWithSheet(contentMatcher: Matcher, noinline block: () -> Unit = {}) {
+ waitUntilViewVisible(contentMatcher)
+ val behaviour = (EspressoHelper.getBottomSheetDialog()!!.dialog as BottomSheetDialog).behavior
+ withIdlingResource(BottomSheetResource(behaviour, BottomSheetBehavior.STATE_EXPANDED), block)
+ withIdlingResource(BottomSheetResource(behaviour, BottomSheetBehavior.STATE_HIDDEN)) {}
+}
+
+class BottomSheetResource(
+ private val bottomSheetBehavior: BottomSheetBehavior<*>,
+ @BottomSheetBehavior.State private val wantedState: Int
+) : IdlingResource, BottomSheetBehavior.BottomSheetCallback() {
+
+ private var isIdle: Boolean = false
+ private var resourceCallback: IdlingResource.ResourceCallback? = null
+
+ override fun onSlide(bottomSheet: View, slideOffset: Float) {}
+
+ override fun onStateChanged(bottomSheet: View, newState: Int) {
+ val wasIdle = isIdle
+ isIdle = newState == BottomSheetBehavior.STATE_EXPANDED
+ if (!wasIdle && isIdle) {
+ bottomSheetBehavior.removeBottomSheetCallback(this)
+ resourceCallback?.onTransitionToIdle()
+ }
+ }
+
+ override fun getName() = "BottomSheet awaiting state: $wantedState"
+
+ override fun isIdleNow() = isIdle
+
+ override fun registerIdleTransitionCallback(callback: IdlingResource.ResourceCallback) {
+ resourceCallback = callback
+
+ val state = bottomSheetBehavior.state
+ isIdle = state == wantedState
+ if (isIdle) {
+ resourceCallback!!.onTransitionToIdle()
+ } else {
+ bottomSheetBehavior.addBottomSheetCallback(this)
+ }
+ }
+}
diff --git a/vector/src/androidTest/java/im/vector/app/VerificationTestBase.kt b/vector/src/androidTest/java/im/vector/app/VerificationTestBase.kt
index 285f40aaf3..47e1e43be3 100644
--- a/vector/src/androidTest/java/im/vector/app/VerificationTestBase.kt
+++ b/vector/src/androidTest/java/im/vector/app/VerificationTestBase.kt
@@ -18,7 +18,7 @@ package im.vector.app
import android.net.Uri
import androidx.lifecycle.Observer
-import im.vector.app.ui.UiTestBase
+import im.vector.app.ui.robot.OnboardingRobot
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.GlobalScope
import kotlinx.coroutines.launch
@@ -39,7 +39,7 @@ abstract class VerificationTestBase {
val password = "password"
val homeServerUrl: String = "http://10.0.2.2:8080"
- protected val uiTestBase = UiTestBase()
+ protected val uiTestBase = OnboardingRobot()
fun createAccountAndSync(matrix: Matrix,
userName: String,
@@ -107,6 +107,7 @@ abstract class VerificationTestBase {
return result!!
}
+ @Suppress("EXPERIMENTAL_API_USAGE")
private fun syncSession(session: Session) {
val lock = CountDownLatch(1)
diff --git a/vector/src/androidTest/java/im/vector/app/VerifySessionInteractiveTest.kt b/vector/src/androidTest/java/im/vector/app/VerifySessionInteractiveTest.kt
index 571bcf474c..982a421425 100644
--- a/vector/src/androidTest/java/im/vector/app/VerifySessionInteractiveTest.kt
+++ b/vector/src/androidTest/java/im/vector/app/VerifySessionInteractiveTest.kt
@@ -44,14 +44,14 @@ import org.junit.runner.RunWith
import org.matrix.android.sdk.api.Matrix
import org.matrix.android.sdk.api.auth.UIABaseAuth
import org.matrix.android.sdk.api.auth.UserInteractiveAuthInterceptor
+import org.matrix.android.sdk.api.auth.UserPasswordAuth
+import org.matrix.android.sdk.api.auth.registration.RegistrationFlowResponse
import org.matrix.android.sdk.api.session.Session
import org.matrix.android.sdk.api.session.crypto.verification.SasVerificationTransaction
import org.matrix.android.sdk.api.session.crypto.verification.VerificationMethod
import org.matrix.android.sdk.api.session.crypto.verification.VerificationService
import org.matrix.android.sdk.api.session.crypto.verification.VerificationTransaction
import org.matrix.android.sdk.api.session.crypto.verification.VerificationTxState
-import org.matrix.android.sdk.api.auth.UserPasswordAuth
-import org.matrix.android.sdk.api.auth.registration.RegistrationFlowResponse
import kotlin.coroutines.Continuation
import kotlin.coroutines.resume
diff --git a/vector/src/androidTest/java/im/vector/app/espresso/tools/EspressoPreference.kt b/vector/src/androidTest/java/im/vector/app/espresso/tools/EspressoPreference.kt
index bf60ad681f..178b9fb9f6 100644
--- a/vector/src/androidTest/java/im/vector/app/espresso/tools/EspressoPreference.kt
+++ b/vector/src/androidTest/java/im/vector/app/espresso/tools/EspressoPreference.kt
@@ -30,9 +30,9 @@ import androidx.test.espresso.matcher.ViewMatchers.withClassName
import androidx.test.espresso.matcher.ViewMatchers.withId
import androidx.test.espresso.matcher.ViewMatchers.withText
import im.vector.app.R
-import org.hamcrest.Matchers.`is`
import org.hamcrest.Matchers.allOf
import org.hamcrest.Matchers.instanceOf
+import org.hamcrest.Matchers.`is`
fun clickOnPreference(@StringRes textResId: Int) {
onView(withId(R.id.recycler_view))
diff --git a/vector/src/androidTest/java/im/vector/app/espresso/tools/ScreenshotFailureRule.kt b/vector/src/androidTest/java/im/vector/app/espresso/tools/ScreenshotFailureRule.kt
new file mode 100644
index 0000000000..2e329ebb6b
--- /dev/null
+++ b/vector/src/androidTest/java/im/vector/app/espresso/tools/ScreenshotFailureRule.kt
@@ -0,0 +1,119 @@
+/*
+ * Copyright (c) 2021 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 im.vector.app.espresso.tools
+
+import android.content.ContentResolver
+import android.content.ContentValues
+import android.graphics.Bitmap
+import android.net.Uri
+import android.os.Build
+import android.os.Environment
+import android.provider.MediaStore
+import androidx.test.platform.app.InstrumentationRegistry.getInstrumentation
+import org.junit.rules.TestWatcher
+import org.junit.runner.Description
+import timber.log.Timber
+import java.io.File
+import java.io.FileOutputStream
+import java.io.IOException
+import java.io.OutputStream
+import java.text.SimpleDateFormat
+import java.util.Date
+import java.util.Locale
+
+private val SCREENSHOT_FOLDER_LOCATION = "${Environment.DIRECTORY_PICTURES}/failure_screenshots"
+private val deviceLanguage = Locale.getDefault().language
+
+class ScreenshotFailureRule : TestWatcher() {
+ override fun failed(e: Throwable?, description: Description) {
+ val screenShotName = "$deviceLanguage-${description.methodName}-${SimpleDateFormat("EEE-MMMM-dd-HH:mm:ss").format(Date())}"
+ val bitmap = getInstrumentation().uiAutomation.takeScreenshot()
+ storeFailureScreenshot(bitmap, screenShotName)
+ }
+}
+
+/**
+ * Stores screenshots in sdcard/Pictures/failure_screenshots
+ */
+private fun storeFailureScreenshot(bitmap: Bitmap, screenshotName: String) {
+ val contentResolver = getInstrumentation().targetContext.applicationContext.contentResolver
+
+ val contentValues = ContentValues().apply {
+ put(MediaStore.Images.Media.MIME_TYPE, "image/jpeg")
+ put(MediaStore.Images.Media.DATE_TAKEN, System.currentTimeMillis())
+ }
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
+ useMediaStoreScreenshotStorage(
+ contentValues,
+ contentResolver,
+ screenshotName,
+ SCREENSHOT_FOLDER_LOCATION,
+ bitmap
+ )
+ } else {
+ usePublicExternalScreenshotStorage(
+ contentValues,
+ contentResolver,
+ screenshotName,
+ SCREENSHOT_FOLDER_LOCATION,
+ bitmap
+ )
+ }
+}
+
+private fun useMediaStoreScreenshotStorage(
+ contentValues: ContentValues,
+ contentResolver: ContentResolver,
+ screenshotName: String,
+ screenshotLocation: String,
+ bitmap: Bitmap
+) {
+ contentValues.put(MediaStore.MediaColumns.DISPLAY_NAME, "$screenshotName.jpeg")
+ contentValues.put(MediaStore.Images.Media.RELATIVE_PATH, screenshotLocation)
+ val uri: Uri? = contentResolver.insert(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, contentValues)
+ if (uri != null) {
+ contentResolver.openOutputStream(uri)?.let { saveScreenshotToStream(bitmap, it) }
+ contentResolver.update(uri, contentValues, null, null)
+ }
+}
+
+@Suppress("DEPRECATION")
+private fun usePublicExternalScreenshotStorage(
+ contentValues: ContentValues,
+ contentResolver: ContentResolver,
+ screenshotName: String,
+ screenshotLocation: String,
+ bitmap: Bitmap
+) {
+ val directory = File(Environment.getExternalStoragePublicDirectory(screenshotLocation).toString())
+ if (!directory.exists()) {
+ directory.mkdirs()
+ }
+ val file = File(directory, "$screenshotName.jpeg")
+ saveScreenshotToStream(bitmap, FileOutputStream(file))
+ contentResolver.insert(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, contentValues)
+}
+
+private fun saveScreenshotToStream(bitmap: Bitmap, outputStream: OutputStream) {
+ outputStream.use {
+ try {
+ bitmap.compress(Bitmap.CompressFormat.JPEG, 50, it)
+ } catch (e: IOException) {
+ Timber.e("Screenshot was not stored at this time")
+ }
+ }
+}
diff --git a/vector/src/androidTest/java/im/vector/app/espresso/tools/WaitActivity.kt b/vector/src/androidTest/java/im/vector/app/espresso/tools/WaitActivity.kt
index 2cdca62c74..7744d4b720 100644
--- a/vector/src/androidTest/java/im/vector/app/espresso/tools/WaitActivity.kt
+++ b/vector/src/androidTest/java/im/vector/app/espresso/tools/WaitActivity.kt
@@ -17,9 +17,18 @@
package im.vector.app.espresso.tools
import android.app.Activity
+import android.view.View
+import androidx.test.espresso.Espresso
+import androidx.test.espresso.matcher.ViewMatchers
import im.vector.app.activityIdlingResource
+import im.vector.app.waitForView
import im.vector.app.withIdlingResource
+import org.hamcrest.Matcher
-inline fun waitUntilActivityVisible(noinline block: (() -> Unit)) {
+inline fun waitUntilActivityVisible(noinline block: (() -> Unit) = {}) {
withIdlingResource(activityIdlingResource(T::class.java), block)
}
+
+fun waitUntilViewVisible(viewMatcher: Matcher) {
+ Espresso.onView(ViewMatchers.isRoot()).perform(waitForView(viewMatcher))
+}
diff --git a/vector/src/androidTest/java/im/vector/app/features/reactions/data/EmojiDataSourceTest.kt b/vector/src/androidTest/java/im/vector/app/features/reactions/data/EmojiDataSourceTest.kt
index 79090c42dd..a880b17e0c 100644
--- a/vector/src/androidTest/java/im/vector/app/features/reactions/data/EmojiDataSourceTest.kt
+++ b/vector/src/androidTest/java/im/vector/app/features/reactions/data/EmojiDataSourceTest.kt
@@ -17,6 +17,10 @@
package im.vector.app.features.reactions.data
import im.vector.app.InstrumentedTest
+import kotlinx.coroutines.CoroutineScope
+import kotlinx.coroutines.Dispatchers
+import kotlinx.coroutines.SupervisorJob
+import kotlinx.coroutines.runBlocking
import org.junit.Assert.assertEquals
import org.junit.Assert.assertTrue
import org.junit.FixMethodOrder
@@ -30,64 +34,80 @@ import kotlin.system.measureTimeMillis
@FixMethodOrder(MethodSorters.JVM)
class EmojiDataSourceTest : InstrumentedTest {
+ private val coroutineScope = CoroutineScope(SupervisorJob() + Dispatchers.Main)
+
@Test
fun checkParsingTime() {
val time = measureTimeMillis {
- EmojiDataSource(context().resources)
+ createEmojiDataSource()
}
-
assertTrue("Too long to parse", time < 100)
}
@Test
fun checkNumberOfResult() {
- val emojiDataSource = EmojiDataSource(context().resources)
- assertTrue("Wrong number of emojis", emojiDataSource.rawData.emojis.size >= 500)
- assertTrue("Wrong number of categories", emojiDataSource.rawData.categories.size >= 8)
+ val emojiDataSource = createEmojiDataSource()
+ val rawData = runBlocking {
+ emojiDataSource.rawData.await()
+ }
+ assertTrue("Wrong number of emojis", rawData.emojis.size >= 500)
+ assertTrue("Wrong number of categories", rawData.categories.size >= 8)
}
@Test
fun searchTestEmptySearch() {
- val emojiDataSource = EmojiDataSource(context().resources)
-
- assertTrue("Empty search should return at least 500 results", emojiDataSource.filterWith("").size >= 500)
+ val emojiDataSource = createEmojiDataSource()
+ val result = runBlocking {
+ emojiDataSource.filterWith("")
+ }
+ assertTrue("Empty search should return at least 500 results", result.size >= 500)
}
@Test
fun searchTestNoResult() {
- val emojiDataSource = EmojiDataSource(context().resources)
-
- assertTrue("Should not have result", emojiDataSource.filterWith("noresult").isEmpty())
+ val emojiDataSource = createEmojiDataSource()
+ val result = runBlocking {
+ emojiDataSource.filterWith("noresult")
+ }
+ assertTrue("Should not have result", result.isEmpty())
}
@Test
fun searchTestOneResult() {
- val emojiDataSource = EmojiDataSource(context().resources)
-
- assertEquals("Should have 1 result", 1, emojiDataSource.filterWith("france").size)
+ val emojiDataSource = createEmojiDataSource()
+ val result = runBlocking {
+ emojiDataSource.filterWith("france")
+ }
+ assertEquals("Should have 1 result", 1, result.size)
}
@Test
fun searchTestManyResult() {
- val emojiDataSource = EmojiDataSource(context().resources)
-
- assertTrue("Should have many result", emojiDataSource.filterWith("fra").size > 1)
+ val emojiDataSource = createEmojiDataSource()
+ val result = runBlocking {
+ emojiDataSource.filterWith("fra")
+ }
+ assertTrue("Should have many result", result.size > 1)
}
@Test
fun testTada() {
- val emojiDataSource = EmojiDataSource(context().resources)
-
- val result = emojiDataSource.filterWith("tada")
-
+ val emojiDataSource = createEmojiDataSource()
+ val result = runBlocking {
+ emojiDataSource.filterWith("tada")
+ }
assertEquals("Should find tada emoji", 1, result.size)
assertEquals("Should find tada emoji", "🎉", result[0].emoji)
}
@Test
fun testQuickReactions() {
- val emojiDataSource = EmojiDataSource(context().resources)
-
- assertEquals("Should have 8 quick reactions", 8, emojiDataSource.getQuickReactions().size)
+ val emojiDataSource = createEmojiDataSource()
+ val result = runBlocking {
+ emojiDataSource.getQuickReactions()
+ }
+ assertEquals("Should have 8 quick reactions", 8, result.size)
}
+
+ private fun createEmojiDataSource() = EmojiDataSource(coroutineScope, context().resources)
}
diff --git a/vector/src/androidTest/java/im/vector/app/ui/UiAllScreensSanityTest.kt b/vector/src/androidTest/java/im/vector/app/ui/UiAllScreensSanityTest.kt
index 26365e0c72..f998a9f23c 100644
--- a/vector/src/androidTest/java/im/vector/app/ui/UiAllScreensSanityTest.kt
+++ b/vector/src/androidTest/java/im/vector/app/ui/UiAllScreensSanityTest.kt
@@ -16,51 +16,19 @@
package im.vector.app.ui
-import android.view.View
-import androidx.recyclerview.widget.RecyclerView
-import androidx.test.espresso.Espresso.onView
-import androidx.test.espresso.Espresso.pressBack
-import androidx.test.espresso.action.ViewActions.closeSoftKeyboard
-import androidx.test.espresso.action.ViewActions.longClick
-import androidx.test.espresso.contrib.RecyclerViewActions.actionOnItem
-import androidx.test.espresso.matcher.ViewMatchers.hasDescendant
-import androidx.test.espresso.matcher.ViewMatchers.isRoot
-import androidx.test.espresso.matcher.ViewMatchers.withId
-import androidx.test.espresso.matcher.ViewMatchers.withText
import androidx.test.ext.junit.rules.ActivityScenarioRule
import androidx.test.ext.junit.runners.AndroidJUnit4
import androidx.test.filters.LargeTest
-import com.schibsted.spain.barista.assertion.BaristaListAssertions.assertListItemCount
-import com.schibsted.spain.barista.assertion.BaristaVisibilityAssertions.assertDisplayed
-import com.schibsted.spain.barista.interaction.BaristaClickInteractions.clickBack
-import com.schibsted.spain.barista.interaction.BaristaClickInteractions.clickOn
-import com.schibsted.spain.barista.interaction.BaristaClickInteractions.longClickOn
-import com.schibsted.spain.barista.interaction.BaristaDialogInteractions.clickDialogNegativeButton
-import com.schibsted.spain.barista.interaction.BaristaDialogInteractions.clickDialogPositiveButton
-import com.schibsted.spain.barista.interaction.BaristaEditTextInteractions.writeTo
-import com.schibsted.spain.barista.interaction.BaristaListInteractions.clickListItem
-import com.schibsted.spain.barista.interaction.BaristaListInteractions.clickListItemChild
-import com.schibsted.spain.barista.interaction.BaristaMenuClickInteractions.clickMenu
-import com.schibsted.spain.barista.interaction.BaristaMenuClickInteractions.openMenu
-import im.vector.app.EspressoHelper
import im.vector.app.R
-import im.vector.app.SleepViewAction
-import im.vector.app.activityIdlingResource
-import im.vector.app.espresso.tools.clickOnPreference
-import im.vector.app.espresso.tools.waitUntilActivityVisible
+import im.vector.app.espresso.tools.ScreenshotFailureRule
import im.vector.app.features.MainActivity
-import im.vector.app.features.createdirect.CreateDirectRoomActivity
-import im.vector.app.features.home.HomeActivity
-import im.vector.app.features.home.room.detail.RoomDetailActivity
-import im.vector.app.features.login.LoginActivity
-import im.vector.app.features.roomdirectory.RoomDirectoryActivity
-import im.vector.app.initialSyncIdlingResource
-import im.vector.app.waitForView
-import im.vector.app.withIdlingResource
+import im.vector.app.getString
+import im.vector.app.ui.robot.ElementRobot
+import im.vector.app.ui.robot.withDeveloperMode
import org.junit.Rule
import org.junit.Test
+import org.junit.rules.RuleChain
import org.junit.runner.RunWith
-import java.lang.Thread.sleep
import java.util.UUID
/**
@@ -71,9 +39,11 @@ import java.util.UUID
class UiAllScreensSanityTest {
@get:Rule
- val activityRule = ActivityScenarioRule(MainActivity::class.java)
+ val testRule = RuleChain
+ .outerRule(ActivityScenarioRule(MainActivity::class.java))
+ .around(ScreenshotFailureRule())
- private val uiTestBase = UiTestBase()
+ private val elementRobot = ElementRobot()
// Last passing:
// 2020-11-09
@@ -83,417 +53,63 @@ class UiAllScreensSanityTest {
fun allScreensTest() {
// Create an account
val userId = "UiTest_" + UUID.randomUUID().toString()
- uiTestBase.createAccount(userId = userId)
+ elementRobot.signUp(userId)
- withIdlingResource(activityIdlingResource(HomeActivity::class.java)) {
- assertDisplayed(R.id.roomListContainer)
- closeSoftKeyboard()
+ elementRobot.settings {
+ general { crawl() }
+ notifications { crawl() }
+ preferences { crawl() }
+ voiceAndVideo()
+ ignoredUsers()
+ securityAndPrivacy { crawl() }
+ labs()
+ advancedSettings { crawl() }
+ helpAndAbout { crawl() }
}
- val activity = EspressoHelper.getCurrentActivity()!!
- val uiSession = (activity as HomeActivity).activeSessionHolder.getActiveSession()
-
- withIdlingResource(initialSyncIdlingResource(uiSession)) {
- assertDisplayed(R.id.roomListContainer)
+ elementRobot.newDirectMessage {
+ verifyQrCodeButton()
+ verifyInviteFriendsButton()
}
- assertDisplayed(R.id.bottomNavigationView)
+ elementRobot.newRoom {
+ createNewRoom {
+ crawl()
+ createRoom {
+ val message = "Hello world!"
+ postMessage(message)
+ crawl()
+ crawlMessage(message)
+ openSettings { crawl() }
+ }
+ }
+ }
- // Settings
- navigateToSettings()
+ elementRobot.withDeveloperMode {
+ settings {
+ advancedSettings { crawlDeveloperOptions() }
+ }
+ roomList {
+ openRoom(getString(R.string.room_displayname_empty_room)) {
+ val message = "Test view source"
+ postMessage(message)
+ openMessageMenu(message) {
+ viewSource()
+ }
+ }
+ }
+ }
- // Create DM
- clickOn(R.id.bottom_action_people)
- createDm()
+ elementRobot.roomList {
+ verifyCreatedRoom()
+ }
- // Create Room
- // First navigate to the other tab
- clickOn(R.id.bottom_action_rooms)
- createRoom()
-
- assertDisplayed(R.id.bottomNavigationView)
-
- // Long click on the room
- onView(withId(R.id.roomListView))
- .perform(
- actionOnItem(
- hasDescendant(withText(R.string.room_displayname_empty_room)),
- longClick()
- )
- )
- pressBack()
-
- uiTestBase.signout()
-
- // We have sent a message in a e2e room, accept to loose it
- clickOn(R.id.exitAnywayButton)
- // Dark pattern
- clickDialogNegativeButton()
+ elementRobot.signout(expectSignOutWarning = true)
// Login again on the same account
- waitUntilActivityVisible {
- assertDisplayed(R.id.loginSplashLogo)
- }
-
- uiTestBase.login(userId)
- ignoreVerification()
-
- uiTestBase.signout()
- clickDialogPositiveButton()
-
+ elementRobot.login(userId)
+ elementRobot.dismissVerificationIfPresent()
// TODO Deactivate account instead of logout?
- }
-
- private fun ignoreVerification() {
- sleep(6000)
- val activity = EspressoHelper.getCurrentActivity()!!
-
- val popup = activity.findViewById(com.tapadoo.alerter.R.id.llAlertBackground)
- activity.runOnUiThread {
- popup.performClick()
- }
-
- assertDisplayed(R.id.bottomSheetFragmentContainer)
-
- onView(isRoot()).perform(SleepViewAction.sleep(2000))
-
- clickOn(R.string.skip)
- assertDisplayed(R.string.are_you_sure)
- clickOn(R.string.skip)
- }
-
- private fun createRoom() {
- clickOn(R.id.createGroupRoomButton)
- waitUntilActivityVisible {
- assertDisplayed(R.id.publicRoomsList)
- }
- clickOn(R.string.create_new_room)
-
- // Create
- assertListItemCount(R.id.createRoomForm, 10)
- clickListItemChild(R.id.createRoomForm, 9, R.id.form_submit_button)
-
- waitUntilActivityVisible {
- assertDisplayed(R.id.roomDetailContainer)
- }
-
- clickOn(R.id.attachmentButton)
- clickBack()
-
- // Send a message
- writeTo(R.id.composerEditText, "Hello world!")
- clickOn(R.id.sendButton)
-
- navigateToRoomSettings()
-
- // Long click on the message
- longClickOnMessageTest()
-
- // Menu
- openMenu()
- pressBack()
- clickMenu(R.id.voice_call)
- pressBack()
- clickMenu(R.id.video_call)
- pressBack()
- clickMenu(R.id.search)
- pressBack()
-
- pressBack()
- }
-
- private fun longClickOnMessageTest() {
- // Test quick reaction
- longClickOnMessage()
- // Add quick reaction
- clickOn("\uD83D\uDC4D️") // 👍
-
- sleep(1000)
-
- // Open reactions
- longClickOn("\uD83D\uDC4D️") // 👍
- pressBack()
-
- // Test add reaction
- longClickOnMessage()
- clickOn(R.string.message_add_reaction)
- // Filter
- // TODO clickMenu(R.id.search)
- clickListItem(R.id.emojiRecyclerView, 4)
-
- // Test Edit mode
- longClickOnMessage()
- clickOn(R.string.edit)
- // TODO Cancel action
- writeTo(R.id.composerEditText, "Hello universe!")
- // Wait a bit for the keyboard layout to update
- sleep(30)
- clickOn(R.id.sendButton)
- // Open edit history
- longClickOnMessage("Hello universe! (edited)")
- clickOn(R.string.message_view_edit_history)
- pressBack()
- }
-
- private fun longClickOnMessage(text: String = "Hello world!") {
- onView(withId(R.id.timelineRecyclerView))
- .perform(
- actionOnItem(
- hasDescendant(withText(text)),
- longClick()
- )
- )
- }
-
- private fun navigateToRoomSettings() {
- clickOn(R.id.roomToolbarTitleView)
- assertDisplayed(R.id.roomProfileAvatarView)
-
- // Room settings
- clickListItem(R.id.matrixProfileRecyclerView, 3)
- navigateToRoomParameters()
- pressBack()
-
- // Notifications
- clickListItem(R.id.matrixProfileRecyclerView, 5)
- pressBack()
-
- assertDisplayed(R.id.roomProfileAvatarView)
-
- // People
- clickListItem(R.id.matrixProfileRecyclerView, 7)
- assertDisplayed(R.id.inviteUsersButton)
- navigateToRoomPeople()
- // Fab
- navigateToInvite()
- pressBack()
- pressBack()
-
- assertDisplayed(R.id.roomProfileAvatarView)
-
- // Uploads
- clickListItem(R.id.matrixProfileRecyclerView, 9)
- // File tab
- clickOn(R.string.uploads_files_title)
- pressBack()
-
- assertDisplayed(R.id.roomProfileAvatarView)
-
- // Leave
- clickListItem(R.id.matrixProfileRecyclerView, 13)
- clickDialogNegativeButton()
-
- // Advanced
- // Room addresses
- clickListItem(R.id.matrixProfileRecyclerView, 15)
- onView(isRoot()).perform(waitForView(withText(R.string.room_alias_published_alias_title)))
- pressBack()
-
- // Room permissions
- clickListItem(R.id.matrixProfileRecyclerView, 17)
- onView(isRoot()).perform(waitForView(withText(R.string.room_permissions_title)))
- clickOn(R.string.room_permissions_change_room_avatar)
- clickDialogNegativeButton()
- // Toggle
- clickOn(R.string.show_advanced)
- clickOn(R.string.hide_advanced)
- pressBack()
-
- // Menu share
- // clickMenu(R.id.roomProfileShareAction)
- // pressBack()
-
- pressBack()
- }
-
- private fun navigateToRoomParameters() {
- // Room history readability
- clickListItem(R.id.roomSettingsRecyclerView, 4)
- pressBack()
-
- // Room access
- clickListItem(R.id.roomSettingsRecyclerView, 6)
- pressBack()
- }
-
- private fun navigateToInvite() {
- assertDisplayed(R.id.inviteUsersButton)
- clickOn(R.id.inviteUsersButton)
- closeSoftKeyboard()
- pressBack()
- }
-
- private fun navigateToRoomPeople() {
- // Open first user
- clickListItem(R.id.roomSettingsRecyclerView, 1)
- assertDisplayed(R.id.memberProfilePowerLevelView)
-
- // Verification
- clickListItem(R.id.matrixProfileRecyclerView, 1)
- clickBack()
-
- // Role
- clickListItem(R.id.matrixProfileRecyclerView, 3)
- clickDialogNegativeButton()
-
- clickBack()
- }
-
- private fun createDm() {
- clickOn(R.id.createChatRoomButton)
-
- withIdlingResource(activityIdlingResource(CreateDirectRoomActivity::class.java)) {
- onView(withId(R.id.userListRecyclerView))
- .perform(waitForView(withText(R.string.qr_code)))
- onView(withId(R.id.userListRecyclerView))
- .perform(waitForView(withText(R.string.invite_friends)))
- }
-
- closeSoftKeyboard()
- pressBack()
- pressBack()
- }
-
- private fun navigateToSettings() {
- clickOn(R.id.groupToolbarAvatarImageView)
- clickOn(R.id.homeDrawerHeaderSettingsView)
-
- clickOn(R.string.settings_general_title)
- navigateToSettingsGeneral()
- pressBack()
-
- clickOn(R.string.settings_notifications)
- navigateToSettingsNotifications()
- pressBack()
-
- clickOn(R.string.settings_preferences)
- navigateToSettingsPreferences()
- pressBack()
-
- clickOn(R.string.preference_voice_and_video)
- pressBack()
-
- clickOn(R.string.settings_ignored_users)
- pressBack()
-
- clickOn(R.string.settings_security_and_privacy)
- navigateToSettingsSecurity()
- pressBack()
-
- clickOn(R.string.room_settings_labs_pref_title)
- pressBack()
-
- clickOn(R.string.settings_advanced_settings)
- navigateToSettingsAdvanced()
- pressBack()
-
- clickOn(R.string.preference_root_help_about)
- navigateToSettingsHelp()
- pressBack()
-
- pressBack()
- }
-
- private fun navigateToSettingsHelp() {
- /*
- clickOn(R.string.settings_app_info_link_title)
- Cannot go back...
- pressBack()
- clickOn(R.string.settings_copyright)
- pressBack()
- clickOn(R.string.settings_app_term_conditions)
- pressBack()
- clickOn(R.string.settings_privacy_policy)
- pressBack()
- */
- clickOn(R.string.settings_third_party_notices)
- clickDialogPositiveButton()
- }
-
- private fun navigateToSettingsAdvanced() {
- clickOnPreference(R.string.settings_notifications_targets)
- pressBack()
-
- clickOnPreference(R.string.settings_push_rules)
- pressBack()
-
- /* TODO P2 test developer screens
- // Enable developer mode
- clickOnSwitchPreference("SETTINGS_DEVELOPER_MODE_PREFERENCE_KEY")
-
- clickOnPreference(R.string.settings_account_data)
- clickOn("m.push_rules")
- pressBack()
- pressBack()
- clickOnPreference(R.string.settings_key_requests)
- pressBack()
-
- // Disable developer mode
- clickOnSwitchPreference("SETTINGS_DEVELOPER_MODE_PREFERENCE_KEY")
- */
- }
-
- private fun navigateToSettingsSecurity() {
- clickOnPreference(R.string.settings_active_sessions_show_all)
- pressBack()
-
- clickOnPreference(R.string.encryption_message_recovery)
- // TODO go deeper here
- pressBack()
- /* Cannot exit
- clickOnPreference(R.string.encryption_export_e2e_room_keys)
- pressBack()
- */
- }
-
- private fun navigateToSettingsPreferences() {
- clickOn(R.string.settings_interface_language)
- onView(isRoot())
- .perform(waitForView(withText("Dansk (Danmark)")))
- pressBack()
- clickOn(R.string.settings_theme)
- clickDialogNegativeButton()
- clickOn(R.string.font_size)
- clickDialogNegativeButton()
- }
-
- private fun navigateToSettingsNotifications() {
- clickOn(R.string.settings_notification_advanced)
- pressBack()
- /*
- clickOn(R.string.settings_noisy_notifications_preferences)
- TODO Cannot go back
- pressBack()
- clickOn(R.string.settings_silent_notifications_preferences)
- pressBack()
- clickOn(R.string.settings_call_notifications_preferences)
- pressBack()
- */
- clickOnPreference(R.string.settings_notification_troubleshoot)
- pressBack()
- }
-
- private fun navigateToSettingsGeneral() {
- clickOn(R.string.settings_profile_picture)
- clickDialogPositiveButton()
- clickOn(R.string.settings_display_name)
- clickDialogNegativeButton()
- clickOn(R.string.settings_password)
- clickDialogNegativeButton()
- clickOn(R.string.settings_emails_and_phone_numbers_title)
- pressBack()
- clickOn(R.string.settings_discovery_manage)
- clickOn(R.string.add_identity_server)
- pressBack()
- pressBack()
- // Homeserver
- clickOnPreference(R.string.settings_home_server)
- pressBack()
- // Identity server
- clickOnPreference(R.string.settings_identity_server)
- pressBack()
- // Deactivate account
- clickOnPreference(R.string.settings_deactivate_my_account)
- pressBack()
+ elementRobot.signout(expectSignOutWarning = false)
}
}
diff --git a/vector/src/androidTest/java/im/vector/app/ui/robot/CreateNewRoomRobot.kt b/vector/src/androidTest/java/im/vector/app/ui/robot/CreateNewRoomRobot.kt
new file mode 100644
index 0000000000..505dfb33e9
--- /dev/null
+++ b/vector/src/androidTest/java/im/vector/app/ui/robot/CreateNewRoomRobot.kt
@@ -0,0 +1,49 @@
+/*
+ * Copyright (c) 2021 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 im.vector.app.ui.robot
+
+import androidx.test.espresso.Espresso.pressBack
+import androidx.test.espresso.matcher.ViewMatchers.withId
+import com.adevinta.android.barista.assertion.BaristaListAssertions
+import com.adevinta.android.barista.interaction.BaristaClickInteractions
+import com.adevinta.android.barista.interaction.BaristaListInteractions
+import im.vector.app.R
+import im.vector.app.espresso.tools.waitUntilActivityVisible
+import im.vector.app.espresso.tools.waitUntilViewVisible
+import im.vector.app.features.home.room.detail.RoomDetailActivity
+
+class CreateNewRoomRobot(
+ var createdRoom: Boolean = false
+) {
+
+ fun createRoom(block: RoomDetailRobot.() -> Unit) {
+ createdRoom = true
+ BaristaListAssertions.assertListItemCount(R.id.createRoomForm, 12)
+ BaristaListInteractions.clickListItemChild(R.id.createRoomForm, 11, R.id.form_submit_button)
+ waitUntilActivityVisible {
+ waitUntilViewVisible(withId(R.id.composerEditText))
+ }
+ block(RoomDetailRobot())
+ pressBack()
+ }
+
+ fun crawl() {
+ // Room access bottom sheet
+ BaristaClickInteractions.clickOn(R.string.room_settings_room_access_private_title)
+ pressBack()
+ }
+}
diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/initsync/InitialSyncProgressService.kt b/vector/src/androidTest/java/im/vector/app/ui/robot/DialogRobot.kt
similarity index 56%
rename from matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/initsync/InitialSyncProgressService.kt
rename to vector/src/androidTest/java/im/vector/app/ui/robot/DialogRobot.kt
index b5d4ef4dbb..14c2d6284e 100644
--- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/initsync/InitialSyncProgressService.kt
+++ b/vector/src/androidTest/java/im/vector/app/ui/robot/DialogRobot.kt
@@ -1,5 +1,5 @@
/*
- * Copyright 2020 The Matrix.org Foundation C.I.C.
+ * Copyright (c) 2021 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.
@@ -13,19 +13,17 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-package org.matrix.android.sdk.api.session.initsync
-import androidx.lifecycle.LiveData
+package im.vector.app.ui.robot
-interface InitialSyncProgressService {
+import com.adevinta.android.barista.interaction.BaristaDialogInteractions.clickDialogNegativeButton
- fun getInitialSyncProgressStatus(): LiveData
+class DialogRobot(
+ var returnedToPreviousScreen: Boolean = false
+) {
- sealed class Status {
- object Idle : Status()
- data class Progressing(
- val initSyncStep: InitSyncStep,
- val percentProgress: Int = 0
- ) : Status()
+ fun negativeAction() {
+ clickDialogNegativeButton()
+ returnedToPreviousScreen = true
}
}
diff --git a/vector/src/androidTest/java/im/vector/app/ui/robot/ElementRobot.kt b/vector/src/androidTest/java/im/vector/app/ui/robot/ElementRobot.kt
new file mode 100644
index 0000000000..a3bc5b26fc
--- /dev/null
+++ b/vector/src/androidTest/java/im/vector/app/ui/robot/ElementRobot.kt
@@ -0,0 +1,149 @@
+/*
+ * Copyright (c) 2021 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 im.vector.app.ui.robot
+
+import android.view.View
+import androidx.test.espresso.Espresso.pressBack
+import androidx.test.espresso.matcher.ViewMatchers
+import androidx.test.espresso.matcher.ViewMatchers.withId
+import com.adevinta.android.barista.assertion.BaristaVisibilityAssertions.assertDisplayed
+import com.adevinta.android.barista.interaction.BaristaClickInteractions.clickOn
+import com.adevinta.android.barista.interaction.BaristaDialogInteractions.clickDialogNegativeButton
+import com.adevinta.android.barista.interaction.BaristaDialogInteractions.clickDialogPositiveButton
+import com.adevinta.android.barista.interaction.BaristaDrawerInteractions.openDrawer
+import im.vector.app.EspressoHelper
+import im.vector.app.R
+import im.vector.app.espresso.tools.waitUntilActivityVisible
+import im.vector.app.espresso.tools.waitUntilViewVisible
+import im.vector.app.features.createdirect.CreateDirectRoomActivity
+import im.vector.app.features.home.HomeActivity
+import im.vector.app.features.login.LoginActivity
+import im.vector.app.initialSyncIdlingResource
+import im.vector.app.ui.robot.settings.SettingsRobot
+import im.vector.app.withIdlingResource
+import timber.log.Timber
+
+class ElementRobot {
+
+ fun signUp(userId: String) {
+ val onboardingRobot = OnboardingRobot()
+ onboardingRobot.createAccount(userId = userId)
+ waitForHome()
+ }
+
+ fun login(userId: String) {
+ val onboardingRobot = OnboardingRobot()
+ onboardingRobot.login(userId = userId)
+ waitForHome()
+ }
+
+ private fun waitForHome() {
+ waitUntilActivityVisible {
+ waitUntilViewVisible(withId(R.id.roomListContainer))
+ }
+ val activity = EspressoHelper.getCurrentActivity()!!
+ val uiSession = (activity as HomeActivity).activeSessionHolder.getActiveSession()
+ withIdlingResource(initialSyncIdlingResource(uiSession)) {
+ waitUntilViewVisible(withId(R.id.bottomNavigationView))
+ }
+ }
+
+ fun settings(block: SettingsRobot.() -> Unit) {
+ openDrawer()
+ clickOn(R.id.homeDrawerHeaderSettingsView)
+ block(SettingsRobot())
+ pressBack()
+ waitUntilViewVisible(withId(R.id.bottomNavigationView))
+ }
+
+ fun newDirectMessage(block: NewDirectMessageRobot.() -> Unit) {
+ clickOn(R.id.bottom_action_people)
+ clickOn(R.id.createChatRoomButton)
+ waitUntilActivityVisible {
+ waitUntilViewVisible(withId(R.id.userListSearch))
+ }
+ // close keyboard
+ pressBack()
+ block(NewDirectMessageRobot())
+ pressBack()
+ waitUntilViewVisible(withId(R.id.bottomNavigationView))
+ }
+
+ fun newRoom(block: NewRoomRobot.() -> Unit) {
+ clickOn(R.id.bottom_action_rooms)
+ RoomListRobot().newRoom { block() }
+ waitUntilViewVisible(withId(R.id.bottomNavigationView))
+ }
+
+ fun roomList(block: RoomListRobot.() -> Unit) {
+ clickOn(R.id.bottom_action_rooms)
+ block(RoomListRobot())
+ waitUntilViewVisible(withId(R.id.bottomNavigationView))
+ }
+
+ fun signout(expectSignOutWarning: Boolean) {
+ clickOn(R.id.groupToolbarAvatarImageView)
+ clickOn(R.id.homeDrawerHeaderSignoutView)
+
+ val isShowingSignOutWarning = kotlin.runCatching {
+ waitUntilViewVisible(withId(R.id.exitAnywayButton))
+ }.isSuccess
+
+ if (expectSignOutWarning != isShowingSignOutWarning) {
+ Timber.w("Unexpected sign out flow, expected warning to be: ${expectSignOutWarning.toWarningType()} but was ${isShowingSignOutWarning.toWarningType()}")
+ }
+
+ if (isShowingSignOutWarning) {
+ // We have sent a message in a e2e room, accept to loose it
+ clickOn(R.id.exitAnywayButton)
+ // Dark pattern
+ waitUntilViewVisible(withId(android.R.id.button2))
+ clickDialogNegativeButton()
+ } else {
+ waitUntilViewVisible(withId(android.R.id.button1))
+ clickDialogPositiveButton()
+ }
+
+ waitUntilActivityVisible {
+ assertDisplayed(R.id.loginSplashLogo)
+ }
+ }
+
+ fun dismissVerificationIfPresent() {
+ kotlin.runCatching {
+ Thread.sleep(6000)
+ val activity = EspressoHelper.getCurrentActivity()!!
+ val popup = activity.findViewById(com.tapadoo.alerter.R.id.llAlertBackground)!!
+ activity.runOnUiThread { popup.performClick() }
+
+ waitUntilViewVisible(withId(R.id.bottomSheetFragmentContainer))
+ waitUntilViewVisible(ViewMatchers.withText(R.string.skip))
+ clickOn(R.string.skip)
+ assertDisplayed(R.string.are_you_sure)
+ clickOn(R.string.skip)
+ waitUntilViewVisible(withId(R.id.bottomSheetFragmentContainer))
+ }.onFailure { Timber.w("Verification popup missing", it) }
+ }
+}
+
+private fun Boolean.toWarningType() = if (this) "shown" else "skipped"
+
+fun ElementRobot.withDeveloperMode(block: ElementRobot.() -> Unit) {
+ settings { toggleDeveloperMode() }
+ block()
+ settings { toggleDeveloperMode() }
+}
diff --git a/vector/src/androidTest/java/im/vector/app/ui/robot/MessageMenuRobot.kt b/vector/src/androidTest/java/im/vector/app/ui/robot/MessageMenuRobot.kt
new file mode 100644
index 0000000000..fd579c0d9f
--- /dev/null
+++ b/vector/src/androidTest/java/im/vector/app/ui/robot/MessageMenuRobot.kt
@@ -0,0 +1,60 @@
+/*
+ * Copyright (c) 2021 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 im.vector.app.ui.robot
+
+import androidx.test.espresso.Espresso.pressBack
+import com.adevinta.android.barista.interaction.BaristaClickInteractions.clickOn
+import com.adevinta.android.barista.interaction.BaristaListInteractions.clickListItem
+import im.vector.app.R
+import java.lang.Thread.sleep
+
+class MessageMenuRobot(
+ var autoClosed: Boolean = false
+) {
+
+ fun viewSource() {
+ clickOn(R.string.view_source)
+ // wait for library
+ sleep(1000)
+ pressBack()
+ autoClosed = true
+ }
+
+ fun editHistory() {
+ clickOn(R.string.message_view_edit_history)
+ pressBack()
+ autoClosed = true
+ }
+
+ fun addQuickReaction(quickReaction: String) {
+ clickOn(quickReaction)
+ autoClosed = true
+ }
+
+ fun addReactionFromEmojiPicker() {
+ clickOn(R.string.message_add_reaction)
+ // Wait for emoji to load, it's async now
+ sleep(2000)
+ clickListItem(R.id.emojiRecyclerView, 4)
+ autoClosed = true
+ }
+
+ fun edit() {
+ clickOn(R.string.edit)
+ autoClosed = true
+ }
+}
diff --git a/vector/src/androidTest/java/im/vector/app/ui/robot/NewDirectMessageRobot.kt b/vector/src/androidTest/java/im/vector/app/ui/robot/NewDirectMessageRobot.kt
new file mode 100644
index 0000000000..34c43c73f7
--- /dev/null
+++ b/vector/src/androidTest/java/im/vector/app/ui/robot/NewDirectMessageRobot.kt
@@ -0,0 +1,35 @@
+/*
+ * Copyright (c) 2021 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 im.vector.app.ui.robot
+
+import androidx.test.espresso.Espresso
+import androidx.test.espresso.matcher.ViewMatchers
+import im.vector.app.R
+import im.vector.app.waitForView
+
+class NewDirectMessageRobot {
+
+ fun verifyQrCodeButton() {
+ Espresso.onView(ViewMatchers.withId(R.id.userListRecyclerView))
+ .perform(waitForView(ViewMatchers.withText(R.string.qr_code)))
+ }
+
+ fun verifyInviteFriendsButton() {
+ Espresso.onView(ViewMatchers.withId(R.id.userListRecyclerView))
+ .perform(waitForView(ViewMatchers.withText(R.string.invite_friends)))
+ }
+}
diff --git a/vector/src/androidTest/java/im/vector/app/ui/robot/NewRoomRobot.kt b/vector/src/androidTest/java/im/vector/app/ui/robot/NewRoomRobot.kt
new file mode 100644
index 0000000000..09ff1162c0
--- /dev/null
+++ b/vector/src/androidTest/java/im/vector/app/ui/robot/NewRoomRobot.kt
@@ -0,0 +1,39 @@
+/*
+ * Copyright (c) 2021 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 im.vector.app.ui.robot
+
+import androidx.test.espresso.Espresso.pressBack
+import androidx.test.espresso.matcher.ViewMatchers.withId
+import com.adevinta.android.barista.interaction.BaristaClickInteractions.clickOn
+import im.vector.app.R
+import im.vector.app.espresso.tools.waitUntilViewVisible
+
+class NewRoomRobot(
+ var createdRoom: Boolean = false
+) {
+
+ fun createNewRoom(block: CreateNewRoomRobot.() -> Unit) {
+ clickOn(R.string.create_new_room)
+ waitUntilViewVisible(withId(R.id.createRoomForm))
+ val createNewRoomRobot = CreateNewRoomRobot()
+ block(createNewRoomRobot)
+ createdRoom = createNewRoomRobot.createdRoom
+ if (!createNewRoomRobot.createdRoom) {
+ pressBack()
+ }
+ }
+}
diff --git a/vector/src/androidTest/java/im/vector/app/ui/UiTestBase.kt b/vector/src/androidTest/java/im/vector/app/ui/robot/OnboardingRobot.kt
similarity index 76%
rename from vector/src/androidTest/java/im/vector/app/ui/UiTestBase.kt
rename to vector/src/androidTest/java/im/vector/app/ui/robot/OnboardingRobot.kt
index ed174b50a2..fef5d4a1a2 100644
--- a/vector/src/androidTest/java/im/vector/app/ui/UiTestBase.kt
+++ b/vector/src/androidTest/java/im/vector/app/ui/robot/OnboardingRobot.kt
@@ -14,23 +14,22 @@
* limitations under the License.
*/
-package im.vector.app.ui
+package im.vector.app.ui.robot
import androidx.test.espresso.Espresso.closeSoftKeyboard
import androidx.test.espresso.Espresso.onView
import androidx.test.espresso.matcher.ViewMatchers.isRoot
import androidx.test.espresso.matcher.ViewMatchers.withId
-import com.schibsted.spain.barista.assertion.BaristaEnabledAssertions.assertDisabled
-import com.schibsted.spain.barista.assertion.BaristaEnabledAssertions.assertEnabled
-import com.schibsted.spain.barista.assertion.BaristaVisibilityAssertions.assertDisplayed
-import com.schibsted.spain.barista.interaction.BaristaClickInteractions.clickOn
-import com.schibsted.spain.barista.interaction.BaristaEditTextInteractions.writeTo
+import com.adevinta.android.barista.assertion.BaristaEnabledAssertions.assertDisabled
+import com.adevinta.android.barista.assertion.BaristaEnabledAssertions.assertEnabled
+import com.adevinta.android.barista.assertion.BaristaVisibilityAssertions.assertDisplayed
+import com.adevinta.android.barista.interaction.BaristaClickInteractions.clickOn
+import com.adevinta.android.barista.interaction.BaristaEditTextInteractions.writeTo
import im.vector.app.R
-import im.vector.app.espresso.tools.waitUntilActivityVisible
-import im.vector.app.features.home.HomeActivity
import im.vector.app.waitForView
-class UiTestBase {
+class OnboardingRobot {
+
fun createAccount(userId: String, password: String = "password", homeServerUrl: String = "http://10.0.2.2:8080") {
initSession(true, userId, password, homeServerUrl)
}
@@ -76,15 +75,5 @@ class UiTestBase {
closeSoftKeyboard()
clickOn(R.id.loginSubmit)
-
- // Wait
- waitUntilActivityVisible {
- assertDisplayed(R.id.homeDetailFragmentContainer)
- }
- }
-
- fun signout() {
- clickOn(R.id.groupToolbarAvatarImageView)
- clickOn(R.id.homeDrawerHeaderSignoutView)
}
}
diff --git a/vector/src/androidTest/java/im/vector/app/ui/robot/RoomDetailRobot.kt b/vector/src/androidTest/java/im/vector/app/ui/robot/RoomDetailRobot.kt
new file mode 100644
index 0000000000..24fe5adf64
--- /dev/null
+++ b/vector/src/androidTest/java/im/vector/app/ui/robot/RoomDetailRobot.kt
@@ -0,0 +1,120 @@
+/*
+ * Copyright (c) 2021 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 im.vector.app.ui.robot
+
+import androidx.recyclerview.widget.RecyclerView
+import androidx.test.espresso.Espresso.onView
+import androidx.test.espresso.Espresso.pressBack
+import androidx.test.espresso.action.ViewActions
+import androidx.test.espresso.contrib.RecyclerViewActions
+import androidx.test.espresso.matcher.ViewMatchers
+import androidx.test.espresso.matcher.ViewMatchers.withId
+import androidx.test.espresso.matcher.ViewMatchers.withText
+import com.adevinta.android.barista.interaction.BaristaClickInteractions
+import com.adevinta.android.barista.interaction.BaristaClickInteractions.clickOn
+import com.adevinta.android.barista.interaction.BaristaClickInteractions.longClickOn
+import com.adevinta.android.barista.interaction.BaristaEditTextInteractions.writeTo
+import com.adevinta.android.barista.interaction.BaristaMenuClickInteractions.clickMenu
+import com.adevinta.android.barista.interaction.BaristaMenuClickInteractions.openMenu
+import im.vector.app.R
+import im.vector.app.espresso.tools.waitUntilViewVisible
+import im.vector.app.features.home.room.detail.timeline.action.MessageActionsBottomSheet
+import im.vector.app.features.reactions.data.EmojiDataSource
+import im.vector.app.interactWithSheet
+import im.vector.app.waitForView
+import java.lang.Thread.sleep
+
+class RoomDetailRobot {
+
+ fun postMessage(content: String) {
+ writeTo(R.id.composerEditText, content)
+ waitUntilViewVisible(withId(R.id.sendButton))
+ clickOn(R.id.sendButton)
+ waitUntilViewVisible(withText(content))
+ }
+
+ fun crawl() {
+ clickOn(R.id.attachmentButton)
+ BaristaClickInteractions.clickBack()
+
+ // Menu
+ openMenu()
+ pressBack()
+ clickMenu(R.id.voice_call)
+ pressBack()
+ clickMenu(R.id.video_call)
+ pressBack()
+ clickMenu(R.id.search)
+ pressBack()
+ }
+
+ fun crawlMessage(message: String) {
+ // Test quick reaction
+ val quickReaction = EmojiDataSource.quickEmojis[0] // 👍
+ openMessageMenu(message) {
+ addQuickReaction(quickReaction)
+ }
+ // Open reactions
+ longClickOn(quickReaction)
+ // wait for bottom sheet
+ pressBack()
+ // Test add reaction
+ openMessageMenu(message) {
+ addReactionFromEmojiPicker()
+ }
+ // Test Edit mode
+ openMessageMenu(message) {
+ edit()
+ }
+ // TODO Cancel action
+ writeTo(R.id.composerEditText, "Hello universe!")
+ // Wait a bit for the keyboard layout to update
+ waitUntilViewVisible(withId(R.id.sendButton))
+ clickOn(R.id.sendButton)
+ // Wait for the UI to update
+ waitUntilViewVisible(withText("Hello universe! (edited)"))
+ // Open edit history
+ openMessageMenu("Hello universe! (edited)") {
+ editHistory()
+ }
+ }
+
+ fun openMessageMenu(message: String, block: MessageMenuRobot.() -> Unit) {
+ onView(withId(R.id.timelineRecyclerView))
+ .perform(
+ RecyclerViewActions.actionOnItem(
+ ViewMatchers.hasDescendant(ViewMatchers.withText(message)),
+ ViewActions.longClick()
+ )
+ )
+ interactWithSheet(contentMatcher = withId(R.id.bottomSheetRecyclerView)) {
+ val messageMenuRobot = MessageMenuRobot()
+ block(messageMenuRobot)
+ if (!messageMenuRobot.autoClosed) {
+ pressBack()
+ }
+ }
+ }
+
+ fun openSettings(block: RoomSettingsRobot.() -> Unit) {
+ clickOn(R.id.roomToolbarTitleView)
+ waitForView(withId(R.id.roomProfileAvatarView))
+ sleep(1000)
+ block(RoomSettingsRobot())
+ pressBack()
+ }
+}
diff --git a/vector/src/androidTest/java/im/vector/app/ui/robot/RoomListRobot.kt b/vector/src/androidTest/java/im/vector/app/ui/robot/RoomListRobot.kt
new file mode 100644
index 0000000000..dc07f06202
--- /dev/null
+++ b/vector/src/androidTest/java/im/vector/app/ui/robot/RoomListRobot.kt
@@ -0,0 +1,62 @@
+/*
+ * Copyright (c) 2021 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 im.vector.app.ui.robot
+
+import androidx.recyclerview.widget.RecyclerView
+import androidx.test.espresso.Espresso.onView
+import androidx.test.espresso.Espresso.pressBack
+import androidx.test.espresso.action.ViewActions
+import androidx.test.espresso.contrib.RecyclerViewActions
+import androidx.test.espresso.matcher.ViewMatchers
+import androidx.test.espresso.matcher.ViewMatchers.withText
+import com.adevinta.android.barista.assertion.BaristaVisibilityAssertions
+import com.adevinta.android.barista.interaction.BaristaClickInteractions.clickOn
+import im.vector.app.R
+import im.vector.app.espresso.tools.waitUntilActivityVisible
+import im.vector.app.features.roomdirectory.RoomDirectoryActivity
+
+class RoomListRobot {
+
+ fun openRoom(roomName: String, block: RoomDetailRobot.() -> Unit) {
+ clickOn(roomName)
+ block(RoomDetailRobot())
+ pressBack()
+ }
+
+ fun verifyCreatedRoom() {
+ onView(ViewMatchers.withId(R.id.roomListView))
+ .perform(
+ RecyclerViewActions.actionOnItem(
+ ViewMatchers.hasDescendant(withText(R.string.room_displayname_empty_room)),
+ ViewActions.longClick()
+ )
+ )
+ pressBack()
+ }
+
+ fun newRoom(block: NewRoomRobot.() -> Unit) {
+ clickOn(R.id.createGroupRoomButton)
+ waitUntilActivityVisible {
+ BaristaVisibilityAssertions.assertDisplayed(R.id.publicRoomsList)
+ }
+ val newRoomRobot = NewRoomRobot()
+ block(newRoomRobot)
+ if (!newRoomRobot.createdRoom) {
+ pressBack()
+ }
+ }
+}
diff --git a/vector/src/androidTest/java/im/vector/app/ui/robot/RoomSettingsRobot.kt b/vector/src/androidTest/java/im/vector/app/ui/robot/RoomSettingsRobot.kt
new file mode 100644
index 0000000000..15186fe0c8
--- /dev/null
+++ b/vector/src/androidTest/java/im/vector/app/ui/robot/RoomSettingsRobot.kt
@@ -0,0 +1,143 @@
+/*
+ * Copyright (c) 2021 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 im.vector.app.ui.robot
+
+import androidx.test.espresso.Espresso.pressBack
+import androidx.test.espresso.action.ViewActions
+import androidx.test.espresso.matcher.ViewMatchers.withId
+import androidx.test.espresso.matcher.ViewMatchers.withText
+import com.adevinta.android.barista.assertion.BaristaVisibilityAssertions.assertDisplayed
+import com.adevinta.android.barista.interaction.BaristaClickInteractions.clickOn
+import com.adevinta.android.barista.interaction.BaristaDialogInteractions.clickDialogNegativeButton
+import com.adevinta.android.barista.interaction.BaristaListInteractions.clickListItem
+import im.vector.app.R
+import im.vector.app.espresso.tools.waitUntilActivityVisible
+import im.vector.app.espresso.tools.waitUntilViewVisible
+import im.vector.app.features.roommemberprofile.RoomMemberProfileActivity
+
+class RoomSettingsRobot {
+
+ fun crawl() {
+ // Room settings
+ clickListItem(R.id.matrixProfileRecyclerView, 3)
+ navigateToRoomParameters()
+ pressBack()
+
+ // Notifications
+ clickListItem(R.id.matrixProfileRecyclerView, 5)
+ pressBack()
+
+ assertDisplayed(R.id.roomProfileAvatarView)
+
+ // People
+ clickListItem(R.id.matrixProfileRecyclerView, 7)
+ assertDisplayed(R.id.inviteUsersButton)
+ navigateToRoomPeople()
+ // Fab
+ navigateToInvite()
+ pressBack()
+ pressBack()
+
+ assertDisplayed(R.id.roomProfileAvatarView)
+
+ // Uploads
+ clickListItem(R.id.matrixProfileRecyclerView, 9)
+ // File tab
+ clickOn(R.string.uploads_files_title)
+ waitUntilViewVisible(withText(R.string.uploads_media_title))
+ pressBack()
+ waitUntilViewVisible(withId(R.id.matrixProfileRecyclerView))
+
+ assertDisplayed(R.id.roomProfileAvatarView)
+
+ // Leave
+ leaveRoom {
+ negativeAction()
+ }
+
+ // Advanced
+ // Room addresses
+
+ clickListItem(R.id.matrixProfileRecyclerView, 15)
+ waitUntilViewVisible(withText(R.string.room_alias_published_alias_title))
+ pressBack()
+
+ // Room permissions
+ clickListItem(R.id.matrixProfileRecyclerView, 17)
+ waitUntilViewVisible(withText(R.string.room_permissions_title))
+ clickOn(R.string.room_permissions_change_room_avatar)
+ waitUntilViewVisible(withId(android.R.id.button2))
+ clickDialogNegativeButton()
+ waitUntilViewVisible(withText(R.string.room_permissions_title))
+ // Toggle
+ clickOn(R.string.show_advanced)
+ clickOn(R.string.hide_advanced)
+ pressBack()
+
+ // Menu share
+ // clickMenu(R.id.roomProfileShareAction)
+ // pressBack()
+ }
+
+ private fun leaveRoom(block: DialogRobot.() -> Unit) {
+ clickListItem(R.id.matrixProfileRecyclerView, 13)
+ waitUntilViewVisible(withId(android.R.id.button2))
+ val dialogRobot = DialogRobot()
+ block(dialogRobot)
+ if (dialogRobot.returnedToPreviousScreen) {
+ waitUntilViewVisible(withId(R.id.matrixProfileRecyclerView))
+ }
+ }
+
+ private fun navigateToRoomParameters() {
+ // Room history readability
+ clickListItem(R.id.roomSettingsRecyclerView, 4)
+ pressBack()
+
+ // Room access
+ clickListItem(R.id.roomSettingsRecyclerView, 6)
+ pressBack()
+ }
+
+ private fun navigateToInvite() {
+ assertDisplayed(R.id.inviteUsersButton)
+ clickOn(R.id.inviteUsersButton)
+ ViewActions.closeSoftKeyboard()
+ pressBack()
+ }
+
+ private fun navigateToRoomPeople() {
+ // Open first user
+ clickListItem(R.id.roomSettingsRecyclerView, 1)
+ waitUntilActivityVisible {
+ waitUntilViewVisible(withId(R.id.memberProfilePowerLevelView))
+ }
+
+ // Verification
+ clickListItem(R.id.matrixProfileRecyclerView, 1)
+ waitUntilViewVisible(withId(R.id.bottomSheetRecyclerView))
+ pressBack()
+ waitUntilViewVisible(withId(R.id.matrixProfileRecyclerView))
+
+ // Role
+ clickListItem(R.id.matrixProfileRecyclerView, 3)
+ waitUntilViewVisible(withId(android.R.id.button2))
+ clickDialogNegativeButton()
+ waitUntilViewVisible(withId(R.id.matrixProfileRecyclerView))
+ pressBack()
+ }
+}
diff --git a/vector/src/androidTest/java/im/vector/app/ui/robot/settings/SettingsAdvancedRobot.kt b/vector/src/androidTest/java/im/vector/app/ui/robot/settings/SettingsAdvancedRobot.kt
new file mode 100644
index 0000000000..4aeb8903dd
--- /dev/null
+++ b/vector/src/androidTest/java/im/vector/app/ui/robot/settings/SettingsAdvancedRobot.kt
@@ -0,0 +1,49 @@
+/*
+ * Copyright (c) 2021 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 im.vector.app.ui.robot.settings
+
+import androidx.test.espresso.Espresso.pressBack
+import androidx.test.espresso.matcher.ViewMatchers.withText
+import com.adevinta.android.barista.interaction.BaristaClickInteractions.clickOn
+import im.vector.app.R
+import im.vector.app.espresso.tools.clickOnPreference
+import im.vector.app.espresso.tools.waitUntilViewVisible
+
+class SettingsAdvancedRobot {
+
+ fun crawl() {
+ clickOnPreference(R.string.settings_notifications_targets)
+ pressBack()
+
+ clickOnPreference(R.string.settings_push_rules)
+ pressBack()
+ }
+
+ fun toggleDeveloperMode() {
+ clickOn(R.string.settings_developer_mode_summary)
+ }
+
+ fun crawlDeveloperOptions() {
+ clickOnPreference(R.string.settings_account_data)
+ waitUntilViewVisible(withText("m.push_rules"))
+ clickOn("m.push_rules")
+ pressBack()
+ pressBack()
+ clickOnPreference(R.string.settings_key_requests)
+ pressBack()
+ }
+}
diff --git a/vector/src/androidTest/java/im/vector/app/ui/robot/settings/SettingsGeneralRobot.kt b/vector/src/androidTest/java/im/vector/app/ui/robot/settings/SettingsGeneralRobot.kt
new file mode 100644
index 0000000000..9082eaa889
--- /dev/null
+++ b/vector/src/androidTest/java/im/vector/app/ui/robot/settings/SettingsGeneralRobot.kt
@@ -0,0 +1,51 @@
+/*
+ * Copyright (c) 2021 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 im.vector.app.ui.robot.settings
+
+import androidx.test.espresso.Espresso.pressBack
+import com.adevinta.android.barista.interaction.BaristaClickInteractions.clickOn
+import com.adevinta.android.barista.interaction.BaristaDialogInteractions.clickDialogNegativeButton
+import com.adevinta.android.barista.interaction.BaristaDialogInteractions.clickDialogPositiveButton
+import im.vector.app.R
+import im.vector.app.espresso.tools.clickOnPreference
+
+class SettingsGeneralRobot {
+
+ fun crawl() {
+ clickOn(R.string.settings_profile_picture)
+ clickDialogPositiveButton()
+ clickOn(R.string.settings_display_name)
+ clickDialogNegativeButton()
+ clickOn(R.string.settings_password)
+ clickDialogNegativeButton()
+ clickOn(R.string.settings_emails_and_phone_numbers_title)
+ pressBack()
+ clickOn(R.string.settings_discovery_manage)
+ clickOn(R.string.add_identity_server)
+ pressBack()
+ pressBack()
+ // Homeserver
+ clickOnPreference(R.string.settings_home_server)
+ pressBack()
+ // Identity server
+ clickOnPreference(R.string.settings_identity_server)
+ pressBack()
+ // Deactivate account
+ clickOnPreference(R.string.settings_deactivate_my_account)
+ pressBack()
+ }
+}
diff --git a/vector/src/androidTest/java/im/vector/app/ui/robot/settings/SettingsHelpRobot.kt b/vector/src/androidTest/java/im/vector/app/ui/robot/settings/SettingsHelpRobot.kt
new file mode 100644
index 0000000000..75f610d016
--- /dev/null
+++ b/vector/src/androidTest/java/im/vector/app/ui/robot/settings/SettingsHelpRobot.kt
@@ -0,0 +1,40 @@
+/*
+ * Copyright (c) 2021 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 im.vector.app.ui.robot.settings
+
+import com.adevinta.android.barista.interaction.BaristaClickInteractions.clickOn
+import com.adevinta.android.barista.interaction.BaristaDialogInteractions.clickDialogPositiveButton
+import im.vector.app.R
+
+class SettingsHelpRobot {
+
+ fun crawl() {
+ /*
+ clickOn(R.string.settings_app_info_link_title)
+ Cannot go back...
+ pressBack()
+ clickOn(R.string.settings_copyright)
+ pressBack()
+ clickOn(R.string.settings_app_term_conditions)
+ pressBack()
+ clickOn(R.string.settings_privacy_policy)
+ pressBack()
+ */
+ clickOn(R.string.settings_third_party_notices)
+ clickDialogPositiveButton()
+ }
+}
diff --git a/vector/src/androidTest/java/im/vector/app/ui/robot/settings/SettingsNotificationsRobot.kt b/vector/src/androidTest/java/im/vector/app/ui/robot/settings/SettingsNotificationsRobot.kt
new file mode 100644
index 0000000000..448552ba8e
--- /dev/null
+++ b/vector/src/androidTest/java/im/vector/app/ui/robot/settings/SettingsNotificationsRobot.kt
@@ -0,0 +1,52 @@
+/*
+ * Copyright (c) 2021 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 im.vector.app.ui.robot.settings
+
+import androidx.test.espresso.Espresso.pressBack
+import com.adevinta.android.barista.interaction.BaristaClickInteractions.clickOn
+import im.vector.app.BuildConfig
+import im.vector.app.R
+import im.vector.app.espresso.tools.clickOnPreference
+
+class SettingsNotificationsRobot {
+
+ fun crawl() {
+ if (BuildConfig.USE_NOTIFICATION_SETTINGS_V2) {
+ clickOn(R.string.settings_notification_default)
+ pressBack()
+ clickOn(R.string.settings_notification_mentions_and_keywords)
+ // TODO Test adding a keyword?
+ pressBack()
+ clickOn(R.string.settings_notification_other)
+ pressBack()
+ } else {
+ clickOn(R.string.settings_notification_advanced)
+ pressBack()
+ }
+ /*
+ clickOn(R.string.settings_noisy_notifications_preferences)
+ TODO Cannot go back
+ pressBack()
+ clickOn(R.string.settings_silent_notifications_preferences)
+ pressBack()
+ clickOn(R.string.settings_call_notifications_preferences)
+ pressBack()
+ */
+ clickOnPreference(R.string.settings_notification_troubleshoot)
+ pressBack()
+ }
+}
diff --git a/vector/src/androidTest/java/im/vector/app/ui/robot/settings/SettingsPreferencesRobot.kt b/vector/src/androidTest/java/im/vector/app/ui/robot/settings/SettingsPreferencesRobot.kt
new file mode 100644
index 0000000000..438bbac5a5
--- /dev/null
+++ b/vector/src/androidTest/java/im/vector/app/ui/robot/settings/SettingsPreferencesRobot.kt
@@ -0,0 +1,37 @@
+/*
+ * Copyright (c) 2021 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 im.vector.app.ui.robot.settings
+
+import androidx.test.espresso.Espresso.pressBack
+import androidx.test.espresso.matcher.ViewMatchers.withText
+import com.adevinta.android.barista.interaction.BaristaClickInteractions.clickOn
+import com.adevinta.android.barista.interaction.BaristaDialogInteractions.clickDialogNegativeButton
+import im.vector.app.R
+import im.vector.app.espresso.tools.waitUntilViewVisible
+
+class SettingsPreferencesRobot {
+
+ fun crawl() {
+ clickOn(R.string.settings_interface_language)
+ waitUntilViewVisible(withText("Dansk (Danmark)"))
+ pressBack()
+ clickOn(R.string.settings_theme)
+ clickDialogNegativeButton()
+ clickOn(R.string.font_size)
+ clickDialogNegativeButton()
+ }
+}
diff --git a/vector/src/androidTest/java/im/vector/app/ui/robot/settings/SettingsRobot.kt b/vector/src/androidTest/java/im/vector/app/ui/robot/settings/SettingsRobot.kt
new file mode 100644
index 0000000000..a9c053f6c3
--- /dev/null
+++ b/vector/src/androidTest/java/im/vector/app/ui/robot/settings/SettingsRobot.kt
@@ -0,0 +1,67 @@
+/*
+ * Copyright (c) 2021 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 im.vector.app.ui.robot.settings
+
+import im.vector.app.R
+import im.vector.app.clickOnAndGoBack
+
+class SettingsRobot {
+
+ fun toggleDeveloperMode() {
+ advancedSettings {
+ toggleDeveloperMode()
+ }
+ }
+
+ fun general(block: SettingsGeneralRobot.() -> Unit) {
+ clickOnAndGoBack(R.string.settings_general_title) { block(SettingsGeneralRobot()) }
+ }
+
+ fun notifications(block: SettingsNotificationsRobot.() -> Unit) {
+ clickOnAndGoBack(R.string.settings_notifications) { block(SettingsNotificationsRobot()) }
+ }
+
+ fun preferences(block: SettingsPreferencesRobot.() -> Unit) {
+ clickOnAndGoBack(R.string.settings_preferences) { block(SettingsPreferencesRobot()) }
+ }
+
+ fun voiceAndVideo(block: () -> Unit = {}) {
+ clickOnAndGoBack(R.string.preference_voice_and_video) { block() }
+ }
+
+ fun ignoredUsers(block: () -> Unit = {}) {
+ clickOnAndGoBack(R.string.settings_ignored_users) { block() }
+ }
+
+ fun securityAndPrivacy(block: SettingsSecurityRobot.() -> Unit) {
+ clickOnAndGoBack(R.string.settings_security_and_privacy) { block(SettingsSecurityRobot()) }
+ }
+
+ fun labs(block: () -> Unit = {}) {
+ clickOnAndGoBack(R.string.room_settings_labs_pref_title) { block() }
+ }
+
+ fun advancedSettings(block: SettingsAdvancedRobot.() -> Unit) {
+ clickOnAndGoBack(R.string.settings_advanced_settings) {
+ block(SettingsAdvancedRobot())
+ }
+ }
+
+ fun helpAndAbout(block: SettingsHelpRobot.() -> Unit) {
+ clickOnAndGoBack(R.string.preference_root_help_about) { block(SettingsHelpRobot()) }
+ }
+}
diff --git a/vector/src/androidTest/java/im/vector/app/ui/robot/settings/SettingsSecurityRobot.kt b/vector/src/androidTest/java/im/vector/app/ui/robot/settings/SettingsSecurityRobot.kt
new file mode 100644
index 0000000000..f2607bbc1c
--- /dev/null
+++ b/vector/src/androidTest/java/im/vector/app/ui/robot/settings/SettingsSecurityRobot.kt
@@ -0,0 +1,37 @@
+/*
+ * Copyright (c) 2021 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 im.vector.app.ui.robot.settings
+
+import androidx.test.espresso.Espresso
+import im.vector.app.R
+import im.vector.app.espresso.tools.clickOnPreference
+
+class SettingsSecurityRobot {
+
+ fun crawl() {
+ clickOnPreference(R.string.settings_active_sessions_show_all)
+ Espresso.pressBack()
+
+ clickOnPreference(R.string.encryption_message_recovery)
+ // TODO go deeper here
+ Espresso.pressBack()
+ /* Cannot exit
+ clickOnPreference(R.string.encryption_export_e2e_room_keys)
+ pressBack()
+ */
+ }
+}
diff --git a/vector/src/debug/java/im/vector/app/features/debug/DebugMenuActivity.kt b/vector/src/debug/java/im/vector/app/features/debug/DebugMenuActivity.kt
index 4b5228d199..960994b169 100644
--- a/vector/src/debug/java/im/vector/app/features/debug/DebugMenuActivity.kt
+++ b/vector/src/debug/java/im/vector/app/features/debug/DebugMenuActivity.kt
@@ -24,9 +24,9 @@ import android.os.Build
import androidx.core.app.NotificationCompat
import androidx.core.app.Person
import androidx.core.content.getSystemService
+import dagger.hilt.android.AndroidEntryPoint
import im.vector.app.R
import im.vector.app.core.di.ActiveSessionHolder
-import im.vector.app.core.di.ScreenComponent
import im.vector.app.core.extensions.registerStartForActivityResult
import im.vector.app.core.platform.VectorBaseActivity
import im.vector.app.core.utils.PERMISSIONS_FOR_TAKING_PHOTO
@@ -50,6 +50,7 @@ import org.matrix.android.sdk.internal.crypto.verification.qrcode.toQrCodeData
import timber.log.Timber
import javax.inject.Inject
+@AndroidEntryPoint
class DebugMenuActivity : VectorBaseActivity() {
override fun getBinding() = ActivityDebugMenuBinding.inflate(layoutInflater)
@@ -57,10 +58,6 @@ class DebugMenuActivity : VectorBaseActivity() {
@Inject
lateinit var activeSessionHolder: ActiveSessionHolder
- override fun injectWith(injector: ScreenComponent) {
- injector.inject(this)
- }
-
private lateinit var buffer: ByteArray
override fun initUiAndData() {
@@ -235,8 +232,8 @@ class DebugMenuActivity : VectorBaseActivity() {
private val qrStartForActivityResult = registerStartForActivityResult { activityResult ->
if (activityResult.resultCode == Activity.RESULT_OK) {
- toast("QrCode: " + QrCodeScannerActivity.getResultText(activityResult.data)
- + " is QRCode: " + QrCodeScannerActivity.getResultIsQrCode(activityResult.data))
+ toast("QrCode: " + QrCodeScannerActivity.getResultText(activityResult.data) +
+ " is QRCode: " + QrCodeScannerActivity.getResultIsQrCode(activityResult.data))
// Also update the current QR Code (reverse operation)
// renderQrCode(QrCodeScannerActivity.getResultText(data) ?: "")
diff --git a/vector/src/debug/java/im/vector/app/features/debug/DebugPermissionActivity.kt b/vector/src/debug/java/im/vector/app/features/debug/DebugPermissionActivity.kt
index 048c64bc3a..a35bb40f8f 100644
--- a/vector/src/debug/java/im/vector/app/features/debug/DebugPermissionActivity.kt
+++ b/vector/src/debug/java/im/vector/app/features/debug/DebugPermissionActivity.kt
@@ -22,6 +22,7 @@ import android.os.Build
import android.widget.Toast
import androidx.core.app.ActivityCompat
import androidx.core.content.ContextCompat
+import dagger.hilt.android.AndroidEntryPoint
import im.vector.app.R
import im.vector.app.core.platform.VectorBaseActivity
import im.vector.app.core.utils.checkPermissions
@@ -31,6 +32,7 @@ import im.vector.app.core.utils.registerForPermissionsResult
import im.vector.app.databinding.ActivityDebugPermissionBinding
import timber.log.Timber
+@AndroidEntryPoint
class DebugPermissionActivity : VectorBaseActivity() {
override fun getBinding() = ActivityDebugPermissionBinding.inflate(layoutInflater)
diff --git a/vector/src/debug/java/im/vector/app/features/debug/sas/SasEmojiItem.kt b/vector/src/debug/java/im/vector/app/features/debug/sas/SasEmojiItem.kt
index 408aebb186..a7b74f3b59 100644
--- a/vector/src/debug/java/im/vector/app/features/debug/sas/SasEmojiItem.kt
+++ b/vector/src/debug/java/im/vector/app/features/debug/sas/SasEmojiItem.kt
@@ -23,9 +23,9 @@ import com.airbnb.epoxy.EpoxyAttribute
import com.airbnb.epoxy.EpoxyModelClass
import im.vector.app.core.epoxy.VectorEpoxyHolder
import im.vector.app.core.epoxy.VectorEpoxyModel
-import org.matrix.android.sdk.api.session.crypto.verification.EmojiRepresentation
import me.gujun.android.span.image
import me.gujun.android.span.span
+import org.matrix.android.sdk.api.session.crypto.verification.EmojiRepresentation
@EpoxyModelClass(layout = im.vector.app.R.layout.item_sas_emoji)
abstract class SasEmojiItem : VectorEpoxyModel() {
diff --git a/vector/src/fdroid/AndroidManifest.xml b/vector/src/fdroid/AndroidManifest.xml
index 3a7c107138..ea9fa023ab 100644
--- a/vector/src/fdroid/AndroidManifest.xml
+++ b/vector/src/fdroid/AndroidManifest.xml
@@ -1,9 +1,11 @@
+
$event")
- }
- } else {
- if (notifiableEvent is NotifiableMessageEvent) {
- if (notifiableEvent.senderName.isNullOrEmpty()) {
- notifiableEvent.senderName = data["sender_display_name"] ?: data["sender"] ?: ""
- }
- if (notifiableEvent.roomName.isNullOrEmpty()) {
- notifiableEvent.roomName = findRoomNameBestEffort(data, session) ?: ""
- }
- }
-
- notifiableEvent.isPushGatewayEvent = true
- notifiableEvent.matrixID = session.myUserId
- notificationDrawerManager.onNotifiableEventReceived(notifiableEvent)
- notificationDrawerManager.refreshNotificationDrawer()
- }
- }
- }
-
- private fun findRoomNameBestEffort(data: Map, session: Session?): String? {
- var roomName: String? = data["room_name"]
- val roomId = data["room_id"]
- if (null == roomName && null != roomId) {
- // Try to get the room name from our store
- roomName = session?.getRoom(roomId)?.roomSummary()?.displayName
- }
- return roomName
- }
-
- /**
- * Try to create an event from the FCM data
- *
- * @param data the FCM data
- * @return the event or null if required data are missing
- */
- private fun parseEvent(data: Map?): Event? {
- return Event(
- eventId = data?.get("event_id") ?: return null,
- senderId = data["sender"],
- roomId = data["room_id"] ?: return null,
- type = data["type"] ?: return null,
- originServerTs = System.currentTimeMillis()
- )
- }
}
diff --git a/vector/src/gplay/java/im/vector/app/push/fcm/FcmHelper.kt b/vector/src/gplay/java/im/vector/app/push/fcm/FcmHelper.kt
index f3bdcafb1c..52ad4be087 100755
--- a/vector/src/gplay/java/im/vector/app/push/fcm/FcmHelper.kt
+++ b/vector/src/gplay/java/im/vector/app/push/fcm/FcmHelper.kt
@@ -75,7 +75,7 @@ object FcmHelper {
.addOnSuccessListener { token ->
storeFcmToken(activity, token)
if (registerPusher) {
- pushersManager.registerPusherWithFcmKey(token)
+ pushersManager.enqueueRegisterPusherWithFcmKey(token)
}
}
.addOnFailureListener { e ->
@@ -108,6 +108,6 @@ object FcmHelper {
@Suppress("UNUSED_PARAMETER")
fun onEnterBackground(context: Context, vectorPreferences: VectorPreferences, activeSessionHolder: ActiveSessionHolder) {
- // TODO FCM fallback
+ // No op
}
}
diff --git a/vector/src/main/AndroidManifest.xml b/vector/src/main/AndroidManifest.xml
index df85e31208..e5d4753235 100644
--- a/vector/src/main/AndroidManifest.xml
+++ b/vector/src/main/AndroidManifest.xml
@@ -4,7 +4,10 @@
package="im.vector.app">
-
+
+
@@ -83,13 +86,19 @@
android:name="android.max_aspect"
android:value="9.9" />
+
+
+
@@ -103,10 +112,13 @@
+
+
@@ -120,10 +132,13 @@
android:scheme="element" />
+
+
@@ -143,7 +158,6 @@
android:name=".features.media.VectorAttachmentViewerActivity"
android:theme="@style/Theme.Vector.Black.Transparent"
tools:ignore="Instantiatable" />
-
-
@@ -180,7 +193,13 @@
-
+
+
+
+
@@ -196,8 +215,37 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+ android:configChanges="screenSize|smallestScreenSize|screenLayout|orientation"
+ android:excludeFromRecents="true"
+ android:launchMode="singleTask"
+ android:supportsPictureInPicture="true"
+ android:taskAffinity=".features.call.VectorCallActivity" />
@@ -360,7 +390,9 @@
A media button receiver receives and helps translate hardware media playback buttons,
such as those found on wired and wireless headsets, into the appropriate callbacks in your app.
-->
-
+
@@ -370,9 +402,15 @@
+ android:name="androidx.startup.InitializationProvider"
+ android:authorities="${applicationId}.androidx-startup"
+ android:exported="false"
+ tools:node="merge">
+
+
+
+
+
+
+
+
-
\ No newline at end of file
+
diff --git a/vector/src/main/assets/open_source_licenses.html b/vector/src/main/assets/open_source_licenses.html
index 490de1f23a..529b7da2f1 100755
--- a/vector/src/main/assets/open_source_licenses.html
+++ b/vector/src/main/assets/open_source_licenses.html
@@ -194,6 +194,37 @@ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLI
+
+
+ hyuwah/DraggableView
+
+ hyuwah/DraggableView is licensed under the MIT License
+ Copyright (c) 2018 Muhammad Wahyudin
+
+
+
+
+Copyright (c) 2018 Muhammad Wahyudin
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
+
+
com.github.piasy:BigImageViewer
@@ -248,25 +279,9 @@ SOFTWARE.
Copyright 2012 The Dagger Authors
- rxkotlin
+ FlowBinding
- Copyright io.reactivex.
-
-
- rxandroid
-
- Copyright io.reactivex.
-
-
- rxrelay
-
- Copyright 2014 Netflix, Inc.
- Copyright 2015 Jake Wharton
-
-
- rxbinding
-
- Copyright (C) 2015 Jake Wharton
+ Copyright 2019 Yang Chen
Epoxy
diff --git a/vector/src/main/java/im/vector/app/AppStateHandler.kt b/vector/src/main/java/im/vector/app/AppStateHandler.kt
index 06174b9573..9ed9dd5b23 100644
--- a/vector/src/main/java/im/vector/app/AppStateHandler.kt
+++ b/vector/src/main/java/im/vector/app/AppStateHandler.kt
@@ -16,16 +16,20 @@
package im.vector.app
-import androidx.lifecycle.Lifecycle
-import androidx.lifecycle.LifecycleObserver
-import androidx.lifecycle.OnLifecycleEvent
+import androidx.lifecycle.DefaultLifecycleObserver
+import androidx.lifecycle.LifecycleOwner
import arrow.core.Option
import im.vector.app.core.di.ActiveSessionHolder
import im.vector.app.core.utils.BehaviorDataSource
import im.vector.app.features.session.coroutineScope
import im.vector.app.features.ui.UiStateRepository
-import io.reactivex.disposables.CompositeDisposable
+import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
+import kotlinx.coroutines.SupervisorJob
+import kotlinx.coroutines.cancelChildren
+import kotlinx.coroutines.flow.distinctUntilChanged
+import kotlinx.coroutines.flow.launchIn
+import kotlinx.coroutines.flow.onEach
import kotlinx.coroutines.launch
import org.matrix.android.sdk.api.extensions.tryOrNull
import org.matrix.android.sdk.api.session.Session
@@ -52,19 +56,32 @@ class AppStateHandler @Inject constructor(
private val sessionDataSource: ActiveSessionDataSource,
private val uiStateRepository: UiStateRepository,
private val activeSessionHolder: ActiveSessionHolder
-) : LifecycleObserver {
+) : DefaultLifecycleObserver {
- private val compositeDisposable = CompositeDisposable()
+ private val coroutineScope = CoroutineScope(SupervisorJob() + Dispatchers.Main)
private val selectedSpaceDataSource = BehaviorDataSource>(Option.empty())
- val selectedRoomGroupingObservable = selectedSpaceDataSource.observe()
+ val selectedRoomGroupingObservable = selectedSpaceDataSource.stream()
- fun getCurrentRoomGroupingMethod(): RoomGroupingMethod? = selectedSpaceDataSource.currentValue?.orNull()
+ fun getCurrentRoomGroupingMethod(): RoomGroupingMethod? {
+ // XXX we should somehow make it live :/ just a work around
+ // For example just after creating a space and switching to it the
+ // name in the app Bar could show Empty Room, and it will not update unless you
+ // switch space
+ return selectedSpaceDataSource.currentValue?.orNull()?.let {
+ if (it is RoomGroupingMethod.BySpace) {
+ // try to refresh sum?
+ it.spaceSummary?.roomId?.let { activeSessionHolder.getSafeActiveSession()?.getRoomSummary(it) }?.let {
+ RoomGroupingMethod.BySpace(it)
+ } ?: it
+ } else it
+ }
+ }
fun setCurrentSpace(spaceId: String?, session: Session? = null) {
val uSession = session ?: activeSessionHolder.getSafeActiveSession() ?: return
- if (selectedSpaceDataSource.currentValue?.orNull() is RoomGroupingMethod.BySpace
- && spaceId == selectedSpaceDataSource.currentValue?.orNull()?.space()?.roomId) return
+ if (selectedSpaceDataSource.currentValue?.orNull() is RoomGroupingMethod.BySpace &&
+ spaceId == selectedSpaceDataSource.currentValue?.orNull()?.space()?.roomId) return
val spaceSum = spaceId?.let { uSession.getRoomSummary(spaceId) }
selectedSpaceDataSource.post(Option.just(RoomGroupingMethod.BySpace(spaceSum)))
if (spaceId != null) {
@@ -78,8 +95,8 @@ class AppStateHandler @Inject constructor(
fun setCurrentGroup(groupId: String?, session: Session? = null) {
val uSession = session ?: activeSessionHolder.getSafeActiveSession() ?: return
- if (selectedSpaceDataSource.currentValue?.orNull() is RoomGroupingMethod.ByLegacyGroup
- && groupId == selectedSpaceDataSource.currentValue?.orNull()?.group()?.groupId) return
+ if (selectedSpaceDataSource.currentValue?.orNull() is RoomGroupingMethod.ByLegacyGroup &&
+ groupId == selectedSpaceDataSource.currentValue?.orNull()?.group()?.groupId) return
val activeGroup = groupId?.let { uSession.getGroupSummary(groupId) }
selectedSpaceDataSource.post(Option.just(RoomGroupingMethod.ByLegacyGroup(activeGroup)))
if (groupId != null) {
@@ -92,9 +109,9 @@ class AppStateHandler @Inject constructor(
}
private fun observeActiveSession() {
- sessionDataSource.observe()
+ sessionDataSource.stream()
.distinctUntilChanged()
- .subscribe {
+ .onEach {
// sessionDataSource could already return a session while activeSession holder still returns null
it.orNull()?.let { session ->
if (uiStateRepository.isGroupingMethodSpace(session.sessionId)) {
@@ -103,9 +120,8 @@ class AppStateHandler @Inject constructor(
setCurrentGroup(uiStateRepository.getSelectedGroup(session.sessionId), session)
}
}
- }.also {
- compositeDisposable.add(it)
}
+ .launchIn(coroutineScope)
}
fun safeActiveSpaceId(): String? {
@@ -116,14 +132,12 @@ class AppStateHandler @Inject constructor(
return (selectedSpaceDataSource.currentValue?.orNull() as? RoomGroupingMethod.ByLegacyGroup)?.groupSummary?.groupId
}
- @OnLifecycleEvent(Lifecycle.Event.ON_RESUME)
- fun entersForeground() {
+ override fun onResume(owner: LifecycleOwner) {
observeActiveSession()
}
- @OnLifecycleEvent(Lifecycle.Event.ON_PAUSE)
- fun entersBackground() {
- compositeDisposable.clear()
+ override fun onPause(owner: LifecycleOwner) {
+ coroutineScope.coroutineContext.cancelChildren()
val session = activeSessionHolder.getSafeActiveSession() ?: return
when (val currentMethod = selectedSpaceDataSource.currentValue?.orNull() ?: RoomGroupingMethod.BySpace(null)) {
is RoomGroupingMethod.BySpace -> {
diff --git a/vector/src/main/java/im/vector/app/VectorApplication.kt b/vector/src/main/java/im/vector/app/VectorApplication.kt
index be8447d409..c1d9eef125 100644
--- a/vector/src/main/java/im/vector/app/VectorApplication.kt
+++ b/vector/src/main/java/im/vector/app/VectorApplication.kt
@@ -27,23 +27,21 @@ import android.os.HandlerThread
import android.os.StrictMode
import androidx.core.provider.FontRequest
import androidx.core.provider.FontsContractCompat
-import androidx.lifecycle.Lifecycle
-import androidx.lifecycle.LifecycleObserver
-import androidx.lifecycle.OnLifecycleEvent
+import androidx.lifecycle.DefaultLifecycleObserver
+import androidx.lifecycle.LifecycleOwner
import androidx.lifecycle.ProcessLifecycleOwner
import androidx.multidex.MultiDex
import com.airbnb.epoxy.EpoxyAsyncUtil
import com.airbnb.epoxy.EpoxyController
+import com.airbnb.mvrx.Mavericks
import com.facebook.stetho.Stetho
import com.gabrielittner.threetenbp.LazyThreeTen
import com.vanniktech.emoji.EmojiManager
import com.vanniktech.emoji.google.GoogleEmojiProvider
+import dagger.hilt.android.HiltAndroidApp
import im.vector.app.core.di.ActiveSessionHolder
-import im.vector.app.core.di.DaggerVectorComponent
-import im.vector.app.core.di.HasVectorInjector
-import im.vector.app.core.di.VectorComponent
import im.vector.app.core.extensions.configureAndStart
-import im.vector.app.core.rx.RxConfig
+import im.vector.app.core.extensions.startSyncing
import im.vector.app.features.call.webrtc.WebRtcCallManager
import im.vector.app.features.configuration.VectorConfiguration
import im.vector.app.features.disclaimer.doNotShowDisclaimerDialog
@@ -53,6 +51,7 @@ import im.vector.app.features.notifications.NotificationDrawerManager
import im.vector.app.features.notifications.NotificationUtils
import im.vector.app.features.pin.PinLocker
import im.vector.app.features.popup.PopupAlertManager
+import im.vector.app.features.rageshake.VectorFileLogger
import im.vector.app.features.rageshake.VectorUncaughtExceptionHandler
import im.vector.app.features.room.VectorRoomDisplayNameFallbackProvider
import im.vector.app.features.settings.VectorLocale
@@ -73,9 +72,9 @@ import java.util.concurrent.Executors
import javax.inject.Inject
import androidx.work.Configuration as WorkConfiguration
+@HiltAndroidApp
class VectorApplication :
Application(),
- HasVectorInjector,
MatrixConfiguration.Provider,
WorkConfiguration.Provider {
@@ -92,21 +91,19 @@ class VectorApplication :
@Inject lateinit var versionProvider: VersionProvider
@Inject lateinit var notificationUtils: NotificationUtils
@Inject lateinit var appStateHandler: AppStateHandler
- @Inject lateinit var rxConfig: RxConfig
@Inject lateinit var popupAlertManager: PopupAlertManager
@Inject lateinit var pinLocker: PinLocker
@Inject lateinit var callManager: WebRtcCallManager
@Inject lateinit var invitesAcceptor: InvitesAcceptor
-
- lateinit var vectorComponent: VectorComponent
+ @Inject lateinit var vectorFileLogger: VectorFileLogger
// font thread handler
private var fontThreadHandler: Handler? = null
private val powerKeyReceiver = object : BroadcastReceiver() {
override fun onReceive(context: Context?, intent: Intent) {
- if (intent.action == Intent.ACTION_SCREEN_OFF
- && vectorPreferences.useFlagPinCode()) {
+ if (intent.action == Intent.ACTION_SCREEN_OFF &&
+ vectorPreferences.useFlagPinCode()) {
pinLocker.screenIsOff()
}
}
@@ -116,11 +113,8 @@ class VectorApplication :
enableStrictModeIfNeeded()
super.onCreate()
appContext = this
- vectorComponent = DaggerVectorComponent.factory().create(this)
- vectorComponent.inject(this)
invitesAcceptor.initialize()
vectorUncaughtExceptionHandler.activate(this)
- rxConfig.setupRxPlugin()
// Remove Log handler statically added by Jitsi
Timber.forest()
@@ -130,14 +124,14 @@ class VectorApplication :
if (BuildConfig.DEBUG) {
Timber.plant(Timber.DebugTree())
}
- Timber.plant(vectorComponent.vectorFileLogger())
+ Timber.plant(vectorFileLogger)
if (BuildConfig.DEBUG) {
Stetho.initializeWithDefaults(this)
}
logInfo()
LazyThreeTen.init(this)
-
+ Mavericks.initialize(debugMode = false)
EpoxyController.defaultDiffingHandler = EpoxyAsyncUtil.getAsyncBackgroundHandler()
EpoxyController.defaultModelBuildingHandler = EpoxyAsyncUtil.getAsyncBackgroundHandler()
registerActivityLifecycleCallbacks(VectorActivityLifecycleCallbacks(popupAlertManager))
@@ -162,14 +156,17 @@ class VectorApplication :
// Do not display the name change popup
doNotShowDisclaimerDialog(this)
}
+
if (authenticationService.hasAuthenticatedSessions() && !activeSessionHolder.hasActiveSession()) {
val lastAuthenticatedSession = authenticationService.getLastAuthenticatedSession()!!
activeSessionHolder.setActiveSession(lastAuthenticatedSession)
- lastAuthenticatedSession.configureAndStart(applicationContext)
+ lastAuthenticatedSession.configureAndStart(applicationContext, startSyncing = false)
}
- ProcessLifecycleOwner.get().lifecycle.addObserver(object : LifecycleObserver {
- @OnLifecycleEvent(Lifecycle.Event.ON_RESUME)
- fun entersForeground() {
+
+ ProcessLifecycleOwner.get().lifecycle.addObserver(startSyncOnFirstStart)
+
+ ProcessLifecycleOwner.get().lifecycle.addObserver(object : DefaultLifecycleObserver {
+ override fun onResume(owner: LifecycleOwner) {
Timber.i("App entered foreground")
FcmHelper.onEnterForeground(appContext, activeSessionHolder)
activeSessionHolder.getSafeActiveSession()?.also {
@@ -177,8 +174,7 @@ class VectorApplication :
}
}
- @OnLifecycleEvent(Lifecycle.Event.ON_PAUSE)
- fun entersBackground() {
+ override fun onPause(owner: LifecycleOwner) {
Timber.i("App entered background") // call persistInfo
notificationDrawerManager.persistInfo()
FcmHelper.onEnterBackground(appContext, vectorPreferences, activeSessionHolder)
@@ -199,6 +195,14 @@ class VectorApplication :
EmojiManager.install(GoogleEmojiProvider())
}
+ private val startSyncOnFirstStart = object : DefaultLifecycleObserver {
+ override fun onStart(owner: LifecycleOwner) {
+ Timber.i("App process started")
+ authenticationService.getLastAuthenticatedSession()?.startSyncing(appContext)
+ ProcessLifecycleOwner.get().lifecycle.removeObserver(this)
+ }
+ }
+
private fun enableStrictModeIfNeeded() {
if (BuildConfig.ENABLE_STRICT_MODE_LOGS) {
StrictMode.setThreadPolicy(StrictMode.ThreadPolicy.Builder()
@@ -221,10 +225,6 @@ class VectorApplication :
.build()
}
- override fun injector(): VectorComponent {
- return vectorComponent
- }
-
private fun logInfo() {
val appVersion = versionProvider.getVersion(longFormat = true, useBuildNumber = true)
val sdkVersion = Matrix.getSdkVersion()
diff --git a/vector/src/main/java/im/vector/app/core/contacts/ContactsDataSource.kt b/vector/src/main/java/im/vector/app/core/contacts/ContactsDataSource.kt
index f5a5e240c6..f99048501d 100644
--- a/vector/src/main/java/im/vector/app/core/contacts/ContactsDataSource.kt
+++ b/vector/src/main/java/im/vector/app/core/contacts/ContactsDataSource.kt
@@ -17,10 +17,10 @@
package im.vector.app.core.contacts
import android.content.Context
-import android.database.Cursor
import android.net.Uri
import android.provider.ContactsContract
import androidx.annotation.WorkerThread
+import im.vector.lib.multipicker.utils.getColumnIndexOrNull
import timber.log.Timber
import javax.inject.Inject
import kotlin.system.measureTimeMillis
@@ -57,16 +57,20 @@ class ContactsDataSource @Inject constructor(
)
?.use { cursor ->
if (cursor.count > 0) {
+ val idColumnIndex = cursor.getColumnIndexOrNull(ContactsContract.Contacts._ID) ?: return@use
+ val displayNameColumnIndex = cursor.getColumnIndexOrNull(ContactsContract.Contacts.DISPLAY_NAME) ?: return@use
+ val photoUriColumnIndex = cursor.getColumnIndexOrNull(ContactsContract.Data.PHOTO_URI)
while (cursor.moveToNext()) {
- val id = cursor.getLong(ContactsContract.Contacts._ID) ?: continue
- val displayName = cursor.getString(ContactsContract.Contacts.DISPLAY_NAME) ?: continue
+ val id = cursor.getLong(idColumnIndex)
+ val displayName = cursor.getString(displayNameColumnIndex)
val mappedContactBuilder = MappedContactBuilder(
id = id,
displayName = displayName
)
- cursor.getString(ContactsContract.Data.PHOTO_URI)
+ photoUriColumnIndex
+ ?.let { cursor.getString(it) }
?.let { Uri.parse(it) }
?.let { mappedContactBuilder.photoURI = it }
@@ -85,12 +89,15 @@ class ContactsDataSource @Inject constructor(
null,
null,
null)
- ?.use { innerCursor ->
- while (innerCursor.moveToNext()) {
- val mappedContactBuilder = innerCursor.getLong(ContactsContract.CommonDataKinds.Phone.CONTACT_ID)
- ?.let { map[it] }
+ ?.use { cursor ->
+ val idColumnIndex = cursor.getColumnIndexOrNull(ContactsContract.CommonDataKinds.Phone.CONTACT_ID) ?: return@use
+ val phoneNumberColumnIndex = cursor.getColumnIndexOrNull(ContactsContract.CommonDataKinds.Phone.NUMBER) ?: return@use
+
+ while (cursor.moveToNext()) {
+ val mappedContactBuilder = cursor.getLong(idColumnIndex)
+ .let { map[it] }
?: continue
- innerCursor.getString(ContactsContract.CommonDataKinds.Phone.NUMBER)
+ cursor.getString(phoneNumberColumnIndex)
?.let {
mappedContactBuilder.msisdns.add(
MappedMsisdn(
@@ -114,14 +121,17 @@ class ContactsDataSource @Inject constructor(
null,
null,
null)
- ?.use { innerCursor ->
- while (innerCursor.moveToNext()) {
+ ?.use { cursor ->
+ val idColumnIndex = cursor.getColumnIndexOrNull(ContactsContract.CommonDataKinds.Email.CONTACT_ID) ?: return@use
+ val emailColumnIndex = cursor.getColumnIndexOrNull(ContactsContract.CommonDataKinds.Email.DATA) ?: return@use
+
+ while (cursor.moveToNext()) {
// This would allow you get several email addresses
// if the email addresses were stored in an array
- val mappedContactBuilder = innerCursor.getLong(ContactsContract.CommonDataKinds.Email.CONTACT_ID)
- ?.let { map[it] }
+ val mappedContactBuilder = cursor.getLong(idColumnIndex)
+ .let { map[it] }
?: continue
- innerCursor.getString(ContactsContract.CommonDataKinds.Email.DATA)
+ cursor.getString(emailColumnIndex)
?.let {
mappedContactBuilder.emails.add(
MappedEmail(
@@ -140,16 +150,4 @@ class ContactsDataSource @Inject constructor(
.filter { it.emails.isNotEmpty() || it.msisdns.isNotEmpty() }
.map { it.build() }
}
-
- private fun Cursor.getString(column: String): String? {
- return getColumnIndex(column)
- .takeIf { it != -1 }
- ?.let { getString(it) }
- }
-
- private fun Cursor.getLong(column: String): Long? {
- return getColumnIndex(column)
- .takeIf { it != -1 }
- ?.let { getLong(it) }
- }
}
diff --git a/vector/src/main/java/im/vector/app/core/date/DefaultDateFormatterProvider.kt b/vector/src/main/java/im/vector/app/core/date/DefaultDateFormatterProvider.kt
index c8736f3ab1..6371035a17 100644
--- a/vector/src/main/java/im/vector/app/core/date/DefaultDateFormatterProvider.kt
+++ b/vector/src/main/java/im/vector/app/core/date/DefaultDateFormatterProvider.kt
@@ -23,8 +23,8 @@ import org.threeten.bp.format.DateTimeFormatter
import javax.inject.Inject
class DefaultDateFormatterProvider @Inject constructor(private val context: Context,
- private val localeProvider: LocaleProvider)
- : DateFormatterProvider {
+ private val localeProvider: LocaleProvider) :
+ DateFormatterProvider {
override val dateWithMonthFormatter: DateTimeFormatter by lazy {
val pattern = DateFormat.getBestDateTimePattern(localeProvider.current(), "d MMMMM")
diff --git a/vector/src/main/java/im/vector/app/core/di/ActiveSessionHolder.kt b/vector/src/main/java/im/vector/app/core/di/ActiveSessionHolder.kt
index e739cac95f..6b7b5f7f62 100644
--- a/vector/src/main/java/im/vector/app/core/di/ActiveSessionHolder.kt
+++ b/vector/src/main/java/im/vector/app/core/di/ActiveSessionHolder.kt
@@ -18,6 +18,7 @@ package im.vector.app.core.di
import arrow.core.Option
import im.vector.app.ActiveSessionDataSource
+import im.vector.app.core.services.GuardServiceStarter
import im.vector.app.features.call.webrtc.WebRtcCallManager
import im.vector.app.features.crypto.keysrequest.KeyRequestHandler
import im.vector.app.features.crypto.verification.IncomingVerificationRequestHandler
@@ -36,7 +37,8 @@ class ActiveSessionHolder @Inject constructor(private val sessionObservableStore
private val callManager: WebRtcCallManager,
private val pushRuleTriggerListener: PushRuleTriggerListener,
private val sessionListener: SessionListener,
- private val imageManager: ImageManager
+ private val imageManager: ImageManager,
+ private val guardServiceStarter: GuardServiceStarter
) {
private var activeSession: AtomicReference = AtomicReference()
@@ -52,6 +54,7 @@ class ActiveSessionHolder @Inject constructor(private val sessionObservableStore
pushRuleTriggerListener.startWithSession(session)
session.callSignalingService().addCallListener(callManager)
imageManager.onSessionStarted(session)
+ guardServiceStarter.start()
}
fun clearActiveSession() {
diff --git a/vector/src/main/java/im/vector/app/core/di/ActivityEntryPoint.kt b/vector/src/main/java/im/vector/app/core/di/ActivityEntryPoint.kt
new file mode 100644
index 0000000000..c5f7317ebe
--- /dev/null
+++ b/vector/src/main/java/im/vector/app/core/di/ActivityEntryPoint.kt
@@ -0,0 +1,30 @@
+/*
+ * Copyright (c) 2021 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 im.vector.app.core.di
+
+import androidx.fragment.app.FragmentFactory
+import androidx.lifecycle.ViewModelProvider
+import dagger.hilt.EntryPoint
+import dagger.hilt.InstallIn
+import dagger.hilt.android.components.ActivityComponent
+
+@InstallIn(ActivityComponent::class)
+@EntryPoint
+interface ActivityEntryPoint {
+ fun fragmentFactory(): FragmentFactory
+ fun viewModelFactory(): ViewModelProvider.Factory
+}
diff --git a/vector/src/main/java/im/vector/app/core/di/FragmentModule.kt b/vector/src/main/java/im/vector/app/core/di/FragmentModule.kt
index cce0c2a66f..b8d00fac5a 100644
--- a/vector/src/main/java/im/vector/app/core/di/FragmentModule.kt
+++ b/vector/src/main/java/im/vector/app/core/di/FragmentModule.kt
@@ -21,6 +21,8 @@ import androidx.fragment.app.Fragment
import androidx.fragment.app.FragmentFactory
import dagger.Binds
import dagger.Module
+import dagger.hilt.InstallIn
+import dagger.hilt.android.components.ActivityComponent
import dagger.multibindings.IntoMap
import im.vector.app.features.attachments.preview.AttachmentsPreviewFragment
import im.vector.app.features.contactsbook.ContactsBookFragment
@@ -76,7 +78,6 @@ import im.vector.app.features.login2.LoginFragmentSigninPassword2
import im.vector.app.features.login2.LoginFragmentSigninUsername2
import im.vector.app.features.login2.LoginFragmentSignupPassword2
import im.vector.app.features.login2.LoginFragmentSignupUsername2
-import im.vector.app.features.login2.created.AccountCreatedFragment
import im.vector.app.features.login2.LoginFragmentToAny2
import im.vector.app.features.login2.LoginGenericTextInputFormFragment2
import im.vector.app.features.login2.LoginResetPasswordFragment2
@@ -88,10 +89,12 @@ import im.vector.app.features.login2.LoginSplashSignUpSignInSelectionFragment2
import im.vector.app.features.login2.LoginSsoOnlyFragment2
import im.vector.app.features.login2.LoginWaitForEmailFragment2
import im.vector.app.features.login2.LoginWebFragment2
+import im.vector.app.features.login2.created.AccountCreatedFragment
import im.vector.app.features.login2.terms.LoginTermsFragment2
import im.vector.app.features.matrixto.MatrixToRoomSpaceFragment
import im.vector.app.features.matrixto.MatrixToUserFragment
import im.vector.app.features.pin.PinFragment
+import im.vector.app.features.poll.create.CreatePollFragment
import im.vector.app.features.qrcode.QrCodeScannerFragment
import im.vector.app.features.reactions.EmojiChooserFragment
import im.vector.app.features.reactions.EmojiSearchResultFragment
@@ -106,19 +109,17 @@ import im.vector.app.features.roomprofile.RoomProfileFragment
import im.vector.app.features.roomprofile.alias.RoomAliasFragment
import im.vector.app.features.roomprofile.banned.RoomBannedMemberListFragment
import im.vector.app.features.roomprofile.members.RoomMemberListFragment
+import im.vector.app.features.roomprofile.notifications.RoomNotificationSettingsFragment
import im.vector.app.features.roomprofile.permissions.RoomPermissionsFragment
import im.vector.app.features.roomprofile.settings.RoomSettingsFragment
-import im.vector.app.features.roomprofile.settings.joinrule.RoomJoinRuleChooseRestrictedFragment
import im.vector.app.features.roomprofile.settings.joinrule.RoomJoinRuleFragment
+import im.vector.app.features.roomprofile.settings.joinrule.advanced.RoomJoinRuleChooseRestrictedFragment
import im.vector.app.features.roomprofile.uploads.RoomUploadsFragment
import im.vector.app.features.roomprofile.uploads.files.RoomUploadsFilesFragment
import im.vector.app.features.roomprofile.uploads.media.RoomUploadsMediaFragment
-import im.vector.app.features.settings.notifications.VectorSettingsAdvancedNotificationPreferenceFragment
import im.vector.app.features.settings.VectorSettingsGeneralFragment
import im.vector.app.features.settings.VectorSettingsHelpAboutFragment
import im.vector.app.features.settings.VectorSettingsLabsFragment
-import im.vector.app.features.settings.notifications.VectorSettingsNotificationPreferenceFragment
-import im.vector.app.features.settings.notifications.VectorSettingsNotificationsTroubleshootFragment
import im.vector.app.features.settings.VectorSettingsPinFragment
import im.vector.app.features.settings.VectorSettingsPreferencesFragment
import im.vector.app.features.settings.VectorSettingsSecurityPrivacyFragment
@@ -133,6 +134,9 @@ import im.vector.app.features.settings.devtools.OutgoingKeyRequestListFragment
import im.vector.app.features.settings.homeserver.HomeserverSettingsFragment
import im.vector.app.features.settings.ignored.VectorSettingsIgnoredUsersFragment
import im.vector.app.features.settings.locale.LocalePickerFragment
+import im.vector.app.features.settings.notifications.VectorSettingsAdvancedNotificationPreferenceFragment
+import im.vector.app.features.settings.notifications.VectorSettingsNotificationPreferenceFragment
+import im.vector.app.features.settings.notifications.VectorSettingsNotificationsTroubleshootFragment
import im.vector.app.features.settings.push.PushGatewaysFragment
import im.vector.app.features.settings.push.PushRulesFragment
import im.vector.app.features.settings.threepids.ThreePidsSettingsFragment
@@ -141,9 +145,11 @@ import im.vector.app.features.signout.soft.SoftLogoutFragment
import im.vector.app.features.spaces.SpaceListFragment
import im.vector.app.features.spaces.create.ChoosePrivateSpaceTypeFragment
import im.vector.app.features.spaces.create.ChooseSpaceTypeFragment
+import im.vector.app.features.spaces.create.CreateSpaceAdd3pidInvitesFragment
import im.vector.app.features.spaces.create.CreateSpaceDefaultRoomsFragment
import im.vector.app.features.spaces.create.CreateSpaceDetailsFragment
import im.vector.app.features.spaces.explore.SpaceDirectoryFragment
+import im.vector.app.features.spaces.leave.SpaceLeaveAdvancedFragment
import im.vector.app.features.spaces.manage.SpaceAddRoomFragment
import im.vector.app.features.spaces.manage.SpaceManageRoomsFragment
import im.vector.app.features.spaces.manage.SpaceSettingsFragment
@@ -154,6 +160,7 @@ import im.vector.app.features.usercode.ShowUserCodeFragment
import im.vector.app.features.userdirectory.UserListFragment
import im.vector.app.features.widgets.WidgetFragment
+@InstallIn(ActivityComponent::class)
@Module
interface FragmentModule {
/**
@@ -717,6 +724,11 @@ interface FragmentModule {
@FragmentKey(RoomBannedMemberListFragment::class)
fun bindRoomBannedMemberListFragment(fragment: RoomBannedMemberListFragment): Fragment
+ @Binds
+ @IntoMap
+ @FragmentKey(RoomNotificationSettingsFragment::class)
+ fun bindRoomNotificationSettingsFragment(fragment: RoomNotificationSettingsFragment): Fragment
+
@Binds
@IntoMap
@FragmentKey(SearchFragment::class)
@@ -787,6 +799,11 @@ interface FragmentModule {
@FragmentKey(ChoosePrivateSpaceTypeFragment::class)
fun bindChoosePrivateSpaceTypeFragment(fragment: ChoosePrivateSpaceTypeFragment): Fragment
+ @Binds
+ @IntoMap
+ @FragmentKey(CreateSpaceAdd3pidInvitesFragment::class)
+ fun bindCreateSpaceAdd3pidInvitesFragment(fragment: CreateSpaceAdd3pidInvitesFragment): Fragment
+
@Binds
@IntoMap
@FragmentKey(SpaceAddRoomFragment::class)
@@ -816,4 +833,14 @@ interface FragmentModule {
@IntoMap
@FragmentKey(RoomJoinRuleChooseRestrictedFragment::class)
fun bindRoomJoinRuleChooseRestrictedFragment(fragment: RoomJoinRuleChooseRestrictedFragment): Fragment
+
+ @Binds
+ @IntoMap
+ @FragmentKey(SpaceLeaveAdvancedFragment::class)
+ fun bindSpaceLeaveAdvancedFragment(fragment: SpaceLeaveAdvancedFragment): Fragment
+
+ @Binds
+ @IntoMap
+ @FragmentKey(CreatePollFragment::class)
+ fun bindCreatePollFragment(fragment: CreatePollFragment): Fragment
}
diff --git a/vector/src/main/java/im/vector/app/core/di/HiltMavericksViewModelFactory.kt b/vector/src/main/java/im/vector/app/core/di/HiltMavericksViewModelFactory.kt
new file mode 100644
index 0000000000..13702053e8
--- /dev/null
+++ b/vector/src/main/java/im/vector/app/core/di/HiltMavericksViewModelFactory.kt
@@ -0,0 +1,92 @@
+/*
+ * Copyright (c) 2021 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 im.vector.app.core.di
+
+import com.airbnb.mvrx.MavericksState
+import com.airbnb.mvrx.MavericksViewModel
+import com.airbnb.mvrx.MavericksViewModelFactory
+import com.airbnb.mvrx.ViewModelContext
+import dagger.hilt.DefineComponent
+import dagger.hilt.EntryPoint
+import dagger.hilt.EntryPoints
+import dagger.hilt.InstallIn
+import dagger.hilt.components.SingletonComponent
+
+/**
+ * To connect Mavericks ViewModel creation with Hilt's dependency injection, add the following Factory and companion object to your MavericksViewModel.
+ *
+ * Example:
+ *
+ * class MyViewModel @AssistedInject constructor(...): MavericksViewModel(...) {
+ *
+ * @AssistedFactory
+ * interface Factory : AssistedViewModelFactory {
+ * ...
+ * }
+ *
+ * companion object : MavericksViewModelFactory by hiltMavericksViewModelFactory()
+ * }
+ */
+
+inline fun , S : MavericksState> hiltMavericksViewModelFactory() = HiltMavericksViewModelFactory(VM::class.java)
+
+class HiltMavericksViewModelFactory, S : MavericksState>(
+ private val viewModelClass: Class>
+) : MavericksViewModelFactory {
+
+ override fun create(viewModelContext: ViewModelContext, state: S): VM {
+ // We want to create the ViewModelComponent. In order to do that, we need to get its parent: ActivityComponent.
+ val componentBuilder = EntryPoints.get(viewModelContext.app(), CreateMavericksViewModelComponent::class.java).mavericksViewModelComponentBuilder()
+ val viewModelComponent = componentBuilder.build()
+ val viewModelFactoryMap = EntryPoints.get(viewModelComponent, HiltMavericksEntryPoint::class.java).viewModelFactories
+ val viewModelFactory = viewModelFactoryMap[viewModelClass]
+
+ @Suppress("UNCHECKED_CAST")
+ val castedViewModelFactory = viewModelFactory as? MavericksAssistedViewModelFactory
+ return castedViewModelFactory?.create(state) as VM
+ }
+
+ override fun initialState(viewModelContext: ViewModelContext): S? {
+ return super.initialState(viewModelContext)
+ }
+}
+
+/**
+ * Hilt's ViewModelComponent's parent is ActivityRetainedComponent but there is no easy way to access it. SingletonComponent should be sufficient
+ * because the ViewModel that gets created is the only object with a reference to the created component so the lifecycle of it will
+ * still be correct.
+ */
+@MavericksViewModelScoped
+@DefineComponent(parent = SingletonComponent::class)
+interface MavericksViewModelComponent
+
+@DefineComponent.Builder
+interface MavericksViewModelComponentBuilder {
+ fun build(): MavericksViewModelComponent
+}
+
+@EntryPoint
+@InstallIn(SingletonComponent::class)
+interface CreateMavericksViewModelComponent {
+ fun mavericksViewModelComponentBuilder(): MavericksViewModelComponentBuilder
+}
+
+@EntryPoint
+@InstallIn(MavericksViewModelComponent::class)
+interface HiltMavericksEntryPoint {
+ val viewModelFactories: Map>, MavericksAssistedViewModelFactory<*, *>>
+}
diff --git a/vector/src/main/java/im/vector/app/core/di/HomeModule.kt b/vector/src/main/java/im/vector/app/core/di/HomeModule.kt
new file mode 100644
index 0000000000..1af67cdc83
--- /dev/null
+++ b/vector/src/main/java/im/vector/app/core/di/HomeModule.kt
@@ -0,0 +1,36 @@
+/*
+ * Copyright (c) 2021 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 im.vector.app.core.di
+
+import android.os.Handler
+import dagger.Module
+import dagger.Provides
+import dagger.hilt.InstallIn
+import dagger.hilt.android.components.ActivityComponent
+import im.vector.app.features.home.room.detail.timeline.TimelineEventControllerHandler
+import im.vector.app.features.home.room.detail.timeline.helper.TimelineAsyncHelper
+
+@Module
+@InstallIn(ActivityComponent::class)
+object HomeModule {
+ @Provides
+ @JvmStatic
+ @TimelineEventControllerHandler
+ fun providesTimelineBackgroundHandler(): Handler {
+ return TimelineAsyncHelper.getBackgroundHandler()
+ }
+}
diff --git a/vector/src/main/java/im/vector/app/core/di/MavericksAssistedViewModelFactory.kt b/vector/src/main/java/im/vector/app/core/di/MavericksAssistedViewModelFactory.kt
new file mode 100644
index 0000000000..7cd6245d64
--- /dev/null
+++ b/vector/src/main/java/im/vector/app/core/di/MavericksAssistedViewModelFactory.kt
@@ -0,0 +1,40 @@
+/*
+ * Copyright (c) 2021 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 im.vector.app.core.di
+
+import com.airbnb.mvrx.MavericksState
+import com.airbnb.mvrx.MavericksViewModel
+
+/**
+ * This factory allows Mavericks to supply the initial or restored [MavericksState] to Hilt.
+ *
+ * Add this interface inside of your [MavericksViewModel] class then create the following Hilt module:
+ *
+ * @Module
+ * @InstallIn(MavericksViewModelComponent::class)
+ * interface ViewModelsModule {
+ * @Binds
+ * @IntoMap
+ * @ViewModelKey(MyViewModel::class)
+ * fun myViewModelFactory(factory: MyViewModel.Factory): AssistedViewModelFactory<*, *>
+ * }
+ *
+ * If you already have a ViewModelsModule then all you have to do is add the multibinding entry for your new [MavericksViewModel].
+ */
+interface MavericksAssistedViewModelFactory, S : MavericksState> {
+ fun create(initialState: S): VM
+}
diff --git a/vector/src/main/java/im/vector/app/core/di/MavericksViewModelModule.kt b/vector/src/main/java/im/vector/app/core/di/MavericksViewModelModule.kt
new file mode 100644
index 0000000000..c827bd0b35
--- /dev/null
+++ b/vector/src/main/java/im/vector/app/core/di/MavericksViewModelModule.kt
@@ -0,0 +1,555 @@
+/*
+ * Copyright 2019 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 im.vector.app.core.di
+
+import dagger.Binds
+import dagger.Module
+import dagger.hilt.InstallIn
+import dagger.multibindings.IntoMap
+import im.vector.app.features.auth.ReAuthViewModel
+import im.vector.app.features.call.VectorCallViewModel
+import im.vector.app.features.call.conference.JitsiCallViewModel
+import im.vector.app.features.call.transfer.CallTransferViewModel
+import im.vector.app.features.contactsbook.ContactsBookViewModel
+import im.vector.app.features.createdirect.CreateDirectRoomViewModel
+import im.vector.app.features.crypto.keysbackup.settings.KeysBackupSettingsViewModel
+import im.vector.app.features.crypto.quads.SharedSecureStorageViewModel
+import im.vector.app.features.crypto.recover.BootstrapSharedViewModel
+import im.vector.app.features.crypto.verification.VerificationBottomSheetViewModel
+import im.vector.app.features.crypto.verification.choose.VerificationChooseMethodViewModel
+import im.vector.app.features.crypto.verification.emoji.VerificationEmojiCodeViewModel
+import im.vector.app.features.devtools.RoomDevToolViewModel
+import im.vector.app.features.discovery.DiscoverySettingsViewModel
+import im.vector.app.features.discovery.change.SetIdentityServerViewModel
+import im.vector.app.features.home.HomeActivityViewModel
+import im.vector.app.features.home.HomeDetailViewModel
+import im.vector.app.features.home.PromoteRestrictedViewModel
+import im.vector.app.features.home.UnknownDeviceDetectorSharedViewModel
+import im.vector.app.features.home.UnreadMessagesSharedViewModel
+import im.vector.app.features.home.room.breadcrumbs.BreadcrumbsViewModel
+import im.vector.app.features.home.room.detail.composer.TextComposerViewModel
+import im.vector.app.features.home.room.detail.search.SearchViewModel
+import im.vector.app.features.home.room.detail.timeline.action.MessageActionsViewModel
+import im.vector.app.features.home.room.detail.timeline.edithistory.ViewEditHistoryViewModel
+import im.vector.app.features.home.room.detail.timeline.reactions.ViewReactionsViewModel
+import im.vector.app.features.home.room.detail.upgrade.MigrateRoomViewModel
+import im.vector.app.features.home.room.list.RoomListViewModel
+import im.vector.app.features.homeserver.HomeServerCapabilitiesViewModel
+import im.vector.app.features.invite.InviteUsersToRoomViewModel
+import im.vector.app.features.login.LoginViewModel
+import im.vector.app.features.login2.LoginViewModel2
+import im.vector.app.features.login2.created.AccountCreatedViewModel
+import im.vector.app.features.matrixto.MatrixToBottomSheetViewModel
+import im.vector.app.features.poll.create.CreatePollViewModel
+import im.vector.app.features.rageshake.BugReportViewModel
+import im.vector.app.features.reactions.EmojiSearchResultViewModel
+import im.vector.app.features.room.RequireActiveMembershipViewModel
+import im.vector.app.features.roomdirectory.RoomDirectoryViewModel
+import im.vector.app.features.roomdirectory.createroom.CreateRoomViewModel
+import im.vector.app.features.roomdirectory.picker.RoomDirectoryPickerViewModel
+import im.vector.app.features.roomdirectory.roompreview.RoomPreviewViewModel
+import im.vector.app.features.roommemberprofile.RoomMemberProfileViewModel
+import im.vector.app.features.roommemberprofile.devices.DeviceListBottomSheetViewModel
+import im.vector.app.features.roomprofile.RoomProfileViewModel
+import im.vector.app.features.roomprofile.alias.RoomAliasViewModel
+import im.vector.app.features.roomprofile.alias.detail.RoomAliasBottomSheetViewModel
+import im.vector.app.features.roomprofile.banned.RoomBannedMemberListViewModel
+import im.vector.app.features.roomprofile.members.RoomMemberListViewModel
+import im.vector.app.features.roomprofile.notifications.RoomNotificationSettingsViewModel
+import im.vector.app.features.roomprofile.permissions.RoomPermissionsViewModel
+import im.vector.app.features.roomprofile.settings.RoomSettingsViewModel
+import im.vector.app.features.roomprofile.settings.joinrule.advanced.RoomJoinRuleChooseRestrictedViewModel
+import im.vector.app.features.roomprofile.uploads.RoomUploadsViewModel
+import im.vector.app.features.settings.account.deactivation.DeactivateAccountViewModel
+import im.vector.app.features.settings.crosssigning.CrossSigningSettingsViewModel
+import im.vector.app.features.settings.devices.DeviceVerificationInfoBottomSheetViewModel
+import im.vector.app.features.settings.devices.DevicesViewModel
+import im.vector.app.features.settings.devtools.AccountDataViewModel
+import im.vector.app.features.settings.devtools.GossipingEventsPaperTrailViewModel
+import im.vector.app.features.settings.devtools.KeyRequestListViewModel
+import im.vector.app.features.settings.devtools.KeyRequestViewModel
+import im.vector.app.features.settings.homeserver.HomeserverSettingsViewModel
+import im.vector.app.features.settings.ignored.IgnoredUsersViewModel
+import im.vector.app.features.settings.locale.LocalePickerViewModel
+import im.vector.app.features.settings.push.PushGatewaysViewModel
+import im.vector.app.features.settings.threepids.ThreePidsSettingsViewModel
+import im.vector.app.features.share.IncomingShareViewModel
+import im.vector.app.features.signout.soft.SoftLogoutViewModel
+import im.vector.app.features.spaces.SpaceListViewModel
+import im.vector.app.features.spaces.SpaceMenuViewModel
+import im.vector.app.features.spaces.create.CreateSpaceViewModel
+import im.vector.app.features.spaces.explore.SpaceDirectoryViewModel
+import im.vector.app.features.spaces.invite.SpaceInviteBottomSheetViewModel
+import im.vector.app.features.spaces.leave.SpaceLeaveAdvancedViewModel
+import im.vector.app.features.spaces.manage.SpaceAddRoomsViewModel
+import im.vector.app.features.spaces.manage.SpaceManageRoomsViewModel
+import im.vector.app.features.spaces.manage.SpaceManageSharedViewModel
+import im.vector.app.features.spaces.people.SpacePeopleViewModel
+import im.vector.app.features.spaces.preview.SpacePreviewViewModel
+import im.vector.app.features.spaces.share.ShareSpaceViewModel
+import im.vector.app.features.terms.ReviewTermsViewModel
+import im.vector.app.features.usercode.UserCodeSharedViewModel
+import im.vector.app.features.userdirectory.UserListViewModel
+import im.vector.app.features.widgets.WidgetViewModel
+import im.vector.app.features.widgets.permissions.RoomWidgetPermissionViewModel
+import im.vector.app.features.workers.signout.ServerBackupStatusViewModel
+import im.vector.app.features.workers.signout.SignoutCheckViewModel
+
+@InstallIn(MavericksViewModelComponent::class)
+@Module
+interface MavericksViewModelModule {
+
+ @Binds
+ @IntoMap
+ @MavericksViewModelKey(RoomListViewModel::class)
+ fun roomListViewModelFactory(factory: RoomListViewModel.Factory): MavericksAssistedViewModelFactory<*, *>
+
+ @Binds
+ @IntoMap
+ @MavericksViewModelKey(SpaceManageRoomsViewModel::class)
+ fun spaceManageRoomsViewModelFactory(factory: SpaceManageRoomsViewModel.Factory): MavericksAssistedViewModelFactory<*, *>
+
+ @Binds
+ @IntoMap
+ @MavericksViewModelKey(SpaceManageSharedViewModel::class)
+ fun spaceManageSharedViewModelFactory(factory: SpaceManageSharedViewModel.Factory): MavericksAssistedViewModelFactory<*, *>
+
+ @Binds
+ @IntoMap
+ @MavericksViewModelKey(SpaceListViewModel::class)
+ fun spaceListViewModelFactory(factory: SpaceListViewModel.Factory): MavericksAssistedViewModelFactory<*, *>
+
+ @Binds
+ @IntoMap
+ @MavericksViewModelKey(ReAuthViewModel::class)
+ fun reAuthViewModelFactory(factory: ReAuthViewModel.Factory): MavericksAssistedViewModelFactory<*, *>
+
+ @Binds
+ @IntoMap
+ @MavericksViewModelKey(VectorCallViewModel::class)
+ fun vectorCallViewModelFactory(factory: VectorCallViewModel.Factory): MavericksAssistedViewModelFactory<*, *>
+
+ @Binds
+ @IntoMap
+ @MavericksViewModelKey(JitsiCallViewModel::class)
+ fun jitsiCallViewModelFactory(factory: JitsiCallViewModel.Factory): MavericksAssistedViewModelFactory<*, *>
+
+ @Binds
+ @IntoMap
+ @MavericksViewModelKey(RoomDirectoryViewModel::class)
+ fun roomDirectoryViewModelFactory(factory: RoomDirectoryViewModel.Factory): MavericksAssistedViewModelFactory<*, *>
+
+ @Binds
+ @IntoMap
+ @MavericksViewModelKey(ViewReactionsViewModel::class)
+ fun viewReactionsViewModelFactory(factory: ViewReactionsViewModel.Factory): MavericksAssistedViewModelFactory<*, *>
+
+ @Binds
+ @IntoMap
+ @MavericksViewModelKey(RoomWidgetPermissionViewModel::class)
+ fun roomWidgetPermissionViewModelFactory(factory: RoomWidgetPermissionViewModel.Factory): MavericksAssistedViewModelFactory<*, *>
+
+ @Binds
+ @IntoMap
+ @MavericksViewModelKey(WidgetViewModel::class)
+ fun widgetViewModelFactory(factory: WidgetViewModel.Factory): MavericksAssistedViewModelFactory<*, *>
+
+ @Binds
+ @IntoMap
+ @MavericksViewModelKey(ServerBackupStatusViewModel::class)
+ fun serverBackupStatusViewModelFactory(factory: ServerBackupStatusViewModel.Factory): MavericksAssistedViewModelFactory<*, *>
+
+ @Binds
+ @IntoMap
+ @MavericksViewModelKey(SignoutCheckViewModel::class)
+ fun signoutCheckViewModelFactory(factory: SignoutCheckViewModel.Factory): MavericksAssistedViewModelFactory<*, *>
+
+ @Binds
+ @IntoMap
+ @MavericksViewModelKey(RoomDirectoryPickerViewModel::class)
+ fun roomDirectoryPickerViewModelFactory(factory: RoomDirectoryPickerViewModel.Factory): MavericksAssistedViewModelFactory<*, *>
+
+ @Binds
+ @IntoMap
+ @MavericksViewModelKey(RoomDevToolViewModel::class)
+ fun roomDevToolViewModelFactory(factory: RoomDevToolViewModel.Factory): MavericksAssistedViewModelFactory<*, *>
+
+ @Binds
+ @IntoMap
+ @MavericksViewModelKey(MigrateRoomViewModel::class)
+ fun migrateRoomViewModelFactory(factory: MigrateRoomViewModel.Factory): MavericksAssistedViewModelFactory<*, *>
+
+ @Binds
+ @IntoMap
+ @MavericksViewModelKey(IgnoredUsersViewModel::class)
+ fun ignoredUsersViewModelFactory(factory: IgnoredUsersViewModel.Factory): MavericksAssistedViewModelFactory<*, *>
+
+ @Binds
+ @IntoMap
+ @MavericksViewModelKey(CallTransferViewModel::class)
+ fun callTransferViewModelFactory(factory: CallTransferViewModel.Factory): MavericksAssistedViewModelFactory<*, *>
+
+ @Binds
+ @IntoMap
+ @MavericksViewModelKey(ContactsBookViewModel::class)
+ fun contactsBookViewModelFactory(factory: ContactsBookViewModel.Factory): MavericksAssistedViewModelFactory<*, *>
+
+ @Binds
+ @IntoMap
+ @MavericksViewModelKey(CreateDirectRoomViewModel::class)
+ fun createDirectRoomViewModelFactory(factory: CreateDirectRoomViewModel.Factory): MavericksAssistedViewModelFactory<*, *>
+
+ @Binds
+ @IntoMap
+ @MavericksViewModelKey(RoomNotificationSettingsViewModel::class)
+ fun roomNotificationSettingsViewModelFactory(factory: RoomNotificationSettingsViewModel.Factory): MavericksAssistedViewModelFactory<*, *>
+
+ @Binds
+ @IntoMap
+ @MavericksViewModelKey(KeysBackupSettingsViewModel::class)
+ fun keysBackupSettingsViewModelFactory(factory: KeysBackupSettingsViewModel.Factory): MavericksAssistedViewModelFactory<*, *>
+
+ @Binds
+ @IntoMap
+ @MavericksViewModelKey(SharedSecureStorageViewModel::class)
+ fun sharedSecureStorageViewModelFactory(factory: SharedSecureStorageViewModel.Factory): MavericksAssistedViewModelFactory<*, *>
+
+ @Binds
+ @IntoMap
+ @MavericksViewModelKey(PromoteRestrictedViewModel::class)
+ fun promoteRestrictedViewModelFactory(factory: PromoteRestrictedViewModel.Factory): MavericksAssistedViewModelFactory<*, *>
+
+ @Binds
+ @IntoMap
+ @MavericksViewModelKey(UserListViewModel::class)
+ fun userListViewModelFactory(factory: UserListViewModel.Factory): MavericksAssistedViewModelFactory<*, *>
+
+ @Binds
+ @IntoMap
+ @MavericksViewModelKey(UserCodeSharedViewModel::class)
+ fun userCodeSharedViewModelFactory(factory: UserCodeSharedViewModel.Factory): MavericksAssistedViewModelFactory<*, *>
+
+ @Binds
+ @IntoMap
+ @MavericksViewModelKey(ReviewTermsViewModel::class)
+ fun reviewTermsViewModelFactory(factory: ReviewTermsViewModel.Factory): MavericksAssistedViewModelFactory<*, *>
+
+ @Binds
+ @IntoMap
+ @MavericksViewModelKey(ShareSpaceViewModel::class)
+ fun shareSpaceViewModelFactory(factory: ShareSpaceViewModel.Factory): MavericksAssistedViewModelFactory<*, *>
+
+ @Binds
+ @IntoMap
+ @MavericksViewModelKey(SpacePreviewViewModel::class)
+ fun spacePreviewViewModelFactory(factory: SpacePreviewViewModel.Factory): MavericksAssistedViewModelFactory<*, *>
+
+ @Binds
+ @IntoMap
+ @MavericksViewModelKey(SpacePeopleViewModel::class)
+ fun spacePeopleViewModelFactory(factory: SpacePeopleViewModel.Factory): MavericksAssistedViewModelFactory<*, *>
+
+ @Binds
+ @IntoMap
+ @MavericksViewModelKey(SpaceAddRoomsViewModel::class)
+ fun spaceAddRoomsViewModelFactory(factory: SpaceAddRoomsViewModel.Factory): MavericksAssistedViewModelFactory<*, *>
+
+ @Binds
+ @IntoMap
+ @MavericksViewModelKey(SpaceLeaveAdvancedViewModel::class)
+ fun spaceLeaveAdvancedViewModelFactory(factory: SpaceLeaveAdvancedViewModel.Factory): MavericksAssistedViewModelFactory<*, *>
+
+ @Binds
+ @IntoMap
+ @MavericksViewModelKey(SpaceInviteBottomSheetViewModel::class)
+ fun spaceInviteBottomSheetViewModelFactory(factory: SpaceInviteBottomSheetViewModel.Factory): MavericksAssistedViewModelFactory<*, *>
+
+ @Binds
+ @IntoMap
+ @MavericksViewModelKey(SpaceDirectoryViewModel::class)
+ fun spaceDirectoryViewModelFactory(factory: SpaceDirectoryViewModel.Factory): MavericksAssistedViewModelFactory<*, *>
+
+ @Binds
+ @IntoMap
+ @MavericksViewModelKey(CreateSpaceViewModel::class)
+ fun createSpaceViewModelFactory(factory: CreateSpaceViewModel.Factory): MavericksAssistedViewModelFactory<*, *>
+
+ @Binds
+ @IntoMap
+ @MavericksViewModelKey(SpaceMenuViewModel::class)
+ fun spaceMenuViewModelFactory(factory: SpaceMenuViewModel.Factory): MavericksAssistedViewModelFactory<*, *>
+
+ @Binds
+ @IntoMap
+ @MavericksViewModelKey(SoftLogoutViewModel::class)
+ fun softLogoutViewModelFactory(factory: SoftLogoutViewModel.Factory): MavericksAssistedViewModelFactory<*, *>
+
+ @Binds
+ @IntoMap
+ @MavericksViewModelKey(IncomingShareViewModel::class)
+ fun incomingShareViewModelFactory(factory: IncomingShareViewModel.Factory): MavericksAssistedViewModelFactory<*, *>
+
+ @Binds
+ @IntoMap
+ @MavericksViewModelKey(ThreePidsSettingsViewModel::class)
+ fun threePidsSettingsViewModelFactory(factory: ThreePidsSettingsViewModel.Factory): MavericksAssistedViewModelFactory<*, *>
+
+ @Binds
+ @IntoMap
+ @MavericksViewModelKey(PushGatewaysViewModel::class)
+ fun pushGatewaysViewModelFactory(factory: PushGatewaysViewModel.Factory): MavericksAssistedViewModelFactory<*, *>
+
+ @Binds
+ @IntoMap
+ @MavericksViewModelKey(HomeserverSettingsViewModel::class)
+ fun homeserverSettingsViewModelFactory(factory: HomeserverSettingsViewModel.Factory): MavericksAssistedViewModelFactory<*, *>
+
+ @Binds
+ @IntoMap
+ @MavericksViewModelKey(LocalePickerViewModel::class)
+ fun localePickerViewModelFactory(factory: LocalePickerViewModel.Factory): MavericksAssistedViewModelFactory<*, *>
+
+ @Binds
+ @IntoMap
+ @MavericksViewModelKey(GossipingEventsPaperTrailViewModel::class)
+ fun gossipingEventsPaperTrailViewModelFactory(factory: GossipingEventsPaperTrailViewModel.Factory): MavericksAssistedViewModelFactory<*, *>
+
+ @Binds
+ @IntoMap
+ @MavericksViewModelKey(AccountDataViewModel::class)
+ fun accountDataViewModelFactory(factory: AccountDataViewModel.Factory): MavericksAssistedViewModelFactory<*, *>
+
+ @Binds
+ @IntoMap
+ @MavericksViewModelKey(DevicesViewModel::class)
+ fun devicesViewModelFactory(factory: DevicesViewModel.Factory): MavericksAssistedViewModelFactory<*, *>
+
+ @Binds
+ @IntoMap
+ @MavericksViewModelKey(KeyRequestListViewModel::class)
+ fun keyRequestListViewModelFactory(factory: KeyRequestListViewModel.Factory): MavericksAssistedViewModelFactory<*, *>
+
+ @Binds
+ @IntoMap
+ @MavericksViewModelKey(KeyRequestViewModel::class)
+ fun keyRequestViewModelFactory(factory: KeyRequestViewModel.Factory): MavericksAssistedViewModelFactory<*, *>
+
+ @Binds
+ @IntoMap
+ @MavericksViewModelKey(CrossSigningSettingsViewModel::class)
+ fun crossSigningSettingsViewModelFactory(factory: CrossSigningSettingsViewModel.Factory): MavericksAssistedViewModelFactory<*, *>
+
+ @Binds
+ @IntoMap
+ @MavericksViewModelKey(DeactivateAccountViewModel::class)
+ fun deactivateAccountViewModelFactory(factory: DeactivateAccountViewModel.Factory): MavericksAssistedViewModelFactory<*, *>
+
+ @Binds
+ @IntoMap
+ @MavericksViewModelKey(RoomUploadsViewModel::class)
+ fun roomUploadsViewModelFactory(factory: RoomUploadsViewModel.Factory): MavericksAssistedViewModelFactory<*, *>
+
+ @Binds
+ @IntoMap
+ @MavericksViewModelKey(RoomJoinRuleChooseRestrictedViewModel::class)
+ fun roomJoinRuleChooseRestrictedViewModelFactory(factory: RoomJoinRuleChooseRestrictedViewModel.Factory): MavericksAssistedViewModelFactory<*, *>
+
+ @Binds
+ @IntoMap
+ @MavericksViewModelKey(RoomSettingsViewModel::class)
+ fun roomSettingsViewModelFactory(factory: RoomSettingsViewModel.Factory): MavericksAssistedViewModelFactory<*, *>
+
+ @Binds
+ @IntoMap
+ @MavericksViewModelKey(RoomPermissionsViewModel::class)
+ fun roomPermissionsViewModelFactory(factory: RoomPermissionsViewModel.Factory): MavericksAssistedViewModelFactory<*, *>
+
+ @Binds
+ @IntoMap
+ @MavericksViewModelKey(RoomMemberListViewModel::class)
+ fun roomMemberListViewModelFactory(factory: RoomMemberListViewModel.Factory): MavericksAssistedViewModelFactory<*, *>
+
+ @Binds
+ @IntoMap
+ @MavericksViewModelKey(RoomBannedMemberListViewModel::class)
+ fun roomBannedMemberListViewModelFactory(factory: RoomBannedMemberListViewModel.Factory): MavericksAssistedViewModelFactory<*, *>
+
+ @Binds
+ @IntoMap
+ @MavericksViewModelKey(RoomAliasViewModel::class)
+ fun roomAliasViewModelFactory(factory: RoomAliasViewModel.Factory): MavericksAssistedViewModelFactory<*, *>
+
+ @Binds
+ @IntoMap
+ @MavericksViewModelKey(RoomAliasBottomSheetViewModel::class)
+ fun roomAliasBottomSheetViewModelFactory(factory: RoomAliasBottomSheetViewModel.Factory): MavericksAssistedViewModelFactory<*, *>
+
+ @Binds
+ @IntoMap
+ @MavericksViewModelKey(RoomProfileViewModel::class)
+ fun roomProfileViewModelFactory(factory: RoomProfileViewModel.Factory): MavericksAssistedViewModelFactory<*, *>
+
+ @Binds
+ @IntoMap
+ @MavericksViewModelKey(RoomMemberProfileViewModel::class)
+ fun roomMemberProfileViewModelFactory(factory: RoomMemberProfileViewModel.Factory): MavericksAssistedViewModelFactory<*, *>
+
+ @Binds
+ @IntoMap
+ @MavericksViewModelKey(RoomPreviewViewModel::class)
+ fun roomPreviewViewModelFactory(factory: RoomPreviewViewModel.Factory): MavericksAssistedViewModelFactory<*, *>
+
+ @Binds
+ @IntoMap
+ @MavericksViewModelKey(CreateRoomViewModel::class)
+ fun createRoomViewModelFactory(factory: CreateRoomViewModel.Factory): MavericksAssistedViewModelFactory<*, *>
+
+ @Binds
+ @IntoMap
+ @MavericksViewModelKey(RequireActiveMembershipViewModel::class)
+ fun requireActiveMembershipViewModelFactory(factory: RequireActiveMembershipViewModel.Factory): MavericksAssistedViewModelFactory<*, *>
+
+ @Binds
+ @IntoMap
+ @MavericksViewModelKey(EmojiSearchResultViewModel::class)
+ fun emojiSearchResultViewModelFactory(factory: EmojiSearchResultViewModel.Factory): MavericksAssistedViewModelFactory<*, *>
+
+ @Binds
+ @IntoMap
+ @MavericksViewModelKey(BugReportViewModel::class)
+ fun bugReportViewModelFactory(factory: BugReportViewModel.Factory): MavericksAssistedViewModelFactory<*, *>
+
+ @Binds
+ @IntoMap
+ @MavericksViewModelKey(MatrixToBottomSheetViewModel::class)
+ fun matrixToBottomSheetViewModelFactory(factory: MatrixToBottomSheetViewModel.Factory): MavericksAssistedViewModelFactory<*, *>
+
+ @Binds
+ @IntoMap
+ @MavericksViewModelKey(AccountCreatedViewModel::class)
+ fun accountCreatedViewModelFactory(factory: AccountCreatedViewModel.Factory): MavericksAssistedViewModelFactory<*, *>
+
+ @Binds
+ @IntoMap
+ @MavericksViewModelKey(LoginViewModel2::class)
+ fun loginViewModel2Factory(factory: LoginViewModel2.Factory): MavericksAssistedViewModelFactory<*, *>
+
+ @Binds
+ @IntoMap
+ @MavericksViewModelKey(LoginViewModel::class)
+ fun loginViewModelFactory(factory: LoginViewModel.Factory): MavericksAssistedViewModelFactory<*, *>
+
+ @Binds
+ @IntoMap
+ @MavericksViewModelKey(HomeServerCapabilitiesViewModel::class)
+ fun homeServerCapabilitiesViewModelFactory(factory: HomeServerCapabilitiesViewModel.Factory): MavericksAssistedViewModelFactory<*, *>
+
+ @Binds
+ @IntoMap
+ @MavericksViewModelKey(InviteUsersToRoomViewModel::class)
+ fun inviteUsersToRoomViewModelFactory(factory: InviteUsersToRoomViewModel.Factory): MavericksAssistedViewModelFactory<*, *>
+
+ @Binds
+ @IntoMap
+ @MavericksViewModelKey(ViewEditHistoryViewModel::class)
+ fun viewEditHistoryViewModelFactory(factory: ViewEditHistoryViewModel.Factory): MavericksAssistedViewModelFactory<*, *>
+
+ @Binds
+ @IntoMap
+ @MavericksViewModelKey(MessageActionsViewModel::class)
+ fun messageActionsViewModelFactory(factory: MessageActionsViewModel.Factory): MavericksAssistedViewModelFactory<*, *>
+
+ @Binds
+ @IntoMap
+ @MavericksViewModelKey(VerificationChooseMethodViewModel::class)
+ fun verificationChooseMethodViewModelFactory(factory: VerificationChooseMethodViewModel.Factory): MavericksAssistedViewModelFactory<*, *>
+
+ @Binds
+ @IntoMap
+ @MavericksViewModelKey(VerificationEmojiCodeViewModel::class)
+ fun verificationEmojiCodeViewModelFactory(factory: VerificationEmojiCodeViewModel.Factory): MavericksAssistedViewModelFactory<*, *>
+
+ @Binds
+ @IntoMap
+ @MavericksViewModelKey(SearchViewModel::class)
+ fun searchViewModelFactory(factory: SearchViewModel.Factory): MavericksAssistedViewModelFactory<*, *>
+
+ @Binds
+ @IntoMap
+ @MavericksViewModelKey(UnreadMessagesSharedViewModel::class)
+ fun unreadMessagesSharedViewModelFactory(factory: UnreadMessagesSharedViewModel.Factory): MavericksAssistedViewModelFactory<*, *>
+
+ @Binds
+ @IntoMap
+ @MavericksViewModelKey(UnknownDeviceDetectorSharedViewModel::class)
+ fun unknownDeviceDetectorSharedViewModelFactory(factory: UnknownDeviceDetectorSharedViewModel.Factory): MavericksAssistedViewModelFactory<*, *>
+
+ @Binds
+ @IntoMap
+ @MavericksViewModelKey(DiscoverySettingsViewModel::class)
+ fun discoverySettingsViewModelFactory(factory: DiscoverySettingsViewModel.Factory): MavericksAssistedViewModelFactory<*, *>
+
+ @Binds
+ @IntoMap
+ @MavericksViewModelKey(TextComposerViewModel::class)
+ fun textComposerViewModelFactory(factory: TextComposerViewModel.Factory): MavericksAssistedViewModelFactory<*, *>
+
+ @Binds
+ @IntoMap
+ @MavericksViewModelKey(SetIdentityServerViewModel::class)
+ fun setIdentityServerViewModelFactory(factory: SetIdentityServerViewModel.Factory): MavericksAssistedViewModelFactory<*, *>
+
+ @Binds
+ @IntoMap
+ @MavericksViewModelKey(BreadcrumbsViewModel::class)
+ fun breadcrumbsViewModelFactory(factory: BreadcrumbsViewModel.Factory): MavericksAssistedViewModelFactory<*, *>
+
+ @Binds
+ @IntoMap
+ @MavericksViewModelKey(HomeDetailViewModel::class)
+ fun homeDetailViewModelFactory(factory: HomeDetailViewModel.Factory): MavericksAssistedViewModelFactory<*, *>
+
+ @Binds
+ @IntoMap
+ @MavericksViewModelKey(DeviceVerificationInfoBottomSheetViewModel::class)
+ fun deviceVerificationInfoBottomSheetViewModelFactory(factory: DeviceVerificationInfoBottomSheetViewModel.Factory): MavericksAssistedViewModelFactory<*, *>
+
+ @Binds
+ @IntoMap
+ @MavericksViewModelKey(DeviceListBottomSheetViewModel::class)
+ fun deviceListBottomSheetViewModelFactory(factory: DeviceListBottomSheetViewModel.Factory): MavericksAssistedViewModelFactory<*, *>
+
+ @Binds
+ @IntoMap
+ @MavericksViewModelKey(HomeActivityViewModel::class)
+ fun homeActivityViewModelFactory(factory: HomeActivityViewModel.Factory): MavericksAssistedViewModelFactory<*, *>
+
+ @Binds
+ @IntoMap
+ @MavericksViewModelKey(BootstrapSharedViewModel::class)
+ fun bootstrapSharedViewModelFactory(factory: BootstrapSharedViewModel.Factory): MavericksAssistedViewModelFactory<*, *>
+
+ @Binds
+ @IntoMap
+ @MavericksViewModelKey(VerificationBottomSheetViewModel::class)
+ fun verificationBottomSheetViewModelFactory(factory: VerificationBottomSheetViewModel.Factory): MavericksAssistedViewModelFactory<*, *>
+
+ @Binds
+ @IntoMap
+ @MavericksViewModelKey(CreatePollViewModel::class)
+ fun createPollViewModelFactory(factory: CreatePollViewModel.Factory): MavericksAssistedViewModelFactory<*, *>
+}
diff --git a/vector/src/main/java/im/vector/app/core/di/ScreenScope.kt b/vector/src/main/java/im/vector/app/core/di/MavericksViewModelScoped.kt
similarity index 71%
rename from vector/src/main/java/im/vector/app/core/di/ScreenScope.kt
rename to vector/src/main/java/im/vector/app/core/di/MavericksViewModelScoped.kt
index c39d6a947e..58b9246fe5 100644
--- a/vector/src/main/java/im/vector/app/core/di/ScreenScope.kt
+++ b/vector/src/main/java/im/vector/app/core/di/MavericksViewModelScoped.kt
@@ -1,11 +1,11 @@
/*
- * Copyright 2019 New Vector Ltd
+ * Copyright (c) 2021 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
+ * 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,
@@ -18,7 +18,8 @@ package im.vector.app.core.di
import javax.inject.Scope
+/**
+ * Scope annotation for bindings that should exist for the life of an MavericksViewModel.
+ */
@Scope
-@MustBeDocumented
-@Retention(AnnotationRetention.RUNTIME)
-annotation class ScreenScope
+annotation class MavericksViewModelScoped
diff --git a/vector/src/main/java/im/vector/app/core/di/ScreenComponent.kt b/vector/src/main/java/im/vector/app/core/di/ScreenComponent.kt
deleted file mode 100644
index 2ec330efe6..0000000000
--- a/vector/src/main/java/im/vector/app/core/di/ScreenComponent.kt
+++ /dev/null
@@ -1,221 +0,0 @@
-/*
- * Copyright 2019 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 im.vector.app.core.di
-
-import androidx.appcompat.app.AppCompatActivity
-import androidx.fragment.app.FragmentFactory
-import androidx.lifecycle.ViewModelProvider
-import dagger.BindsInstance
-import dagger.Component
-import im.vector.app.core.dialogs.UnrecognizedCertificateDialog
-import im.vector.app.core.error.ErrorFormatter
-import im.vector.app.core.preference.UserAvatarPreference
-import im.vector.app.features.MainActivity
-import im.vector.app.features.auth.ReAuthActivity
-import im.vector.app.features.call.CallControlsBottomSheet
-import im.vector.app.features.call.VectorCallActivity
-import im.vector.app.features.call.conference.VectorJitsiActivity
-import im.vector.app.features.call.transfer.CallTransferActivity
-import im.vector.app.features.createdirect.CreateDirectRoomActivity
-import im.vector.app.features.crypto.keysbackup.settings.KeysBackupManageActivity
-import im.vector.app.features.crypto.keysbackup.setup.KeysBackupSetupActivity
-import im.vector.app.features.crypto.quads.SharedSecureStorageActivity
-import im.vector.app.features.crypto.recover.BootstrapBottomSheet
-import im.vector.app.features.crypto.verification.VerificationBottomSheet
-import im.vector.app.features.debug.DebugMenuActivity
-import im.vector.app.features.devtools.RoomDevToolActivity
-import im.vector.app.features.home.HomeActivity
-import im.vector.app.features.home.HomeModule
-import im.vector.app.features.home.room.detail.JoinReplacementRoomBottomSheet
-import im.vector.app.features.home.room.detail.RoomDetailActivity
-import im.vector.app.features.home.room.detail.readreceipts.DisplayReadReceiptsBottomSheet
-import im.vector.app.features.home.room.detail.search.SearchActivity
-import im.vector.app.features.home.room.detail.timeline.action.MessageActionsBottomSheet
-import im.vector.app.features.home.room.detail.timeline.edithistory.ViewEditHistoryBottomSheet
-import im.vector.app.features.home.room.detail.timeline.reactions.ViewReactionsBottomSheet
-import im.vector.app.features.home.room.detail.upgrade.MigrateRoomBottomSheet
-import im.vector.app.features.home.room.detail.widget.RoomWidgetsBottomSheet
-import im.vector.app.features.home.room.filtered.FilteredRoomsActivity
-import im.vector.app.features.home.room.list.RoomListModule
-import im.vector.app.features.home.room.list.actions.RoomListQuickActionsBottomSheet
-import im.vector.app.features.invite.AutoAcceptInvites
-import im.vector.app.features.invite.InviteUsersToRoomActivity
-import im.vector.app.features.invite.VectorInviteView
-import im.vector.app.features.link.LinkHandlerActivity
-import im.vector.app.features.login.LoginActivity
-import im.vector.app.features.login2.LoginActivity2
-import im.vector.app.features.matrixto.MatrixToBottomSheet
-import im.vector.app.features.media.BigImageViewerActivity
-import im.vector.app.features.media.VectorAttachmentViewerActivity
-import im.vector.app.features.navigation.Navigator
-import im.vector.app.features.permalink.PermalinkHandlerActivity
-import im.vector.app.features.pin.PinLocker
-import im.vector.app.features.qrcode.QrCodeScannerActivity
-import im.vector.app.features.rageshake.BugReportActivity
-import im.vector.app.features.rageshake.BugReporter
-import im.vector.app.features.rageshake.RageShake
-import im.vector.app.features.reactions.EmojiReactionPickerActivity
-import im.vector.app.features.reactions.widget.ReactionButton
-import im.vector.app.features.roomdirectory.RoomDirectoryActivity
-import im.vector.app.features.roomdirectory.createroom.CreateRoomActivity
-import im.vector.app.features.roommemberprofile.RoomMemberProfileActivity
-import im.vector.app.features.roommemberprofile.devices.DeviceListBottomSheet
-import im.vector.app.features.roomprofile.RoomProfileActivity
-import im.vector.app.features.roomprofile.alias.detail.RoomAliasBottomSheet
-import im.vector.app.features.roomprofile.settings.historyvisibility.RoomHistoryVisibilityBottomSheet
-import im.vector.app.features.roomprofile.settings.joinrule.RoomJoinRuleActivity
-import im.vector.app.features.roomprofile.settings.joinrule.RoomJoinRuleBottomSheet
-import im.vector.app.features.settings.VectorSettingsActivity
-import im.vector.app.features.settings.devices.DeviceVerificationInfoBottomSheet
-import im.vector.app.features.share.IncomingShareActivity
-import im.vector.app.features.signout.soft.SoftLogoutActivity
-import im.vector.app.features.spaces.InviteRoomSpaceChooserBottomSheet
-import im.vector.app.features.spaces.SpaceCreationActivity
-import im.vector.app.features.spaces.SpaceExploreActivity
-import im.vector.app.features.spaces.SpaceSettingsMenuBottomSheet
-import im.vector.app.features.spaces.invite.SpaceInviteBottomSheet
-import im.vector.app.features.spaces.manage.SpaceManageActivity
-import im.vector.app.features.spaces.share.ShareSpaceBottomSheet
-import im.vector.app.features.terms.ReviewTermsActivity
-import im.vector.app.features.ui.UiStateRepository
-import im.vector.app.features.usercode.UserCodeActivity
-import im.vector.app.features.widgets.WidgetActivity
-import im.vector.app.features.widgets.permissions.RoomWidgetPermissionBottomSheet
-import im.vector.app.features.workers.signout.SignOutBottomSheetDialogFragment
-
-@Component(
- dependencies = [
- VectorComponent::class
- ],
- modules = [
- ViewModelModule::class,
- FragmentModule::class,
- HomeModule::class,
- RoomListModule::class,
- ScreenModule::class
- ]
-)
-@ScreenScope
-interface ScreenComponent {
-
- /* ==========================================================================================
- * Shortcut to VectorComponent elements
- * ========================================================================================== */
-
- fun activeSessionHolder(): ActiveSessionHolder
- fun fragmentFactory(): FragmentFactory
- fun viewModelFactory(): ViewModelProvider.Factory
- fun bugReporter(): BugReporter
- fun rageShake(): RageShake
- fun navigator(): Navigator
- fun pinLocker(): PinLocker
- fun errorFormatter(): ErrorFormatter
- fun uiStateRepository(): UiStateRepository
- fun unrecognizedCertificateDialog(): UnrecognizedCertificateDialog
- fun autoAcceptInvites(): AutoAcceptInvites
-
- /* ==========================================================================================
- * Activities
- * ========================================================================================== */
-
- fun inject(activity: HomeActivity)
- fun inject(activity: RoomDetailActivity)
- fun inject(activity: RoomProfileActivity)
- fun inject(activity: RoomMemberProfileActivity)
- fun inject(activity: VectorSettingsActivity)
- fun inject(activity: KeysBackupManageActivity)
- fun inject(activity: EmojiReactionPickerActivity)
- fun inject(activity: LoginActivity)
- fun inject(activity: LoginActivity2)
- fun inject(activity: LinkHandlerActivity)
- fun inject(activity: MainActivity)
- fun inject(activity: RoomDirectoryActivity)
- fun inject(activity: KeysBackupSetupActivity)
- fun inject(activity: BugReportActivity)
- fun inject(activity: FilteredRoomsActivity)
- fun inject(activity: CreateRoomActivity)
- fun inject(activity: CreateDirectRoomActivity)
- fun inject(activity: IncomingShareActivity)
- fun inject(activity: SoftLogoutActivity)
- fun inject(activity: PermalinkHandlerActivity)
- fun inject(activity: QrCodeScannerActivity)
- fun inject(activity: DebugMenuActivity)
- fun inject(activity: SharedSecureStorageActivity)
- fun inject(activity: BigImageViewerActivity)
- fun inject(activity: InviteUsersToRoomActivity)
- fun inject(activity: ReviewTermsActivity)
- fun inject(activity: WidgetActivity)
- fun inject(activity: VectorCallActivity)
- fun inject(activity: VectorAttachmentViewerActivity)
- fun inject(activity: VectorJitsiActivity)
- fun inject(activity: SearchActivity)
- fun inject(activity: UserCodeActivity)
- fun inject(activity: CallTransferActivity)
- fun inject(activity: ReAuthActivity)
- fun inject(activity: RoomDevToolActivity)
- fun inject(activity: SpaceCreationActivity)
- fun inject(activity: SpaceExploreActivity)
- fun inject(activity: SpaceManageActivity)
- fun inject(activity: RoomJoinRuleActivity)
-
- /* ==========================================================================================
- * BottomSheets
- * ========================================================================================== */
-
- fun inject(bottomSheet: MessageActionsBottomSheet)
- fun inject(bottomSheet: ViewReactionsBottomSheet)
- fun inject(bottomSheet: ViewEditHistoryBottomSheet)
- fun inject(bottomSheet: DisplayReadReceiptsBottomSheet)
- fun inject(bottomSheet: RoomListQuickActionsBottomSheet)
- fun inject(bottomSheet: RoomAliasBottomSheet)
- fun inject(bottomSheet: RoomHistoryVisibilityBottomSheet)
- fun inject(bottomSheet: RoomJoinRuleBottomSheet)
- fun inject(bottomSheet: VerificationBottomSheet)
- fun inject(bottomSheet: DeviceVerificationInfoBottomSheet)
- fun inject(bottomSheet: DeviceListBottomSheet)
- fun inject(bottomSheet: BootstrapBottomSheet)
- fun inject(bottomSheet: RoomWidgetPermissionBottomSheet)
- fun inject(bottomSheet: RoomWidgetsBottomSheet)
- fun inject(bottomSheet: CallControlsBottomSheet)
- fun inject(bottomSheet: SignOutBottomSheetDialogFragment)
- fun inject(bottomSheet: MatrixToBottomSheet)
- fun inject(bottomSheet: ShareSpaceBottomSheet)
- fun inject(bottomSheet: SpaceSettingsMenuBottomSheet)
- fun inject(bottomSheet: InviteRoomSpaceChooserBottomSheet)
- fun inject(bottomSheet: SpaceInviteBottomSheet)
- fun inject(bottomSheet: JoinReplacementRoomBottomSheet)
- fun inject(bottomSheet: MigrateRoomBottomSheet)
-
- /* ==========================================================================================
- * Others
- * ========================================================================================== */
-
- fun inject(view: VectorInviteView)
- fun inject(preference: UserAvatarPreference)
- fun inject(button: ReactionButton)
-
- /* ==========================================================================================
- * Factory
- * ========================================================================================== */
-
- @Component.Factory
- interface Factory {
- fun create(vectorComponent: VectorComponent,
- @BindsInstance context: AppCompatActivity
- ): ScreenComponent
- }
-}
diff --git a/vector/src/main/java/im/vector/app/core/di/ScreenModule.kt b/vector/src/main/java/im/vector/app/core/di/ScreenModule.kt
index 5f50f186d0..2dab05378c 100644
--- a/vector/src/main/java/im/vector/app/core/di/ScreenModule.kt
+++ b/vector/src/main/java/im/vector/app/core/di/ScreenModule.kt
@@ -1,11 +1,11 @@
/*
- * Copyright 2019 New Vector Ltd
+ * Copyright (c) 2021 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
+ * 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,
@@ -20,9 +20,13 @@ import androidx.appcompat.app.AppCompatActivity
import androidx.recyclerview.widget.RecyclerView
import dagger.Module
import dagger.Provides
+import dagger.hilt.InstallIn
+import dagger.hilt.android.components.ActivityComponent
+import dagger.hilt.android.scopes.ActivityScoped
import im.vector.app.core.glide.GlideApp
@Module
+@InstallIn(ActivityComponent::class)
object ScreenModule {
@Provides
@@ -31,6 +35,6 @@ object ScreenModule {
@Provides
@JvmStatic
- @ScreenScope
+ @ActivityScoped
fun providesSharedViewPool() = RecyclerView.RecycledViewPool()
}
diff --git a/vector/src/main/java/im/vector/app/core/di/SingletonEntryPoint.kt b/vector/src/main/java/im/vector/app/core/di/SingletonEntryPoint.kt
new file mode 100644
index 0000000000..52316751e6
--- /dev/null
+++ b/vector/src/main/java/im/vector/app/core/di/SingletonEntryPoint.kt
@@ -0,0 +1,61 @@
+/*
+ * Copyright (c) 2021 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 im.vector.app.core.di
+
+import dagger.hilt.EntryPoint
+import dagger.hilt.InstallIn
+import dagger.hilt.components.SingletonComponent
+import im.vector.app.core.dialogs.UnrecognizedCertificateDialog
+import im.vector.app.core.error.ErrorFormatter
+import im.vector.app.features.call.webrtc.WebRtcCallManager
+import im.vector.app.features.home.AvatarRenderer
+import im.vector.app.features.navigation.Navigator
+import im.vector.app.features.pin.PinLocker
+import im.vector.app.features.rageshake.BugReporter
+import im.vector.app.features.session.SessionListener
+import im.vector.app.features.settings.VectorPreferences
+import im.vector.app.features.ui.UiStateRepository
+import kotlinx.coroutines.CoroutineScope
+
+@InstallIn(SingletonComponent::class)
+@EntryPoint
+interface SingletonEntryPoint {
+
+ fun sessionListener(): SessionListener
+
+ fun avatarRenderer(): AvatarRenderer
+
+ fun activeSessionHolder(): ActiveSessionHolder
+
+ fun unrecognizedCertificateDialog(): UnrecognizedCertificateDialog
+
+ fun navigator(): Navigator
+
+ fun errorFormatter(): ErrorFormatter
+
+ fun bugReporter(): BugReporter
+
+ fun vectorPreferences(): VectorPreferences
+
+ fun uiStateRepository(): UiStateRepository
+
+ fun pinLocker(): PinLocker
+
+ fun webRtcCallManager(): WebRtcCallManager
+
+ fun appCoroutineScope(): CoroutineScope
+}
diff --git a/vector/src/main/java/im/vector/app/core/di/VectorModule.kt b/vector/src/main/java/im/vector/app/core/di/SingletonModule.kt
similarity index 50%
rename from vector/src/main/java/im/vector/app/core/di/VectorModule.kt
rename to vector/src/main/java/im/vector/app/core/di/SingletonModule.kt
index 006a2f5aa0..a3d8f39b30 100644
--- a/vector/src/main/java/im/vector/app/core/di/VectorModule.kt
+++ b/vector/src/main/java/im/vector/app/core/di/SingletonModule.kt
@@ -16,6 +16,7 @@
package im.vector.app.core.di
+import android.app.Application
import android.content.Context
import android.content.Context.MODE_PRIVATE
import android.content.SharedPreferences
@@ -23,6 +24,9 @@ import android.content.res.Resources
import dagger.Binds
import dagger.Module
import dagger.Provides
+import dagger.hilt.InstallIn
+import dagger.hilt.components.SingletonComponent
+import im.vector.app.core.dispatchers.CoroutineDispatchers
import im.vector.app.core.error.DefaultErrorFormatter
import im.vector.app.core.error.ErrorFormatter
import im.vector.app.features.invite.AutoAcceptInvites
@@ -33,68 +37,20 @@ import im.vector.app.features.pin.PinCodeStore
import im.vector.app.features.pin.SharedPrefPinCodeStore
import im.vector.app.features.ui.SharedPreferencesUiStateRepository
import im.vector.app.features.ui.UiStateRepository
+import kotlinx.coroutines.CoroutineScope
+import kotlinx.coroutines.Dispatchers
+import kotlinx.coroutines.SupervisorJob
import org.matrix.android.sdk.api.Matrix
import org.matrix.android.sdk.api.auth.AuthenticationService
import org.matrix.android.sdk.api.auth.HomeServerHistoryService
import org.matrix.android.sdk.api.legacy.LegacySessionImporter
import org.matrix.android.sdk.api.raw.RawService
import org.matrix.android.sdk.api.session.Session
+import javax.inject.Singleton
+@InstallIn(SingletonComponent::class)
@Module
-abstract class VectorModule {
-
- @Module
- companion object {
-
- @Provides
- @JvmStatic
- fun providesResources(context: Context): Resources {
- return context.resources
- }
-
- @Provides
- @JvmStatic
- fun providesSharedPreferences(context: Context): SharedPreferences {
- return context.getSharedPreferences("im.vector.riot", MODE_PRIVATE)
- }
-
- @Provides
- @JvmStatic
- fun providesMatrix(context: Context): Matrix {
- return Matrix.getInstance(context)
- }
-
- @Provides
- @JvmStatic
- fun providesCurrentSession(activeSessionHolder: ActiveSessionHolder): Session {
- // TODO: handle session injection better
- return activeSessionHolder.getActiveSession()
- }
-
- @Provides
- @JvmStatic
- fun providesLegacySessionImporter(matrix: Matrix): LegacySessionImporter {
- return matrix.legacySessionImporter()
- }
-
- @Provides
- @JvmStatic
- fun providesAuthenticationService(matrix: Matrix): AuthenticationService {
- return matrix.authenticationService()
- }
-
- @Provides
- @JvmStatic
- fun providesRawService(matrix: Matrix): RawService {
- return matrix.rawService()
- }
-
- @Provides
- @JvmStatic
- fun providesHomeServerHistoryService(matrix: Matrix): HomeServerHistoryService {
- return matrix.homeServerHistoryService()
- }
- }
+abstract class VectorBindModule {
@Binds
abstract fun bindNavigator(navigator: DefaultNavigator): Navigator
@@ -111,3 +67,76 @@ abstract class VectorModule {
@Binds
abstract fun bindAutoAcceptInvites(autoAcceptInvites: CompileTimeAutoAcceptInvites): AutoAcceptInvites
}
+
+@InstallIn(SingletonComponent::class)
+@Module
+object VectorStaticModule {
+
+ @Provides
+ @JvmStatic
+ fun providesContext(application: Application): Context {
+ return application.applicationContext
+ }
+
+ @Provides
+ @JvmStatic
+ fun providesResources(context: Context): Resources {
+ return context.resources
+ }
+
+ @Provides
+ @JvmStatic
+ fun providesSharedPreferences(context: Context): SharedPreferences {
+ return context.getSharedPreferences("im.vector.riot", MODE_PRIVATE)
+ }
+
+ @Provides
+ @JvmStatic
+ fun providesMatrix(context: Context): Matrix {
+ return Matrix.getInstance(context)
+ }
+
+ @Provides
+ @JvmStatic
+ fun providesCurrentSession(activeSessionHolder: ActiveSessionHolder): Session {
+ // TODO: handle session injection better
+ return activeSessionHolder.getActiveSession()
+ }
+
+ @Provides
+ @JvmStatic
+ fun providesLegacySessionImporter(matrix: Matrix): LegacySessionImporter {
+ return matrix.legacySessionImporter()
+ }
+
+ @Provides
+ @JvmStatic
+ fun providesAuthenticationService(matrix: Matrix): AuthenticationService {
+ return matrix.authenticationService()
+ }
+
+ @Provides
+ @JvmStatic
+ fun providesRawService(matrix: Matrix): RawService {
+ return matrix.rawService()
+ }
+
+ @Provides
+ @JvmStatic
+ fun providesHomeServerHistoryService(matrix: Matrix): HomeServerHistoryService {
+ return matrix.homeServerHistoryService()
+ }
+
+ @Provides
+ @JvmStatic
+ @Singleton
+ fun providesApplicationCoroutineScope(): CoroutineScope {
+ return CoroutineScope(SupervisorJob() + Dispatchers.Main)
+ }
+
+ @Provides
+ @JvmStatic
+ fun providesCoroutineDispatchers(): CoroutineDispatchers {
+ return CoroutineDispatchers(io = Dispatchers.IO, computation = Dispatchers.Default)
+ }
+}
diff --git a/vector/src/main/java/im/vector/app/core/di/VectorComponent.kt b/vector/src/main/java/im/vector/app/core/di/VectorComponent.kt
deleted file mode 100644
index 4a3379cb5a..0000000000
--- a/vector/src/main/java/im/vector/app/core/di/VectorComponent.kt
+++ /dev/null
@@ -1,174 +0,0 @@
-/*
- * Copyright 2019 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 im.vector.app.core.di
-
-import android.content.Context
-import android.content.res.Resources
-import dagger.BindsInstance
-import dagger.Component
-import im.vector.app.ActiveSessionDataSource
-import im.vector.app.AppStateHandler
-import im.vector.app.EmojiCompatFontProvider
-import im.vector.app.EmojiCompatWrapper
-import im.vector.app.VectorApplication
-import im.vector.app.core.dialogs.UnrecognizedCertificateDialog
-import im.vector.app.core.error.ErrorFormatter
-import im.vector.app.core.network.WifiDetector
-import im.vector.app.core.pushers.PushersManager
-import im.vector.app.core.utils.AssetReader
-import im.vector.app.core.utils.DimensionConverter
-import im.vector.app.features.call.webrtc.WebRtcCallManager
-import im.vector.app.features.configuration.VectorConfiguration
-import im.vector.app.features.crypto.keysrequest.KeyRequestHandler
-import im.vector.app.features.crypto.verification.IncomingVerificationRequestHandler
-import im.vector.app.features.home.AvatarRenderer
-import im.vector.app.features.home.CurrentSpaceSuggestedRoomListDataSource
-import im.vector.app.features.home.room.detail.RoomDetailPendingActionStore
-import im.vector.app.features.home.room.detail.timeline.helper.MatrixItemColorProvider
-import im.vector.app.features.home.room.detail.timeline.helper.RoomSummariesHolder
-import im.vector.app.features.html.EventHtmlRenderer
-import im.vector.app.features.html.VectorHtmlCompressor
-import im.vector.app.features.invite.AutoAcceptInvites
-import im.vector.app.features.login.ReAuthHelper
-import im.vector.app.features.navigation.Navigator
-import im.vector.app.features.notifications.NotifiableEventResolver
-import im.vector.app.features.notifications.NotificationBroadcastReceiver
-import im.vector.app.features.notifications.NotificationDrawerManager
-import im.vector.app.features.notifications.NotificationUtils
-import im.vector.app.features.notifications.PushRuleTriggerListener
-import im.vector.app.features.pin.PinCodeStore
-import im.vector.app.features.pin.PinLocker
-import im.vector.app.features.popup.PopupAlertManager
-import im.vector.app.features.rageshake.BugReporter
-import im.vector.app.features.rageshake.VectorFileLogger
-import im.vector.app.features.rageshake.VectorUncaughtExceptionHandler
-import im.vector.app.features.reactions.data.EmojiDataSource
-import im.vector.app.features.session.SessionListener
-import im.vector.app.features.settings.VectorPreferences
-import im.vector.app.features.ui.UiStateRepository
-import org.matrix.android.sdk.api.Matrix
-import org.matrix.android.sdk.api.auth.AuthenticationService
-import org.matrix.android.sdk.api.auth.HomeServerHistoryService
-import org.matrix.android.sdk.api.raw.RawService
-import org.matrix.android.sdk.api.session.Session
-import javax.inject.Singleton
-
-@Component(modules = [VectorModule::class])
-@Singleton
-interface VectorComponent {
-
- fun inject(notificationBroadcastReceiver: NotificationBroadcastReceiver)
-
- fun inject(vectorApplication: VectorApplication)
-
- fun matrix(): Matrix
-
- fun matrixItemColorProvider(): MatrixItemColorProvider
-
- fun sessionListener(): SessionListener
-
- fun currentSession(): Session
-
- fun notificationUtils(): NotificationUtils
-
- fun notificationDrawerManager(): NotificationDrawerManager
-
- fun appContext(): Context
-
- fun resources(): Resources
-
- fun assetReader(): AssetReader
-
- fun dimensionConverter(): DimensionConverter
-
- fun vectorConfiguration(): VectorConfiguration
-
- fun avatarRenderer(): AvatarRenderer
-
- fun activeSessionHolder(): ActiveSessionHolder
-
- fun unrecognizedCertificateDialog(): UnrecognizedCertificateDialog
-
- fun emojiCompatFontProvider(): EmojiCompatFontProvider
-
- fun emojiCompatWrapper(): EmojiCompatWrapper
-
- fun eventHtmlRenderer(): EventHtmlRenderer
-
- fun vectorHtmlCompressor(): VectorHtmlCompressor
-
- fun navigator(): Navigator
-
- fun errorFormatter(): ErrorFormatter
-
- fun appStateHandler(): AppStateHandler
-
- fun currentSpaceSuggestedRoomListDataSource(): CurrentSpaceSuggestedRoomListDataSource
-
- fun roomDetailPendingActionStore(): RoomDetailPendingActionStore
-
- fun activeSessionObservableStore(): ActiveSessionDataSource
-
- fun incomingVerificationRequestHandler(): IncomingVerificationRequestHandler
-
- fun incomingKeyRequestHandler(): KeyRequestHandler
-
- fun authenticationService(): AuthenticationService
-
- fun rawService(): RawService
-
- fun homeServerHistoryService(): HomeServerHistoryService
-
- fun bugReporter(): BugReporter
-
- fun vectorUncaughtExceptionHandler(): VectorUncaughtExceptionHandler
-
- fun pushRuleTriggerListener(): PushRuleTriggerListener
-
- fun pusherManager(): PushersManager
-
- fun notifiableEventResolver(): NotifiableEventResolver
-
- fun vectorPreferences(): VectorPreferences
-
- fun wifiDetector(): WifiDetector
-
- fun vectorFileLogger(): VectorFileLogger
-
- fun uiStateRepository(): UiStateRepository
-
- fun pinCodeStore(): PinCodeStore
-
- fun emojiDataSource(): EmojiDataSource
-
- fun alertManager(): PopupAlertManager
-
- fun reAuthHelper(): ReAuthHelper
-
- fun pinLocker(): PinLocker
-
- fun autoAcceptInvites(): AutoAcceptInvites
-
- fun webRtcCallManager(): WebRtcCallManager
-
- fun roomSummaryHolder(): RoomSummariesHolder
-
- @Component.Factory
- interface Factory {
- fun create(@BindsInstance context: Context): VectorComponent
- }
-}
diff --git a/vector/src/main/java/im/vector/app/core/di/ViewModelKey.kt b/vector/src/main/java/im/vector/app/core/di/ViewModelKey.kt
index 5f0ee30821..2782edd558 100644
--- a/vector/src/main/java/im/vector/app/core/di/ViewModelKey.kt
+++ b/vector/src/main/java/im/vector/app/core/di/ViewModelKey.kt
@@ -17,6 +17,7 @@
package im.vector.app.core.di
import androidx.lifecycle.ViewModel
+import com.airbnb.mvrx.MavericksViewModel
import dagger.MapKey
import kotlin.reflect.KClass
@@ -24,3 +25,8 @@ import kotlin.reflect.KClass
@Retention(AnnotationRetention.RUNTIME)
@MapKey
annotation class ViewModelKey(val value: KClass)
+
+@Retention(AnnotationRetention.RUNTIME)
+@Target(AnnotationTarget.FUNCTION)
+@MapKey
+annotation class MavericksViewModelKey(val value: KClass>)
diff --git a/vector/src/main/java/im/vector/app/core/di/ViewModelModule.kt b/vector/src/main/java/im/vector/app/core/di/ViewModelModule.kt
index 4e07c1e2ca..4f8329c026 100644
--- a/vector/src/main/java/im/vector/app/core/di/ViewModelModule.kt
+++ b/vector/src/main/java/im/vector/app/core/di/ViewModelModule.kt
@@ -20,6 +20,8 @@ import androidx.lifecycle.ViewModel
import androidx.lifecycle.ViewModelProvider
import dagger.Binds
import dagger.Module
+import dagger.hilt.InstallIn
+import dagger.hilt.android.components.ActivityComponent
import dagger.multibindings.IntoMap
import im.vector.app.core.platform.ConfigurationViewModel
import im.vector.app.features.call.SharedKnownCallsViewModel
@@ -42,6 +44,7 @@ import im.vector.app.features.spaces.SpacePreviewSharedActionViewModel
import im.vector.app.features.spaces.people.SpacePeopleSharedActionViewModel
import im.vector.app.features.userdirectory.UserListSharedActionViewModel
+@InstallIn(ActivityComponent::class)
@Module
interface ViewModelModule {
diff --git a/vector/src/main/java/im/vector/app/core/dispatchers/CoroutineDispatchers.kt b/vector/src/main/java/im/vector/app/core/dispatchers/CoroutineDispatchers.kt
new file mode 100644
index 0000000000..008ca4a9ce
--- /dev/null
+++ b/vector/src/main/java/im/vector/app/core/dispatchers/CoroutineDispatchers.kt
@@ -0,0 +1,24 @@
+/*
+ * Copyright (c) 2021 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 im.vector.app.core.dispatchers
+
+import kotlinx.coroutines.CoroutineDispatcher
+import javax.inject.Inject
+
+data class CoroutineDispatchers @Inject constructor(
+ val io: CoroutineDispatcher,
+ val computation: CoroutineDispatcher)
diff --git a/vector/src/main/java/im/vector/app/core/epoxy/bottomsheet/BottomSheetRadioActionItem.kt b/vector/src/main/java/im/vector/app/core/epoxy/bottomsheet/BottomSheetRadioActionItem.kt
index 91361aa89d..8899532d04 100644
--- a/vector/src/main/java/im/vector/app/core/epoxy/bottomsheet/BottomSheetRadioActionItem.kt
+++ b/vector/src/main/java/im/vector/app/core/epoxy/bottomsheet/BottomSheetRadioActionItem.kt
@@ -27,6 +27,7 @@ import im.vector.app.core.epoxy.ClickListener
import im.vector.app.core.epoxy.VectorEpoxyHolder
import im.vector.app.core.epoxy.VectorEpoxyModel
import im.vector.app.core.epoxy.onClick
+import im.vector.app.core.extensions.setAttributeTintedImageResource
import im.vector.app.core.extensions.setTextOrHide
/**
@@ -62,7 +63,7 @@ abstract class BottomSheetRadioActionItem : VectorEpoxyModel(R.id.matrixItemTitle)
val subtitleView by bind(R.id.matrixItemSubtitle)
+ val powerLabel by bind(R.id.matrixItemPowerLevelLabel)
+ val presenceImageView by bind(R.id.matrixItemPresenceImageView)
val avatarImageView by bind(R.id.matrixItemAvatar)
val avatarDecorationImageView by bind(R.id.matrixItemAvatarDecoration)
val editableView by bind(R.id.matrixItemEditable)
diff --git a/vector/src/main/java/im/vector/app/core/epoxy/profiles/ProfileMatrixItemWithPowerLevel.kt b/vector/src/main/java/im/vector/app/core/epoxy/profiles/ProfileMatrixItemWithPowerLevel.kt
index b7fd597789..12189dc8f4 100644
--- a/vector/src/main/java/im/vector/app/core/epoxy/profiles/ProfileMatrixItemWithPowerLevel.kt
+++ b/vector/src/main/java/im/vector/app/core/epoxy/profiles/ProfileMatrixItemWithPowerLevel.kt
@@ -17,7 +17,6 @@
package im.vector.app.core.epoxy.profiles
-import android.widget.TextView
import androidx.core.view.isVisible
import com.airbnb.epoxy.EpoxyAttribute
import com.airbnb.epoxy.EpoxyModelClass
@@ -25,7 +24,7 @@ import im.vector.app.R
import im.vector.app.core.extensions.setTextOrHide
@EpoxyModelClass(layout = R.layout.item_profile_matrix_item)
-abstract class ProfileMatrixItemWithPowerLevel : BaseProfileMatrixItem() {
+abstract class ProfileMatrixItemWithPowerLevel : ProfileMatrixItem() {
@EpoxyAttribute var powerLevelLabel: CharSequence? = null
@@ -34,8 +33,4 @@ abstract class ProfileMatrixItemWithPowerLevel : BaseProfileMatrixItem(R.id.matrixItemPowerLevelLabel)
- }
}
diff --git a/vector/src/main/java/im/vector/app/core/epoxy/profiles/ProfileMatrixItemWithPowerLevelWithPresence.kt b/vector/src/main/java/im/vector/app/core/epoxy/profiles/ProfileMatrixItemWithPowerLevelWithPresence.kt
new file mode 100644
index 0000000000..92216cbb38
--- /dev/null
+++ b/vector/src/main/java/im/vector/app/core/epoxy/profiles/ProfileMatrixItemWithPowerLevelWithPresence.kt
@@ -0,0 +1,34 @@
+/*
+ * Copyright 2021 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 im.vector.app.core.epoxy.profiles
+
+import com.airbnb.epoxy.EpoxyAttribute
+import com.airbnb.epoxy.EpoxyModelClass
+import im.vector.app.R
+import org.matrix.android.sdk.api.session.presence.model.UserPresence
+
+@EpoxyModelClass(layout = R.layout.item_profile_matrix_item)
+abstract class ProfileMatrixItemWithPowerLevelWithPresence : ProfileMatrixItemWithPowerLevel() {
+
+ @EpoxyAttribute var userPresence: UserPresence? = null
+
+ override fun bind(holder: Holder) {
+ super.bind(holder)
+ holder.presenceImageView.render(userPresence = userPresence)
+ }
+}
diff --git a/vector/src/main/java/im/vector/app/core/epoxy/profiles/notifications/NotificationSettingsFooterItem.kt b/vector/src/main/java/im/vector/app/core/epoxy/profiles/notifications/NotificationSettingsFooterItem.kt
new file mode 100644
index 0000000000..4608f2b1ce
--- /dev/null
+++ b/vector/src/main/java/im/vector/app/core/epoxy/profiles/notifications/NotificationSettingsFooterItem.kt
@@ -0,0 +1,62 @@
+/*
+ * Copyright (c) 2021 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 im.vector.app.core.epoxy.profiles.notifications
+
+import android.widget.TextView
+import com.airbnb.epoxy.EpoxyAttribute
+import com.airbnb.epoxy.EpoxyModelClass
+import im.vector.app.R
+import im.vector.app.core.epoxy.ClickListener
+import im.vector.app.core.epoxy.VectorEpoxyHolder
+import im.vector.app.core.epoxy.VectorEpoxyModel
+import im.vector.app.core.extensions.setTextWithColoredPart
+
+@EpoxyModelClass(layout = R.layout.item_notifications_footer)
+abstract class NotificationSettingsFooterItem : VectorEpoxyModel() {
+
+ @EpoxyAttribute
+ var encrypted: Boolean = false
+
+ @EpoxyAttribute(EpoxyAttribute.Option.DoNotHash)
+ var clickListener: ClickListener? = null
+
+ override fun bind(holder: Holder) {
+ super.bind(holder)
+ val accountSettingsString = holder.view.context.getString(R.string.room_settings_room_notifications_account_settings)
+ val manageNotificationsString = holder.view.context.getString(
+ R.string.room_settings_room_notifications_manage_notifications,
+ accountSettingsString
+ )
+ val manageNotificationsBuilder = StringBuilder(manageNotificationsString)
+ if (encrypted) {
+ val encryptionNotice = holder.view.context.getString(R.string.room_settings_room_notifications_encryption_notice)
+ manageNotificationsBuilder.appendLine().append(encryptionNotice)
+ }
+
+ holder.textView.setTextWithColoredPart(
+ manageNotificationsBuilder.toString(),
+ accountSettingsString,
+ underline = true
+ ) {
+ clickListener?.invoke(holder.textView)
+ }
+ }
+
+ class Holder : VectorEpoxyHolder() {
+ val textView by bind(R.id.footerText)
+ }
+}
diff --git a/vector/src/main/java/im/vector/app/core/epoxy/profiles/notifications/RadioButtonItem.kt b/vector/src/main/java/im/vector/app/core/epoxy/profiles/notifications/RadioButtonItem.kt
new file mode 100644
index 0000000000..721d84e050
--- /dev/null
+++ b/vector/src/main/java/im/vector/app/core/epoxy/profiles/notifications/RadioButtonItem.kt
@@ -0,0 +1,70 @@
+/*
+ * Copyright (c) 2021 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 im.vector.app.core.epoxy.profiles.notifications
+
+import android.widget.ImageView
+import android.widget.TextView
+import androidx.annotation.StringRes
+import androidx.core.content.ContextCompat
+import com.airbnb.epoxy.EpoxyAttribute
+import com.airbnb.epoxy.EpoxyModelClass
+import im.vector.app.R
+import im.vector.app.core.epoxy.ClickListener
+import im.vector.app.core.epoxy.VectorEpoxyHolder
+import im.vector.app.core.epoxy.VectorEpoxyModel
+import im.vector.app.core.epoxy.onClick
+import im.vector.app.core.extensions.setAttributeTintedImageResource
+
+@EpoxyModelClass(layout = R.layout.item_radio)
+abstract class RadioButtonItem : VectorEpoxyModel() {
+
+ @EpoxyAttribute
+ var title: CharSequence? = null
+
+ @StringRes
+ @EpoxyAttribute
+ var titleRes: Int? = null
+
+ @EpoxyAttribute
+ var selected = false
+
+ @EpoxyAttribute(EpoxyAttribute.Option.DoNotHash)
+ lateinit var listener: ClickListener
+
+ override fun bind(holder: Holder) {
+ super.bind(holder)
+ holder.view.onClick(listener)
+ if (titleRes != null) {
+ holder.titleText.setText(titleRes!!)
+ } else {
+ holder.titleText.text = title
+ }
+
+ if (selected) {
+ holder.radioImage.setAttributeTintedImageResource(R.drawable.ic_radio_on, R.attr.colorPrimary)
+ holder.radioImage.contentDescription = holder.view.context.getString(R.string.a11y_checked)
+ } else {
+ holder.radioImage.setImageDrawable(ContextCompat.getDrawable(holder.view.context, R.drawable.ic_radio_off))
+ holder.radioImage.contentDescription = holder.view.context.getString(R.string.a11y_unchecked)
+ }
+ }
+
+ class Holder : VectorEpoxyHolder() {
+ val titleText by bind(R.id.actionTitle)
+ val radioImage by bind(R.id.radioIcon)
+ }
+}
diff --git a/vector/src/main/java/im/vector/app/core/epoxy/profiles/notifications/TextHeaderItem.kt b/vector/src/main/java/im/vector/app/core/epoxy/profiles/notifications/TextHeaderItem.kt
new file mode 100644
index 0000000000..2dfe7be2e6
--- /dev/null
+++ b/vector/src/main/java/im/vector/app/core/epoxy/profiles/notifications/TextHeaderItem.kt
@@ -0,0 +1,50 @@
+/*
+ * Copyright (c) 2021 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 im.vector.app.core.epoxy.profiles.notifications
+
+import android.widget.TextView
+import androidx.annotation.StringRes
+import com.airbnb.epoxy.EpoxyAttribute
+import com.airbnb.epoxy.EpoxyModelClass
+import im.vector.app.R
+import im.vector.app.core.epoxy.VectorEpoxyHolder
+import im.vector.app.core.epoxy.VectorEpoxyModel
+
+@EpoxyModelClass(layout = R.layout.item_text_header)
+abstract class TextHeaderItem : VectorEpoxyModel() {
+
+ @EpoxyAttribute
+ var text: String? = null
+
+ @StringRes
+ @EpoxyAttribute
+ var textRes: Int? = null
+
+ override fun bind(holder: Holder) {
+ super.bind(holder)
+ val textResource = textRes
+ if (textResource != null) {
+ holder.textView.setText(textResource)
+ } else {
+ holder.textView.text = text
+ }
+ }
+
+ class Holder : VectorEpoxyHolder() {
+ val textView by bind(R.id.headerText)
+ }
+}
diff --git a/vector/src/main/java/im/vector/app/core/error/ErrorFormatter.kt b/vector/src/main/java/im/vector/app/core/error/ErrorFormatter.kt
index f0ba79e31c..6494f31336 100644
--- a/vector/src/main/java/im/vector/app/core/error/ErrorFormatter.kt
+++ b/vector/src/main/java/im/vector/app/core/error/ErrorFormatter.kt
@@ -58,49 +58,49 @@ class DefaultErrorFormatter @Inject constructor(
}
is Failure.ServerError -> {
when {
- throwable.error.code == MatrixError.M_CONSENT_NOT_GIVEN -> {
+ throwable.error.code == MatrixError.M_CONSENT_NOT_GIVEN -> {
// Special case for terms and conditions
stringProvider.getString(R.string.error_terms_not_accepted)
}
- throwable.isInvalidPassword() -> {
+ throwable.isInvalidPassword() -> {
stringProvider.getString(R.string.auth_invalid_login_param)
}
- throwable.error.code == MatrixError.M_USER_IN_USE -> {
+ throwable.error.code == MatrixError.M_USER_IN_USE -> {
stringProvider.getString(R.string.login_signup_error_user_in_use)
}
- throwable.error.code == MatrixError.M_BAD_JSON -> {
+ throwable.error.code == MatrixError.M_BAD_JSON -> {
stringProvider.getString(R.string.login_error_bad_json)
}
- throwable.error.code == MatrixError.M_NOT_JSON -> {
+ throwable.error.code == MatrixError.M_NOT_JSON -> {
stringProvider.getString(R.string.login_error_not_json)
}
- throwable.error.code == MatrixError.M_THREEPID_DENIED -> {
+ throwable.error.code == MatrixError.M_THREEPID_DENIED -> {
stringProvider.getString(R.string.login_error_threepid_denied)
}
- throwable.error.code == MatrixError.M_LIMIT_EXCEEDED -> {
+ throwable.error.code == MatrixError.M_LIMIT_EXCEEDED -> {
limitExceededError(throwable.error)
}
- throwable.error.code == MatrixError.M_TOO_LARGE -> {
+ throwable.error.code == MatrixError.M_TOO_LARGE -> {
stringProvider.getString(R.string.error_file_too_big_simple)
}
- throwable.error.code == MatrixError.M_THREEPID_NOT_FOUND -> {
+ throwable.error.code == MatrixError.M_THREEPID_NOT_FOUND -> {
stringProvider.getString(R.string.login_reset_password_error_not_found)
}
- throwable.error.code == MatrixError.M_USER_DEACTIVATED -> {
+ throwable.error.code == MatrixError.M_USER_DEACTIVATED -> {
stringProvider.getString(R.string.auth_invalid_login_deactivated_account)
}
- throwable.error.code == MatrixError.M_THREEPID_IN_USE
- && throwable.error.message == "Email is already in use" -> {
+ throwable.error.code == MatrixError.M_THREEPID_IN_USE &&
+ throwable.error.message == "Email is already in use" -> {
stringProvider.getString(R.string.account_email_already_used_error)
}
- throwable.error.code == MatrixError.M_THREEPID_IN_USE
- && throwable.error.message == "MSISDN is already in use" -> {
+ throwable.error.code == MatrixError.M_THREEPID_IN_USE &&
+ throwable.error.message == "MSISDN is already in use" -> {
stringProvider.getString(R.string.account_phone_number_already_used_error)
}
- throwable.error.code == MatrixError.M_THREEPID_AUTH_FAILED -> {
+ throwable.error.code == MatrixError.M_THREEPID_AUTH_FAILED -> {
stringProvider.getString(R.string.error_threepid_auth_failed)
}
- else -> {
+ else -> {
throwable.error.message.takeIf { it.isNotEmpty() }
?: throwable.error.code.takeIf { it.isNotEmpty() }
}
diff --git a/vector/src/main/java/im/vector/app/core/extensions/BasicExtensions.kt b/vector/src/main/java/im/vector/app/core/extensions/BasicExtensions.kt
index 07a684abef..dbe90dfdc1 100644
--- a/vector/src/main/java/im/vector/app/core/extensions/BasicExtensions.kt
+++ b/vector/src/main/java/im/vector/app/core/extensions/BasicExtensions.kt
@@ -57,7 +57,7 @@ fun CharSequence.isMsisdn(): Boolean {
* - "fi.le.txt".insertBeforeLast("_foo") will return "fi.le_foo.txt"
* - null.insertBeforeLast("_foo") will return "_foo"
*/
-fun String?.insertBeforeLast(insert: String, delimiter: String = ".") : String {
+fun String?.insertBeforeLast(insert: String, delimiter: String = "."): String {
if (this == null) return insert
val idx = lastIndexOf(delimiter)
return if (idx == -1) {
@@ -66,3 +66,7 @@ fun String?.insertBeforeLast(insert: String, delimiter: String = ".") : String {
replaceRange(idx, idx, insert)
}
}
+
+inline fun Any?.takeAs(): R? {
+ return takeIf { it is R } as R?
+}
diff --git a/vector/src/main/java/im/vector/app/core/extensions/Context.kt b/vector/src/main/java/im/vector/app/core/extensions/Context.kt
index c1c435edf2..59847da7c9 100644
--- a/vector/src/main/java/im/vector/app/core/extensions/Context.kt
+++ b/vector/src/main/java/im/vector/app/core/extensions/Context.kt
@@ -17,14 +17,9 @@
package im.vector.app.core.extensions
import android.content.Context
-import im.vector.app.core.di.HasVectorInjector
-import im.vector.app.core.di.VectorComponent
+import dagger.hilt.EntryPoints
+import im.vector.app.core.di.SingletonEntryPoint
-fun Context.vectorComponent(): VectorComponent {
- val appContext = applicationContext
- if (appContext is HasVectorInjector) {
- return appContext.injector()
- } else {
- throw IllegalStateException("Your application context doesn't implement HasVectorInjector")
- }
+fun Context.singletonEntryPoint(): SingletonEntryPoint {
+ return EntryPoints.get(applicationContext, SingletonEntryPoint::class.java)
}
diff --git a/vector/src/main/java/im/vector/app/core/extensions/EditText.kt b/vector/src/main/java/im/vector/app/core/extensions/EditText.kt
index 05b70def3d..0eb9dcdaf9 100644
--- a/vector/src/main/java/im/vector/app/core/extensions/EditText.kt
+++ b/vector/src/main/java/im/vector/app/core/extensions/EditText.kt
@@ -18,6 +18,7 @@ package im.vector.app.core.extensions
import android.text.Editable
import android.text.InputType
+import android.text.Spanned
import android.view.MotionEvent
import android.view.View
import android.view.inputmethod.EditorInfo
@@ -57,3 +58,38 @@ fun EditText.setupAsSearch(@DrawableRes searchIconRes: Int = R.drawable.ic_searc
return@OnTouchListener false
})
}
+
+fun EditText.setTextIfDifferent(newText: CharSequence?): Boolean {
+ if (!isTextDifferent(newText, text)) {
+ // Previous text is the same. No op
+ return false
+ }
+ setText(newText)
+ // Since the text changed we move the cursor to the end of the new text.
+ // This allows us to fill in text programmatically with a different value,
+ // but if the user is typing and the view is rebound we won't lose their cursor position.
+ setSelection(newText?.length ?: 0)
+ return true
+}
+
+private fun isTextDifferent(str1: CharSequence?, str2: CharSequence?): Boolean {
+ if (str1 === str2) {
+ return false
+ }
+ if (str1 == null || str2 == null) {
+ return true
+ }
+ val length = str1.length
+ if (length != str2.length) {
+ return true
+ }
+ if (str1 is Spanned) {
+ return str1 != str2
+ }
+ for (i in 0 until length) {
+ if (str1[i] != str2[i]) {
+ return true
+ }
+ }
+ return false
+}
diff --git a/vector/src/main/java/im/vector/app/core/extensions/Parcelable.kt b/vector/src/main/java/im/vector/app/core/extensions/Parcelable.kt
index 6ca0144601..65f59f7b73 100644
--- a/vector/src/main/java/im/vector/app/core/extensions/Parcelable.kt
+++ b/vector/src/main/java/im/vector/app/core/extensions/Parcelable.kt
@@ -18,8 +18,8 @@ package im.vector.app.core.extensions
import android.os.Bundle
import android.os.Parcelable
-import com.airbnb.mvrx.MvRx
+import com.airbnb.mvrx.Mavericks
fun Parcelable?.toMvRxBundle(): Bundle? {
- return this?.let { Bundle().apply { putParcelable(MvRx.KEY_ARG, it) } }
+ return this?.let { Bundle().apply { putParcelable(Mavericks.KEY_ARG, it) } }
}
diff --git a/vector/src/main/java/im/vector/app/core/extensions/Session.kt b/vector/src/main/java/im/vector/app/core/extensions/Session.kt
index 699247ab6d..90b08ef92b 100644
--- a/vector/src/main/java/im/vector/app/core/extensions/Session.kt
+++ b/vector/src/main/java/im/vector/app/core/extensions/Session.kt
@@ -26,13 +26,15 @@ import org.matrix.android.sdk.api.session.crypto.keysbackup.KeysBackupState
import org.matrix.android.sdk.api.session.sync.FilterService
import timber.log.Timber
-fun Session.configureAndStart(context: Context) {
+fun Session.configureAndStart(context: Context, startSyncing: Boolean = true) {
Timber.i("Configure and start session for $myUserId")
open()
setFilter(FilterService.FilterPreset.ElementFilter)
- startSyncing(context)
+ if (startSyncing) {
+ startSyncing(context)
+ }
refreshPushers()
- context.vectorComponent().webRtcCallManager().checkForProtocolsSupportIfNeeded()
+ context.singletonEntryPoint().webRtcCallManager().checkForProtocolsSupportIfNeeded()
}
fun Session.startSyncing(context: Context) {
@@ -62,15 +64,15 @@ fun Session.startSyncing(context: Context) {
* Tell is the session has unsaved e2e keys in the backup
*/
fun Session.hasUnsavedKeys(): Boolean {
- return cryptoService().inboundGroupSessionsCount(false) > 0
- && cryptoService().keysBackupService().state != KeysBackupState.ReadyToBackUp
+ return cryptoService().inboundGroupSessionsCount(false) > 0 &&
+ cryptoService().keysBackupService().state != KeysBackupState.ReadyToBackUp
}
fun Session.cannotLogoutSafely(): Boolean {
// has some encrypted chat
- return hasUnsavedKeys()
+ return hasUnsavedKeys() ||
// has local cross signing keys
- || (cryptoService().crossSigningService().allPrivateKeysKnown()
+ (cryptoService().crossSigningService().allPrivateKeysKnown() &&
// That are not backed up
- && !sharedSecretStorageService.isRecoverySetup())
+ !sharedSecretStorageService.isRecoverySetup())
}
diff --git a/vector/src/main/java/im/vector/app/core/extensions/TextView.kt b/vector/src/main/java/im/vector/app/core/extensions/TextView.kt
index bb991ac32c..adb655f169 100644
--- a/vector/src/main/java/im/vector/app/core/extensions/TextView.kt
+++ b/vector/src/main/java/im/vector/app/core/extensions/TextView.kt
@@ -39,13 +39,15 @@ import im.vector.app.features.themes.ThemeUtils
/**
* Set a text in the TextView, or set visibility to GONE if the text is null
*/
-fun TextView.setTextOrHide(newText: CharSequence?, hideWhenBlank: Boolean = true) {
- if (newText == null
- || (newText.isBlank() && hideWhenBlank)) {
+fun TextView.setTextOrHide(newText: CharSequence?, hideWhenBlank: Boolean = true, vararg relatedViews: View = emptyArray()) {
+ if (newText == null ||
+ (newText.isBlank() && hideWhenBlank)) {
isVisible = false
+ relatedViews.forEach { it.isVisible = false }
} else {
this.text = newText
isVisible = true
+ relatedViews.forEach { it.isVisible = true }
}
}
@@ -65,6 +67,23 @@ fun TextView.setTextWithColoredPart(@StringRes fullTextRes: Int,
val coloredPart = resources.getString(coloredTextRes)
// Insert colored part into the full text
val fullText = resources.getString(fullTextRes, coloredPart)
+
+ setTextWithColoredPart(fullText, coloredPart, colorAttribute, underline, onClick)
+}
+
+/**
+ * Set text with a colored part
+ * @param fullText The full text.
+ * @param coloredPart The colored part of the text
+ * @param colorAttribute attribute of the color. Default to colorPrimary
+ * @param underline true to also underline the text. Default to false
+ * @param onClick attributes to handle click on the colored part if needed
+ */
+fun TextView.setTextWithColoredPart(fullText: String,
+ coloredPart: String,
+ @AttrRes colorAttribute: Int = R.attr.colorPrimary,
+ underline: Boolean = false,
+ onClick: (() -> Unit)? = null) {
val color = ThemeUtils.getColor(context, colorAttribute)
val foregroundSpan = ForegroundColorSpan(color)
diff --git a/vector/src/main/java/im/vector/app/core/extensions/TimelineEvent.kt b/vector/src/main/java/im/vector/app/core/extensions/TimelineEvent.kt
index 48e3a488ed..43ff186e99 100644
--- a/vector/src/main/java/im/vector/app/core/extensions/TimelineEvent.kt
+++ b/vector/src/main/java/im/vector/app/core/extensions/TimelineEvent.kt
@@ -22,7 +22,7 @@ import org.matrix.android.sdk.api.session.room.timeline.TimelineEvent
fun TimelineEvent.canReact(): Boolean {
// Only event of type EventType.MESSAGE or EventType.STICKER are supported for the moment
- return root.getClearType() in listOf(EventType.MESSAGE, EventType.STICKER)
- && root.sendState == SendState.SYNCED
- && !root.isRedacted()
+ return root.getClearType() in listOf(EventType.MESSAGE, EventType.STICKER) &&
+ root.sendState == SendState.SYNCED &&
+ !root.isRedacted()
}
diff --git a/vector/src/main/java/im/vector/app/core/extensions/UriExtensions.kt b/vector/src/main/java/im/vector/app/core/extensions/UriExtensions.kt
new file mode 100644
index 0000000000..ec7a03bdbb
--- /dev/null
+++ b/vector/src/main/java/im/vector/app/core/extensions/UriExtensions.kt
@@ -0,0 +1,25 @@
+/*
+ * Copyright (c) 2021 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 im.vector.app.core.extensions
+
+import android.net.Uri
+
+const val IGNORED_SCHEMA = "ignored"
+
+fun Uri.isIgnored() = scheme == IGNORED_SCHEMA
+
+fun createIgnoredUri(path: String): Uri = Uri.parse("$IGNORED_SCHEMA://$path")
diff --git a/vector/src/main/java/im/vector/app/core/extensions/ViewExtensions.kt b/vector/src/main/java/im/vector/app/core/extensions/ViewExtensions.kt
index 92dc76670f..54fcac42d1 100644
--- a/vector/src/main/java/im/vector/app/core/extensions/ViewExtensions.kt
+++ b/vector/src/main/java/im/vector/app/core/extensions/ViewExtensions.kt
@@ -16,12 +16,20 @@
package im.vector.app.core.extensions
+import android.graphics.drawable.Drawable
import android.text.InputType
import android.view.View
import android.view.ViewGroup
import android.widget.EditText
+import android.widget.ImageView
+import androidx.annotation.AttrRes
+import androidx.annotation.DrawableRes
import androidx.appcompat.widget.SearchView
+import androidx.core.content.ContextCompat
+import androidx.core.graphics.drawable.DrawableCompat
+import androidx.core.view.isVisible
import im.vector.app.R
+import im.vector.app.features.themes.ThemeUtils
/**
* Remove left margin of a SearchView
@@ -50,3 +58,25 @@ fun View.getMeasurements(): Pair {
val height = measuredHeight
return width to height
}
+
+fun ImageView.setDrawableOrHide(drawableRes: Drawable?) {
+ setImageDrawable(drawableRes)
+ isVisible = drawableRes != null
+}
+
+fun View.setAttributeTintedBackground(@DrawableRes drawableRes: Int, @AttrRes tint: Int) {
+ val drawable = ContextCompat.getDrawable(context, drawableRes)!!
+ DrawableCompat.setTint(drawable, ThemeUtils.getColor(context, tint))
+ background = drawable
+}
+
+fun ImageView.setAttributeTintedImageResource(@DrawableRes drawableRes: Int, @AttrRes tint: Int) {
+ val drawable = ContextCompat.getDrawable(context, drawableRes)!!
+ DrawableCompat.setTint(drawable, ThemeUtils.getColor(context, tint))
+ setImageDrawable(drawable)
+}
+
+fun View.setAttributeBackground(@AttrRes attributeId: Int) {
+ val attribute = ThemeUtils.getAttribute(context, attributeId)!!
+ setBackgroundResource(attribute.resourceId)
+}
diff --git a/vector/src/main/java/im/vector/app/core/flow/TimingOperators.kt b/vector/src/main/java/im/vector/app/core/flow/TimingOperators.kt
new file mode 100644
index 0000000000..621a80d96e
--- /dev/null
+++ b/vector/src/main/java/im/vector/app/core/flow/TimingOperators.kt
@@ -0,0 +1,102 @@
+/*
+ * Copyright (c) 2021 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 im.vector.app.core.flow
+
+import kotlinx.coroutines.CoroutineScope
+import kotlinx.coroutines.ExperimentalCoroutinesApi
+import kotlinx.coroutines.channels.Channel
+import kotlinx.coroutines.channels.ClosedReceiveChannelException
+import kotlinx.coroutines.channels.ReceiveChannel
+import kotlinx.coroutines.channels.produce
+import kotlinx.coroutines.coroutineScope
+import kotlinx.coroutines.delay
+import kotlinx.coroutines.flow.Flow
+import kotlinx.coroutines.flow.collect
+import kotlinx.coroutines.flow.consumeAsFlow
+import kotlinx.coroutines.flow.flow
+import kotlinx.coroutines.isActive
+import kotlinx.coroutines.selects.select
+
+@ExperimentalCoroutinesApi
+fun Flow.chunk(durationInMillis: Long): Flow> {
+ require(durationInMillis > 0) { "Duration should be greater than 0" }
+ return flow {
+ coroutineScope {
+ val events = ArrayList()
+ val ticker = fixedPeriodTicker(durationInMillis)
+ try {
+ val upstreamValues = produce(capacity = Channel.CONFLATED) {
+ collect { value -> send(value) }
+ }
+ while (isActive) {
+ var hasTimedOut = false
+ select {
+ upstreamValues.onReceive {
+ events.add(it)
+ }
+ ticker.onReceive {
+ hasTimedOut = true
+ }
+ }
+ if (hasTimedOut && events.isNotEmpty()) {
+ emit(events.toList())
+ events.clear()
+ }
+ }
+ } catch (e: ClosedReceiveChannelException) {
+ // drain remaining events
+ if (events.isNotEmpty()) emit(events.toList())
+ } finally {
+ ticker.cancel()
+ }
+ }
+ }
+}
+
+@ExperimentalCoroutinesApi
+fun Flow.throttleFirst(windowDuration: Long): Flow = flow {
+ var windowStartTime = System.currentTimeMillis()
+ var emitted = false
+ collect { value ->
+ val currentTime = System.currentTimeMillis()
+ val delta = currentTime - windowStartTime
+ if (delta >= windowDuration) {
+ windowStartTime += delta / windowDuration * windowDuration
+ emitted = false
+ }
+ if (!emitted) {
+ emit(value)
+ emitted = true
+ }
+ }
+}
+
+fun tickerFlow(scope: CoroutineScope, delayMillis: Long, initialDelayMillis: Long = delayMillis): Flow {
+ return scope.fixedPeriodTicker(delayMillis, initialDelayMillis).consumeAsFlow()
+}
+
+private fun CoroutineScope.fixedPeriodTicker(delayMillis: Long, initialDelayMillis: Long = delayMillis): ReceiveChannel {
+ require(delayMillis >= 0) { "Expected non-negative delay, but has $delayMillis ms" }
+ require(initialDelayMillis >= 0) { "Expected non-negative initial delay, but has $initialDelayMillis ms" }
+ return produce(capacity = 0) {
+ delay(initialDelayMillis)
+ while (true) {
+ channel.send(Unit)
+ delay(delayMillis)
+ }
+ }
+}
diff --git a/vector/src/main/java/im/vector/app/core/glide/AvatarPlaceholder.kt b/vector/src/main/java/im/vector/app/core/glide/AvatarPlaceholder.kt
index 32968c4f80..e61f81de55 100644
--- a/vector/src/main/java/im/vector/app/core/glide/AvatarPlaceholder.kt
+++ b/vector/src/main/java/im/vector/app/core/glide/AvatarPlaceholder.kt
@@ -26,7 +26,7 @@ import com.bumptech.glide.load.model.ModelLoader
import com.bumptech.glide.load.model.ModelLoaderFactory
import com.bumptech.glide.load.model.MultiModelLoaderFactory
import com.bumptech.glide.signature.ObjectKey
-import im.vector.app.core.extensions.vectorComponent
+import im.vector.app.core.extensions.singletonEntryPoint
import org.matrix.android.sdk.api.util.MatrixItem
data class AvatarPlaceholder(val matrixItem: MatrixItem)
@@ -42,8 +42,8 @@ class AvatarPlaceholderModelLoaderFactory(private val context: Context) : ModelL
}
}
-class AvatarPlaceholderModelLoader(private val context: Context)
- : ModelLoader {
+class AvatarPlaceholderModelLoader(private val context: Context) :
+ ModelLoader {
override fun buildLoadData(model: AvatarPlaceholder, width: Int, height: Int, options: Options): ModelLoader.LoadData? {
return ModelLoader.LoadData(ObjectKey(model), AvatarPlaceholderDataFetcher(context, model))
@@ -54,10 +54,10 @@ class AvatarPlaceholderModelLoader(private val context: Context)
}
}
-class AvatarPlaceholderDataFetcher(context: Context, private val data: AvatarPlaceholder)
- : DataFetcher {
+class AvatarPlaceholderDataFetcher(context: Context, private val data: AvatarPlaceholder) :
+ DataFetcher {
- private val avatarRenderer = context.vectorComponent().avatarRenderer()
+ private val avatarRenderer = context.singletonEntryPoint().avatarRenderer()
override fun loadData(priority: Priority, callback: DataFetcher.DataCallback) {
val avatarPlaceholder = avatarRenderer.getPlaceholderDrawable(data.matrixItem)
diff --git a/vector/src/main/java/im/vector/app/core/glide/MyAppGlideModule.kt b/vector/src/main/java/im/vector/app/core/glide/MyAppGlideModule.kt
index 74c9d4f0f6..59bffd95fd 100644
--- a/vector/src/main/java/im/vector/app/core/glide/MyAppGlideModule.kt
+++ b/vector/src/main/java/im/vector/app/core/glide/MyAppGlideModule.kt
@@ -19,7 +19,6 @@ package im.vector.app.core.glide
import android.content.Context
import android.graphics.drawable.Drawable
import android.util.Log
-
import com.bumptech.glide.Glide
import com.bumptech.glide.GlideBuilder
import com.bumptech.glide.Registry
diff --git a/vector/src/main/java/im/vector/app/core/glide/VectorGlideModelLoader.kt b/vector/src/main/java/im/vector/app/core/glide/VectorGlideModelLoader.kt
index 5fae815dfb..6b42e3fff8 100644
--- a/vector/src/main/java/im/vector/app/core/glide/VectorGlideModelLoader.kt
+++ b/vector/src/main/java/im/vector/app/core/glide/VectorGlideModelLoader.kt
@@ -25,7 +25,7 @@ import com.bumptech.glide.load.model.ModelLoader
import com.bumptech.glide.load.model.ModelLoaderFactory
import com.bumptech.glide.load.model.MultiModelLoaderFactory
import com.bumptech.glide.signature.ObjectKey
-import im.vector.app.core.extensions.vectorComponent
+import im.vector.app.core.extensions.singletonEntryPoint
import im.vector.app.core.files.LocalFilesHelper
import im.vector.app.features.media.ImageContentRenderer
import im.vector.app.features.session.coroutineScope
@@ -48,8 +48,8 @@ class VectorGlideModelLoaderFactory(private val context: Context) : ModelLoaderF
}
}
-class VectorGlideModelLoader(private val context: Context)
- : ModelLoader {
+class VectorGlideModelLoader(private val context: Context) :
+ ModelLoader {
override fun handles(model: ImageContentRenderer.Data): Boolean {
// Always handle
return true
@@ -63,11 +63,11 @@ class VectorGlideModelLoader(private val context: Context)
class VectorGlideDataFetcher(context: Context,
private val data: ImageContentRenderer.Data,
private val width: Int,
- private val height: Int)
- : DataFetcher {
+ private val height: Int) :
+ DataFetcher {
private val localFilesHelper = LocalFilesHelper(context)
- private val activeSessionHolder = context.vectorComponent().activeSessionHolder()
+ private val activeSessionHolder = context.singletonEntryPoint().activeSessionHolder()
private val client = activeSessionHolder.getSafeActiveSession()?.getOkHttpClient() ?: OkHttpClient()
diff --git a/vector/src/main/java/im/vector/app/core/intent/Filename.kt b/vector/src/main/java/im/vector/app/core/intent/Filename.kt
index 5d118c19a1..a38602e4a5 100644
--- a/vector/src/main/java/im/vector/app/core/intent/Filename.kt
+++ b/vector/src/main/java/im/vector/app/core/intent/Filename.kt
@@ -19,15 +19,17 @@ package im.vector.app.core.intent
import android.content.Context
import android.net.Uri
import android.provider.OpenableColumns
+import im.vector.lib.multipicker.utils.getColumnIndexOrNull
fun getFilenameFromUri(context: Context?, uri: Uri): String? {
if (context != null && uri.scheme == "content") {
- val cursor = context.contentResolver.query(uri, null, null, null, null)
- cursor?.use {
- if (it.moveToFirst()) {
- return it.getString(it.getColumnIndex(OpenableColumns.DISPLAY_NAME))
- }
- }
+ context.contentResolver.query(uri, null, null, null, null)
+ ?.use { cursor ->
+ if (cursor.moveToFirst()) {
+ return cursor.getColumnIndexOrNull(OpenableColumns.DISPLAY_NAME)
+ ?.let { cursor.getString(it) }
+ }
+ }
}
return uri.path?.substringAfterLast('/')
}
diff --git a/vector/src/main/java/im/vector/app/core/platform/ButtonStateView.kt b/vector/src/main/java/im/vector/app/core/platform/ButtonStateView.kt
index ee2933f542..e7e91dbfd9 100755
--- a/vector/src/main/java/im/vector/app/core/platform/ButtonStateView.kt
+++ b/vector/src/main/java/im/vector/app/core/platform/ButtonStateView.kt
@@ -28,8 +28,8 @@ import im.vector.app.core.epoxy.ClickListener
import im.vector.app.core.epoxy.onClick
import im.vector.app.databinding.ViewButtonStateBinding
-class ButtonStateView @JvmOverloads constructor(context: Context, attrs: AttributeSet? = null, defStyle: Int = 0)
- : FrameLayout(context, attrs, defStyle) {
+class ButtonStateView @JvmOverloads constructor(context: Context, attrs: AttributeSet? = null, defStyle: Int = 0) :
+ FrameLayout(context, attrs, defStyle) {
sealed class State {
object Button : State()
diff --git a/vector/src/main/java/im/vector/app/core/platform/LifecycleAwareLazy.kt b/vector/src/main/java/im/vector/app/core/platform/LifecycleAwareLazy.kt
new file mode 100644
index 0000000000..54add00459
--- /dev/null
+++ b/vector/src/main/java/im/vector/app/core/platform/LifecycleAwareLazy.kt
@@ -0,0 +1,73 @@
+/*
+ * Copyright (c) 2021 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 im.vector.app.core.platform
+
+import androidx.annotation.MainThread
+import androidx.fragment.app.Fragment
+import androidx.lifecycle.DefaultLifecycleObserver
+import androidx.lifecycle.Lifecycle
+import androidx.lifecycle.LifecycleOwner
+
+fun LifecycleOwner.lifecycleAwareLazy(initializer: () -> T): Lazy = LifecycleAwareLazy(this, initializer)
+
+private object UninitializedValue
+
+class LifecycleAwareLazy(
+ private val owner: LifecycleOwner,
+ initializer: () -> T
+) : Lazy, DefaultLifecycleObserver {
+
+ private var initializer: (() -> T)? = initializer
+
+ private var _value: Any? = UninitializedValue
+
+ @Suppress("UNCHECKED_CAST")
+ override val value: T
+ @MainThread
+ get() {
+ if (_value === UninitializedValue) {
+ _value = initializer!!()
+ attachToLifecycle()
+ }
+ return _value as T
+ }
+
+ override fun onDestroy(owner: LifecycleOwner) {
+ _value = UninitializedValue
+ detachFromLifecycle()
+ }
+
+ private fun attachToLifecycle() {
+ if (getLifecycleOwner().lifecycle.currentState == Lifecycle.State.DESTROYED) {
+ throw IllegalStateException("Initialization failed because lifecycle has been destroyed!")
+ }
+ getLifecycleOwner().lifecycle.addObserver(this)
+ }
+
+ private fun detachFromLifecycle() {
+ getLifecycleOwner().lifecycle.removeObserver(this)
+ }
+
+ private fun getLifecycleOwner() = when (owner) {
+ is Fragment -> owner.viewLifecycleOwner
+ else -> owner
+ }
+
+ override fun isInitialized(): Boolean = _value !== UninitializedValue
+
+ override fun toString(): String = if (isInitialized()) value.toString() else "Lazy value not initialized yet."
+}
diff --git a/vector/src/main/java/im/vector/app/core/platform/MaxHeightScrollView.kt b/vector/src/main/java/im/vector/app/core/platform/MaxHeightScrollView.kt
index 139ccc8c05..8d4c5d8950 100644
--- a/vector/src/main/java/im/vector/app/core/platform/MaxHeightScrollView.kt
+++ b/vector/src/main/java/im/vector/app/core/platform/MaxHeightScrollView.kt
@@ -24,8 +24,8 @@ import im.vector.app.R
private const val DEFAULT_MAX_HEIGHT = 200
-class MaxHeightScrollView @JvmOverloads constructor(context: Context, attrs: AttributeSet? = null, defStyle: Int = 0)
- : NestedScrollView(context, attrs, defStyle) {
+class MaxHeightScrollView @JvmOverloads constructor(context: Context, attrs: AttributeSet? = null, defStyle: Int = 0) :
+ NestedScrollView(context, attrs, defStyle) {
var maxHeight: Int = 0
set(value) {
diff --git a/vector/src/main/java/im/vector/app/features/call/telecom/TelecomUtils.kt b/vector/src/main/java/im/vector/app/core/platform/PendingIntentCompat.kt
similarity index 55%
rename from vector/src/main/java/im/vector/app/features/call/telecom/TelecomUtils.kt
rename to vector/src/main/java/im/vector/app/core/platform/PendingIntentCompat.kt
index 819a1f6c0a..832c11888c 100644
--- a/vector/src/main/java/im/vector/app/features/call/telecom/TelecomUtils.kt
+++ b/vector/src/main/java/im/vector/app/core/platform/PendingIntentCompat.kt
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2020 New Vector Ltd
+ * Copyright (c) 2021 New Vector Ltd
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -14,17 +14,21 @@
* limitations under the License.
*/
-package im.vector.app.features.call.telecom
+package im.vector.app.core.platform
-import android.content.Context
-import android.telephony.TelephonyManager
-import androidx.core.content.getSystemService
+import android.app.PendingIntent
+import android.os.Build
-object TelecomUtils {
+object PendingIntentCompat {
+ val FLAG_IMMUTABLE = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
+ PendingIntent.FLAG_IMMUTABLE
+ } else {
+ 0
+ }
- fun isLineBusy(context: Context): Boolean {
- val telephonyManager = context.getSystemService()
- ?: return false
- return telephonyManager.callState != TelephonyManager.CALL_STATE_IDLE
+ val FLAG_MUTABLE = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) {
+ PendingIntent.FLAG_MUTABLE
+ } else {
+ 0
}
}
diff --git a/vector/src/main/java/im/vector/app/core/platform/SimpleFragmentActivity.kt b/vector/src/main/java/im/vector/app/core/platform/SimpleFragmentActivity.kt
index 066bd165a9..a70b2d66e6 100644
--- a/vector/src/main/java/im/vector/app/core/platform/SimpleFragmentActivity.kt
+++ b/vector/src/main/java/im/vector/app/core/platform/SimpleFragmentActivity.kt
@@ -15,15 +15,11 @@
*/
package im.vector.app.core.platform
-import androidx.annotation.CallSuper
import androidx.core.view.isGone
import androidx.core.view.isVisible
-import im.vector.app.core.di.ScreenComponent
import im.vector.app.core.extensions.hideKeyboard
import im.vector.app.databinding.ActivityBinding
-import org.matrix.android.sdk.api.session.Session
-
/**
* Simple activity with a toolbar, a waiting overlay, and a fragment container and a session.
*/
@@ -33,13 +29,6 @@ abstract class SimpleFragmentActivity : VectorBaseActivity() {
final override fun getCoordinatorLayout() = views.coordinatorLayout
- lateinit var session: Session
-
- @CallSuper
- override fun injectWith(injector: ScreenComponent) {
- session = injector.activeSessionHolder().getActiveSession()
- }
-
override fun initUiAndData() {
configureToolbar(views.toolbar)
waitingView = views.waitingView.waitingView
diff --git a/vector/src/main/java/im/vector/app/core/platform/StateView.kt b/vector/src/main/java/im/vector/app/core/platform/StateView.kt
index a935c56c51..b3d42dc38f 100755
--- a/vector/src/main/java/im/vector/app/core/platform/StateView.kt
+++ b/vector/src/main/java/im/vector/app/core/platform/StateView.kt
@@ -26,8 +26,8 @@ import im.vector.app.R
import im.vector.app.core.extensions.updateConstraintSet
import im.vector.app.databinding.ViewStateBinding
-class StateView @JvmOverloads constructor(context: Context, attrs: AttributeSet? = null, defStyle: Int = 0)
- : FrameLayout(context, attrs, defStyle) {
+class StateView @JvmOverloads constructor(context: Context, attrs: AttributeSet? = null, defStyle: Int = 0) :
+ FrameLayout(context, attrs, defStyle) {
sealed class State {
object Content : State()
diff --git a/vector/src/main/java/im/vector/app/core/platform/VectorBaseActivity.kt b/vector/src/main/java/im/vector/app/core/platform/VectorBaseActivity.kt
index 61abbd445b..0fd660effb 100644
--- a/vector/src/main/java/im/vector/app/core/platform/VectorBaseActivity.kt
+++ b/vector/src/main/java/im/vector/app/core/platform/VectorBaseActivity.kt
@@ -16,6 +16,7 @@
package im.vector.app.core.platform
+import android.annotation.SuppressLint
import android.app.Activity
import android.content.Context
import android.content.res.Configuration
@@ -39,19 +40,17 @@ import androidx.fragment.app.Fragment
import androidx.fragment.app.FragmentFactory
import androidx.fragment.app.FragmentManager
import androidx.lifecycle.ViewModelProvider
+import androidx.lifecycle.lifecycleScope
import androidx.viewbinding.ViewBinding
+import com.airbnb.mvrx.MavericksView
import com.bumptech.glide.util.Util
import com.google.android.material.appbar.MaterialToolbar
import com.google.android.material.snackbar.Snackbar
-import com.jakewharton.rxbinding3.view.clicks
+import dagger.hilt.android.EntryPointAccessors
import im.vector.app.BuildConfig
import im.vector.app.R
import im.vector.app.core.di.ActiveSessionHolder
-import im.vector.app.core.di.DaggerScreenComponent
-import im.vector.app.core.di.HasScreenInjector
-import im.vector.app.core.di.HasVectorInjector
-import im.vector.app.core.di.ScreenComponent
-import im.vector.app.core.di.VectorComponent
+import im.vector.app.core.di.ActivityEntryPoint
import im.vector.app.core.dialogs.DialogLocker
import im.vector.app.core.dialogs.UnrecognizedCertificateDialog
import im.vector.app.core.extensions.exhaustive
@@ -60,7 +59,8 @@ import im.vector.app.core.extensions.observeNotNull
import im.vector.app.core.extensions.registerStartForActivityResult
import im.vector.app.core.extensions.restart
import im.vector.app.core.extensions.setTextOrHide
-import im.vector.app.core.extensions.vectorComponent
+import im.vector.app.core.extensions.singletonEntryPoint
+import im.vector.app.core.flow.throttleFirst
import im.vector.app.core.utils.toast
import im.vector.app.features.MainActivity
import im.vector.app.features.MainActivityArgs
@@ -79,16 +79,15 @@ import im.vector.app.features.settings.VectorPreferences
import im.vector.app.features.themes.ActivityOtherThemes
import im.vector.app.features.themes.ThemeUtils
import im.vector.app.receivers.DebugReceiver
-import io.reactivex.android.schedulers.AndroidSchedulers
-import io.reactivex.disposables.CompositeDisposable
-import io.reactivex.disposables.Disposable
+import kotlinx.coroutines.flow.launchIn
+import kotlinx.coroutines.flow.onEach
import org.matrix.android.sdk.api.extensions.tryOrNull
import org.matrix.android.sdk.api.failure.GlobalError
+import reactivecircus.flowbinding.android.view.clicks
import timber.log.Timber
-import java.util.concurrent.TimeUnit
-import kotlin.system.measureTimeMillis
+import javax.inject.Inject
-abstract class VectorBaseActivity : AppCompatActivity(), HasScreenInjector {
+abstract class VectorBaseActivity : AppCompatActivity(), MavericksView {
/* ==========================================================================================
* View
* ========================================================================================== */
@@ -106,13 +105,12 @@ abstract class VectorBaseActivity : AppCompatActivity(), HasSc
protected fun VectorViewModel<*, *, T>.observeViewEvents(observer: (T) -> Unit) {
viewEvents
- .observe()
- .observeOn(AndroidSchedulers.mainThread())
- .subscribe {
+ .stream()
+ .onEach {
hideWaitingView()
observer(it)
}
- .disposeOnDestroy()
+ .launchIn(lifecycleScope)
}
/* ==========================================================================================
@@ -121,10 +119,9 @@ abstract class VectorBaseActivity : AppCompatActivity(), HasSc
protected fun View.debouncedClicks(onClicked: () -> Unit) {
clicks()
- .throttleFirst(300, TimeUnit.MILLISECONDS)
- .observeOn(AndroidSchedulers.mainThread())
- .subscribe { onClicked() }
- .disposeOnDestroy()
+ .throttleFirst(300)
+ .onEach { onClicked() }
+ .launchIn(lifecycleScope)
}
/* ==========================================================================================
@@ -135,8 +132,9 @@ abstract class VectorBaseActivity : AppCompatActivity(), HasSc
private lateinit var sessionListener: SessionListener
protected lateinit var bugReporter: BugReporter
private lateinit var pinLocker: PinLocker
- lateinit var rageShake: RageShake
+ @Inject
+ lateinit var rageShake: RageShake
lateinit var navigator: Navigator
private set
private lateinit var fragmentFactory: FragmentFactory
@@ -152,11 +150,8 @@ abstract class VectorBaseActivity : AppCompatActivity(), HasSc
// For debug only
private var debugReceiver: DebugReceiver? = null
- private val uiDisposables = CompositeDisposable()
private val restorables = ArrayList()
- private lateinit var screenComponent: ScreenComponent
-
override fun attachBaseContext(base: Context) {
val vectorConfiguration = VectorConfiguration(this)
super.attachBaseContext(vectorConfiguration.getLocalisedContext(base))
@@ -179,32 +174,22 @@ abstract class VectorBaseActivity : AppCompatActivity(), HasSc
return this
}
- protected fun Disposable.disposeOnDestroy() {
- uiDisposables.add(this)
- }
-
@CallSuper
override fun onCreate(savedInstanceState: Bundle?) {
Timber.i("onCreate Activity ${javaClass.simpleName}")
- val vectorComponent = getVectorComponent()
- screenComponent = DaggerScreenComponent.factory().create(vectorComponent, this)
- val timeForInjection = measureTimeMillis {
- injectWith(screenComponent)
- }
- Timber.v("Injecting dependencies into ${javaClass.simpleName} took $timeForInjection ms")
+ val singletonEntryPoint = singletonEntryPoint()
+ val activityEntryPoint = EntryPointAccessors.fromActivity(this, ActivityEntryPoint::class.java)
ThemeUtils.setActivityTheme(this, getOtherThemes())
- fragmentFactory = screenComponent.fragmentFactory()
+ fragmentFactory = activityEntryPoint.fragmentFactory()
supportFragmentManager.fragmentFactory = fragmentFactory
+ viewModelFactory = activityEntryPoint.viewModelFactory()
super.onCreate(savedInstanceState)
- viewModelFactory = screenComponent.viewModelFactory()
configurationViewModel = viewModelProvider.get(ConfigurationViewModel::class.java)
- bugReporter = screenComponent.bugReporter()
- pinLocker = screenComponent.pinLocker()
- // Shake detector
- rageShake = screenComponent.rageShake()
- navigator = screenComponent.navigator()
- activeSessionHolder = screenComponent.activeSessionHolder()
- vectorPreferences = vectorComponent.vectorPreferences()
+ bugReporter = singletonEntryPoint.bugReporter()
+ pinLocker = singletonEntryPoint.pinLocker()
+ navigator = singletonEntryPoint.navigator()
+ activeSessionHolder = singletonEntryPoint.activeSessionHolder()
+ vectorPreferences = singletonEntryPoint.vectorPreferences()
configurationViewModel.activityRestarter.observe(this) {
if (!it.hasBeenHandled) {
// Recreate the Activity because configuration has changed
@@ -216,7 +201,7 @@ abstract class VectorBaseActivity : AppCompatActivity(), HasSc
navigator.openPinCode(this, pinStartForActivityResult, PinMode.AUTH)
}
}
- sessionListener = vectorComponent.sessionListener()
+ sessionListener = singletonEntryPoint.sessionListener()
sessionListener.globalErrorLiveData.observeEvent(this) {
handleGlobalError(it)
}
@@ -267,11 +252,12 @@ abstract class VectorBaseActivity : AppCompatActivity(), HasSc
activeSessionHolder.getActiveSession().sessionParams.homeServerHost ?: "")
is GlobalError.CertificateError ->
handleCertificateError(globalError)
+ GlobalError.ExpiredAccount -> Unit // TODO Handle account expiration
}.exhaustive
}
private fun handleCertificateError(certificateError: GlobalError.CertificateError) {
- vectorComponent()
+ singletonEntryPoint()
.unrecognizedCertificateDialog()
.show(this,
certificateError.fingerprint,
@@ -311,8 +297,6 @@ abstract class VectorBaseActivity : AppCompatActivity(), HasSc
override fun onDestroy() {
super.onDestroy()
Timber.i("onDestroy Activity ${javaClass.simpleName}")
-
- uiDisposables.dispose()
}
private val pinStartForActivityResult = registerStartForActivityResult { activityResult ->
@@ -401,12 +385,6 @@ abstract class VectorBaseActivity : AppCompatActivity(), HasSc
bugReporter.inMultiWindowMode = isInMultiWindowMode
}
- override fun injector(): ScreenComponent {
- return screenComponent
- }
-
- protected open fun injectWith(injector: ScreenComponent) = Unit
-
protected fun createFragment(fragmentClass: Class, args: Bundle?): Fragment {
return fragmentFactory.instantiate(classLoader, fragmentClass.name).apply {
arguments = args
@@ -417,10 +395,6 @@ abstract class VectorBaseActivity : AppCompatActivity(), HasSc
* PRIVATE METHODS
* ========================================================================================== */
- internal fun getVectorComponent(): VectorComponent {
- return (application as HasVectorInjector).injector()
- }
-
/**
* Force to render the activity in fullscreen
*/
@@ -430,7 +404,12 @@ abstract class VectorBaseActivity : AppCompatActivity(), HasSc
// New API instead of SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN and SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION
window.setDecorFitsSystemWindows(false)
// New API instead of SYSTEM_UI_FLAG_IMMERSIVE
- window.decorView.windowInsetsController?.systemBarsBehavior = WindowInsetsController.BEHAVIOR_SHOW_BARS_BY_SWIPE
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) {
+ window.decorView.windowInsetsController?.systemBarsBehavior = WindowInsetsController.BEHAVIOR_SHOW_TRANSIENT_BARS_BY_SWIPE
+ } else {
+ @SuppressLint("WrongConstant")
+ window.decorView.windowInsetsController?.systemBarsBehavior = WindowInsetsController.BEHAVIOR_SHOW_BARS_BY_SWIPE
+ }
// New API instead of FLAG_TRANSLUCENT_STATUS
window.statusBarColor = ContextCompat.getColor(this, im.vector.lib.attachmentviewer.R.color.half_transparent_status_bar)
// New API instead of FLAG_TRANSLUCENT_NAVIGATION
@@ -575,6 +554,8 @@ abstract class VectorBaseActivity : AppCompatActivity(), HasSc
open fun initUiAndData() = Unit
+ override fun invalidate() = Unit
+
@StringRes
open fun getTitleRes() = -1
diff --git a/vector/src/main/java/im/vector/app/core/platform/VectorBaseBottomSheetDialogFragment.kt b/vector/src/main/java/im/vector/app/core/platform/VectorBaseBottomSheetDialogFragment.kt
index b9b5bc8ca5..20697c6d11 100644
--- a/vector/src/main/java/im/vector/app/core/platform/VectorBaseBottomSheetDialogFragment.kt
+++ b/vector/src/main/java/im/vector/app/core/platform/VectorBaseBottomSheetDialogFragment.kt
@@ -26,31 +26,26 @@ import android.view.ViewGroup
import android.widget.FrameLayout
import androidx.annotation.CallSuper
import androidx.lifecycle.ViewModelProvider
+import androidx.lifecycle.lifecycleScope
import androidx.viewbinding.ViewBinding
-import com.airbnb.mvrx.MvRx
-import com.airbnb.mvrx.MvRxView
-import com.airbnb.mvrx.MvRxViewId
+import com.airbnb.mvrx.Mavericks
+import com.airbnb.mvrx.MavericksView
import com.google.android.material.bottomsheet.BottomSheetBehavior
import com.google.android.material.bottomsheet.BottomSheetDialog
import com.google.android.material.bottomsheet.BottomSheetDialogFragment
-import com.jakewharton.rxbinding3.view.clicks
-import im.vector.app.core.di.DaggerScreenComponent
-import im.vector.app.core.di.ScreenComponent
+import dagger.hilt.android.EntryPointAccessors
+import im.vector.app.core.di.ActivityEntryPoint
+import im.vector.app.core.flow.throttleFirst
import im.vector.app.core.utils.DimensionConverter
-import io.reactivex.android.schedulers.AndroidSchedulers
-import io.reactivex.disposables.CompositeDisposable
-import io.reactivex.disposables.Disposable
+import kotlinx.coroutines.flow.launchIn
+import kotlinx.coroutines.flow.onEach
+import reactivecircus.flowbinding.android.view.clicks
import timber.log.Timber
-import java.util.concurrent.TimeUnit
/**
- * Add MvRx capabilities to bottomsheetdialog (like BaseMvRxFragment)
+ * Add Mavericks capabilities, handle DI and bindings.
*/
-abstract class VectorBaseBottomSheetDialogFragment : BottomSheetDialogFragment(), MvRxView {
-
- private val mvrxViewIdProperty = MvRxViewId()
- final override val mvrxViewId: String by mvrxViewIdProperty
- private lateinit var screenComponent: ScreenComponent
+abstract class VectorBaseBottomSheetDialogFragment : BottomSheetDialogFragment(), MavericksView {
/* ==========================================================================================
* View
@@ -113,29 +108,19 @@ abstract class VectorBaseBottomSheetDialogFragment : BottomShe
@CallSuper
override fun onDestroyView() {
- uiDisposables.clear()
_binding = null
super.onDestroyView()
}
@CallSuper
override fun onDestroy() {
- uiDisposables.dispose()
super.onDestroy()
}
override fun onAttach(context: Context) {
- screenComponent = DaggerScreenComponent.factory().create(vectorBaseActivity.getVectorComponent(), vectorBaseActivity)
- viewModelFactory = screenComponent.viewModelFactory()
+ val activityEntryPoint = EntryPointAccessors.fromActivity(vectorBaseActivity, ActivityEntryPoint::class.java)
+ viewModelFactory = activityEntryPoint.viewModelFactory()
super.onAttach(context)
- injectWith(screenComponent)
- }
-
- protected open fun injectWith(injector: ScreenComponent) = Unit
-
- override fun onCreate(savedInstanceState: Bundle?) {
- mvrxViewIdProperty.restoreFrom(savedInstanceState)
- super.onCreate(savedInstanceState)
}
override fun onResume() {
@@ -154,11 +139,6 @@ abstract class VectorBaseBottomSheetDialogFragment : BottomShe
}
}
- override fun onSaveInstanceState(outState: Bundle) {
- super.onSaveInstanceState(outState)
- mvrxViewIdProperty.saveTo(outState)
- }
-
override fun onStart() {
super.onStart()
// This ensures that invalidate() is called for static screens that don't
@@ -179,18 +159,7 @@ abstract class VectorBaseBottomSheetDialogFragment : BottomShe
}
protected fun setArguments(args: Parcelable? = null) {
- arguments = args?.let { Bundle().apply { putParcelable(MvRx.KEY_ARG, it) } }
- }
-
- /* ==========================================================================================
- * Disposable
- * ========================================================================================== */
-
- private val uiDisposables = CompositeDisposable()
-
- protected fun Disposable.disposeOnDestroyView(): Disposable {
- uiDisposables.add(this)
- return this
+ arguments = args?.let { Bundle().apply { putParcelable(Mavericks.KEY_ARG, it) } }
}
/* ==========================================================================================
@@ -199,10 +168,9 @@ abstract class VectorBaseBottomSheetDialogFragment : BottomShe
protected fun View.debouncedClicks(onClicked: () -> Unit) {
clicks()
- .throttleFirst(300, TimeUnit.MILLISECONDS)
- .observeOn(AndroidSchedulers.mainThread())
- .subscribe { onClicked() }
- .disposeOnDestroyView()
+ .throttleFirst(300)
+ .onEach { onClicked() }
+ .launchIn(viewLifecycleOwner.lifecycleScope)
}
/* ==========================================================================================
@@ -211,11 +179,10 @@ abstract class VectorBaseBottomSheetDialogFragment : BottomShe
protected fun VectorViewModel<*, *, T>.observeViewEvents(observer: (T) -> Unit) {
viewEvents
- .observe()
- .observeOn(AndroidSchedulers.mainThread())
- .subscribe {
+ .stream()
+ .onEach {
observer(it)
}
- .disposeOnDestroyView()
+ .launchIn(viewLifecycleOwner.lifecycleScope)
}
}
diff --git a/vector/src/main/java/im/vector/app/core/platform/VectorBaseFragment.kt b/vector/src/main/java/im/vector/app/core/platform/VectorBaseFragment.kt
index 2c9452c4fd..f4e1fe84e1 100644
--- a/vector/src/main/java/im/vector/app/core/platform/VectorBaseFragment.kt
+++ b/vector/src/main/java/im/vector/app/core/platform/VectorBaseFragment.kt
@@ -27,29 +27,30 @@ import android.view.ViewGroup
import androidx.annotation.CallSuper
import androidx.annotation.MainThread
import androidx.appcompat.app.AlertDialog
+import androidx.fragment.app.Fragment
import androidx.lifecycle.ViewModelProvider
+import androidx.lifecycle.lifecycleScope
import androidx.viewbinding.ViewBinding
-import com.airbnb.mvrx.BaseMvRxFragment
+import com.airbnb.mvrx.MavericksView
import com.bumptech.glide.util.Util.assertMainThread
import com.google.android.material.appbar.MaterialToolbar
import com.google.android.material.dialog.MaterialAlertDialogBuilder
-import com.jakewharton.rxbinding3.view.clicks
+import dagger.hilt.android.EntryPointAccessors
import im.vector.app.R
-import im.vector.app.core.di.DaggerScreenComponent
-import im.vector.app.core.di.HasScreenInjector
-import im.vector.app.core.di.ScreenComponent
+import im.vector.app.core.di.ActivityEntryPoint
import im.vector.app.core.dialogs.UnrecognizedCertificateDialog
import im.vector.app.core.error.ErrorFormatter
+import im.vector.app.core.extensions.singletonEntryPoint
import im.vector.app.core.extensions.toMvRxBundle
+import im.vector.app.core.flow.throttleFirst
import im.vector.app.features.navigation.Navigator
import im.vector.lib.ui.styles.dialogs.MaterialProgressDialog
-import io.reactivex.android.schedulers.AndroidSchedulers
-import io.reactivex.disposables.CompositeDisposable
-import io.reactivex.disposables.Disposable
+import kotlinx.coroutines.flow.launchIn
+import kotlinx.coroutines.flow.onEach
+import reactivecircus.flowbinding.android.view.clicks
import timber.log.Timber
-import java.util.concurrent.TimeUnit
-abstract class VectorBaseFragment : BaseMvRxFragment(), HasScreenInjector {
+abstract class VectorBaseFragment : Fragment(), MavericksView {
protected val vectorBaseActivity: VectorBaseActivity<*> by lazy {
activity as VectorBaseActivity<*>
@@ -59,8 +60,6 @@ abstract class VectorBaseFragment : BaseMvRxFragment(), HasScr
* Navigator and other common objects
* ========================================================================================== */
- private lateinit var screenComponent: ScreenComponent
-
protected lateinit var navigator: Navigator
protected lateinit var errorFormatter: ErrorFormatter
protected lateinit var unrecognizedCertificateDialog: UnrecognizedCertificateDialog
@@ -94,12 +93,13 @@ abstract class VectorBaseFragment : BaseMvRxFragment(), HasScr
* ========================================================================================== */
override fun onAttach(context: Context) {
- screenComponent = DaggerScreenComponent.factory().create(vectorBaseActivity.getVectorComponent(), vectorBaseActivity)
- navigator = screenComponent.navigator()
- errorFormatter = screenComponent.errorFormatter()
- unrecognizedCertificateDialog = screenComponent.unrecognizedCertificateDialog()
- viewModelFactory = screenComponent.viewModelFactory()
- childFragmentManager.fragmentFactory = screenComponent.fragmentFactory()
+ val singletonEntryPoint = context.singletonEntryPoint()
+ val activityEntryPoint = EntryPointAccessors.fromActivity(vectorBaseActivity, ActivityEntryPoint::class.java)
+ navigator = singletonEntryPoint.navigator()
+ errorFormatter = singletonEntryPoint.errorFormatter()
+ unrecognizedCertificateDialog = singletonEntryPoint.unrecognizedCertificateDialog()
+ viewModelFactory = activityEntryPoint.viewModelFactory()
+ childFragmentManager.fragmentFactory = activityEntryPoint.fragmentFactory()
super.onAttach(context)
}
@@ -148,7 +148,6 @@ abstract class VectorBaseFragment : BaseMvRxFragment(), HasScr
@CallSuper
override fun onDestroyView() {
Timber.i("onDestroyView Fragment ${javaClass.simpleName}")
- uiDisposables.clear()
_binding = null
super.onDestroyView()
}
@@ -156,14 +155,9 @@ abstract class VectorBaseFragment : BaseMvRxFragment(), HasScr
@CallSuper
override fun onDestroy() {
Timber.i("onDestroy Fragment ${javaClass.simpleName}")
- uiDisposables.dispose()
super.onDestroy()
}
- override fun injector(): ScreenComponent {
- return screenComponent
- }
-
/* ==========================================================================================
* Restorable
* ========================================================================================== */
@@ -225,29 +219,18 @@ abstract class VectorBaseFragment : BaseMvRxFragment(), HasScr
}
}
- /* ==========================================================================================
- * Disposable
- * ========================================================================================== */
-
- private val uiDisposables = CompositeDisposable()
-
- protected fun Disposable.disposeOnDestroyView() {
- uiDisposables.add(this)
- }
-
/* ==========================================================================================
* ViewEvents
* ========================================================================================== */
protected fun VectorViewModel<*, *, T>.observeViewEvents(observer: (T) -> Unit) {
viewEvents
- .observe()
- .observeOn(AndroidSchedulers.mainThread())
- .subscribe {
+ .stream()
+ .onEach {
dismissLoadingDialog()
observer(it)
}
- .disposeOnDestroyView()
+ .launchIn(viewLifecycleOwner.lifecycleScope)
}
/* ==========================================================================================
@@ -256,10 +239,9 @@ abstract class VectorBaseFragment : BaseMvRxFragment(), HasScr
protected fun View.debouncedClicks(onClicked: () -> Unit) {
clicks()
- .throttleFirst(300, TimeUnit.MILLISECONDS)
- .observeOn(AndroidSchedulers.mainThread())
- .subscribe { onClicked() }
- .disposeOnDestroyView()
+ .throttleFirst(300)
+ .onEach { onClicked() }
+ .launchIn(viewLifecycleOwner.lifecycleScope)
}
/* ==========================================================================================
diff --git a/vector/src/main/java/im/vector/app/core/platform/VectorEventViewModel.kt b/vector/src/main/java/im/vector/app/core/platform/VectorEventViewModel.kt
index 2d499db531..9ab46557a5 100644
--- a/vector/src/main/java/im/vector/app/core/platform/VectorEventViewModel.kt
+++ b/vector/src/main/java/im/vector/app/core/platform/VectorEventViewModel.kt
@@ -25,5 +25,5 @@ interface VectorSharedAction
/**
* Parent class to handle navigation events, action events, or other any events
*/
-open class VectorSharedActionViewModel(private val store: MutableDataSource = PublishDataSource())
- : ViewModel(), MutableDataSource by store
+open class VectorSharedActionViewModel(private val store: MutableDataSource = PublishDataSource()) :
+ ViewModel(), MutableDataSource by store
diff --git a/vector/src/main/java/im/vector/app/core/platform/VectorViewModel.kt b/vector/src/main/java/im/vector/app/core/platform/VectorViewModel.kt
index d6f43beaf7..c9d58f9545 100644
--- a/vector/src/main/java/im/vector/app/core/platform/VectorViewModel.kt
+++ b/vector/src/main/java/im/vector/app/core/platform/VectorViewModel.kt
@@ -16,53 +16,17 @@
package im.vector.app.core.platform
-import com.airbnb.mvrx.Async
-import com.airbnb.mvrx.BaseMvRxViewModel
-import com.airbnb.mvrx.Fail
-import com.airbnb.mvrx.Loading
-import com.airbnb.mvrx.MvRxState
-import com.airbnb.mvrx.Success
+import com.airbnb.mvrx.MavericksState
+import com.airbnb.mvrx.MavericksViewModel
import im.vector.app.core.utils.DataSource
import im.vector.app.core.utils.PublishDataSource
-import io.reactivex.Observable
-import io.reactivex.Single
-abstract class VectorViewModel(initialState: S)
- : BaseMvRxViewModel(initialState, false) {
-
- interface Factory {
- fun create(state: S): BaseMvRxViewModel
- }
+abstract class VectorViewModel(initialState: S) :
+ MavericksViewModel(initialState) {
// Used to post transient events to the View
protected val _viewEvents = PublishDataSource()
val viewEvents: DataSource = _viewEvents
- /**
- * This method does the same thing as the execute function, but it doesn't subscribe to the stream
- * so you can use this in a switchMap or a flatMap
- */
- // False positive
- @Suppress("USELESS_CAST", "NULLABLE_TYPE_PARAMETER_AGAINST_NOT_NULL_TYPE_PARAMETER")
- fun Single.toAsync(stateReducer: S.(Async) -> S): Single> {
- setState { stateReducer(Loading()) }
- return map { Success(it) as Async }
- .onErrorReturn { Fail(it) }
- .doOnSuccess { setState { stateReducer(it) } }
- }
-
- /**
- * This method does the same thing as the execute function, but it doesn't subscribe to the stream
- * so you can use this in a switchMap or a flatMap
- */
- // False positive
- @Suppress("USELESS_CAST", "NULLABLE_TYPE_PARAMETER_AGAINST_NOT_NULL_TYPE_PARAMETER")
- fun Observable.toAsync(stateReducer: S.(Async) -> S): Observable> {
- setState { stateReducer(Loading()) }
- return map { Success(it) as Async }
- .onErrorReturn { Fail(it) }
- .doOnNext { setState { stateReducer(it) } }
- }
-
abstract fun handle(action: VA)
}
diff --git a/vector/src/main/java/im/vector/app/core/preference/KeywordPreference.kt b/vector/src/main/java/im/vector/app/core/preference/KeywordPreference.kt
new file mode 100644
index 0000000000..b57bb27671
--- /dev/null
+++ b/vector/src/main/java/im/vector/app/core/preference/KeywordPreference.kt
@@ -0,0 +1,167 @@
+/*
+ * Copyright (c) 2021 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 im.vector.app.core.preference
+
+import android.content.Context
+import android.text.Editable
+import android.util.AttributeSet
+import android.view.inputmethod.EditorInfo
+import android.widget.Button
+import android.widget.EditText
+import androidx.core.view.children
+import androidx.preference.PreferenceViewHolder
+import com.google.android.material.chip.Chip
+import com.google.android.material.chip.ChipGroup
+import com.google.android.material.textfield.TextInputLayout
+import im.vector.app.R
+import im.vector.app.core.epoxy.addTextChangedListenerOnce
+import im.vector.app.core.platform.SimpleTextWatcher
+
+class KeywordPreference : VectorPreference {
+
+ interface Listener {
+ fun onFocusDidChange(hasFocus: Boolean)
+ fun didAddKeyword(keyword: String)
+ fun didRemoveKeyword(keyword: String)
+ }
+
+ private var keywordsEnabled = true
+ private var isCurrentKeywordValid = true
+
+ private var _keywords: LinkedHashSet = linkedSetOf()
+
+ var keywords: Set
+ get() {
+ return _keywords
+ }
+ set(value) {
+ // Updates existing `LinkedHashSet` vs assign a new set.
+ // This preserves the order added while on the screen (avoids keywords jumping around).
+ _keywords.removeAll(_keywords.filter { !value.contains(it) })
+ _keywords.addAll(value.sorted())
+ notifyChanged()
+ }
+
+ var listener: Listener? = null
+
+ constructor(context: Context) : super(context)
+
+ constructor(context: Context, attrs: AttributeSet) : super(context, attrs)
+
+ constructor(context: Context, attrs: AttributeSet, defStyle: Int) : super(context, attrs, defStyle)
+
+ init {
+ layoutResource = R.layout.vector_preference_chip_group
+ }
+
+ override fun setEnabled(enabled: Boolean) {
+ super.setEnabled(enabled)
+ keywordsEnabled = enabled
+ notifyChanged()
+ }
+
+ override fun onBindViewHolder(holder: PreferenceViewHolder) {
+ super.onBindViewHolder(holder)
+
+ holder.itemView.setOnClickListener(null)
+ holder.itemView.setOnLongClickListener(null)
+
+ val chipEditText = holder.findViewById(R.id.chipEditText) as? EditText ?: return
+ val chipGroup = holder.findViewById(R.id.chipGroup) as? ChipGroup ?: return
+ val addKeywordButton = holder.findViewById(R.id.addKeywordButton) as? Button ?: return
+ val chipTextInputLayout = holder.findViewById(R.id.chipTextInputLayout) as? TextInputLayout ?: return
+
+ chipEditText.text = null
+ chipGroup.removeAllViews()
+
+ keywords.forEach {
+ addChipToGroup(it, chipGroup)
+ }
+
+ chipEditText.isEnabled = keywordsEnabled
+ chipGroup.isEnabled = keywordsEnabled
+ chipGroup.children.forEach { it.isEnabled = keywordsEnabled }
+
+ chipEditText.addTextChangedListenerOnce(onTextChangeListener(chipTextInputLayout, addKeywordButton))
+ chipEditText.setOnEditorActionListener { _, actionId, _ ->
+ if (actionId != EditorInfo.IME_ACTION_DONE) {
+ return@setOnEditorActionListener false
+ }
+ return@setOnEditorActionListener addKeyword(chipEditText)
+ }
+ chipEditText.setOnFocusChangeListener { _, hasFocus ->
+ listener?.onFocusDidChange(hasFocus)
+ }
+
+ addKeywordButton.setOnClickListener {
+ addKeyword(chipEditText)
+ }
+ }
+
+ private fun addKeyword(chipEditText: EditText): Boolean {
+ val keyword = chipEditText.text.toString().trim()
+
+ if (!isCurrentKeywordValid || keyword.isEmpty()) {
+ return false
+ }
+
+ listener?.didAddKeyword(keyword)
+ onPreferenceChangeListener?.onPreferenceChange(this, _keywords)
+ notifyChanged()
+ chipEditText.text = null
+ return true
+ }
+
+ private fun onTextChangeListener(chipTextInputLayout: TextInputLayout, addKeywordButton: Button) = object : SimpleTextWatcher() {
+ override fun afterTextChanged(s: Editable) {
+ val keyword = s.toString().trim()
+ val errorMessage = when {
+ keyword.startsWith(".") -> {
+ context.getString(R.string.settings_notification_keyword_contains_dot)
+ }
+ keyword.contains("\\") -> {
+ context.getString(R.string.settings_notification_keyword_contains_invalid_character, "\\")
+ }
+ keyword.contains("/") -> {
+ context.getString(R.string.settings_notification_keyword_contains_invalid_character, "/")
+ }
+ else -> null
+ }
+
+ chipTextInputLayout.isErrorEnabled = errorMessage != null
+ chipTextInputLayout.error = errorMessage
+ val keywordValid = errorMessage == null
+ addKeywordButton.isEnabled = keywordsEnabled && keywordValid
+ this@KeywordPreference.isCurrentKeywordValid = keywordValid
+ }
+ }
+
+ private fun addChipToGroup(keyword: String, chipGroup: ChipGroup) {
+ val chip = Chip(context, null, R.attr.vctr_keyword_style)
+ chip.text = keyword
+ chipGroup.addView(chip)
+
+ chip.setOnCloseIconClickListener {
+ if (!keywordsEnabled) {
+ return@setOnCloseIconClickListener
+ }
+ listener?.didRemoveKeyword(keyword)
+ onPreferenceChangeListener?.onPreferenceChange(this, _keywords)
+ notifyChanged()
+ }
+ }
+}
diff --git a/vector/src/main/java/im/vector/app/core/preference/UserAvatarPreference.kt b/vector/src/main/java/im/vector/app/core/preference/UserAvatarPreference.kt
index 3bb50c6284..3095f98ea5 100755
--- a/vector/src/main/java/im/vector/app/core/preference/UserAvatarPreference.kt
+++ b/vector/src/main/java/im/vector/app/core/preference/UserAvatarPreference.kt
@@ -23,7 +23,7 @@ import android.widget.ProgressBar
import androidx.preference.Preference
import androidx.preference.PreferenceViewHolder
import im.vector.app.R
-import im.vector.app.core.extensions.vectorComponent
+import im.vector.app.core.extensions.singletonEntryPoint
import im.vector.app.features.home.AvatarRenderer
import org.matrix.android.sdk.api.session.user.model.User
import org.matrix.android.sdk.api.util.MatrixItem
@@ -33,7 +33,7 @@ class UserAvatarPreference : Preference {
private var mAvatarView: ImageView? = null
private var mLoadingProgressBar: ProgressBar? = null
- private var avatarRenderer: AvatarRenderer = context.vectorComponent().avatarRenderer()
+ private var avatarRenderer: AvatarRenderer = context.singletonEntryPoint().avatarRenderer()
private var userItem: MatrixItem.UserItem? = null
diff --git a/vector/src/main/java/im/vector/app/core/pushers/PushersManager.kt b/vector/src/main/java/im/vector/app/core/pushers/PushersManager.kt
index 5896122393..27d6d05708 100644
--- a/vector/src/main/java/im/vector/app/core/pushers/PushersManager.kt
+++ b/vector/src/main/java/im/vector/app/core/pushers/PushersManager.kt
@@ -21,6 +21,7 @@ import im.vector.app.core.di.ActiveSessionHolder
import im.vector.app.core.resources.AppNameProvider
import im.vector.app.core.resources.LocaleProvider
import im.vector.app.core.resources.StringProvider
+import org.matrix.android.sdk.api.session.pushers.PushersService
import java.util.UUID
import javax.inject.Inject
import kotlin.math.abs
@@ -44,23 +45,45 @@ class PushersManager @Inject constructor(
)
}
- fun registerPusherWithFcmKey(pushKey: String): UUID {
+ fun enqueueRegisterPusherWithFcmKey(pushKey: String): UUID {
val currentSession = activeSessionHolder.getActiveSession()
- val profileTag = DEFAULT_PUSHER_FILE_TAG + "_" + abs(currentSession.myUserId.hashCode())
+ return currentSession.enqueueAddHttpPusher(createHttpPusher(pushKey))
+ }
- return currentSession.addHttpPusher(
- pushKey,
- stringProvider.getString(R.string.pusher_app_id),
- profileTag,
- localeProvider.current().language,
- appNameProvider.getAppName(),
- currentSession.sessionParams.deviceId ?: "MOBILE",
- stringProvider.getString(R.string.pusher_http_url),
- append = false,
- withEventIdOnly = true
+ suspend fun registerPusherWithFcmKey(pushKey: String) {
+ val currentSession = activeSessionHolder.getActiveSession()
+ currentSession.addHttpPusher(createHttpPusher(pushKey))
+ }
+
+ private fun createHttpPusher(pushKey: String) = PushersService.HttpPusher(
+ pushKey,
+ stringProvider.getString(R.string.pusher_app_id),
+ profileTag = DEFAULT_PUSHER_FILE_TAG + "_" + abs(activeSessionHolder.getActiveSession().myUserId.hashCode()),
+ localeProvider.current().language,
+ appNameProvider.getAppName(),
+ activeSessionHolder.getActiveSession().sessionParams.deviceId ?: "MOBILE",
+ stringProvider.getString(R.string.pusher_http_url),
+ append = false,
+ withEventIdOnly = true
+ )
+
+ suspend fun registerEmailForPush(email: String) {
+ val currentSession = activeSessionHolder.getActiveSession()
+ val appName = appNameProvider.getAppName()
+ currentSession.addEmailPusher(
+ email = email,
+ lang = localeProvider.current().language,
+ emailBranding = appName,
+ appDisplayName = appName,
+ deviceDisplayName = currentSession.sessionParams.deviceId ?: "MOBILE"
)
}
+ suspend fun unregisterEmailPusher(email: String) {
+ val currentSession = activeSessionHolder.getSafeActiveSession() ?: return
+ currentSession.removeEmailPusher(email)
+ }
+
suspend fun unregisterPusher(pushKey: String) {
val currentSession = activeSessionHolder.getSafeActiveSession() ?: return
currentSession.removeHttpPusher(pushKey, stringProvider.getString(R.string.pusher_app_id))
diff --git a/vector/src/main/java/im/vector/app/core/rx/RxConfig.kt b/vector/src/main/java/im/vector/app/core/rx/RxConfig.kt
deleted file mode 100644
index ab0ffb7802..0000000000
--- a/vector/src/main/java/im/vector/app/core/rx/RxConfig.kt
+++ /dev/null
@@ -1,43 +0,0 @@
-/*
- * Copyright 2019 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 im.vector.app.core.rx
-
-import im.vector.app.features.settings.VectorPreferences
-import io.reactivex.plugins.RxJavaPlugins
-import timber.log.Timber
-import javax.inject.Inject
-
-class RxConfig @Inject constructor(
- private val vectorPreferences: VectorPreferences
-) {
-
- /**
- * Make sure unhandled Rx error does not crash the app in production
- */
- fun setupRxPlugin() {
- RxJavaPlugins.setErrorHandler { throwable ->
- Timber.e(throwable, "RxError")
- // is InterruptedException -> fine, some blocking code was interrupted by a dispose call
- if (throwable !is InterruptedException) {
- // Avoid crash in production, except if user wants it
- if (vectorPreferences.failFast()) {
- throw throwable
- }
- }
- }
- }
-}
diff --git a/vector/src/main/java/im/vector/app/core/services/CallRingPlayer.kt b/vector/src/main/java/im/vector/app/core/services/CallRingPlayer.kt
index f23eb07424..524ff37914 100644
--- a/vector/src/main/java/im/vector/app/core/services/CallRingPlayer.kt
+++ b/vector/src/main/java/im/vector/app/core/services/CallRingPlayer.kt
@@ -62,6 +62,10 @@ class CallRingPlayerIncoming(
val ringtoneUri = RingtoneManager.getDefaultUri(RingtoneManager.TYPE_RINGTONE)
ringtone = RingtoneManager.getRingtone(applicationContext, ringtoneUri)
Timber.v("Play ringtone for incoming call")
+
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) {
+ ringtone?.isLooping = true
+ }
ringtone?.play()
}
@@ -98,13 +102,10 @@ class CallRingPlayerOutgoing(
private var player: MediaPlayer? = null
fun start() {
- val audioManager: AudioManager? = applicationContext.getSystemService()
+ applicationContext.getSystemService()?.mode = AudioManager.MODE_IN_COMMUNICATION
player?.release()
player = createPlayer()
-
- // Check if sound is enabled
- val ringerMode = audioManager?.ringerMode
- if (player != null && ringerMode == AudioManager.RINGER_MODE_NORMAL) {
+ if (player != null) {
try {
if (player?.isPlaying == false) {
player?.start()
@@ -116,8 +117,6 @@ class CallRingPlayerOutgoing(
Timber.e(failure, "## VOIP Failed to start ringing outgoing")
player = null
}
- } else {
- Timber.v("## VOIP Can't play $player ode $ringerMode")
}
}
diff --git a/vector/src/main/java/im/vector/app/core/services/CallService.kt b/vector/src/main/java/im/vector/app/core/services/CallService.kt
index d8cf8cf6b8..d194434641 100644
--- a/vector/src/main/java/im/vector/app/core/services/CallService.kt
+++ b/vector/src/main/java/im/vector/app/core/services/CallService.kt
@@ -25,14 +25,16 @@ import android.view.KeyEvent
import androidx.core.app.NotificationManagerCompat
import androidx.core.content.ContextCompat
import androidx.media.session.MediaButtonReceiver
-import com.airbnb.mvrx.MvRx
-import im.vector.app.core.extensions.vectorComponent
+import com.airbnb.mvrx.Mavericks
+import dagger.hilt.android.AndroidEntryPoint
+import im.vector.app.core.extensions.singletonEntryPoint
import im.vector.app.features.call.CallArgs
import im.vector.app.features.call.VectorCallActivity
import im.vector.app.features.call.telecom.CallConnection
import im.vector.app.features.call.webrtc.WebRtcCall
import im.vector.app.features.call.webrtc.WebRtcCallManager
import im.vector.app.features.call.webrtc.getOpponentAsMatrixItem
+import im.vector.app.features.displayname.getBestName
import im.vector.app.features.home.AvatarRenderer
import im.vector.app.features.notifications.NotificationUtils
import im.vector.app.features.popup.IncomingCallAlert
@@ -41,23 +43,25 @@ import org.matrix.android.sdk.api.logger.LoggerTag
import org.matrix.android.sdk.api.session.room.model.call.EndCallReason
import org.matrix.android.sdk.api.util.MatrixItem
import timber.log.Timber
+import javax.inject.Inject
private val loggerTag = LoggerTag("CallService", LoggerTag.VOIP)
/**
* Foreground service to manage calls
*/
+@AndroidEntryPoint
class CallService : VectorService() {
private val connections = mutableMapOf()
- private val knownCalls = mutableSetOf()
+ private val knownCalls = mutableMapOf()
private val connectedCallIds = mutableSetOf()
- private lateinit var notificationManager: NotificationManagerCompat
- private lateinit var notificationUtils: NotificationUtils
- private lateinit var callManager: WebRtcCallManager
- private lateinit var avatarRenderer: AvatarRenderer
- private lateinit var alertManager: PopupAlertManager
+ lateinit var notificationManager: NotificationManagerCompat
+ @Inject lateinit var notificationUtils: NotificationUtils
+ @Inject lateinit var callManager: WebRtcCallManager
+ @Inject lateinit var avatarRenderer: AvatarRenderer
+ @Inject lateinit var alertManager: PopupAlertManager
private var callRingPlayerIncoming: CallRingPlayerIncoming? = null
private var callRingPlayerOutgoing: CallRingPlayerOutgoing? = null
@@ -79,10 +83,6 @@ class CallService : VectorService() {
override fun onCreate() {
super.onCreate()
notificationManager = NotificationManagerCompat.from(this)
- notificationUtils = vectorComponent().notificationUtils()
- callManager = vectorComponent().webRtcCallManager()
- avatarRenderer = vectorComponent().avatarRenderer()
- alertManager = vectorComponent().alertManager()
callRingPlayerIncoming = CallRingPlayerIncoming(applicationContext, notificationUtils)
callRingPlayerOutgoing = CallRingPlayerOutgoing(applicationContext)
}
@@ -165,7 +165,7 @@ class CallService : VectorService() {
val incomingCallAlert = IncomingCallAlert(callId,
shouldBeDisplayedIn = { activity ->
if (activity is VectorCallActivity) {
- activity.intent.getParcelableExtra(MvRx.KEY_ARG)?.callId != call.callId
+ activity.intent.getParcelableExtra(Mavericks.KEY_ARG)?.callId != call.callId
} else true
}
).apply {
@@ -190,7 +190,7 @@ class CallService : VectorService() {
} else {
notificationManager.notify(callId.hashCode(), notification)
}
- knownCalls.add(callInformation)
+ knownCalls[callId] = callInformation
}
private fun handleCallTerminated(intent: Intent) {
@@ -198,20 +198,22 @@ class CallService : VectorService() {
val endCallReason = intent.getSerializableExtra(EXTRA_END_CALL_REASON) as EndCallReason
val rejected = intent.getBooleanExtra(EXTRA_END_CALL_REJECTED, false)
alertManager.cancelAlert(callId)
- val terminatedCall = knownCalls.firstOrNull { it.callId == callId }
+ val terminatedCall = knownCalls.remove(callId)
if (terminatedCall == null) {
- Timber.tag(loggerTag.value).v("Call terminated for unknown call $callId$")
+ Timber.tag(loggerTag.value).v("Call terminated for unknown call $callId")
handleUnexpectedState(callId)
return
}
- knownCalls.remove(terminatedCall)
+ val notification = notificationUtils.buildCallEndedNotification(false)
+ val notificationId = callId.hashCode()
+ startForeground(notificationId, notification)
if (knownCalls.isEmpty()) {
+ Timber.tag(loggerTag.value).v("No more call, stop the service")
+ stopForeground(true)
mediaSession?.isActive = false
myStopSelf()
}
val wasConnected = connectedCallIds.remove(callId)
- val notification = notificationUtils.buildCallEndedNotification(terminatedCall.isVideoCall)
- notificationManager.notify(callId.hashCode(), notification)
if (!wasConnected && !terminatedCall.isOutgoing && !rejected && endCallReason != EndCallReason.ANSWERED_ELSEWHERE) {
val missedCallNotification = notificationUtils.buildCallMissedNotification(terminatedCall)
notificationManager.notify(MISSED_CALL_TAG, terminatedCall.nativeRoomId.hashCode(), missedCallNotification)
@@ -243,7 +245,7 @@ class CallService : VectorService() {
} else {
notificationManager.notify(callId.hashCode(), notification)
}
- knownCalls.add(callInformation)
+ knownCalls[callId] = callInformation
}
/**
@@ -267,18 +269,19 @@ class CallService : VectorService() {
} else {
notificationManager.notify(callId.hashCode(), notification)
}
- knownCalls.add(callInformation)
+ knownCalls[callId] = callInformation
}
private fun handleUnexpectedState(callId: String?) {
Timber.tag(loggerTag.value).v("Fallback to clear everything")
callRingPlayerIncoming?.stop()
callRingPlayerOutgoing?.stop()
- if (callId != null) {
- notificationManager.cancel(callId.hashCode())
- }
val notification = notificationUtils.buildCallEndedNotification(false)
- startForeground(DEFAULT_NOTIFICATION_ID, notification)
+ if (callId != null) {
+ startForeground(callId.hashCode(), notification)
+ } else {
+ startForeground(DEFAULT_NOTIFICATION_ID, notification)
+ }
if (knownCalls.isEmpty()) {
mediaSession?.isActive = false
myStopSelf()
@@ -294,7 +297,7 @@ class CallService : VectorService() {
callId = this.callId,
nativeRoomId = this.nativeRoomId,
opponentUserId = this.mxCall.opponentUserId,
- opponentMatrixItem = vectorComponent().activeSessionHolder().getSafeActiveSession()?.let {
+ opponentMatrixItem = singletonEntryPoint().activeSessionHolder().getSafeActiveSession()?.let {
this.getOpponentAsMatrixItem(it)
},
isVideoCall = this.mxCall.isVideoCall,
@@ -371,7 +374,7 @@ class CallService : VectorService() {
putExtra(EXTRA_END_CALL_REASON, endCallReason)
putExtra(EXTRA_END_CALL_REJECTED, rejected)
}
- ContextCompat.startForegroundService(context, intent)
+ context.startService(intent)
}
}
diff --git a/vector/src/main/java/im/vector/app/core/di/HasVectorInjector.kt b/vector/src/main/java/im/vector/app/core/services/GuardServiceStarter.kt
similarity index 80%
rename from vector/src/main/java/im/vector/app/core/di/HasVectorInjector.kt
rename to vector/src/main/java/im/vector/app/core/services/GuardServiceStarter.kt
index 79254defcc..71c6816cea 100644
--- a/vector/src/main/java/im/vector/app/core/di/HasVectorInjector.kt
+++ b/vector/src/main/java/im/vector/app/core/services/GuardServiceStarter.kt
@@ -1,5 +1,5 @@
/*
- * Copyright 2019 New Vector Ltd
+ * Copyright (c) 2021 New Vector Ltd
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -14,9 +14,9 @@
* limitations under the License.
*/
-package im.vector.app.core.di
+package im.vector.app.core.services
-interface HasVectorInjector {
-
- fun injector(): VectorComponent
+interface GuardServiceStarter {
+ fun start() {}
+ fun stop() {}
}
diff --git a/vector/src/main/java/im/vector/app/core/services/VectorSyncService.kt b/vector/src/main/java/im/vector/app/core/services/VectorSyncService.kt
index 2a00e94976..a6f6d8d82f 100644
--- a/vector/src/main/java/im/vector/app/core/services/VectorSyncService.kt
+++ b/vector/src/main/java/im/vector/app/core/services/VectorSyncService.kt
@@ -30,13 +30,16 @@ import androidx.work.WorkManager
import androidx.work.WorkRequest
import androidx.work.Worker
import androidx.work.WorkerParameters
+import dagger.hilt.android.AndroidEntryPoint
import im.vector.app.R
-import im.vector.app.core.extensions.vectorComponent
+import im.vector.app.core.platform.PendingIntentCompat
import im.vector.app.features.notifications.NotificationUtils
import im.vector.app.features.settings.BackgroundSyncMode
import org.matrix.android.sdk.internal.session.sync.job.SyncService
import timber.log.Timber
+import javax.inject.Inject
+@AndroidEntryPoint
class VectorSyncService : SyncService() {
companion object {
@@ -71,12 +74,7 @@ class VectorSyncService : SyncService() {
}
}
- private lateinit var notificationUtils: NotificationUtils
-
- override fun onCreate() {
- super.onCreate()
- notificationUtils = vectorComponent().notificationUtils()
- }
+ @Inject lateinit var notificationUtils: NotificationUtils
override fun getDefaultSyncDelaySeconds() = BackgroundSyncMode.DEFAULT_SYNC_DELAY_SECONDS
@@ -86,7 +84,7 @@ class VectorSyncService : SyncService() {
val notificationSubtitleRes = if (isInitialSync) {
R.string.notification_initial_sync
} else {
- R.string.notification_listening_for_events
+ R.string.notification_listening_for_notifications
}
val notification = notificationUtils.buildForegroundServiceNotification(notificationSubtitleRes, false)
startForeground(NotificationUtils.NOTIFICATION_ID_FOREGROUND_SERVICE, notification)
@@ -202,9 +200,9 @@ private fun Context.rescheduleSyncService(sessionId: String,
startService(intent)
} else {
val pendingIntent = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
- PendingIntent.getForegroundService(this, 0, intent, 0)
+ PendingIntent.getForegroundService(this, 0, intent, PendingIntentCompat.FLAG_IMMUTABLE)
} else {
- PendingIntent.getService(this, 0, intent, 0)
+ PendingIntent.getService(this, 0, intent, PendingIntentCompat.FLAG_IMMUTABLE)
}
val firstMillis = System.currentTimeMillis() + syncDelaySeconds * 1000L
val alarmMgr = getSystemService()!!
diff --git a/vector/src/main/java/im/vector/app/core/services/WiredHeadsetStateReceiver.kt b/vector/src/main/java/im/vector/app/core/services/WiredHeadsetStateReceiver.kt
index e276e24851..ac6ced002e 100644
--- a/vector/src/main/java/im/vector/app/core/services/WiredHeadsetStateReceiver.kt
+++ b/vector/src/main/java/im/vector/app/core/services/WiredHeadsetStateReceiver.kt
@@ -21,7 +21,6 @@ import android.content.Context
import android.content.Intent
import android.content.IntentFilter
import android.media.AudioManager
-import android.os.Build
import timber.log.Timber
import java.lang.ref.WeakReference
@@ -69,11 +68,7 @@ class WiredHeadsetStateReceiver : BroadcastReceiver() {
fun createAndRegister(context: Context, listener: HeadsetEventListener): WiredHeadsetStateReceiver {
val receiver = WiredHeadsetStateReceiver()
receiver.delegate = WeakReference(listener)
- val action = if (Build.VERSION.SDK_INT >= 21) {
- AudioManager.ACTION_HEADSET_PLUG
- } else {
- Intent.ACTION_HEADSET_PLUG
- }
+ val action = AudioManager.ACTION_HEADSET_PLUG
context.registerReceiver(receiver, IntentFilter(action))
return receiver
}
diff --git a/vector/src/main/java/im/vector/app/core/ui/bottomsheet/BottomSheetGeneric.kt b/vector/src/main/java/im/vector/app/core/ui/bottomsheet/BottomSheetGeneric.kt
index e773993b21..bd7a07c640 100644
--- a/vector/src/main/java/im/vector/app/core/ui/bottomsheet/BottomSheetGeneric.kt
+++ b/vector/src/main/java/im/vector/app/core/ui/bottomsheet/BottomSheetGeneric.kt
@@ -26,7 +26,6 @@ import im.vector.app.core.extensions.cleanup
import im.vector.app.core.extensions.configureWith
import im.vector.app.core.platform.VectorBaseBottomSheetDialogFragment
import im.vector.app.databinding.BottomSheetGenericListBinding
-
import javax.inject.Inject
/**
diff --git a/vector/src/main/java/im/vector/app/core/ui/bottomsheet/BottomSheetGenericController.kt b/vector/src/main/java/im/vector/app/core/ui/bottomsheet/BottomSheetGenericController.kt
index f0715e6bba..6e92549809 100644
--- a/vector/src/main/java/im/vector/app/core/ui/bottomsheet/BottomSheetGenericController.kt
+++ b/vector/src/main/java/im/vector/app/core/ui/bottomsheet/BottomSheetGenericController.kt
@@ -20,8 +20,8 @@ import com.airbnb.epoxy.TypedEpoxyController
/**
* Epoxy controller for generic bottom sheet actions
*/
-abstract class BottomSheetGenericController
- : TypedEpoxyController() {
+abstract class BottomSheetGenericController :
+ TypedEpoxyController() {
var listener: Listener? = null
diff --git a/vector/src/main/java/im/vector/app/core/ui/bottomsheet/BottomSheetGenericState.kt b/vector/src/main/java/im/vector/app/core/ui/bottomsheet/BottomSheetGenericState.kt
index 38c81a7ef6..0f57600b13 100644
--- a/vector/src/main/java/im/vector/app/core/ui/bottomsheet/BottomSheetGenericState.kt
+++ b/vector/src/main/java/im/vector/app/core/ui/bottomsheet/BottomSheetGenericState.kt
@@ -16,6 +16,6 @@
package im.vector.app.core.ui.bottomsheet
-import com.airbnb.mvrx.MvRxState
+import com.airbnb.mvrx.MavericksState
-abstract class BottomSheetGenericState : MvRxState
+abstract class BottomSheetGenericState : MavericksState
diff --git a/vector/src/main/java/im/vector/app/core/ui/bottomsheet/BottomSheetGenericViewModel.kt b/vector/src/main/java/im/vector/app/core/ui/bottomsheet/BottomSheetGenericViewModel.kt
index 6cc2c4c981..bde87a5588 100644
--- a/vector/src/main/java/im/vector/app/core/ui/bottomsheet/BottomSheetGenericViewModel.kt
+++ b/vector/src/main/java/im/vector/app/core/ui/bottomsheet/BottomSheetGenericViewModel.kt
@@ -16,12 +16,12 @@
package im.vector.app.core.ui.bottomsheet
-import com.airbnb.mvrx.MvRxState
+import com.airbnb.mvrx.MavericksState
import im.vector.app.core.platform.EmptyAction
import im.vector.app.core.platform.EmptyViewEvents
import im.vector.app.core.platform.VectorViewModel
-abstract class BottomSheetGenericViewModel(initialState: State) :
+abstract class BottomSheetGenericViewModel(initialState: State) :
VectorViewModel(initialState) {
override fun handle(action: EmptyAction) {
diff --git a/vector/src/main/java/im/vector/app/core/ui/list/GenericButtonItem.kt b/vector/src/main/java/im/vector/app/core/ui/list/GenericButtonItem.kt
index eb683631fd..fe59c82ce9 100644
--- a/vector/src/main/java/im/vector/app/core/ui/list/GenericButtonItem.kt
+++ b/vector/src/main/java/im/vector/app/core/ui/list/GenericButtonItem.kt
@@ -15,6 +15,8 @@
*/
package im.vector.app.core.ui.list
+import android.graphics.Typeface
+import android.view.Gravity
import androidx.annotation.ColorInt
import androidx.annotation.DrawableRes
import com.airbnb.epoxy.EpoxyAttribute
@@ -47,6 +49,12 @@ abstract class GenericButtonItem : VectorEpoxyModel()
@DrawableRes
var iconRes: Int? = null
+ @EpoxyAttribute
+ var gravity: Int = Gravity.CENTER
+
+ @EpoxyAttribute
+ var bold: Boolean = false
+
override fun bind(holder: Holder) {
super.bind(holder)
holder.button.text = text
@@ -58,6 +66,10 @@ abstract class GenericButtonItem : VectorEpoxyModel()
holder.button.icon = null
}
+ holder.button.gravity = gravity or Gravity.CENTER_VERTICAL
+ val textStyle = if (bold) Typeface.BOLD else Typeface.NORMAL
+ holder.button.setTypeface(null, textStyle)
+
holder.button.onClick(buttonClickAction)
}
diff --git a/vector/src/main/java/im/vector/app/core/ui/views/ActiveConferenceView.kt b/vector/src/main/java/im/vector/app/core/ui/views/ActiveConferenceView.kt
deleted file mode 100644
index 256f2d963e..0000000000
--- a/vector/src/main/java/im/vector/app/core/ui/views/ActiveConferenceView.kt
+++ /dev/null
@@ -1,110 +0,0 @@
-/*
- * 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.
- */
-
-package im.vector.app.core.ui.views
-
-import android.content.Context
-import android.text.SpannableString
-import android.text.method.LinkMovementMethod
-import android.text.style.ClickableSpan
-import android.util.AttributeSet
-import android.view.View
-import android.widget.RelativeLayout
-import androidx.core.view.isVisible
-import im.vector.app.R
-import im.vector.app.core.utils.tappableMatchingText
-import im.vector.app.databinding.ViewActiveConferenceViewBinding
-import im.vector.app.features.home.room.detail.RoomDetailViewState
-import im.vector.app.features.themes.ThemeUtils
-import org.matrix.android.sdk.api.session.room.model.Membership
-import org.matrix.android.sdk.api.session.widgets.model.Widget
-import org.matrix.android.sdk.api.session.widgets.model.WidgetType
-
-class ActiveConferenceView @JvmOverloads constructor(
- context: Context,
- attrs: AttributeSet? = null,
- defStyleAttr: Int = 0
-) : RelativeLayout(context, attrs, defStyleAttr) {
-
- interface Callback {
- fun onTapJoinAudio(jitsiWidget: Widget)
- fun onTapJoinVideo(jitsiWidget: Widget)
- fun onDelete(jitsiWidget: Widget)
- }
-
- var callback: Callback? = null
- private var jitsiWidget: Widget? = null
-
- private lateinit var views: ViewActiveConferenceViewBinding
-
- init {
- setupView()
- }
-
- private fun setupView() {
- inflate(context, R.layout.view_active_conference_view, this)
- views = ViewActiveConferenceViewBinding.bind(this)
- setBackgroundColor(ThemeUtils.getColor(context, R.attr.colorPrimary))
-
- // "voice" and "video" texts are underlined and clickable
- val voiceString = context.getString(R.string.ongoing_conference_call_voice)
- val videoString = context.getString(R.string.ongoing_conference_call_video)
-
- val fullMessage = context.getString(R.string.ongoing_conference_call, voiceString, videoString)
-
- val styledText = SpannableString(fullMessage)
- styledText.tappableMatchingText(voiceString, object : ClickableSpan() {
- override fun onClick(widget: View) {
- jitsiWidget?.let {
- callback?.onTapJoinAudio(it)
- }
- }
- })
- styledText.tappableMatchingText(videoString, object : ClickableSpan() {
- override fun onClick(widget: View) {
- jitsiWidget?.let {
- callback?.onTapJoinVideo(it)
- }
- }
- })
-
- views.activeConferenceInfo.apply {
- text = styledText
- movementMethod = LinkMovementMethod.getInstance()
- }
-
- views.deleteWidgetButton.setOnClickListener {
- jitsiWidget?.let { callback?.onDelete(it) }
- }
- }
-
- fun render(state: RoomDetailViewState) {
- val summary = state.asyncRoomSummary()
- if (summary?.membership == Membership.JOIN) {
- // We only display banner for 'live' widgets
- jitsiWidget = state.activeRoomWidgets()?.firstOrNull {
- // for now only jitsi?
- it.type == WidgetType.Jitsi
- }
-
- isVisible = jitsiWidget != null
- // if sent by me or if i can moderate?
- views.deleteWidgetButton.isVisible = state.isAllowedToManageWidgets
- } else {
- isVisible = false
- }
- }
-}
diff --git a/vector/src/main/java/im/vector/app/core/ui/views/BottomSheetActionButton.kt b/vector/src/main/java/im/vector/app/core/ui/views/BottomSheetActionButton.kt
index 97194f2c03..a3e8b3780c 100644
--- a/vector/src/main/java/im/vector/app/core/ui/views/BottomSheetActionButton.kt
+++ b/vector/src/main/java/im/vector/app/core/ui/views/BottomSheetActionButton.kt
@@ -26,6 +26,7 @@ import androidx.core.view.isGone
import androidx.core.view.isInvisible
import androidx.core.view.isVisible
import im.vector.app.R
+import im.vector.app.core.extensions.setDrawableOrHide
import im.vector.app.core.extensions.setTextOrHide
import im.vector.app.databinding.ViewBottomSheetActionButtonBinding
import im.vector.app.features.themes.ThemeUtils
@@ -80,7 +81,7 @@ class BottomSheetActionButton @JvmOverloads constructor(
var rightIcon: Drawable? = null
set(value) {
field = value
- views.bottomSheetActionIcon.setImageDrawable(value)
+ views.bottomSheetActionIcon.setDrawableOrHide(value)
}
var tint: Int? = null
@@ -95,6 +96,12 @@ class BottomSheetActionButton @JvmOverloads constructor(
value?.let { views.bottomSheetActionTitle.setTextColor(it) }
}
+ var isBetaAction: Boolean? = null
+ set(value) {
+ field = value
+ views.bottomSheetActionBeta.isVisible = field ?: false
+ }
+
init {
inflate(context, R.layout.view_bottom_sheet_action_button, this)
views = ViewBottomSheetActionButtonBinding.bind(this)
@@ -109,6 +116,8 @@ class BottomSheetActionButton @JvmOverloads constructor(
tint = getColor(R.styleable.BottomSheetActionButton_tint, ThemeUtils.getColor(context, android.R.attr.textColor))
titleTextColor = getColor(R.styleable.BottomSheetActionButton_titleTextColor, ThemeUtils.getColor(context, R.attr.colorPrimary))
+
+ isBetaAction = getBoolean(R.styleable.BottomSheetActionButton_betaAction, false)
}
}
}
diff --git a/vector/src/main/java/im/vector/app/core/ui/views/CurrentCallsView.kt b/vector/src/main/java/im/vector/app/core/ui/views/CurrentCallsView.kt
index d1332f18dc..2f7eecc22c 100644
--- a/vector/src/main/java/im/vector/app/core/ui/views/CurrentCallsView.kt
+++ b/vector/src/main/java/im/vector/app/core/ui/views/CurrentCallsView.kt
@@ -18,7 +18,9 @@ package im.vector.app.core.ui.views
import android.content.Context
import android.util.AttributeSet
-import android.widget.RelativeLayout
+import android.util.TypedValue
+import android.widget.FrameLayout
+import androidx.appcompat.content.res.AppCompatResources
import im.vector.app.R
import im.vector.app.databinding.ViewCurrentCallsBinding
import im.vector.app.features.call.webrtc.WebRtcCall
@@ -29,7 +31,7 @@ class CurrentCallsView @JvmOverloads constructor(
context: Context,
attrs: AttributeSet? = null,
defStyleAttr: Int = 0
-) : RelativeLayout(context, attrs, defStyleAttr) {
+) : FrameLayout(context, attrs, defStyleAttr) {
interface Callback {
fun onTapToReturnToCall()
@@ -42,25 +44,33 @@ class CurrentCallsView @JvmOverloads constructor(
inflate(context, R.layout.view_current_calls, this)
views = ViewCurrentCallsBinding.bind(this)
setBackgroundColor(ThemeUtils.getColor(context, R.attr.colorPrimary))
+ val outValue = TypedValue().also {
+ context.theme.resolveAttribute(android.R.attr.selectableItemBackground, it, true)
+ }
+ foreground = AppCompatResources.getDrawable(context, outValue.resourceId)
setOnClickListener { callback?.onTapToReturnToCall() }
}
fun render(calls: List, formattedDuration: String) {
- val connectedCalls = calls.filter {
- it.mxCall.state is CallState.Connected
- }
- val heldCalls = connectedCalls.filter {
- it.isLocalOnHold || it.remoteOnHold
- }
- if (connectedCalls.isEmpty()) return
- views.currentCallsInfo.text = if (connectedCalls.size == heldCalls.size) {
- resources.getQuantityString(R.plurals.call_only_paused, heldCalls.size, heldCalls.size)
- } else {
- if (heldCalls.isEmpty()) {
- resources.getString(R.string.call_only_active, formattedDuration)
- } else {
- resources.getQuantityString(R.plurals.call_one_active_and_other_paused, heldCalls.size, formattedDuration, heldCalls.size)
+ val tapToReturnFormat = if (calls.size == 1) {
+ val firstCall = calls.first()
+ when (firstCall.mxCall.state) {
+ is CallState.Idle,
+ is CallState.CreateOffer,
+ is CallState.LocalRinging,
+ is CallState.Dialing -> {
+ resources.getString(R.string.call_ringing)
+ }
+ is CallState.Answering -> {
+ resources.getString(R.string.call_connecting)
+ }
+ else -> {
+ resources.getString(R.string.call_one_active, formattedDuration)
+ }
}
+ } else {
+ resources.getQuantityString(R.plurals.call_active_status, calls.size, calls.size)
}
+ views.currentCallsInfo.text = resources.getString(R.string.call_tap_to_return, tapToReturnFormat)
}
}
diff --git a/vector/src/main/java/im/vector/app/core/ui/views/CurrentCallsViewPresenter.kt b/vector/src/main/java/im/vector/app/core/ui/views/CurrentCallsViewPresenter.kt
new file mode 100644
index 0000000000..13db5ddcb3
--- /dev/null
+++ b/vector/src/main/java/im/vector/app/core/ui/views/CurrentCallsViewPresenter.kt
@@ -0,0 +1,55 @@
+/*
+ * Copyright (c) 2021 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 im.vector.app.core.ui.views
+
+import androidx.core.view.isVisible
+import im.vector.app.features.call.webrtc.WebRtcCall
+
+class CurrentCallsViewPresenter {
+
+ private var currentCallsView: CurrentCallsView? = null
+ private var currentCall: WebRtcCall? = null
+ private var calls: List = emptyList()
+
+ private val tickListener = object : WebRtcCall.Listener {
+ override fun onTick(formattedDuration: String) {
+ currentCallsView?.render(calls, formattedDuration)
+ }
+ }
+
+ fun updateCall(currentCall: WebRtcCall?, calls: List) {
+ this.currentCall?.removeListener(tickListener)
+ this.currentCall = currentCall
+ this.currentCall?.addListener(tickListener)
+ this.calls = calls
+ val hasActiveCall = calls.isNotEmpty()
+ currentCallsView?.isVisible = hasActiveCall
+ currentCallsView?.render(calls, currentCall?.formattedDuration() ?: "")
+ }
+
+ fun bind(activeCallView: CurrentCallsView, interactionListener: CurrentCallsView.Callback) {
+ this.currentCallsView = activeCallView
+ this.currentCallsView?.callback = interactionListener
+ this.currentCall?.addListener(tickListener)
+ }
+
+ fun unBind() {
+ this.currentCallsView?.callback = null
+ this.currentCall?.removeListener(tickListener)
+ currentCallsView = null
+ }
+}
diff --git a/vector/src/main/java/im/vector/app/core/ui/views/FailedMessagesWarningView.kt b/vector/src/main/java/im/vector/app/core/ui/views/FailedMessagesWarningView.kt
index f9518552a3..755230b5bf 100644
--- a/vector/src/main/java/im/vector/app/core/ui/views/FailedMessagesWarningView.kt
+++ b/vector/src/main/java/im/vector/app/core/ui/views/FailedMessagesWarningView.kt
@@ -19,7 +19,6 @@ package im.vector.app.core.ui.views
import android.content.Context
import android.util.AttributeSet
import androidx.constraintlayout.widget.ConstraintLayout
-import androidx.core.view.isVisible
import im.vector.app.R
import im.vector.app.databinding.ViewFailedMessagesWarningBinding
@@ -49,8 +48,4 @@ class FailedMessagesWarningView @JvmOverloads constructor(
views.failedMessagesDeleteAllButton.setOnClickListener { callback?.onDeleteAllClicked() }
views.failedMessagesRetryButton.setOnClickListener { callback?.onRetryClicked() }
}
-
- fun render(hasFailedMessages: Boolean) {
- isVisible = hasFailedMessages
- }
}
diff --git a/vector/src/main/java/im/vector/app/core/ui/views/JoinConferenceView.kt b/vector/src/main/java/im/vector/app/core/ui/views/JoinConferenceView.kt
new file mode 100644
index 0000000000..fa1e2c1403
--- /dev/null
+++ b/vector/src/main/java/im/vector/app/core/ui/views/JoinConferenceView.kt
@@ -0,0 +1,69 @@
+/*
+ * 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.
+ */
+
+package im.vector.app.core.ui.views
+
+import android.animation.Animator
+import android.animation.ArgbEvaluator
+import android.animation.ValueAnimator
+import android.annotation.SuppressLint
+import android.content.Context
+import android.util.AttributeSet
+import android.widget.FrameLayout
+import androidx.core.content.ContextCompat
+import im.vector.app.R
+import im.vector.app.databinding.ViewJoinConferenceBinding
+
+class JoinConferenceView @JvmOverloads constructor(
+ context: Context,
+ attrs: AttributeSet? = null,
+ defStyleAttr: Int = 0
+) : FrameLayout(context, attrs, defStyleAttr) {
+
+ var views: ViewJoinConferenceBinding? = null
+ var onJoinClicked: (() -> Unit)? = null
+ var backgroundAnimator: Animator? = null
+
+ init {
+ inflate(context, R.layout.view_join_conference, this)
+ }
+
+ @SuppressLint("Recycle")
+ override fun onAttachedToWindow() {
+ super.onAttachedToWindow()
+ views = ViewJoinConferenceBinding.bind(this)
+ views?.joinConferenceButton?.setOnClickListener { onJoinClicked?.invoke() }
+ val colorFrom = ContextCompat.getColor(context, R.color.palette_element_green)
+ val colorTo = ContextCompat.getColor(context, R.color.join_conference_animated_color)
+ // Animate button color to highlight
+ backgroundAnimator = ValueAnimator.ofObject(ArgbEvaluator(), colorFrom, colorTo).apply {
+ repeatMode = ValueAnimator.REVERSE
+ repeatCount = ValueAnimator.INFINITE
+ duration = 500
+ addUpdateListener { animator ->
+ val color = animator.animatedValue as Int
+ views?.joinConferenceButton?.setBackgroundColor(color)
+ }
+ }
+ backgroundAnimator?.start()
+ }
+
+ override fun onDetachedFromWindow() {
+ super.onDetachedFromWindow()
+ views = null
+ backgroundAnimator?.cancel()
+ }
+}
diff --git a/vector/src/main/java/im/vector/app/core/ui/views/KeysBackupBanner.kt b/vector/src/main/java/im/vector/app/core/ui/views/KeysBackupBanner.kt
index 153cac2ac7..94c1ab6576 100755
--- a/vector/src/main/java/im/vector/app/core/ui/views/KeysBackupBanner.kt
+++ b/vector/src/main/java/im/vector/app/core/ui/views/KeysBackupBanner.kt
@@ -25,7 +25,6 @@ import androidx.core.view.isVisible
import im.vector.app.R
import im.vector.app.core.di.DefaultSharedPreferences
import im.vector.app.databinding.ViewKeysBackupBannerBinding
-
import timber.log.Timber
/**
@@ -137,8 +136,8 @@ class KeysBackupBanner @JvmOverloads constructor(
}
private fun renderSetup(nbOfKeys: Int) {
- if (nbOfKeys == 0
- || DefaultSharedPreferences.getInstance(context).getBoolean(BANNER_SETUP_DO_NOT_SHOW_AGAIN, false)) {
+ if (nbOfKeys == 0 ||
+ DefaultSharedPreferences.getInstance(context).getBoolean(BANNER_SETUP_DO_NOT_SHOW_AGAIN, false)) {
// Do not display the setup banner if there is no keys to backup, or if the user has already closed it
isVisible = false
} else {
diff --git a/vector/src/main/java/im/vector/app/core/ui/views/KnownCallsViewHolder.kt b/vector/src/main/java/im/vector/app/core/ui/views/KnownCallsViewHolder.kt
deleted file mode 100644
index d49cf929b6..0000000000
--- a/vector/src/main/java/im/vector/app/core/ui/views/KnownCallsViewHolder.kt
+++ /dev/null
@@ -1,114 +0,0 @@
-/*
- * 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.
- */
-
-package im.vector.app.core.ui.views
-
-import androidx.core.view.isVisible
-import com.google.android.material.card.MaterialCardView
-import im.vector.app.core.epoxy.onClick
-import im.vector.app.features.call.utils.EglUtils
-import im.vector.app.features.call.webrtc.WebRtcCall
-import org.matrix.android.sdk.api.session.call.CallState
-import org.webrtc.RendererCommon
-import org.webrtc.SurfaceViewRenderer
-
-class KnownCallsViewHolder {
-
- private var activeCallPiP: SurfaceViewRenderer? = null
- private var currentCallsView: CurrentCallsView? = null
- private var pipWrapper: MaterialCardView? = null
- private var currentCall: WebRtcCall? = null
- private var calls: List = emptyList()
-
- private var activeCallPipInitialized = false
-
- private val tickListener = object : WebRtcCall.Listener {
- override fun onTick(formattedDuration: String) {
- currentCallsView?.render(calls, formattedDuration)
- }
- }
-
- fun updateCall(currentCall: WebRtcCall?, calls: List) {
- activeCallPiP?.let {
- this.currentCall?.detachRenderers(listOf(it))
- }
- this.currentCall?.removeListener(tickListener)
- this.currentCall = currentCall
- this.currentCall?.addListener(tickListener)
- this.calls = calls
- val hasActiveCall = currentCall?.mxCall?.state is CallState.Connected
- if (hasActiveCall) {
- val isVideoCall = currentCall?.mxCall?.isVideoCall == true
- if (isVideoCall) initIfNeeded()
- currentCallsView?.isVisible = !isVideoCall
- currentCallsView?.render(calls, currentCall?.formattedDuration() ?: "")
- pipWrapper?.isVisible = isVideoCall
- activeCallPiP?.isVisible = isVideoCall
- activeCallPiP?.let {
- currentCall?.attachViewRenderers(null, it, null)
- }
- } else {
- currentCallsView?.isVisible = false
- activeCallPiP?.isVisible = false
- pipWrapper?.isVisible = false
- activeCallPiP?.let {
- currentCall?.detachRenderers(listOf(it))
- }
- }
- }
-
- private fun initIfNeeded() {
- if (!activeCallPipInitialized && activeCallPiP != null) {
- activeCallPiP?.setScalingType(RendererCommon.ScalingType.SCALE_ASPECT_FILL)
- EglUtils.rootEglBase?.let { eglBase ->
- activeCallPiP?.init(eglBase.eglBaseContext, null)
- activeCallPiP?.setScalingType(RendererCommon.ScalingType.SCALE_ASPECT_BALANCED)
- activeCallPiP?.setEnableHardwareScaler(true /* enabled */)
- activeCallPiP?.setZOrderMediaOverlay(true)
- activeCallPipInitialized = true
- }
- }
- }
-
- fun bind(activeCallPiP: SurfaceViewRenderer,
- activeCallView: CurrentCallsView,
- pipWrapper: MaterialCardView,
- interactionListener: CurrentCallsView.Callback) {
- this.activeCallPiP = activeCallPiP
- this.currentCallsView = activeCallView
- this.pipWrapper = pipWrapper
- this.currentCallsView?.callback = interactionListener
- pipWrapper.onClick {
- interactionListener.onTapToReturnToCall()
- }
- this.currentCall?.addListener(tickListener)
- }
-
- fun unBind() {
- activeCallPiP?.let {
- currentCall?.detachRenderers(listOf(it))
- }
- if (activeCallPipInitialized) {
- activeCallPiP?.release()
- }
- this.currentCallsView?.callback = null
- this.currentCall?.removeListener(tickListener)
- pipWrapper?.setOnClickListener(null)
- activeCallPiP = null
- currentCallsView = null
- pipWrapper = null
- }
-}
diff --git a/vector/src/main/java/im/vector/app/core/ui/views/NotificationAreaView.kt b/vector/src/main/java/im/vector/app/core/ui/views/NotificationAreaView.kt
index 463d94b288..94809d2981 100644
--- a/vector/src/main/java/im/vector/app/core/ui/views/NotificationAreaView.kt
+++ b/vector/src/main/java/im/vector/app/core/ui/views/NotificationAreaView.kt
@@ -30,7 +30,6 @@ import im.vector.app.core.extensions.exhaustive
import im.vector.app.core.utils.DimensionConverter
import im.vector.app.databinding.ViewNotificationAreaBinding
import im.vector.app.features.themes.ThemeUtils
-
import me.gujun.android.span.span
import me.saket.bettermovementmethod.BetterLinkMovementMethod
import org.matrix.android.sdk.api.failure.MatrixError
@@ -50,7 +49,7 @@ class NotificationAreaView @JvmOverloads constructor(
var delegate: Delegate? = null
private var state: State = State.Initial
- private lateinit var views : ViewNotificationAreaBinding
+ private lateinit var views: ViewNotificationAreaBinding
init {
setupView()
diff --git a/vector/src/main/java/im/vector/app/core/ui/views/PasswordStrengthBar.kt b/vector/src/main/java/im/vector/app/core/ui/views/PasswordStrengthBar.kt
index 2f6c4b45cf..a984707bf7 100644
--- a/vector/src/main/java/im/vector/app/core/ui/views/PasswordStrengthBar.kt
+++ b/vector/src/main/java/im/vector/app/core/ui/views/PasswordStrengthBar.kt
@@ -35,8 +35,8 @@ import im.vector.app.databinding.ViewPasswordStrengthBarBinding
class PasswordStrengthBar @JvmOverloads constructor(
context: Context,
attrs: AttributeSet? = null,
- defStyleAttr: Int = 0)
- : LinearLayout(context, attrs, defStyleAttr) {
+ defStyleAttr: Int = 0) :
+ LinearLayout(context, attrs, defStyleAttr) {
private val views: ViewPasswordStrengthBarBinding
diff --git a/vector/src/main/java/im/vector/app/core/ui/views/PresenceStateImageView.kt b/vector/src/main/java/im/vector/app/core/ui/views/PresenceStateImageView.kt
new file mode 100644
index 0000000000..301f8afdc9
--- /dev/null
+++ b/vector/src/main/java/im/vector/app/core/ui/views/PresenceStateImageView.kt
@@ -0,0 +1,54 @@
+/*
+ * Copyright (c) 2021 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 im.vector.app.core.ui.views
+
+import android.content.Context
+import android.util.AttributeSet
+import androidx.appcompat.widget.AppCompatImageView
+import androidx.core.view.isVisible
+import im.vector.app.R
+import org.matrix.android.sdk.api.session.presence.model.PresenceEnum
+import org.matrix.android.sdk.api.session.presence.model.UserPresence
+
+/**
+ * Custom ImageView to dynamically render Presence state in multiple screens
+ */
+class PresenceStateImageView @JvmOverloads constructor(
+ context: Context,
+ attrs: AttributeSet? = null,
+ defStyleAttr: Int = 0
+) : AppCompatImageView(context, attrs, defStyleAttr) {
+
+ fun render(showPresence: Boolean = true, userPresence: UserPresence?) {
+ isVisible = showPresence && userPresence != null
+
+ when (userPresence?.presence) {
+ PresenceEnum.ONLINE -> {
+ setImageResource(R.drawable.ic_presence_online)
+ contentDescription = context.getString(R.string.a11y_presence_online)
+ }
+ PresenceEnum.UNAVAILABLE -> {
+ setImageResource(R.drawable.ic_presence_offline)
+ contentDescription = context.getString(R.string.a11y_presence_unavailable)
+ }
+ PresenceEnum.OFFLINE -> {
+ setImageResource(R.drawable.ic_presence_offline)
+ contentDescription = context.getString(R.string.a11y_presence_offline)
+ }
+ }
+ }
+}
diff --git a/vector/src/main/java/im/vector/app/core/ui/views/ReadReceiptsView.kt b/vector/src/main/java/im/vector/app/core/ui/views/ReadReceiptsView.kt
index 02b351737e..3a79e7e328 100644
--- a/vector/src/main/java/im/vector/app/core/ui/views/ReadReceiptsView.kt
+++ b/vector/src/main/java/im/vector/app/core/ui/views/ReadReceiptsView.kt
@@ -37,7 +37,7 @@ class ReadReceiptsView @JvmOverloads constructor(
defStyleAttr: Int = 0
) : LinearLayout(context, attrs, defStyleAttr) {
- private val views : ViewReadReceiptsBinding
+ private val views: ViewReadReceiptsBinding
init {
setupView()
diff --git a/vector/src/main/java/im/vector/app/core/utils/CountUpTimer.kt b/vector/src/main/java/im/vector/app/core/utils/CountUpTimer.kt
index a029f4eec9..b58d0fb3f6 100644
--- a/vector/src/main/java/im/vector/app/core/utils/CountUpTimer.kt
+++ b/vector/src/main/java/im/vector/app/core/utils/CountUpTimer.kt
@@ -16,23 +16,36 @@
package im.vector.app.core.utils
-import io.reactivex.Observable
-import java.util.concurrent.TimeUnit
+import im.vector.app.core.flow.tickerFlow
+import kotlinx.coroutines.CoroutineScope
+import kotlinx.coroutines.Dispatchers
+import kotlinx.coroutines.cancel
+import kotlinx.coroutines.flow.filter
+import kotlinx.coroutines.flow.launchIn
+import kotlinx.coroutines.flow.map
+import kotlinx.coroutines.flow.onEach
import java.util.concurrent.atomic.AtomicBoolean
import java.util.concurrent.atomic.AtomicLong
class CountUpTimer(private val intervalInMs: Long = 1_000) {
+ private val coroutineScope = CoroutineScope(Dispatchers.Main)
private val elapsedTime: AtomicLong = AtomicLong()
private val resumed: AtomicBoolean = AtomicBoolean(false)
- private val disposable = Observable.interval(intervalInMs / 10, TimeUnit.MILLISECONDS)
- .filter { resumed.get() }
- .map { elapsedTime.addAndGet(intervalInMs / 10) }
- .filter { it % intervalInMs == 0L }
- .subscribe {
- tickListener?.onTick(it)
- }
+ init {
+ startCounter()
+ }
+
+ private fun startCounter() {
+ tickerFlow(coroutineScope, intervalInMs / 10)
+ .filter { resumed.get() }
+ .map { elapsedTime.addAndGet(intervalInMs / 10) }
+ .filter { it % intervalInMs == 0L }
+ .onEach {
+ tickListener?.onTick(it)
+ }.launchIn(coroutineScope)
+ }
var tickListener: TickListener? = null
@@ -49,7 +62,7 @@ class CountUpTimer(private val intervalInMs: Long = 1_000) {
}
fun stop() {
- disposable.dispose()
+ coroutineScope.cancel()
}
interface TickListener {
diff --git a/vector/src/main/java/im/vector/app/core/utils/DataSource.kt b/vector/src/main/java/im/vector/app/core/utils/DataSource.kt
index fc4ee330bb..f83eda68e9 100644
--- a/vector/src/main/java/im/vector/app/core/utils/DataSource.kt
+++ b/vector/src/main/java/im/vector/app/core/utils/DataSource.kt
@@ -16,13 +16,12 @@
package im.vector.app.core.utils
-import com.jakewharton.rxrelay2.BehaviorRelay
-import com.jakewharton.rxrelay2.PublishRelay
-import io.reactivex.Observable
-import io.reactivex.android.schedulers.AndroidSchedulers
+import kotlinx.coroutines.channels.BufferOverflow
+import kotlinx.coroutines.flow.Flow
+import kotlinx.coroutines.flow.MutableSharedFlow
interface DataSource {
- fun observe(): Observable
+ fun stream(): Flow
}
interface MutableDataSource : DataSource {
@@ -34,25 +33,17 @@ interface MutableDataSource : DataSource {
*/
open class BehaviorDataSource(private val defaultValue: T? = null) : MutableDataSource {
- private val behaviorRelay = createRelay()
+ private val mutableFlow = MutableSharedFlow(replay = 1)
val currentValue: T?
- get() = behaviorRelay.value
+ get() = mutableFlow.replayCache.firstOrNull()
- override fun observe(): Observable {
- return behaviorRelay.hide().observeOn(AndroidSchedulers.mainThread())
+ override fun stream(): Flow {
+ return mutableFlow
}
override fun post(value: T) {
- behaviorRelay.accept(value!!)
- }
-
- private fun createRelay(): BehaviorRelay {
- return if (defaultValue == null) {
- BehaviorRelay.create()
- } else {
- BehaviorRelay.createDefault(defaultValue)
- }
+ mutableFlow.tryEmit(value)
}
}
@@ -61,13 +52,13 @@ open class BehaviorDataSource(private val defaultValue: T? = null) : MutableD
*/
open class PublishDataSource : MutableDataSource {
- private val publishRelay = PublishRelay.create()
+ private val mutableFlow = MutableSharedFlow(replay = 0, extraBufferCapacity = 1, onBufferOverflow = BufferOverflow.DROP_OLDEST)
- override fun observe(): Observable {
- return publishRelay.hide().observeOn(AndroidSchedulers.mainThread())
+ override fun stream(): Flow {
+ return mutableFlow
}
override fun post(value: T) {
- publishRelay.accept(value!!)
+ mutableFlow.tryEmit(value)
}
}
diff --git a/vector/src/main/java/im/vector/app/core/utils/DefaultSubscriber.kt b/vector/src/main/java/im/vector/app/core/utils/DefaultSubscriber.kt
deleted file mode 100644
index a82e5a4e03..0000000000
--- a/vector/src/main/java/im/vector/app/core/utils/DefaultSubscriber.kt
+++ /dev/null
@@ -1,31 +0,0 @@
-/*
- * Copyright 2019 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 im.vector.app.core.utils
-
-import io.reactivex.Completable
-import io.reactivex.Single
-import io.reactivex.disposables.Disposable
-import io.reactivex.internal.functions.Functions
-import timber.log.Timber
-
-fun Single.subscribeLogError(): Disposable {
- return subscribe(Functions.emptyConsumer(), { Timber.e(it) })
-}
-
-fun Completable.subscribeLogError(): Disposable {
- return subscribe({}, { Timber.e(it) })
-}
diff --git a/vector/src/main/java/im/vector/app/core/utils/Dialogs.kt b/vector/src/main/java/im/vector/app/core/utils/Dialogs.kt
index 7806f2603d..ad62b0fcb1 100644
--- a/vector/src/main/java/im/vector/app/core/utils/Dialogs.kt
+++ b/vector/src/main/java/im/vector/app/core/utils/Dialogs.kt
@@ -20,6 +20,7 @@ import android.content.Context
import android.webkit.WebView
import android.webkit.WebViewClient
import com.google.android.material.dialog.MaterialAlertDialogBuilder
+import im.vector.app.R
/**
* Open a web view above the current activity.
@@ -38,3 +39,17 @@ fun Context.displayInWebView(url: String) {
.setPositiveButton(android.R.string.ok, null)
.show()
}
+
+fun Context.showIdentityServerConsentDialog(configuredIdentityServer: String?, policyLinkCallback: () -> Unit, consentCallBack: (() -> Unit)) {
+ MaterialAlertDialogBuilder(this)
+ .setTitle(getString(R.string.identity_server_consent_dialog_title_2, configuredIdentityServer ?: ""))
+ .setMessage(R.string.identity_server_consent_dialog_content_2)
+ .setPositiveButton(R.string.yes) { _, _ ->
+ consentCallBack.invoke()
+ }
+ .setNeutralButton(R.string.identity_server_consent_dialog_neutral_policy) { _, _ ->
+ policyLinkCallback.invoke()
+ }
+ .setNegativeButton(R.string.no, null)
+ .show()
+}
diff --git a/vector/src/main/java/im/vector/app/core/utils/ExternalApplicationsUtil.kt b/vector/src/main/java/im/vector/app/core/utils/ExternalApplicationsUtil.kt
index d0535b667f..bdaf520ba1 100644
--- a/vector/src/main/java/im/vector/app/core/utils/ExternalApplicationsUtil.kt
+++ b/vector/src/main/java/im/vector/app/core/utils/ExternalApplicationsUtil.kt
@@ -36,6 +36,7 @@ import androidx.activity.result.ActivityResultLauncher
import androidx.browser.customtabs.CustomTabColorSchemeParams
import androidx.browser.customtabs.CustomTabsIntent
import androidx.browser.customtabs.CustomTabsSession
+import androidx.core.app.ShareCompat
import androidx.core.content.FileProvider
import androidx.core.content.getSystemService
import im.vector.app.BuildConfig
@@ -297,23 +298,19 @@ fun openMedia(activity: Activity, savedMediaPath: String, mimeType: String) {
}
fun shareMedia(context: Context, file: File, mediaMimeType: String?) {
- var mediaUri: Uri? = null
- try {
- mediaUri = FileProvider.getUriForFile(context, BuildConfig.APPLICATION_ID + ".fileProvider", file)
+ val mediaUri = try {
+ FileProvider.getUriForFile(context, BuildConfig.APPLICATION_ID + ".fileProvider", file)
} catch (e: Exception) {
Timber.e(e, "onMediaAction Selected File cannot be shared")
+ return
}
- if (null != mediaUri) {
- val sendIntent = Intent()
- sendIntent.action = Intent.ACTION_SEND
- // Grant temporary read permission to the content URI
- sendIntent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION)
- sendIntent.type = mediaMimeType
- sendIntent.putExtra(Intent.EXTRA_STREAM, mediaUri)
+ val sendIntent = ShareCompat.IntentBuilder(context)
+ .setType(mediaMimeType)
+ .setStream(mediaUri)
+ .getIntent()
- sendShareIntent(context, sendIntent)
- }
+ sendShareIntent(context, sendIntent)
}
fun shareText(context: Context, text: String) {
diff --git a/vector/src/main/java/im/vector/app/core/utils/PermissionsTools.kt b/vector/src/main/java/im/vector/app/core/utils/PermissionsTools.kt
index 9f1497a40a..ba396ed252 100644
--- a/vector/src/main/java/im/vector/app/core/utils/PermissionsTools.kt
+++ b/vector/src/main/java/im/vector/app/core/utils/PermissionsTools.kt
@@ -52,8 +52,7 @@ private var permissionDialogDisplayed = false
* So when the user does not grant the permission and check the box do not ask again, this boolean will be false.
* Only useful if the first boolean is false
*/
-fun ComponentActivity.registerForPermissionsResult(lambda: (allGranted: Boolean, deniedPermanently: Boolean) -> Unit)
- : ActivityResultLauncher> {
+fun ComponentActivity.registerForPermissionsResult(lambda: (allGranted: Boolean, deniedPermanently: Boolean) -> Unit): ActivityResultLauncher> {
return registerForActivityResult(ActivityResultContracts.RequestMultiplePermissions()) { result ->
onPermissionResult(result, lambda)
}
diff --git a/vector/src/main/java/im/vector/app/core/utils/SnapHelperUtils.kt b/vector/src/main/java/im/vector/app/core/utils/SnapHelperUtils.kt
index e039e0bde5..070c953a3f 100644
--- a/vector/src/main/java/im/vector/app/core/utils/SnapHelperUtils.kt
+++ b/vector/src/main/java/im/vector/app/core/utils/SnapHelperUtils.kt
@@ -59,8 +59,8 @@ class SnapOnScrollListener(
}
override fun onScrollStateChanged(recyclerView: RecyclerView, newState: Int) {
- if (behavior == Behavior.NOTIFY_ON_SCROLL_STATE_IDLE
- && newState == RecyclerView.SCROLL_STATE_IDLE) {
+ if (behavior == Behavior.NOTIFY_ON_SCROLL_STATE_IDLE &&
+ newState == RecyclerView.SCROLL_STATE_IDLE) {
maybeNotifySnapPositionChange(recyclerView)
}
}
diff --git a/vector/src/main/java/im/vector/app/core/utils/SystemUtils.kt b/vector/src/main/java/im/vector/app/core/utils/SystemUtils.kt
index b12c1b7369..966b38828e 100644
--- a/vector/src/main/java/im/vector/app/core/utils/SystemUtils.kt
+++ b/vector/src/main/java/im/vector/app/core/utils/SystemUtils.kt
@@ -48,8 +48,8 @@ import im.vector.app.features.notifications.NotificationUtils
*/
fun isIgnoringBatteryOptimizations(context: Context): Boolean {
// no issue before Android M, battery optimisations did not exist
- return Build.VERSION.SDK_INT < Build.VERSION_CODES.M
- || context.getSystemService()?.isIgnoringBatteryOptimizations(context.packageName) == true
+ return Build.VERSION.SDK_INT < Build.VERSION_CODES.M ||
+ context.getSystemService()?.isIgnoringBatteryOptimizations(context.packageName) == true
}
fun isAirplaneModeOn(context: Context): Boolean {
diff --git a/vector/src/main/java/im/vector/app/features/MainActivity.kt b/vector/src/main/java/im/vector/app/features/MainActivity.kt
index 583aae260b..8e0995b426 100644
--- a/vector/src/main/java/im/vector/app/features/MainActivity.kt
+++ b/vector/src/main/java/im/vector/app/features/MainActivity.kt
@@ -24,9 +24,9 @@ import androidx.lifecycle.Lifecycle
import androidx.lifecycle.lifecycleScope
import com.bumptech.glide.Glide
import com.google.android.material.dialog.MaterialAlertDialogBuilder
+import dagger.hilt.android.AndroidEntryPoint
import im.vector.app.R
import im.vector.app.core.di.ActiveSessionHolder
-import im.vector.app.core.di.ScreenComponent
import im.vector.app.core.error.ErrorFormatter
import im.vector.app.core.extensions.startSyncing
import im.vector.app.core.platform.VectorBaseActivity
@@ -45,10 +45,10 @@ import im.vector.app.features.signout.soft.SoftLogoutActivity
import im.vector.app.features.signout.soft.SoftLogoutActivity2
import im.vector.app.features.themes.ActivityOtherThemes
import im.vector.app.features.ui.UiStateRepository
-import kotlinx.parcelize.Parcelize
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext
+import kotlinx.parcelize.Parcelize
import org.matrix.android.sdk.api.failure.GlobalError
import timber.log.Timber
import javax.inject.Inject
@@ -67,6 +67,7 @@ data class MainActivityArgs(
* This Activity, when started with argument, is also doing some cleanup when user signs out,
* clears cache, is logged out, or is soft logged out
*/
+@AndroidEntryPoint
class MainActivity : VectorBaseActivity(), UnlockedActivity {
companion object {
@@ -98,10 +99,6 @@ class MainActivity : VectorBaseActivity(), UnlockedActivity
@Inject lateinit var pinLocker: PinLocker
@Inject lateinit var popupAlertManager: PopupAlertManager
- override fun injectWith(injector: ScreenComponent) {
- injector.inject(this)
- }
-
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
args = parseArgs()
@@ -220,20 +217,20 @@ class MainActivity : VectorBaseActivity(), UnlockedActivity
private fun startNextActivityAndFinish(ignoreClearCredentials: Boolean = false) {
val intent = when {
- args.clearCredentials
- && !ignoreClearCredentials
- && (!args.isUserLoggedOut || args.isAccountDeactivated) -> {
+ args.clearCredentials &&
+ !ignoreClearCredentials &&
+ (!args.isUserLoggedOut || args.isAccountDeactivated) -> {
// User has explicitly asked to log out or deactivated his account
navigator.openLogin(this, null)
null
}
- args.isSoftLogout ->
+ args.isSoftLogout ->
// The homeserver has invalidated the token, with a soft logout
getSoftLogoutActivityIntent()
- args.isUserLoggedOut ->
+ args.isUserLoggedOut ->
// the homeserver has invalidated the token (password changed, device deleted, other security reasons)
SignedOutActivity.newIntent(this)
- sessionHolder.hasActiveSession() ->
+ sessionHolder.hasActiveSession() ->
// We have a session.
// Check it can be opened
if (sessionHolder.getActiveSession().isOpenable) {
@@ -242,7 +239,7 @@ class MainActivity : VectorBaseActivity(), UnlockedActivity
// The token is still invalid
getSoftLogoutActivityIntent()
}
- else -> {
+ else -> {
// First start, or no active session
navigator.openLogin(this, null)
null
diff --git a/vector/src/main/java/im/vector/app/features/attachments/AttachmentTypeSelectorView.kt b/vector/src/main/java/im/vector/app/features/attachments/AttachmentTypeSelectorView.kt
index c0d4669108..6c349d18dc 100644
--- a/vector/src/main/java/im/vector/app/features/attachments/AttachmentTypeSelectorView.kt
+++ b/vector/src/main/java/im/vector/app/features/attachments/AttachmentTypeSelectorView.kt
@@ -53,8 +53,8 @@ private const val ANIMATION_DURATION = 250
*/
class AttachmentTypeSelectorView(context: Context,
inflater: LayoutInflater,
- var callback: Callback?)
- : PopupWindow(context) {
+ var callback: Callback?) :
+ PopupWindow(context) {
interface Callback {
fun onTypeSelected(type: Type)
@@ -75,6 +75,7 @@ class AttachmentTypeSelectorView(context: Context,
views.attachmentStickersButton.configure(Type.STICKER)
views.attachmentAudioButton.configure(Type.AUDIO)
views.attachmentContactButton.configure(Type.CONTACT)
+ views.attachmentPollButton.configure(Type.POLL)
width = LinearLayout.LayoutParams.MATCH_PARENT
height = LinearLayout.LayoutParams.WRAP_CONTENT
animationStyle = 0
@@ -103,11 +104,12 @@ class AttachmentTypeSelectorView(context: Context,
animateWindowInCircular(anchor, contentView)
}
animateButtonIn(views.attachmentGalleryButton, ANIMATION_DURATION / 2)
- animateButtonIn(views.attachmentCameraButton, ANIMATION_DURATION / 2)
- animateButtonIn(views.attachmentFileButton, ANIMATION_DURATION / 4)
- animateButtonIn(views.attachmentAudioButton, ANIMATION_DURATION / 2)
+ animateButtonIn(views.attachmentCameraButton, ANIMATION_DURATION / 4)
+ animateButtonIn(views.attachmentFileButton, ANIMATION_DURATION / 2)
+ animateButtonIn(views.attachmentAudioButton, 0)
animateButtonIn(views.attachmentContactButton, ANIMATION_DURATION / 4)
- animateButtonIn(views.attachmentStickersButton, 0)
+ animateButtonIn(views.attachmentStickersButton, ANIMATION_DURATION / 2)
+ animateButtonIn(views.attachmentPollButton, ANIMATION_DURATION / 4)
}
override fun dismiss() {
@@ -212,6 +214,7 @@ class AttachmentTypeSelectorView(context: Context,
FILE(PERMISSIONS_EMPTY),
STICKER(PERMISSIONS_EMPTY),
AUDIO(PERMISSIONS_EMPTY),
- CONTACT(PERMISSIONS_FOR_PICKING_CONTACT)
+ CONTACT(PERMISSIONS_FOR_PICKING_CONTACT),
+ POLL(PERMISSIONS_EMPTY)
}
}
diff --git a/vector/src/main/java/im/vector/app/features/attachments/ContentAttachmentData.kt b/vector/src/main/java/im/vector/app/features/attachments/ContentAttachmentData.kt
index 0502f2b0ad..9805b6f755 100644
--- a/vector/src/main/java/im/vector/app/features/attachments/ContentAttachmentData.kt
+++ b/vector/src/main/java/im/vector/app/features/attachments/ContentAttachmentData.kt
@@ -27,9 +27,9 @@ private val listOfPreviewableMimeTypes = listOf(
fun ContentAttachmentData.isPreviewable(): Boolean {
// Preview supports image and video
- return (type == ContentAttachmentData.Type.IMAGE
- && listOfPreviewableMimeTypes.contains(getSafeMimeType() ?: ""))
- || type == ContentAttachmentData.Type.VIDEO
+ return (type == ContentAttachmentData.Type.IMAGE &&
+ listOfPreviewableMimeTypes.contains(getSafeMimeType() ?: "")) ||
+ type == ContentAttachmentData.Type.VIDEO
}
data class GroupedContentAttachmentData(
diff --git a/vector/src/main/java/im/vector/app/features/attachments/preview/AttachmentsPreviewActivity.kt b/vector/src/main/java/im/vector/app/features/attachments/preview/AttachmentsPreviewActivity.kt
index 6c25f688bd..939dd9f11d 100644
--- a/vector/src/main/java/im/vector/app/features/attachments/preview/AttachmentsPreviewActivity.kt
+++ b/vector/src/main/java/im/vector/app/features/attachments/preview/AttachmentsPreviewActivity.kt
@@ -20,6 +20,7 @@ package im.vector.app.features.attachments.preview
import android.content.Context
import android.content.Intent
import com.google.android.material.appbar.MaterialToolbar
+import dagger.hilt.android.AndroidEntryPoint
import im.vector.app.R
import im.vector.app.core.extensions.addFragment
import im.vector.app.core.platform.ToolbarConfigurable
@@ -28,6 +29,7 @@ import im.vector.app.databinding.ActivitySimpleBinding
import im.vector.app.features.themes.ActivityOtherThemes
import org.matrix.android.sdk.api.session.content.ContentAttachmentData
+@AndroidEntryPoint
class AttachmentsPreviewActivity : VectorBaseActivity(), ToolbarConfigurable {
companion object {
diff --git a/vector/src/main/java/im/vector/app/features/attachments/preview/AttachmentsPreviewViewModel.kt b/vector/src/main/java/im/vector/app/features/attachments/preview/AttachmentsPreviewViewModel.kt
index 28d617e613..0a0e700ce9 100644
--- a/vector/src/main/java/im/vector/app/features/attachments/preview/AttachmentsPreviewViewModel.kt
+++ b/vector/src/main/java/im/vector/app/features/attachments/preview/AttachmentsPreviewViewModel.kt
@@ -20,8 +20,8 @@ package im.vector.app.features.attachments.preview
import im.vector.app.core.extensions.exhaustive
import im.vector.app.core.platform.VectorViewModel
-class AttachmentsPreviewViewModel(initialState: AttachmentsPreviewViewState)
- : VectorViewModel(initialState) {
+class AttachmentsPreviewViewModel(initialState: AttachmentsPreviewViewState) :
+ VectorViewModel